@openparachute/agent 0.1.2 → 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.parachute/module.json +124 -8
- package/LICENSE +2 -16
- package/README.md +118 -166
- package/package.json +35 -42
- package/scripts/spawn-agent.ts +371 -0
- package/src/_parked/interactive-spawn.test.ts +324 -0
- package/src/_parked/interactive-spawn.ts +701 -0
- package/src/agent-defs.test.ts +1504 -0
- package/src/agent-defs.ts +1702 -0
- package/src/agent-mcp-config.test.ts +115 -0
- package/src/agent-mcp-config.ts +115 -0
- package/src/agents.test.ts +360 -0
- package/src/agents.ts +379 -0
- package/src/auth.test.ts +46 -0
- package/src/auth.ts +140 -0
- package/src/backends/attached-queue.test.ts +376 -0
- package/src/backends/attached-queue.ts +372 -0
- package/src/backends/programmatic.test.ts +1715 -0
- package/src/backends/programmatic.ts +927 -0
- package/src/backends/registry.test.ts +1494 -0
- package/src/backends/registry.ts +1202 -0
- package/src/backends/stream-json.test.ts +570 -0
- package/src/backends/stream-json.ts +392 -0
- package/src/backends/types.ts +223 -0
- package/src/bridge.ts +417 -0
- package/src/channel-backend-wiring.test.ts +237 -0
- package/src/credentials.test.ts +274 -0
- package/src/credentials.ts +380 -0
- package/src/cron.test.ts +342 -0
- package/src/cron.ts +380 -0
- package/src/daemon-agent-def-api.test.ts +166 -0
- package/src/daemon-agent-defs-api.test.ts +953 -0
- package/src/daemon-agent-env-api.test.ts +338 -0
- package/src/daemon-attached-queue-store.test.ts +65 -0
- package/src/daemon-config-api.test.ts +962 -0
- package/src/daemon-jobs-api.test.ts +271 -0
- package/src/daemon-vault-chat.test.ts +250 -0
- package/src/daemon.test.ts +746 -0
- package/src/daemon.ts +3314 -0
- package/src/def-vaults.test.ts +136 -0
- package/src/def-vaults.ts +165 -0
- package/src/delivery-state.test.ts +110 -0
- package/src/delivery-state.ts +154 -0
- package/src/effective-env.test.ts +114 -0
- package/src/effective-env.ts +184 -0
- package/src/env-compat.ts +39 -0
- package/src/grants.test.ts +638 -0
- package/src/grants.ts +675 -0
- package/src/hub-jwt.test.ts +161 -0
- package/src/hub-jwt.ts +182 -0
- package/src/jobs.test.ts +245 -0
- package/src/jobs.ts +266 -0
- package/src/mcp-http.test.ts +265 -0
- package/src/mcp-http.ts +771 -0
- package/src/mint-token.test.ts +152 -0
- package/src/mint-token.ts +139 -0
- package/src/module-manifest.test.ts +158 -0
- package/src/oauth-discovery.ts +134 -0
- package/src/programmatic-wiring.test.ts +838 -0
- package/src/registry.test.ts +227 -0
- package/src/registry.ts +228 -0
- package/src/resolve-port.test.ts +64 -0
- package/src/routing.test.ts +184 -0
- package/src/routing.ts +76 -0
- package/src/runner.test.ts +506 -0
- package/src/runner.ts +255 -0
- package/src/sandbox/config.test.ts +150 -0
- package/src/sandbox/config.ts +102 -0
- package/src/sandbox/egress.test.ts +113 -0
- package/src/sandbox/egress.ts +123 -0
- package/src/sandbox/index.ts +180 -0
- package/src/sandbox/live-seatbelt.test.ts +277 -0
- package/src/sandbox/mounts.test.ts +154 -0
- package/src/sandbox/mounts.ts +133 -0
- package/src/sandbox/sandbox.test.ts +168 -0
- package/src/sandbox/types.ts +382 -0
- package/src/services-manifest.test.ts +106 -0
- package/src/services-manifest.ts +95 -0
- package/src/spa-serve.test.ts +116 -0
- package/src/spa-serve.ts +116 -0
- package/src/spawn-agent-cli.test.ts +172 -0
- package/src/spawn-agent.test.ts +1218 -0
- package/src/spawn-agent.ts +569 -0
- package/src/spawn-deps.test.ts +54 -0
- package/src/spawn-deps.ts +166 -0
- package/src/telegram/api.ts +153 -0
- package/src/terminal-assets.test.ts +50 -0
- package/src/terminal-assets.ts +79 -0
- package/src/terminal-ui.ts +305 -0
- package/src/terminal.test.ts +530 -0
- package/src/terminal.ts +458 -0
- package/src/transport.ts +270 -0
- package/src/transports/http-ui.test.ts +455 -0
- package/src/transports/http-ui.ts +201 -0
- package/src/transports/telegram.test.ts +174 -0
- package/src/transports/telegram.ts +426 -0
- package/src/transports/vault.test.ts +2011 -0
- package/src/transports/vault.ts +1790 -0
- package/src/ui-kit.test.ts +178 -0
- package/src/ui-kit.ts +402 -0
- package/tsconfig.json +8 -14
- package/web/ui/dist/assets/index-C-iWdFFV.css +1 -0
- package/web/ui/dist/assets/index-VFETBk0a.js +60 -0
- package/web/ui/dist/index.html +15 -0
- package/web/ui/tsconfig.json +2 -1
- package/.claude/scheduled_tasks.lock +0 -1
- package/.claude/settings.json +0 -5
- package/.claude/skills/add-atomic-chat-tool/SKILL.md +0 -243
- package/.claude/skills/add-atomic-chat-tool/atomic-chat-mcp-stdio.ts +0 -229
- package/.claude/skills/add-codex/SKILL.md +0 -161
- package/.claude/skills/add-dashboard/SKILL.md +0 -138
- package/.claude/skills/add-dashboard/resources/dashboard-pusher.ts +0 -495
- package/.claude/skills/add-emacs/SKILL.md +0 -296
- package/.claude/skills/add-gcal-tool/SKILL.md +0 -210
- package/.claude/skills/add-gchat/REMOVE.md +0 -6
- package/.claude/skills/add-gchat/SKILL.md +0 -92
- package/.claude/skills/add-gchat/VERIFY.md +0 -3
- package/.claude/skills/add-github/REMOVE.md +0 -6
- package/.claude/skills/add-github/SKILL.md +0 -148
- package/.claude/skills/add-github/VERIFY.md +0 -3
- package/.claude/skills/add-gmail-tool/SKILL.md +0 -229
- package/.claude/skills/add-imessage/REMOVE.md +0 -6
- package/.claude/skills/add-imessage/SKILL.md +0 -113
- package/.claude/skills/add-imessage/VERIFY.md +0 -3
- package/.claude/skills/add-karpathy-llm-wiki/SKILL.md +0 -110
- package/.claude/skills/add-karpathy-llm-wiki/llm-wiki.md +0 -75
- package/.claude/skills/add-linear/REMOVE.md +0 -6
- package/.claude/skills/add-linear/SKILL.md +0 -168
- package/.claude/skills/add-linear/VERIFY.md +0 -3
- package/.claude/skills/add-macos-statusbar/SKILL.md +0 -133
- package/.claude/skills/add-macos-statusbar/add/src/statusbar.swift +0 -147
- package/.claude/skills/add-matrix/REMOVE.md +0 -6
- package/.claude/skills/add-matrix/SKILL.md +0 -148
- package/.claude/skills/add-matrix/VERIFY.md +0 -3
- package/.claude/skills/add-ollama-provider/SKILL.md +0 -179
- package/.claude/skills/add-ollama-tool/SKILL.md +0 -193
- package/.claude/skills/add-opencode/SKILL.md +0 -229
- package/.claude/skills/add-parallel/SKILL.md +0 -290
- package/.claude/skills/add-resend/REMOVE.md +0 -6
- package/.claude/skills/add-resend/SKILL.md +0 -93
- package/.claude/skills/add-resend/VERIFY.md +0 -3
- package/.claude/skills/add-signal/REMOVE.md +0 -13
- package/.claude/skills/add-signal/SKILL.md +0 -318
- package/.claude/skills/add-signal/VERIFY.md +0 -5
- package/.claude/skills/add-slack/REMOVE.md +0 -6
- package/.claude/skills/add-slack/SKILL.md +0 -112
- package/.claude/skills/add-slack/VERIFY.md +0 -3
- package/.claude/skills/add-teams/REMOVE.md +0 -6
- package/.claude/skills/add-teams/SKILL.md +0 -207
- package/.claude/skills/add-teams/VERIFY.md +0 -3
- package/.claude/skills/add-vercel/SKILL.md +0 -147
- package/.claude/skills/add-vercel/container-skills/vercel-cli/SKILL.md +0 -103
- package/.claude/skills/add-webex/REMOVE.md +0 -6
- package/.claude/skills/add-webex/SKILL.md +0 -88
- package/.claude/skills/add-webex/VERIFY.md +0 -3
- package/.claude/skills/add-wechat/REMOVE.md +0 -49
- package/.claude/skills/add-wechat/SKILL.md +0 -170
- package/.claude/skills/add-wechat/scripts/wire-dm.ts +0 -172
- package/.claude/skills/add-whatsapp/SKILL.md +0 -264
- package/.claude/skills/add-whatsapp-cloud/REMOVE.md +0 -6
- package/.claude/skills/add-whatsapp-cloud/SKILL.md +0 -95
- package/.claude/skills/add-whatsapp-cloud/VERIFY.md +0 -3
- package/.claude/skills/claw/SKILL.md +0 -131
- package/.claude/skills/claw/scripts/claw +0 -374
- package/.claude/skills/convert-to-apple-container/SKILL.md +0 -212
- package/.claude/skills/customize/SKILL.md +0 -110
- package/.claude/skills/debug/SKILL.md +0 -349
- package/.claude/skills/get-qodo-rules/SKILL.md +0 -122
- package/.claude/skills/get-qodo-rules/references/output-format.md +0 -41
- package/.claude/skills/get-qodo-rules/references/pagination.md +0 -33
- package/.claude/skills/get-qodo-rules/references/repository-scope.md +0 -26
- package/.claude/skills/init-first-agent/SKILL.md +0 -120
- package/.claude/skills/init-onecli/SKILL.md +0 -270
- package/.claude/skills/manage-channels/SKILL.md +0 -87
- package/.claude/skills/manage-mounts/SKILL.md +0 -47
- package/.claude/skills/migrate-from-openclaw/MIGRATE_CRONS.md +0 -100
- package/.claude/skills/migrate-from-openclaw/SKILL.md +0 -447
- package/.claude/skills/migrate-from-openclaw/scripts/discover-openclaw.ts +0 -734
- package/.claude/skills/migrate-from-openclaw/scripts/extract-channel-credentials.ts +0 -476
- package/.claude/skills/migrate-nanoclaw/SKILL.md +0 -484
- package/.claude/skills/migrate-nanoclaw/diagnostics.md +0 -51
- package/.claude/skills/qodo-pr-resolver/SKILL.md +0 -326
- package/.claude/skills/qodo-pr-resolver/resources/providers.md +0 -329
- package/.claude/skills/update-nanoclaw/SKILL.md +0 -243
- package/.claude/skills/update-nanoclaw/diagnostics.md +0 -48
- package/.claude/skills/update-skills/SKILL.md +0 -130
- package/.claude/skills/use-native-credential-proxy/SKILL.md +0 -167
- package/.claude/skills/x-integration/SKILL.md +0 -417
- package/.claude/skills/x-integration/agent.ts +0 -243
- package/.claude/skills/x-integration/host.ts +0 -155
- package/.claude/skills/x-integration/lib/browser.ts +0 -148
- package/.claude/skills/x-integration/lib/config.ts +0 -62
- package/.claude/skills/x-integration/scripts/like.ts +0 -56
- package/.claude/skills/x-integration/scripts/post.ts +0 -66
- package/.claude/skills/x-integration/scripts/quote.ts +0 -80
- package/.claude/skills/x-integration/scripts/reply.ts +0 -74
- package/.claude/skills/x-integration/scripts/retweet.ts +0 -62
- package/.claude/skills/x-integration/scripts/setup.ts +0 -87
- package/.github/CODEOWNERS +0 -10
- package/.github/PULL_REQUEST_TEMPLATE.md +0 -18
- package/.github/workflows/bump-version.yml +0 -35
- package/.github/workflows/ci.yml +0 -39
- package/.github/workflows/label-pr.yml +0 -40
- package/.github/workflows/update-tokens.yml +0 -43
- package/.husky/pre-commit +0 -1
- package/.mcp.json +0 -3
- package/.nvmrc +0 -1
- package/.prettierrc +0 -4
- package/CHANGELOG.md +0 -263
- package/CLAUDE.md +0 -307
- package/CODE_OF_CONDUCT.md +0 -128
- package/CONTRIBUTING.md +0 -159
- package/CONTRIBUTORS.md +0 -26
- package/LICENSE-NANOCLAW-MIT +0 -21
- package/README_ja.md +0 -194
- package/README_zh.md +0 -194
- package/assets/nanoclaw-favicon.png +0 -0
- package/assets/nanoclaw-icon.png +0 -0
- package/assets/nanoclaw-logo-dark.png +0 -0
- package/assets/nanoclaw-logo.png +0 -0
- package/assets/nanoclaw-profile.jpeg +0 -0
- package/assets/nanoclaw-sales.png +0 -0
- package/assets/social-preview.jpg +0 -0
- package/config-examples/mount-allowlist.json +0 -25
- package/container/.dockerignore +0 -2
- package/container/CLAUDE.md +0 -21
- package/container/Dockerfile +0 -121
- package/container/agent-runner/bun.lock +0 -243
- package/container/agent-runner/package.json +0 -22
- package/container/agent-runner/scripts/sdk-signal-probe.ts +0 -169
- package/container/agent-runner/src/config.ts +0 -55
- package/container/agent-runner/src/db/connection.ts +0 -267
- package/container/agent-runner/src/db/index.ts +0 -20
- package/container/agent-runner/src/db/messages-in.ts +0 -138
- package/container/agent-runner/src/db/messages-out.ts +0 -143
- package/container/agent-runner/src/db/session-routing.ts +0 -30
- package/container/agent-runner/src/db/session-state.test.ts +0 -100
- package/container/agent-runner/src/db/session-state.ts +0 -79
- package/container/agent-runner/src/destinations.ts +0 -135
- package/container/agent-runner/src/formatter.test.ts +0 -167
- package/container/agent-runner/src/formatter.ts +0 -260
- package/container/agent-runner/src/index.ts +0 -110
- package/container/agent-runner/src/integration.test.ts +0 -121
- package/container/agent-runner/src/mcp-tools/agents.instructions.md +0 -26
- package/container/agent-runner/src/mcp-tools/agents.ts +0 -66
- package/container/agent-runner/src/mcp-tools/core.instructions.md +0 -27
- package/container/agent-runner/src/mcp-tools/core.ts +0 -262
- package/container/agent-runner/src/mcp-tools/index.ts +0 -22
- package/container/agent-runner/src/mcp-tools/interactive.instructions.md +0 -22
- package/container/agent-runner/src/mcp-tools/interactive.ts +0 -169
- package/container/agent-runner/src/mcp-tools/scheduling.instructions.md +0 -40
- package/container/agent-runner/src/mcp-tools/scheduling.ts +0 -299
- package/container/agent-runner/src/mcp-tools/self-mod.instructions.md +0 -25
- package/container/agent-runner/src/mcp-tools/self-mod.ts +0 -120
- package/container/agent-runner/src/mcp-tools/server.ts +0 -54
- package/container/agent-runner/src/mcp-tools/types.ts +0 -6
- package/container/agent-runner/src/poll-loop.test.ts +0 -248
- package/container/agent-runner/src/poll-loop.ts +0 -437
- package/container/agent-runner/src/providers/claude.ts +0 -379
- package/container/agent-runner/src/providers/factory.test.ts +0 -19
- package/container/agent-runner/src/providers/factory.ts +0 -13
- package/container/agent-runner/src/providers/index.ts +0 -6
- package/container/agent-runner/src/providers/mock.ts +0 -77
- package/container/agent-runner/src/providers/provider-registry.ts +0 -33
- package/container/agent-runner/src/providers/types.ts +0 -82
- package/container/agent-runner/src/scheduling/task-script.ts +0 -121
- package/container/agent-runner/src/timezone.test.ts +0 -93
- package/container/agent-runner/src/timezone.ts +0 -107
- package/container/agent-runner/tsconfig.json +0 -14
- package/container/build.sh +0 -48
- package/container/entrypoint.sh +0 -16
- package/container/skills/agent-browser/SKILL.md +0 -159
- package/container/skills/frontend-engineer/SKILL.md +0 -157
- package/container/skills/self-customize/SKILL.md +0 -87
- package/container/skills/slack-formatting/SKILL.md +0 -94
- package/container/skills/vercel-cli/SKILL.md +0 -111
- package/container/skills/welcome/SKILL.md +0 -85
- package/docs/APPLE-CONTAINER-NETWORKING.md +0 -90
- package/docs/BRANCH-FORK-MAINTENANCE.md +0 -81
- package/docs/README.md +0 -25
- package/docs/SDK_DEEP_DIVE.md +0 -643
- package/docs/SECURITY.md +0 -162
- package/docs/agent-runner-details.md +0 -749
- package/docs/api-details.md +0 -365
- package/docs/architecture-diagram.html +0 -422
- package/docs/architecture-diagram.md +0 -215
- package/docs/architecture.md +0 -751
- package/docs/audit/2026-04-30-channel-endpoint-audit.md +0 -36
- package/docs/build-and-runtime.md +0 -80
- package/docs/cross-mount-stress/README.md +0 -112
- package/docs/cross-mount-stress/container-writer-retry.mjs +0 -55
- package/docs/cross-mount-stress/container-writer-slow.mjs +0 -42
- package/docs/cross-mount-stress/container-writer.mjs +0 -47
- package/docs/cross-mount-stress/host-writer-retry.mjs +0 -55
- package/docs/cross-mount-stress/host-writer-slow.mjs +0 -43
- package/docs/cross-mount-stress/host-writer.mjs +0 -47
- package/docs/db-central.md +0 -316
- package/docs/db-session.md +0 -183
- package/docs/db.md +0 -119
- package/docs/design/2026-04-29-vault-management-ui.md +0 -231
- package/docs/design/2026-04-30-channel-wiring-rework.md +0 -234
- package/docs/design/2026-05-01-channel-wiring-approvals-deep-dive.md +0 -272
- package/docs/design/2026-05-02-channel-policy-and-approval-routing.md +0 -250
- package/docs/docker-sandboxes.md +0 -359
- package/docs/isolation-model.md +0 -88
- package/docs/ollama.md +0 -79
- package/docs/parachute-integration.md +0 -109
- package/docs/post-night-rebirth-reflections.md +0 -151
- package/eslint.config.js +0 -32
- package/pnpm-workspace.yaml +0 -8
- package/repo-tokens/README.md +0 -113
- package/repo-tokens/action.yml +0 -186
- package/repo-tokens/badge.svg +0 -23
- package/repo-tokens/examples/green.svg +0 -14
- package/repo-tokens/examples/red.svg +0 -14
- package/repo-tokens/examples/yellow-green.svg +0 -14
- package/repo-tokens/examples/yellow.svg +0 -14
- package/scripts/chat.ts +0 -101
- package/scripts/cleanup-sessions.sh +0 -150
- package/scripts/init-cli-agent.ts +0 -172
- package/scripts/init-first-agent.ts +0 -378
- package/scripts/parachute.ts +0 -158
- package/scripts/run-migrations.ts +0 -105
- package/scripts/sanity-live-poll.ts +0 -95
- package/scripts/seed-discord.ts +0 -80
- package/scripts/test-v2-agent.ts +0 -106
- package/scripts/test-v2-channel-e2e.ts +0 -265
- package/scripts/test-v2-host.ts +0 -184
- package/src/channels/adapter.ts +0 -214
- package/src/channels/api-translator.test.ts +0 -306
- package/src/channels/api-translator.ts +0 -214
- package/src/channels/ask-question.ts +0 -46
- package/src/channels/channel-registry.test.ts +0 -421
- package/src/channels/channel-registry.ts +0 -313
- package/src/channels/chat-sdk-bridge.test.ts +0 -84
- package/src/channels/chat-sdk-bridge.ts +0 -652
- package/src/channels/cli.ts +0 -276
- package/src/channels/discord.ts +0 -90
- package/src/channels/index.ts +0 -17
- package/src/channels/telegram-markdown-sanitize.test.ts +0 -78
- package/src/channels/telegram-markdown-sanitize.ts +0 -55
- package/src/channels/telegram-pairing.test.ts +0 -254
- package/src/channels/telegram-pairing.ts +0 -339
- package/src/channels/telegram.ts +0 -279
- package/src/channels/trust-hint.test.ts +0 -48
- package/src/channels/trust-hint.ts +0 -75
- package/src/claude-md-compose.migrate.test.ts +0 -64
- package/src/claude-md-compose.ts +0 -205
- package/src/command-gate.ts +0 -63
- package/src/config.test.ts +0 -93
- package/src/config.ts +0 -128
- package/src/container-config.ts +0 -167
- package/src/container-runner.test.ts +0 -32
- package/src/container-runner.ts +0 -576
- package/src/container-runtime.test.ts +0 -269
- package/src/container-runtime.ts +0 -167
- package/src/db/_bun-sqlite-shim.ts +0 -88
- package/src/db/agent-activity.test.ts +0 -155
- package/src/db/agent-activity.ts +0 -121
- package/src/db/agent-groups.ts +0 -77
- package/src/db/connection.migrate.test.ts +0 -176
- package/src/db/connection.ts +0 -259
- package/src/db/db-v2.test.ts +0 -440
- package/src/db/dropped-messages.ts +0 -44
- package/src/db/index.ts +0 -40
- package/src/db/messaging-groups.ts +0 -252
- package/src/db/migrations/001-initial.ts +0 -112
- package/src/db/migrations/002-chat-sdk-state.ts +0 -36
- package/src/db/migrations/008-dropped-messages.ts +0 -27
- package/src/db/migrations/009-drop-pending-credentials.ts +0 -13
- package/src/db/migrations/010-engage-modes.ts +0 -103
- package/src/db/migrations/011-pending-sender-approvals.ts +0 -40
- package/src/db/migrations/012-channel-registration.ts +0 -48
- package/src/db/migrations/013-approval-render-metadata.ts +0 -27
- package/src/db/migrations/014-secrets.ts +0 -44
- package/src/db/migrations/015-secrets-drop-host-pattern.ts +0 -18
- package/src/db/migrations/016-secret-assignments.ts +0 -30
- package/src/db/migrations/017-agent-activity.ts +0 -40
- package/src/db/migrations/018-oauth-app-configs.ts +0 -34
- package/src/db/migrations/019-oauth-app-connections.ts +0 -48
- package/src/db/migrations/020-agent-app-connections.ts +0 -28
- package/src/db/migrations/021-pending-oauth-states.ts +0 -35
- package/src/db/migrations/022-app-connections-provider.ts +0 -25
- package/src/db/migrations/023-agent-group-secret-mode.test.ts +0 -124
- package/src/db/migrations/023-agent-group-secret-mode.ts +0 -65
- package/src/db/migrations/024-collapse-approvals.test.ts +0 -249
- package/src/db/migrations/024-collapse-approvals.ts +0 -182
- package/src/db/migrations/025-secret-mode-check.test.ts +0 -155
- package/src/db/migrations/025-secret-mode-check.ts +0 -49
- package/src/db/migrations/026-user-dms-bot-id.test.ts +0 -116
- package/src/db/migrations/026-user-dms-bot-id.ts +0 -54
- package/src/db/migrations/027-provider-credentials.ts +0 -41
- package/src/db/migrations/_test-helpers.ts +0 -41
- package/src/db/migrations/index.ts +0 -127
- package/src/db/migrations/module-agent-to-agent-destinations.ts +0 -84
- package/src/db/migrations/module-approvals-pending-approvals.ts +0 -42
- package/src/db/migrations/module-approvals-title-options.ts +0 -40
- package/src/db/schema.ts +0 -258
- package/src/db/session-db.test.ts +0 -93
- package/src/db/session-db.ts +0 -325
- package/src/db/sessions.ts +0 -241
- package/src/delivery.test.ts +0 -148
- package/src/delivery.ts +0 -445
- package/src/env.ts +0 -74
- package/src/group-folder.test.ts +0 -35
- package/src/group-folder.ts +0 -44
- package/src/group-init.ts +0 -92
- package/src/host-core.test.ts +0 -456
- package/src/host-sweep.test.ts +0 -146
- package/src/host-sweep.ts +0 -287
- package/src/index.ts +0 -232
- package/src/install-slug.ts +0 -33
- package/src/log.test.ts +0 -81
- package/src/log.ts +0 -117
- package/src/mcp/http.ts +0 -72
- package/src/mcp/server.ts +0 -92
- package/src/mcp/stdio.ts +0 -51
- package/src/mcp/tools/activity.ts +0 -88
- package/src/mcp/tools/agent-groups.ts +0 -183
- package/src/mcp/tools/approvals.ts +0 -122
- package/src/mcp/tools/channels.test.ts +0 -126
- package/src/mcp/tools/channels.ts +0 -134
- package/src/mcp/tools/index.ts +0 -27
- package/src/mcp/tools/oauth.ts +0 -48
- package/src/mcp/tools/secrets.ts +0 -169
- package/src/mcp/tools/sessions.ts +0 -135
- package/src/mcp/types.ts +0 -51
- package/src/modules/agent-to-agent/agent-route.test.ts +0 -46
- package/src/modules/agent-to-agent/agent-route.ts +0 -223
- package/src/modules/agent-to-agent/create-agent.ts +0 -127
- package/src/modules/agent-to-agent/db/agent-destinations.ts +0 -135
- package/src/modules/agent-to-agent/index.ts +0 -22
- package/src/modules/agent-to-agent/write-destinations.ts +0 -59
- package/src/modules/approvals/agent.md +0 -45
- package/src/modules/approvals/index.ts +0 -21
- package/src/modules/approvals/picks.test.ts +0 -291
- package/src/modules/approvals/primitive.ts +0 -279
- package/src/modules/approvals/project.md +0 -27
- package/src/modules/approvals/response-handler.ts +0 -87
- package/src/modules/index.ts +0 -24
- package/src/modules/interactive/agent.md +0 -21
- package/src/modules/interactive/index.ts +0 -69
- package/src/modules/interactive/project.md +0 -12
- package/src/modules/mount-security/expand-path.test.ts +0 -82
- package/src/modules/mount-security/index.ts +0 -459
- package/src/modules/mount-security/migrate.test.ts +0 -91
- package/src/modules/permissions/access.ts +0 -28
- package/src/modules/permissions/channel-approval.test.ts +0 -389
- package/src/modules/permissions/channel-approval.ts +0 -188
- package/src/modules/permissions/db/agent-group-members.ts +0 -44
- package/src/modules/permissions/db/pending-channel-approvals.test.ts +0 -86
- package/src/modules/permissions/db/pending-channel-approvals.ts +0 -66
- package/src/modules/permissions/db/pending-sender-approvals.ts +0 -60
- package/src/modules/permissions/db/user-dms.ts +0 -58
- package/src/modules/permissions/db/user-roles.ts +0 -85
- package/src/modules/permissions/db/users.ts +0 -38
- package/src/modules/permissions/index.ts +0 -421
- package/src/modules/permissions/permissions.test.ts +0 -358
- package/src/modules/permissions/sender-approval.test.ts +0 -641
- package/src/modules/permissions/sender-approval.ts +0 -165
- package/src/modules/permissions/user-dm.ts +0 -200
- package/src/modules/provider-credentials/db.ts +0 -121
- package/src/modules/provider-credentials/index.ts +0 -12
- package/src/modules/provider-credentials/spawn.test.ts +0 -206
- package/src/modules/provider-credentials/spawn.ts +0 -114
- package/src/modules/scheduling/actions.ts +0 -113
- package/src/modules/scheduling/db.test.ts +0 -282
- package/src/modules/scheduling/db.ts +0 -148
- package/src/modules/scheduling/index.ts +0 -34
- package/src/modules/scheduling/recurrence.test.ts +0 -98
- package/src/modules/scheduling/recurrence.ts +0 -54
- package/src/modules/self-mod/agent.md +0 -30
- package/src/modules/self-mod/apply.ts +0 -85
- package/src/modules/self-mod/index.ts +0 -30
- package/src/modules/self-mod/project.md +0 -39
- package/src/modules/self-mod/request.ts +0 -91
- package/src/modules/typing/index.ts +0 -165
- package/src/oauth/agent-app-connections.ts +0 -103
- package/src/oauth/app-configs.test.ts +0 -64
- package/src/oauth/app-configs.ts +0 -114
- package/src/oauth/app-connections.test.ts +0 -109
- package/src/oauth/app-connections.ts +0 -178
- package/src/oauth/crypto.ts +0 -56
- package/src/oauth/flow.ts +0 -104
- package/src/oauth/providers/google.test.ts +0 -38
- package/src/oauth/providers/google.ts +0 -46
- package/src/oauth/providers/index.ts +0 -48
- package/src/oauth/state-store.test.ts +0 -54
- package/src/oauth/state-store.ts +0 -93
- package/src/parachute/README.md +0 -27
- package/src/parachute/create-agent.test.ts +0 -83
- package/src/parachute/create-agent.ts +0 -122
- package/src/parachute/group-status.test.ts +0 -165
- package/src/parachute/group-status.ts +0 -136
- package/src/parachute/types.ts +0 -41
- package/src/parachute/vault-mcp.test.ts +0 -251
- package/src/parachute/vault-mcp.ts +0 -232
- package/src/platform-id.test.ts +0 -104
- package/src/platform-id.ts +0 -109
- package/src/providers/index.ts +0 -6
- package/src/providers/provider-container-registry.ts +0 -58
- package/src/response-registry.ts +0 -45
- package/src/router.ts +0 -530
- package/src/secrets/crypto.test.ts +0 -45
- package/src/secrets/crypto.ts +0 -55
- package/src/secrets/index.ts +0 -461
- package/src/secrets/master-key.ts +0 -70
- package/src/secrets/secrets.test.ts +0 -651
- package/src/session-manager.attachments.test.ts +0 -171
- package/src/session-manager.dup-skip.test.ts +0 -173
- package/src/session-manager.migrate.test.ts +0 -59
- package/src/session-manager.ts +0 -451
- package/src/startup-bootstrap.test.ts +0 -226
- package/src/startup-bootstrap.ts +0 -207
- package/src/state-sqlite.ts +0 -182
- package/src/timezone.test.ts +0 -64
- package/src/timezone.ts +0 -37
- package/src/types.ts +0 -233
- package/src/web/auth.test.ts +0 -335
- package/src/web/auth.ts +0 -214
- package/src/web/discord-validate.test.ts +0 -77
- package/src/web/discord-validate.ts +0 -88
- package/src/web/hub-discovery.test.ts +0 -98
- package/src/web/hub-discovery.ts +0 -69
- package/src/web/routes/activity.ts +0 -106
- package/src/web/routes/agent-provider.test.ts +0 -282
- package/src/web/routes/agent-provider.ts +0 -309
- package/src/web/routes/approvals.ts +0 -185
- package/src/web/routes/apps.ts +0 -434
- package/src/web/routes/channels-mg-detail.test.ts +0 -324
- package/src/web/routes/channels-mga-detail.test.ts +0 -472
- package/src/web/routes/channels.ts +0 -311
- package/src/web/routes/oauth-providers.ts +0 -42
- package/src/web/routes/secrets.test.ts +0 -220
- package/src/web/routes/secrets.ts +0 -317
- package/src/web/routes/sessions.ts +0 -123
- package/src/web/routes/settings.test.ts +0 -106
- package/src/web/routes/settings.ts +0 -247
- package/src/web/routes/setup-status.ts +0 -205
- package/src/web/routes/vaults.test.ts +0 -389
- package/src/web/routes/vaults.ts +0 -225
- package/src/web/server-version.test.ts +0 -16
- package/src/web/server.ts +0 -1024
- package/src/web/services-manifest.test.ts +0 -148
- package/src/web/services-manifest.ts +0 -66
- package/src/web/static-serve.test.ts +0 -255
- package/src/web/static-serve.ts +0 -104
- package/src/web/telegram-validate.test.ts +0 -116
- package/src/web/telegram-validate.ts +0 -107
- package/src/web/vault-proxy.test.ts +0 -214
- package/src/web/vault-proxy.ts +0 -120
- package/src/web/wire-channel.ts +0 -181
- package/src/webhook-server.ts +0 -134
- package/vitest.config.ts +0 -18
- package/web/README.md +0 -63
- package/web/ui/index.html +0 -13
- package/web/ui/package.json +0 -35
- package/web/ui/pnpm-lock.yaml +0 -2164
- package/web/ui/scripts/verify-base.mjs +0 -31
- package/web/ui/src/App.tsx +0 -88
- package/web/ui/src/components/ActivityFeed.tsx +0 -444
- package/web/ui/src/components/AgentGroupPicker.tsx +0 -263
- package/web/ui/src/components/AgentProviderCards.tsx +0 -220
- package/web/ui/src/components/CredentialForm.tsx +0 -214
- package/web/ui/src/components/ScopeGrants.tsx +0 -74
- package/web/ui/src/components/StatusDot.tsx +0 -43
- package/web/ui/src/components/VaultPicker.tsx +0 -127
- package/web/ui/src/components/setup/AdapterInstallStep.tsx +0 -178
- package/web/ui/src/components/setup/AgentGroupStep.tsx +0 -43
- package/web/ui/src/components/setup/ChannelPickStep.tsx +0 -74
- package/web/ui/src/components/setup/DoneStep.tsx +0 -49
- package/web/ui/src/components/setup/PrereqStep.tsx +0 -129
- package/web/ui/src/components/setup/TestConnectionStep.tsx +0 -108
- package/web/ui/src/components/setup/TestMessageStep.tsx +0 -104
- package/web/ui/src/components/setup/WireChannelStep.tsx +0 -166
- package/web/ui/src/components/setup/types.ts +0 -105
- package/web/ui/src/lib/api.test.ts +0 -410
- package/web/ui/src/lib/api.ts +0 -1248
- package/web/ui/src/lib/auth.test.ts +0 -352
- package/web/ui/src/lib/auth.ts +0 -405
- package/web/ui/src/lib/channel-adapters.ts +0 -136
- package/web/ui/src/main.tsx +0 -19
- package/web/ui/src/routes/ApprovalsList.tsx +0 -294
- package/web/ui/src/routes/Apps.tsx +0 -613
- package/web/ui/src/routes/ChannelWireDetail.test.tsx +0 -233
- package/web/ui/src/routes/ChannelWireDetail.tsx +0 -403
- package/web/ui/src/routes/ChannelsList.tsx +0 -158
- package/web/ui/src/routes/GroupDetail.test.tsx +0 -206
- package/web/ui/src/routes/GroupDetail.tsx +0 -880
- package/web/ui/src/routes/GroupList.tsx +0 -187
- package/web/ui/src/routes/MessagingGroupDetail.test.tsx +0 -233
- package/web/ui/src/routes/MessagingGroupDetail.tsx +0 -306
- package/web/ui/src/routes/NewGroupWizard.tsx +0 -390
- package/web/ui/src/routes/OAuthCallback.tsx +0 -56
- package/web/ui/src/routes/SecretsList.tsx +0 -942
- package/web/ui/src/routes/SessionsList.tsx +0 -220
- package/web/ui/src/routes/SettingsAgentProvider.tsx +0 -109
- package/web/ui/src/routes/SettingsApprovals.tsx +0 -234
- package/web/ui/src/routes/SetupWizard.tsx +0 -219
- package/web/ui/src/routes/VaultDetail.test.tsx +0 -363
- package/web/ui/src/routes/VaultDetail.tsx +0 -960
- package/web/ui/src/routes/VaultsList.tsx +0 -295
- package/web/ui/src/routes/WireChannelPage.tsx +0 -413
- package/web/ui/src/styles.css +0 -608
- package/web/ui/src/test/setup.ts +0 -23
- package/web/ui/src/vite-env.d.ts +0 -10
- package/web/ui/vite.config.ts +0 -34
- package/web/ui/vitest.config.ts +0 -25
|
@@ -1,306 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Round-trip + validator coverage for the shared channel-wire translator
|
|
3
|
-
* (paraclaw#123). The HTTP and MCP surfaces both depend on this module to
|
|
4
|
-
* keep the wire ↔ DB enums in lockstep — paraclaw#94/#122 was the drift
|
|
5
|
-
* incident that motivated extracting these tests behind one file.
|
|
6
|
-
*/
|
|
7
|
-
import { describe, it, expect } from 'vitest';
|
|
8
|
-
|
|
9
|
-
import type { MessagingGroupAgent } from '../types.js';
|
|
10
|
-
import {
|
|
11
|
-
ALL_MESSAGES_PATTERN_SENTINEL,
|
|
12
|
-
apiToDbPatch,
|
|
13
|
-
dbToApiEngage,
|
|
14
|
-
dbToApiIgnoredPolicy,
|
|
15
|
-
dbToApiSenderScope,
|
|
16
|
-
rowToView,
|
|
17
|
-
validatePatchInput,
|
|
18
|
-
type WireJoinRow,
|
|
19
|
-
} from './api-translator.js';
|
|
20
|
-
|
|
21
|
-
function baseRow(overrides: Partial<WireJoinRow> = {}): WireJoinRow {
|
|
22
|
-
return {
|
|
23
|
-
id: 'mga-1',
|
|
24
|
-
messaging_group_id: 'mg-1',
|
|
25
|
-
agent_group_id: 'ag-1',
|
|
26
|
-
engage_mode: 'mention',
|
|
27
|
-
engage_pattern: null,
|
|
28
|
-
sender_scope: 'all',
|
|
29
|
-
ignored_message_policy: 'drop',
|
|
30
|
-
session_mode: 'shared',
|
|
31
|
-
priority: 0,
|
|
32
|
-
created_at: '2026-05-05T00:00:00Z',
|
|
33
|
-
mg_channel_type: 'discord',
|
|
34
|
-
mg_platform_id: 'guild-123',
|
|
35
|
-
mg_name: 'general',
|
|
36
|
-
ag_folder: 'research',
|
|
37
|
-
ag_name: 'Research',
|
|
38
|
-
...overrides,
|
|
39
|
-
};
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
function baseCurrent(overrides: Partial<MessagingGroupAgent> = {}): MessagingGroupAgent {
|
|
43
|
-
return {
|
|
44
|
-
id: 'mga-1',
|
|
45
|
-
messaging_group_id: 'mg-1',
|
|
46
|
-
agent_group_id: 'ag-1',
|
|
47
|
-
engage_mode: 'mention',
|
|
48
|
-
engage_pattern: null,
|
|
49
|
-
sender_scope: 'all',
|
|
50
|
-
ignored_message_policy: 'drop',
|
|
51
|
-
session_mode: 'shared',
|
|
52
|
-
priority: 0,
|
|
53
|
-
created_at: '2026-05-05T00:00:00Z',
|
|
54
|
-
...overrides,
|
|
55
|
-
};
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
describe('dbToApiEngage', () => {
|
|
59
|
-
it('mention + null → mention', () => {
|
|
60
|
-
expect(dbToApiEngage('mention', null)).toBe('mention');
|
|
61
|
-
});
|
|
62
|
-
|
|
63
|
-
it('mention-sticky collapses to mention on the wire', () => {
|
|
64
|
-
// The wire deliberately doesn't expose sticky — see api-translator.ts
|
|
65
|
-
// docblock. apiToDbPatch's mention-sticky preservation is what keeps
|
|
66
|
-
// sticky-mode rows from silently flattening on PATCHes that don't
|
|
67
|
-
// touch the engagement fields.
|
|
68
|
-
expect(dbToApiEngage('mention-sticky', null)).toBe('mention');
|
|
69
|
-
});
|
|
70
|
-
|
|
71
|
-
it("pattern + '.' sentinel → all", () => {
|
|
72
|
-
expect(dbToApiEngage('pattern', ALL_MESSAGES_PATTERN_SENTINEL)).toBe('all');
|
|
73
|
-
});
|
|
74
|
-
|
|
75
|
-
it('pattern + real regex body → pattern', () => {
|
|
76
|
-
expect(dbToApiEngage('pattern', '\\bdeploy\\b')).toBe('pattern');
|
|
77
|
-
});
|
|
78
|
-
|
|
79
|
-
it('pattern + null → pattern (defensive — schema disallows but translator must not crash)', () => {
|
|
80
|
-
expect(dbToApiEngage('pattern', null)).toBe('pattern');
|
|
81
|
-
});
|
|
82
|
-
});
|
|
83
|
-
|
|
84
|
-
describe('dbToApiSenderScope', () => {
|
|
85
|
-
it("DB 'known' → wire 'allowlist'", () => {
|
|
86
|
-
expect(dbToApiSenderScope('known')).toBe('allowlist');
|
|
87
|
-
});
|
|
88
|
-
|
|
89
|
-
it("DB 'all' → wire 'unrestricted' (paraclaw#94 — disjoint literals)", () => {
|
|
90
|
-
expect(dbToApiSenderScope('all')).toBe('unrestricted');
|
|
91
|
-
});
|
|
92
|
-
});
|
|
93
|
-
|
|
94
|
-
describe('dbToApiIgnoredPolicy', () => {
|
|
95
|
-
it("DB 'accumulate' → wire 'silent'", () => {
|
|
96
|
-
expect(dbToApiIgnoredPolicy('accumulate')).toBe('silent');
|
|
97
|
-
});
|
|
98
|
-
|
|
99
|
-
it("DB 'drop' → wire 'drop'", () => {
|
|
100
|
-
expect(dbToApiIgnoredPolicy('drop')).toBe('drop');
|
|
101
|
-
});
|
|
102
|
-
});
|
|
103
|
-
|
|
104
|
-
describe('rowToView', () => {
|
|
105
|
-
it('projects every join column onto the wire view', () => {
|
|
106
|
-
const view = rowToView(
|
|
107
|
-
baseRow({
|
|
108
|
-
engage_mode: 'pattern',
|
|
109
|
-
engage_pattern: '\\bping\\b',
|
|
110
|
-
sender_scope: 'known',
|
|
111
|
-
ignored_message_policy: 'accumulate',
|
|
112
|
-
priority: 5,
|
|
113
|
-
}),
|
|
114
|
-
);
|
|
115
|
-
expect(view).toEqual({
|
|
116
|
-
id: 'mga-1',
|
|
117
|
-
channelType: 'discord',
|
|
118
|
-
messagingGroupId: 'mg-1',
|
|
119
|
-
platformId: 'guild-123',
|
|
120
|
-
displayName: 'general',
|
|
121
|
-
agentGroupId: 'ag-1',
|
|
122
|
-
agentGroupFolder: 'research',
|
|
123
|
-
agentGroupName: 'Research',
|
|
124
|
-
engageMode: 'pattern',
|
|
125
|
-
engagePattern: '\\bping\\b',
|
|
126
|
-
senderScope: 'allowlist',
|
|
127
|
-
ignoredMessagePolicy: 'silent',
|
|
128
|
-
priority: 5,
|
|
129
|
-
createdAt: '2026-05-05T00:00:00Z',
|
|
130
|
-
});
|
|
131
|
-
});
|
|
132
|
-
|
|
133
|
-
it("collapses pattern + '.' to engageMode='all' and nulls engagePattern on the wire", () => {
|
|
134
|
-
const view = rowToView(baseRow({ engage_mode: 'pattern', engage_pattern: ALL_MESSAGES_PATTERN_SENTINEL }));
|
|
135
|
-
expect(view.engageMode).toBe('all');
|
|
136
|
-
expect(view.engagePattern).toBeNull();
|
|
137
|
-
});
|
|
138
|
-
|
|
139
|
-
it('mention mode never leaks the engage_pattern column to the wire', () => {
|
|
140
|
-
// In practice the schema keeps engage_pattern null for mention rows, but
|
|
141
|
-
// the projection must not surface stale pattern bodies if a row drifts.
|
|
142
|
-
const view = rowToView(baseRow({ engage_mode: 'mention', engage_pattern: 'leftover' }));
|
|
143
|
-
expect(view.engageMode).toBe('mention');
|
|
144
|
-
expect(view.engagePattern).toBeNull();
|
|
145
|
-
});
|
|
146
|
-
});
|
|
147
|
-
|
|
148
|
-
describe('apiToDbPatch — engageMode encoding', () => {
|
|
149
|
-
it("engageMode='all' → mode=pattern + pattern='.'", () => {
|
|
150
|
-
const out = apiToDbPatch({ engageMode: 'all' }, baseCurrent());
|
|
151
|
-
expect(out.engage_mode).toBe('pattern');
|
|
152
|
-
expect(out.engage_pattern).toBe(ALL_MESSAGES_PATTERN_SENTINEL);
|
|
153
|
-
});
|
|
154
|
-
|
|
155
|
-
it('engageMode=pattern + engagePattern → both written', () => {
|
|
156
|
-
const out = apiToDbPatch({ engageMode: 'pattern', engagePattern: '\\bdeploy\\b' }, baseCurrent());
|
|
157
|
-
expect(out.engage_mode).toBe('pattern');
|
|
158
|
-
expect(out.engage_pattern).toBe('\\bdeploy\\b');
|
|
159
|
-
});
|
|
160
|
-
|
|
161
|
-
it('engageMode=pattern without engagePattern → only mode set, pattern preserved on the row', () => {
|
|
162
|
-
// The PATCH-shape semantic: an undefined field means "leave it alone."
|
|
163
|
-
// The DB-side row already has the prior pattern; we don't overwrite it.
|
|
164
|
-
const out = apiToDbPatch({ engageMode: 'pattern' }, baseCurrent({ engage_pattern: 'old' }));
|
|
165
|
-
expect(out.engage_mode).toBe('pattern');
|
|
166
|
-
expect(out).not.toHaveProperty('engage_pattern');
|
|
167
|
-
});
|
|
168
|
-
|
|
169
|
-
it("engageMode='mention' nulls engage_pattern", () => {
|
|
170
|
-
const out = apiToDbPatch({ engageMode: 'mention' }, baseCurrent());
|
|
171
|
-
expect(out.engage_mode).toBe('mention');
|
|
172
|
-
expect(out.engage_pattern).toBeNull();
|
|
173
|
-
});
|
|
174
|
-
|
|
175
|
-
it("engageMode='mention' preserves mention-sticky when current row is sticky", () => {
|
|
176
|
-
// Wire doesn't expose sticky → both mention + mention-sticky show as
|
|
177
|
-
// 'mention' on the read side. A PATCH that flips back to 'mention' on
|
|
178
|
-
// the wire shouldn't silently demote the sticky bit on the row.
|
|
179
|
-
const out = apiToDbPatch({ engageMode: 'mention' }, baseCurrent({ engage_mode: 'mention-sticky' }));
|
|
180
|
-
expect(out.engage_mode).toBe('mention-sticky');
|
|
181
|
-
expect(out.engage_pattern).toBeNull();
|
|
182
|
-
});
|
|
183
|
-
|
|
184
|
-
it('engagePattern alone (no engageMode) → only pattern body changes', () => {
|
|
185
|
-
const out = apiToDbPatch({ engagePattern: '\\bnew\\b' }, baseCurrent({ engage_mode: 'pattern' }));
|
|
186
|
-
expect(out).not.toHaveProperty('engage_mode');
|
|
187
|
-
expect(out.engage_pattern).toBe('\\bnew\\b');
|
|
188
|
-
});
|
|
189
|
-
});
|
|
190
|
-
|
|
191
|
-
describe('apiToDbPatch — sender scope and ignored policy', () => {
|
|
192
|
-
it("senderScope 'allowlist' → DB 'known'", () => {
|
|
193
|
-
expect(apiToDbPatch({ senderScope: 'allowlist' }, baseCurrent()).sender_scope).toBe('known');
|
|
194
|
-
});
|
|
195
|
-
|
|
196
|
-
it("senderScope 'unrestricted' → DB 'all'", () => {
|
|
197
|
-
expect(apiToDbPatch({ senderScope: 'unrestricted' }, baseCurrent()).sender_scope).toBe('all');
|
|
198
|
-
});
|
|
199
|
-
|
|
200
|
-
it("ignoredMessagePolicy 'silent' → DB 'accumulate'", () => {
|
|
201
|
-
expect(apiToDbPatch({ ignoredMessagePolicy: 'silent' }, baseCurrent()).ignored_message_policy).toBe('accumulate');
|
|
202
|
-
});
|
|
203
|
-
|
|
204
|
-
it("ignoredMessagePolicy 'drop' → DB 'drop'", () => {
|
|
205
|
-
expect(apiToDbPatch({ ignoredMessagePolicy: 'drop' }, baseCurrent()).ignored_message_policy).toBe('drop');
|
|
206
|
-
});
|
|
207
|
-
|
|
208
|
-
it('priority passes through unchanged', () => {
|
|
209
|
-
expect(apiToDbPatch({ priority: 7 }, baseCurrent()).priority).toBe(7);
|
|
210
|
-
});
|
|
211
|
-
|
|
212
|
-
it('empty input → empty patch', () => {
|
|
213
|
-
expect(apiToDbPatch({}, baseCurrent())).toEqual({});
|
|
214
|
-
});
|
|
215
|
-
});
|
|
216
|
-
|
|
217
|
-
describe('validatePatchInput', () => {
|
|
218
|
-
it('rejects non-object body', () => {
|
|
219
|
-
expect(validatePatchInput(null)).toEqual({ ok: false, reason: 'body must be an object' });
|
|
220
|
-
expect(validatePatchInput('string')).toEqual({ ok: false, reason: 'body must be an object' });
|
|
221
|
-
expect(validatePatchInput(42)).toEqual({ ok: false, reason: 'body must be an object' });
|
|
222
|
-
});
|
|
223
|
-
|
|
224
|
-
it('passes a fully-populated valid body', () => {
|
|
225
|
-
const result = validatePatchInput({
|
|
226
|
-
engageMode: 'pattern',
|
|
227
|
-
engagePattern: '\\bping\\b',
|
|
228
|
-
senderScope: 'allowlist',
|
|
229
|
-
ignoredMessagePolicy: 'silent',
|
|
230
|
-
priority: 3,
|
|
231
|
-
});
|
|
232
|
-
expect(result).toEqual({
|
|
233
|
-
ok: true,
|
|
234
|
-
input: {
|
|
235
|
-
engageMode: 'pattern',
|
|
236
|
-
engagePattern: '\\bping\\b',
|
|
237
|
-
senderScope: 'allowlist',
|
|
238
|
-
ignoredMessagePolicy: 'silent',
|
|
239
|
-
priority: 3,
|
|
240
|
-
},
|
|
241
|
-
});
|
|
242
|
-
});
|
|
243
|
-
|
|
244
|
-
it("rejects legacy wire-side senderScope='all' (paraclaw#94 rename)", () => {
|
|
245
|
-
// Pre-paraclaw#94 the wire used 'all' on both axes; the rename to
|
|
246
|
-
// 'unrestricted' was specifically to make a grep-refactor unable to
|
|
247
|
-
// conflate the wire and DB unions. The validator must now reject the
|
|
248
|
-
// old literal.
|
|
249
|
-
const result = validatePatchInput({ senderScope: 'all' });
|
|
250
|
-
expect(result.ok).toBe(false);
|
|
251
|
-
if (!result.ok) expect(result.reason).toContain('senderScope');
|
|
252
|
-
});
|
|
253
|
-
|
|
254
|
-
it("rejects legacy ignoredMessagePolicy='accumulate' on the wire", () => {
|
|
255
|
-
// 'accumulate' is the DB-side spelling. The wire spelling is 'silent'.
|
|
256
|
-
const result = validatePatchInput({ ignoredMessagePolicy: 'accumulate' });
|
|
257
|
-
expect(result.ok).toBe(false);
|
|
258
|
-
if (!result.ok) expect(result.reason).toContain('ignoredMessagePolicy');
|
|
259
|
-
});
|
|
260
|
-
|
|
261
|
-
it("rejects engageMode='mention-sticky' (DB-only literal)", () => {
|
|
262
|
-
const result = validatePatchInput({ engageMode: 'mention-sticky' });
|
|
263
|
-
expect(result.ok).toBe(false);
|
|
264
|
-
if (!result.ok) expect(result.reason).toContain('engageMode');
|
|
265
|
-
});
|
|
266
|
-
|
|
267
|
-
it("rejects bare '.' as engagePattern (sentinel reservation)", () => {
|
|
268
|
-
// Storing '.' would silently round-trip back as engageMode='all' on the
|
|
269
|
-
// next read. The fix landed in paraclaw#122 — keep the regression here.
|
|
270
|
-
const result = validatePatchInput({ engagePattern: ALL_MESSAGES_PATTERN_SENTINEL });
|
|
271
|
-
expect(result.ok).toBe(false);
|
|
272
|
-
if (!result.ok) expect(result.reason).toMatch(/sentinel/);
|
|
273
|
-
});
|
|
274
|
-
|
|
275
|
-
it("accepts escaped literal-dot pattern '\\\\.'", () => {
|
|
276
|
-
// The error message above tells the caller to escape; that escaped
|
|
277
|
-
// form must round-trip cleanly.
|
|
278
|
-
const result = validatePatchInput({ engagePattern: '\\.' });
|
|
279
|
-
expect(result.ok).toBe(true);
|
|
280
|
-
if (result.ok) expect(result.input.engagePattern).toBe('\\.');
|
|
281
|
-
});
|
|
282
|
-
|
|
283
|
-
it('accepts engagePattern=null (clear-the-pattern PATCH)', () => {
|
|
284
|
-
const result = validatePatchInput({ engagePattern: null });
|
|
285
|
-
expect(result.ok).toBe(true);
|
|
286
|
-
if (result.ok) expect(result.input.engagePattern).toBeNull();
|
|
287
|
-
});
|
|
288
|
-
|
|
289
|
-
it('rejects non-string non-null engagePattern', () => {
|
|
290
|
-
expect(validatePatchInput({ engagePattern: 5 }).ok).toBe(false);
|
|
291
|
-
expect(validatePatchInput({ engagePattern: {} }).ok).toBe(false);
|
|
292
|
-
});
|
|
293
|
-
|
|
294
|
-
it('rejects non-finite priority', () => {
|
|
295
|
-
expect(validatePatchInput({ priority: Infinity }).ok).toBe(false);
|
|
296
|
-
expect(validatePatchInput({ priority: NaN }).ok).toBe(false);
|
|
297
|
-
expect(validatePatchInput({ priority: '5' }).ok).toBe(false);
|
|
298
|
-
});
|
|
299
|
-
|
|
300
|
-
it('drops unknown keys silently (forward-compat)', () => {
|
|
301
|
-
// The validator only inspects fields it knows; unknown keys aren't an
|
|
302
|
-
// error, they just don't make it into the typed output.
|
|
303
|
-
const result = validatePatchInput({ engageMode: 'mention', futureField: 'nope' });
|
|
304
|
-
expect(result).toEqual({ ok: true, input: { engageMode: 'mention' } });
|
|
305
|
-
});
|
|
306
|
-
});
|
|
@@ -1,214 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Shared translator between the storage shape (`messaging_group_agents` row,
|
|
3
|
-
* snake_case + legacy enum names) and the API contract that both `/api/channels`
|
|
4
|
-
* and the MCP `*-channel-wire` tools speak.
|
|
5
|
-
*
|
|
6
|
-
* Background. Both surfaces used to maintain their own copy of these types,
|
|
7
|
-
* constants, translators, and the patch validator. The duplication was a
|
|
8
|
-
* structural drift hazard: paraclaw#94 / PR #122 surfaced exactly that class
|
|
9
|
-
* — the rename of wire-side `'all'` → `'unrestricted'` initially landed only
|
|
10
|
-
* the HTTP-side validator and missed the MCP-side silent-no-op. Extracting
|
|
11
|
-
* here makes the drift class structurally impossible: a future enum change
|
|
12
|
-
* touches one file, both surfaces pick it up. paraclaw#123.
|
|
13
|
-
*
|
|
14
|
-
* API contract: engageMode = mention | pattern | all, senderScope = allowlist
|
|
15
|
-
* | unrestricted, ignoredMessagePolicy = drop | silent.
|
|
16
|
-
*
|
|
17
|
-
* DB shape (still pre-rebuild): engage_mode = mention | pattern |
|
|
18
|
-
* mention-sticky (with engage_pattern='.' as the "match every message"
|
|
19
|
-
* sentinel), sender_scope = all | known, ignored_message_policy = drop |
|
|
20
|
-
* accumulate. The translator collapses pattern + '.' into the API's `all`,
|
|
21
|
-
* lossy on mention-sticky (rendered as `mention` to the wire).
|
|
22
|
-
*
|
|
23
|
-
* The validator returns a discriminated result rather than throwing so each
|
|
24
|
-
* caller can pick its own error idiom: HTTP wraps `{ ok: false }` into a
|
|
25
|
-
* 400 + JSON error; MCP throws on `{ ok: false }`.
|
|
26
|
-
*/
|
|
27
|
-
import type {
|
|
28
|
-
EngageMode as DbEngageMode,
|
|
29
|
-
IgnoredMessagePolicy as DbIgnoredMessagePolicy,
|
|
30
|
-
MessagingGroupAgent,
|
|
31
|
-
SenderScope as DbSenderScope,
|
|
32
|
-
} from '../types.js';
|
|
33
|
-
|
|
34
|
-
export type ApiEngageMode = 'mention' | 'pattern' | 'all';
|
|
35
|
-
export type ApiSenderScope = 'allowlist' | 'unrestricted';
|
|
36
|
-
export type ApiIgnoredMessagePolicy = 'drop' | 'silent';
|
|
37
|
-
|
|
38
|
-
export const ALL_MESSAGES_PATTERN_SENTINEL = '.';
|
|
39
|
-
|
|
40
|
-
export const VALID_API_ENGAGE_MODES: ApiEngageMode[] = ['mention', 'pattern', 'all'];
|
|
41
|
-
export const VALID_API_SENDER_SCOPES: ApiSenderScope[] = ['allowlist', 'unrestricted'];
|
|
42
|
-
export const VALID_API_IGNORED_POLICIES: ApiIgnoredMessagePolicy[] = ['drop', 'silent'];
|
|
43
|
-
|
|
44
|
-
export interface ChannelWireView {
|
|
45
|
-
id: string;
|
|
46
|
-
channelType: string;
|
|
47
|
-
messagingGroupId: string;
|
|
48
|
-
platformId: string;
|
|
49
|
-
displayName: string | null;
|
|
50
|
-
agentGroupId: string;
|
|
51
|
-
agentGroupFolder: string;
|
|
52
|
-
agentGroupName: string;
|
|
53
|
-
engageMode: ApiEngageMode;
|
|
54
|
-
engagePattern: string | null;
|
|
55
|
-
senderScope: ApiSenderScope;
|
|
56
|
-
ignoredMessagePolicy: ApiIgnoredMessagePolicy;
|
|
57
|
-
priority: number;
|
|
58
|
-
createdAt: string;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
export interface WireJoinRow extends MessagingGroupAgent {
|
|
62
|
-
mg_channel_type: string;
|
|
63
|
-
mg_platform_id: string;
|
|
64
|
-
mg_name: string | null;
|
|
65
|
-
ag_folder: string;
|
|
66
|
-
ag_name: string;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
export interface PatchInput {
|
|
70
|
-
engageMode?: ApiEngageMode;
|
|
71
|
-
engagePattern?: string | null;
|
|
72
|
-
senderScope?: ApiSenderScope;
|
|
73
|
-
ignoredMessagePolicy?: ApiIgnoredMessagePolicy;
|
|
74
|
-
priority?: number;
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
export interface DbPatch {
|
|
78
|
-
engage_mode?: DbEngageMode;
|
|
79
|
-
engage_pattern?: string | null;
|
|
80
|
-
sender_scope?: DbSenderScope;
|
|
81
|
-
ignored_message_policy?: DbIgnoredMessagePolicy;
|
|
82
|
-
priority?: number;
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
export function dbToApiEngage(mode: DbEngageMode, pattern: string | null): ApiEngageMode {
|
|
86
|
-
if (mode === 'pattern') {
|
|
87
|
-
return pattern === ALL_MESSAGES_PATTERN_SENTINEL ? 'all' : 'pattern';
|
|
88
|
-
}
|
|
89
|
-
// mention + mention-sticky both render as 'mention' on the wire today.
|
|
90
|
-
return 'mention';
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
export function dbToApiSenderScope(s: DbSenderScope): ApiSenderScope {
|
|
94
|
-
return s === 'known' ? 'allowlist' : 'unrestricted';
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
export function dbToApiIgnoredPolicy(p: DbIgnoredMessagePolicy): ApiIgnoredMessagePolicy {
|
|
98
|
-
return p === 'accumulate' ? 'silent' : 'drop';
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
export function rowToView(row: WireJoinRow): ChannelWireView {
|
|
102
|
-
return {
|
|
103
|
-
id: row.id,
|
|
104
|
-
channelType: row.mg_channel_type,
|
|
105
|
-
messagingGroupId: row.messaging_group_id,
|
|
106
|
-
platformId: row.mg_platform_id,
|
|
107
|
-
displayName: row.mg_name,
|
|
108
|
-
agentGroupId: row.agent_group_id,
|
|
109
|
-
agentGroupFolder: row.ag_folder,
|
|
110
|
-
agentGroupName: row.ag_name,
|
|
111
|
-
engageMode: dbToApiEngage(row.engage_mode, row.engage_pattern),
|
|
112
|
-
engagePattern:
|
|
113
|
-
row.engage_mode === 'pattern' && row.engage_pattern !== ALL_MESSAGES_PATTERN_SENTINEL ? row.engage_pattern : null,
|
|
114
|
-
senderScope: dbToApiSenderScope(row.sender_scope),
|
|
115
|
-
ignoredMessagePolicy: dbToApiIgnoredPolicy(row.ignored_message_policy),
|
|
116
|
-
priority: row.priority,
|
|
117
|
-
createdAt: row.created_at,
|
|
118
|
-
};
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
export function apiToDbPatch(input: PatchInput, current: MessagingGroupAgent): DbPatch {
|
|
122
|
-
const out: DbPatch = {};
|
|
123
|
-
|
|
124
|
-
// engageMode is paired with engagePattern: 'all' encodes as
|
|
125
|
-
// mode='pattern' + pattern='.', which the router treats as match-every.
|
|
126
|
-
if (input.engageMode !== undefined) {
|
|
127
|
-
if (input.engageMode === 'all') {
|
|
128
|
-
out.engage_mode = 'pattern';
|
|
129
|
-
out.engage_pattern = ALL_MESSAGES_PATTERN_SENTINEL;
|
|
130
|
-
} else if (input.engageMode === 'pattern') {
|
|
131
|
-
out.engage_mode = 'pattern';
|
|
132
|
-
// Pattern body comes from input.engagePattern when present; otherwise
|
|
133
|
-
// preserve what's already on the row. validatePatchInput already
|
|
134
|
-
// rejects bare '.' here so the next read can't silently collapse to
|
|
135
|
-
// 'all'.
|
|
136
|
-
if (input.engagePattern !== undefined) {
|
|
137
|
-
out.engage_pattern = input.engagePattern;
|
|
138
|
-
}
|
|
139
|
-
} else if (input.engageMode === 'mention') {
|
|
140
|
-
// Preserve mention-sticky if that's what's currently on the row;
|
|
141
|
-
// collapsing it to plain mention here would silently change router
|
|
142
|
-
// behavior (sticky engagement persists across replies). The wire
|
|
143
|
-
// doesn't expose sticky → it sees `mention` for both, but a PATCH
|
|
144
|
-
// that doesn't touch the sticky distinction shouldn't lose it.
|
|
145
|
-
out.engage_mode = current.engage_mode === 'mention-sticky' ? 'mention-sticky' : 'mention';
|
|
146
|
-
out.engage_pattern = null;
|
|
147
|
-
}
|
|
148
|
-
} else if (input.engagePattern !== undefined) {
|
|
149
|
-
// pattern body changed without changing the mode.
|
|
150
|
-
out.engage_pattern = input.engagePattern;
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
if (input.senderScope !== undefined) {
|
|
154
|
-
// wire 'unrestricted' → DB 'all'. validatePatchInput has already gated
|
|
155
|
-
// the union to the two known values, so the binary mapping is safe.
|
|
156
|
-
out.sender_scope = input.senderScope === 'allowlist' ? 'known' : 'all';
|
|
157
|
-
}
|
|
158
|
-
if (input.ignoredMessagePolicy !== undefined) {
|
|
159
|
-
out.ignored_message_policy = input.ignoredMessagePolicy === 'silent' ? 'accumulate' : 'drop';
|
|
160
|
-
}
|
|
161
|
-
if (input.priority !== undefined) {
|
|
162
|
-
out.priority = input.priority;
|
|
163
|
-
}
|
|
164
|
-
return out;
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
export type ValidatePatchResult = { ok: true; input: PatchInput } | { ok: false; reason: string };
|
|
168
|
-
|
|
169
|
-
export function validatePatchInput(body: unknown): ValidatePatchResult {
|
|
170
|
-
if (!body || typeof body !== 'object') return { ok: false, reason: 'body must be an object' };
|
|
171
|
-
const b = body as Record<string, unknown>;
|
|
172
|
-
const out: PatchInput = {};
|
|
173
|
-
if ('engageMode' in b) {
|
|
174
|
-
if (!VALID_API_ENGAGE_MODES.includes(b.engageMode as ApiEngageMode)) {
|
|
175
|
-
return { ok: false, reason: `invalid engageMode: ${String(b.engageMode)}` };
|
|
176
|
-
}
|
|
177
|
-
out.engageMode = b.engageMode as ApiEngageMode;
|
|
178
|
-
}
|
|
179
|
-
if ('engagePattern' in b) {
|
|
180
|
-
if (b.engagePattern !== null && typeof b.engagePattern !== 'string') {
|
|
181
|
-
return { ok: false, reason: 'engagePattern must be string or null' };
|
|
182
|
-
}
|
|
183
|
-
// Bare '.' is the wire-format sentinel for engageMode='all' — accepting
|
|
184
|
-
// it as a literal pattern would silently round-trip back as 'all' on the
|
|
185
|
-
// next read and lose the user's intent. Force the caller to disambiguate.
|
|
186
|
-
if (b.engagePattern === ALL_MESSAGES_PATTERN_SENTINEL) {
|
|
187
|
-
return {
|
|
188
|
-
ok: false,
|
|
189
|
-
reason:
|
|
190
|
-
"engagePattern '.' is reserved as the 'all' sentinel — use '\\\\.' (escaped) to match a literal dot, or set engageMode to 'all'",
|
|
191
|
-
};
|
|
192
|
-
}
|
|
193
|
-
out.engagePattern = b.engagePattern as string | null;
|
|
194
|
-
}
|
|
195
|
-
if ('senderScope' in b) {
|
|
196
|
-
if (!VALID_API_SENDER_SCOPES.includes(b.senderScope as ApiSenderScope)) {
|
|
197
|
-
return { ok: false, reason: `invalid senderScope: ${String(b.senderScope)}` };
|
|
198
|
-
}
|
|
199
|
-
out.senderScope = b.senderScope as ApiSenderScope;
|
|
200
|
-
}
|
|
201
|
-
if ('ignoredMessagePolicy' in b) {
|
|
202
|
-
if (!VALID_API_IGNORED_POLICIES.includes(b.ignoredMessagePolicy as ApiIgnoredMessagePolicy)) {
|
|
203
|
-
return { ok: false, reason: `invalid ignoredMessagePolicy: ${String(b.ignoredMessagePolicy)}` };
|
|
204
|
-
}
|
|
205
|
-
out.ignoredMessagePolicy = b.ignoredMessagePolicy as ApiIgnoredMessagePolicy;
|
|
206
|
-
}
|
|
207
|
-
if ('priority' in b) {
|
|
208
|
-
if (typeof b.priority !== 'number' || !Number.isFinite(b.priority)) {
|
|
209
|
-
return { ok: false, reason: 'priority must be a finite number' };
|
|
210
|
-
}
|
|
211
|
-
out.priority = b.priority;
|
|
212
|
-
}
|
|
213
|
-
return { ok: true, input: out };
|
|
214
|
-
}
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Shared ask_question payload schema + normalization.
|
|
3
|
-
*
|
|
4
|
-
* Producers (host-side approvals, container-side ask_user_question MCP tool)
|
|
5
|
-
* emit an `ask_question` payload. Options may be bare strings for ergonomics,
|
|
6
|
-
* but are normalized here into a consistent shape before delivery, persistence,
|
|
7
|
-
* and rendering.
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
export interface OptionInput {
|
|
11
|
-
label: string;
|
|
12
|
-
selectedLabel?: string;
|
|
13
|
-
value?: string;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
export type RawOption = string | OptionInput;
|
|
17
|
-
|
|
18
|
-
export interface NormalizedOption {
|
|
19
|
-
label: string;
|
|
20
|
-
selectedLabel: string;
|
|
21
|
-
value: string;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
export function normalizeOption(raw: RawOption): NormalizedOption {
|
|
25
|
-
if (typeof raw === 'string') {
|
|
26
|
-
return { label: raw, selectedLabel: raw, value: raw };
|
|
27
|
-
}
|
|
28
|
-
const label = raw.label;
|
|
29
|
-
return {
|
|
30
|
-
label,
|
|
31
|
-
selectedLabel: raw.selectedLabel ?? label,
|
|
32
|
-
value: raw.value ?? label,
|
|
33
|
-
};
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
export function normalizeOptions(raws: RawOption[]): NormalizedOption[] {
|
|
37
|
-
return raws.map(normalizeOption);
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
export interface AskQuestionPayload {
|
|
41
|
-
type: 'ask_question';
|
|
42
|
-
questionId: string;
|
|
43
|
-
title: string;
|
|
44
|
-
question: string;
|
|
45
|
-
options: NormalizedOption[];
|
|
46
|
-
}
|