switchroom 0.18.8 → 0.18.10

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.
Files changed (93) hide show
  1. package/README.md +2 -2
  2. package/dist/agent-scheduler/index.js +1 -0
  3. package/dist/auth-broker/index.js +198 -13
  4. package/dist/cli/notion-write-pretool.mjs +1 -0
  5. package/dist/cli/switchroom.js +28 -4
  6. package/dist/host-control/main.js +3 -2
  7. package/dist/vault/approvals/kernel-server.js +2 -1
  8. package/dist/vault/broker/server.js +2 -1
  9. package/package.json +1 -1
  10. package/profiles/_base/start.sh.hbs +119 -37
  11. package/profiles/_shared/dev-protocol.md.hbs +42 -0
  12. package/skills/dev-protocol/SKILL.md +131 -0
  13. package/telegram-plugin/README.md +2 -1
  14. package/telegram-plugin/admin-commands/dispatch.test.ts +40 -2
  15. package/telegram-plugin/admin-commands/index.ts +6 -1
  16. package/telegram-plugin/bridge/bridge.ts +23 -1
  17. package/telegram-plugin/bridge/crash-breadcrumb.ts +42 -0
  18. package/telegram-plugin/chat-lock.ts +13 -0
  19. package/telegram-plugin/dist/bridge/bridge.js +24 -1
  20. package/telegram-plugin/dist/gateway/gateway.js +80236 -77465
  21. package/telegram-plugin/dist/server.js +29 -2
  22. package/telegram-plugin/fallback-card-collapse.ts +131 -0
  23. package/telegram-plugin/gateway/approval-card-stores.ts +99 -0
  24. package/telegram-plugin/gateway/bot-commands-ops-info.ts +194 -0
  25. package/telegram-plugin/gateway/bridge-dead-watchdog.ts +546 -0
  26. package/telegram-plugin/gateway/callback-query-handlers.ts +2660 -0
  27. package/telegram-plugin/gateway/effort-command.ts +47 -3
  28. package/telegram-plugin/gateway/gateway.ts +2051 -3180
  29. package/telegram-plugin/gateway/inbound-delivery-machine-dispatch.ts +181 -23
  30. package/telegram-plugin/gateway/inbound-delivery-machine.ts +8 -0
  31. package/telegram-plugin/gateway/model-command.ts +94 -8
  32. package/telegram-plugin/gateway/outbound-send-path.ts +375 -0
  33. package/telegram-plugin/gateway/pending-session-command.ts +365 -0
  34. package/telegram-plugin/gateway/pending-state-stores.ts +106 -0
  35. package/telegram-plugin/gateway/permission-timeout.ts +25 -0
  36. package/telegram-plugin/gateway/register-bot-commands.ts +30 -0
  37. package/telegram-plugin/gateway/resume-inbound-builder.ts +23 -3
  38. package/telegram-plugin/gateway/session-model-file.ts +166 -23
  39. package/telegram-plugin/gateway/stop-command.ts +56 -0
  40. package/telegram-plugin/photo-precheck.ts +201 -0
  41. package/telegram-plugin/quota-watch.ts +141 -2
  42. package/telegram-plugin/registry/subagents-schema.ts +26 -3
  43. package/telegram-plugin/registry/subagents.test.ts +67 -0
  44. package/telegram-plugin/retry-api-call.ts +31 -0
  45. package/telegram-plugin/subagent-watcher.ts +392 -1
  46. package/telegram-plugin/tests/approval-card-stores.test.ts +124 -0
  47. package/telegram-plugin/tests/bridge-dead-watchdog.test.ts +576 -0
  48. package/telegram-plugin/tests/buffer-gate-broadened.test.ts +11 -5
  49. package/telegram-plugin/tests/callback-query-handlers.test.ts +701 -0
  50. package/telegram-plugin/tests/chat-lock-unhandled-rejection.test.ts +101 -0
  51. package/telegram-plugin/tests/crash-breadcrumb.test.ts +57 -0
  52. package/telegram-plugin/tests/effort-command.test.ts +59 -2
  53. package/telegram-plugin/tests/emission-determinism-wiring.test.ts +11 -4
  54. package/telegram-plugin/tests/fallback-card-collapse.test.ts +104 -0
  55. package/telegram-plugin/tests/fixtures/cutover-killswitch-probe.ts +75 -0
  56. package/telegram-plugin/tests/gateway-outbound-redact.test.ts +5 -1
  57. package/telegram-plugin/tests/gateway-pending-command-wiring.test.ts +124 -0
  58. package/telegram-plugin/tests/gateway-secret-detect.test.ts +7 -1
  59. package/telegram-plugin/tests/gateway-session-model-relaunch.test.ts +19 -11
  60. package/telegram-plugin/tests/inbound-delivery-cutover-flip.test.ts +418 -0
  61. package/telegram-plugin/tests/inbound-delivery-dispatch-equivalence.test.ts +348 -0
  62. package/telegram-plugin/tests/inbound-delivery-machine-dispatch.test.ts +141 -52
  63. package/telegram-plugin/tests/mental-model-propose-callback-gate.test.ts +8 -1
  64. package/telegram-plugin/tests/model-command.test.ts +46 -3
  65. package/telegram-plugin/tests/outbound-send-chunks.test.ts +304 -0
  66. package/telegram-plugin/tests/outbound-send-path.test.ts +222 -0
  67. package/telegram-plugin/tests/pending-card-durability-wiring.test.ts +34 -15
  68. package/telegram-plugin/tests/pending-session-command.test.ts +322 -0
  69. package/telegram-plugin/tests/pending-state-stores.test.ts +235 -0
  70. package/telegram-plugin/tests/permission-timeout.test.ts +26 -0
  71. package/telegram-plugin/tests/permission-verdict-resume-guard.test.ts +16 -0
  72. package/telegram-plugin/tests/photo-dimension-fallback.test.ts +129 -0
  73. package/telegram-plugin/tests/photo-precheck.test.ts +240 -0
  74. package/telegram-plugin/tests/photo-reroute-wiring.test.ts +85 -0
  75. package/telegram-plugin/tests/quota-watch.test.ts +225 -0
  76. package/telegram-plugin/tests/session-model-file.test.ts +101 -2
  77. package/telegram-plugin/tests/stop-command.test.ts +234 -0
  78. package/telegram-plugin/tests/subagent-watcher-env-thresholds.test.ts +27 -9
  79. package/telegram-plugin/tests/subagent-watcher-resurrection.test.ts +398 -0
  80. package/telegram-plugin/tests/subagent-watcher-stall-terminal.test.ts +172 -0
  81. package/telegram-plugin/tests/turn-flush-safety.test.ts +18 -4
  82. package/telegram-plugin/tests/vault-approval-posture.test.ts +15 -7
  83. package/telegram-plugin/tests/vault-grant-auto-resume.test.ts +8 -4
  84. package/telegram-plugin/tests/vault-grant-union.test.ts +8 -4
  85. package/telegram-plugin/tests/vault-grant-wizard.test.ts +8 -1
  86. package/telegram-plugin/tests/vault-grants-revoke.test.ts +8 -1
  87. package/telegram-plugin/tests/vault-key-regex-allows-slash.test.ts +8 -4
  88. package/telegram-plugin/tests/vault-request-access-tool.test.ts +8 -4
  89. package/telegram-plugin/tests/vault-request-access-unlock-resume.test.ts +8 -4
  90. package/telegram-plugin/tests/worker-activity-feed.test.ts +37 -0
  91. package/telegram-plugin/tests/worker-visibility-prose-silent-harness.test.ts +18 -4
  92. package/telegram-plugin/welcome-text.ts +4 -3
  93. package/telegram-plugin/worker-activity-feed.ts +27 -0
