switchroom 0.15.44 → 0.16.4

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 (150) hide show
  1. package/dist/agent-scheduler/index.js +122 -88
  2. package/dist/auth-broker/index.js +463 -177
  3. package/dist/cli/autoaccept-poll.js +4842 -35
  4. package/dist/cli/drive-write-pretool.mjs +17 -14
  5. package/dist/cli/notion-write-pretool.mjs +117 -86
  6. package/dist/cli/self-improve-apply-guard-pretool.mjs +626 -0
  7. package/dist/cli/self-improve-stop.mjs +428 -0
  8. package/dist/cli/skill-validate-pretool.mjs +72 -72
  9. package/dist/cli/switchroom.js +3249 -1241
  10. package/dist/cli/ui/index.html +1 -1
  11. package/dist/host-control/main.js +2833 -355
  12. package/dist/vault/approvals/kernel-server.js +7482 -7439
  13. package/dist/vault/broker/server.js +11315 -11272
  14. package/examples/minimal.yaml +1 -0
  15. package/examples/switchroom.yaml +1 -0
  16. package/package.json +3 -3
  17. package/profiles/_base/start.sh.hbs +88 -1
  18. package/profiles/_shared/execution-discipline.md.hbs +18 -0
  19. package/profiles/default/CLAUDE.md.hbs +3 -22
  20. package/telegram-plugin/.claude-plugin/plugin.json +2 -2
  21. package/telegram-plugin/answer-stream-flag.ts +12 -49
  22. package/telegram-plugin/answer-stream.ts +5 -150
  23. package/telegram-plugin/auth-snapshot-format.ts +280 -48
  24. package/telegram-plugin/auto-fallback-fleet.ts +44 -1
  25. package/telegram-plugin/context-exhaustion.ts +12 -0
  26. package/telegram-plugin/demo-mask.ts +154 -0
  27. package/telegram-plugin/dist/bridge/bridge.js +167 -124
  28. package/telegram-plugin/dist/gateway/gateway.js +3039 -1159
  29. package/telegram-plugin/dist/server.js +215 -172
  30. package/telegram-plugin/docs/waiting-ux-spec.md +2 -2
  31. package/telegram-plugin/draft-stream.ts +47 -410
  32. package/telegram-plugin/final-answer-detect.ts +17 -12
  33. package/telegram-plugin/fleet-fallback-resume.ts +131 -0
  34. package/telegram-plugin/format.ts +56 -19
  35. package/telegram-plugin/gateway/auth-add-flow.ts +332 -127
  36. package/telegram-plugin/gateway/auth-broker-client.ts +2 -2
  37. package/telegram-plugin/gateway/auth-command.ts +70 -14
  38. package/telegram-plugin/gateway/clean-shutdown-marker.ts +44 -0
  39. package/telegram-plugin/gateway/config-approval-handler.test.ts +91 -4
  40. package/telegram-plugin/gateway/config-approval-handler.ts +94 -13
  41. package/telegram-plugin/gateway/current-turn-map.ts +188 -0
  42. package/telegram-plugin/gateway/disconnect-flush.ts +3 -1
  43. package/telegram-plugin/gateway/effort-command.ts +8 -3
  44. package/telegram-plugin/gateway/emission-authority.ts +369 -0
  45. package/telegram-plugin/gateway/feed-open-gate.ts +292 -0
  46. package/telegram-plugin/gateway/gateway.ts +1837 -291
  47. package/telegram-plugin/gateway/inject-handler.test.ts +2 -1
  48. package/telegram-plugin/gateway/ms365-write-approval.test.ts +4 -4
  49. package/telegram-plugin/gateway/represent-guard.ts +72 -0
  50. package/telegram-plugin/gateway/status-surface-log.test.ts +5 -4
  51. package/telegram-plugin/gateway/status-surface-log.ts +14 -3
  52. package/telegram-plugin/history.ts +33 -11
  53. package/telegram-plugin/hooks/repo-context-pretool.mjs +26 -0
  54. package/telegram-plugin/hooks/subagent-tracker-posttool.mjs +5 -0
  55. package/telegram-plugin/hooks/subagent-tracker-pretool.mjs +8 -0
  56. package/telegram-plugin/hooks/tool-label-pretool.mjs +39 -15
  57. package/telegram-plugin/issues-card.ts +4 -0
  58. package/telegram-plugin/model-unavailable.ts +124 -0
  59. package/telegram-plugin/narrative-dedup.ts +69 -0
  60. package/telegram-plugin/over-ping-safety-net.ts +70 -4
  61. package/telegram-plugin/package.json +3 -3
  62. package/telegram-plugin/pending-work-progress.ts +12 -0
  63. package/telegram-plugin/permission-rule.ts +32 -5
  64. package/telegram-plugin/permission-title.ts +152 -9
  65. package/telegram-plugin/quota-check.ts +13 -0
  66. package/telegram-plugin/quota-watch.ts +135 -7
  67. package/telegram-plugin/registry/turns-schema.test.ts +24 -0
  68. package/telegram-plugin/registry/turns-schema.ts +9 -0
  69. package/telegram-plugin/runtime-metrics.ts +13 -0
  70. package/telegram-plugin/session-tail.ts +96 -11
  71. package/telegram-plugin/silence-poke.ts +170 -24
  72. package/telegram-plugin/slot-banner-driver.ts +3 -0
  73. package/telegram-plugin/status-no-truncate.ts +44 -0
  74. package/telegram-plugin/status-reactions.ts +20 -3
  75. package/telegram-plugin/stream-controller.ts +4 -23
  76. package/telegram-plugin/stream-reply-handler.ts +6 -24
  77. package/telegram-plugin/streaming-metrics.ts +91 -0
  78. package/telegram-plugin/subagent-watcher.ts +212 -66
  79. package/telegram-plugin/tests/activity-ever-opened-sticky.test.ts +47 -0
  80. package/telegram-plugin/tests/answer-stream-dedup.test.ts +9 -26
  81. package/telegram-plugin/tests/answer-stream-flag.test.ts +25 -58
  82. package/telegram-plugin/tests/answer-stream-silent-markers.test.ts +41 -51
  83. package/telegram-plugin/tests/answer-stream.test.ts +2 -411
  84. package/telegram-plugin/tests/auth-add-flow.test.ts +488 -253
  85. package/telegram-plugin/tests/auth-command-format2.test.ts +71 -1
  86. package/telegram-plugin/tests/auth-snapshot-format.test.ts +376 -6
  87. package/telegram-plugin/tests/auto-fallback-fleet.test.ts +120 -0
  88. package/telegram-plugin/tests/cross-turn-card-gate.test.ts +424 -0
  89. package/telegram-plugin/tests/demo-mask.test.ts +127 -0
  90. package/telegram-plugin/tests/draft-stream.test.ts +0 -827
  91. package/telegram-plugin/tests/emission-authority-card-drain-gate.test.ts +236 -0
  92. package/telegram-plugin/tests/emission-authority-facade.test.ts +488 -0
  93. package/telegram-plugin/tests/emission-authority-open-gate.test.ts +179 -0
  94. package/telegram-plugin/tests/emission-authority-ping-gate.test.ts +395 -0
  95. package/telegram-plugin/tests/emission-determinism-wiring.test.ts +177 -0
  96. package/telegram-plugin/tests/feed-heartbeat-liveness-open.test.ts +146 -0
  97. package/telegram-plugin/tests/feed-open-gate.test.ts +259 -0
  98. package/telegram-plugin/tests/feed-survival.test.ts +526 -0
  99. package/telegram-plugin/tests/fleet-fallback-resume.test.ts +197 -0
  100. package/telegram-plugin/tests/gateway-clean-shutdown-marker.test.ts +117 -0
  101. package/telegram-plugin/tests/gateway-no-reply-single-emit.test.ts +4 -11
  102. package/telegram-plugin/tests/history.test.ts +60 -0
  103. package/telegram-plugin/tests/model-unavailable.test.ts +118 -0
  104. package/telegram-plugin/tests/narrative-dedup.test.ts +118 -0
  105. package/telegram-plugin/tests/orphaned-reply-rearm.test.ts +285 -0
  106. package/telegram-plugin/tests/over-ping-final-answer-decoupling.test.ts +194 -0
  107. package/telegram-plugin/tests/over-ping-safety-net.test.ts +2 -2
  108. package/telegram-plugin/tests/per-topic-current-turn.test.ts +373 -0
  109. package/telegram-plugin/tests/permission-card-origin-kill-switch.test.ts +42 -0
  110. package/telegram-plugin/tests/permission-rule.test.ts +17 -0
  111. package/telegram-plugin/tests/permission-title.test.ts +206 -17
  112. package/telegram-plugin/tests/quota-watch.test.ts +252 -9
  113. package/telegram-plugin/tests/reply-terminal-reaction.test.ts +6 -1
  114. package/telegram-plugin/tests/repo-context-pretool.test.ts +62 -0
  115. package/telegram-plugin/tests/represent-guard.test.ts +162 -0
  116. package/telegram-plugin/tests/session-tail.test.ts +147 -3
  117. package/telegram-plugin/tests/silence-liveness-wiring.test.ts +18 -0
  118. package/telegram-plugin/tests/status-card-budget-parity.test.ts +72 -0
  119. package/telegram-plugin/tests/status-surface-log.test.ts +146 -0
  120. package/telegram-plugin/tests/subagent-watcher-clip-narrative.test.ts +58 -0
  121. package/telegram-plugin/tests/subagent-watcher-parent-turn-key.test.ts +102 -0
  122. package/telegram-plugin/tests/subagent-watcher-workflow-visibility.test.ts +225 -0
  123. package/telegram-plugin/tests/subagent-watcher.test.ts +147 -0
  124. package/telegram-plugin/tests/telegram-activity-visibility-integration.test.ts +597 -0
  125. package/telegram-plugin/tests/telegram-format.test.ts +101 -6
  126. package/telegram-plugin/tests/tool-activity-summary.test.ts +550 -15
  127. package/telegram-plugin/tests/tool-label-pretool.test.ts +73 -0
  128. package/telegram-plugin/tests/tool-label-sidecar.test.ts +44 -0
  129. package/telegram-plugin/tests/tool-labels.test.ts +67 -0
  130. package/telegram-plugin/tests/turn-liveness-floor.test.ts +196 -0
  131. package/telegram-plugin/tests/turn-liveness-invariant.test.ts +340 -0
  132. package/telegram-plugin/tests/welcome-text.test.ts +32 -3
  133. package/telegram-plugin/tests/worker-activity-feed.test.ts +470 -22
  134. package/telegram-plugin/tool-activity-summary.ts +375 -58
  135. package/telegram-plugin/turn-liveness-floor.ts +240 -0
  136. package/telegram-plugin/uat/assertions.ts +115 -0
  137. package/telegram-plugin/uat/driver.ts +68 -0
  138. package/telegram-plugin/uat/scenarios/bg-sub-agent-dispatch-dm.test.ts +119 -133
  139. package/telegram-plugin/uat/scenarios/jtbd-answer-pings.test.ts +94 -0
  140. package/telegram-plugin/uat/scenarios/jtbd-cross-turn-card-dm.test.ts +109 -0
  141. package/telegram-plugin/uat/scenarios/jtbd-foreground-feed-thinkgap-dm.test.ts +478 -0
  142. package/telegram-plugin/uat/scenarios/jtbd-foreground-feed-visibility-dm.test.ts +396 -0
  143. package/telegram-plugin/uat/scenarios/jtbd-liveness-feed-open-dm.test.ts +202 -0
  144. package/telegram-plugin/uat/scenarios/jtbd-reply-is-last-dm.test.ts +202 -0
  145. package/telegram-plugin/uat/scenarios/reactions-dm.test.ts +93 -87
  146. package/telegram-plugin/welcome-text.ts +13 -1
  147. package/telegram-plugin/worker-activity-feed.ts +157 -82
  148. package/telegram-plugin/draft-transport.ts +0 -122
  149. package/telegram-plugin/tests/draft-retirement-wiring.test.ts +0 -82
  150. package/telegram-plugin/tests/draft-transport.test.ts +0 -211
