switchroom 0.7.15 → 0.10.0
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/README.md +51 -59
- package/bin/run-hook.sh +27 -11
- package/bin/timezone-hook.sh +9 -7
- package/dist/agent-scheduler/index.js +410 -133
- package/dist/auth-broker/index.js +13932 -0
- package/dist/cli/switchroom.js +26937 -5601
- package/dist/host-control/main.js +12702 -0
- package/dist/vault/approvals/kernel-server.js +467 -184
- package/dist/vault/broker/server.js +1430 -724
- package/examples/minimal.yaml +63 -0
- package/examples/personal-google-workspace-mcp/.env.example +34 -0
- package/examples/personal-google-workspace-mcp/README.md +194 -0
- package/examples/personal-google-workspace-mcp/compose.yaml +66 -0
- package/examples/switchroom.yaml +220 -0
- package/package.json +7 -4
- package/profiles/_base/settings.json.hbs +20 -5
- package/profiles/_base/start.sh.hbs +16 -3
- package/profiles/_shared/agent-self-service.md.hbs +126 -0
- package/profiles/_shared/telegram-style.md.hbs +20 -90
- package/profiles/_shared/vault-protocol.md.hbs +68 -0
- package/profiles/default/CLAUDE.md +50 -96
- package/profiles/default/CLAUDE.md.hbs +36 -6
- package/profiles/default/workspace/SOUL.md.hbs +12 -5
- package/skills/buildkite-agent-infrastructure/SKILL.md +30 -11
- package/skills/buildkite-agent-runtime/SKILL.md +44 -11
- package/skills/buildkite-api/SKILL.md +31 -8
- package/skills/buildkite-cli/SKILL.md +27 -9
- package/skills/buildkite-migration/SKILL.md +22 -9
- package/skills/buildkite-pipelines/SKILL.md +26 -9
- package/skills/buildkite-secure-delivery/SKILL.md +23 -9
- package/skills/buildkite-test-engine/SKILL.md +25 -8
- package/skills/docx/SKILL.md +1 -1
- package/skills/docx/scripts/office/validators/__pycache__/__init__.cpython-313.pyc +0 -0
- package/skills/docx/scripts/office/validators/__pycache__/base.cpython-313.pyc +0 -0
- package/skills/file-bug/SKILL.md +34 -6
- package/skills/humanizer/SKILL.md +15 -0
- package/skills/humanizer-calibrate/SKILL.md +7 -1
- package/skills/mcp-builder/SKILL.md +1 -1
- package/skills/pdf/SKILL.md +1 -1
- package/skills/pptx/SKILL.md +1 -1
- package/skills/skill-creator/SKILL.md +21 -1
- package/skills/skill-creator/scripts/__pycache__/__init__.cpython-313.pyc +0 -0
- package/skills/skill-creator/scripts/__pycache__/generate_report.cpython-313.pyc +0 -0
- package/skills/skill-creator/scripts/__pycache__/improve_description.cpython-313.pyc +0 -0
- package/skills/skill-creator/scripts/__pycache__/run_eval.cpython-313.pyc +0 -0
- package/skills/skill-creator/scripts/__pycache__/run_loop.cpython-313.pyc +0 -0
- package/skills/skill-creator/scripts/__pycache__/utils.cpython-313.pyc +0 -0
- package/skills/switchroom-cli/SKILL.md +63 -64
- package/skills/switchroom-health/SKILL.md +23 -10
- package/skills/switchroom-install/SKILL.md +3 -3
- package/skills/switchroom-manage/SKILL.md +26 -19
- package/skills/switchroom-runtime/SKILL.md +191 -0
- package/skills/switchroom-status/SKILL.md +27 -2
- package/skills/telegram-test-harness/SKILL.md +3 -0
- package/skills/token-helpers/SKILL.md +24 -1
- package/skills/webapp-testing/SKILL.md +31 -1
- package/skills/xlsx/SKILL.md +1 -1
- package/telegram-plugin/admin-commands/index.ts +7 -5
- package/telegram-plugin/analytics-posthog.ts +191 -0
- package/telegram-plugin/bridge/bridge.ts +69 -0
- package/telegram-plugin/bridge/ipc-client.ts +4 -1
- package/telegram-plugin/dist/bridge/bridge.js +194 -119
- package/telegram-plugin/dist/gateway/gateway.js +23611 -19671
- package/telegram-plugin/dist/server.js +245 -189
- package/telegram-plugin/first-paint.ts +3 -24
- package/telegram-plugin/gateway/auth-add-flow.ts +326 -0
- package/telegram-plugin/gateway/auth-broker-client.ts +75 -0
- package/telegram-plugin/gateway/auth-command.ts +794 -0
- package/telegram-plugin/gateway/auth-line.ts +123 -0
- package/telegram-plugin/gateway/boot-card.ts +169 -40
- package/telegram-plugin/gateway/boot-issue-cache.ts +308 -0
- package/telegram-plugin/gateway/boot-probes.ts +166 -123
- package/telegram-plugin/gateway/boot-reason.ts +41 -7
- package/telegram-plugin/gateway/boot-version.ts +66 -0
- package/telegram-plugin/gateway/gateway.ts +3499 -1885
- package/telegram-plugin/gateway/hostd-dispatch.ts +117 -0
- package/telegram-plugin/gateway/ipc-protocol.ts +18 -0
- package/telegram-plugin/gateway/pending-inbound-buffer.ts +106 -0
- package/telegram-plugin/gateway/quarantine.ts +69 -0
- package/telegram-plugin/gateway/quota-cache.ts +9 -4
- package/telegram-plugin/gateway/reaction-trigger.ts +401 -0
- package/telegram-plugin/gateway/recent-denials.test.ts +103 -0
- package/telegram-plugin/gateway/recent-denials.ts +77 -0
- package/telegram-plugin/gateway/startup-network-retry.ts +109 -31
- package/telegram-plugin/gateway/vault-grant-inbound-builders.ts +125 -0
- package/telegram-plugin/history.ts +91 -0
- package/telegram-plugin/hooks/hooks.json +10 -0
- package/telegram-plugin/hooks/sandbox-hint-posttool.mjs +130 -0
- package/telegram-plugin/hooks/subagent-tracker-posttool.mjs +19 -2
- package/telegram-plugin/hooks/subagent-tracker-pretool.mjs +22 -2
- package/telegram-plugin/hooks/tool-label-pretool.mjs +11 -0
- package/telegram-plugin/hooks/wedge-detect-posttool.mjs +303 -0
- package/telegram-plugin/inbound-classifier.ts +50 -0
- package/telegram-plugin/inline-keyboard-callbacks.ts +136 -0
- package/telegram-plugin/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +1 -0
- package/telegram-plugin/package.json +4 -2
- package/telegram-plugin/permission-rule.ts +51 -0
- package/telegram-plugin/permission-title.ts +56 -0
- package/telegram-plugin/quota-check.ts +19 -41
- package/telegram-plugin/registry/reaper.ts +223 -0
- package/telegram-plugin/retry-api-call.ts +80 -0
- package/telegram-plugin/runtime-metrics.ts +177 -0
- package/telegram-plugin/scripts/build.mjs +0 -1
- package/telegram-plugin/secret-detect/index.ts +24 -0
- package/telegram-plugin/secret-detect/vault-error.test.ts +64 -12
- package/telegram-plugin/secret-detect/vault-error.ts +78 -11
- package/telegram-plugin/secret-detect/vault-write.ts +14 -2
- package/telegram-plugin/server.js +41795 -0
- package/telegram-plugin/session-tail.ts +6 -1
- package/telegram-plugin/shared/bot-runtime.ts +5 -4
- package/telegram-plugin/silence-poke.ts +420 -0
- package/telegram-plugin/silent-end.ts +174 -0
- package/telegram-plugin/stream-controller.ts +13 -0
- package/telegram-plugin/stream-reply-handler.ts +7 -0
- package/telegram-plugin/subagent-watcher.ts +213 -4
- package/telegram-plugin/tests/auth-add-flow.test.ts +559 -0
- package/telegram-plugin/tests/auth-code-redact.test.ts +8 -4
- package/telegram-plugin/tests/auth-command-vernacular.test.ts +531 -0
- package/telegram-plugin/tests/boot-card-issue-dedup.test.ts +247 -0
- package/telegram-plugin/tests/boot-card-reason-to-render.test.ts +182 -0
- package/telegram-plugin/tests/boot-card-reason.test.ts +65 -2
- package/telegram-plugin/tests/boot-card-render.test.ts +146 -0
- package/telegram-plugin/tests/boot-card-silent-on-operator.test.ts +103 -0
- package/telegram-plugin/tests/boot-probes.test.ts +216 -10
- package/telegram-plugin/tests/boot-version-string.test.ts +0 -0
- package/telegram-plugin/tests/finalize-callback.test.ts +190 -0
- package/telegram-plugin/tests/gateway-message-validator.test.ts +26 -0
- package/telegram-plugin/tests/gateway-secret-detect.test.ts +12 -3
- package/telegram-plugin/tests/gateway-startup-network-retry.test.ts +104 -0
- package/telegram-plugin/tests/history-reaper.test.ts +378 -0
- package/telegram-plugin/tests/hostd-dispatch.test.ts +129 -0
- package/telegram-plugin/tests/inbound-classifier.test.ts +76 -0
- package/telegram-plugin/tests/inbound-message-types.test.ts +267 -0
- package/telegram-plugin/tests/issues-card.test.ts +49 -0
- package/telegram-plugin/tests/pending-inbound-buffer.test.ts +132 -0
- package/telegram-plugin/tests/permission-rule.test.ts +80 -1
- package/telegram-plugin/tests/permission-title.test.ts +31 -0
- package/telegram-plugin/tests/quota-check.test.ts +5 -35
- package/telegram-plugin/tests/races.test.ts +179 -0
- package/telegram-plugin/tests/reaction-trigger-flow.test.ts +353 -0
- package/telegram-plugin/tests/reaction-trigger.test.ts +397 -0
- package/telegram-plugin/tests/retry-api-call.test.ts +152 -1
- package/telegram-plugin/tests/runtime-metrics.test.ts +145 -0
- package/telegram-plugin/tests/sandbox-hint-posttool.test.ts +155 -0
- package/telegram-plugin/tests/secret-detect-delete-must-surface-failures.test.ts +133 -0
- package/telegram-plugin/tests/secret-detect-false-positives.test.ts +137 -0
- package/telegram-plugin/tests/silence-poke.test.ts +493 -0
- package/telegram-plugin/tests/silent-end.test.ts +206 -0
- package/telegram-plugin/tests/subagent-tracker-hooks.test.ts +107 -0
- package/telegram-plugin/tests/subagent-watcher-env-thresholds.test.ts +224 -0
- package/telegram-plugin/tests/subagent-watcher-stall-terminal.test.ts +316 -0
- package/telegram-plugin/tests/subagent-watcher.test.ts +263 -0
- package/telegram-plugin/tests/turn-signal-tracker.test.ts +81 -0
- package/telegram-plugin/tests/vault-approval-posture.test.ts +256 -0
- package/telegram-plugin/tests/vault-grant-auto-resume.test.ts +73 -0
- package/telegram-plugin/tests/vault-grant-inbound-builders.test.ts +226 -0
- package/telegram-plugin/tests/vault-grant-union.test.ts +130 -0
- package/telegram-plugin/tests/vault-key-regex-allows-slash.test.ts +140 -0
- package/telegram-plugin/tests/vault-posture-quarantine.test.ts +104 -0
- package/telegram-plugin/tests/vault-request-access-tool.test.ts +114 -0
- package/telegram-plugin/tests/vault-request-access-unlock-resume.test.ts +106 -0
- package/telegram-plugin/turn-signal-tracker.ts +100 -24
- package/telegram-plugin/uat/SETUP.md +210 -35
- package/telegram-plugin/uat/assertions.ts +264 -37
- package/telegram-plugin/uat/driver-info.ts +57 -0
- package/telegram-plugin/uat/driver.ts +590 -51
- package/telegram-plugin/uat/harness.ts +140 -94
- package/telegram-plugin/uat/load-env.test.ts +72 -0
- package/telegram-plugin/uat/load-env.ts +48 -0
- package/telegram-plugin/uat/login.ts +96 -53
- package/telegram-plugin/uat/runners/agent-self-sufficiency.ts +457 -0
- package/telegram-plugin/uat/runners/paraphrases.ts +231 -0
- package/telegram-plugin/uat/runners/report.ts +150 -0
- package/telegram-plugin/uat/runners/run-agent-self-sufficiency.sh +50 -0
- package/telegram-plugin/uat/runners/scorer.test.ts +196 -0
- package/telegram-plugin/uat/runners/scorer.ts +106 -0
- package/telegram-plugin/uat/runners/skill-coverage.test.ts +100 -0
- package/telegram-plugin/uat/runners/skill-coverage.ts +620 -0
- package/telegram-plugin/uat/scenarios/ask-user-button-tap-dm.test.ts +141 -0
- package/telegram-plugin/uat/scenarios/bg-sub-agent-dispatch-dm.test.ts +191 -0
- package/telegram-plugin/uat/scenarios/fuzz-extended-dm.test.ts +255 -0
- package/telegram-plugin/uat/scenarios/fuzz-human-style-dm.test.ts +275 -0
- package/telegram-plugin/uat/scenarios/fuzz-random-prompts-dm.test.ts +146 -0
- package/telegram-plugin/uat/scenarios/fuzz-status-ask-dm.test.ts +486 -0
- package/telegram-plugin/uat/scenarios/jtbd-interrupt-marker-dm.test.ts +67 -0
- package/telegram-plugin/uat/scenarios/jtbd-rapid-followup-dm.test.ts +100 -0
- package/telegram-plugin/uat/scenarios/jtbd-soft-commit-dm.test.ts +67 -0
- package/telegram-plugin/uat/scenarios/jtbd-status-query-dm.test.ts +49 -0
- package/telegram-plugin/uat/scenarios/location-inbound-dm.test.ts +65 -0
- package/telegram-plugin/uat/scenarios/midturn-silent-dm.test.ts +175 -0
- package/telegram-plugin/uat/scenarios/reactions-dm.test.ts +142 -0
- package/telegram-plugin/uat/scenarios/reactions-trigger-turn-dm.test.ts +96 -0
- package/telegram-plugin/uat/scenarios/secret-redaction-deletes-original-dm.test.ts +123 -0
- package/telegram-plugin/uat/scenarios/secret-redaction-no-false-positive-dm.test.ts +87 -0
- package/telegram-plugin/uat/scenarios/silence-poke-soft-dm.test.ts +155 -0
- package/telegram-plugin/uat/scenarios/silent-end-recovery-dm.test.ts +95 -0
- package/telegram-plugin/uat/scenarios/smoke-dm-reply.test.ts +57 -0
- package/telegram-plugin/uat/scenarios/subagent-watcher-no-rerun-dm.test.ts +135 -0
- package/telegram-plugin/uat/scenarios/vault-approval-posture-telegram-id-dm.test.ts +191 -0
- package/telegram-plugin/uat/scenarios/vault-audit-allow-dm.test.ts +108 -0
- package/telegram-plugin/uat/scenarios/vault-grant-auto-resume-dm.test.ts +121 -0
- package/telegram-plugin/uat/scenarios/vault-request-access-concurrent-dm.test.ts +161 -0
- package/telegram-plugin/uat/scenarios/vault-request-access-end-to-end-dm.test.ts +158 -0
- package/telegram-plugin/uat/scenarios/voice-inbound-dm.test.ts +65 -0
- package/telegram-plugin/vault-approval-posture.ts +42 -0
- package/telegram-plugin/welcome-text.ts +1 -0
- package/telegram-plugin/active-pins-sweep.ts +0 -204
- package/telegram-plugin/active-pins.ts +0 -146
- package/telegram-plugin/auth-dashboard.ts +0 -1104
- package/telegram-plugin/auth-slot-parser.ts +0 -497
- package/telegram-plugin/card-event-log.ts +0 -138
- package/telegram-plugin/dist/foreman/foreman.js +0 -31106
- package/telegram-plugin/docs/multi-agent-card-design.md +0 -847
- package/telegram-plugin/docs/pinned-progress-card-reliability.md +0 -144
- package/telegram-plugin/foreman/foreman-create-flow.ts +0 -202
- package/telegram-plugin/foreman/foreman-handlers.ts +0 -493
- package/telegram-plugin/foreman/foreman.ts +0 -1165
- package/telegram-plugin/foreman/setup-flow.ts +0 -345
- package/telegram-plugin/foreman/setup-state.ts +0 -239
- package/telegram-plugin/foreman/state.ts +0 -203
- package/telegram-plugin/pin-event-log.ts +0 -76
- package/telegram-plugin/progress-card-driver.ts +0 -2886
- package/telegram-plugin/progress-card-pin-manager.ts +0 -589
- package/telegram-plugin/progress-card-pin-watchdog.ts +0 -98
- package/telegram-plugin/progress-card.ts +0 -1409
- package/telegram-plugin/tests/HARNESS.md +0 -340
- package/telegram-plugin/tests/_progress-card-harness.ts +0 -109
- package/telegram-plugin/tests/active-pins-boot-reaper.test.ts +0 -211
- package/telegram-plugin/tests/active-pins-sweep.test.ts +0 -309
- package/telegram-plugin/tests/active-pins.test.ts +0 -187
- package/telegram-plugin/tests/auth-account-identity-surface.test.ts +0 -118
- package/telegram-plugin/tests/auth-dashboard-edge-cases.test.ts +0 -260
- package/telegram-plugin/tests/auth-dashboard-restart-flow.test.ts +0 -140
- package/telegram-plugin/tests/auth-dashboard-v3b.test.ts +0 -559
- package/telegram-plugin/tests/auth-dashboard.test.ts +0 -1045
- package/telegram-plugin/tests/auth-slot-commands.test.ts +0 -640
- package/telegram-plugin/tests/bg-agent-progress-card-757.test.ts +0 -201
- package/telegram-plugin/tests/boot-card-account-quota.test.ts +0 -137
- package/telegram-plugin/tests/card-event-log.test.ts +0 -145
- package/telegram-plugin/tests/first-paint.test.ts +0 -257
- package/telegram-plugin/tests/foreman-create-flow.test.ts +0 -359
- package/telegram-plugin/tests/foreman-handlers.test.ts +0 -347
- package/telegram-plugin/tests/foreman-state.test.ts +0 -164
- package/telegram-plugin/tests/foreman-write-ops.test.ts +0 -214
- package/telegram-plugin/tests/harness-ordering-invariants.test.ts +0 -243
- package/telegram-plugin/tests/pin-event-log.test.ts +0 -124
- package/telegram-plugin/tests/progress-card-api-failure-during-deferred.test.ts +0 -73
- package/telegram-plugin/tests/progress-card-close-paths-converge.test.ts +0 -272
- package/telegram-plugin/tests/progress-card-cross-turn.test.ts +0 -258
- package/telegram-plugin/tests/progress-card-delay-842.test.ts +0 -160
- package/telegram-plugin/tests/progress-card-dispose-preservepending.test.ts +0 -81
- package/telegram-plugin/tests/progress-card-draft-flag.test.ts +0 -80
- package/telegram-plugin/tests/progress-card-driver-eviction.test.ts +0 -215
- package/telegram-plugin/tests/progress-card-driver-fleet-shadow.test.ts +0 -123
- package/telegram-plugin/tests/progress-card-driver-force-complete-parent-done.test.ts +0 -76
- package/telegram-plugin/tests/progress-card-edit-timestamps-budget.test.ts +0 -62
- package/telegram-plugin/tests/progress-card-memory-bounds.test.ts +0 -84
- package/telegram-plugin/tests/progress-card-pin-failure-paths.test.ts +0 -139
- package/telegram-plugin/tests/progress-card-pin-manager.test.ts +0 -773
- package/telegram-plugin/tests/progress-card-pin-race-fast-turn.test.ts +0 -66
- package/telegram-plugin/tests/progress-card-pin-sidecar-partial-write.test.ts +0 -64
- package/telegram-plugin/tests/progress-card-pin-watchdog.test.ts +0 -190
- package/telegram-plugin/tests/progress-card-sigterm-pin-flush.test.ts +0 -146
- package/telegram-plugin/tests/real-gateway-f1-ladder-integrity.test.ts +0 -123
- package/telegram-plugin/tests/real-gateway-f2-instant-draft.test.ts +0 -82
- package/telegram-plugin/tests/real-gateway-f3-late-card.test.ts +0 -114
- package/telegram-plugin/tests/real-gateway-harness.ts +0 -699
- package/telegram-plugin/tests/real-gateway-i6-turn-flush-replay-dedup.test.ts +0 -313
- package/telegram-plugin/tests/real-gateway-ipc-lifecycle.test.ts +0 -299
- package/telegram-plugin/tests/real-gateway-spec.test.ts +0 -487
- package/telegram-plugin/tests/real-gateway.smoke.test.ts +0 -101
- package/telegram-plugin/tests/setup-flow.test.ts +0 -510
- package/telegram-plugin/tests/setup-state.test.ts +0 -146
- package/telegram-plugin/tests/sync-chat-running-subagents.test.ts +0 -116
- package/telegram-plugin/tests/turn-end-regressions.test.ts +0 -489
- package/telegram-plugin/tests/turn-flush-card-takeover.test.ts +0 -218
- package/telegram-plugin/tests/turn-flush-prose-recovery.test.ts +0 -78
- package/telegram-plugin/tests/two-zone-bg-carry-full-lifecycle.test.ts +0 -131
- package/telegram-plugin/tests/two-zone-bg-detection.test.ts +0 -120
- package/telegram-plugin/tests/two-zone-bg-done-when-all-terminal.test.ts +0 -116
- package/telegram-plugin/tests/two-zone-bg-early-turn-end.test.ts +0 -87
- package/telegram-plugin/tests/two-zone-bg-survives-next-turn.test.ts +0 -211
- package/telegram-plugin/tests/two-zone-card-cap.test.ts +0 -62
- package/telegram-plugin/tests/two-zone-card-fleet-row.test.ts +0 -101
- package/telegram-plugin/tests/two-zone-card-header-phases.test.ts +0 -78
- package/telegram-plugin/tests/two-zone-card-html-balance.test.ts +0 -110
- package/telegram-plugin/tests/two-zone-card-lifecycle.test.ts +0 -128
- package/telegram-plugin/tests/two-zone-card-sanitise.test.ts +0 -58
- package/telegram-plugin/tests/two-zone-card-snapshot.test.ts +0 -133
- package/telegram-plugin/tests/two-zone-concurrent-turns-isolation.test.ts +0 -155
- package/telegram-plugin/tests/two-zone-phasefor-precedence.test.ts +0 -117
- package/telegram-plugin/tests/two-zone-snapshot-extras.test.ts +0 -187
- package/telegram-plugin/tests/two-zone-stuck-edit-throttle.test.ts +0 -149
- package/telegram-plugin/tests/two-zone-stuck-header-escalation.test.ts +0 -101
- package/telegram-plugin/tests/two-zone-stuck-per-member.test.ts +0 -114
- package/telegram-plugin/tests/two-zone-stuck-recovery.test.ts +0 -105
- package/telegram-plugin/tests/waiting-ux-harness.ts +0 -381
- package/telegram-plugin/tests/waiting-ux.e2e.test.ts +0 -233
- package/telegram-plugin/turn-flush-prose-recovery.ts +0 -40
- package/telegram-plugin/two-zone-card.ts +0 -269
- package/telegram-plugin/uat/scenarios/smoke-clerk-reply.test.ts +0 -61
|
@@ -62,17 +62,57 @@ describe("parseVaultCliError", () => {
|
|
|
62
62
|
});
|
|
63
63
|
|
|
64
64
|
describe("renderVaultCliError", () => {
|
|
65
|
-
|
|
65
|
+
// 2026-05-12: renderer copy migrated from host-CLI suggestions to
|
|
66
|
+
// Telegram-native next-step actions (vault_request_save, /vault
|
|
67
|
+
// audit, /vault broker status). Tests below assert the new copy.
|
|
68
|
+
// The pre-fix pins are documented in
|
|
69
|
+
// tests/jtbd-talk-from-anywhere.test.ts as the closed punch-list
|
|
70
|
+
// items.
|
|
71
|
+
it("renders sandbox_context for verb=set with the vault_request_save tool, surfacing the affected key", () => {
|
|
66
72
|
const out = renderVaultCliError(
|
|
67
73
|
{ kind: "sandbox_context", original: "x" },
|
|
68
74
|
{ verb: "set", key: "my_key" },
|
|
69
75
|
);
|
|
70
76
|
expect(out.suppressRaw).toBe(true);
|
|
71
|
-
expect(out.html).
|
|
72
|
-
expect(out.html).
|
|
77
|
+
expect(out.html).toMatch(/vault_request_save/);
|
|
78
|
+
expect(out.html).not.toMatch(/Open a host shell/);
|
|
79
|
+
// Reviewer-flagged on #1037: pre-fix test asserted the key
|
|
80
|
+
// appeared in output (so the operator knew which key triggered
|
|
81
|
+
// the card). New copy keeps the key in <code>…</code> form via
|
|
82
|
+
// htmlEscape — assert it.
|
|
83
|
+
expect(out.html).toContain("<code>my_key</code>");
|
|
73
84
|
});
|
|
74
85
|
|
|
75
|
-
it("renders
|
|
86
|
+
it("renders sandbox_context for verb=set WITHOUT a key (defensive fallback)", () => {
|
|
87
|
+
// The gateway sometimes doesn't have the key in hand (e.g. when
|
|
88
|
+
// the agent's stderr was opaque). Renderer should still produce
|
|
89
|
+
// useful output, not crash or render an empty <code></code>.
|
|
90
|
+
const out = renderVaultCliError(
|
|
91
|
+
{ kind: "sandbox_context", original: "x" },
|
|
92
|
+
{ verb: "set" },
|
|
93
|
+
);
|
|
94
|
+
expect(out.html).toMatch(/vault_request_save/);
|
|
95
|
+
expect(out.html).not.toContain("<code></code>");
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
it("renders sandbox_context for verb=get with /vault get", () => {
|
|
99
|
+
const out = renderVaultCliError(
|
|
100
|
+
{ kind: "sandbox_context", original: "x" },
|
|
101
|
+
{ verb: "get", key: "my_key" },
|
|
102
|
+
);
|
|
103
|
+
expect(out.html).toMatch(/\/vault get/);
|
|
104
|
+
expect(out.html).toMatch(/my_key/);
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
it("renders sandbox_context for verb=init with the one-time-host-shell note", () => {
|
|
108
|
+
const out = renderVaultCliError(
|
|
109
|
+
{ kind: "sandbox_context", original: "x" },
|
|
110
|
+
{ verb: "init" },
|
|
111
|
+
);
|
|
112
|
+
expect(out.html).toMatch(/one-time host-shell|switchroom vault init/);
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
it("renders needs_approval naming the live vault_request_save tool (not a 'on the way' stub)", () => {
|
|
76
116
|
const out = renderVaultCliError(
|
|
77
117
|
{ kind: "needs_approval", original: "x", key: "telegram_bot_token" },
|
|
78
118
|
{ verb: "save" },
|
|
@@ -80,35 +120,47 @@ describe("renderVaultCliError", () => {
|
|
|
80
120
|
expect(out.suppressRaw).toBe(true);
|
|
81
121
|
expect(out.html).toContain("operator approval required");
|
|
82
122
|
expect(out.html).toContain("<code>telegram_bot_token</code>");
|
|
83
|
-
expect(out.html).
|
|
84
|
-
expect(out.html).
|
|
123
|
+
expect(out.html).toMatch(/vault_request_save/);
|
|
124
|
+
expect(out.html).not.toMatch(/on the way/i);
|
|
85
125
|
});
|
|
86
126
|
|
|
87
|
-
it("renders broker_unreachable
|
|
127
|
+
it("renders broker_unreachable as an honest 'tracked follow-up' instead of a false in-chat promise", () => {
|
|
128
|
+
// Pre-fix (rejected by #1037 reviewer): renderer pointed at
|
|
129
|
+
// `/vault broker status` / `/vault broker restart` — neither
|
|
130
|
+
// command is registered in the gateway dispatcher. Telling the
|
|
131
|
+
// operator to type unregistered commands is worse than the
|
|
132
|
+
// host-CLI punt it was meant to replace.
|
|
133
|
+
//
|
|
134
|
+
// Post-fix: renderer names the in-Telegram follow-up as
|
|
135
|
+
// tracked + unbuilt, and points at the host CLI for now.
|
|
136
|
+
// Honest about the gap until /vault broker {status,restart}
|
|
137
|
+
// actually ships.
|
|
88
138
|
const out = renderVaultCliError(
|
|
89
139
|
{ kind: "broker_unreachable", original: "x" },
|
|
90
140
|
{ verb: "set" },
|
|
91
141
|
);
|
|
92
142
|
expect(out.suppressRaw).toBe(true);
|
|
93
143
|
expect(out.html).toContain("broker isn't reachable");
|
|
94
|
-
expect(out.html).
|
|
144
|
+
expect(out.html).toMatch(/tracked as a follow-up/i);
|
|
145
|
+
expect(out.html).toMatch(/switchroom vault broker status/);
|
|
95
146
|
});
|
|
96
147
|
|
|
97
|
-
it("renders broker_denied
|
|
148
|
+
it("renders broker_denied pointing at /vault audit one-tap allow + vault_request_access", () => {
|
|
98
149
|
const out = renderVaultCliError(
|
|
99
150
|
{ kind: "broker_denied", original: "x", key: "shared_token" },
|
|
100
151
|
{ verb: "set" },
|
|
101
152
|
);
|
|
102
153
|
expect(out.suppressRaw).toBe(true);
|
|
103
154
|
expect(out.html).toContain("refused the request");
|
|
104
|
-
expect(out.html).
|
|
155
|
+
expect(out.html).toMatch(/\/vault audit/);
|
|
156
|
+
expect(out.html).toMatch(/vault_request_access/);
|
|
105
157
|
expect(out.html).toContain("shared_token");
|
|
106
158
|
});
|
|
107
159
|
|
|
108
|
-
it("prefers verbHint.key over parser-extracted key (verbHint wins for
|
|
160
|
+
it("prefers verbHint.key over parser-extracted key (verbHint wins for in-Telegram next-step)", () => {
|
|
109
161
|
// The gateway always knows the key the user asked for; rendering
|
|
110
162
|
// must use that over any heuristic extraction so a parser glitch
|
|
111
|
-
// can't surface the wrong key in the
|
|
163
|
+
// can't surface the wrong key in the in-chat next-step suggestion.
|
|
112
164
|
const out = renderVaultCliError(
|
|
113
165
|
{ kind: "broker_denied", original: "x", key: "parser-extracted" },
|
|
114
166
|
{ verb: "set", key: "gateway-supplied" },
|
|
@@ -154,15 +154,22 @@ export function renderVaultCliError(
|
|
|
154
154
|
const key = verbHint.key ?? err.key;
|
|
155
155
|
switch (err.kind) {
|
|
156
156
|
case "sandbox_context":
|
|
157
|
+
// The agent tried direct vault file IO from inside the sandbox.
|
|
158
|
+
// Route the operator at the Telegram-native equivalent for the
|
|
159
|
+
// verb in flight — only `init` needs a one-time host shell.
|
|
160
|
+
// Closes the "leave Telegram for a verb that exists in Telegram"
|
|
161
|
+
// anti-pattern from reference/talk-to-agents-from-anywhere.md.
|
|
157
162
|
return {
|
|
158
163
|
suppressRaw: true,
|
|
159
164
|
html:
|
|
160
|
-
|
|
161
|
-
`The vault file isn't mounted inside the agent sandbox; only ` +
|
|
162
|
-
`the broker socket is. Open a host shell and run:\n` +
|
|
163
|
-
`<pre>switchroom vault ${verbHint.verb}${key ? ` ${htmlEscape(key)}` : ""}</pre>`,
|
|
165
|
+
renderSandboxContextSuggestion(verbHint.verb, key),
|
|
164
166
|
};
|
|
165
167
|
case "needs_approval":
|
|
168
|
+
// Agent tried to save a new key. The `vault_request_save` MCP
|
|
169
|
+
// tool shipped in #969 P1a renders an approval card in
|
|
170
|
+
// operator chat — no host shell, no re-paste. Telling the
|
|
171
|
+
// operator to "run switchroom vault set on the host" punts
|
|
172
|
+
// them to the desktop for a feature that exists in Telegram.
|
|
166
173
|
return {
|
|
167
174
|
suppressRaw: true,
|
|
168
175
|
html:
|
|
@@ -172,20 +179,34 @@ export function renderVaultCliError(
|
|
|
172
179
|
: `The agent tried to save a new key, but `) +
|
|
173
180
|
`agents can only rotate existing keys via the broker; introducing ` +
|
|
174
181
|
`a new key needs an operator action.\n\n` +
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
182
|
+
`<b>Ask the agent</b> to call its <code>vault_request_save</code> ` +
|
|
183
|
+
`tool — it'll render an approval card in this chat with ` +
|
|
184
|
+
`[✅ Save once] [🚫 Discard] [✏️ Rename] buttons. One tap saves the ` +
|
|
185
|
+
`secret to the vault; no re-paste needed.`,
|
|
178
186
|
};
|
|
179
187
|
case "broker_unreachable":
|
|
188
|
+
// No Telegram-native broker control plane exists yet —
|
|
189
|
+
// `/vault broker status` and `/vault broker restart` are on
|
|
190
|
+
// the JTBD punch list but not built (the broker socket lives
|
|
191
|
+
// outside the agent container; the gateway would need a
|
|
192
|
+
// host-side daemon to drive it). Be honest about that gap
|
|
193
|
+
// rather than promising commands that don't dispatch.
|
|
180
194
|
return {
|
|
181
195
|
suppressRaw: true,
|
|
182
196
|
html:
|
|
183
197
|
`⚠️ <b>Vault broker isn't reachable.</b>\n` +
|
|
184
198
|
`From inside the agent sandbox there's no fallback path. ` +
|
|
185
|
-
`
|
|
186
|
-
|
|
199
|
+
`Telegram-native broker recovery is tracked as a follow-up — ` +
|
|
200
|
+
`for now, on the host:\n` +
|
|
201
|
+
`<pre>switchroom vault broker status</pre>\n` +
|
|
202
|
+
`<i>Or, if the broker is wedged: <code>docker compose -p switchroom restart vault-broker</code>.</i>`,
|
|
187
203
|
};
|
|
188
204
|
case "broker_denied":
|
|
205
|
+
// Telegram-native grant flow shipped in #969 P2b + #1012:
|
|
206
|
+
// - operator runs `/vault audit <agent>`, taps [🔓 Allow <key>]
|
|
207
|
+
// for a recent denial — one tap, no shell.
|
|
208
|
+
// - OR the agent itself calls `vault_request_access` and the
|
|
209
|
+
// approval card with [✅ Approve] / [🚫 Deny] lands here.
|
|
189
210
|
return {
|
|
190
211
|
suppressRaw: true,
|
|
191
212
|
html:
|
|
@@ -193,10 +214,56 @@ export function renderVaultCliError(
|
|
|
193
214
|
(key
|
|
194
215
|
? `The agent isn't authorized to access <code>${htmlEscape(key)}</code>. `
|
|
195
216
|
: `The agent isn't authorized to access this key. `) +
|
|
196
|
-
`
|
|
197
|
-
|
|
217
|
+
`Grant access in two taps:\n` +
|
|
218
|
+
`• <code>/vault audit <agent></code> in this chat → tap ` +
|
|
219
|
+
`[🔓 Allow${key ? ` ${htmlEscape(key)}` : ""}] on the recent denial, OR\n` +
|
|
220
|
+
`• ask the agent to call <code>vault_request_access</code> — ` +
|
|
221
|
+
`an approval card lands here with [✅ Approve] / [🚫 Deny].`,
|
|
198
222
|
};
|
|
199
223
|
case "other":
|
|
200
224
|
return { suppressRaw: false, html: "" };
|
|
201
225
|
}
|
|
202
226
|
}
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* Suggest the Telegram-native command for each sandbox-context verb.
|
|
230
|
+
* Only `init` still needs a one-time host shell (vault bootstrap is
|
|
231
|
+
* a setup step, not a steering-while-mobile workflow).
|
|
232
|
+
*/
|
|
233
|
+
function renderSandboxContextSuggestion(
|
|
234
|
+
verb: "set" | "get" | "list" | "init" | "remove" | "save",
|
|
235
|
+
key: string | undefined,
|
|
236
|
+
): string {
|
|
237
|
+
const head = `⚠️ <b>Direct vault file IO isn't available from inside the agent sandbox.</b>\n`;
|
|
238
|
+
switch (verb) {
|
|
239
|
+
case "set":
|
|
240
|
+
case "save":
|
|
241
|
+
return (
|
|
242
|
+
head +
|
|
243
|
+
(key
|
|
244
|
+
? `<b>Ask the agent</b> to call its <code>vault_request_save</code> ` +
|
|
245
|
+
`tool for <code>${htmlEscape(key)}</code> — an approval card ` +
|
|
246
|
+
`lands here with [✅ Save once] / [🚫 Discard] / [✏️ Rename] buttons.`
|
|
247
|
+
: `<b>Ask the agent</b> to call its <code>vault_request_save</code> ` +
|
|
248
|
+
`tool — an approval card lands here with [✅ Save once] / [🚫 Discard] / [✏️ Rename] buttons.`)
|
|
249
|
+
);
|
|
250
|
+
case "get":
|
|
251
|
+
return (
|
|
252
|
+
head +
|
|
253
|
+
`From this chat: <code>/vault get${key ? ` ${htmlEscape(key)}` : " <key>"}</code>`
|
|
254
|
+
);
|
|
255
|
+
case "list":
|
|
256
|
+
return head + `From this chat: <code>/vault list</code>`;
|
|
257
|
+
case "remove":
|
|
258
|
+
return (
|
|
259
|
+
head +
|
|
260
|
+
`Use the operator host CLI for now — Telegram-native delete is tracked as a follow-up. ` +
|
|
261
|
+
`<i>(Removing a vault key is a rare, irreversible operation; an in-chat confirmation card is on the punch list.)</i>`
|
|
262
|
+
);
|
|
263
|
+
case "init":
|
|
264
|
+
return (
|
|
265
|
+
head +
|
|
266
|
+
`Vault bootstrap is a one-time host-shell step: <code>switchroom vault init</code>.`
|
|
267
|
+
);
|
|
268
|
+
}
|
|
269
|
+
}
|
|
@@ -25,7 +25,13 @@ export type VaultWriteFn = (
|
|
|
25
25
|
export type VaultListFn = (passphrase: string) => { ok: boolean; keys: string[] }
|
|
26
26
|
|
|
27
27
|
export const defaultVaultWrite: VaultWriteFn = (slug, value, passphrase) => {
|
|
28
|
-
|
|
28
|
+
// Suppress the #969 P3 deprecation warning — the gateway forwarding
|
|
29
|
+
// the operator's passphrase per-spawn is the canonical P1a flow.
|
|
30
|
+
const env = {
|
|
31
|
+
...process.env,
|
|
32
|
+
SWITCHROOM_VAULT_PASSPHRASE: passphrase,
|
|
33
|
+
SWITCHROOM_NO_VAULT_DEPRECATION_WARNING: '1',
|
|
34
|
+
}
|
|
29
35
|
try {
|
|
30
36
|
const result = execFileSync(
|
|
31
37
|
process.env.SWITCHROOM_CLI_PATH ?? 'switchroom',
|
|
@@ -41,7 +47,13 @@ export const defaultVaultWrite: VaultWriteFn = (slug, value, passphrase) => {
|
|
|
41
47
|
}
|
|
42
48
|
|
|
43
49
|
export const defaultVaultList: VaultListFn = (passphrase) => {
|
|
44
|
-
|
|
50
|
+
// Suppress the #969 P3 deprecation warning — the gateway forwarding
|
|
51
|
+
// the operator's passphrase per-spawn is the canonical P1a flow.
|
|
52
|
+
const env = {
|
|
53
|
+
...process.env,
|
|
54
|
+
SWITCHROOM_VAULT_PASSPHRASE: passphrase,
|
|
55
|
+
SWITCHROOM_NO_VAULT_DEPRECATION_WARNING: '1',
|
|
56
|
+
}
|
|
45
57
|
try {
|
|
46
58
|
const result = execFileSync(
|
|
47
59
|
process.env.SWITCHROOM_CLI_PATH ?? 'switchroom',
|