@@ -47,6 +47,7 @@ export function isValidEffortArg(arg: string): boolean {
47
47
  export type ParsedEffortCommand =
48
48
  | { kind: 'show' }
49
49
  | { kind: 'set'; level: EffortLevel }
50
+ | { kind: 'default' }
50
51
  | { kind: 'help'; reason?: string }
51
52
 
52
53
  /**
@@ -64,6 +65,9 @@ export function parseEffortCommand(text: string): ParsedEffortCommand | null {
64
65
  }
65
66
  const arg = parts[0]
66
67
  if (arg.toLowerCase() === 'help') return { kind: 'help' }
68
+ // `/effort default` — explicit user action that clears the durable
69
+ // `.session-effort` override and restores the configured default (#3039).
70
+ if (arg.toLowerCase() === 'default') return { kind: 'default' }
67
71
  if (!isValidEffortArg(arg)) {
68
72
  return { kind: 'help', reason: `not a valid effort level: ${arg}` }
69
73
  }
@@ -86,6 +90,17 @@ export interface EffortCommandDeps {
86
90
  * Null when unreadable — rendered as the built-in default.
87
91
  */
88
92
  getConfiguredEffort: () => string | null
93
+ /**
94
+ * Delete the durable `.session-effort` override (#3039). Optional so
95
+ * gateway-agnostic tests can omit it; the gateway always wires it.
96
+ */
97
+ clearSessionEffort?: () => void
98
+ /**
99
+ * The active durable `.session-effort` override level, or null when none
100
+ * (#3039). Optional; used to mark the LIVE level in the menu and the show
101
+ * text honestly after a restart re-applied the override.
102
+ */
103
+ getSessionEffort?: () => string | null
89
104
  escapeHtml: (s: string) => string
90
105
  }
