switchroom 0.15.45 → 0.16.5
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 +56 -15
- package/dist/auth-broker/index.js +383 -97
- package/dist/cli/autoaccept-poll.js +4842 -35
- package/dist/cli/drive-write-pretool.mjs +7 -4
- package/dist/cli/notion-write-pretool.mjs +35 -4
- package/dist/cli/self-improve-apply-guard-pretool.mjs +626 -0
- package/dist/cli/self-improve-stop.mjs +428 -0
- package/dist/cli/switchroom.js +2894 -841
- package/dist/host-control/main.js +2685 -207
- package/dist/vault/approvals/kernel-server.js +7453 -7413
- package/dist/vault/broker/server.js +11428 -11388
- package/examples/minimal.yaml +1 -0
- package/examples/switchroom.yaml +1 -0
- package/package.json +3 -3
- package/profiles/_base/start.sh.hbs +97 -1
- package/profiles/_shared/execution-discipline.md.hbs +18 -0
- package/profiles/default/CLAUDE.md.hbs +0 -19
- package/telegram-plugin/.claude-plugin/plugin.json +2 -2
- package/telegram-plugin/answer-stream-flag.ts +12 -49
- package/telegram-plugin/answer-stream.ts +5 -150
- package/telegram-plugin/auth-snapshot-format.ts +280 -48
- package/telegram-plugin/auto-fallback-fleet.ts +44 -1
- package/telegram-plugin/context-exhaustion.ts +12 -0
- package/telegram-plugin/demo-mask.ts +154 -0
- package/telegram-plugin/dist/bridge/bridge.js +55 -12
- package/telegram-plugin/dist/gateway/gateway.js +2938 -977
- package/telegram-plugin/dist/server.js +55 -12
- package/telegram-plugin/docs/waiting-ux-spec.md +2 -2
- package/telegram-plugin/draft-stream.ts +47 -410
- package/telegram-plugin/final-answer-detect.ts +17 -12
- package/telegram-plugin/fleet-fallback-resume.ts +131 -0
- package/telegram-plugin/format.ts +56 -19
- package/telegram-plugin/gateway/auth-add-flow.ts +332 -127
- package/telegram-plugin/gateway/auth-broker-client.ts +2 -2
- package/telegram-plugin/gateway/auth-command.ts +70 -14
- package/telegram-plugin/gateway/clean-shutdown-marker.ts +44 -0
- package/telegram-plugin/gateway/config-approval-handler.test.ts +91 -4
- package/telegram-plugin/gateway/config-approval-handler.ts +94 -13
- package/telegram-plugin/gateway/current-turn-map.ts +188 -0
- package/telegram-plugin/gateway/disconnect-flush.ts +3 -1
- package/telegram-plugin/gateway/effort-command.ts +8 -3
- package/telegram-plugin/gateway/emission-authority.ts +369 -0
- package/telegram-plugin/gateway/feed-open-gate.ts +292 -0
- package/telegram-plugin/gateway/gateway.ts +1857 -292
- package/telegram-plugin/gateway/inject-handler.test.ts +2 -1
- package/telegram-plugin/gateway/model-command.ts +115 -4
- package/telegram-plugin/gateway/ms365-write-approval.test.ts +4 -4
- package/telegram-plugin/gateway/represent-guard.ts +72 -0
- package/telegram-plugin/gateway/status-surface-log.test.ts +5 -4
- package/telegram-plugin/gateway/status-surface-log.ts +14 -3
- package/telegram-plugin/history.ts +33 -11
- package/telegram-plugin/hooks/repo-context-pretool.mjs +26 -0
- package/telegram-plugin/hooks/subagent-tracker-posttool.mjs +5 -0
- package/telegram-plugin/hooks/subagent-tracker-pretool.mjs +8 -0
- package/telegram-plugin/hooks/tool-label-pretool.mjs +39 -15
- package/telegram-plugin/issues-card.ts +4 -0
- package/telegram-plugin/model-unavailable.ts +124 -0
- package/telegram-plugin/narrative-dedup.ts +69 -0
- package/telegram-plugin/over-ping-safety-net.ts +70 -4
- package/telegram-plugin/package.json +3 -3
- package/telegram-plugin/pending-work-progress.ts +12 -0
- package/telegram-plugin/permission-rule.ts +32 -5
- package/telegram-plugin/permission-title.ts +152 -9
- package/telegram-plugin/quota-check.ts +13 -0
- package/telegram-plugin/quota-watch.ts +135 -7
- package/telegram-plugin/registry/turns-schema.test.ts +24 -0
- package/telegram-plugin/registry/turns-schema.ts +9 -0
- package/telegram-plugin/runtime-metrics.ts +13 -0
- package/telegram-plugin/session-tail.ts +96 -11
- package/telegram-plugin/silence-poke.ts +170 -24
- package/telegram-plugin/slot-banner-driver.ts +3 -0
- package/telegram-plugin/status-no-truncate.ts +44 -0
- package/telegram-plugin/status-reactions.ts +20 -3
- package/telegram-plugin/stream-controller.ts +4 -23
- package/telegram-plugin/stream-reply-handler.ts +6 -24
- package/telegram-plugin/streaming-metrics.ts +91 -0
- package/telegram-plugin/subagent-watcher.ts +212 -66
- package/telegram-plugin/tests/activity-ever-opened-sticky.test.ts +47 -0
- package/telegram-plugin/tests/answer-stream-dedup.test.ts +9 -26
- package/telegram-plugin/tests/answer-stream-flag.test.ts +25 -58
- package/telegram-plugin/tests/answer-stream-silent-markers.test.ts +41 -51
- package/telegram-plugin/tests/answer-stream.test.ts +2 -411
- package/telegram-plugin/tests/auth-add-flow.test.ts +488 -253
- package/telegram-plugin/tests/auth-command-format2.test.ts +71 -1
- package/telegram-plugin/tests/auth-snapshot-format.test.ts +376 -6
- package/telegram-plugin/tests/auto-fallback-fleet.test.ts +120 -0
- package/telegram-plugin/tests/cross-turn-card-gate.test.ts +424 -0
- package/telegram-plugin/tests/demo-mask.test.ts +127 -0
- package/telegram-plugin/tests/draft-stream.test.ts +0 -827
- package/telegram-plugin/tests/emission-authority-card-drain-gate.test.ts +236 -0
- package/telegram-plugin/tests/emission-authority-facade.test.ts +488 -0
- package/telegram-plugin/tests/emission-authority-open-gate.test.ts +179 -0
- package/telegram-plugin/tests/emission-authority-ping-gate.test.ts +395 -0
- package/telegram-plugin/tests/emission-determinism-wiring.test.ts +177 -0
- package/telegram-plugin/tests/feed-heartbeat-liveness-open.test.ts +146 -0
- package/telegram-plugin/tests/feed-open-gate.test.ts +259 -0
- package/telegram-plugin/tests/feed-survival.test.ts +526 -0
- package/telegram-plugin/tests/fleet-fallback-resume.test.ts +197 -0
- package/telegram-plugin/tests/gateway-clean-shutdown-marker.test.ts +117 -0
- package/telegram-plugin/tests/gateway-no-reply-single-emit.test.ts +4 -11
- package/telegram-plugin/tests/history.test.ts +60 -0
- package/telegram-plugin/tests/model-command.test.ts +134 -0
- package/telegram-plugin/tests/model-unavailable.test.ts +118 -0
- package/telegram-plugin/tests/narrative-dedup.test.ts +118 -0
- package/telegram-plugin/tests/orphaned-reply-rearm.test.ts +285 -0
- package/telegram-plugin/tests/over-ping-final-answer-decoupling.test.ts +194 -0
- package/telegram-plugin/tests/over-ping-safety-net.test.ts +2 -2
- package/telegram-plugin/tests/per-topic-current-turn.test.ts +373 -0
- package/telegram-plugin/tests/permission-card-origin-kill-switch.test.ts +42 -0
- package/telegram-plugin/tests/permission-rule.test.ts +17 -0
- package/telegram-plugin/tests/permission-title.test.ts +206 -17
- package/telegram-plugin/tests/quota-watch.test.ts +252 -9
- package/telegram-plugin/tests/reply-terminal-reaction.test.ts +6 -1
- package/telegram-plugin/tests/repo-context-pretool.test.ts +62 -0
- package/telegram-plugin/tests/represent-guard.test.ts +162 -0
- package/telegram-plugin/tests/session-tail.test.ts +147 -3
- package/telegram-plugin/tests/silence-liveness-wiring.test.ts +18 -0
- package/telegram-plugin/tests/status-card-budget-parity.test.ts +72 -0
- package/telegram-plugin/tests/status-surface-log.test.ts +146 -0
- package/telegram-plugin/tests/subagent-watcher-clip-narrative.test.ts +58 -0
- package/telegram-plugin/tests/subagent-watcher-parent-turn-key.test.ts +102 -0
- package/telegram-plugin/tests/subagent-watcher-workflow-visibility.test.ts +225 -0
- package/telegram-plugin/tests/subagent-watcher.test.ts +147 -0
- package/telegram-plugin/tests/telegram-activity-visibility-integration.test.ts +597 -0
- package/telegram-plugin/tests/telegram-format.test.ts +101 -6
- package/telegram-plugin/tests/tool-activity-summary.test.ts +550 -15
- package/telegram-plugin/tests/tool-label-pretool.test.ts +73 -0
- package/telegram-plugin/tests/tool-label-sidecar.test.ts +44 -0
- package/telegram-plugin/tests/tool-labels.test.ts +67 -0
- package/telegram-plugin/tests/turn-liveness-floor.test.ts +196 -0
- package/telegram-plugin/tests/turn-liveness-invariant.test.ts +340 -0
- package/telegram-plugin/tests/welcome-text.test.ts +32 -3
- package/telegram-plugin/tests/worker-activity-feed.test.ts +470 -22
- package/telegram-plugin/tool-activity-summary.ts +375 -58
- package/telegram-plugin/turn-liveness-floor.ts +240 -0
- package/telegram-plugin/uat/assertions.ts +115 -0
- package/telegram-plugin/uat/driver.ts +68 -0
- package/telegram-plugin/uat/scenarios/bg-sub-agent-dispatch-dm.test.ts +119 -133
- package/telegram-plugin/uat/scenarios/jtbd-answer-pings.test.ts +94 -0
- package/telegram-plugin/uat/scenarios/jtbd-cross-turn-card-dm.test.ts +109 -0
- package/telegram-plugin/uat/scenarios/jtbd-foreground-feed-thinkgap-dm.test.ts +478 -0
- package/telegram-plugin/uat/scenarios/jtbd-foreground-feed-visibility-dm.test.ts +396 -0
- package/telegram-plugin/uat/scenarios/jtbd-liveness-feed-open-dm.test.ts +202 -0
- package/telegram-plugin/uat/scenarios/jtbd-reply-is-last-dm.test.ts +202 -0
- package/telegram-plugin/uat/scenarios/reactions-dm.test.ts +93 -87
- package/telegram-plugin/welcome-text.ts +13 -1
- package/telegram-plugin/worker-activity-feed.ts +157 -82
- package/telegram-plugin/draft-transport.ts +0 -122
- package/telegram-plugin/tests/draft-retirement-wiring.test.ts +0 -82
- package/telegram-plugin/tests/draft-transport.test.ts +0 -211
|
@@ -695,12 +695,57 @@ describe('repairEscapedWhitespace', () => {
|
|
|
695
695
|
expect(isLikelyTelegramHtml(repaired)).toBe(true)
|
|
696
696
|
})
|
|
697
697
|
|
|
698
|
-
test('
|
|
699
|
-
//
|
|
700
|
-
//
|
|
701
|
-
// a
|
|
702
|
-
const input = 'Real newline here\nand a literal \\n in
|
|
703
|
-
|
|
698
|
+
test('unescapes literal \\n in prose even when real newlines are present (mixed-message fix, #2456)', () => {
|
|
699
|
+
// The old implementation bailed entirely when any real newline was present.
|
|
700
|
+
// The new implementation unescapes literal \\n outside code spans regardless,
|
|
701
|
+
// so a mixed message (real newlines + stray literal \\n in prose) is repaired.
|
|
702
|
+
const input = 'Real newline here\nand a literal \\n escape in prose'
|
|
703
|
+
const out = repairEscapedWhitespace(input)
|
|
704
|
+
// The literal \n in prose becomes a real newline; the existing real newline is preserved.
|
|
705
|
+
expect(out).toBe('Real newline here\nand a literal \n escape in prose')
|
|
706
|
+
})
|
|
707
|
+
|
|
708
|
+
test('preserves literal \\n inside inline code span when mixed with real newlines (#2456)', () => {
|
|
709
|
+
// The structurally safe version: a \\n inside backticks must stay verbatim,
|
|
710
|
+
// even in a message that also has real newlines and literal \\n in prose.
|
|
711
|
+
const input = 'First line\nUse `grep -P \\n` for newlines\nand prose \\n here'
|
|
712
|
+
const out = repairEscapedWhitespace(input)
|
|
713
|
+
// Inline code span preserved verbatim (\\n inside backticks untouched).
|
|
714
|
+
expect(out).toContain('`grep -P \\n`')
|
|
715
|
+
// The literal \\n in prose is unescaped to a real newline.
|
|
716
|
+
expect(out).toContain('and prose \n here')
|
|
717
|
+
// The original real newlines are preserved.
|
|
718
|
+
expect(out).toContain('First line\n')
|
|
719
|
+
})
|
|
720
|
+
|
|
721
|
+
test('preserves literal \\n inside fenced code block (#2456)', () => {
|
|
722
|
+
// A fenced code block containing a literal \\n (e.g. a regex or shell snippet)
|
|
723
|
+
// must not be unescaped.
|
|
724
|
+
const input = 'Prose \\n here\n```bash\necho "line1\\nline2"\n```\nMore \\n prose'
|
|
725
|
+
const out = repairEscapedWhitespace(input)
|
|
726
|
+
// The \\n inside the fenced block stays verbatim.
|
|
727
|
+
expect(out).toContain('```bash\necho "line1\\nline2"\n```')
|
|
728
|
+
// The \\n in prose is unescaped.
|
|
729
|
+
expect(out).toContain('Prose \n here')
|
|
730
|
+
expect(out).toContain('More \n prose')
|
|
731
|
+
})
|
|
732
|
+
|
|
733
|
+
test('pure no-real-newline case still unescapes (backward compat)', () => {
|
|
734
|
+
// Original pre-#2456 case: message with NO real newlines and literal \\n.
|
|
735
|
+
const input = 'Line one\\nLine two\\nLine three'
|
|
736
|
+
expect(repairEscapedWhitespace(input)).toBe('Line one\nLine two\nLine three')
|
|
737
|
+
})
|
|
738
|
+
|
|
739
|
+
test('genuine escaped backslash (\\\\n) stays literal even in mixed-newline message (#2456)', () => {
|
|
740
|
+
// \\\\n in the source is the two-char sequence \\ then n — the user typed
|
|
741
|
+
// a backslash followed by the letter n, NOT a newline. The protect-\\
|
|
742
|
+
// phase must still work inside mixed messages.
|
|
743
|
+
const input = 'Windows path: C:\\\\temp\\\\file.txt\\nnext line\nreal newline too'
|
|
744
|
+
const out = repairEscapedWhitespace(input)
|
|
745
|
+
// The \\n becomes a real newline.
|
|
746
|
+
expect(out).toContain('C:\\temp\\file.txt\nnext line')
|
|
747
|
+
// The real newline is preserved.
|
|
748
|
+
expect(out).toContain('real newline too')
|
|
704
749
|
})
|
|
705
750
|
|
|
706
751
|
test('leaves single-line text alone when it has no escape sequences', () => {
|
|
@@ -740,6 +785,56 @@ describe('repairEscapedWhitespace', () => {
|
|
|
740
785
|
// Literal \n must not survive anywhere.
|
|
741
786
|
expect(html).not.toContain('\\n')
|
|
742
787
|
})
|
|
788
|
+
|
|
789
|
+
// ── Sentinel-collision safety (reviewer blocker) ─────────────────────────
|
|
790
|
+
|
|
791
|
+
test('does not produce "undefined" when input contains NUL-byte sequences (#2456)', () => {
|
|
792
|
+
// A per-call random nonce makes sentinel collision statistically impossible.
|
|
793
|
+
// Confirm that a message containing NUL bytes (which could match a hardcoded
|
|
794
|
+
// sentinel) is passed through safely rather than emitting literal "undefined".
|
|
795
|
+
// We craft a string that would have matched the OLD hardcoded sentinel \x00REPMASK0\x00
|
|
796
|
+
// to prove it no longer causes corruption.
|
|
797
|
+
const dangerous = 'hello \x00REPMASK0\x00 world \\n end'
|
|
798
|
+
const out = repairEscapedWhitespace(dangerous)
|
|
799
|
+
// Must not produce the string "undefined" in output.
|
|
800
|
+
expect(out).not.toContain('undefined')
|
|
801
|
+
// The \\n in prose must be unescaped.
|
|
802
|
+
expect(out).toContain(' end')
|
|
803
|
+
expect(out).not.toContain('\\n')
|
|
804
|
+
})
|
|
805
|
+
|
|
806
|
+
// ── Unclosed fenced block (reviewer major) ────────────────────────────────
|
|
807
|
+
|
|
808
|
+
test('handles unclosed fenced block gracefully: \\n in trailing content is still unescaped', () => {
|
|
809
|
+
// An unclosed ``` is not matched by the fenced-block regex (it requires a
|
|
810
|
+
// closing ```). Content after the unmatched opening is treated as prose, so
|
|
811
|
+
// literal \\n there gets unescaped — which is the least-surprising outcome
|
|
812
|
+
// for malformed input (the alternative would be silently swallowing content).
|
|
813
|
+
const input = 'Prose \\n here\n```bash\necho "line1\\nline2"\n'
|
|
814
|
+
const out = repairEscapedWhitespace(input)
|
|
815
|
+
// \\n in prose before the unclosed fence is unescaped.
|
|
816
|
+
expect(out).toContain('Prose \n here')
|
|
817
|
+
// The function must not throw and must return a string.
|
|
818
|
+
expect(typeof out).toBe('string')
|
|
819
|
+
})
|
|
820
|
+
|
|
821
|
+
// ── \\t and CRLF in mixed-newline messages (reviewer gaps) ────────────────
|
|
822
|
+
|
|
823
|
+
test('unescapes \\t in prose even when real newlines are also present (#2456)', () => {
|
|
824
|
+
const input = 'First line\nCol1\\tCol2\\tCol3\nthird'
|
|
825
|
+
const out = repairEscapedWhitespace(input)
|
|
826
|
+
expect(out).toContain('Col1\tCol2\tCol3')
|
|
827
|
+
expect(out).toContain('First line\n')
|
|
828
|
+
expect(out).toContain('\nthird')
|
|
829
|
+
})
|
|
830
|
+
|
|
831
|
+
test('unescapes \\r in prose when real newlines are also present (#2456)', () => {
|
|
832
|
+
// A message that mixes real newlines and a literal \\r escape in prose.
|
|
833
|
+
const input = 'First line\nsome \\r carriage return in prose'
|
|
834
|
+
const out = repairEscapedWhitespace(input)
|
|
835
|
+
expect(out).toContain('some \r carriage return in prose')
|
|
836
|
+
expect(out).toContain('First line\n')
|
|
837
|
+
})
|
|
743
838
|
})
|
|
744
839
|
|
|
745
840
|
// ---------------------------------------------------------------------------
|