@ouro.bot/cli 0.1.0-alpha.105 → 0.1.0-alpha.107
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/changelog.json +14 -0
- package/dist/heart/active-work.js +170 -34
- package/dist/heart/commitments.js +0 -4
- package/dist/heart/core.js +7 -53
- package/dist/mind/obligation-steering.js +22 -122
- package/dist/mind/prompt.js +28 -15
- package/dist/senses/pipeline.js +0 -24
- package/package.json +1 -1
package/changelog.json
CHANGED
|
@@ -1,6 +1,20 @@
|
|
|
1
1
|
{
|
|
2
2
|
"_note": "This changelog is maintained as part of the PR/version-bump workflow. Agent-curated, not auto-generated. Agents read this file directly via read_file to understand what changed between versions.",
|
|
3
3
|
"versions": [
|
|
4
|
+
{
|
|
5
|
+
"version": "0.1.0-alpha.107",
|
|
6
|
+
"changes": [
|
|
7
|
+
"Family-scoped 'what are you up to?' answers now widen to the full live world-state: the current conversation, live coding lanes, other active friend-facing sessions, and any active inner holding state, instead of collapsing to just the current lane.",
|
|
8
|
+
"The runtime no longer regex-polices an exact status-answer template; family status now rides on the same live obligation and session world-state the agent already uses everywhere else, which keeps cross-session answers truthful and natural."
|
|
9
|
+
]
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
"version": "0.1.0-alpha.106",
|
|
13
|
+
"changes": [
|
|
14
|
+
"Family-scoped status answers now come from the live obligation/session world-state directly instead of a regex-triggered 'status question' mode, so agents can answer naturally while still seeing all material live work across sessions.",
|
|
15
|
+
"Raw inbound text no longer masquerades as a real commitment or next action; current lanes, artifacts, and next steps are now grounded in persistent obligations, live coding state, and concrete session activity."
|
|
16
|
+
]
|
|
17
|
+
},
|
|
4
18
|
{
|
|
5
19
|
"version": "0.1.0-alpha.105",
|
|
6
20
|
"changes": [
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.formatOtherActiveSessionSummaries = formatOtherActiveSessionSummaries;
|
|
3
4
|
exports.suggestBridgeForActiveWork = suggestBridgeForActiveWork;
|
|
4
5
|
exports.buildActiveWorkFrame = buildActiveWorkFrame;
|
|
5
6
|
exports.formatActiveWorkFrame = formatActiveWorkFrame;
|
|
@@ -7,6 +8,7 @@ const runtime_1 = require("../nerves/runtime");
|
|
|
7
8
|
const state_machine_1 = require("./bridges/state-machine");
|
|
8
9
|
const obligations_1 = require("./obligations");
|
|
9
10
|
const target_resolution_1 = require("./target-resolution");
|
|
11
|
+
const config_1 = require("./config");
|
|
10
12
|
function activityPriority(source) {
|
|
11
13
|
return source === "friend-facing" ? 0 : 1;
|
|
12
14
|
}
|
|
@@ -28,9 +30,9 @@ function isActiveBridge(bridge) {
|
|
|
28
30
|
return bridge.lifecycle === "active";
|
|
29
31
|
}
|
|
30
32
|
function hasSharedObligationPressure(input) {
|
|
31
|
-
return
|
|
32
|
-
|
|
33
|
-
||
|
|
33
|
+
return input.mustResolveBeforeHandoff
|
|
34
|
+
|| summarizeLiveTasks(input.taskBoard).length > 0
|
|
35
|
+
|| activeObligationCount(input.pendingObligations) > 0;
|
|
34
36
|
}
|
|
35
37
|
function formatCodingLaneLabel(session) {
|
|
36
38
|
return `${session.runner} ${session.id}`;
|
|
@@ -86,6 +88,16 @@ function findPrimaryOpenObligation(frame) {
|
|
|
86
88
|
?? (frame.pendingObligations ?? []).find(obligations_1.isOpenObligation)
|
|
87
89
|
?? null;
|
|
88
90
|
}
|
|
91
|
+
function matchesCurrentSession(frame, obligation) {
|
|
92
|
+
return Boolean(frame.currentSession
|
|
93
|
+
&& obligation.origin.friendId === frame.currentSession.friendId
|
|
94
|
+
&& obligation.origin.channel === frame.currentSession.channel
|
|
95
|
+
&& (0, config_1.sanitizeKey)(obligation.origin.key) === (0, config_1.sanitizeKey)(frame.currentSession.key));
|
|
96
|
+
}
|
|
97
|
+
function findCurrentSessionOpenObligation(frame) {
|
|
98
|
+
return (frame.pendingObligations ?? []).find((obligation) => (0, obligations_1.isOpenObligationStatus)(obligation.status) && matchesCurrentSession(frame, obligation))
|
|
99
|
+
?? null;
|
|
100
|
+
}
|
|
89
101
|
function formatActiveLane(frame, obligation) {
|
|
90
102
|
const liveCodingSession = frame.codingSessions?.[0];
|
|
91
103
|
if (liveCodingSession) {
|
|
@@ -94,12 +106,12 @@ function formatActiveLane(frame, obligation) {
|
|
|
94
106
|
if (obligation?.currentSurface?.label) {
|
|
95
107
|
return obligation.currentSurface.label;
|
|
96
108
|
}
|
|
109
|
+
if (obligation && matchesCurrentSession(frame, obligation) && frame.currentSession) {
|
|
110
|
+
return "this same thread";
|
|
111
|
+
}
|
|
97
112
|
if (frame.inner?.job?.status === "running") {
|
|
98
113
|
return "inner dialog";
|
|
99
114
|
}
|
|
100
|
-
if (typeof frame.currentObligation === "string" && frame.currentObligation.trim().length > 0 && frame.currentSession) {
|
|
101
|
-
return "this same thread";
|
|
102
|
-
}
|
|
103
115
|
return null;
|
|
104
116
|
}
|
|
105
117
|
function formatCurrentArtifact(frame, obligation) {
|
|
@@ -112,13 +124,27 @@ function formatCurrentArtifact(frame, obligation) {
|
|
|
112
124
|
if ((frame.codingSessions ?? []).length > 0) {
|
|
113
125
|
return "no PR or merge artifact yet";
|
|
114
126
|
}
|
|
115
|
-
if (
|
|
127
|
+
if (obligation) {
|
|
116
128
|
return "no artifact yet";
|
|
117
129
|
}
|
|
118
130
|
return null;
|
|
119
131
|
}
|
|
132
|
+
function formatObligationContentNextAction(obligation) {
|
|
133
|
+
const content = obligation?.content?.trim();
|
|
134
|
+
if (!content)
|
|
135
|
+
return null;
|
|
136
|
+
return `work on "${content}" and bring back a concrete artifact`;
|
|
137
|
+
}
|
|
120
138
|
function formatNextAction(frame, obligation) {
|
|
121
|
-
|
|
139
|
+
const obligationHasConcreteArtifact = Boolean(obligation?.currentArtifact?.trim())
|
|
140
|
+
|| obligation?.currentSurface?.kind === "merge";
|
|
141
|
+
if (obligation?.status === "waiting_for_merge") {
|
|
142
|
+
return obligation.nextAction?.trim() || `wait for checks, merge ${formatMergeArtifact(obligation)}, then update runtime`;
|
|
143
|
+
}
|
|
144
|
+
if (obligation?.status === "updating_runtime") {
|
|
145
|
+
return obligation.nextAction?.trim() || "update runtime, verify version/changelog, then re-observe";
|
|
146
|
+
}
|
|
147
|
+
if (obligationHasConcreteArtifact && obligation?.nextAction?.trim()) {
|
|
122
148
|
return obligation.nextAction.trim();
|
|
123
149
|
}
|
|
124
150
|
const liveCodingSession = frame.codingSessions?.[0];
|
|
@@ -131,19 +157,133 @@ function formatNextAction(frame, obligation) {
|
|
|
131
157
|
if (liveCodingSession) {
|
|
132
158
|
return "finish the coding pass and bring the result back here";
|
|
133
159
|
}
|
|
160
|
+
if (obligation?.nextAction?.trim())
|
|
161
|
+
return obligation.nextAction.trim();
|
|
162
|
+
if (obligation) {
|
|
163
|
+
return formatObligationContentNextAction(obligation) || "continue the active loop and bring the result back here";
|
|
164
|
+
}
|
|
165
|
+
if (frame.mustResolveBeforeHandoff) {
|
|
166
|
+
return "finish what i started here before moving on";
|
|
167
|
+
}
|
|
168
|
+
return null;
|
|
169
|
+
}
|
|
170
|
+
const RECENT_OTHER_LIVE_SESSION_WINDOW_MS = 60 * 60 * 1000;
|
|
171
|
+
function sessionOriginKey(origin) {
|
|
172
|
+
return `${origin.friendId}/${origin.channel}/${(0, config_1.sanitizeKey)(origin.key)}`;
|
|
173
|
+
}
|
|
174
|
+
function codingSessionTimestampMs(session) {
|
|
175
|
+
return Date.parse(session.lastActivityAt ?? session.startedAt);
|
|
176
|
+
}
|
|
177
|
+
function obligationTimestampMs(obligation) {
|
|
178
|
+
return Date.parse(obligation.updatedAt ?? obligation.createdAt);
|
|
179
|
+
}
|
|
180
|
+
function newestObligationFirst(left, right) {
|
|
181
|
+
return obligationTimestampMs(right) - obligationTimestampMs(left);
|
|
182
|
+
}
|
|
183
|
+
function formatOtherSessionArtifact(obligation, codingSession) {
|
|
184
|
+
if (obligation?.currentArtifact?.trim())
|
|
185
|
+
return obligation.currentArtifact.trim();
|
|
186
|
+
if (obligation?.currentSurface?.kind === "merge" && obligation.currentSurface.label.trim()) {
|
|
187
|
+
return obligation.currentSurface.label.trim();
|
|
188
|
+
}
|
|
189
|
+
if (codingSession)
|
|
190
|
+
return "no PR or merge artifact yet";
|
|
191
|
+
return obligation ? "no artifact yet" : "no explicit artifact yet";
|
|
192
|
+
}
|
|
193
|
+
function formatOtherSessionNextAction(obligation, codingSession) {
|
|
194
|
+
if (obligation?.nextAction?.trim())
|
|
195
|
+
return obligation.nextAction.trim();
|
|
134
196
|
if (obligation?.status === "waiting_for_merge") {
|
|
135
197
|
return `wait for checks, merge ${formatMergeArtifact(obligation)}, then update runtime`;
|
|
136
198
|
}
|
|
137
199
|
if (obligation?.status === "updating_runtime") {
|
|
138
200
|
return "update runtime, verify version/changelog, then re-observe";
|
|
139
201
|
}
|
|
140
|
-
if (
|
|
141
|
-
return
|
|
202
|
+
if (codingSession?.status === "waiting_input") {
|
|
203
|
+
return `answer ${formatCodingLaneLabel(codingSession)} and continue`;
|
|
142
204
|
}
|
|
143
|
-
if (
|
|
144
|
-
return `
|
|
205
|
+
if (codingSession?.status === "stalled") {
|
|
206
|
+
return `unstick ${formatCodingLaneLabel(codingSession)} and continue`;
|
|
145
207
|
}
|
|
146
|
-
|
|
208
|
+
if (codingSession) {
|
|
209
|
+
return "finish the coding pass and bring the result back there";
|
|
210
|
+
}
|
|
211
|
+
if (obligation) {
|
|
212
|
+
return formatObligationContentNextAction(obligation) || "continue the active loop and bring the result back there";
|
|
213
|
+
}
|
|
214
|
+
return "check this session and bring back the latest concrete state";
|
|
215
|
+
}
|
|
216
|
+
function formatOtherSessionLine(label, status, activeLane, artifact, nextAction) {
|
|
217
|
+
return `- ${label}: [${status}] ${activeLane}; artifact ${artifact}; next ${nextAction}`;
|
|
218
|
+
}
|
|
219
|
+
function formatOtherActiveSessionSummaries(frame, nowMs = Date.now()) {
|
|
220
|
+
const originMap = new Map();
|
|
221
|
+
for (const session of frame.friendActivity?.allOtherLiveSessions ?? []) {
|
|
222
|
+
if (session.friendId === "self" || session.channel === "inner")
|
|
223
|
+
continue;
|
|
224
|
+
originMap.set(sessionOriginKey(session), {
|
|
225
|
+
friendId: session.friendId,
|
|
226
|
+
channel: session.channel,
|
|
227
|
+
key: session.key,
|
|
228
|
+
});
|
|
229
|
+
}
|
|
230
|
+
const orphanCodingSummaries = (frame.otherCodingSessions ?? [])
|
|
231
|
+
.filter((session) => !session.originSession)
|
|
232
|
+
.sort((left, right) => codingSessionTimestampMs(right) - codingSessionTimestampMs(left))
|
|
233
|
+
.map((session) => ({
|
|
234
|
+
timestampMs: codingSessionTimestampMs(session),
|
|
235
|
+
line: formatOtherSessionLine("another session", session.status, formatCodingLaneLabel(session), "no PR or merge artifact yet", formatOtherSessionNextAction(null, session)),
|
|
236
|
+
}));
|
|
237
|
+
for (const session of frame.otherCodingSessions ?? []) {
|
|
238
|
+
if (!session.originSession)
|
|
239
|
+
continue;
|
|
240
|
+
if (frame.currentSession
|
|
241
|
+
&& session.originSession.friendId === frame.currentSession.friendId
|
|
242
|
+
&& session.originSession.channel === frame.currentSession.channel
|
|
243
|
+
&& (0, config_1.sanitizeKey)(session.originSession.key) === (0, config_1.sanitizeKey)(frame.currentSession.key)) {
|
|
244
|
+
continue;
|
|
245
|
+
}
|
|
246
|
+
originMap.set(sessionOriginKey(session.originSession), session.originSession);
|
|
247
|
+
}
|
|
248
|
+
for (const obligation of frame.pendingObligations ?? []) {
|
|
249
|
+
if (obligation.status === "fulfilled" || matchesCurrentSession(frame, obligation))
|
|
250
|
+
continue;
|
|
251
|
+
originMap.set(sessionOriginKey(obligation.origin), obligation.origin);
|
|
252
|
+
}
|
|
253
|
+
const summaries = [...originMap.values()].map((origin) => {
|
|
254
|
+
const originKey = sessionOriginKey(origin);
|
|
255
|
+
const obligation = [...(frame.pendingObligations ?? [])]
|
|
256
|
+
.filter((candidate) => candidate.status !== "fulfilled" && sessionOriginKey(candidate.origin) === originKey)
|
|
257
|
+
.sort(newestObligationFirst)[0] ?? null;
|
|
258
|
+
const codingSession = [...(frame.otherCodingSessions ?? [])]
|
|
259
|
+
.filter((candidate) => candidate.originSession && sessionOriginKey(candidate.originSession) === originKey)
|
|
260
|
+
.sort((left, right) => codingSessionTimestampMs(right) - codingSessionTimestampMs(left))[0] ?? null;
|
|
261
|
+
const liveSession = (frame.friendActivity?.allOtherLiveSessions ?? []).find((candidate) => sessionOriginKey(candidate) === originKey) ?? null;
|
|
262
|
+
const hasMaterialLiveSession = liveSession
|
|
263
|
+
? ((nowMs - liveSession.lastActivityMs) <= RECENT_OTHER_LIVE_SESSION_WINDOW_MS
|
|
264
|
+
|| (frame.currentSession != null
|
|
265
|
+
&& liveSession.friendId === frame.currentSession.friendId
|
|
266
|
+
&& liveSession.channel !== frame.currentSession.channel))
|
|
267
|
+
: false;
|
|
268
|
+
if (!obligation && !codingSession && !hasMaterialLiveSession) {
|
|
269
|
+
return null;
|
|
270
|
+
}
|
|
271
|
+
const timestampMs = Math.max(liveSession?.lastActivityMs ?? 0, codingSession ? codingSessionTimestampMs(codingSession) : 0, obligation ? obligationTimestampMs(obligation) : 0);
|
|
272
|
+
const activeLane = codingSession
|
|
273
|
+
? formatCodingLaneLabel(codingSession)
|
|
274
|
+
: obligation?.currentSurface?.label?.trim() || "this live thread";
|
|
275
|
+
const artifact = formatOtherSessionArtifact(obligation, codingSession);
|
|
276
|
+
const nextAction = formatOtherSessionNextAction(obligation, codingSession);
|
|
277
|
+
const status = obligation?.status ?? codingSession?.status ?? "active";
|
|
278
|
+
const label = liveSession?.friendName ?? origin.friendId;
|
|
279
|
+
return {
|
|
280
|
+
timestampMs,
|
|
281
|
+
line: formatOtherSessionLine(`${label}/${origin.channel}/${origin.key}`, status, activeLane, artifact, nextAction),
|
|
282
|
+
};
|
|
283
|
+
}).filter((entry) => entry !== null)
|
|
284
|
+
.sort((left, right) => right.timestampMs - left.timestampMs);
|
|
285
|
+
const lines = summaries.map((entry) => entry.line);
|
|
286
|
+
return [...lines, ...orphanCodingSummaries.map((entry) => entry.line)];
|
|
147
287
|
}
|
|
148
288
|
function suggestBridgeForActiveWork(input) {
|
|
149
289
|
const targetCandidates = (input.targetCandidates ?? [])
|
|
@@ -164,10 +304,17 @@ function suggestBridgeForActiveWork(input) {
|
|
|
164
304
|
.sort((a, b) => {
|
|
165
305
|
return b.lastActivityMs - a.lastActivityMs;
|
|
166
306
|
});
|
|
167
|
-
if (!hasSharedObligationPressure(
|
|
307
|
+
if (!hasSharedObligationPressure({
|
|
308
|
+
mustResolveBeforeHandoff: input.mustResolveBeforeHandoff,
|
|
309
|
+
taskBoard: input.taskBoard,
|
|
310
|
+
pendingObligations: input.pendingObligations,
|
|
311
|
+
}) || targetCandidates.length === 0) {
|
|
168
312
|
return null;
|
|
169
313
|
}
|
|
170
314
|
const targetSession = targetCandidates[0];
|
|
315
|
+
const objectiveHint = [...(input.pendingObligations ?? [])]
|
|
316
|
+
.find((obligation) => (0, obligations_1.isOpenObligationStatus)(obligation.status))
|
|
317
|
+
?.content?.trim() || "keep this shared work aligned";
|
|
171
318
|
const activeBridge = input.bridges.find(isActiveBridge) ?? null;
|
|
172
319
|
if (activeBridge) {
|
|
173
320
|
const alreadyAttached = activeBridge.attachedSessions.some((session) => session.friendId === targetSession.friendId
|
|
@@ -186,7 +333,7 @@ function suggestBridgeForActiveWork(input) {
|
|
|
186
333
|
return {
|
|
187
334
|
kind: "begin-new",
|
|
188
335
|
targetSession,
|
|
189
|
-
objectiveHint
|
|
336
|
+
objectiveHint,
|
|
190
337
|
reason: "shared-work-candidate",
|
|
191
338
|
};
|
|
192
339
|
}
|
|
@@ -237,6 +384,7 @@ function buildActiveWorkFrame(input) {
|
|
|
237
384
|
currentObligation: input.currentObligation,
|
|
238
385
|
mustResolveBeforeHandoff: input.mustResolveBeforeHandoff,
|
|
239
386
|
bridges: input.bridges,
|
|
387
|
+
pendingObligations: input.pendingObligations,
|
|
240
388
|
taskBoard: input.taskBoard,
|
|
241
389
|
targetCandidates: input.targetCandidates,
|
|
242
390
|
}),
|
|
@@ -263,16 +411,16 @@ function buildActiveWorkFrame(input) {
|
|
|
263
411
|
function formatActiveWorkFrame(frame) {
|
|
264
412
|
const lines = ["## what i'm holding"];
|
|
265
413
|
const primaryObligation = findPrimaryOpenObligation(frame);
|
|
414
|
+
const currentSessionObligation = findCurrentSessionOpenObligation(frame);
|
|
266
415
|
const activeLane = formatActiveLane(frame, primaryObligation);
|
|
267
416
|
const currentArtifact = formatCurrentArtifact(frame, primaryObligation);
|
|
268
417
|
const nextAction = formatNextAction(frame, primaryObligation);
|
|
269
|
-
const
|
|
270
|
-
const otherLiveSessions = frame.friendActivity?.allOtherLiveSessions ?? [];
|
|
418
|
+
const otherActiveSessions = formatOtherActiveSessionSummaries(frame);
|
|
271
419
|
// Session line
|
|
272
420
|
if (frame.currentSession) {
|
|
273
421
|
let sessionLine = `i'm in a conversation on ${formatSessionLabel(frame.currentSession)}.`;
|
|
274
|
-
if (
|
|
275
|
-
sessionLine += ` i
|
|
422
|
+
if (currentSessionObligation?.content?.trim()) {
|
|
423
|
+
sessionLine += ` i still owe them: ${currentSessionObligation.content.trim()}.`;
|
|
276
424
|
}
|
|
277
425
|
else if (frame.mustResolveBeforeHandoff) {
|
|
278
426
|
sessionLine += " i need to finish what i started here before moving on.";
|
|
@@ -340,22 +488,10 @@ function formatActiveWorkFrame(frame) {
|
|
|
340
488
|
lines.push(`- [${session.status}] ${formatCodingLaneLabel(session)}${describeCodingSessionScope(session, frame.currentSession)}`);
|
|
341
489
|
}
|
|
342
490
|
}
|
|
343
|
-
if (
|
|
344
|
-
lines.push("");
|
|
345
|
-
lines.push("## other live coding work");
|
|
346
|
-
for (const session of otherCodingSessions) {
|
|
347
|
-
const origin = session.originSession
|
|
348
|
-
? `${session.originSession.friendId}/${session.originSession.channel}/${session.originSession.key}`
|
|
349
|
-
: "another session";
|
|
350
|
-
lines.push(`- [${session.status}] ${formatCodingLaneLabel(session)} for ${origin}`);
|
|
351
|
-
}
|
|
352
|
-
}
|
|
353
|
-
if (otherLiveSessions.length > 0) {
|
|
491
|
+
if (otherActiveSessions.length > 0) {
|
|
354
492
|
lines.push("");
|
|
355
|
-
lines.push("## other
|
|
356
|
-
|
|
357
|
-
lines.push(`- ${session.friendName}/${session.channel}/${session.key}`);
|
|
358
|
-
}
|
|
493
|
+
lines.push("## other active sessions");
|
|
494
|
+
lines.push(...otherActiveSessions);
|
|
359
495
|
}
|
|
360
496
|
// Task pressure
|
|
361
497
|
if ((frame.taskPressure?.liveTaskNames ?? []).length > 0) {
|
|
@@ -34,10 +34,6 @@ function deriveCommitments(activeWorkFrame, innerJob, pendingObligations) {
|
|
|
34
34
|
completionCriteria.push("close my active obligation loops");
|
|
35
35
|
}
|
|
36
36
|
}
|
|
37
|
-
// Obligation (from current turn -- kept for backward compat)
|
|
38
|
-
if (typeof activeWorkFrame.currentObligation === "string" && activeWorkFrame.currentObligation.trim().length > 0) {
|
|
39
|
-
committedTo.push(`i told them i'd ${activeWorkFrame.currentObligation.trim()}`);
|
|
40
|
-
}
|
|
41
37
|
// Inner job
|
|
42
38
|
if (innerJob.status === "queued" || innerJob.status === "running") {
|
|
43
39
|
const contentSuffix = innerJob.content ? ` -- ${innerJob.content.slice(0, 60)}` : "";
|
package/dist/heart/core.js
CHANGED
|
@@ -27,7 +27,6 @@ const azure_1 = require("./providers/azure");
|
|
|
27
27
|
const minimax_1 = require("./providers/minimax");
|
|
28
28
|
const openai_codex_1 = require("./providers/openai-codex");
|
|
29
29
|
const github_copilot_1 = require("./providers/github-copilot");
|
|
30
|
-
const obligation_steering_1 = require("../mind/obligation-steering");
|
|
31
30
|
const pending_1 = require("../mind/pending");
|
|
32
31
|
const identity_2 = require("./identity");
|
|
33
32
|
const socket_client_1 = require("./daemon/socket-client");
|
|
@@ -273,45 +272,6 @@ function getFinalAnswerRetryError(mustResolveBeforeHandoff, intent, sawSteeringF
|
|
|
273
272
|
}
|
|
274
273
|
return null;
|
|
275
274
|
}
|
|
276
|
-
function hasExactStatusReplyShape(answer, statusCheckScope) {
|
|
277
|
-
const lines = answer.trimEnd().split(/\r?\n/);
|
|
278
|
-
const hasFiveLineHeader = (/^live conversation:\s+\S.+$/i.test(lines[0])
|
|
279
|
-
&& /^active lane:\s+\S.+$/i.test(lines[1])
|
|
280
|
-
&& /^current artifact:\s+\S.+$/i.test(lines[2])
|
|
281
|
-
&& /^latest checkpoint:\s+\S.+$/i.test(lines[3])
|
|
282
|
-
&& /^next action:\s+\S.+$/i.test(lines[4]));
|
|
283
|
-
if (!hasFiveLineHeader)
|
|
284
|
-
return false;
|
|
285
|
-
if (statusCheckScope !== "all-sessions-family") {
|
|
286
|
-
return lines.length === 5;
|
|
287
|
-
}
|
|
288
|
-
if (lines.length < 7)
|
|
289
|
-
return false;
|
|
290
|
-
if (!/^other active sessions:\s*$/i.test(lines[5]))
|
|
291
|
-
return false;
|
|
292
|
-
return lines.slice(6).every((line) => /^-\s+\S.+$/i.test(line));
|
|
293
|
-
}
|
|
294
|
-
function extractLatestCheckpoint(answer) {
|
|
295
|
-
const latestLine = answer.trimEnd().split(/\r?\n/)[3];
|
|
296
|
-
return latestLine.replace(/^latest checkpoint:\s*/i, "").trim();
|
|
297
|
-
}
|
|
298
|
-
function getStatusReplyRetryError(answer, statusCheckRequested, activeWorkFrame, statusCheckScope) {
|
|
299
|
-
if (!statusCheckRequested || answer == null)
|
|
300
|
-
return null;
|
|
301
|
-
if (hasExactStatusReplyShape(answer, statusCheckScope))
|
|
302
|
-
return null;
|
|
303
|
-
if (!activeWorkFrame) {
|
|
304
|
-
return `the user asked for current status. call final_answer again using exactly these five non-empty lines and nothing else:
|
|
305
|
-
live conversation: ...
|
|
306
|
-
active lane: ...
|
|
307
|
-
current artifact: ...
|
|
308
|
-
latest checkpoint: ...
|
|
309
|
-
next action: ...`;
|
|
310
|
-
}
|
|
311
|
-
return `the user asked for current status right now.
|
|
312
|
-
${(0, obligation_steering_1.renderExactStatusReplyContract)(activeWorkFrame, (0, obligation_steering_1.findStatusObligation)(activeWorkFrame), statusCheckScope)}
|
|
313
|
-
call final_answer again using that exact status shape and nothing else.`;
|
|
314
|
-
}
|
|
315
275
|
// Re-export kick utilities for backward compat
|
|
316
276
|
var kicks_1 = require("./kicks");
|
|
317
277
|
Object.defineProperty(exports, "hasToolIntent", { enumerable: true, get: function () { return kicks_1.hasToolIntent; } });
|
|
@@ -591,7 +551,7 @@ async function runAgent(messages, callbacks, channel, signal, options) {
|
|
|
591
551
|
traceId,
|
|
592
552
|
toolChoiceRequired,
|
|
593
553
|
reasoningEffort: currentReasoningEffort,
|
|
594
|
-
eagerFinalAnswerStreaming:
|
|
554
|
+
eagerFinalAnswerStreaming: true,
|
|
595
555
|
});
|
|
596
556
|
// Track usage from the latest API call
|
|
597
557
|
if (result.usage)
|
|
@@ -640,21 +600,16 @@ async function runAgent(messages, callbacks, channel, signal, options) {
|
|
|
640
600
|
// Supports: {"answer":"text","intent":"..."} or "text" (JSON string).
|
|
641
601
|
const { answer, intent } = parseFinalAnswerPayload(result.toolCalls[0].arguments);
|
|
642
602
|
const retryError = getFinalAnswerRetryError(mustResolveBeforeHandoffActive, intent, sawSteeringFollowUp, options?.delegationDecision, sawSendMessageSelf, sawGoInward, sawQuerySession, options?.currentObligation ?? null, options?.activeWorkFrame?.inner?.job, sawExternalStateQuery);
|
|
643
|
-
const
|
|
644
|
-
const exactStatusReplyAccepted = Boolean(options?.statusCheckRequested) && !statusReplyRetryError && answer != null;
|
|
645
|
-
const deliveredAnswer = exactStatusReplyAccepted && options?.activeWorkFrame
|
|
646
|
-
? (0, obligation_steering_1.buildExactStatusReply)(options.activeWorkFrame, (0, obligation_steering_1.findStatusObligation)(options.activeWorkFrame), extractLatestCheckpoint(answer), options?.statusCheckScope)
|
|
647
|
-
: answer;
|
|
603
|
+
const deliveredAnswer = answer;
|
|
648
604
|
const validDirectReply = mustResolveBeforeHandoffActive && intent === "direct_reply" && sawSteeringFollowUp;
|
|
649
605
|
const validTerminalIntent = intent === "complete" || intent === "blocked";
|
|
650
606
|
const validClosure = deliveredAnswer != null
|
|
651
|
-
&&
|
|
652
|
-
&& !
|
|
653
|
-
&& (exactStatusReplyAccepted || !mustResolveBeforeHandoffActive || validDirectReply || validTerminalIntent);
|
|
607
|
+
&& !retryError
|
|
608
|
+
&& (!mustResolveBeforeHandoffActive || validDirectReply || validTerminalIntent);
|
|
654
609
|
if (validClosure) {
|
|
655
610
|
completion = {
|
|
656
611
|
answer: deliveredAnswer,
|
|
657
|
-
intent: validDirectReply
|
|
612
|
+
intent: validDirectReply ? "direct_reply" : intent === "blocked" ? "blocked" : "complete",
|
|
658
613
|
};
|
|
659
614
|
if (result.finalAnswerStreamed) {
|
|
660
615
|
// The streaming layer already parsed and emitted the answer
|
|
@@ -669,7 +624,7 @@ async function runAgent(messages, callbacks, channel, signal, options) {
|
|
|
669
624
|
callbacks.onTextChunk(deliveredAnswer);
|
|
670
625
|
}
|
|
671
626
|
messages.push(msg);
|
|
672
|
-
if (validDirectReply
|
|
627
|
+
if (validDirectReply) {
|
|
673
628
|
const resumeWork = "direct reply delivered. resume the unresolved obligation now and keep working until you can finish or clearly report that you are blocked.";
|
|
674
629
|
messages.push({ role: "tool", tool_call_id: result.toolCalls[0].id, content: resumeWork });
|
|
675
630
|
providerRuntime.appendToolOutput(result.toolCalls[0].id, resumeWork);
|
|
@@ -688,8 +643,7 @@ async function runAgent(messages, callbacks, channel, signal, options) {
|
|
|
688
643
|
// assistant msg + error tool result and let the model try again.
|
|
689
644
|
callbacks.onClearText?.();
|
|
690
645
|
messages.push(msg);
|
|
691
|
-
const toolRetryMessage =
|
|
692
|
-
?? retryError
|
|
646
|
+
const toolRetryMessage = retryError
|
|
693
647
|
?? "your final_answer was incomplete or malformed. call final_answer again with your complete response.";
|
|
694
648
|
messages.push({ role: "tool", tool_call_id: result.toolCalls[0].id, content: toolRetryMessage });
|
|
695
649
|
providerRuntime.appendToolOutput(result.toolCalls[0].id, toolRetryMessage);
|
|
@@ -8,8 +8,8 @@ exports.renderLiveThreadStatusShape = renderLiveThreadStatusShape;
|
|
|
8
8
|
exports.buildExactStatusReply = buildExactStatusReply;
|
|
9
9
|
exports.renderExactStatusReplyContract = renderExactStatusReplyContract;
|
|
10
10
|
const config_1 = require("../heart/config");
|
|
11
|
+
const active_work_1 = require("../heart/active-work");
|
|
11
12
|
const runtime_1 = require("../nerves/runtime");
|
|
12
|
-
const RECENT_OTHER_LIVE_SESSION_WINDOW_MS = 60 * 60 * 1000;
|
|
13
13
|
function findActivePersistentObligation(frame) {
|
|
14
14
|
if (!frame)
|
|
15
15
|
return null;
|
|
@@ -30,102 +30,6 @@ function matchesSessionOrigin(frame, origin) {
|
|
|
30
30
|
&& origin.channel === frame.currentSession.channel
|
|
31
31
|
&& (0, config_1.sanitizeKey)(origin.key) === (0, config_1.sanitizeKey)(frame.currentSession.key));
|
|
32
32
|
}
|
|
33
|
-
function sessionOriginKey(origin) {
|
|
34
|
-
return `${origin.friendId}/${origin.channel}/${(0, config_1.sanitizeKey)(origin.key)}`;
|
|
35
|
-
}
|
|
36
|
-
function codingSessionTimestampMs(session) {
|
|
37
|
-
return Date.parse(session.lastActivityAt ?? session.startedAt);
|
|
38
|
-
}
|
|
39
|
-
function formatCodingLaneLabel(session) {
|
|
40
|
-
return `${session.runner} ${session.id}`;
|
|
41
|
-
}
|
|
42
|
-
function formatOtherSessionArtifact(obligation, codingSession) {
|
|
43
|
-
if (obligation?.currentArtifact?.trim())
|
|
44
|
-
return obligation.currentArtifact.trim();
|
|
45
|
-
if (obligation?.currentSurface?.kind === "merge" && obligation.currentSurface.label.trim()) {
|
|
46
|
-
return obligation.currentSurface.label.trim();
|
|
47
|
-
}
|
|
48
|
-
if (codingSession)
|
|
49
|
-
return "no PR or merge artifact yet";
|
|
50
|
-
return "no artifact yet";
|
|
51
|
-
}
|
|
52
|
-
function formatOtherSessionNextAction(obligation, codingSession) {
|
|
53
|
-
if (obligation?.nextAction?.trim())
|
|
54
|
-
return obligation.nextAction.trim();
|
|
55
|
-
if (obligation?.status === "waiting_for_merge") {
|
|
56
|
-
return `wait for checks, merge ${formatMergeArtifact(obligation)}, then update runtime`;
|
|
57
|
-
}
|
|
58
|
-
if (obligation?.status === "updating_runtime") {
|
|
59
|
-
return "update runtime, verify version/changelog, then re-observe";
|
|
60
|
-
}
|
|
61
|
-
if (codingSession?.status === "waiting_input") {
|
|
62
|
-
return `answer ${formatCodingLaneLabel(codingSession)} and continue`;
|
|
63
|
-
}
|
|
64
|
-
if (codingSession?.status === "stalled") {
|
|
65
|
-
return `unstick ${formatCodingLaneLabel(codingSession)} and continue`;
|
|
66
|
-
}
|
|
67
|
-
if (codingSession) {
|
|
68
|
-
return "finish the coding pass and bring the result back there";
|
|
69
|
-
}
|
|
70
|
-
if (obligation) {
|
|
71
|
-
return "continue the active loop and bring the result back there";
|
|
72
|
-
}
|
|
73
|
-
return "check this session and bring back the latest concrete state";
|
|
74
|
-
}
|
|
75
|
-
function findFriendNameForOrigin(frame, origin) {
|
|
76
|
-
return (frame.friendActivity?.allOtherLiveSessions ?? []).find((entry) => sessionOriginKey(entry) === sessionOriginKey(origin))?.friendName ?? origin.friendId;
|
|
77
|
-
}
|
|
78
|
-
function buildOtherActiveSessionLines(frame) {
|
|
79
|
-
const originMap = new Map();
|
|
80
|
-
for (const session of frame.friendActivity?.allOtherLiveSessions ?? []) {
|
|
81
|
-
if (session.friendId === "self" || session.channel === "inner")
|
|
82
|
-
continue;
|
|
83
|
-
originMap.set(sessionOriginKey(session), {
|
|
84
|
-
friendId: session.friendId,
|
|
85
|
-
channel: session.channel,
|
|
86
|
-
key: session.key,
|
|
87
|
-
});
|
|
88
|
-
}
|
|
89
|
-
for (const session of frame.otherCodingSessions ?? []) {
|
|
90
|
-
if (!session.originSession || matchesSessionOrigin(frame, session.originSession))
|
|
91
|
-
continue;
|
|
92
|
-
originMap.set(sessionOriginKey(session.originSession), session.originSession);
|
|
93
|
-
}
|
|
94
|
-
for (const obligation of frame.pendingObligations ?? []) {
|
|
95
|
-
if (obligation.status === "fulfilled" || matchesSessionOrigin(frame, obligation.origin))
|
|
96
|
-
continue;
|
|
97
|
-
originMap.set(sessionOriginKey(obligation.origin), obligation.origin);
|
|
98
|
-
}
|
|
99
|
-
const summaries = [...originMap.values()].map((origin) => {
|
|
100
|
-
const obligation = [...(frame.pendingObligations ?? [])]
|
|
101
|
-
.filter((candidate) => candidate.status !== "fulfilled" && sessionOriginKey(candidate.origin) === sessionOriginKey(origin))
|
|
102
|
-
.sort(newestObligationFirst)[0] ?? null;
|
|
103
|
-
const codingSession = [...(frame.otherCodingSessions ?? [])]
|
|
104
|
-
.filter((candidate) => candidate.originSession && sessionOriginKey(candidate.originSession) === sessionOriginKey(origin))
|
|
105
|
-
.sort((left, right) => codingSessionTimestampMs(right) - codingSessionTimestampMs(left))[0] ?? null;
|
|
106
|
-
const liveSession = (frame.friendActivity?.allOtherLiveSessions ?? []).find((candidate) => sessionOriginKey(candidate) === sessionOriginKey(origin)) ?? null;
|
|
107
|
-
const hasFreshSessionActivity = liveSession
|
|
108
|
-
? (Date.now() - liveSession.lastActivityMs) <= RECENT_OTHER_LIVE_SESSION_WINDOW_MS
|
|
109
|
-
: false;
|
|
110
|
-
if (!obligation && !codingSession && !hasFreshSessionActivity) {
|
|
111
|
-
return null;
|
|
112
|
-
}
|
|
113
|
-
const timestampMs = Math.max(liveSession?.lastActivityMs ?? 0, codingSession ? codingSessionTimestampMs(codingSession) : 0, obligation ? obligationTimestampMs(obligation) : 0);
|
|
114
|
-
const activeLane = codingSession
|
|
115
|
-
? formatCodingLaneLabel(codingSession)
|
|
116
|
-
: obligation?.currentSurface?.label?.trim() || "this live thread";
|
|
117
|
-
const artifact = formatOtherSessionArtifact(obligation, codingSession);
|
|
118
|
-
const nextAction = formatOtherSessionNextAction(obligation, codingSession);
|
|
119
|
-
const status = obligation?.status ?? codingSession?.status ?? "active";
|
|
120
|
-
const friendName = findFriendNameForOrigin(frame, origin);
|
|
121
|
-
return {
|
|
122
|
-
timestampMs,
|
|
123
|
-
line: `- ${friendName}/${origin.channel}/${origin.key}: [${status}] ${activeLane}; artifact ${artifact}; next ${nextAction}`,
|
|
124
|
-
};
|
|
125
|
-
}).filter((entry) => entry !== null)
|
|
126
|
-
.sort((left, right) => right.timestampMs - left.timestampMs);
|
|
127
|
-
return summaries.length > 0 ? summaries.map((entry) => entry.line) : ["- none"];
|
|
128
|
-
}
|
|
129
33
|
function findStatusObligation(frame) {
|
|
130
34
|
if (!frame)
|
|
131
35
|
return null;
|
|
@@ -197,30 +101,29 @@ function formatActiveLane(frame, obligation) {
|
|
|
197
101
|
: `${liveCodingSession.runner} ${liveCodingSession.id}`;
|
|
198
102
|
}
|
|
199
103
|
return obligation.currentSurface?.label
|
|
200
|
-
|| (frame
|
|
104
|
+
|| (matchesCurrentSession(frame, obligation) ? "this same thread" : "this live loop");
|
|
201
105
|
}
|
|
202
106
|
function formatCurrentArtifact(frame, obligation) {
|
|
203
107
|
if (obligation?.currentArtifact)
|
|
204
108
|
return obligation.currentArtifact;
|
|
205
109
|
if (obligation?.currentSurface?.kind === "merge")
|
|
206
110
|
return obligation.currentSurface.label;
|
|
207
|
-
if (frame.currentObligation?.trim())
|
|
208
|
-
return "no artifact yet";
|
|
209
111
|
if ((frame.codingSessions ?? []).length > 0)
|
|
210
112
|
return "no PR or merge artifact yet";
|
|
211
|
-
return obligation ? "no
|
|
212
|
-
}
|
|
213
|
-
function isStatusCheckPrompt(text) {
|
|
214
|
-
const trimmed = text?.trim();
|
|
215
|
-
if (!trimmed)
|
|
216
|
-
return false;
|
|
217
|
-
return /^(what are you doing|what(?:'|’)s your status|status|status update|what changed|where are you at|where things stand)\??$/i.test(trimmed);
|
|
113
|
+
return obligation ? "no artifact yet" : "";
|
|
218
114
|
}
|
|
219
115
|
function formatNextAction(frame, obligation) {
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
116
|
+
const obligationHasConcreteArtifact = Boolean(obligation?.currentArtifact?.trim())
|
|
117
|
+
|| obligation?.currentSurface?.kind === "merge";
|
|
118
|
+
if (obligation?.status === "waiting_for_merge") {
|
|
119
|
+
return obligation.nextAction?.trim() || `wait for checks, merge ${formatMergeArtifact(obligation)}, then update runtime`;
|
|
120
|
+
}
|
|
121
|
+
if (obligation?.status === "updating_runtime") {
|
|
122
|
+
return obligation.nextAction?.trim() || "update runtime, verify version/changelog, then re-observe";
|
|
123
|
+
}
|
|
124
|
+
if (obligationHasConcreteArtifact && obligation?.nextAction?.trim()) {
|
|
125
|
+
return obligation.nextAction.trim();
|
|
126
|
+
}
|
|
224
127
|
const liveCodingSession = frame.codingSessions?.[0];
|
|
225
128
|
if (liveCodingSession?.status === "waiting_input") {
|
|
226
129
|
return `answer ${liveCodingSession.runner} ${liveCodingSession.id} and continue`;
|
|
@@ -231,19 +134,15 @@ function formatNextAction(frame, obligation) {
|
|
|
231
134
|
if (liveCodingSession) {
|
|
232
135
|
return "finish the coding pass and bring the result back here";
|
|
233
136
|
}
|
|
234
|
-
if (obligation?.
|
|
235
|
-
return
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
return "update runtime, verify version/changelog, then re-observe";
|
|
239
|
-
}
|
|
240
|
-
if (currentObligation && !statusCheckPrompt) {
|
|
241
|
-
return `work on "${currentObligation}" and bring back a concrete artifact`;
|
|
137
|
+
if (obligation?.nextAction?.trim())
|
|
138
|
+
return obligation.nextAction.trim();
|
|
139
|
+
if (obligation?.content?.trim()) {
|
|
140
|
+
return `work on "${obligation.content.trim()}" and bring back a concrete artifact`;
|
|
242
141
|
}
|
|
243
142
|
return obligation ? "continue the active loop and bring the result back here" : "";
|
|
244
143
|
}
|
|
245
144
|
function renderConcreteStatusGuidance(frame, obligation) {
|
|
246
|
-
const activeLane = obligation ? formatActiveLane(frame, obligation) :
|
|
145
|
+
const activeLane = obligation ? formatActiveLane(frame, obligation) : "";
|
|
247
146
|
const currentArtifact = formatCurrentArtifact(frame, obligation);
|
|
248
147
|
const nextAction = formatNextAction(frame, obligation);
|
|
249
148
|
const liveConversation = frame.currentSession
|
|
@@ -258,7 +157,7 @@ the current artifact is ${currentArtifact}.
|
|
|
258
157
|
if i just finished or verified something concrete in this live lane, i name that as the latest checkpoint.
|
|
259
158
|
the next action is ${nextAction}.
|
|
260
159
|
|
|
261
|
-
i
|
|
160
|
+
i answer naturally from those facts instead of forcing a canned status block.`;
|
|
262
161
|
}
|
|
263
162
|
function renderLiveThreadStatusShape(frame) {
|
|
264
163
|
if (!frame.currentSession)
|
|
@@ -297,7 +196,8 @@ function buildExactStatusReply(frame, obligation, latestCheckpoint, statusCheckS
|
|
|
297
196
|
];
|
|
298
197
|
if (statusCheckScope === "all-sessions-family") {
|
|
299
198
|
lines.push("other active sessions:");
|
|
300
|
-
|
|
199
|
+
const summaries = (0, active_work_1.formatOtherActiveSessionSummaries)(frame);
|
|
200
|
+
lines.push(...(summaries.length > 0 ? summaries : ["- none"]));
|
|
301
201
|
}
|
|
302
202
|
return lines.join("\n");
|
|
303
203
|
}
|
package/dist/mind/prompt.js
CHANGED
|
@@ -457,7 +457,24 @@ function activeWorkSection(options) {
|
|
|
457
457
|
return "";
|
|
458
458
|
return (0, active_work_1.formatActiveWorkFrame)(options.activeWorkFrame);
|
|
459
459
|
}
|
|
460
|
-
function
|
|
460
|
+
function familyCrossSessionTruthSection(context, options) {
|
|
461
|
+
if (!options?.activeWorkFrame)
|
|
462
|
+
return "";
|
|
463
|
+
if (context?.friend?.trustLevel !== "family")
|
|
464
|
+
return "";
|
|
465
|
+
return `## cross-session truth
|
|
466
|
+
if a family member asks what i'm up to or how things are going, that includes the material live work i can see across sessions, not just this thread.
|
|
467
|
+
i answer naturally from the live world-state in this prompt.
|
|
468
|
+
i do not rely on canned status-question modes or phrase matching.
|
|
469
|
+
if part of the picture is still fuzzy, i say what i can see and what still needs checking.
|
|
470
|
+
when the live ask is about status, i widen before answering:
|
|
471
|
+
- where i am right now
|
|
472
|
+
- any other material active sessions or coding lanes i can see
|
|
473
|
+
- the freshest concrete checkpoint
|
|
474
|
+
- the next concrete step
|
|
475
|
+
i do not collapse down to only the current lane.`;
|
|
476
|
+
}
|
|
477
|
+
function centerOfGravitySteeringSection(channel, options, context) {
|
|
461
478
|
if (channel === "inner")
|
|
462
479
|
return "";
|
|
463
480
|
const frame = options?.activeWorkFrame;
|
|
@@ -512,8 +529,15 @@ i should bring my answer back to the conversation it came from.`;
|
|
|
512
529
|
: liveCodingSession.originSession
|
|
513
530
|
? ` for ${liveCodingSession.originSession.channel}/${liveCodingSession.originSession.key}`
|
|
514
531
|
: "";
|
|
532
|
+
const otherSessionLines = (0, active_work_1.formatOtherActiveSessionSummaries)(frame);
|
|
533
|
+
const familyStatusClause = context?.friend?.trustLevel === "family"
|
|
534
|
+
? `\nif a family member asks what i'm up to, i treat this coding lane as one part of the visible picture, not the whole picture.
|
|
535
|
+
after i name this lane, i widen back out with:
|
|
536
|
+
other active sessions:
|
|
537
|
+
${otherSessionLines.length > 0 ? otherSessionLines.join("\n") : "- none"}`
|
|
538
|
+
: "";
|
|
515
539
|
return `## where my attention is
|
|
516
|
-
i already have coding work running in ${liveCodingSession.runner} ${liveCodingSession.id}${scopeClause}
|
|
540
|
+
i already have coding work running in ${liveCodingSession.runner} ${liveCodingSession.id}${scopeClause}.${familyStatusClause}
|
|
517
541
|
|
|
518
542
|
i should orient around that live lane first, then decide what still needs to come back here.`;
|
|
519
543
|
}
|
|
@@ -535,17 +559,6 @@ i should keep the different sides aligned. what i learn here may matter there, a
|
|
|
535
559
|
/* v8 ignore next -- unreachable: all center-of-gravity modes covered above @preserve */
|
|
536
560
|
return "";
|
|
537
561
|
}
|
|
538
|
-
function statusCheckSection(channel, options) {
|
|
539
|
-
if (channel === "inner" || !options?.statusCheckRequested)
|
|
540
|
-
return "";
|
|
541
|
-
const frame = options.activeWorkFrame;
|
|
542
|
-
if (!frame)
|
|
543
|
-
return "";
|
|
544
|
-
const activeObligation = (0, obligation_steering_1.findStatusObligation)(frame);
|
|
545
|
-
return `## status question on this turn
|
|
546
|
-
the user is asking for current status right now.
|
|
547
|
-
${(0, obligation_steering_1.renderExactStatusReplyContract)(frame, activeObligation, options.statusCheckScope)}`;
|
|
548
|
-
}
|
|
549
562
|
function commitmentsSection(options) {
|
|
550
563
|
if (!options?.activeWorkFrame)
|
|
551
564
|
return "";
|
|
@@ -753,8 +766,8 @@ async function buildSystem(channel = "cli", options, context) {
|
|
|
753
766
|
skillsSection(),
|
|
754
767
|
taskBoardSection(),
|
|
755
768
|
activeWorkSection(options),
|
|
756
|
-
|
|
757
|
-
centerOfGravitySteeringSection(channel, options),
|
|
769
|
+
familyCrossSessionTruthSection(context, options),
|
|
770
|
+
centerOfGravitySteeringSection(channel, options, context),
|
|
758
771
|
commitmentsSection(options),
|
|
759
772
|
delegationHintSection(options),
|
|
760
773
|
bridgeContextSection(options),
|
package/dist/senses/pipeline.js
CHANGED
|
@@ -38,23 +38,6 @@ function emptyTaskBoard() {
|
|
|
38
38
|
activeBridges: [],
|
|
39
39
|
};
|
|
40
40
|
}
|
|
41
|
-
const STATUS_CHECK_PATTERNS = [
|
|
42
|
-
/^\s*what are you doing\??\s*$/i,
|
|
43
|
-
/^\s*what'?s your status\??\s*$/i,
|
|
44
|
-
/^\s*status\??\s*$/i,
|
|
45
|
-
/^\s*status update\??\s*$/i,
|
|
46
|
-
/^\s*what changed\??\s*$/i,
|
|
47
|
-
/^\s*where (?:are you at|things stand)\??\s*$/i,
|
|
48
|
-
];
|
|
49
|
-
function isStatusCheckRequested(ingressTexts) {
|
|
50
|
-
const latest = ingressTexts
|
|
51
|
-
?.map((text) => text.trim())
|
|
52
|
-
.filter((text) => text.length > 0)
|
|
53
|
-
.at(-1);
|
|
54
|
-
if (!latest)
|
|
55
|
-
return false;
|
|
56
|
-
return STATUS_CHECK_PATTERNS.some((pattern) => pattern.test(latest));
|
|
57
|
-
}
|
|
58
41
|
function isLiveCodingSessionStatus(status) {
|
|
59
42
|
return status === "spawning"
|
|
60
43
|
|| status === "running"
|
|
@@ -293,10 +276,6 @@ async function handleInboundTurn(input) {
|
|
|
293
276
|
}
|
|
294
277
|
// Step 5: runAgent
|
|
295
278
|
const existingToolContext = input.runAgentOptions?.toolContext;
|
|
296
|
-
const statusCheckRequested = isStatusCheckRequested(input.continuityIngressTexts);
|
|
297
|
-
const statusCheckScope = statusCheckRequested && resolvedContext.friend.trustLevel === "family"
|
|
298
|
-
? "all-sessions-family"
|
|
299
|
-
: undefined;
|
|
300
279
|
const runAgentOptions = {
|
|
301
280
|
...input.runAgentOptions,
|
|
302
281
|
bridgeContext,
|
|
@@ -304,9 +283,6 @@ async function handleInboundTurn(input) {
|
|
|
304
283
|
delegationDecision,
|
|
305
284
|
currentSessionKey: currentSession.key,
|
|
306
285
|
currentObligation,
|
|
307
|
-
statusCheckRequested,
|
|
308
|
-
statusCheckScope,
|
|
309
|
-
toolChoiceRequired: statusCheckRequested ? true : input.runAgentOptions?.toolChoiceRequired,
|
|
310
286
|
mustResolveBeforeHandoff,
|
|
311
287
|
setMustResolveBeforeHandoff: (value) => {
|
|
312
288
|
mustResolveBeforeHandoff = value;
|