clisbot 0.1.45-beta.7 → 0.1.45-beta.8
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/README.md +1 -1
- package/dist/main.js +215 -154
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -139,7 +139,7 @@ Need the step-by-step setup docs instead of the shortest path?
|
|
|
139
139
|
|
|
140
140
|
- Telegram: [Telegram Bot Setup](docs/user-guide/telegram-setup.md)
|
|
141
141
|
- Slack: [Slack App Setup](docs/user-guide/slack-setup.md)
|
|
142
|
-
- Release history: [CHANGELOG.md](CHANGELOG.md), [release notes](docs/releases/README.md), [update guide](docs/update
|
|
142
|
+
- Release history: [CHANGELOG.md](CHANGELOG.md), [release notes](docs/releases/README.md), [update guide](docs/updates/update-guide.md), [release guides](docs/updates/README.md), and [migration index](docs/migrations/index.md)
|
|
143
143
|
- Slack app manifest template: [app-manifest.json](templates/slack/default/app-manifest.json)
|
|
144
144
|
- Slack app manifest guide: [app-manifest-guide.md](templates/slack/default/app-manifest-guide.md)
|
|
145
145
|
|
package/dist/main.js
CHANGED
|
@@ -54803,7 +54803,7 @@ function renderCliHelp() {
|
|
|
54803
54803
|
" status Show runtime process, config, log, tmux socket status, and recent runner sessions.",
|
|
54804
54804
|
" version Show the installed clisbot version.",
|
|
54805
54805
|
" logs Print the most recent clisbot log lines.",
|
|
54806
|
-
" update Print the
|
|
54806
|
+
" update Print the update guide and release/migration doc links.",
|
|
54807
54807
|
` See ${renderCliCommand("update --help", { inline: true })} before asking an agent to update clisbot.`,
|
|
54808
54808
|
" timezone Manage the app-wide wall-clock timezone used by schedules and loops.",
|
|
54809
54809
|
` See ${renderCliCommand("timezone --help", { inline: true })} for override guidance.`,
|
|
@@ -66541,19 +66541,6 @@ class AgentSessionState {
|
|
|
66541
66541
|
agentId: target.agentId
|
|
66542
66542
|
};
|
|
66543
66543
|
}
|
|
66544
|
-
async listActiveSessionRuntimes() {
|
|
66545
|
-
const entries = await this.sessionStore.list();
|
|
66546
|
-
return entries.filter(hasActiveRuntime).map((entry) => ({
|
|
66547
|
-
state: entry.runtime.state,
|
|
66548
|
-
startedAt: entry.runtime.startedAt,
|
|
66549
|
-
detachedAt: entry.runtime.detachedAt,
|
|
66550
|
-
finalReplyAt: entry.runtime.finalReplyAt,
|
|
66551
|
-
lastMessageToolReplyAt: entry.runtime.lastMessageToolReplyAt,
|
|
66552
|
-
messageToolFinalReplyAt: entry.runtime.messageToolFinalReplyAt,
|
|
66553
|
-
sessionKey: entry.sessionKey,
|
|
66554
|
-
agentId: entry.agentId
|
|
66555
|
-
}));
|
|
66556
|
-
}
|
|
66557
66544
|
async listIntervalLoops(params) {
|
|
66558
66545
|
const entries = await this.sessionStore.list();
|
|
66559
66546
|
return entries.flatMap((entry) => getStoredLoops(entry).filter((loop) => !params?.sessionKey || entry.sessionKey === params.sessionKey).map((loop) => ({
|
|
@@ -66811,6 +66798,10 @@ class AgentSessionState {
|
|
|
66811
66798
|
const entry = await this.sessionStore.get(sessionKey);
|
|
66812
66799
|
return getStoredQueues(entry).some((item) => item.status === "pending" || item.status === "running");
|
|
66813
66800
|
}
|
|
66801
|
+
async hasQueuedItem(sessionKey, queueId) {
|
|
66802
|
+
const entry = await this.sessionStore.get(sessionKey);
|
|
66803
|
+
return getStoredQueues(entry).some((item) => item.id === queueId);
|
|
66804
|
+
}
|
|
66814
66805
|
async resetStaleRunningQueuedItems(activeSessionKeys) {
|
|
66815
66806
|
const entries = await this.sessionStore.list();
|
|
66816
66807
|
let reset = 0;
|
|
@@ -66891,9 +66882,6 @@ function getStoredLoops(entry) {
|
|
|
66891
66882
|
function getStoredQueues(entry) {
|
|
66892
66883
|
return entry?.queues ?? [];
|
|
66893
66884
|
}
|
|
66894
|
-
function hasActiveRuntime(entry) {
|
|
66895
|
-
return entry.runtime?.state === "running" || entry.runtime?.state === "detached";
|
|
66896
|
-
}
|
|
66897
66885
|
|
|
66898
66886
|
// src/agents/session-key.ts
|
|
66899
66887
|
var DEFAULT_MAIN_KEY = "main";
|
|
@@ -67146,39 +67134,15 @@ class AgentJobQueue {
|
|
|
67146
67134
|
if (!state) {
|
|
67147
67135
|
return 0;
|
|
67148
67136
|
}
|
|
67149
|
-
|
|
67150
|
-
const removedEntries = state.entries.filter((entry) => entry.status === "pending");
|
|
67151
|
-
state.entries = keptEntries;
|
|
67152
|
-
for (const entry of removedEntries) {
|
|
67153
|
-
Promise.resolve(entry.lifecycle?.onClear?.()).catch(() => {
|
|
67154
|
-
return;
|
|
67155
|
-
});
|
|
67156
|
-
entry.reject(new ClearedQueuedTaskError);
|
|
67157
|
-
}
|
|
67158
|
-
if (state.entries.length === 0 && !state.running) {
|
|
67159
|
-
this.states.delete(key);
|
|
67160
|
-
}
|
|
67161
|
-
return removedEntries.length;
|
|
67137
|
+
return this.clearPendingEntriesForState(key, state, () => true);
|
|
67162
67138
|
}
|
|
67163
|
-
|
|
67164
|
-
const
|
|
67165
|
-
|
|
67166
|
-
|
|
67167
|
-
const keptEntries = state.entries.filter((entry) => entry.status === "running" || !idSet.has(entry.id));
|
|
67168
|
-
const removedEntries = state.entries.filter((entry) => entry.status === "pending" && idSet.has(entry.id));
|
|
67169
|
-
state.entries = keptEntries;
|
|
67170
|
-
cleared += removedEntries.length;
|
|
67171
|
-
for (const entry of removedEntries) {
|
|
67172
|
-
Promise.resolve(entry.lifecycle?.onClear?.()).catch(() => {
|
|
67173
|
-
return;
|
|
67174
|
-
});
|
|
67175
|
-
entry.reject(new ClearedQueuedTaskError);
|
|
67176
|
-
}
|
|
67177
|
-
if (state.entries.length === 0 && !state.running) {
|
|
67178
|
-
this.states.delete(key);
|
|
67179
|
-
}
|
|
67139
|
+
clearPendingByIdsForKey(key, ids) {
|
|
67140
|
+
const state = this.states.get(key);
|
|
67141
|
+
if (!state) {
|
|
67142
|
+
return 0;
|
|
67180
67143
|
}
|
|
67181
|
-
|
|
67144
|
+
const idSet = new Set(ids);
|
|
67145
|
+
return this.clearPendingEntriesForState(key, state, (entry) => idSet.has(entry.id));
|
|
67182
67146
|
}
|
|
67183
67147
|
getOrCreateState(key) {
|
|
67184
67148
|
const existing = this.states.get(key);
|
|
@@ -67203,6 +67167,21 @@ class AgentJobQueue {
|
|
|
67203
67167
|
return left.sequence - right.sequence;
|
|
67204
67168
|
});
|
|
67205
67169
|
}
|
|
67170
|
+
clearPendingEntriesForState(key, state, shouldClear) {
|
|
67171
|
+
const keptEntries = state.entries.filter((entry) => entry.status === "running" || !shouldClear(entry));
|
|
67172
|
+
const removedEntries = state.entries.filter((entry) => entry.status === "pending" && shouldClear(entry));
|
|
67173
|
+
state.entries = keptEntries;
|
|
67174
|
+
for (const entry of removedEntries) {
|
|
67175
|
+
Promise.resolve(entry.lifecycle?.onClear?.()).catch(() => {
|
|
67176
|
+
return;
|
|
67177
|
+
});
|
|
67178
|
+
entry.reject(new ClearedQueuedTaskError);
|
|
67179
|
+
}
|
|
67180
|
+
if (state.entries.length === 0 && !state.running) {
|
|
67181
|
+
this.states.delete(key);
|
|
67182
|
+
}
|
|
67183
|
+
return removedEntries.length;
|
|
67184
|
+
}
|
|
67206
67185
|
async drain(key, state) {
|
|
67207
67186
|
if (state.running) {
|
|
67208
67187
|
return;
|
|
@@ -67542,87 +67521,86 @@ class ManagedLoopController {
|
|
|
67542
67521
|
}
|
|
67543
67522
|
async reconcilePersistedIntervalLoops() {
|
|
67544
67523
|
const persistedLoops = await this.deps.sessionState.listIntervalLoops();
|
|
67545
|
-
const
|
|
67524
|
+
const persistedKeys = new Set;
|
|
67546
67525
|
for (const persisted of persistedLoops) {
|
|
67547
|
-
|
|
67526
|
+
const managedKey = this.buildManagedLoopKey(persisted.sessionKey, persisted.id);
|
|
67527
|
+
persistedKeys.add(managedKey);
|
|
67548
67528
|
if (persisted.attemptedRuns >= persisted.maxRuns) {
|
|
67549
|
-
this.dropManagedIntervalLoop(
|
|
67529
|
+
this.dropManagedIntervalLoop(managedKey);
|
|
67550
67530
|
continue;
|
|
67551
67531
|
}
|
|
67552
|
-
if (this.intervalLoops.has(
|
|
67532
|
+
if (this.intervalLoops.has(managedKey)) {
|
|
67553
67533
|
continue;
|
|
67554
67534
|
}
|
|
67555
|
-
this.intervalLoops.set(
|
|
67535
|
+
this.intervalLoops.set(managedKey, {
|
|
67556
67536
|
target: {
|
|
67557
67537
|
agentId: persisted.agentId,
|
|
67558
67538
|
sessionKey: persisted.sessionKey
|
|
67559
67539
|
},
|
|
67560
67540
|
loop: persisted
|
|
67561
67541
|
});
|
|
67562
|
-
this.scheduleIntervalLoopTimer(
|
|
67542
|
+
this.scheduleIntervalLoopTimer(managedKey, Math.max(0, persisted.nextRunAt - Date.now()));
|
|
67563
67543
|
}
|
|
67564
|
-
for (const
|
|
67565
|
-
if (!
|
|
67566
|
-
this.dropManagedIntervalLoop(
|
|
67544
|
+
for (const managedKey of this.intervalLoops.keys()) {
|
|
67545
|
+
if (!persistedKeys.has(managedKey)) {
|
|
67546
|
+
this.dropManagedIntervalLoop(managedKey);
|
|
67567
67547
|
}
|
|
67568
67548
|
}
|
|
67569
67549
|
}
|
|
67570
67550
|
async createIntervalLoop(params) {
|
|
67571
67551
|
this.assertActiveLoopCapacity();
|
|
67572
67552
|
const loop = createStoredIntervalLoop(params);
|
|
67553
|
+
const managedKey = this.buildManagedLoopKey(params.target.sessionKey, loop.id);
|
|
67573
67554
|
await this.deps.sessionState.setIntervalLoop(this.deps.resolveTarget(params.target), loop);
|
|
67574
|
-
this.intervalLoops.set(
|
|
67555
|
+
this.intervalLoops.set(managedKey, {
|
|
67575
67556
|
target: params.target,
|
|
67576
67557
|
loop
|
|
67577
67558
|
});
|
|
67578
|
-
await this.runIntervalLoopIteration(
|
|
67559
|
+
await this.runIntervalLoopIteration(managedKey, {
|
|
67579
67560
|
notifyStart: false
|
|
67580
67561
|
});
|
|
67581
|
-
return this.getIntervalLoop(loop.id);
|
|
67562
|
+
return this.getIntervalLoop(params.target.sessionKey, loop.id);
|
|
67582
67563
|
}
|
|
67583
67564
|
async createCalendarLoop(params) {
|
|
67584
67565
|
this.assertActiveLoopCapacity();
|
|
67585
67566
|
const loop = createStoredCalendarLoop(params);
|
|
67567
|
+
const managedKey = this.buildManagedLoopKey(params.target.sessionKey, loop.id);
|
|
67586
67568
|
await this.deps.sessionState.setIntervalLoop(this.deps.resolveTarget(params.target), loop);
|
|
67587
|
-
this.intervalLoops.set(
|
|
67569
|
+
this.intervalLoops.set(managedKey, {
|
|
67588
67570
|
target: params.target,
|
|
67589
67571
|
loop
|
|
67590
67572
|
});
|
|
67591
|
-
this.scheduleIntervalLoopTimer(
|
|
67592
|
-
return this.getIntervalLoop(loop.id);
|
|
67573
|
+
this.scheduleIntervalLoopTimer(managedKey, Math.max(0, loop.nextRunAt - Date.now()));
|
|
67574
|
+
return this.getIntervalLoop(params.target.sessionKey, loop.id);
|
|
67593
67575
|
}
|
|
67594
|
-
async cancelIntervalLoop(loopId) {
|
|
67595
|
-
const
|
|
67576
|
+
async cancelIntervalLoop(target, loopId) {
|
|
67577
|
+
const managedKey = this.buildManagedLoopKey(target.sessionKey, loopId);
|
|
67578
|
+
const managed = this.intervalLoops.get(managedKey);
|
|
67596
67579
|
if (!managed) {
|
|
67597
67580
|
return false;
|
|
67598
67581
|
}
|
|
67599
|
-
|
|
67600
|
-
clearTimeout(managed.timer);
|
|
67601
|
-
this.loopTimers.delete(managed.timer);
|
|
67602
|
-
}
|
|
67603
|
-
this.intervalLoops.delete(loopId);
|
|
67604
|
-
await this.deps.sessionState.removeIntervalLoop(this.deps.resolveTarget(managed.target), loopId);
|
|
67582
|
+
await this.cancelManagedIntervalLoop(managedKey, managed);
|
|
67605
67583
|
return true;
|
|
67606
67584
|
}
|
|
67607
67585
|
async cancelIntervalLoopsForSession(target) {
|
|
67608
|
-
const matching = [...this.intervalLoops.
|
|
67609
|
-
for (const
|
|
67610
|
-
await this.
|
|
67586
|
+
const matching = [...this.intervalLoops.entries()].filter(([, managed]) => managed.target.sessionKey === target.sessionKey);
|
|
67587
|
+
for (const [managedKey, managed] of matching) {
|
|
67588
|
+
await this.cancelManagedIntervalLoop(managedKey, managed);
|
|
67611
67589
|
}
|
|
67612
67590
|
return matching.length;
|
|
67613
67591
|
}
|
|
67614
67592
|
async cancelAllIntervalLoops() {
|
|
67615
|
-
const
|
|
67616
|
-
for (const
|
|
67617
|
-
await this.
|
|
67593
|
+
const matching = [...this.intervalLoops.entries()];
|
|
67594
|
+
for (const [managedKey, managed] of matching) {
|
|
67595
|
+
await this.cancelManagedIntervalLoop(managedKey, managed);
|
|
67618
67596
|
}
|
|
67619
|
-
return
|
|
67597
|
+
return matching.length;
|
|
67620
67598
|
}
|
|
67621
67599
|
listIntervalLoops(params) {
|
|
67622
67600
|
return [...this.intervalLoops.values()].filter((managed) => !params?.sessionKey || managed.target.sessionKey === params.sessionKey).map((managed) => this.toLoopStatus(managed)).sort((left, right) => left.nextRunAt - right.nextRunAt);
|
|
67623
67601
|
}
|
|
67624
|
-
getIntervalLoop(loopId) {
|
|
67625
|
-
const managed = this.intervalLoops.get(loopId);
|
|
67602
|
+
getIntervalLoop(sessionKey, loopId) {
|
|
67603
|
+
const managed = this.intervalLoops.get(this.buildManagedLoopKey(sessionKey, loopId));
|
|
67626
67604
|
return managed ? this.toLoopStatus(managed) : null;
|
|
67627
67605
|
}
|
|
67628
67606
|
getActiveIntervalLoopCount() {
|
|
@@ -67646,8 +67624,8 @@ class ManagedLoopController {
|
|
|
67646
67624
|
const entry = await this.deps.sessionState.getEntry(managed.target.sessionKey);
|
|
67647
67625
|
return (entry?.loops ?? entry?.intervalLoops ?? []).some((loop) => loop.id === managed.loop.id);
|
|
67648
67626
|
}
|
|
67649
|
-
dropManagedIntervalLoop(
|
|
67650
|
-
const managed = this.intervalLoops.get(
|
|
67627
|
+
dropManagedIntervalLoop(managedKey) {
|
|
67628
|
+
const managed = this.intervalLoops.get(managedKey);
|
|
67651
67629
|
if (!managed) {
|
|
67652
67630
|
return;
|
|
67653
67631
|
}
|
|
@@ -67655,30 +67633,34 @@ class ManagedLoopController {
|
|
|
67655
67633
|
clearTimeout(managed.timer);
|
|
67656
67634
|
this.loopTimers.delete(managed.timer);
|
|
67657
67635
|
}
|
|
67658
|
-
this.intervalLoops.delete(
|
|
67636
|
+
this.intervalLoops.delete(managedKey);
|
|
67659
67637
|
}
|
|
67660
|
-
async
|
|
67661
|
-
|
|
67638
|
+
async cancelManagedIntervalLoop(managedKey, managed) {
|
|
67639
|
+
this.dropManagedIntervalLoop(managedKey);
|
|
67640
|
+
await this.deps.sessionState.removeIntervalLoop(this.deps.resolveTarget(managed.target), managed.loop.id);
|
|
67641
|
+
}
|
|
67642
|
+
async runIntervalLoopIteration(managedKey, options = {}) {
|
|
67643
|
+
const managed = this.intervalLoops.get(managedKey);
|
|
67662
67644
|
if (!managed) {
|
|
67663
67645
|
return;
|
|
67664
67646
|
}
|
|
67665
67647
|
if (!await this.isManagedLoopPersisted(managed)) {
|
|
67666
|
-
this.dropManagedIntervalLoop(
|
|
67648
|
+
this.dropManagedIntervalLoop(managedKey);
|
|
67667
67649
|
return;
|
|
67668
67650
|
}
|
|
67669
67651
|
const attemptedRuns = managed.loop.attemptedRuns + 1;
|
|
67670
67652
|
const now = Date.now();
|
|
67671
67653
|
const nextLoopState = this.buildNextLoopState(managed.loop, attemptedRuns, now);
|
|
67672
67654
|
if (await this.deps.isSessionBusy(managed.target)) {
|
|
67673
|
-
await this.skipLoopIteration(
|
|
67655
|
+
await this.skipLoopIteration(managedKey, managed, nextLoopState, attemptedRuns, now);
|
|
67674
67656
|
return;
|
|
67675
67657
|
}
|
|
67676
67658
|
nextLoopState.executedRuns += 1;
|
|
67677
67659
|
if (!await this.updateManagedIntervalLoop(managed, nextLoopState)) {
|
|
67678
|
-
this.dropManagedIntervalLoop(
|
|
67660
|
+
this.dropManagedIntervalLoop(managedKey);
|
|
67679
67661
|
return;
|
|
67680
67662
|
}
|
|
67681
|
-
await this.executeLoopIteration(
|
|
67663
|
+
await this.executeLoopIteration(managedKey, managed.target, nextLoopState, attemptedRuns, now, options.notifyStart !== false);
|
|
67682
67664
|
}
|
|
67683
67665
|
buildNextLoopState(loop, attemptedRuns, now) {
|
|
67684
67666
|
return {
|
|
@@ -67688,33 +67670,35 @@ class ManagedLoopController {
|
|
|
67688
67670
|
nextRunAt: this.computeNextManagedLoopRunAtMs(loop, now)
|
|
67689
67671
|
};
|
|
67690
67672
|
}
|
|
67691
|
-
async skipLoopIteration(
|
|
67673
|
+
async skipLoopIteration(managedKey, managed, nextLoopState, attemptedRuns, now) {
|
|
67692
67674
|
nextLoopState.skippedRuns += 1;
|
|
67693
67675
|
if (!await this.updateManagedIntervalLoop(managed, nextLoopState)) {
|
|
67694
|
-
this.dropManagedIntervalLoop(
|
|
67676
|
+
this.dropManagedIntervalLoop(managedKey);
|
|
67695
67677
|
return;
|
|
67696
67678
|
}
|
|
67697
67679
|
if (attemptedRuns >= managed.loop.maxRuns) {
|
|
67698
|
-
|
|
67680
|
+
this.dropManagedIntervalLoop(managedKey);
|
|
67681
|
+
await this.deps.sessionState.removeIntervalLoop(this.deps.resolveTarget(managed.target), managed.loop.id);
|
|
67699
67682
|
return;
|
|
67700
67683
|
}
|
|
67701
|
-
this.scheduleIntervalLoopTimer(
|
|
67684
|
+
this.scheduleIntervalLoopTimer(managedKey, Math.max(0, nextLoopState.nextRunAt - now));
|
|
67702
67685
|
}
|
|
67703
|
-
async executeLoopIteration(
|
|
67704
|
-
await this.notifyAndEnqueueLoop(
|
|
67686
|
+
async executeLoopIteration(managedKey, target, nextLoopState, attemptedRuns, now, notifyStart) {
|
|
67687
|
+
await this.notifyAndEnqueueLoop(managedKey, target, nextLoopState, attemptedRuns, notifyStart);
|
|
67705
67688
|
if (attemptedRuns >= nextLoopState.maxRuns) {
|
|
67706
|
-
|
|
67689
|
+
this.dropManagedIntervalLoop(managedKey);
|
|
67690
|
+
await this.deps.sessionState.removeIntervalLoop(this.deps.resolveTarget(target), nextLoopState.id);
|
|
67707
67691
|
return;
|
|
67708
67692
|
}
|
|
67709
|
-
this.scheduleIntervalLoopTimer(
|
|
67693
|
+
this.scheduleIntervalLoopTimer(managedKey, Math.max(0, nextLoopState.nextRunAt - now));
|
|
67710
67694
|
}
|
|
67711
|
-
async notifyAndEnqueueLoop(
|
|
67695
|
+
async notifyAndEnqueueLoop(managedKey, target, nextLoopState, attemptedRuns, notifyStart) {
|
|
67712
67696
|
if (notifyStart) {
|
|
67713
67697
|
await this.deps.surfaceRuntime.notifyManagedLoopStart(target, nextLoopState);
|
|
67714
67698
|
}
|
|
67715
67699
|
const promptText = await this.deps.surfaceRuntime.buildManagedLoopPrompt(target.agentId, nextLoopState);
|
|
67716
67700
|
const { result } = this.deps.enqueuePrompt(target, promptText, {
|
|
67717
|
-
observerId: `loop:${
|
|
67701
|
+
observerId: `loop:${managedKey}:${attemptedRuns}`,
|
|
67718
67702
|
onUpdate: async () => {
|
|
67719
67703
|
return;
|
|
67720
67704
|
}
|
|
@@ -67725,8 +67709,8 @@ class ManagedLoopController {
|
|
|
67725
67709
|
}
|
|
67726
67710
|
});
|
|
67727
67711
|
}
|
|
67728
|
-
scheduleIntervalLoopTimer(
|
|
67729
|
-
const managed = this.intervalLoops.get(
|
|
67712
|
+
scheduleIntervalLoopTimer(managedKey, delayMs) {
|
|
67713
|
+
const managed = this.intervalLoops.get(managedKey);
|
|
67730
67714
|
if (!managed) {
|
|
67731
67715
|
return;
|
|
67732
67716
|
}
|
|
@@ -67736,12 +67720,12 @@ class ManagedLoopController {
|
|
|
67736
67720
|
}
|
|
67737
67721
|
const timer = setTimeout(() => {
|
|
67738
67722
|
this.loopTimers.delete(timer);
|
|
67739
|
-
const current = this.intervalLoops.get(
|
|
67723
|
+
const current = this.intervalLoops.get(managedKey);
|
|
67740
67724
|
if (!current) {
|
|
67741
67725
|
return;
|
|
67742
67726
|
}
|
|
67743
67727
|
current.timer = undefined;
|
|
67744
|
-
this.runIntervalLoopIteration(
|
|
67728
|
+
this.runIntervalLoopIteration(managedKey, { notifyStart: true }).catch((error) => {
|
|
67745
67729
|
if (!this.deps.shouldSuppressShutdownError(error)) {
|
|
67746
67730
|
console.error("loop execution failed", error);
|
|
67747
67731
|
}
|
|
@@ -67758,6 +67742,9 @@ class ManagedLoopController {
|
|
|
67758
67742
|
managed.loop = nextLoopState;
|
|
67759
67743
|
return true;
|
|
67760
67744
|
}
|
|
67745
|
+
buildManagedLoopKey(sessionKey, loopId) {
|
|
67746
|
+
return `${sessionKey}::${loopId}`;
|
|
67747
|
+
}
|
|
67761
67748
|
computeNextManagedLoopRunAtMs(loop, nowMs) {
|
|
67762
67749
|
if (loop.kind === "calendar") {
|
|
67763
67750
|
return computeNextCalendarLoopRunAtMs({
|
|
@@ -67798,7 +67785,7 @@ class ManagedQueueController {
|
|
|
67798
67785
|
}
|
|
67799
67786
|
async clearQueuedPrompts(target) {
|
|
67800
67787
|
const clearedStored = await this.deps.sessionState.clearPendingQueuedItemsForSessionKey(target.sessionKey);
|
|
67801
|
-
this.deps.queue.
|
|
67788
|
+
this.deps.queue.clearPendingByIdsForKey(target.sessionKey, clearedStored.map((item) => item.id));
|
|
67802
67789
|
return clearedStored.length;
|
|
67803
67790
|
}
|
|
67804
67791
|
enqueuePrompt(target, prompt, callbacks) {
|
|
@@ -67836,8 +67823,8 @@ class ManagedQueueController {
|
|
|
67836
67823
|
return;
|
|
67837
67824
|
}
|
|
67838
67825
|
this.setManagedQueueItem(target, item, true);
|
|
67839
|
-
return this.persistQueueItem(this.deps.resolveTarget(target), item).then(() => this.markPersisted(item)).catch((error) => {
|
|
67840
|
-
this.clearPendingById(item);
|
|
67826
|
+
return this.persistQueueItem(this.deps.resolveTarget(target), item).then(() => this.markPersisted(target, item)).catch((error) => {
|
|
67827
|
+
this.clearPendingById(target, item);
|
|
67841
67828
|
throw error;
|
|
67842
67829
|
});
|
|
67843
67830
|
}
|
|
@@ -67848,16 +67835,32 @@ class ManagedQueueController {
|
|
|
67848
67835
|
await reconciledBeforeStart;
|
|
67849
67836
|
return !await this.deps.hasBlockingActiveRun(target);
|
|
67850
67837
|
}
|
|
67838
|
+
async canStartPersistedQueueItem(target, item) {
|
|
67839
|
+
if (await this.deps.hasBlockingActiveRun(target)) {
|
|
67840
|
+
return false;
|
|
67841
|
+
}
|
|
67842
|
+
if (!await this.deps.sessionState.hasQueuedItem(target.sessionKey, item.id)) {
|
|
67843
|
+
this.clearPendingById(target, item);
|
|
67844
|
+
return false;
|
|
67845
|
+
}
|
|
67846
|
+
return true;
|
|
67847
|
+
}
|
|
67851
67848
|
async reconcilePersistedQueueItems() {
|
|
67852
67849
|
const persistedItems = await this.deps.sessionState.listQueuedItems({
|
|
67853
67850
|
statuses: ["pending", "running"]
|
|
67854
67851
|
});
|
|
67855
|
-
const
|
|
67856
|
-
const
|
|
67857
|
-
if (
|
|
67858
|
-
|
|
67859
|
-
for (const
|
|
67860
|
-
|
|
67852
|
+
const persistedKeys = new Set(persistedItems.map((item) => this.buildManagedQueueKey(item.sessionKey, item.id)));
|
|
67853
|
+
const removedManagedItems = [...this.queuedItems.entries()].filter(([key, managed]) => !managed.persisting && !persistedKeys.has(key));
|
|
67854
|
+
if (removedManagedItems.length > 0) {
|
|
67855
|
+
const removedBySession = new Map;
|
|
67856
|
+
for (const [key, managed] of removedManagedItems) {
|
|
67857
|
+
const ids = removedBySession.get(managed.target.sessionKey) ?? [];
|
|
67858
|
+
ids.push(managed.item.id);
|
|
67859
|
+
removedBySession.set(managed.target.sessionKey, ids);
|
|
67860
|
+
this.queuedItems.delete(key);
|
|
67861
|
+
}
|
|
67862
|
+
for (const [sessionKey, itemIds] of removedBySession.entries()) {
|
|
67863
|
+
this.deps.queue.clearPendingByIdsForKey(sessionKey, itemIds);
|
|
67861
67864
|
}
|
|
67862
67865
|
}
|
|
67863
67866
|
for (const persisted of persistedItems) {
|
|
@@ -67865,14 +67868,14 @@ class ManagedQueueController {
|
|
|
67865
67868
|
await this.clearStaleRunningQueueItem(persisted);
|
|
67866
67869
|
continue;
|
|
67867
67870
|
}
|
|
67868
|
-
if (this.queuedItems.has(persisted.id)) {
|
|
67871
|
+
if (this.queuedItems.has(this.buildManagedQueueKey(persisted.sessionKey, persisted.id))) {
|
|
67869
67872
|
continue;
|
|
67870
67873
|
}
|
|
67871
67874
|
this.enqueuePersistedQueueItem(persisted);
|
|
67872
67875
|
}
|
|
67873
67876
|
}
|
|
67874
67877
|
async clearStaleRunningQueueItem(item) {
|
|
67875
|
-
if (this.queuedItems.has(item.id)) {
|
|
67878
|
+
if (this.queuedItems.has(this.buildManagedQueueKey(item.sessionKey, item.id))) {
|
|
67876
67879
|
return;
|
|
67877
67880
|
}
|
|
67878
67881
|
const target = {
|
|
@@ -67896,21 +67899,22 @@ class ManagedQueueController {
|
|
|
67896
67899
|
});
|
|
67897
67900
|
}
|
|
67898
67901
|
setManagedQueueItem(target, item, persisting) {
|
|
67899
|
-
this.queuedItems.set(item.id, {
|
|
67902
|
+
this.queuedItems.set(this.buildManagedQueueKey(target.sessionKey, item.id), {
|
|
67900
67903
|
target,
|
|
67901
67904
|
item,
|
|
67902
67905
|
persisting
|
|
67903
67906
|
});
|
|
67904
67907
|
}
|
|
67905
|
-
markPersisted(item) {
|
|
67906
|
-
const
|
|
67908
|
+
markPersisted(target, item) {
|
|
67909
|
+
const key = this.buildManagedQueueKey(target.sessionKey, item.id);
|
|
67910
|
+
const managed = this.queuedItems.get(key);
|
|
67907
67911
|
if (managed) {
|
|
67908
|
-
this.queuedItems.set(
|
|
67912
|
+
this.queuedItems.set(key, { ...managed, persisting: false });
|
|
67909
67913
|
}
|
|
67910
67914
|
}
|
|
67911
|
-
clearPendingById(item) {
|
|
67912
|
-
this.deps.queue.
|
|
67913
|
-
this.queuedItems.delete(item.id);
|
|
67915
|
+
clearPendingById(target, item) {
|
|
67916
|
+
this.deps.queue.clearPendingByIdsForKey(target.sessionKey, [item.id]);
|
|
67917
|
+
this.queuedItems.delete(this.buildManagedQueueKey(target.sessionKey, item.id));
|
|
67914
67918
|
}
|
|
67915
67919
|
async markQueueItemRunning(target, item) {
|
|
67916
67920
|
if (!item) {
|
|
@@ -67923,7 +67927,7 @@ class ManagedQueueController {
|
|
|
67923
67927
|
startedAt: now,
|
|
67924
67928
|
updatedAt: now
|
|
67925
67929
|
};
|
|
67926
|
-
this.queuedItems.set(item.id, {
|
|
67930
|
+
this.queuedItems.set(this.buildManagedQueueKey(target.sessionKey, item.id), {
|
|
67927
67931
|
target,
|
|
67928
67932
|
item: next
|
|
67929
67933
|
});
|
|
@@ -67934,7 +67938,7 @@ class ManagedQueueController {
|
|
|
67934
67938
|
if (!item) {
|
|
67935
67939
|
return;
|
|
67936
67940
|
}
|
|
67937
|
-
this.queuedItems.delete(item.id);
|
|
67941
|
+
this.queuedItems.delete(this.buildManagedQueueKey(target.sessionKey, item.id));
|
|
67938
67942
|
await this.deps.sessionState.removeQueuedItem(this.deps.resolveTarget(target), item.id);
|
|
67939
67943
|
}
|
|
67940
67944
|
enqueuePersistedQueueItem(item) {
|
|
@@ -67942,7 +67946,7 @@ class ManagedQueueController {
|
|
|
67942
67946
|
agentId: item.agentId,
|
|
67943
67947
|
sessionKey: item.sessionKey
|
|
67944
67948
|
};
|
|
67945
|
-
this.queuedItems.set(item.id, {
|
|
67949
|
+
this.queuedItems.set(this.buildManagedQueueKey(target.sessionKey, item.id), {
|
|
67946
67950
|
target,
|
|
67947
67951
|
item
|
|
67948
67952
|
});
|
|
@@ -67974,7 +67978,7 @@ class ManagedQueueController {
|
|
|
67974
67978
|
id: item.id,
|
|
67975
67979
|
createdAt: item.createdAt,
|
|
67976
67980
|
text: item.promptSummary,
|
|
67977
|
-
canStart: async () =>
|
|
67981
|
+
canStart: async () => this.canStartPersistedQueueItem(target, item),
|
|
67978
67982
|
onComplete: async (value) => {
|
|
67979
67983
|
if (!value.messageToolFinalAlreadySent && !await this.hasMessageToolFinalForQueueItem(target, item)) {
|
|
67980
67984
|
await this.deps.surfaceRuntime.notifyManagedQueueSettlement(target, item, value);
|
|
@@ -67988,6 +67992,9 @@ class ManagedQueueController {
|
|
|
67988
67992
|
onClear: () => this.removeManagedQueueItem(target, item)
|
|
67989
67993
|
});
|
|
67990
67994
|
queued.result.catch((error) => {
|
|
67995
|
+
if (error instanceof ClearedQueuedTaskError) {
|
|
67996
|
+
return;
|
|
67997
|
+
}
|
|
67991
67998
|
if (this.deps.shouldSuppressShutdownError(error)) {
|
|
67992
67999
|
return;
|
|
67993
68000
|
}
|
|
@@ -68004,7 +68011,7 @@ class ManagedQueueController {
|
|
|
68004
68011
|
return false;
|
|
68005
68012
|
}
|
|
68006
68013
|
async hasMessageToolFinalForQueueItem(target, item) {
|
|
68007
|
-
const startedAt = this.queuedItems.get(item.id)?.item.startedAt ?? item.startedAt;
|
|
68014
|
+
const startedAt = this.queuedItems.get(this.buildManagedQueueKey(target.sessionKey, item.id))?.item.startedAt ?? item.startedAt;
|
|
68008
68015
|
if (typeof startedAt !== "number" || !Number.isFinite(startedAt)) {
|
|
68009
68016
|
return false;
|
|
68010
68017
|
}
|
|
@@ -68025,6 +68032,9 @@ class ManagedQueueController {
|
|
|
68025
68032
|
messageToolFinalAlreadySent: true
|
|
68026
68033
|
};
|
|
68027
68034
|
}
|
|
68035
|
+
buildManagedQueueKey(sessionKey, itemId) {
|
|
68036
|
+
return `${sessionKey}::${itemId}`;
|
|
68037
|
+
}
|
|
68028
68038
|
}
|
|
68029
68039
|
|
|
68030
68040
|
// src/agents/runner-service.ts
|
|
@@ -69731,7 +69741,11 @@ class RunnerService {
|
|
|
69731
69741
|
args: args.map((value) => applyTemplate(value, values))
|
|
69732
69742
|
};
|
|
69733
69743
|
}
|
|
69734
|
-
async
|
|
69744
|
+
async syncStoredSessionId(target) {
|
|
69745
|
+
const resolved = this.resolveTarget(target);
|
|
69746
|
+
return this.syncStoredSessionIdForResolvedTarget(resolved);
|
|
69747
|
+
}
|
|
69748
|
+
async syncStoredSessionIdForResolvedTarget(resolved) {
|
|
69735
69749
|
const existing = await this.sessionState.getEntry(resolved.sessionKey);
|
|
69736
69750
|
if (existing?.sessionId) {
|
|
69737
69751
|
this.sessionIdentityCaptureRetryAt.delete(resolved.sessionKey);
|
|
@@ -69793,12 +69807,41 @@ class RunnerService {
|
|
|
69793
69807
|
remainingFreshRetries: remainingFreshRetries - 1
|
|
69794
69808
|
});
|
|
69795
69809
|
}
|
|
69796
|
-
async retryAfterStartupFault(target, resolved, error, remainingFreshRetries) {
|
|
69810
|
+
async retryAfterStartupFault(target, resolved, error, remainingFreshRetries, allowFreshResumeFallback) {
|
|
69811
|
+
if (allowFreshResumeFallback) {
|
|
69812
|
+
const resumedFresh = await this.retryFreshStartAfterStoredResumeFailure(target, resolved, error, remainingFreshRetries);
|
|
69813
|
+
if (resumedFresh) {
|
|
69814
|
+
return resumedFresh;
|
|
69815
|
+
}
|
|
69816
|
+
}
|
|
69797
69817
|
if (!isRetryableFreshStartFault(error)) {
|
|
69798
69818
|
return null;
|
|
69799
69819
|
}
|
|
69800
69820
|
return this.retryRunnerRestartPreservingSessionId(target, resolved, remainingFreshRetries);
|
|
69801
69821
|
}
|
|
69822
|
+
async retryFreshStartAfterStoredResumeFailure(target, resolved, error, remainingFreshRetries) {
|
|
69823
|
+
if (!isRecoverableStartupSessionLoss(error)) {
|
|
69824
|
+
return null;
|
|
69825
|
+
}
|
|
69826
|
+
if (resolved.runner.sessionId.resume.mode !== "command" || resolved.runner.sessionId.create.mode !== "runner") {
|
|
69827
|
+
return null;
|
|
69828
|
+
}
|
|
69829
|
+
const existing = await this.sessionState.getEntry(resolved.sessionKey);
|
|
69830
|
+
if (!existing?.sessionId) {
|
|
69831
|
+
return null;
|
|
69832
|
+
}
|
|
69833
|
+
const exitRecord = await readRunnerExitRecord(this.loadedConfig.stateDir, resolved.sessionName);
|
|
69834
|
+
if (!exitRecord || exitRecord.exitCode === 0) {
|
|
69835
|
+
return null;
|
|
69836
|
+
}
|
|
69837
|
+
console.log(`clisbot clearing stored sessionId after failed runner resume startup ${resolved.sessionName}`);
|
|
69838
|
+
await this.sessionState.clearSessionIdEntry(resolved, {
|
|
69839
|
+
runnerCommand: resolved.runner.command
|
|
69840
|
+
});
|
|
69841
|
+
return this.ensureSessionReady(target, {
|
|
69842
|
+
remainingFreshRetries
|
|
69843
|
+
});
|
|
69844
|
+
}
|
|
69802
69845
|
async retryAfterStartupTimeout(target, resolved, remainingFreshRetries) {
|
|
69803
69846
|
return this.retryRunnerRestartPreservingSessionId(target, resolved, remainingFreshRetries);
|
|
69804
69847
|
}
|
|
@@ -69897,7 +69940,7 @@ class RunnerService {
|
|
|
69897
69940
|
});
|
|
69898
69941
|
try {
|
|
69899
69942
|
await clearRunnerExitRecord(this.loadedConfig.stateDir, resolved.sessionName);
|
|
69900
|
-
await this.
|
|
69943
|
+
await this.syncStoredSessionIdForResolvedTarget(resolved);
|
|
69901
69944
|
} catch (error) {
|
|
69902
69945
|
throw await this.mapSessionError(error, resolved.sessionName, "during startup");
|
|
69903
69946
|
}
|
|
@@ -69967,7 +70010,7 @@ class RunnerService {
|
|
|
69967
70010
|
runnerCommand: runnerLaunch.command
|
|
69968
70011
|
});
|
|
69969
70012
|
} catch (error) {
|
|
69970
|
-
const retried = await this.retryAfterStartupFault(target, resolved, error, remainingFreshRetries);
|
|
70013
|
+
const retried = await this.retryAfterStartupFault(target, resolved, error, remainingFreshRetries, options.allowFreshRetry !== false);
|
|
69971
70014
|
if (retried) {
|
|
69972
70015
|
return retried;
|
|
69973
70016
|
}
|
|
@@ -69989,7 +70032,7 @@ class RunnerService {
|
|
|
69989
70032
|
});
|
|
69990
70033
|
return;
|
|
69991
70034
|
}
|
|
69992
|
-
await this.
|
|
70035
|
+
await this.syncStoredSessionIdForResolvedTarget(resolved);
|
|
69993
70036
|
}
|
|
69994
70037
|
async dismissTrustPrompt(resolved) {
|
|
69995
70038
|
if (!resolved.runner.trustWorkspace) {
|
|
@@ -70522,16 +70565,21 @@ class SessionService {
|
|
|
70522
70565
|
this.resolveTarget = resolveTarget;
|
|
70523
70566
|
}
|
|
70524
70567
|
async recoverPersistedRuns() {
|
|
70568
|
+
const activeSessionKeys = new Set;
|
|
70525
70569
|
const entries = await this.sessionState.listEntries();
|
|
70526
70570
|
for (const entry of entries) {
|
|
70527
70571
|
if (!entry.runtime || entry.runtime.state === "idle") {
|
|
70528
70572
|
continue;
|
|
70529
70573
|
}
|
|
70530
|
-
await this.reconcilePersistedActiveRun({
|
|
70574
|
+
const run = await this.reconcilePersistedActiveRun({
|
|
70531
70575
|
agentId: entry.agentId,
|
|
70532
70576
|
sessionKey: entry.sessionKey
|
|
70533
70577
|
});
|
|
70578
|
+
if (run) {
|
|
70579
|
+
activeSessionKeys.add(run.resolved.sessionKey);
|
|
70580
|
+
}
|
|
70534
70581
|
}
|
|
70582
|
+
return activeSessionKeys;
|
|
70535
70583
|
}
|
|
70536
70584
|
async clearLostPersistedActiveRuns() {
|
|
70537
70585
|
const entries = await this.sessionState.listEntries();
|
|
@@ -70762,6 +70810,14 @@ class SessionService {
|
|
|
70762
70810
|
}
|
|
70763
70811
|
this.activeRuns.clear();
|
|
70764
70812
|
}
|
|
70813
|
+
listLiveSessionRuntimes() {
|
|
70814
|
+
return [...this.activeRuns.values()].map((run) => ({
|
|
70815
|
+
state: run.latestUpdate.status === "detached" ? "detached" : "running",
|
|
70816
|
+
startedAt: run.startedAt,
|
|
70817
|
+
sessionKey: run.resolved.sessionKey,
|
|
70818
|
+
agentId: run.resolved.agentId
|
|
70819
|
+
}));
|
|
70820
|
+
}
|
|
70765
70821
|
buildDetachedNote(resolved) {
|
|
70766
70822
|
return `This session has been running for over ${resolved.stream.maxRuntimeLabel}. clisbot left it running and will post the final result here when it completes. Use \`/attach\` for live updates, \`/watch every <duration>\` for periodic updates, or \`/stop\` to interrupt it.`;
|
|
70767
70823
|
}
|
|
@@ -72407,9 +72463,8 @@ class AgentService {
|
|
|
72407
72463
|
});
|
|
72408
72464
|
}
|
|
72409
72465
|
async start() {
|
|
72410
|
-
await this.activeRuns.recoverPersistedRuns();
|
|
72411
|
-
|
|
72412
|
-
await this.sessionState.resetStaleRunningQueuedItems(activeSessions);
|
|
72466
|
+
const activeSessionKeys = await this.activeRuns.recoverPersistedRuns();
|
|
72467
|
+
await this.sessionState.resetStaleRunningQueuedItems(activeSessionKeys);
|
|
72413
72468
|
await this.managedQueues.reconcilePersistedQueueItems();
|
|
72414
72469
|
this.queueReconcileTimer = setInterval(() => {
|
|
72415
72470
|
this.managedQueues.reconcilePersistedQueueItems().catch((error) => {
|
|
@@ -72492,14 +72547,13 @@ class AgentService {
|
|
|
72492
72547
|
const storedSessionId = entry?.sessionId?.trim() || undefined;
|
|
72493
72548
|
return {
|
|
72494
72549
|
sessionName: resolved.sessionName,
|
|
72495
|
-
sessionId: storedSessionId,
|
|
72496
72550
|
storedSessionId,
|
|
72497
72551
|
resumeCommand: buildResumeCommandPreview(resolved, storedSessionId)
|
|
72498
72552
|
};
|
|
72499
72553
|
}
|
|
72500
|
-
async
|
|
72554
|
+
async listLiveSessionRuntimes() {
|
|
72501
72555
|
await this.activeRuns.clearLostPersistedActiveRuns();
|
|
72502
|
-
return this.
|
|
72556
|
+
return this.activeRuns.listLiveSessionRuntimes();
|
|
72503
72557
|
}
|
|
72504
72558
|
async setConversationFollowUpMode(target, mode) {
|
|
72505
72559
|
return this.sessionState.setConversationFollowUpMode(this.resolveTarget(target), mode);
|
|
@@ -72600,8 +72654,8 @@ class AgentService {
|
|
|
72600
72654
|
async createCalendarLoop(params) {
|
|
72601
72655
|
return this.managedLoops.createCalendarLoop(params);
|
|
72602
72656
|
}
|
|
72603
|
-
async cancelIntervalLoop(loopId) {
|
|
72604
|
-
return this.managedLoops.cancelIntervalLoop(loopId);
|
|
72657
|
+
async cancelIntervalLoop(target, loopId) {
|
|
72658
|
+
return this.managedLoops.cancelIntervalLoop(target, loopId);
|
|
72605
72659
|
}
|
|
72606
72660
|
async cancelIntervalLoopsForSession(target) {
|
|
72607
72661
|
return this.managedLoops.cancelIntervalLoopsForSession(target);
|
|
@@ -72612,8 +72666,8 @@ class AgentService {
|
|
|
72612
72666
|
listIntervalLoops(params) {
|
|
72613
72667
|
return this.managedLoops.listIntervalLoops(params);
|
|
72614
72668
|
}
|
|
72615
|
-
getIntervalLoop(loopId) {
|
|
72616
|
-
return this.managedLoops.getIntervalLoop(loopId);
|
|
72669
|
+
getIntervalLoop(target, loopId) {
|
|
72670
|
+
return this.managedLoops.getIntervalLoop(target.sessionKey, loopId);
|
|
72617
72671
|
}
|
|
72618
72672
|
getActiveIntervalLoopCount() {
|
|
72619
72673
|
return this.managedLoops.getActiveIntervalLoopCount();
|
|
@@ -72919,7 +72973,6 @@ function renderStartupSteeringUnavailableMessage() {
|
|
|
72919
72973
|
`);
|
|
72920
72974
|
}
|
|
72921
72975
|
function renderWhoAmIMessage(params) {
|
|
72922
|
-
const storedSessionId = params.sessionDiagnostics.storedSessionId ?? params.sessionDiagnostics.sessionId;
|
|
72923
72976
|
const lines = [
|
|
72924
72977
|
"Who am I",
|
|
72925
72978
|
"",
|
|
@@ -72927,7 +72980,7 @@ function renderWhoAmIMessage(params) {
|
|
|
72927
72980
|
`conversationKind: \`${params.identity.conversationKind}\``,
|
|
72928
72981
|
`agentId: \`${params.route.agentId}\``,
|
|
72929
72982
|
`sessionName: \`${params.sessionDiagnostics.sessionName ?? "(not available)"}\``,
|
|
72930
|
-
`storedSessionId: \`${storedSessionId ?? "(not captured yet)"}\``
|
|
72983
|
+
`storedSessionId: \`${params.sessionDiagnostics.storedSessionId ?? "(not captured yet)"}\``
|
|
72931
72984
|
];
|
|
72932
72985
|
if (params.identity.senderId) {
|
|
72933
72986
|
lines.push(`senderId: \`${params.identity.senderId}\``);
|
|
@@ -72949,7 +73002,6 @@ function renderWhoAmIMessage(params) {
|
|
|
72949
73002
|
`);
|
|
72950
73003
|
}
|
|
72951
73004
|
function renderRouteStatusMessage(params) {
|
|
72952
|
-
const storedSessionId = params.sessionDiagnostics.storedSessionId ?? params.sessionDiagnostics.sessionId;
|
|
72953
73005
|
const lines = [
|
|
72954
73006
|
"Status",
|
|
72955
73007
|
"",
|
|
@@ -72957,7 +73009,7 @@ function renderRouteStatusMessage(params) {
|
|
|
72957
73009
|
`conversationKind: \`${params.identity.conversationKind}\``,
|
|
72958
73010
|
`agentId: \`${params.route.agentId}\``,
|
|
72959
73011
|
`sessionName: \`${params.sessionDiagnostics.sessionName ?? "(not available)"}\``,
|
|
72960
|
-
`storedSessionId: \`${storedSessionId ?? "(not captured yet)"}\``
|
|
73012
|
+
`storedSessionId: \`${params.sessionDiagnostics.storedSessionId ?? "(not captured yet)"}\``
|
|
72961
73013
|
];
|
|
72962
73014
|
if (params.identity.senderId) {
|
|
72963
73015
|
lines.push(`senderId: \`${params.identity.senderId}\``);
|
|
@@ -74047,7 +74099,7 @@ async function processChannelInteraction(params) {
|
|
|
74047
74099
|
await params.agentService.recordConversationReply(params.sessionTarget);
|
|
74048
74100
|
return interactionResult;
|
|
74049
74101
|
}
|
|
74050
|
-
const cancelled = await params.agentService.cancelIntervalLoop(targetLoopId);
|
|
74102
|
+
const cancelled = await params.agentService.cancelIntervalLoop(params.sessionTarget, targetLoopId);
|
|
74051
74103
|
await params.postText(cancelled ? `Cancelled loop \`${targetLoopId}\`.` : `No active loop found with id \`${targetLoopId}\`.`);
|
|
74052
74104
|
await params.agentService.recordConversationReply(params.sessionTarget);
|
|
74053
74105
|
return interactionResult;
|
|
@@ -84282,18 +84334,27 @@ function renderUpdateHelp() {
|
|
|
84282
84334
|
" 2. Read docs in priority order and follow them before installing.",
|
|
84283
84335
|
" 3. npm install -g clisbot@<target> && clisbot restart",
|
|
84284
84336
|
` 4. ${renderCliCommand("status")}`,
|
|
84285
|
-
" 5. Report version, health, manual action, and useful release
|
|
84337
|
+
" 5. Report version, health, manual action, and useful release highlights.",
|
|
84286
84338
|
"",
|
|
84287
84339
|
"Docs, read in order:",
|
|
84288
84340
|
` 1. Migration index: ${GITHUB_RAW_BASE}/docs/migrations/index.md`,
|
|
84289
84341
|
" If Manual action: required, follow its runbook. If none, continue.",
|
|
84290
|
-
` 2.
|
|
84291
|
-
" Use for
|
|
84292
|
-
` 3.
|
|
84293
|
-
" Use for
|
|
84294
|
-
|
|
84342
|
+
` 2. Update guide: ${GITHUB_RAW_BASE}/docs/updates/update-guide.md`,
|
|
84343
|
+
" Use for target choice, install flow, verification, and wrong-publish recovery.",
|
|
84344
|
+
` 3. Release notes: ${GITHUB_RAW_BASE}/docs/releases/README.md`,
|
|
84345
|
+
" Use for the canonical version map and full version notes.",
|
|
84346
|
+
` 4. Release guides: ${GITHUB_RAW_BASE}/docs/updates/README.md`,
|
|
84347
|
+
" Use for shorter catch-up notes: what changed, what to try, and what to watch.",
|
|
84348
|
+
" 5. Full docs: https://github.com/longbkit/clisbot/tree/main/docs",
|
|
84295
84349
|
" Use for deep questions. If needed, fetch or clone docs and inspect relevant files.",
|
|
84296
84350
|
"",
|
|
84351
|
+
"Recovery:",
|
|
84352
|
+
" - If a version was published by mistake, publish the corrected target or tag first.",
|
|
84353
|
+
" - Then deprecate the wrong version.",
|
|
84354
|
+
" - Start with `npm login` in an attached session.",
|
|
84355
|
+
" - If npm returns a browser approval URL, keep that same session open and continue it after approval.",
|
|
84356
|
+
" - If the write command still returns EOTP, ask the operator for a current OTP and rerun the exact command with --otp=<code>.",
|
|
84357
|
+
"",
|
|
84297
84358
|
"Rules:",
|
|
84298
84359
|
" - Use npm dist-tags, not highest semver.",
|
|
84299
84360
|
" - Stable/latest is default; beta only when the user asks.",
|
|
@@ -84847,7 +84908,7 @@ async function getRuntimeOperatorSummary(params) {
|
|
|
84847
84908
|
},
|
|
84848
84909
|
agentSummaries,
|
|
84849
84910
|
channelSummaries,
|
|
84850
|
-
activeRuns: await agentService.
|
|
84911
|
+
activeRuns: await agentService.listLiveSessionRuntimes(),
|
|
84851
84912
|
configuredAgents: agentSummaries.length,
|
|
84852
84913
|
bootstrapPendingAgents: agentSummaries.filter((item) => item.bootstrapState === "missing" || item.bootstrapState === "not-bootstrapped").length,
|
|
84853
84914
|
bootstrappedAgents: agentSummaries.filter((item) => item.bootstrapState === "bootstrapped").length,
|