crewly 1.20.299 → 1.20.301
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/config/skills/agent/core/publish-app/SKILL.md +10 -1
- package/dist/backend/backend/src/controllers/messaging/messenger.routes.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/messaging/messenger.routes.js +2 -1
- package/dist/backend/backend/src/controllers/messaging/messenger.routes.js.map +1 -1
- package/dist/backend/backend/src/index.d.ts.map +1 -1
- package/dist/backend/backend/src/index.js +20 -1
- package/dist/backend/backend/src/index.js.map +1 -1
- package/dist/backend/backend/src/services/agent/follow-through.service.d.ts +33 -0
- package/dist/backend/backend/src/services/agent/follow-through.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/agent/follow-through.service.js +80 -7
- package/dist/backend/backend/src/services/agent/follow-through.service.js.map +1 -1
- package/dist/backend/backend/src/services/agent/follow-through.wiring.d.ts +34 -0
- package/dist/backend/backend/src/services/agent/follow-through.wiring.d.ts.map +1 -1
- package/dist/backend/backend/src/services/agent/follow-through.wiring.js +109 -4
- package/dist/backend/backend/src/services/agent/follow-through.wiring.js.map +1 -1
- package/dist/backend/backend/src/services/agent/idle-detection.service.d.ts +9 -0
- package/dist/backend/backend/src/services/agent/idle-detection.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/agent/idle-detection.service.js +24 -1
- package/dist/backend/backend/src/services/agent/idle-detection.service.js.map +1 -1
- package/dist/backend/backend/src/services/agent/idle-work-guard.d.ts +12 -1
- package/dist/backend/backend/src/services/agent/idle-work-guard.d.ts.map +1 -1
- package/dist/backend/backend/src/services/agent/idle-work-guard.js +11 -1
- package/dist/backend/backend/src/services/agent/idle-work-guard.js.map +1 -1
- package/dist/backend/backend/src/services/agent/stated-intent.d.ts +2 -2
- package/dist/backend/backend/src/services/agent/stated-intent.d.ts.map +1 -1
- package/dist/backend/backend/src/services/agent/stated-intent.js +17 -7
- package/dist/backend/backend/src/services/agent/stated-intent.js.map +1 -1
- package/dist/backend/backend/src/services/cloud/cloud-client.service.d.ts +2 -19
- package/dist/backend/backend/src/services/cloud/cloud-client.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/cloud/cloud-client.service.js +14 -10
- package/dist/backend/backend/src/services/cloud/cloud-client.service.js.map +1 -1
- package/dist/backend/backend/src/services/cloud/cloud-config-file.d.ts +84 -0
- package/dist/backend/backend/src/services/cloud/cloud-config-file.d.ts.map +1 -0
- package/dist/backend/backend/src/services/cloud/cloud-config-file.js +86 -0
- package/dist/backend/backend/src/services/cloud/cloud-config-file.js.map +1 -0
- package/dist/backend/backend/src/services/cloud/cloud-disconnect-notice.service.d.ts +5 -0
- package/dist/backend/backend/src/services/cloud/cloud-disconnect-notice.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/cloud/cloud-disconnect-notice.service.js +9 -3
- package/dist/backend/backend/src/services/cloud/cloud-disconnect-notice.service.js.map +1 -1
- package/dist/backend/backend/src/services/cloud/cloud-disconnect-notice.utils.d.ts +5 -1
- package/dist/backend/backend/src/services/cloud/cloud-disconnect-notice.utils.d.ts.map +1 -1
- package/dist/backend/backend/src/services/cloud/cloud-disconnect-notice.utils.js +17 -3
- package/dist/backend/backend/src/services/cloud/cloud-disconnect-notice.utils.js.map +1 -1
- package/dist/backend/backend/src/services/cloud/cloud-sync.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/cloud/cloud-sync.service.js +2 -1
- package/dist/backend/backend/src/services/cloud/cloud-sync.service.js.map +1 -1
- package/dist/backend/backend/src/services/cloud/device-identity.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/cloud/device-identity.service.js +3 -2
- package/dist/backend/backend/src/services/cloud/device-identity.service.js.map +1 -1
- package/dist/backend/backend/src/services/core/api-token.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/core/api-token.service.js +2 -3
- package/dist/backend/backend/src/services/core/api-token.service.js.map +1 -1
- package/dist/backend/backend/src/services/messaging/deferred-start-retry.d.ts +2 -0
- package/dist/backend/backend/src/services/messaging/deferred-start-retry.d.ts.map +1 -1
- package/dist/backend/backend/src/services/messaging/deferred-start-retry.js +1 -1
- package/dist/backend/backend/src/services/messaging/deferred-start-retry.js.map +1 -1
- package/dist/backend/backend/src/services/messaging/owner-thread-sentinel.service.d.ts +16 -0
- package/dist/backend/backend/src/services/messaging/owner-thread-sentinel.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/messaging/owner-thread-sentinel.service.js +38 -0
- package/dist/backend/backend/src/services/messaging/owner-thread-sentinel.service.js.map +1 -1
- package/dist/backend/backend/src/utils/file-io.utils.d.ts +66 -5
- package/dist/backend/backend/src/utils/file-io.utils.d.ts.map +1 -1
- package/dist/backend/backend/src/utils/file-io.utils.js +169 -15
- package/dist/backend/backend/src/utils/file-io.utils.js.map +1 -1
- package/dist/backend/build-info.json +2 -2
- package/dist/cli/backend/src/services/agent/follow-through.service.d.ts +33 -0
- package/dist/cli/backend/src/services/agent/follow-through.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/agent/follow-through.service.js +80 -7
- package/dist/cli/backend/src/services/agent/follow-through.service.js.map +1 -1
- package/dist/cli/backend/src/services/agent/stated-intent.d.ts +2 -2
- package/dist/cli/backend/src/services/agent/stated-intent.d.ts.map +1 -1
- package/dist/cli/backend/src/services/agent/stated-intent.js +17 -7
- package/dist/cli/backend/src/services/agent/stated-intent.js.map +1 -1
- package/dist/cli/backend/src/services/cloud/cloud-client.service.d.ts +2 -19
- package/dist/cli/backend/src/services/cloud/cloud-client.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/cloud/cloud-client.service.js +14 -10
- package/dist/cli/backend/src/services/cloud/cloud-client.service.js.map +1 -1
- package/dist/cli/backend/src/services/cloud/cloud-config-file.d.ts +84 -0
- package/dist/cli/backend/src/services/cloud/cloud-config-file.d.ts.map +1 -0
- package/dist/cli/backend/src/services/cloud/cloud-config-file.js +86 -0
- package/dist/cli/backend/src/services/cloud/cloud-config-file.js.map +1 -0
- package/dist/cli/backend/src/services/cloud/cloud-sync.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/cloud/cloud-sync.service.js +2 -1
- package/dist/cli/backend/src/services/cloud/cloud-sync.service.js.map +1 -1
- package/dist/cli/backend/src/services/cloud/device-identity.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/cloud/device-identity.service.js +3 -2
- package/dist/cli/backend/src/services/cloud/device-identity.service.js.map +1 -1
- package/dist/cli/backend/src/services/core/api-token.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/core/api-token.service.js +2 -3
- package/dist/cli/backend/src/services/core/api-token.service.js.map +1 -1
- package/dist/cli/backend/src/services/messaging/owner-thread-sentinel.service.d.ts +16 -0
- package/dist/cli/backend/src/services/messaging/owner-thread-sentinel.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/messaging/owner-thread-sentinel.service.js +38 -0
- package/dist/cli/backend/src/services/messaging/owner-thread-sentinel.service.js.map +1 -1
- package/dist/cli/backend/src/utils/file-io.utils.d.ts +66 -5
- package/dist/cli/backend/src/utils/file-io.utils.d.ts.map +1 -1
- package/dist/cli/backend/src/utils/file-io.utils.js +169 -15
- package/dist/cli/backend/src/utils/file-io.utils.js.map +1 -1
- package/dist/cli/cli/src/commands/cloud.d.ts.map +1 -1
- package/dist/cli/cli/src/commands/cloud.js +10 -28
- package/dist/cli/cli/src/commands/cloud.js.map +1 -1
- package/package.json +1 -1
|
@@ -27,6 +27,18 @@ export declare const FOLLOW_THROUGH_CONSTANTS: {
|
|
|
27
27
|
readonly OUTPUT_WORK_MS: 45000;
|
|
28
28
|
/** After a runtime restart the first tool call is the harness's own register-self */
|
|
29
29
|
readonly TOOLS_AFTER_RESTART: 2;
|
|
30
|
+
/**
|
|
31
|
+
* Tool calls after the statement that count as having started. One is not
|
|
32
|
+
* enough: the reply itself is followed by housekeeping (status mark,
|
|
33
|
+
* memory write) that is not the promised work (Pia, 2026-10-11).
|
|
34
|
+
*/
|
|
35
|
+
readonly TOOLS_TO_COUNT: 3;
|
|
36
|
+
/** A statement this old whose agent is quiet is checked without waiting for a turn-end event */
|
|
37
|
+
readonly SWEEP_AFTER_MS: 60000;
|
|
38
|
+
/** How often open statements are swept */
|
|
39
|
+
readonly SWEEP_INTERVAL_MS: 20000;
|
|
40
|
+
/** Quiet for this long = the agent is not mid-turn */
|
|
41
|
+
readonly QUIET_MS: 15000;
|
|
30
42
|
};
|
|
31
43
|
/** What the guard needs from the rest of the backend. */
|
|
32
44
|
export interface FollowThroughDeps {
|
|
@@ -44,6 +56,12 @@ export interface FollowThroughDeps {
|
|
|
44
56
|
waitingOnOwner?: (session: string) => Promise<boolean>;
|
|
45
57
|
/** Owner-stopped or team-paused agents are never nudged */
|
|
46
58
|
isHeldBack?: (session: string) => boolean;
|
|
59
|
+
/** The agent produced no output for {@link FOLLOW_THROUGH_CONSTANTS.QUIET_MS} (sweep only) */
|
|
60
|
+
isQuiet?: (session: string) => boolean;
|
|
61
|
+
/** Make the statement a durable WorkItem for the agent; returns its id */
|
|
62
|
+
commit?: (session: string, sentence: string, at: number) => Promise<string | null>;
|
|
63
|
+
/** The statement was answered: close its WorkItem */
|
|
64
|
+
settle?: (workItemId: string) => Promise<void>;
|
|
47
65
|
now?: () => number;
|
|
48
66
|
}
|
|
49
67
|
/** What a turn end did. */
|
|
@@ -103,7 +121,15 @@ export declare class AgentFollowThroughService {
|
|
|
103
121
|
takeIntent(agent: string): {
|
|
104
122
|
sentence: string;
|
|
105
123
|
at: number;
|
|
124
|
+
workItemId?: string;
|
|
106
125
|
} | null;
|
|
126
|
+
/**
|
|
127
|
+
* Age of the agent's open stated intent.
|
|
128
|
+
*
|
|
129
|
+
* @param agent - Session
|
|
130
|
+
* @returns Milliseconds, or null when none is open
|
|
131
|
+
*/
|
|
132
|
+
intentAgeMs(agent: string): number | null;
|
|
107
133
|
/**
|
|
108
134
|
* The agent's turn ended: nudge it once when it stated an intent that
|
|
109
135
|
* nothing followed. Never throws.
|
|
@@ -112,6 +138,13 @@ export declare class AgentFollowThroughService {
|
|
|
112
138
|
* @returns What happened
|
|
113
139
|
*/
|
|
114
140
|
onTurnEnd(agent: string): Promise<TurnEndOutcome>;
|
|
141
|
+
/**
|
|
142
|
+
* Check statements whose agent went quiet without a turn-end event reaching
|
|
143
|
+
* us (the post can land after the turn-end settle ran). Called on a timer.
|
|
144
|
+
*
|
|
145
|
+
* @returns Agents nudged
|
|
146
|
+
*/
|
|
147
|
+
sweep(): Promise<string[]>;
|
|
115
148
|
/** Whether the agent did anything after the statement. */
|
|
116
149
|
private followed;
|
|
117
150
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"follow-through.service.d.ts","sourceRoot":"","sources":["../../../../../../backend/src/services/agent/follow-through.service.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAMH,qBAAqB;AACrB,eAAO,MAAM,wBAAwB;IACpC,oFAAoF;;IAEpF,wEAAwE;;IAExE,wEAAwE;;IAExE,6FAA6F;;IAE7F,qFAAqF;;
|
|
1
|
+
{"version":3,"file":"follow-through.service.d.ts","sourceRoot":"","sources":["../../../../../../backend/src/services/agent/follow-through.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -30,15 +30,28 @@ export const FOLLOW_THROUGH_CONSTANTS = {
|
|
|
30
30
|
OUTPUT_WORK_MS: 45_000,
|
|
31
31
|
/** After a runtime restart the first tool call is the harness's own register-self */
|
|
32
32
|
TOOLS_AFTER_RESTART: 2,
|
|
33
|
+
/**
|
|
34
|
+
* Tool calls after the statement that count as having started. One is not
|
|
35
|
+
* enough: the reply itself is followed by housekeeping (status mark,
|
|
36
|
+
* memory write) that is not the promised work (Pia, 2026-10-11).
|
|
37
|
+
*/
|
|
38
|
+
TOOLS_TO_COUNT: 3,
|
|
39
|
+
/** A statement this old whose agent is quiet is checked without waiting for a turn-end event */
|
|
40
|
+
SWEEP_AFTER_MS: 60_000,
|
|
41
|
+
/** How often open statements are swept */
|
|
42
|
+
SWEEP_INTERVAL_MS: 20_000,
|
|
43
|
+
/** Quiet for this long = the agent is not mid-turn */
|
|
44
|
+
QUIET_MS: 15_000,
|
|
33
45
|
};
|
|
34
46
|
/**
|
|
35
47
|
* @param sentence - What the agent said
|
|
36
48
|
* @returns The nudge text (harness text, English)
|
|
37
49
|
*/
|
|
38
50
|
export function followThroughNudge(sentence) {
|
|
39
|
-
return (`[FOLLOW-THROUGH] You told the owner you
|
|
40
|
-
'Your turn ended without starting it. Start it now, in this turn
|
|
41
|
-
|
|
51
|
+
return (`[FOLLOW-THROUGH] You told the owner you're starting this now: "${sentence}". ` +
|
|
52
|
+
'Your turn ended without starting it. Start it now, in this turn. ' +
|
|
53
|
+
'If you were waiting on an answer, proceed with the default you stated; a question with a default is not a reason to wait. ' +
|
|
54
|
+
"Don't reply again until there's a result or a real blocker.");
|
|
42
55
|
}
|
|
43
56
|
/**
|
|
44
57
|
* Tracks the last stated intent per agent and nudges once when a turn ends
|
|
@@ -69,11 +82,42 @@ export class AgentFollowThroughService {
|
|
|
69
82
|
return;
|
|
70
83
|
const at = input.at ?? this.now();
|
|
71
84
|
const found = detectStatedIntent(input.text);
|
|
85
|
+
const prior = this.statements.get(input.agent);
|
|
72
86
|
if (found) {
|
|
73
|
-
|
|
87
|
+
const stmt = {
|
|
88
|
+
at,
|
|
89
|
+
sentence: found.sentence,
|
|
90
|
+
nudged: false,
|
|
91
|
+
...(prior?.workItemId ? { workItemId: prior.workItemId } : {}),
|
|
92
|
+
...(prior?.committing ? { committing: true } : {}),
|
|
93
|
+
};
|
|
94
|
+
this.statements.set(input.agent, stmt);
|
|
95
|
+
// Durable: the promise becomes a WorkItem for the agent (the answer goes to the
|
|
96
|
+
// owner's thread), so a stop or restart does not lose it.
|
|
97
|
+
if (!stmt.workItemId && !stmt.committing && this.deps.commit) {
|
|
98
|
+
stmt.committing = true;
|
|
99
|
+
const agent = input.agent;
|
|
100
|
+
void this.deps.commit(agent, found.sentence, at).then((id) => {
|
|
101
|
+
// The statement may have been replaced meanwhile: attach to the live one.
|
|
102
|
+
const live = this.statements.get(agent);
|
|
103
|
+
if (id && live) {
|
|
104
|
+
live.workItemId = id;
|
|
105
|
+
live.committing = false;
|
|
106
|
+
}
|
|
107
|
+
else if (id) {
|
|
108
|
+
void this.deps.settle?.(id).catch(() => undefined);
|
|
109
|
+
}
|
|
110
|
+
}, () => {
|
|
111
|
+
const live = this.statements.get(agent);
|
|
112
|
+
if (live)
|
|
113
|
+
live.committing = false;
|
|
114
|
+
});
|
|
115
|
+
}
|
|
74
116
|
return;
|
|
75
117
|
}
|
|
76
118
|
this.statements.delete(input.agent);
|
|
119
|
+
if (prior?.workItemId && !input.interim)
|
|
120
|
+
void this.deps.settle?.(prior.workItemId).catch(() => undefined);
|
|
77
121
|
if (!input.interim)
|
|
78
122
|
this.lastReplyAt.set(input.agent, at);
|
|
79
123
|
}
|
|
@@ -109,7 +153,17 @@ export class AgentFollowThroughService {
|
|
|
109
153
|
if (!s)
|
|
110
154
|
return null;
|
|
111
155
|
this.statements.delete(agent);
|
|
112
|
-
return { sentence: s.sentence, at: s.at };
|
|
156
|
+
return { sentence: s.sentence, at: s.at, ...(s.workItemId ? { workItemId: s.workItemId } : {}) };
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Age of the agent's open stated intent.
|
|
160
|
+
*
|
|
161
|
+
* @param agent - Session
|
|
162
|
+
* @returns Milliseconds, or null when none is open
|
|
163
|
+
*/
|
|
164
|
+
intentAgeMs(agent) {
|
|
165
|
+
const s = this.statements.get(agent);
|
|
166
|
+
return s ? this.now() - s.at : null;
|
|
113
167
|
}
|
|
114
168
|
/**
|
|
115
169
|
* The agent's turn ended: nudge it once when it stated an intent that
|
|
@@ -141,10 +195,10 @@ export class AgentFollowThroughService {
|
|
|
141
195
|
if (this.deps.isHeldBack?.(agent))
|
|
142
196
|
return 'held';
|
|
143
197
|
// One nudge per statement; one per agent per cooldown, whatever it says next.
|
|
144
|
-
s.nudged = true;
|
|
145
198
|
const last = this.lastNudgeAt.get(agent);
|
|
146
199
|
if (last !== undefined && now - last < FOLLOW_THROUGH_CONSTANTS.NUDGE_COOLDOWN_MS)
|
|
147
200
|
return 'cooldown';
|
|
201
|
+
s.nudged = true;
|
|
148
202
|
const ok = await this.deps.nudgeAgent(agent, followThroughNudge(s.sentence)).catch(() => false);
|
|
149
203
|
this.logger.info('Stated intent without action — agent nudged', { agent, sentence: s.sentence, delivered: ok });
|
|
150
204
|
if (!ok)
|
|
@@ -157,12 +211,31 @@ export class AgentFollowThroughService {
|
|
|
157
211
|
return 'none';
|
|
158
212
|
}
|
|
159
213
|
}
|
|
214
|
+
/**
|
|
215
|
+
* Check statements whose agent went quiet without a turn-end event reaching
|
|
216
|
+
* us (the post can land after the turn-end settle ran). Called on a timer.
|
|
217
|
+
*
|
|
218
|
+
* @returns Agents nudged
|
|
219
|
+
*/
|
|
220
|
+
async sweep() {
|
|
221
|
+
const out = [];
|
|
222
|
+
const now = this.now();
|
|
223
|
+
for (const [agent, s] of [...this.statements]) {
|
|
224
|
+
if (s.nudged || now - s.at < FOLLOW_THROUGH_CONSTANTS.SWEEP_AFTER_MS)
|
|
225
|
+
continue;
|
|
226
|
+
if (this.deps.isQuiet && !this.deps.isQuiet(agent))
|
|
227
|
+
continue;
|
|
228
|
+
if ((await this.onTurnEnd(agent)) === 'nudged')
|
|
229
|
+
out.push(agent);
|
|
230
|
+
}
|
|
231
|
+
return out;
|
|
232
|
+
}
|
|
160
233
|
/** Whether the agent did anything after the statement. */
|
|
161
234
|
followed(agent, s) {
|
|
162
235
|
const tools = this.deps.toolStartsSince(agent, s.at);
|
|
163
236
|
if (tools !== null) {
|
|
164
237
|
const restarted = (this.deps.runtimeStartedAt?.(agent) ?? 0) > s.at;
|
|
165
|
-
return tools >= (restarted ? FOLLOW_THROUGH_CONSTANTS.TOOLS_AFTER_RESTART :
|
|
238
|
+
return tools >= FOLLOW_THROUGH_CONSTANTS.TOOLS_TO_COUNT + (restarted ? FOLLOW_THROUGH_CONSTANTS.TOOLS_AFTER_RESTART : 0);
|
|
166
239
|
}
|
|
167
240
|
const span = this.deps.outputSpanSince?.(agent, s.at);
|
|
168
241
|
// No hooks and no output reading: cannot tell, so do not nag.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"follow-through.service.js","sourceRoot":"","sources":["../../../../../../backend/src/services/agent/follow-through.service.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EAAE,yBAAyB,EAAE,MAAM,oBAAoB,CAAC;AAC/D,OAAO,EAAE,aAAa,EAAwB,MAAM,2BAA2B,CAAC;AAChF,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAExD,qBAAqB;AACrB,MAAM,CAAC,MAAM,wBAAwB,GAAG;IACvC,oFAAoF;IACpF,UAAU,EAAE,EAAE,GAAG,MAAM;IACvB,wEAAwE;IACxE,OAAO,EAAE,EAAE,GAAG,MAAM;IACpB,wEAAwE;IACxE,iBAAiB,EAAE,EAAE,GAAG,MAAM;IAC9B,6FAA6F;IAC7F,cAAc,EAAE,MAAM;IACtB,qFAAqF;IACrF,mBAAmB,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"follow-through.service.js","sourceRoot":"","sources":["../../../../../../backend/src/services/agent/follow-through.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -36,6 +36,30 @@ export interface FollowThroughWiringDeps {
|
|
|
36
36
|
* @returns The guard, or null when switched off
|
|
37
37
|
*/
|
|
38
38
|
export declare function createFollowThrough(deps: FollowThroughWiringDeps): AgentFollowThroughService | null;
|
|
39
|
+
/** Metadata marker on WorkItems made for a stated intent. */
|
|
40
|
+
export declare const STATED_INTENT_MARKER = "stated-intent";
|
|
41
|
+
/**
|
|
42
|
+
* Make "I'm starting X now" a WorkItem for the agent, so it survives a stop or
|
|
43
|
+
* restart. Created with the agent as creator, so the answer goes to the owner
|
|
44
|
+
* thread the agent is in (the pool stamps the origin). One open item per agent.
|
|
45
|
+
*
|
|
46
|
+
* @param session - The agent
|
|
47
|
+
* @param sentence - What it said
|
|
48
|
+
* @returns The WorkItem id, or null when none could be made
|
|
49
|
+
*/
|
|
50
|
+
export declare function commitStatedIntent(session: string, sentence: string): Promise<string | null>;
|
|
51
|
+
/**
|
|
52
|
+
* @param sentence - What the agent told the owner
|
|
53
|
+
* @returns The brief put on the promise's WorkItem (harness text)
|
|
54
|
+
*/
|
|
55
|
+
export declare function stateIntentBrief(sentence: string): string;
|
|
56
|
+
/**
|
|
57
|
+
* The promise was answered: close its WorkItem (queued ones are cancelled,
|
|
58
|
+
* started ones completed). Never throws.
|
|
59
|
+
*
|
|
60
|
+
* @param workItemId - The promise's WorkItem
|
|
61
|
+
*/
|
|
62
|
+
export declare function settleStatedIntent(workItemId: string): Promise<void>;
|
|
39
63
|
/**
|
|
40
64
|
* End of an agent's turn: nudge a stated intent nothing followed, give an
|
|
41
65
|
* unanswered owner ticket a WorkItem, then (the caller) submit answered
|
|
@@ -51,6 +75,16 @@ export declare function idleWorkGuardDeps(): IdleWorkGuardDeps;
|
|
|
51
75
|
export declare function idlePendingWorkCheck(): (session: string) => Promise<string | null>;
|
|
52
76
|
/** Seams of the work release on the real services. */
|
|
53
77
|
export declare function releaseWorkDeps(): ReleaseWorkDeps;
|
|
78
|
+
/**
|
|
79
|
+
* After an agent that owes work was stopped for memory: build the reminder it
|
|
80
|
+
* gets when it is brought back, from the WorkItems queued for it. Null when
|
|
81
|
+
* nothing is queued for it.
|
|
82
|
+
*
|
|
83
|
+
* @param items - Pool items
|
|
84
|
+
* @param session - The stopped agent
|
|
85
|
+
* @returns Reminder text, or null
|
|
86
|
+
*/
|
|
87
|
+
export declare function owedWorkReminder(items: readonly WorkItem[], session: string): string | null;
|
|
54
88
|
/**
|
|
55
89
|
* Release what a stopping agent holds (idle stop under pressure, emergency stop).
|
|
56
90
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"follow-through.wiring.d.ts","sourceRoot":"","sources":["../../../../../../backend/src/services/agent/follow-through.wiring.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,
|
|
1
|
+
{"version":3,"file":"follow-through.wiring.d.ts","sourceRoot":"","sources":["../../../../../../backend/src/services/agent/follow-through.wiring.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,EAA+C,KAAK,QAAQ,EAAE,MAAM,mCAAmC,CAAC;AAY/G,OAAO,EAAE,yBAAyB,EAAgE,MAAM,6BAA6B,CAAC;AACtI,OAAO,EAAkC,KAAK,iBAAiB,EAAE,KAAK,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAIpH;;;;;;;;;GASG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,SAAS,QAAQ,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAYlG;AAED,uDAAuD;AACvD,MAAM,WAAW,uBAAuB;IACvC,UAAU,EAAE,MAAM,CAAC;IACnB,gDAAgD;IAChD,WAAW,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC;QAAE,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;CAC9E;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,uBAAuB,GAAG,yBAAyB,GAAG,IAAI,CA8BnG;AAID,6DAA6D;AAC7D,eAAO,MAAM,oBAAoB,kBAAkB,CAAC;AAEpD;;;;;;;;GAQG;AACH,wBAAsB,kBAAkB,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAgBlG;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAKzD;AAED;;;;;GAKG;AACH,wBAAsB,kBAAkB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAO1E;AAID;;;;;;;GAOG;AACH,wBAAsB,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAqBxE;AAED,yDAAyD;AACzD,wBAAgB,iBAAiB,IAAI,iBAAiB,CAWrD;AAED,gEAAgE;AAChE,wBAAgB,oBAAoB,IAAI,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAElF;AAED,sDAAsD;AACtD,wBAAgB,eAAe,IAAI,eAAe,CAsCjD;AAED;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,SAAS,QAAQ,EAAE,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAQ3F;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAElF"}
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* @see specs/2026-10-10-agent-follow-through.md
|
|
8
8
|
*/
|
|
9
9
|
import { PROJECT_TICKET_CONSTANTS } from '../../constants.js';
|
|
10
|
-
import { createWorkItem } from '../../types/v2/work-item.types.js';
|
|
10
|
+
import { createWorkItem, TERMINAL_WORK_ITEM_STATUSES } from '../../types/v2/work-item.types.js';
|
|
11
11
|
import { LoggerService } from '../core/logger.service.js';
|
|
12
12
|
import { RequestService } from '../v3/request.service.js';
|
|
13
13
|
import { getTicketReviewService } from '../v3/ticket-review.service.js';
|
|
@@ -19,7 +19,7 @@ import { AgentTurnStateService } from '../monitoring/agent-turn-state.js';
|
|
|
19
19
|
import { isOwnerStopped } from './owner-stopped.registry.js';
|
|
20
20
|
import { pausedTeamOfSession } from '../team/team-pause.registry.js';
|
|
21
21
|
import { PtyActivityTrackerService } from './pty-activity-tracker.service.js';
|
|
22
|
-
import { AgentFollowThroughService, getFollowThrough, setFollowThrough } from './follow-through.service.js';
|
|
22
|
+
import { AgentFollowThroughService, FOLLOW_THROUGH_CONSTANTS, getFollowThrough, setFollowThrough } from './follow-through.service.js';
|
|
23
23
|
import { holdReasonFor, releaseHeldWork } from './idle-work-guard.js';
|
|
24
24
|
const logger = LoggerService.getInstance().createComponentLogger('FollowThroughWiring');
|
|
25
25
|
/**
|
|
@@ -36,9 +36,14 @@ export function handedOffSince(items, session, since) {
|
|
|
36
36
|
return items.some((wi) => {
|
|
37
37
|
if (Date.parse(wi.createdAt) < since)
|
|
38
38
|
return false;
|
|
39
|
-
if (wi.target === session)
|
|
40
|
-
return true;
|
|
41
39
|
const m = (wi.metadata ?? {});
|
|
40
|
+
if (wi.target === session) {
|
|
41
|
+
// An item the harness queued for the agent (the promise's own WorkItem,
|
|
42
|
+
// a ticket's) is not the agent starting: it waits until the agent does.
|
|
43
|
+
const waiting = wi.status === 'queued' || wi.status === 'proposed' || wi.status === 'scheduled' || wi.status === 'blocked';
|
|
44
|
+
if (!(waiting && typeof m['harnessCreated'] === 'string'))
|
|
45
|
+
return true;
|
|
46
|
+
}
|
|
42
47
|
return m['delegatedBy'] === session || m['createdBy'] === session || m[PROJECT_TICKET_CONSTANTS.DELEGATION_CALLER_METADATA_KEY] === session;
|
|
43
48
|
});
|
|
44
49
|
}
|
|
@@ -69,10 +74,71 @@ export function createFollowThrough(deps) {
|
|
|
69
74
|
return open.length > 0;
|
|
70
75
|
},
|
|
71
76
|
isHeldBack: (session) => isOwnerStopped(session) || !!pausedTeamOfSession(session),
|
|
77
|
+
isQuiet: (session) => !tracker.hasActivity(session) || tracker.getIdleTimeMs(session) >= FOLLOW_THROUGH_CONSTANTS.QUIET_MS,
|
|
78
|
+
commit: (session, sentence) => commitStatedIntent(session, sentence),
|
|
79
|
+
settle: (workItemId) => settleStatedIntent(workItemId),
|
|
72
80
|
});
|
|
73
81
|
setFollowThrough(service);
|
|
82
|
+
// A post can land after the turn-end settle ran: sweep quiet agents too.
|
|
83
|
+
if (sweepTimer)
|
|
84
|
+
clearInterval(sweepTimer);
|
|
85
|
+
sweepTimer = setInterval(() => {
|
|
86
|
+
void service.sweep().catch(() => undefined);
|
|
87
|
+
}, FOLLOW_THROUGH_CONSTANTS.SWEEP_INTERVAL_MS);
|
|
88
|
+
sweepTimer.unref?.();
|
|
74
89
|
return service;
|
|
75
90
|
}
|
|
91
|
+
let sweepTimer = null;
|
|
92
|
+
/** Metadata marker on WorkItems made for a stated intent. */
|
|
93
|
+
export const STATED_INTENT_MARKER = 'stated-intent';
|
|
94
|
+
/**
|
|
95
|
+
* Make "I'm starting X now" a WorkItem for the agent, so it survives a stop or
|
|
96
|
+
* restart. Created with the agent as creator, so the answer goes to the owner
|
|
97
|
+
* thread the agent is in (the pool stamps the origin). One open item per agent.
|
|
98
|
+
*
|
|
99
|
+
* @param session - The agent
|
|
100
|
+
* @param sentence - What it said
|
|
101
|
+
* @returns The WorkItem id, or null when none could be made
|
|
102
|
+
*/
|
|
103
|
+
export async function commitStatedIntent(session, sentence) {
|
|
104
|
+
const pool = TaskPoolService.getInstance();
|
|
105
|
+
const open = (await pool.getAllItems()).find((wi) => wi.target === session && wi.metadata?.['harnessCreated'] === STATED_INTENT_MARKER && !TERMINAL_WORK_ITEM_STATUSES.has(wi.status));
|
|
106
|
+
if (open)
|
|
107
|
+
return open.id;
|
|
108
|
+
const wi = createWorkItem({
|
|
109
|
+
type: 'delegate',
|
|
110
|
+
owner: 'agent',
|
|
111
|
+
target: session,
|
|
112
|
+
title: `Follow through: ${sentence.slice(0, 70)}`,
|
|
113
|
+
description: stateIntentBrief(sentence),
|
|
114
|
+
metadata: { harnessCreated: STATED_INTENT_MARKER },
|
|
115
|
+
});
|
|
116
|
+
await pool.addToPool(wi, { creatorSession: session });
|
|
117
|
+
return wi.id;
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* @param sentence - What the agent told the owner
|
|
121
|
+
* @returns The brief put on the promise's WorkItem (harness text)
|
|
122
|
+
*/
|
|
123
|
+
export function stateIntentBrief(sentence) {
|
|
124
|
+
return (`You told the owner: "${sentence}". Do it now, and reply in the owner's thread when there is a result or a real blocker. ` +
|
|
125
|
+
'If you asked a question and stated a default, go ahead with the default.');
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* The promise was answered: close its WorkItem (queued ones are cancelled,
|
|
129
|
+
* started ones completed). Never throws.
|
|
130
|
+
*
|
|
131
|
+
* @param workItemId - The promise's WorkItem
|
|
132
|
+
*/
|
|
133
|
+
export async function settleStatedIntent(workItemId) {
|
|
134
|
+
const pool = TaskPoolService.getInstance();
|
|
135
|
+
try {
|
|
136
|
+
await pool.cancelQueued(workItemId, 'answered by the agent', { cancelledBy: 'system' });
|
|
137
|
+
}
|
|
138
|
+
catch {
|
|
139
|
+
await pool.completeSimpleItem(workItemId, 'system').catch(() => undefined);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
76
142
|
const settling = new Set();
|
|
77
143
|
/**
|
|
78
144
|
* End of an agent's turn: nudge a stated intent nothing followed, give an
|
|
@@ -115,6 +181,10 @@ export function idleWorkGuardDeps() {
|
|
|
115
181
|
listTickets: () => RequestService.getInstance().listAll(),
|
|
116
182
|
owesOwner: (session) => getOwnerThreadSentinel()?.owesOwner(session) ?? false,
|
|
117
183
|
holdsIntent: (session) => getFollowThrough()?.holdsIntent(session) ?? false,
|
|
184
|
+
owedAgeMs: (session) => {
|
|
185
|
+
const ages = [getOwnerThreadSentinel()?.owedAgeMs(session) ?? null, getFollowThrough()?.intentAgeMs(session) ?? null].filter((a) => a !== null);
|
|
186
|
+
return ages.length > 0 ? Math.min(...ages) : null;
|
|
187
|
+
},
|
|
118
188
|
};
|
|
119
189
|
}
|
|
120
190
|
/** The idle check's pending-work check on the real services. */
|
|
@@ -131,6 +201,9 @@ export function releaseWorkDeps() {
|
|
|
131
201
|
const intent = getFollowThrough()?.takeIntent(session);
|
|
132
202
|
if (!intent)
|
|
133
203
|
return null;
|
|
204
|
+
// Already a WorkItem since the statement: nothing more to park.
|
|
205
|
+
if (intent.workItemId)
|
|
206
|
+
return intent.workItemId;
|
|
134
207
|
const wi = createWorkItem({
|
|
135
208
|
type: 'delegate',
|
|
136
209
|
owner: 'system',
|
|
@@ -143,8 +216,40 @@ export function releaseWorkDeps() {
|
|
|
143
216
|
await pool.addToPool(wi, { creatorSession: session });
|
|
144
217
|
return wi.id;
|
|
145
218
|
},
|
|
219
|
+
parkPromise: async (session) => {
|
|
220
|
+
const text = getOwnerThreadSentinel()?.promiseText(session);
|
|
221
|
+
if (!text)
|
|
222
|
+
return null;
|
|
223
|
+
const wi = createWorkItem({
|
|
224
|
+
type: 'delegate',
|
|
225
|
+
owner: 'system',
|
|
226
|
+
target: session,
|
|
227
|
+
title: `Follow through: ${text.slice(0, 70)}`,
|
|
228
|
+
description: `You promised the owner: "${text}". Crewly stopped you (memory) before you delivered. Deliver it; reply in the owner's thread with the result or a real blocker.`,
|
|
229
|
+
metadata: { harnessCreated: 'owner-promise' },
|
|
230
|
+
});
|
|
231
|
+
await pool.addToPool(wi, { creatorSession: session });
|
|
232
|
+
return wi.id;
|
|
233
|
+
},
|
|
146
234
|
};
|
|
147
235
|
}
|
|
236
|
+
/**
|
|
237
|
+
* After an agent that owes work was stopped for memory: build the reminder it
|
|
238
|
+
* gets when it is brought back, from the WorkItems queued for it. Null when
|
|
239
|
+
* nothing is queued for it.
|
|
240
|
+
*
|
|
241
|
+
* @param items - Pool items
|
|
242
|
+
* @param session - The stopped agent
|
|
243
|
+
* @returns Reminder text, or null
|
|
244
|
+
*/
|
|
245
|
+
export function owedWorkReminder(items, session) {
|
|
246
|
+
const queued = items.filter((wi) => wi.target === session && wi.status === 'queued');
|
|
247
|
+
if (queued.length === 0)
|
|
248
|
+
return null;
|
|
249
|
+
const lines = queued.slice(0, 5).map((wi) => `- ${wi.title}`);
|
|
250
|
+
return ('[FOLLOW-THROUGH] You were stopped to free memory while you still owed the owner this. It is still yours; start it now and reply in the owner thread with the result:\n' +
|
|
251
|
+
lines.join('\n'));
|
|
252
|
+
}
|
|
148
253
|
/**
|
|
149
254
|
* Release what a stopping agent holds (idle stop under pressure, emergency stop).
|
|
150
255
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"follow-through.wiring.js","sourceRoot":"","sources":["../../../../../../backend/src/services/agent/follow-through.wiring.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,wBAAwB,EAAE,MAAM,oBAAoB,CAAC;AAC9D,OAAO,EAAE,cAAc,EAAiB,MAAM,mCAAmC,CAAC;
|
|
1
|
+
{"version":3,"file":"follow-through.wiring.js","sourceRoot":"","sources":["../../../../../../backend/src/services/agent/follow-through.wiring.ts"],"names":[],"mappings":"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"}
|
|
@@ -42,6 +42,7 @@ export declare class IdleDetectionService {
|
|
|
42
42
|
private agentRegistrationService;
|
|
43
43
|
private pendingWorkCheck;
|
|
44
44
|
private workReleaser;
|
|
45
|
+
private owedStopHook;
|
|
45
46
|
private isChecking;
|
|
46
47
|
private lastTickStartedAt;
|
|
47
48
|
private lastTickCompletedAt;
|
|
@@ -147,7 +148,15 @@ export declare class IdleDetectionService {
|
|
|
147
148
|
* @param sessionName - Agent session
|
|
148
149
|
* @returns A reason, or null when nothing holds it or the check fails
|
|
149
150
|
*/
|
|
151
|
+
/**
|
|
152
|
+
* Inject what happens after an agent that still owed work was stopped for
|
|
153
|
+
* memory: it is brought back when a slot frees (the work is already queued).
|
|
154
|
+
*
|
|
155
|
+
* @param hook - Called once per such stop, or null
|
|
156
|
+
*/
|
|
157
|
+
setOwedStopHook(hook: ((sessionName: string) => void) | null): void;
|
|
150
158
|
private holdReason;
|
|
159
|
+
private runOwedStopHook;
|
|
151
160
|
/** Put the work a stopping agent holds back in the queue (best-effort). */
|
|
152
161
|
private releaseWork;
|
|
153
162
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"idle-detection.service.d.ts","sourceRoot":"","sources":["../../../../../../backend/src/services/agent/idle-detection.service.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAaH,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,iCAAiC,CAAC;AAChF,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mCAAmC,CAAC;AAKxE;;;;;GAKG;AACH,eAAO,MAAM,qBAAqB,EAAE,WAAW,CAAC,cAAc,CAA0E,CAAC;AAEzI;;;;GAIG;AACH,MAAM,MAAM,gBAAgB,GAAG,CAAC,WAAW,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,GAAG,MAAM,GAAG,IAAI,CAAC,CAAC;AAEzF;;;GAGG;AACH,MAAM,MAAM,YAAY,GAAG,CAAC,WAAW,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;AAElF;;;;;;;GAOG;AACH,qBAAa,oBAAoB;IAChC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAqC;IAC5D,OAAO,CAAC,MAAM,CAAkB;IAChC,OAAO,CAAC,KAAK,CAA+C;IAC5D,OAAO,CAAC,wBAAwB,CAAyC;IACzE,OAAO,CAAC,gBAAgB,CAAiC;IACzD,OAAO,CAAC,YAAY,CAA6B;
|
|
1
|
+
{"version":3,"file":"idle-detection.service.d.ts","sourceRoot":"","sources":["../../../../../../backend/src/services/agent/idle-detection.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -43,6 +43,7 @@ export class IdleDetectionService {
|
|
|
43
43
|
agentRegistrationService = null;
|
|
44
44
|
pendingWorkCheck = null;
|
|
45
45
|
workReleaser = null;
|
|
46
|
+
owedStopHook = null;
|
|
46
47
|
// Observability: surfaces silent hangs that previously caused the
|
|
47
48
|
// loop to "stop" for hours with no log evidence (2026-05-14 incident).
|
|
48
49
|
isChecking = false;
|
|
@@ -390,7 +391,9 @@ export class IdleDetectionService {
|
|
|
390
391
|
// pressure mode, where memory wins; then the work is put back
|
|
391
392
|
// in the queue first so the next start redelivers it.
|
|
392
393
|
const held = await this.holdReason(member.sessionName);
|
|
393
|
-
|
|
394
|
+
// A promise made to the owner minutes ago is spared even under
|
|
395
|
+
// pressure; only the emergency stop overrides it.
|
|
396
|
+
if (held === 'fresh_promise' || (held && !pressure)) {
|
|
394
397
|
this.logger.info('Agent idle but has queued work, keeping alive', {
|
|
395
398
|
sessionName: member.sessionName,
|
|
396
399
|
role: member.role,
|
|
@@ -418,6 +421,8 @@ export class IdleDetectionService {
|
|
|
418
421
|
await this.agentRegistrationService.terminateAgentSession(member.sessionName, member.role);
|
|
419
422
|
await StorageService.getInstance().updateAgentStatus(member.sessionName, CREWLY_CONSTANTS.AGENT_STATUSES.INACTIVE, 'idle_exit');
|
|
420
423
|
reportOwnerThreadBlocking(member.sessionName, { kind: 'stopped', why: 'idle' });
|
|
424
|
+
if (held)
|
|
425
|
+
this.runOwedStopHook(member.sessionName);
|
|
421
426
|
}
|
|
422
427
|
catch (err) {
|
|
423
428
|
this.logger.error('Failed to stop idle agent', {
|
|
@@ -454,6 +459,15 @@ export class IdleDetectionService {
|
|
|
454
459
|
* @param sessionName - Agent session
|
|
455
460
|
* @returns A reason, or null when nothing holds it or the check fails
|
|
456
461
|
*/
|
|
462
|
+
/**
|
|
463
|
+
* Inject what happens after an agent that still owed work was stopped for
|
|
464
|
+
* memory: it is brought back when a slot frees (the work is already queued).
|
|
465
|
+
*
|
|
466
|
+
* @param hook - Called once per such stop, or null
|
|
467
|
+
*/
|
|
468
|
+
setOwedStopHook(hook) {
|
|
469
|
+
this.owedStopHook = hook;
|
|
470
|
+
}
|
|
457
471
|
async holdReason(sessionName) {
|
|
458
472
|
if (!this.pendingWorkCheck)
|
|
459
473
|
return null;
|
|
@@ -467,6 +481,14 @@ export class IdleDetectionService {
|
|
|
467
481
|
return null;
|
|
468
482
|
}
|
|
469
483
|
}
|
|
484
|
+
runOwedStopHook(sessionName) {
|
|
485
|
+
try {
|
|
486
|
+
this.owedStopHook?.(sessionName);
|
|
487
|
+
}
|
|
488
|
+
catch {
|
|
489
|
+
/* best-effort */
|
|
490
|
+
}
|
|
491
|
+
}
|
|
470
492
|
/** Put the work a stopping agent holds back in the queue (best-effort). */
|
|
471
493
|
async releaseWork(sessionName, why) {
|
|
472
494
|
try {
|
|
@@ -557,6 +579,7 @@ export class IdleDetectionService {
|
|
|
557
579
|
PtyActivityTrackerService.getInstance().clearSession(member.sessionName);
|
|
558
580
|
await StorageService.getInstance().updateAgentStatus(member.sessionName, CREWLY_CONSTANTS.AGENT_STATUSES.INACTIVE, 'idle_exit_pressure');
|
|
559
581
|
reportOwnerThreadBlocking(member.sessionName, { kind: 'stopped', why: 'pressure' });
|
|
582
|
+
this.runOwedStopHook(member.sessionName);
|
|
560
583
|
stoppedCount++;
|
|
561
584
|
}
|
|
562
585
|
catch (err) {
|