mirror of
https://github.com/qwibitai/nanoclaw.git
synced 2026-07-03 18:45:07 +08:00
0d841bcd05
`ncl messaging-groups create` failed with a NOT NULL violation on the
`instance` column (migration 016). The generic CRUD insert builds its
column list from the resource definition, and `instance` wasn't declared
there — so the INSERT omitted the column entirely. The router path never
hit this because it goes through `createMessagingGroup`, which has its own
`instance ?? channel_type` fallback.
There is no operator-facing reason to require `--instance`: the default
instance IS the channel type (migration 016, `createMessagingGroup`, and
the default-instance resolver all encode this). So rather than force a
flag, default it.
- crud: add `defaultFrom` to ColumnDef — default a column to another
already-resolved column's value on create. Generic, reusable.
- messaging-groups: declare `instance` with `defaultFrom: 'channel_type'`
(placed after channel_type so it resolves first), still overridable via
`--instance` for multi-instance setups.
- test: drive the real dispatch('messaging-groups-create') path; asserts
omitted -> channel_type and explicit --instance preserved. Goes red if
the column/defaultFrom wiring is deleted (insert fails NOT NULL).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
67 lines
2.4 KiB
TypeScript
67 lines
2.4 KiB
TypeScript
import { registerResource } from '../crud.js';
|
|
|
|
registerResource({
|
|
name: 'messaging-group',
|
|
plural: 'messaging-groups',
|
|
table: 'messaging_groups',
|
|
description:
|
|
'Messaging group — one chat or channel on one platform (a Telegram DM, a Discord channel, a Slack thread root, an email address). Identity is the (channel_type, platform_id) pair, which must be unique.',
|
|
idColumn: 'id',
|
|
columns: [
|
|
{ name: 'id', type: 'string', description: 'UUID.', generated: true },
|
|
{
|
|
name: 'channel_type',
|
|
type: 'string',
|
|
description:
|
|
'Channel adapter type — matches the adapter registered by /add-<channel> (e.g. telegram, discord, slack, whatsapp).',
|
|
required: true,
|
|
},
|
|
{
|
|
name: 'platform_id',
|
|
type: 'string',
|
|
description:
|
|
'Platform-specific chat ID. Format varies: Telegram chat ID, Discord channel snowflake, Slack channel ID, phone number, email address.',
|
|
required: true,
|
|
},
|
|
{
|
|
name: 'instance',
|
|
type: 'string',
|
|
description:
|
|
'Adapter instance that owns this chat, when running N adapters of one channel type. Defaults to channel_type (the default instance) when omitted.',
|
|
defaultFrom: 'channel_type',
|
|
updatable: true,
|
|
},
|
|
{
|
|
name: 'name',
|
|
type: 'string',
|
|
description: 'Display name. Often auto-populated by the channel adapter.',
|
|
updatable: true,
|
|
},
|
|
{
|
|
name: 'is_group',
|
|
type: 'number',
|
|
description: 'Multi-user group chat (1) or direct message (0). Affects session scoping.',
|
|
default: 0,
|
|
updatable: true,
|
|
},
|
|
{
|
|
name: 'unknown_sender_policy',
|
|
type: 'string',
|
|
description:
|
|
'What happens when an unrecognized sender posts. "strict" drops silently. "request_approval" sends an approval card to an admin. "public" allows anyone.',
|
|
enum: ['strict', 'request_approval', 'public'],
|
|
default: 'strict',
|
|
updatable: true,
|
|
},
|
|
{
|
|
name: 'denied_at',
|
|
type: 'string',
|
|
description:
|
|
'Set when the owner explicitly denies registering this channel. While set, the router drops all messages silently without re-escalating. Cleared by any explicit wiring mutation.',
|
|
updatable: true,
|
|
},
|
|
{ name: 'created_at', type: 'string', description: 'Auto-set.', generated: true },
|
|
],
|
|
operations: { list: 'open', get: 'open', create: 'approval', update: 'approval', delete: 'approval' },
|
|
});
|