Commit Graph

198 Commits

Author SHA1 Message Date
Koshkoshinsk
f553c8126c refactor(new-setup): add step-4 join barrier and drop scripted one-liners
Two flow fixes:

1. Add "Ordering and parallelism" section making explicit that step 4
   (auth) must block until step 3 (OneCLI) is complete — auth writes
   the secret into the vault, so firing an AskUserQuestion while
   OneCLI is still installing asks the user for a credential the
   system can't store. Step 2 (container build) is safe to run past
   step 4, joined before step 6 (first CLI agent).

2. Drop the per-step quoted one-liners. They duplicated Claude's own
   natural narration ("While those build, let's get your credential
   set up." → immediately echoed by the scripted "Your agent needs an
   Anthropic credential..."). Each step now has a short description
   instead; Claude narrates in its own voice.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 11:50:00 +00:00
Koshkoshinsk
77fec6c7c3 fix(new-setup): avoid double-bootstrap and corepack EACCES on system Node
Two fixes to the fresh-install path:

1. setup.sh: when `corepack enable` runs as a non-root user against a
   system-wide Node install (apt-installed to /usr/bin), it fails EACCES
   trying to symlink /usr/bin/pnpm, leaving pnpm off PATH. Retry with
   sudo when pnpm is still missing — gated to Linux/WSL so macOS
   Homebrew prefixes aren't polluted with root-owned shims.

2. SKILL.md step 1: if the probe reports STATUS: unavailable (Node not
   installed), install Node BEFORE invoking `bash setup.sh`. The old
   flow ran setup.sh first as a diagnostic, which always failed fast,
   installed Node, then re-ran — two bootstraps for no reason.

Combined: fresh Linux box now goes Node install -> single setup.sh run.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 11:37:03 +00:00
Koshkoshinsk
77624d7854 fix(new-setup): wrap probe in shell script for single-command permission check
The chained `&& / ||` inline command tripped Claude Code's per-operation
permission check. Move the Node-missing fallback into setup/probe.sh so
the skill's `!` block is a single `bash setup/probe.sh` call.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 11:05:54 +00:00
Koshkoshinsk
b3e8b2e047 fix(new-setup): run probe before pnpm is installed
Port probe to zero-dep plain ESM (setup/probe.mjs) so /new-setup can
inject dynamic context on a fresh machine where pnpm/node_modules
don't yet exist. Skill falls back to a STATUS: unavailable block if
Node itself isn't on PATH, and the flow treats that as "run every
step from 1" (each step is idempotent).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 11:03:49 +00:00
Koshkoshinsk
f6ddd20636 feat(new-setup): add skill definition
Shortest path from zero to a working two-way agent chat via the CLI
channel. Renders `!`pnpm exec tsx setup/index.ts --step probe`` at the
top for dynamic context injection — Claude sees current system state
before generating its first response and routes each subsequent step
(skip/ask/run) off the probe snapshot. Pre-approves the Bash patterns
it needs via `allowed-tools` so setup runs without per-step prompts.

Lives alongside /setup for now; will replace it once proven.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 10:43:41 +00:00
gavrielc
c37609ffc8 docs(skills): drop "v2" from skill content + src/index.ts log lines
Cleans up the prose-level v2 references that the rename commit didn't
touch. Skills now describe themselves and the codebase without "v2"
versioning language. /add-X-v2 cross-references in setup, init-first-agent,
and manage-channels updated to /add-X.

Runtime path identifiers (data/v2.db, data/v2-sessions/, container name
nanoclaw-v2) deliberately left as-is — renaming them breaks live installs
without commensurate benefit.

Verified: pnpm run build clean, 326 host tests pass.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-17 14:42:55 +03:00
gavrielc
00fb1bee4a chore(skills): rename add-*-v2 → add-* and drop dead v1 channel skills
Renamed 13 skill folders to drop the -v2 suffix (the v2/v1 distinction
isn't load-bearing anymore — there is no v1 runtime). Deleted the four
v1 channel skills that occupied the rename target paths (add-discord,
add-slack, add-telegram, add-whatsapp); they targeted src/v1 which is
reference-only per CLAUDE.md.

Skill content still says "v2" in places — that's a follow-up commit.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-17 14:38:19 +03:00
gavrielc
4857512267 refactor(v2): move setup/groups.ts off trunk + drop pino dep
setup/groups.ts is whatsapp-only — its inline syncScript imports baileys
and pino to fetch group metadata via Baileys.groupFetchAllParticipating.
On trunk it was a no-op for non-whatsapp users (returned early without
auth) and the only thing keeping pino alive.

Removed:
- setup/groups.ts (lives on `channels` branch; restored by /add-whatsapp-v2)
- `groups` STEPS entry from setup/index.ts
- pino from package.json (no longer used outside the moved file)

/add-whatsapp-v2 skill updated to copy setup/groups.ts and register both
groups + whatsapp-auth in setup/index.ts STEPS, install pino@9.6.0 along
with baileys + qrcode.

Verified: build clean, 326 host tests pass.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-17 14:34:16 +03:00
gavrielc
a3376c25df docs(channel-skills): rewrite all 13 /add-*-v2 skills for copy-from-channels-branch pattern
Each skill now:
- Pre-flight: checks for file present + import line + dep listed (idempotent)
- git fetch origin channels
- git show origin/channels:<paths> > <paths> to copy adapter (and helpers/tests/setup-step where applicable)
- Append `import './<chan>.js';` to src/channels/index.ts
- pnpm install <pkg>@<pinned-version>
- pnpm run build

Telegram additionally copies 4 helper/test files + setup/pair-telegram.ts
and registers `'pair-telegram':` in setup/index.ts STEPS.

WhatsApp (native) additionally copies setup/whatsapp-auth.ts and
registers `'whatsapp-auth':` in setup/index.ts STEPS, installs
@whiskeysockets/baileys + qrcode + @types/qrcode pinned.

All credential / next-steps / channel-info / troubleshooting sections
preserved verbatim.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-17 14:24:20 +03:00
gavrielc
32a973f1cd docs(add-opencode): rewrite skill for copy-from-providers-branch pattern
v2 no longer ships opencode on trunk. The skill now:
- Fetches origin/providers
- Copies opencode source files to their target paths
- Appends self-registration imports to both provider barrels
- Adds @opencode-ai/sdk@1.4.3 as a pinned agent-runner dep
- Adds OPENCODE_VERSION ARG + opencode-ai pnpm global install to Dockerfile
- Rebuilds host + container

All steps idempotent. Credential/env/Zen docs unchanged.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-17 14:14:10 +03:00
Tal Moskovich
c9dd6e050e docs: update OpenCode Zen integration details in SKILL.md
- Clarified the use of `x-api-key` for Zen's HTTP API, addressing common issues with Bearer tokens.
- Added configuration examples for `.env` and OneCLI registration for Zen keys.
- Provided guidance on naming conventions for OpenCode agent and provider settings.
- Included a note on the difference in authentication methods between OpenCode and OpenRouter.
2026-04-17 12:20:22 +03:00
Tal Moskovich
22150261c5 feat(v2): OpenCode agent provider
- Add OpenCodeProvider (SSE, session resume, MCP via mcp-to-opencode)
- Register opencode in factory; AGENT_PROVIDER passthrough from DB
- Host: XDG mount, NO_PROXY merge, OPENCODE_* env for opencode sessions
- Dockerfile: opencode-ai CLI; docs checklist + architecture diagram
- Skill add-opencode for v2; AgentProviderName in src/types.ts

Made-with: Cursor
2026-04-17 12:20:22 +03:00
gavrielc
f04921deee docs(v2): runtime-split guide, CLAUDE.md gotchas, setup CJK autodetect
- docs/v2-build-and-runtime.md: new — runtime split rationale (Node host,
  Bun container), lockfile topology, supply-chain trade-offs, image build
  surface, two session-wake paths, CI shape, key invariants. Indexed from
  CLAUDE.md v2 Docs Index.
- CLAUDE.md: Container Runtime (Bun) section with trigger/action gotchas
  a contributor editing the container must know (named-param prefix rule,
  bun:test vs vitest, bun.lock regeneration, no minimumReleaseAge for the
  Bun tree, no tsc build step, DELETE pragma invariant). CJK font support
  section for Claude sessions outside of /setup to proactively offer when
  they detect CJK signals. Development section updated with Bun commands.
- .claude/skills/setup/SKILL.md: step 3b — auto-enable CJK fonts without
  asking if the user is already writing in CJK; otherwise ask only on clear
  signals (CJK timezone from step 2a). 3c renumbered from old 3b.
2026-04-17 11:38:20 +03:00
gavrielc
22498ae69c fix: remaining npm→pnpm gaps + dockerignore for pnpm symlinks
- container/.dockerignore (new): exclude agent-runner/node_modules and
  agent-runner/dist so COPY agent-runner/ ./ doesn't clobber the
  pnpm-installed node_modules with host directories. Under npm's flat
  layout this was forgiving; under pnpm's symlink layout it's a hard
  conflict (overlay2 cannot copy onto a symlink target).
- setup/{groups,service}.ts: execSync('pnpm run build') not npm.
- setup/index.ts: usage string.
- scripts/*.ts: usage comments + seed-discord final log.
- .claude/settings.json: permission allowlist entries.
- .claude/skills/{add-whatsapp-v2,add-dashboard}/SKILL.md: docs.
- container/skills/{frontend-engineer,vercel-cli,self-customize}/SKILL.md:
  agent-facing docs still told the container agent to run npm.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-17 09:53:00 +03:00
gavrielc
504e5296c9 fix: pnpm-lock sync, per-group build-script allowlist, ppnpm typos
- Regenerate pnpm-lock.yaml to match v2 package.json (Baileys 6.17.16,
  @chat-adapter/linear 4.26.0)
- src/container-runner.ts: when install_packages rebuilds a per-group
  image, append each installed package to /root/.npmrc's
  only-built-dependencies before pnpm install -g, so packages with
  postinstall scripts (playwright, puppeteer, native addons) don't
  install silently broken
- Fix stray 'ppnpm uninstall' in 13 skill files (REMOVE.md + SKILL.md)
  left over from the npm→pnpm sed pass

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-17 09:25:59 +03:00
meeech
211d2b5877 docs: convert all skill instructions from npm to pnpm
Batch update 62 files across .claude/skills/ — SKILL.md, REMOVE.md,
and script files. Conversions: npm run -> pnpm run, npm install ->
pnpm install, npx -> pnpm exec/dlx, npm uninstall -> pnpm uninstall,
package-lock.json -> pnpm-lock.yaml, shebangs updated.
2026-04-17 09:22:45 +03:00
Gabi Simons
1aeb8fb4ca refactor(add-vercel): drop Frontend Engineer delegation, add pre-deploy checks
The specialist-subagent pattern forced every /add-vercel user through the
OneCLI credential-assignment plumbing (dynamically created Frontend Engineer
agents had no Vercel secret on first deploy). For a personal assistant the
isolation wasn't worth the complexity — the host agent can deploy to Vercel
directly using the same CLI.

- Remove the Phase 5 CLAUDE.md patch that forbade writing frontend code
- Drop the bundled frontend-engineer container skill
- Strip the HARD RULE + "Building Websites" delegation from vercel-cli
- Add a concise "Pre-Send Checks" section: local build, deployment READY,
  live URL returns 2xx, optional agent-browser visual check

Net: -194 lines. /add-vercel now installs the CLI, registers the secret,
assigns it to existing agents, and teaches the agent to verify before
sharing the URL. No subagent plumbing.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-16 19:59:30 +00:00
gavrielc
cc784ff94b refactor(v2): remove trigger_credential_collection MCP tool
Drops the in-chat credential-collection flow introduced in e92b245. Agents
can no longer collect API keys via a secure modal — users must add secrets
through OneCLI directly. Keeps the OneCLI manual-approval handler and
threaded-routing work from the same commit intact.

Removed:
* container/agent-runner/src/mcp-tools/credentials.ts (MCP tool)
* src/credentials.ts (host-side modal/OneCLI pipeline)
* src/db/credentials.ts + migration 005 (pending_credentials table)
* src/onecli-secrets.ts (createSecret CLI facade, only caller was credentials.ts)
* findCredentialResponse from agent-runner DB layer
* PendingCredential types
* Four credential hooks from ChannelSetup (getCredentialForModal,
  onCredentialReject, onCredentialSubmit, onCredentialChannelUnsupported)
* Credential card/modal handling in chat-sdk-bridge (nccr/nccm prefixes,
  Modal/TextInput imports)
* credential_request text fallback in WhatsApp adapter
* request_credential system-action case in delivery.ts

Added:
* Migration 009 drops pending_credentials on existing installs.

Vercel skill now tells the agent to ask the user to register the token via
OneCLI instead of invoking the removed tool.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-16 21:41:41 +03:00
gavrielc
e55ed0f4e8 fix(whatsapp): upgrade Baileys 6.7→6.17, fix proto import and 515 restart
Baileys 6.7.21 silently failed the pairing handshake. Upgrade to 6.17.16
which fixes this. Three related issues:

1. proto is no longer a named ESM export in 6.17.x — use createRequire
   to import via CJS (matching the proven v1 pattern).
2. Setup auth script didn't handle the 515 stream restart that WhatsApp
   sends after successful pairing. Refactored to reconnect (matching v1's
   connectSocket(isReconnect) pattern) instead of hanging until timeout.
3. Added succeeded guard and process.exit(0) to prevent timeout race
   after successful auth.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-16 21:01:55 +03:00
gabi-simons
82422d2077 fix(vercel): complete add-vercel flow for fresh installs
- Add Phase 5: patch agent CLAUDE.md with frontend delegation rule
  so agents treat it as a hard constraint, not a suggestion
- Add Phase 6: sync container skills to existing agent sessions
  (skills are copied once at group creation, not auto-updated)
- Add OneCLI secret assignment step in Phase 3 (selective mode
  requires explicit assignment per agent)
- Add hard rule to vercel-cli container skill header
- Clean up Phase 4 (check Dockerfile before rebuilding)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-16 15:36:06 +00:00
gavrielc
4ae9785a61 fix(setup): move OpenClaw detection into environment step
Avoids running `ls -d ~/.openclaw` as a separate Bash command which
triggers permission prompts for reading outside the project directory.
The environment step now reports OPENCLAW_PATH in its status block.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-16 14:14:25 +03:00
gavrielc
79fd142be4 improve setup UX: welcome message + AskUserQuestion for pre-approval
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-16 14:06:37 +03:00
gavrielc
ce80e4ec3e feat(setup): add Linear channel, fix setup permissions
Enable Linear channel adapter. Fix setup permission rules: use specific
npm install entries per adapter package, replace cp -r with rsync -a to
avoid built-in cp safety prompt, add head to allow list for chained
commands. Update Linear API key URL.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-16 14:00:27 +03:00
gavrielc
57c9bfc670 improve setup flow: streamline steps, add pre-approval, new manage-mounts skill
- Disable sandbox by default in project settings
- Setup: remove Apple Container option (Docker only), single channel selection
  with plain text list, move fork to end, auto-set empty mounts, add command
  pre-approval step, add UTC timezone confirmation, add wait-on-user guidance,
  add 5m timeouts for long steps
- iMessage: improve Full Disk Access UX with Finder open + drag instructions
- Add /manage-mounts skill for post-setup mount configuration
- Enable iMessage channel import

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-16 11:26:20 +03:00
gavrielc
20a24dfd13 style: apply prettier formatting
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 21:15:13 +03:00
Gabi Simons
c54c779834 feat(v2/add-vercel): add frontend-engineer skill with agent delegation
When /add-vercel is applied, agents that need to build websites spin up
a dedicated Frontend Engineer agent instead of building inline. The
frontend agent enforces build-test-verify discipline with visual browser
verification before deploying to Vercel.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 13:44:27 +00:00
Gabi Simons
e9a427ad1a docs(v2): add /add-dashboard skill with resource-based pusher
Self-contained skill: SKILL.md has instructions, resources/ holds
the dashboard-pusher.ts that gets copied to src/ at install time.
No src/ changes until the skill is applied.

npm package: @nanoco/nanoclaw-dashboard
Repo: https://github.com/qwibitai/nanoclaw-dashboard

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 13:21:19 +00:00
Koshkoshinsk
77321984ba feat(pair-telegram): emit REMINDER_TO_ASSISTANT in status block
Move the "print the pairing code as plain text" directive from three
skill docs into the CLI output itself. Every caller of pair-telegram
(init-first-agent, manage-channels, add-telegram-v2, future callers)
now sees the reminder directly in the PAIR_TELEGRAM_ISSUED and
PAIR_TELEGRAM_NEW_CODE blocks. Skill docs shortened to point at it.

Also add a short pre-tool-call sentence in init-first-agent step 3b
instructing the assistant to extract the code and ask the user to send
it in Telegram.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 11:50:25 +00:00
Koshkoshinsk
1eaf4f88d9 Revert "docs(skills): print pairing code as final message; drop log-tail verify"
This reverts commit bd6a26a002.
2026-04-15 10:48:17 +00:00
Koshkoshinsk
bd6a26a002 docs(skills): print pairing code as final message; drop log-tail verify
- Reword pair-code instruction across add-telegram-v2, manage-channels,
  and init-first-agent so the very last user-visible message after
  generating the code MUST be a plain-text print of it.
- Replace init-first-agent's tail -f based verify step with a plain-text
  prompt asking the user to confirm receipt of the welcome DM, falling
  back to DB-based diagnostics only on non-arrival. Avoids harness
  blocks on long leading sleeps and fragile log-string greps.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 10:31:46 +00:00
Koshkoshinsk
6801a14736 docs(skills): require pairing code be printed as final user-visible message
Claude Code's UI collapses bash tool output, so the user never sees the
pairing code emitted by pair-telegram. Reframe the skill instructions
to require the last user-visible message at this step to be a plain-text
print of the code.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 10:06:58 +00:00
Koshkoshinsk
f60b42666f docs(skills): surface telegram pairing code outside bash output
Claude Code's UI folds bash tool results by default, hiding the 4-digit
pairing code from the user. Instruct the skill to echo the CODE as plain
text in the reply so it's always visible.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 08:42:39 +00:00
gavrielc
0d3326aae5 feat(v2): user-level privilege model + cold DM infra + init-first-agent skill
Replaces the agent-group-centric "main group" concept with user-level
privileges and adds the cold-DM infrastructure needed for proactive
outbound messaging (pairing, approvals, welcome flows).

Privilege model
- New tables: users, user_roles (owner global-only; admin global or
  scoped to an agent_group), agent_group_members (explicit non-
  privileged access; admin/owner imply membership), user_dms (cold-DM
  resolution cache).
- Removed agent_groups.is_admin, messaging_groups.admin_user_id. Replaced
  with messaging_groups.unknown_sender_policy (strict | request_approval
  | public) for per-chat unknown-sender gating.
- src/access.ts: canAccessAgentGroup, pickApprover, pickApprovalDelivery.
- src/router.ts: access gate on every inbound, honoring
  unknown_sender_policy for unknown senders.
- src/channels/telegram.ts: pairing interceptor upserts the paired user
  and promotes them to owner if hasAnyOwner() is false (first-pair-wins).

Cold DM infrastructure
- ChannelAdapter.openDM?(handle) — optional method. Chat-SDK-bridge wires
  it to chat.openDM() for resolution-required channels (Discord, Slack,
  Teams, Webex, gChat); direct-addressable channels (Telegram, WhatsApp,
  iMessage, Matrix, Resend) fall through to the handle directly.
- src/user-dm.ts: ensureUserDm(userId) — resolves + caches via user_dms.

Approval routing
- onecli-approvals + delivery use pickApprover + pickApprovalDelivery:
  scoped admins → global admins → owners (dedup), first reachable via
  ensureUserDm, same-channel-kind tie-break. Approvals land in the
  approver's DM, not the origin chat.

Delivery fixes
- delivery.ts ACL rejection now throws instead of returning undefined —
  the outer loop previously marked rejected messages as delivered.
- Implicit-origin allow: session.messaging_group_id === target skips the
  destination check.
- createMessagingGroupAgent auto-creates the companion agent_destinations
  row (normalized local_name from the messaging group's name, collision-
  broken within the agent's namespace).

Container
- container-runner.ts: /workspace/global always read-only; drops
  NANOCLAW_IS_ADMIN; adds NANOCLAW_ADMIN_USER_IDS (owners + global admins
  + scoped admins for this agent group). Agent-runner poll-loop gates
  slash commands against that set.

New skill: /init-first-agent
- Walks the operator through standing up the first agent for a channel:
  channel pick → identity lookup (reads each channel SKILL.md's
  ## Channel Info > how-to-find-id) → DM platform_id resolution (direct-
  addressable, cold-DM via "user DMs bot first + sqlite lookup", or
  Telegram pair-code fallback) → run scripts/init-first-agent.ts →
  verify via tail of nanoclaw.log.
- scripts/init-first-agent.ts: parameterized helper that upserts the
  user + grants owner (if none), creates dm-with-<display-name> agent
  group + initGroupFilesystem, reuses/creates the DM messaging_group,
  wires it (auto-creates destination), resolves the session, and writes
  a kind:'chat' / sender:'system' welcome message into inbound.db. Host
  sweep wakes the container and the agent DMs the operator via the
  normal delivery path.

/manage-channels rewrite
- Drops --is-main / --jid / main-vs-non-main isolation references.
- First-channel flow delegates to /init-first-agent.
- Explains createMessagingGroupAgent auto-creates destinations.
- Adds a privileged-users show section.

setup/
- register.ts: drop --is-main, --jid, --local-name, --trigger
  requiresTrigger defaults; call initGroupFilesystem; normalize to
  v2 schema (no is_admin, no admin_user_id, sets unknown_sender_policy
  'strict'); let createMessagingGroupAgent handle the destination row.
- pair-telegram.ts: emit PAIRED_USER_ID (namespaced "telegram:<id>")
  instead of ADMIN_USER_ID; update header comment.
- register.test.ts deleted — was v1-only, tested a registered_groups
  table that no longer exists.

Docs
- v2-architecture-diagram.{md,html}: ER diagram updated to drop
  is_admin/admin_user_id, add unknown_sender_policy, and include
  users/user_roles/agent_group_members/user_dms.
- v2-architecture-draft.md: approval-routing paragraph rewritten for
  pickApprover/pickApprovalDelivery/ensureUserDm; SQL schema block
  updated; admin-verification paragraph references
  NANOCLAW_ADMIN_USER_IDS.
- v2-setup-wiring.md: entity-model sketch rewritten.
- v2-checklist.md: marked privilege refactor / container filtering /
  approval routing / unknown-sender gating done; removed obsolete
  admin_user_id and main-vs-non-main items.

Scripts
- scripts/init-first-agent.ts (new) replaces scripts/welcome-owner-dm.ts
  (removed; welcome-owner was a Discord-specific one-off).
- test-v2-host.ts, test-v2-channel-e2e.ts, seed-discord.ts: drop
  is_admin + admin_user_id, use unknown_sender_policy.

Tests
- src/access.test.ts (new): 14 tests for canAccessAgentGroup, role
  helpers, pickApprover, ensureUserDm, pickApprovalDelivery.
- src/db/db-v2.test.ts: adds 3 tests for the auto-created
  agent_destinations row (normalized name, no duplicates, collision
  break within an agent group).
- host-core.test.ts, channel-registry.test.ts: updated fixtures to
  use unknown_sender_policy: 'public' where the test exercises routing
  rather than the access gate.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 00:03:51 +03:00
Gabi Simons
8d60af71d3 feat(v2): add /add-vercel skill for agent Vercel deployments
Setup skill that installs Vercel CLI in agent containers and configures
OneCLI credential injection for api.vercel.com. Container skill bundled
in .claude/skills/add-vercel/container-skills/ and copied to
container/skills/ during setup. Also adds dashboard & web apps prompt
to /setup flow (step 5b).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-14 15:24:31 +00:00
Gabi Simons
192a5a7569 docs(v2): add /add-whatsapp-v2 setup skill
Separate from the v1 /add-whatsapp skill — v1 remains untouched.
Follows the v2 skill pattern (flat sections, defers to /manage-channels
for wiring). Covers Baileys auth, pairing code, QR code, and
documents the native adapter's features and limitations.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-14 12:02:27 +00:00
Koshkoshinsk
65afcdc946 feat(telegram-pairing): surface wrong-code attempts + auto-regen with retry cap
- createPairing now replaces any existing pending pairing for the same intent
  (replace-by-default; no "two pending codes for one intent" state)
- tryConsume records each attempt on pending records (capped at 10); a
  wrong code invalidates the pairing immediately (one attempt per code)
- waitForPairing gains onAttempt callback for misses and rejects with a
  distinct "invalidated by wrong code" message so callers can distinguish
  TTL expiry from user-error
- pair-telegram emits PAIR_TELEGRAM_ATTEMPT on misses and auto-regenerates
  the pairing up to 5 times, emitting PAIR_TELEGRAM_NEW_CODE for each
- Skill docs updated so the host Claude knows to show new codes and
  offer another batch on max-regenerations-exceeded

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 12:27:09 +00:00
Koshkoshinsk
2454444f2e feat(telegram-pairing): accept bare 4-digit codes
Require the message to be exactly the 4 digits (optionally prefixed by
@botname). Loose matches like "my pin is 0349" are rejected to avoid false
positives from chat traffic that happens to contain a 4-digit number.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 12:27:06 +00:00
Koshkoshinsk
2017589683 feat(telegram): self-contained pairing for chat ownership verification
BotFather issues bot tokens with no user binding, so anyone who guesses the
bot's username can DM it and get registered as a channel. Pairing closes that
gap: setup issues a one-time 4-digit code, the operator echoes it back from
the chat they want to register, and the inbound interceptor binds
admin_user_id before the message reaches the router.

- src/channels/telegram-pairing.ts: JSON-backed store with createPairing,
  tryConsume, getStatus, waitForPairing (fs.watch + poll fallback)
- src/channels/telegram.ts: wraps bridge.setup with an onInbound interceptor
  that consumes pairing codes and upserts messaging_groups
- setup/pair-telegram.ts: CLI step issues a code and waits up to 5 min for
  the operator to echo it back, emitting PLATFORM_ID/IS_GROUP/ADMIN_USER_ID
- Skill docs: /setup reorders mounts -> service -> wire (pairing needs a
  live polling adapter); /manage-channels and /add-telegram-v2 use pairing
  instead of asking the user to discover chat IDs

All other channels still bind admin via install-time identity (OAuth/QR/token);
pairing is Telegram-only. The bridge, router, and other adapters are untouched.
2026-04-13 12:27:02 +00:00
Gabi Simons
3db0dceb1b docs(teams-v2): full setup guide with Azure CLI, manifest, and sideloading
Rewrites the add-teams-v2 skill with step-by-step instructions
covering App Registration, client secret, Azure Bot creation (portal
and CLI), messaging endpoint, Teams channel, manifest template,
sideloading, and RSC permissions for receiving all messages.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 07:45:28 +00:00
gavrielc
f0e4f07ac2 refactor(v2): extract webhook server into standalone module
Aligns with upstream feat/chat-sdk-integration pattern: regex-based
routing (/webhook/{adapterName}), response streaming, cleanup function.
Updates Slack and Teams skill docs to match /webhook/{name} convention
used by all other v2 channel skills.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 17:36:16 +03:00
gavrielc
5a606a83d4 refactor(v2): use Chat SDK webhooks proxy and clean up webhook server
Route webhook requests through chat.webhooks[name]() instead of calling
adapter.handleWebhook() directly, getting proper auto-initialization and
signature verification. Extract Node↔Web Request/Response conversion
into reusable helpers, parse URL pathname properly for query string
safety, and support all HTTP methods (not just POST).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 17:36:16 +03:00
Gabi Simons
7e74bfd330 feat(v2): Teams adapter env-driven app type and updated skill docs
Teams adapter now reads TEAMS_APP_TYPE and TEAMS_APP_TENANT_ID from
env, supporting both MultiTenant (default) and SingleTenant configs.
Updated add-teams-v2 skill docs with full Azure Bot setup flow,
webhook endpoint format, and app package sideloading instructions.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 12:34:09 +00:00
Gabi Simons
a9f9eda9f8 docs(slack-v2): update skill with DM setup, webhook URL, and reinstall step
Corrects webhook URL to /api/webhooks/slack, adds Enable DMs step
(App Home > Messages Tab), documents reinstall requirement after
adding event subscriptions, and adds webhook server section.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 12:33:56 +00:00
Gabi Simons
9af9bc947a fix(discord-v2): document required DISCORD_PUBLIC_KEY and APPLICATION_ID
The Discord adapter fails to start without all three env vars. Also
fix platform ID format docs to show discord:{guildId}:{channelId}.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 13:57:28 +00:00
gavrielc
57a6491c7e v2: channel isolation model, manage-channels skill, refactored channel skills
- Add three-level isolation model (shared session, same agent, separate agent)
  with agent-shared session mode for cross-channel shared sessions
- Create /manage-channels skill for wiring channels to agent groups
- Refactor all 12 v2 channel skills: lean SKILL.md + VERIFY.md + REMOVE.md
  with structured Channel Info section for platform-specific metadata
- Create /add-discord-v2 skill (was missing)
- Add step 5a to setup SKILL.md invoking /manage-channels after channel install
- Update setup/verify.ts to check all 12 channel token types
- Add docs/v2-isolation-model.md explaining the isolation model
- Update v2-checklist.md and v2-setup-wiring.md to reflect completed work

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 13:19:19 +03:00
gavrielc
9486d56b01 v2: make v2 the main entry point, move v1 to src/v1/
- Move all v1 files (index, router, container-runner, db, ipc, types,
  logger, channels/registry, and all utilities) to src/v1/ as a
  fully self-contained archive with no shared dependencies
- Rename v2 files to remove -v2 suffix (index-v2.ts → index.ts, etc.)
- Update all imports across v2 source, tests, and setup files
- Migrate shared utilities (config, env, container-runtime, mount-security,
  timezone, group-folder) from pino logger to v2 log module
- Migrate setup/ files from logger to log with argument order swap
- Container agent-runner: move v1 entry to v1/, rename v2 to index.ts
- Update setup skill to offer all 13 v2 channels
- Install all Chat SDK adapter packages
- dist/index.js now runs v2; dist/v1/index.js runs v1

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 11:40:36 +03:00
gavrielc
12af451069 v2: add Chat SDK channel adapters and skills for 11 platforms
Thin wrapper adapters + SKILL.md for Slack, Telegram, GitHub, Linear,
Google Chat, Teams, WhatsApp Cloud API, Resend, Matrix, Webex, iMessage.
All follow the same pattern as discord-v2.ts: readEnvFile → create*Adapter
→ createChatSdkBridge → registerChannelAdapter.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 11:26:33 +03:00
gavrielc
32a487b96b Merge pull request #1660 from johnnyfish/fix/gmail-onecli-credential-mode
fix(gmail): add OneCLI credential mode detection
2026-04-07 01:12:05 +03:00
johnnyfish
751a9ed2d1 fix(gmail): add OneCLI credential mode detection 2026-04-06 20:34:24 +03:00
gavrielc
22d7856ce0 reduce setup friction 2026-04-06 01:19:22 +03:00