@@ -1,211 +0,0 @@
1
- /**
2
- * Unit tests for draft-transport.ts — shared regex constants and
3
- * shouldFallbackFromDraftTransport helper.
4
- */
5
- import { describe, it, expect, beforeEach } from 'vitest'
6
- import {
7
- DRAFT_METHOD_UNAVAILABLE_RE,
8
- DRAFT_CHAT_UNSUPPORTED_RE,
9
- shouldFallbackFromDraftTransport,
10
- allocateDraftId,
11
- __resetDraftIdForTests,
12
- extractDraft429RetryAfterSecs,
13
- isDraft429,
14
- } from '../draft-transport.js'
15
-
16
- describe('DRAFT_METHOD_UNAVAILABLE_RE', () => {
17
- it('matches "unknown method"', () => {
18
- expect(DRAFT_METHOD_UNAVAILABLE_RE.test('unknown method sendMessageDraft')).toBe(true)
19
- })
20
-
21
- it('matches "method not found"', () => {
22
- expect(DRAFT_METHOD_UNAVAILABLE_RE.test('method sendMessageDraft not found')).toBe(true)
23
- })
24
-
25
- it('matches "method not available"', () => {
26
- expect(DRAFT_METHOD_UNAVAILABLE_RE.test('method is not available')).toBe(true)
27
- })
28
-
29
- it('matches "method not supported"', () => {
30
- expect(DRAFT_METHOD_UNAVAILABLE_RE.test('method not supported')).toBe(true)
31
- })
32
-
33
- it('matches "unsupported"', () => {
34
- expect(DRAFT_METHOD_UNAVAILABLE_RE.test('unsupported')).toBe(true)
35
- })
36
-
37
- it('is case-insensitive', () => {
38
- expect(DRAFT_METHOD_UNAVAILABLE_RE.test('UNKNOWN METHOD')).toBe(true)
39
- })
40
-
41
- it('does NOT match unrelated errors', () => {
42
- expect(DRAFT_METHOD_UNAVAILABLE_RE.test('network timeout')).toBe(false)
43
- expect(DRAFT_METHOD_UNAVAILABLE_RE.test('chat not found')).toBe(false)
44
- })
45
- })
46
-
47
- describe('DRAFT_CHAT_UNSUPPORTED_RE', () => {
48
- it('matches "can\'t be used"', () => {
49
- expect(DRAFT_CHAT_UNSUPPORTED_RE.test("sendMessageDraft can't be used in this type of chat")).toBe(true)
50
- })
51
-
52
- it('matches "can be used only"', () => {
53
- expect(DRAFT_CHAT_UNSUPPORTED_RE.test('sendMessageDraft can be used only in private chats')).toBe(true)
54
- })
55
-
56
- it('is case-insensitive', () => {
57
- expect(DRAFT_CHAT_UNSUPPORTED_RE.test("CAN'T BE USED")).toBe(true)
58
- })
59
-
60
- it('does NOT match unrelated errors', () => {
61
- expect(DRAFT_CHAT_UNSUPPORTED_RE.test('message not found')).toBe(false)
62
- expect(DRAFT_CHAT_UNSUPPORTED_RE.test('forbidden')).toBe(false)
63
- })
64
- })
65
-
66
- describe('shouldFallbackFromDraftTransport', () => {
67
- it('returns false when error text does not mention sendMessageDraft', () => {
68
- expect(shouldFallbackFromDraftTransport(new Error('unknown method'))).toBe(false)
69
- expect(shouldFallbackFromDraftTransport(new Error('unsupported feature'))).toBe(false)
70
- })
71
-
72
- it('returns true for DRAFT_METHOD_UNAVAILABLE_RE with sendMessageDraft in message', () => {
73
- expect(shouldFallbackFromDraftTransport(
74
- new Error('sendMessageDraft: unknown method'),
75
- )).toBe(true)
76
- expect(shouldFallbackFromDraftTransport(
77
- new Error('400: sendMessageDraft method not found'),
78
- )).toBe(true)
79
- })
80
-
81
- it('returns true for DRAFT_CHAT_UNSUPPORTED_RE with sendMessageDraft in message', () => {
82
- expect(shouldFallbackFromDraftTransport(
83
- new Error("sendMessageDraft can't be used in group chats"),
84
- )).toBe(true)
85
- expect(shouldFallbackFromDraftTransport(
86
- new Error('sendMessageDraft can be used only in private chats'),
87
- )).toBe(true)
88
- })
89
-
90
- it('accepts a plain string as the error', () => {
91
- expect(shouldFallbackFromDraftTransport('sendMessageDraft: unknown method')).toBe(true)
92
- expect(shouldFallbackFromDraftTransport('network error')).toBe(false)
93
- })
94
-
95
- it('accepts an object with a description field', () => {
96
- expect(shouldFallbackFromDraftTransport({
97
- description: 'sendMessageDraft: unknown method',
98
- })).toBe(true)
99
- expect(shouldFallbackFromDraftTransport({
100
- description: 'sendMessageDraft can be used only in DMs',
101
- })).toBe(true)
102
- })
103
-
104
- it('returns false for null / undefined / unrelated objects', () => {
105
- expect(shouldFallbackFromDraftTransport(null)).toBe(false)
106
- expect(shouldFallbackFromDraftTransport(undefined)).toBe(false)
107
- expect(shouldFallbackFromDraftTransport(42)).toBe(false)
108
- expect(shouldFallbackFromDraftTransport({})).toBe(false)
109
- })
110
-
111
- it('returns false when sendMessageDraft is in message but pattern does not match', () => {
112
- expect(shouldFallbackFromDraftTransport(
113
- new Error('sendMessageDraft: rate limited'),
114
- )).toBe(false)
115
- expect(shouldFallbackFromDraftTransport(
116
- new Error('sendMessageDraft: internal server error'),
117
- )).toBe(false)
118
- })
119
- })
120
-
121
- describe('allocateDraftId', () => {
122
- beforeEach(() => {
123
- __resetDraftIdForTests()
124
- })
125
-
126
- it('allocates incrementing ids starting at 1', () => {
127
- expect(allocateDraftId()).toBe(1)
128
- expect(allocateDraftId()).toBe(2)
129
- expect(allocateDraftId()).toBe(3)
130
- })
131
-
132
- it('wraps at 2_147_483_647 back to 1', () => {
133
- // Manually set the counter near max via multiple allocations would be too slow.
134
- // Instead, use the global state directly.
135
- const g = globalThis as Record<PropertyKey, unknown>
136
- const key = Symbol.for('switchroom.draftStreamState')
137
- const state = g[key] as { nextDraftId: number }
138
- state.nextDraftId = 2_147_483_647 - 1
139
- expect(allocateDraftId()).toBe(2_147_483_647)
140
- // Next should wrap
141
- expect(allocateDraftId()).toBe(1)
142
- })
143
- })
144
-
145
- // ─── PR D: 429 + non-True helpers ──────────────────────────────────────
146
-
147
- describe('extractDraft429RetryAfterSecs (PR D)', () => {
148
- it('returns retry_after on a grammY 429', () => {
149
- const err = { error_code: 429, parameters: { retry_after: 7 } }
150
- expect(extractDraft429RetryAfterSecs(err)).toBe(7)
151
- })
152
-
153
- it('returns null on non-429 error_code', () => {
154
- const err = { error_code: 400, parameters: { retry_after: 7 } }
155
- expect(extractDraft429RetryAfterSecs(err)).toBeNull()
156
- })
157
-
158
- it('returns null when retry_after is missing', () => {
159
- const err = { error_code: 429 }
160
- expect(extractDraft429RetryAfterSecs(err)).toBeNull()
161
- })
162
-
163
- it('returns null when retry_after is non-positive', () => {
164
- expect(extractDraft429RetryAfterSecs({ error_code: 429, parameters: { retry_after: 0 } })).toBeNull()
165
- expect(extractDraft429RetryAfterSecs({ error_code: 429, parameters: { retry_after: -1 } })).toBeNull()
166
- })
167
-
168
- it('returns null on primitive errors', () => {
169
- expect(extractDraft429RetryAfterSecs(null)).toBeNull()
170
- expect(extractDraft429RetryAfterSecs(undefined)).toBeNull()
171
- expect(extractDraft429RetryAfterSecs('boom')).toBeNull()
172
- expect(extractDraft429RetryAfterSecs(42)).toBeNull()
173
- })
174
- })
175
-
176
- describe('isDraft429 (PR D)', () => {
177
- it('returns true when 429 carries method=sendMessageDraft', () => {
178
- const err = {
179
- error_code: 429,
180
- parameters: { retry_after: 5 },
181
- method: 'sendMessageDraft',
182
- }
183
- expect(isDraft429(err)).toBe(true)
184
- })
185
-
186
- it('returns true when 429 description mentions sendMessageDraft', () => {
187
- const err = {
188
- error_code: 429,
189
- parameters: { retry_after: 5 },
190
- description: 'sendMessageDraft: Too Many Requests: retry after 5',
191
- }
192
- expect(isDraft429(err)).toBe(true)
193
- })
194
-
195
- it('returns false on 429 from a different method', () => {
196
- const err = {
197
- error_code: 429,
198
- parameters: { retry_after: 5 },
199
- method: 'sendMessage',
200
- }
201
- expect(isDraft429(err)).toBe(false)
202
- })
203
-
204
- it('returns false on non-429 errors even when mentioning sendMessageDraft', () => {
205
- const err = {
206
- error_code: 400,
207
- description: 'sendMessageDraft: bad request',
208
- }
209
- expect(isDraft429(err)).toBe(false)
210
- })
211
- })