switchroom 0.18.11 → 0.18.13
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/dist/agent-scheduler/index.js +37 -5
- package/dist/auth-broker/index.js +116 -78
- package/dist/cli/hindsight-mental-model-pretool.mjs +39 -0
- package/dist/cli/ms-365-write-pretool.mjs +31 -8
- package/dist/cli/notion-write-pretool.mjs +38 -6
- package/dist/cli/skill-validate-pretool.mjs +144 -2847
- package/dist/cli/switchroom.js +3529 -4543
- package/dist/cli/ui/index.html +163 -17
- package/dist/host-control/main.js +605 -2847
- package/dist/vault/approvals/kernel-server.js +120 -13
- package/dist/vault/broker/server.js +259 -157
- package/package.json +3 -4
- package/profiles/_base/start.sh.hbs +65 -0
- package/profiles/_shared/vault-protocol.md.hbs +3 -1
- package/profiles/coding/CLAUDE.md.hbs +1 -1
- package/profiles/default/CLAUDE.md.hbs +2 -2
- package/profiles/executive-assistant/CLAUDE.md.hbs +1 -1
- package/profiles/health-coach/CLAUDE.md.hbs +1 -1
- package/telegram-plugin/bridge/bridge.ts +37 -0
- package/telegram-plugin/bridge/inbound-dedup.ts +101 -0
- package/telegram-plugin/dist/bridge/bridge.js +122 -4
- package/telegram-plugin/dist/gateway/gateway.js +4213 -3288
- package/telegram-plugin/dist/server.js +139 -5
- package/telegram-plugin/flood-circuit-breaker.ts +493 -21
- package/telegram-plugin/format.ts +19 -0
- package/telegram-plugin/gateway/approval-hold.ts +602 -0
- package/telegram-plugin/gateway/auth-command.ts +92 -2
- package/telegram-plugin/gateway/auth-loopback-relay.ts +670 -0
- package/telegram-plugin/gateway/boot-card.ts +12 -5
- package/telegram-plugin/gateway/callback-query-handlers.ts +88 -1
- package/telegram-plugin/gateway/config-approval-handler.ts +6 -1
- package/telegram-plugin/gateway/disconnect-flush.ts +19 -0
- package/telegram-plugin/gateway/dm-pin-sweep.test.ts +251 -0
- package/telegram-plugin/gateway/dm-pin-sweep.ts +178 -0
- package/telegram-plugin/gateway/gateway.ts +1695 -230
- package/telegram-plugin/gateway/hostd-dispatch.ts +23 -0
- package/telegram-plugin/gateway/idle-clear.ts +90 -6
- package/telegram-plugin/gateway/inbound-delivery-machine-shadow.ts +26 -5
- package/telegram-plugin/gateway/inject-handler.ts +8 -0
- package/telegram-plugin/gateway/ipc-protocol.ts +46 -3
- package/telegram-plugin/gateway/ipc-server.ts +43 -0
- package/telegram-plugin/gateway/mental-model-propose-resolve.ts +145 -37
- package/telegram-plugin/gateway/model-command.ts +9 -3
- package/telegram-plugin/gateway/pending-session-command.ts +13 -1
- package/telegram-plugin/gateway/permission-ttl-sweep.ts +66 -0
- package/telegram-plugin/gateway/pre-approval-check.ts +74 -0
- package/telegram-plugin/gateway/queued-card-store.ts +217 -0
- package/telegram-plugin/gateway/session-model-file.ts +26 -1
- package/telegram-plugin/gateway/turn-end-gate-backstop.ts +59 -0
- package/telegram-plugin/gateway/turn-end-gate.ts +95 -0
- package/telegram-plugin/gateway/turn-typing-loop.ts +10 -2
- package/telegram-plugin/gateway/unhandled-rejection-policy.ts +13 -0
- package/telegram-plugin/history.ts +51 -0
- package/telegram-plugin/hooks/dispatch-claim-scan.mjs +259 -0
- package/telegram-plugin/hooks/dispatch-claim-stop.mjs +129 -0
- package/telegram-plugin/hooks/hooks.json +9 -0
- package/telegram-plugin/inline-keyboard-callbacks.ts +303 -2
- package/telegram-plugin/model-unavailable.ts +41 -11
- package/telegram-plugin/operator-events.ts +23 -0
- package/telegram-plugin/outbound-field-redact.ts +69 -0
- package/telegram-plugin/package.json +0 -1
- package/telegram-plugin/permission-rule.ts +1 -0
- package/telegram-plugin/permission-title.ts +1 -0
- package/telegram-plugin/render/render.ts +32 -14
- package/telegram-plugin/retry-api-call.ts +212 -2
- package/telegram-plugin/scoped-approval.ts +11 -2
- package/telegram-plugin/secret-detect/chunker.ts +18 -4
- package/telegram-plugin/secret-detect/index.ts +12 -56
- package/telegram-plugin/send-gate-degraded.test.ts +574 -0
- package/telegram-plugin/send-gate-observability.test.ts +470 -0
- package/telegram-plugin/send-gate-observability.ts +355 -0
- package/telegram-plugin/send-gate.test.ts +717 -0
- package/telegram-plugin/send-gate.ts +1056 -0
- package/telegram-plugin/session-tail.ts +82 -7
- package/telegram-plugin/shared/bot-runtime.ts +17 -5
- package/telegram-plugin/shared/gw-trace-gate.ts +105 -0
- package/telegram-plugin/status-pin-driver.ts +52 -7
- package/telegram-plugin/status-pin.ts +81 -0
- package/telegram-plugin/subagent-watcher.ts +173 -18
- package/telegram-plugin/tests/activity-card-wiring.test.ts +18 -5
- package/telegram-plugin/tests/approval-hold-harness.ts +425 -0
- package/telegram-plugin/tests/approval-hold-outcome.test.ts +327 -0
- package/telegram-plugin/tests/approval-hold-record.test.ts +531 -0
- package/telegram-plugin/tests/approval-hold-redeliver.test.ts +602 -0
- package/telegram-plugin/tests/auth-loopback-relay.test.ts +533 -0
- package/telegram-plugin/tests/boot-card-flood-suppress.test.ts +53 -7
- package/telegram-plugin/tests/busy-key-reaper.test.ts +1 -0
- package/telegram-plugin/tests/callback-query-handlers.test.ts +65 -0
- package/telegram-plugin/tests/dispatch-claim-scan.test.ts +250 -0
- package/telegram-plugin/tests/flood-breaker-blindness.test.ts +213 -0
- package/telegram-plugin/tests/flood-windows-persistence.test.ts +224 -0
- package/telegram-plugin/tests/gateway-boot-marker-clear.test.ts +3 -3
- package/telegram-plugin/tests/gateway-disconnect-flush.test.ts +29 -1
- package/telegram-plugin/tests/gateway-loopback-paste-redact.test.ts +66 -0
- package/telegram-plugin/tests/gateway-outbound-redact.test.ts +57 -0
- package/telegram-plugin/tests/gw-trace-gate.test.ts +105 -0
- package/telegram-plugin/tests/history.test.ts +115 -0
- package/telegram-plugin/tests/idle-clear.test.ts +233 -3
- package/telegram-plugin/tests/inbound-dedup.test.ts +93 -0
- package/telegram-plugin/tests/inbound-message-types.test.ts +5 -1
- package/telegram-plugin/tests/inline-keyboard-callbacks.test.ts +448 -0
- package/telegram-plugin/tests/ipc-server-check-pre-approved.test.ts +194 -0
- package/telegram-plugin/tests/mental-model-propose-resolve.test.ts +123 -0
- package/telegram-plugin/tests/missed-approvals-wiring.test.ts +1 -1
- package/telegram-plugin/tests/model-command.test.ts +14 -0
- package/telegram-plugin/tests/operator-events-session-tail.test.ts +74 -0
- package/telegram-plugin/tests/outbound-field-redact.test.ts +107 -0
- package/telegram-plugin/tests/pending-session-command.test.ts +21 -0
- package/telegram-plugin/tests/permission-card-routing.test.ts +30 -5
- package/telegram-plugin/tests/permission-no-repeat-wiring.test.ts +8 -7
- package/telegram-plugin/tests/permission-rearm-wiring.test.ts +1 -1
- package/telegram-plugin/tests/pre-approval-check.test.ts +148 -0
- package/telegram-plugin/tests/queued-card-store.test.ts +232 -0
- package/telegram-plugin/tests/reaction-flush-turn-gated.test.ts +100 -0
- package/telegram-plugin/tests/reaction-gate-routing.test.ts +173 -0
- package/telegram-plugin/tests/render/render.test.ts +88 -0
- package/telegram-plugin/tests/retry-api-call.test.ts +398 -0
- package/telegram-plugin/tests/scoped-approval.test.ts +27 -0
- package/telegram-plugin/tests/secret-detect-chunk-overlap.test.ts +65 -0
- package/telegram-plugin/tests/secret-detect-oauth-code.test.ts +5 -4
- package/telegram-plugin/tests/session-model-file.test.ts +50 -0
- package/telegram-plugin/tests/session-tail-sidecar-reap.test.ts +268 -0
- package/telegram-plugin/tests/status-pin-boot-recovery.test.ts +35 -14
- package/telegram-plugin/tests/status-pin.test.ts +275 -1
- package/telegram-plugin/tests/subagent-watcher-deferral-log-ratelimit.test.ts +316 -0
- package/telegram-plugin/tests/subagent-watcher-fd-leak.test.ts +275 -0
- package/telegram-plugin/tests/turn-end-gate-backstop.test.ts +92 -0
- package/telegram-plugin/tests/turn-end-gate.test.ts +137 -0
- package/telegram-plugin/tests/typing-emitter.test.ts +586 -0
- package/telegram-plugin/tests/unhandled-rejection-policy.test.ts +20 -0
- package/telegram-plugin/tests/worktree-watch-cwds.test.ts +215 -1
- package/telegram-plugin/typing-emitter.ts +224 -0
- package/telegram-plugin/uat/scenarios/jtbd-feel-like-a-colleague-dm.test.ts +136 -0
- package/telegram-plugin/welcome-text.ts +42 -0
- package/telegram-plugin/worktree-watch-cwds.ts +194 -5
- package/vendor/hindsight-memory/scripts/drain_pending.py +22 -6
- package/vendor/hindsight-memory/scripts/lib/client.py +12 -5
- package/vendor/hindsight-memory/scripts/lib/directives.py +38 -3
- package/vendor/hindsight-memory/scripts/lib/pending.py +36 -9
- package/vendor/hindsight-memory/scripts/session_end.py +14 -3
- package/vendor/hindsight-memory/scripts/session_start.py +21 -0
- package/vendor/hindsight-memory/scripts/tests/test_directives.py +38 -0
- package/vendor/hindsight-memory/tests/test_drain_pending.py +68 -0
- package/vendor/hindsight-memory/tests/test_pending.py +44 -0
- package/vendor/hindsight-memory/tests/test_session_end_pending.py +38 -0
- package/vendor/hindsight-memory/tests/test_session_start_drain.py +155 -0
- package/telegram-plugin/channel-envelope-safety.test.ts +0 -56
- package/telegram-plugin/channel-envelope-safety.ts +0 -56
- package/telegram-plugin/secret-detect/secretlint-source.ts +0 -95
- package/telegram-plugin/tests/secret-detect-secretlint.test.ts +0 -105
|
@@ -24,10 +24,33 @@ var GATED_MS365_WRITE_TOOLS = new Set([
|
|
|
24
24
|
"update-message",
|
|
25
25
|
"delete-message"
|
|
26
26
|
]);
|
|
27
|
+
var KNOWN_SAFE_MS365_READ_TOOLS = new Set([
|
|
28
|
+
"list-files",
|
|
29
|
+
"list-drive-items",
|
|
30
|
+
"get-drive-item",
|
|
31
|
+
"download-bytes",
|
|
32
|
+
"search-files",
|
|
33
|
+
"list-events",
|
|
34
|
+
"get-event",
|
|
35
|
+
"list-calendars",
|
|
36
|
+
"get-calendar",
|
|
37
|
+
"list-messages",
|
|
38
|
+
"get-message",
|
|
39
|
+
"search-mail",
|
|
40
|
+
"list-mail-folders",
|
|
41
|
+
"get-mail-folder",
|
|
42
|
+
"whoami",
|
|
43
|
+
"get-current-user"
|
|
44
|
+
]);
|
|
27
45
|
function isGatedMs365Tool(toolName) {
|
|
28
46
|
if (!toolName.startsWith(TOOL_PREFIX))
|
|
29
47
|
return false;
|
|
30
|
-
|
|
48
|
+
const bare = toolName.slice(TOOL_PREFIX.length);
|
|
49
|
+
if (bare.length === 0)
|
|
50
|
+
return false;
|
|
51
|
+
if (KNOWN_SAFE_MS365_READ_TOOLS.has(bare))
|
|
52
|
+
return false;
|
|
53
|
+
return true;
|
|
31
54
|
}
|
|
32
55
|
function readStdin() {
|
|
33
56
|
try {
|
|
@@ -170,13 +193,12 @@ async function rpcKernel(payload) {
|
|
|
170
193
|
});
|
|
171
194
|
});
|
|
172
195
|
}
|
|
173
|
-
async function
|
|
196
|
+
async function approvalLookupByRequest(agentUnit, requestId, approverSet) {
|
|
174
197
|
const res = await rpcKernel({
|
|
175
198
|
v: 1,
|
|
176
|
-
op: "
|
|
199
|
+
op: "approval_lookup_by_request",
|
|
177
200
|
agent_unit: agentUnit,
|
|
178
|
-
|
|
179
|
-
action: "write",
|
|
201
|
+
request_id: requestId,
|
|
180
202
|
current_approver_set: approverSet
|
|
181
203
|
});
|
|
182
204
|
if (!res.ok)
|
|
@@ -203,7 +225,7 @@ async function main() {
|
|
|
203
225
|
}
|
|
204
226
|
const agentName = process.env.SWITCHROOM_AGENT_NAME;
|
|
205
227
|
if (!agentName) {
|
|
206
|
-
|
|
228
|
+
fail("SWITCHROOM_AGENT_NAME unset \u2014 cannot identify agent to gate write");
|
|
207
229
|
}
|
|
208
230
|
const accountEmail = process.env.SWITCHROOM_MICROSOFT_ACCOUNT ?? "(unknown)";
|
|
209
231
|
const extract = extractMs365Preview(toolName, input.tool_input);
|
|
@@ -230,11 +252,11 @@ async function main() {
|
|
|
230
252
|
if (!response.ok || !response.requestId) {
|
|
231
253
|
fail(response.reason ?? "gateway returned ok=false");
|
|
232
254
|
}
|
|
255
|
+
const requestId = response.requestId;
|
|
233
256
|
const deadline = response.expiresAtMs ?? Date.now() + HOOK_TIMEOUT_MS;
|
|
234
|
-
const scope = `ms-365:write:${preview.itemId}`;
|
|
235
257
|
while (Date.now() < deadline) {
|
|
236
258
|
await new Promise((r) => setTimeout(r, KERNEL_POLL_INTERVAL_MS));
|
|
237
|
-
const lookup = await
|
|
259
|
+
const lookup = await approvalLookupByRequest(agentName, requestId, []);
|
|
238
260
|
if (!lookup)
|
|
239
261
|
continue;
|
|
240
262
|
const state = lookup.state;
|
|
@@ -255,5 +277,6 @@ if (__require.main == __require.module) {
|
|
|
255
277
|
export {
|
|
256
278
|
isGatedMs365Tool,
|
|
257
279
|
extractMs365Preview,
|
|
280
|
+
KNOWN_SAFE_MS365_READ_TOOLS,
|
|
258
281
|
GATED_MS365_WRITE_TOOLS
|
|
259
282
|
};
|
|
@@ -10928,7 +10928,7 @@ function decodeResponse(line) {
|
|
|
10928
10928
|
const obj = JSON.parse(line);
|
|
10929
10929
|
return ResponseSchema.parse(obj);
|
|
10930
10930
|
}
|
|
10931
|
-
var MAX_FRAME_BYTES, AgentNameSchema, GetRequestSchema, PutRequestSchema, ListRequestSchema, MintGrantRequestSchema, ListGrantsRequestSchema, RevokeGrantRequestSchema, StatusRequestSchema, LockRequestSchema, PreflightAccessRequestSchema, OkPreflightAccessResponseSchema, ApprovalRequestRequestSchema, ApprovalLookupRequestSchema, ApprovalConsumeRequestSchema, ApprovalRevokeRequestSchema, ApprovalListRequestSchema, ApprovalDecisionModeSchema, ApprovalRecordRequestSchema, ApprovalConsumeRecordRequestSchema, RequestSchema, VaultEntrySchema, ErrorCode, OkEntryResponseSchema, OkKeysResponseSchema, BrokerStatus, OkStatusResponseSchema, OkLockResponseSchema, OkPutResponseSchema, OkMintGrantResponseSchema, GrantMetaSchema, OkListGrantsResponseSchema, OkRevokeGrantResponseSchema, OkApprovalRequestResponseSchema, ApprovalDecisionMetaSchema, OkApprovalLookupResponseSchema, OkApprovalConsumeResponseSchema, OkApprovalRevokeResponseSchema, OkApprovalListResponseSchema, OkApprovalRecordResponseSchema, OkApprovalConsumeRecordResponseSchema, ErrorResponseSchema, ResponseSchema;
|
|
10931
|
+
var MAX_FRAME_BYTES, AgentNameSchema, GetRequestSchema, PutRequestSchema, ListRequestSchema, MintGrantRequestSchema, ListGrantsRequestSchema, RevokeGrantRequestSchema, StatusRequestSchema, LockRequestSchema, PreflightAccessRequestSchema, OkPreflightAccessResponseSchema, ApprovalRequestRequestSchema, ApprovalLookupRequestSchema, ApprovalLookupByRequestRequestSchema, ApprovalConsumeRequestSchema, ApprovalRevokeRequestSchema, ApprovalListRequestSchema, ApprovalDecisionModeSchema, ApprovalRecordRequestSchema, ApprovalConsumeRecordRequestSchema, RequestSchema, VaultEntrySchema, ErrorCode, OkEntryResponseSchema, OkKeysResponseSchema, BrokerStatus, OkStatusResponseSchema, OkLockResponseSchema, OkPutResponseSchema, OkMintGrantResponseSchema, GrantMetaSchema, OkListGrantsResponseSchema, OkRevokeGrantResponseSchema, OkApprovalRequestResponseSchema, ApprovalDecisionMetaSchema, OkApprovalLookupResponseSchema, OkApprovalConsumeResponseSchema, OkApprovalRevokeResponseSchema, OkApprovalListResponseSchema, OkApprovalRecordResponseSchema, OkApprovalConsumeRecordResponseSchema, ErrorResponseSchema, ResponseSchema;
|
|
10932
10932
|
var init_protocol = __esm(() => {
|
|
10933
10933
|
init_zod();
|
|
10934
10934
|
init_peercred();
|
|
@@ -11028,6 +11028,13 @@ var init_protocol = __esm(() => {
|
|
|
11028
11028
|
action: exports_external.string().min(1),
|
|
11029
11029
|
current_approver_set: exports_external.array(exports_external.string())
|
|
11030
11030
|
});
|
|
11031
|
+
ApprovalLookupByRequestRequestSchema = exports_external.object({
|
|
11032
|
+
v: exports_external.literal(1),
|
|
11033
|
+
op: exports_external.literal("approval_lookup_by_request"),
|
|
11034
|
+
agent_unit: exports_external.string().min(1),
|
|
11035
|
+
request_id: exports_external.string().regex(/^[0-9a-f]{32}$/),
|
|
11036
|
+
current_approver_set: exports_external.array(exports_external.string())
|
|
11037
|
+
});
|
|
11031
11038
|
ApprovalConsumeRequestSchema = exports_external.object({
|
|
11032
11039
|
v: exports_external.literal(1),
|
|
11033
11040
|
op: exports_external.literal("approval_consume"),
|
|
@@ -11082,6 +11089,7 @@ var init_protocol = __esm(() => {
|
|
|
11082
11089
|
RevokeGrantRequestSchema,
|
|
11083
11090
|
ApprovalRequestRequestSchema,
|
|
11084
11091
|
ApprovalLookupRequestSchema,
|
|
11092
|
+
ApprovalLookupByRequestRequestSchema,
|
|
11085
11093
|
ApprovalConsumeRequestSchema,
|
|
11086
11094
|
ApprovalRevokeRequestSchema,
|
|
11087
11095
|
ApprovalListRequestSchema,
|
|
@@ -11104,7 +11112,8 @@ var init_protocol = __esm(() => {
|
|
|
11104
11112
|
"DENIED",
|
|
11105
11113
|
"UNKNOWN_KEY",
|
|
11106
11114
|
"BAD_REQUEST",
|
|
11107
|
-
"INTERNAL"
|
|
11115
|
+
"INTERNAL",
|
|
11116
|
+
"AUDIT_UNAVAILABLE"
|
|
11108
11117
|
]);
|
|
11109
11118
|
OkEntryResponseSchema = exports_external.object({
|
|
11110
11119
|
ok: exports_external.literal(true),
|
|
@@ -11808,7 +11817,12 @@ var ScheduleEntrySchema = exports_external.object({
|
|
|
11808
11817
|
var AgentSoulSchema = exports_external.object({
|
|
11809
11818
|
name: exports_external.string().describe("Agent persona name (e.g., 'Coach', 'Sage')"),
|
|
11810
11819
|
style: exports_external.string().describe("Communication style description"),
|
|
11811
|
-
|
|
11820
|
+
creature: exports_external.string().optional().describe("Persona creature/form (e.g., 'owl', 'octopus')"),
|
|
11821
|
+
vibe: exports_external.string().optional().describe("One-line personality vibe (e.g., 'calm, precise')"),
|
|
11822
|
+
expertise: exports_external.string().optional().describe("Domain expertise summary rendered into the persona"),
|
|
11823
|
+
emoji: exports_external.string().optional().describe("Signature emoji for the persona (e.g., '\uD83E\uDD89')"),
|
|
11824
|
+
boundaries: exports_external.string().optional().describe("Behavioral boundaries and disclaimers"),
|
|
11825
|
+
shape: exports_external.enum(["executive-assistant", "developer", "coach", "generalist"]).default("generalist").describe("Persona-shape discriminator the per-agent CLAUDE.md template can " + "branch on (e.g., 'you are an executive assistant' vs 'a senior " + "engineer'). No runtime behavior yet \u2014 template work lands in a " + "later issue. Cascade: override (per-agent wins over default).")
|
|
11812
11826
|
}).optional();
|
|
11813
11827
|
var AgentToolsSchema = exports_external.object({
|
|
11814
11828
|
allow: exports_external.array(exports_external.string()).default([]).describe("Allowed tools (use ['all'] for unrestricted)"),
|
|
@@ -11973,6 +11987,11 @@ var TelegramChannelSchema = exports_external.object({
|
|
|
11973
11987
|
safe_boundary: exports_external.boolean().optional().describe("When true (the default), a `!`-prefix interrupt that arrives while " + "the agent is mid-tool-call is DEFERRED: the SIGINT and the " + "replacement turn wait until the in-flight tool call finishes (a " + "clean boundary) instead of C-c'ing the agent mid-write/mid-bash. If " + "no tool is in flight the interrupt still fires immediately. Bounded " + "by max_wait_ms so a long tool never strands the user. Set false to " + "fire synchronously the moment `!` is received (historical " + "behaviour). Rapid repeated `!` while one is pending coalesce into a " + "single deferred interrupt carrying the latest body."),
|
|
11974
11988
|
max_wait_ms: exports_external.number().int().positive().optional().describe("Upper bound (ms) the gateway waits for a safe boundary before firing " + "a deferred `!` interrupt anyway. Only consulted when safe_boundary is " + "true. Default 8000. Keep it short \u2014 the user explicitly asked to " + "interrupt, so a long in-flight tool shouldn't ghost them; the cap " + "trades a tiny risk of a mid-tool C-c for a guaranteed response.")
|
|
11975
11989
|
}).optional().describe("Interrupt timing \u2014 how a `!`-prefix interrupt behaves when it lands " + "mid-tool-call. Off by default (fire immediately). Cascades from " + "defaults.channels.telegram.interrupt."),
|
|
11990
|
+
button_choice_confirmation: exports_external.object({
|
|
11991
|
+
enabled: exports_external.boolean().default(false).describe("When true, tapping an agent-emitted inline_keyboard button annotates " + "the source message body with a '\u2705 You chose: <label> \u00b7 HH:MM' line so " + "the chat surface is self-documenting. Only applies to single-use " + "keyboards (re-tappable keyboards are never annotated). Requires the " + "agent's parseMode to be the default 'html'. Opt-in (default false). " + "Limitation: the annotated body is rebuilt from the message's plain " + "text, so any formatting entities (bold, links, code, ...) on the " + "original message are lost when the annotation is applied."),
|
|
11992
|
+
format: exports_external.string().default("\u2705 You chose: {label} \u00b7 {time}").describe("Template for the annotation line. `{label}` is replaced with the " + "tapped button's text (newlines stripped, HTML-escaped, trimmed to 60 " + "chars) and `{time}` with HH:MM in the chosen timezone. Note: retap " + "dedup (replacing a prior annotation instead of appending another " + "line) only recognizes the DEFAULT format shape \u2014 a custom format " + "accumulates one line per retap."),
|
|
11993
|
+
timezone: exports_external.enum(["gateway", "utc"]).default("gateway").describe("Timezone for the {time} placeholder. 'gateway' uses the gateway " + "process's local time; 'utc' uses UTC. Per-user timezones are out of " + "scope for v1.")
|
|
11994
|
+
}).optional().describe("Auto-confirm 'You chose: X' annotation on inline_keyboard taps (#789). " + "Cascades from defaults.channels.telegram.button_choice_confirmation."),
|
|
11976
11995
|
webhook_sources: exports_external.array(exports_external.enum(["github", "generic", "linear"])).optional().describe("External webhook sources allowed to ingest events into this agent's " + "log. POST /webhook/<agent>/<source> on the switchroom web server. " + "Each source has its own signature verification ('github' = " + "X-Hub-Signature-256 HMAC-SHA256, 'generic' = Bearer token, " + "'linear' = Linear-Signature bare-hex HMAC-SHA256 of the raw body). " + "Per-source secret read from ~/.switchroom/webhook-secrets.json " + "keyed by [agent][source]. Verified events append to " + "<agent>/telegram/webhook-events.jsonl for the agent to read on " + "demand. Off by default \u2014 webhook is the only untrusted-inbound " + "surface in the system, so opt-in is mandatory. " + "Cascades from defaults.channels.telegram.webhook_sources. " + "(Migrated from per-agent root in #596 \u2014 see #577.)"),
|
|
11977
11996
|
webhook_dispatch: exports_external.object({
|
|
11978
11997
|
github: exports_external.array(webhookDispatchRule).optional(),
|
|
@@ -12121,7 +12140,12 @@ var profileFields = {
|
|
|
12121
12140
|
soul: exports_external.object({
|
|
12122
12141
|
name: exports_external.string().optional(),
|
|
12123
12142
|
style: exports_external.string().optional(),
|
|
12124
|
-
|
|
12143
|
+
creature: exports_external.string().optional(),
|
|
12144
|
+
vibe: exports_external.string().optional(),
|
|
12145
|
+
expertise: exports_external.string().optional(),
|
|
12146
|
+
emoji: exports_external.string().optional(),
|
|
12147
|
+
boundaries: exports_external.string().optional(),
|
|
12148
|
+
shape: exports_external.enum(["executive-assistant", "developer", "coach", "generalist"]).optional()
|
|
12125
12149
|
}).optional(),
|
|
12126
12150
|
tools: exports_external.object({
|
|
12127
12151
|
allow: exports_external.array(exports_external.string()).optional(),
|
|
@@ -12318,7 +12342,8 @@ var VaultConfigSchema = exports_external.object({
|
|
|
12318
12342
|
autoUnlockCredentialPath: exports_external.string().default("~/.switchroom/vault-auto-unlock").describe("Path to the machine-bound auto-unlock blob (see " + "src/vault/auto-unlock.ts for the format). Default lives under " + "~/.switchroom so it can be bind-mounted into the vault-broker " + "container by docker compose. Tilde-expansion happens " + "at read time."),
|
|
12319
12343
|
approvalAuth: exports_external.enum(["passphrase", "telegram-id"]).default("passphrase").describe("Posture for tap-to-Approve on vault grant cards. `passphrase` " + "(default) prompts the operator to type the vault passphrase on " + "every Approve \u2014 two-factor (Telegram ID + passphrase). " + "`telegram-id` mints immediately on Approve with no passphrase " + "prompt \u2014 single-factor (Telegram ID only); REQUIRES " + "`autoUnlock: true` so the broker already holds the passphrase. " + "Trades a factor of security for smoother UX; opt-in only."),
|
|
12320
12344
|
postureMintAgents: exports_external.array(exports_external.string().min(1)).default([]).describe("Per-agent opt-in for posture-attested broker calls (`mint_grant` / " + "`list_grants` / `put` with `attest_via_posture: true`). Only agents " + "whose names are in this list can use the silent-mint path under " + "`approvalAuth: telegram-id`. Default `[]` \u2014 no agent can self-mint " + "until the operator explicitly opts it in. The request's `agent` " + "field must also equal the calling peer's resolved agent name " + "(broker rejects cross-agent posture mints). When `approvalAuth` is " + "`passphrase` this list is ignored \u2014 passphrase attestation still " + "works as before. Each entry is an agent slug exactly as it appears " + "under `agents:` in this config."),
|
|
12321
|
-
adminOnlyKeys: exports_external.array(exports_external.string().min(1)).default([]).describe("Vault keys held to a higher approval bar: only the admin operator " + "(`access.allowFrom[0]`) may approve a grant for them, and they can " + "NEVER be minted via posture attestation \u2014 granting one requires the " + "operator passphrase (so an agent, even one on `postureMintAgents`, " + "cannot self-grant it). Entries are exact key names or `*` globs, " + "e.g. `stripe/*`, `*/oauth-token`, `microsoft/ken-tokens` (`*` matches " + "any run of characters incl. `/`; case-sensitive). Default `[]` \u2014 no " + "key is admin-only. Posture may RETAIN an admin-only key across a " + "union re-mint but never ADD one. Takes effect on broker + gateway " + "restart (broker has no ACL hot-reload).")
|
|
12345
|
+
adminOnlyKeys: exports_external.array(exports_external.string().min(1)).default([]).describe("Vault keys held to a higher approval bar: only the admin operator " + "(`access.allowFrom[0]`) may approve a grant for them, and they can " + "NEVER be minted via posture attestation \u2014 granting one requires the " + "operator passphrase (so an agent, even one on `postureMintAgents`, " + "cannot self-grant it). Entries are exact key names or `*` globs, " + "e.g. `stripe/*`, `*/oauth-token`, `microsoft/ken-tokens` (`*` matches " + "any run of characters incl. `/`; case-sensitive). Default `[]` \u2014 no " + "key is admin-only. Posture may RETAIN an admin-only key across a " + "union re-mint but never ADD one. Takes effect on broker + gateway " + "restart (broker has no ACL hot-reload)."),
|
|
12346
|
+
auditFailClosed: exports_external.boolean().default(false).describe("sec WS10-F3 (#1420) \u2014 fail-CLOSED on an audit-append failure. When " + "`false` (default, backward-compatible) the broker fails OPEN: if a " + "vault-audit.log append fails it logs to stderr, bumps the durable " + "fail-open counter, and STILL releases the secret. When `true`, a " + "failed audit append DENIES the secret release with " + "`AUDIT_UNAVAILABLE` \u2014 no secret leaves the broker without a durable " + "audit row. The env var `SWITCHROOM_VAULT_AUDIT_FAIL_CLOSED` " + "(`1`/`true` or `0`/`false`) overrides this at runtime. Either way " + "the fail-open counter is surfaced by `switchroom doctor`. Takes " + "effect on broker restart.")
|
|
12322
12347
|
}).default({}).superRefine((broker, ctx) => {
|
|
12323
12348
|
if (broker.approvalAuth === "telegram-id" && broker.autoUnlock !== true) {
|
|
12324
12349
|
ctx.addIssue({
|
|
@@ -12357,7 +12382,9 @@ var FleetHealthConfigSchema = exports_external.object({
|
|
|
12357
12382
|
});
|
|
12358
12383
|
var HostdConfigSchema = exports_external.object({
|
|
12359
12384
|
config_edit_enabled: exports_external.boolean().default(false).describe("Opt-in toggle for the `config_propose_edit` hostd verb (RFC " + "admin-agent-config-edit \u00a73). Default false \u2014 the verb returns " + "`E_CONFIG_EDIT_DISABLED` until the operator explicitly flips " + "this to true. When true, admin agents can propose unified-diff " + "patches against " + "`/state/config/switchroom.yaml`, gated by an operator approval " + "card in the primary chat. Same trust posture as `update_apply` " + "and `agent_restart`: the human-in-the-loop tap is the security " + "boundary, not the agent's judgement."),
|
|
12360
|
-
config_edit_rate_per_hour: exports_external.number().int().min(1).max(20).default(3).describe("Per-requesting-agent rate cap for `config_propose_edit` cards " + "(RFC admin-agent-config-edit \u00a75). Default 3 cards/hour; min 1, " + "max 20. ENFORCED server-side: a caller exceeding this in a sliding " + "1-hour window is rejected with `E_RATE_LIMITED` (carrying a " + "`retry_after` fix) instead of posting another operator approval " + "card \u2014 so a looping agent is throttled rather than spamming the chat.")
|
|
12385
|
+
config_edit_rate_per_hour: exports_external.number().int().min(1).max(20).default(3).describe("Per-requesting-agent rate cap for `config_propose_edit` cards " + "(RFC admin-agent-config-edit \u00a75). Default 3 cards/hour; min 1, " + "max 20. ENFORCED server-side: a caller exceeding this in a sliding " + "1-hour window is rejected with `E_RATE_LIMITED` (carrying a " + "`retry_after` fix) instead of posting another operator approval " + "card \u2014 so a looping agent is throttled rather than spamming the chat."),
|
|
12386
|
+
operator_attest_enabled: exports_external.boolean().default(false).describe("Opt-in toggle for the operator-passphrase 2nd factor on hostd's " + "mutating verbs (#1841, RFC host-control-daemon.md \u00a75.4). Default " + "false \u2014 attestation is ACCEPTED-and-audited whenever present, but " + "no verb REQUIRES it (behaviour is byte-identical to today, so " + "existing fleets and the Telegram approval-card flow are unchanged). " + "When true, the verbs in `operator_attest_required_verbs` demand a " + "valid operator-passphrase attestation IN ADDITION to admin: hostd " + "forwards the passphrase to the vault broker over its own admin-client " + "connection (`/run/switchroom/broker/hostd/sock`) and treats a broker " + "DENIED as a gate failure. hostd never holds the passphrase. Leave " + "this off until BOTH the gateway passphrase-forward and the " + "cross-compose broker socket are deployed, or gated verbs will fail."),
|
|
12387
|
+
operator_attest_required_verbs: exports_external.array(exports_external.string().min(1)).default(["update_apply", "apply", "rollout"]).describe("Which mutating hostd verbs REQUIRE a valid operator-passphrase " + "attestation when `operator_attest_enabled` is true (#1841). Default " + "is the RFC \u00a75.4 fleet-mutation set (`update_apply`, `apply`, " + "`rollout`). Verbs NOT in this list still accept-and-audit an " + "attestation when one is supplied, but never require it. Ignored " + "entirely when `operator_attest_enabled` is false.")
|
|
12361
12388
|
});
|
|
12362
12389
|
var CronEgressSchema = exports_external.object({
|
|
12363
12390
|
allowed_hosts: exports_external.array(exports_external.string().min(1)).default([]).describe("Hosts a poll may reach (exact, https-only). loopback/private/IP-literal are always rejected."),
|
|
@@ -12771,6 +12798,11 @@ function mergeAgentConfig(defaultsIn, agentIn) {
|
|
|
12771
12798
|
if (v !== undefined)
|
|
12772
12799
|
combined[k] = v;
|
|
12773
12800
|
}
|
|
12801
|
+
const baseSoul = base;
|
|
12802
|
+
const overrideSoul = override;
|
|
12803
|
+
if (baseSoul.shape !== undefined && (overrideSoul.shape === undefined || overrideSoul.shape === "generalist")) {
|
|
12804
|
+
combined.shape = baseSoul.shape;
|
|
12805
|
+
}
|
|
12774
12806
|
merged.soul = combined;
|
|
12775
12807
|
}
|
|
12776
12808
|
if (defaults.memory || merged.memory) {
|