From 416fe018550cbb3f83826cc1a3d67dc165920720 Mon Sep 17 00:00:00 2001 From: gavrielc Date: Wed, 22 Apr 2026 02:13:22 +0300 Subject: [PATCH] refactor(setup): drop CLI-bonus wiring from init-first-agent MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit init-first-agent used to double-wire the CLI channel to every new DM agent as a convenience for `pnpm run chat`, gated by --no-cli-bonus. With the /new-setup-2 flow gone and a dedicated scratch CLI agent created earlier in setup:auto, that bonus just stomps on CLI routing the user already set up. Remove the CLI_CHANNEL/CLI_PLATFORM_ID constants, ensureCliMessagingGroup, the --no-cli-bonus flag, and the cli-bonus wiring block. Pass the paired user's identity through to the welcome delivery so the sender resolver sees the real owner (e.g. telegram:) instead of cli:local. Extend the CLI channel's admin-transport payload to accept optional sender/senderId overrides — falls back to the old cli/cli:local defaults when omitted, so existing callers are unchanged. Co-Authored-By: Claude Opus 4.7 (1M context) --- scripts/init-first-agent.ts | 74 +++++++++++-------------------------- src/channels/cli.ts | 6 ++- 2 files changed, 26 insertions(+), 54 deletions(-) diff --git a/scripts/init-first-agent.ts b/scripts/init-first-agent.ts index 29ca6d4..c634851 100644 --- a/scripts/init-first-agent.ts +++ b/scripts/init-first-agent.ts @@ -1,16 +1,13 @@ /** * Init the first (or Nth) NanoClaw v2 agent for a DM channel. * - * Wires a real DM channel (discord, telegram, etc.) to a new agent group - * (and the local CLI channel as a convenience bonus), then hands a welcome - * message to the running service via its CLI socket. The service routes - * that message into the DM session, which wakes the container synchronously — - * the agent processes the welcome and DMs the operator through the normal - * delivery path. + * Wires a real DM channel (discord, telegram, etc.) to a new agent group, + * then hands a welcome message to the running service via the CLI socket + * (admin transport). The service routes that message into the DM session, + * which wakes the container synchronously — the agent processes the welcome + * and DMs the operator through the normal delivery path. * - * For the CLI-only scratch agent used during `/new-setup`, see - * `scripts/init-cli-agent.ts` — that's a distinct flow and doesn't run - * through here. + * CLI channel wiring is handled separately by `scripts/init-cli-agent.ts`. * * Creates/reuses: user, owner grant (if none), agent group + filesystem, * messaging group(s), wiring. @@ -27,8 +24,7 @@ * --platform-id discord:@me:1491573333382523708 \ * --display-name "Gavriel" \ * [--agent-name "Andy"] \ - * [--welcome "System instruction: ..."] \ - * [--no-cli-bonus] + * [--welcome "System instruction: ..."] * * For direct-addressable channels (telegram, whatsapp, etc.), --platform-id * is typically the same as the handle in --user-id, with the channel prefix. @@ -53,7 +49,6 @@ import { initGroupFilesystem } from '../src/group-init.js'; import type { AgentGroup, MessagingGroup } from '../src/types.js'; interface Args { - noCliBonus: boolean; channel: string; userId: string; platformId: string; @@ -65,18 +60,12 @@ interface Args { const DEFAULT_WELCOME = 'System instruction: run /welcome to introduce yourself to the user on this new channel.'; -const CLI_CHANNEL = 'cli'; -const CLI_PLATFORM_ID = 'local'; - function parseArgs(argv: string[]): Args { - const out: Partial = { noCliBonus: false }; + const out: Partial = {}; for (let i = 0; i < argv.length; i++) { const key = argv[i]; const val = argv[i + 1]; switch (key) { - case '--no-cli-bonus': - out.noCliBonus = true; - break; case '--channel': out.channel = (val ?? '').toLowerCase(); i++; @@ -115,7 +104,6 @@ function parseArgs(argv: string[]): Args { } return { - noCliBonus: out.noCliBonus ?? false, channel: out.channel!, userId: out.userId!, platformId: out.platformId!, @@ -137,24 +125,6 @@ function generateId(prefix: string): string { return `${prefix}-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`; } -function ensureCliMessagingGroup(now: string): MessagingGroup { - let cliMg = getMessagingGroupByPlatform(CLI_CHANNEL, CLI_PLATFORM_ID); - if (cliMg) return cliMg; - - cliMg = { - id: generateId('mg'), - channel_type: CLI_CHANNEL, - platform_id: CLI_PLATFORM_ID, - name: 'Local CLI', - is_group: 0, - unknown_sender_policy: 'public', - created_at: now, - }; - createMessagingGroup(cliMg); - console.log(`Created CLI messaging group: ${cliMg.id}`); - return cliMg; -} - function wireIfMissing(mg: MessagingGroup, ag: AgentGroup, now: string, label: string): void { const existing = getMessagingGroupAgentByPair(mg.id, ag.id); if (existing) { @@ -252,29 +222,23 @@ async function main(): Promise { console.log(`Reusing messaging group: ${dmMg.id} (${platformId})`); } - // 4. Wire DM (auto-creates companion agent_destinations row) and, - // unless suppressed, also wire the CLI channel so `pnpm run chat` works - // against the new agent immediately. `/new-setup-2` sets --no-cli-bonus - // so the scratch CLI agent from `/new-setup` keeps owning CLI routing. + // 4. Wire DM messaging group to the agent. wireIfMissing(dmMg, ag, now, 'dm'); - if (!args.noCliBonus) { - const cliMg = ensureCliMessagingGroup(now); - wireIfMissing(cliMg, ag, now, 'cli-bonus'); - } // 5. Welcome delivery over the CLI socket. Router picks up the line, // writes the message into the DM session's inbound.db, and wakes the - // container synchronously — no sweep wait. - await sendWelcomeViaCliSocket(dmMg, args.welcome); + // container synchronously — no sweep wait. The paired user's identity is + // passed so the sender resolver sees the real owner, not cli:local. + await sendWelcomeViaCliSocket(dmMg, args.welcome, { + senderId: userId, + sender: args.displayName, + }); console.log(''); console.log('Init complete.'); console.log(` owner: ${userId}${promotedToOwner ? ' (promoted on first owner)' : ''}`); console.log(` agent: ${ag.name} [${ag.id}] @ groups/${folder}`); console.log(` channel: ${args.channel} ${dmMg.platform_id}`); - if (!args.noCliBonus) { - console.log(` cli: cli/${CLI_PLATFORM_ID} wired — try \`pnpm run chat hi\``); - } console.log(''); console.log('Welcome DM queued — the agent will greet you shortly.'); } @@ -288,7 +252,11 @@ async function main(): Promise { * Throws if the socket isn't reachable — this script requires the service * to be running. */ -async function sendWelcomeViaCliSocket(dmMg: MessagingGroup, welcome: string): Promise { +async function sendWelcomeViaCliSocket( + dmMg: MessagingGroup, + welcome: string, + identity: { senderId: string; sender: string }, +): Promise { const sockPath = path.join(DATA_DIR, 'cli.sock'); await new Promise((resolve, reject) => { @@ -318,6 +286,8 @@ async function sendWelcomeViaCliSocket(dmMg: MessagingGroup, welcome: string): P const payload = JSON.stringify({ text: welcome, + senderId: identity.senderId, + sender: identity.sender, to: { channelType: dmMg.channel_type, platformId: dmMg.platform_id, diff --git a/src/channels/cli.ts b/src/channels/cli.ts index b738186..ad78bea 100644 --- a/src/channels/cli.ts +++ b/src/channels/cli.ts @@ -183,6 +183,8 @@ function createAdapter(): ChannelAdapter { text?: unknown; to?: unknown; reply_to?: unknown; + sender?: unknown; + senderId?: unknown; }; try { payload = JSON.parse(line); @@ -209,8 +211,8 @@ function createAdapter(): ChannelAdapter { timestamp: new Date().toISOString(), content: JSON.stringify({ text: payload.text, - sender: 'cli', - senderId: `cli:${PLATFORM_ID}`, + sender: typeof payload.sender === 'string' ? payload.sender : 'cli', + senderId: typeof payload.senderId === 'string' ? payload.senderId : `cli:${PLATFORM_ID}`, }), }, replyTo: replyTo ?? undefined,