switchroom 0.19.18 → 0.19.19
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 +2 -1
- package/dist/auth-broker/index.js +3 -1
- package/dist/cli/drive-write-pretool.mjs +48 -5
- package/dist/cli/ms-365-write-pretool.mjs +40 -2
- package/dist/cli/notion-write-pretool.mjs +2 -1
- package/dist/cli/switchroom.js +3392 -1569
- package/dist/host-control/main.js +12209 -11396
- package/dist/vault/approvals/kernel-server.js +60 -7
- package/dist/vault/broker/server.js +206 -76
- package/package.json +4 -3
- package/profiles/_base/start.sh.hbs +61 -1
- package/telegram-plugin/bridge/bridge.ts +14 -0
- package/telegram-plugin/dist/bridge/bridge.js +13 -0
- package/telegram-plugin/dist/gateway/gateway.js +1644 -1044
- package/telegram-plugin/dist/server.js +13 -0
- package/telegram-plugin/gateway/always-allow-persist-queue.ts +97 -11
- package/telegram-plugin/gateway/missed-approvals-store.ts +66 -17
- package/telegram-plugin/gateway/pending-card-store.ts +46 -16
- package/telegram-plugin/gateway/scoped-grant-store.ts +39 -14
- package/telegram-plugin/gateway/store-file.ts +244 -0
- package/telegram-plugin/hooks/tool-label-pretool.mjs +88 -2
- package/telegram-plugin/tests/bridge-tool-parity.test.ts +95 -0
- package/telegram-plugin/tests/store-atomic-write.test.ts +411 -0
- package/telegram-plugin/tests/tool-activity-summary.test.ts +9 -2
- package/telegram-plugin/tests/tool-label-pretool.test.ts +94 -0
- package/telegram-plugin/tests/worker-feed-repeat-steps.test.ts +147 -0
- package/telegram-plugin/worker-activity-feed.ts +51 -1
- package/vendor/hindsight-memory/scripts/drain_pending.py +668 -56
- package/vendor/hindsight-memory/scripts/lib/client.py +124 -0
- package/vendor/hindsight-memory/scripts/lib/pending.py +865 -33
- package/vendor/hindsight-memory/scripts/lib/retain_split.py +449 -0
- package/vendor/hindsight-memory/scripts/session_start.py +48 -0
- package/vendor/hindsight-memory/scripts/tests/test_client_document_exists.py +470 -0
- package/vendor/hindsight-memory/scripts/tests/test_pending_drops.py +2121 -0
- package/vendor/hindsight-memory/scripts/tests/test_retain_split.py +430 -0
- package/vendor/hindsight-memory/scripts/tests/test_session_start_version_skew.py +204 -0
- package/vendor/hindsight-memory/tests/test_drain_pending.py +102 -6
- package/vendor/hindsight-memory/tests/test_pending.py +32 -7
|
@@ -142,6 +142,25 @@ export interface BotApiForWorkerFeed {
|
|
|
142
142
|
/** Dispatch-time task description cap for the worker header. */
|
|
143
143
|
const DESC_MAX = 80
|
|
144
144
|
|
|
145
|
+
/**
|
|
146
|
+
* Repeat marker appended to a narrative step that fired more than once in a
|
|
147
|
+
* row (`Running a command ·×3`). Rendered inline on the step line so a worker
|
|
148
|
+
* whose every step carries the SAME label still visibly advances instead of
|
|
149
|
+
* freezing the card. `·` is already the card's separator glyph.
|
|
150
|
+
*/
|
|
151
|
+
const REPEAT_SUFFIX_RE = / ·×(\d+)$/
|
|
152
|
+
|
|
153
|
+
/** The step text without its `·×N` marker (identity for dedup comparisons). */
|
|
154
|
+
export function stripRepeatSuffix(line: string): string {
|
|
155
|
+
return line.replace(REPEAT_SUFFIX_RE, '')
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/** How many times a step line has fired: 1 when it carries no marker. */
|
|
159
|
+
export function repeatCountOf(line: string): number {
|
|
160
|
+
const m = REPEAT_SUFFIX_RE.exec(line)
|
|
161
|
+
return m == null ? 1 : Number(m[1])
|
|
162
|
+
}
|
|
163
|
+
|
|
145
164
|
/**
|
|
146
165
|
* Thin adapter over the unified `renderStatusCard` primitive (emoji 🛠, label
|
|
147
166
|
* 'Worker'): builds the header, passes raw narrative steps (the primitive runs
|
|
@@ -428,6 +447,13 @@ interface WorkerRow {
|
|
|
428
447
|
* live render so the feed reads like the main agent's answer.
|
|
429
448
|
*/
|
|
430
449
|
narrative: string[]
|
|
450
|
+
/**
|
|
451
|
+
* `view.toolCount` observed when the newest narrative step was last recorded
|
|
452
|
+
* or counted. The repeat counter (`·×N`) increments only when toolCount has
|
|
453
|
+
* MOVED — the watcher re-emits an unchanged view every tick, so counting
|
|
454
|
+
* label-equality alone would inflate the number with no work behind it.
|
|
455
|
+
*/
|
|
456
|
+
lastNarrativeToolCount: number | null
|
|
431
457
|
/** Last view for this worker (drives the heartbeat re-render + combined row). */
|
|
432
458
|
lastView: WorkerActivityView | null
|
|
433
459
|
/** Latest state observed for this worker; excluded from the running set once
|
|
@@ -794,10 +820,33 @@ export function createWorkerActivityFeed(opts: WorkerActivityFeedOpts): WorkerAc
|
|
|
794
820
|
function accumulateNarrative(row: WorkerRow, view: WorkerActivityView): void {
|
|
795
821
|
const line = view.latestSummary.trim()
|
|
796
822
|
if (line.length === 0) return
|
|
823
|
+
|
|
824
|
+
// A REPEAT of the current step is counted, not dropped. A worker whose
|
|
825
|
+
// steps all render the same label (e.g. Bash calls with no description →
|
|
826
|
+
// "Running a command") used to hit the dedup below on every tool call and
|
|
827
|
+
// the card held ONE frozen line for the whole job — indistinguishable from
|
|
828
|
+
// a wedged worker. `·×N` makes the repetition visible and, because a new
|
|
829
|
+
// count resets stepStartedAtMs, the climbing `· Ns` step timer restarts
|
|
830
|
+
// with each real call.
|
|
831
|
+
//
|
|
832
|
+
// Gated on `view.toolCount`, NOT on the label: the watcher re-emits an
|
|
833
|
+
// UNCHANGED view on every tick, so counting label-equality alone would
|
|
834
|
+
// inflate the number with no work behind it. One increment per observed
|
|
835
|
+
// tool call, deterministically.
|
|
836
|
+
const last = row.narrative.length > 0 ? row.narrative[row.narrative.length - 1] : null
|
|
837
|
+
if (last != null && stripRepeatSuffix(last) === line) {
|
|
838
|
+
if (view.toolCount === row.lastNarrativeToolCount) return
|
|
839
|
+
row.lastNarrativeToolCount = view.toolCount
|
|
840
|
+
row.narrative[row.narrative.length - 1] = `${line} ·×${repeatCountOf(last) + 1}`
|
|
841
|
+
row.stepStartedAtMs = nowFn()
|
|
842
|
+
return
|
|
843
|
+
}
|
|
844
|
+
|
|
797
845
|
// Dedup within the whole rolling window (the watcher re-emits the same
|
|
798
846
|
// narrative across ticks, and a preamble + its tool label can repeat
|
|
799
847
|
// non-adjacently — the A,B,A duplication observed on live cards).
|
|
800
|
-
if (row.narrative.
|
|
848
|
+
if (row.narrative.some((l) => stripRepeatSuffix(l) === line)) return
|
|
849
|
+
row.lastNarrativeToolCount = view.toolCount
|
|
801
850
|
row.narrative.push(line)
|
|
802
851
|
// The `→` current-step line just CHANGED — reset the per-step timer.
|
|
803
852
|
row.stepStartedAtMs = nowFn()
|
|
@@ -1545,6 +1594,7 @@ export function createWorkerActivityFeed(opts: WorkerActivityFeedOpts): WorkerAc
|
|
|
1545
1594
|
agentId,
|
|
1546
1595
|
ordinal: ++g.workerOrdinalCounter,
|
|
1547
1596
|
narrative: [],
|
|
1597
|
+
lastNarrativeToolCount: null,
|
|
1548
1598
|
lastView: null,
|
|
1549
1599
|
state: 'running',
|
|
1550
1600
|
finished: false,
|