91
106
 
@@ -95,7 +110,7 @@ export interface EffortCommandReply {
95
110
  }
96
111
 
97
112
  const PERSIST_NOTE =
98
- '_Session-onlyreverts to the configured default on restart. To change the default, set \`thinking_effort:\` in switchroom.yaml and restart._'
113
+ '_Stickypersists across restarts and deploys until \`/effort default\` clears it. To change the configured default, set \`thinking_effort:\` in switchroom.yaml._'
99
114
 
100
115
  const LEVELS_INLINE = EFFORT_LEVELS.map(l => `\`${l}\``).join(' · ')
101
116
 
@@ -106,6 +121,7 @@ function helpText(deps: EffortCommandDeps, reason?: string): EffortCommandReply
106
121
  '**/effort** — show or switch the reasoning effort (faster→smarter)',
107
122
  '\`/effort\` — show the configured effort + a tap menu',
108
123
  `\`/effort <level>\` — switch the live session (${LEVELS_INLINE})`,
124
+ '\`/effort default\` — clear the override, back to the configured default',
109
125
  PERSIST_NOTE,
110
126
  )
111
127
  return { text: lines.join('\n'), html: true }
@@ -117,13 +133,41 @@ export async function handleEffortCommand(
117
133
  ): Promise<EffortCommandReply> {
118
134
  if (parsed.kind === 'help') return helpText(deps, parsed.reason)
119
135
 
136
+ if (parsed.kind === 'default') {
137
+ // Explicit clear: restore the configured default level in the live
138
+ // session, THEN delete the durable override (order matters — the
139
+ // gateway's applyEffort wrapper re-persists on a confirmed apply, so
140
+ // clearing last leaves no file behind).
141
+ const configured = deps.getConfiguredEffort()
142
+ const restoreLevel = configured && isValidEffortArg(configured) ? configured.toLowerCase() : 'low'
143
+ let restored: EffortApplyResult | null = null
144
+ try {
145
+ restored = await deps.applyEffort(deps.getAgentName(), restoreLevel)
146
+ } catch {
147
+ restored = null
148
+ }
149
+ deps.clearSessionEffort?.()
150
+ const cfgHtml = `\`${deps.escapeHtml(restoreLevel)}\``
151
+ if (restored?.ok) {
152
+ return {
153
+ text: `✅ Effort override cleared — back on the configured default ${cfgHtml}. It will also boot on ${cfgHtml} from now on.`,
154
+ html: true,
155
+ }
156
+ }
157
+ return {
158
+ text: `✅ Effort override cleared — the agent boots on the configured default ${cfgHtml} from now on. (Couldn't switch the live session right now; it may already be on ${cfgHtml}, or will be after the next restart.)`,
159
+ html: true,
160
+ }
161
+ }
162
+
120
163
  if (parsed.kind === 'show') {
121
164
  const configured = deps.getConfiguredEffort()
122
165
  const shown = configured && configured.length > 0 ? configured : 'low'
166
+ const override = deps.getSessionEffort?.() ?? null
123
167
  return {
124
168
  text: [
125
169
  `**Effort — ${deps.escapeHtml(deps.getAgentName())}**`,
126
- `Configured default: \`${deps.escapeHtml(shown)}\``,
170
+ `Configured default: \`${deps.escapeHtml(shown)}\`${override ? ` · session override: \`${deps.escapeHtml(override)}\`` : ''}`,
127
171
  `Switch the live session: ${EFFORT_LEVELS.map(l => `\`/effort ${l}\``).join(' · ')}`,
128
172
  PERSIST_NOTE,
129
173
  ].join('\n'),
@@ -217,7 +261,7 @@ function menuKeyboard(highlight: string): EffortMenuKeyboardButton[][] {
217
261
  */
218
262
  export function buildEffortMenu(deps: EffortCommandDeps, highlight?: string): EffortMenuReply {
219
263
  const configured = deps.getConfiguredEffort() || 'low'
220
- const live = highlight ?? configured
264
+ const live = highlight ?? deps.getSessionEffort?.() ?? configured
221
265
  return {
222
266
  text: [
223
267
  `**Effort — ${deps.escapeHtml(deps.getAgentName())}**`,