@ouro.bot/cli 0.1.0-alpha.106 → 0.1.0-alpha.108
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 +18 -10
- package/dist/heart/core.js +7 -53
- package/dist/mind/obligation-steering.js +13 -8
- package/dist/mind/prompt.js +29 -21
- package/dist/repertoire/tools-base.js +170 -0
- 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.108",
|
|
6
|
+
"changes": [
|
|
7
|
+
"Agents now have a first-class `query_active_work` tool that reads one top-level live world-state across the current conversation, other active sessions, live coding lanes, inner work, and return obligations instead of reconstructing status from side tools.",
|
|
8
|
+
"Family-facing status guidance now treats the active-work world-state as the agent's center of gravity, so 'what are you up to?' answers stay anchored in one coherent live picture instead of drifting into inner-dialog archaeology."
|
|
9
|
+
]
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
"version": "0.1.0-alpha.107",
|
|
13
|
+
"changes": [
|
|
14
|
+
"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.",
|
|
15
|
+
"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."
|
|
16
|
+
]
|
|
17
|
+
},
|
|
4
18
|
{
|
|
5
19
|
"version": "0.1.0-alpha.106",
|
|
6
20
|
"changes": [
|
|
@@ -136,7 +136,15 @@ function formatObligationContentNextAction(obligation) {
|
|
|
136
136
|
return `work on "${content}" and bring back a concrete artifact`;
|
|
137
137
|
}
|
|
138
138
|
function formatNextAction(frame, obligation) {
|
|
139
|
-
|
|
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()) {
|
|
140
148
|
return obligation.nextAction.trim();
|
|
141
149
|
}
|
|
142
150
|
const liveCodingSession = frame.codingSessions?.[0];
|
|
@@ -149,12 +157,8 @@ function formatNextAction(frame, obligation) {
|
|
|
149
157
|
if (liveCodingSession) {
|
|
150
158
|
return "finish the coding pass and bring the result back here";
|
|
151
159
|
}
|
|
152
|
-
if (obligation?.
|
|
153
|
-
return
|
|
154
|
-
}
|
|
155
|
-
if (obligation?.status === "updating_runtime") {
|
|
156
|
-
return "update runtime, verify version/changelog, then re-observe";
|
|
157
|
-
}
|
|
160
|
+
if (obligation?.nextAction?.trim())
|
|
161
|
+
return obligation.nextAction.trim();
|
|
158
162
|
if (obligation) {
|
|
159
163
|
return formatObligationContentNextAction(obligation) || "continue the active loop and bring the result back here";
|
|
160
164
|
}
|
|
@@ -255,10 +259,13 @@ function formatOtherActiveSessionSummaries(frame, nowMs = Date.now()) {
|
|
|
255
259
|
.filter((candidate) => candidate.originSession && sessionOriginKey(candidate.originSession) === originKey)
|
|
256
260
|
.sort((left, right) => codingSessionTimestampMs(right) - codingSessionTimestampMs(left))[0] ?? null;
|
|
257
261
|
const liveSession = (frame.friendActivity?.allOtherLiveSessions ?? []).find((candidate) => sessionOriginKey(candidate) === originKey) ?? null;
|
|
258
|
-
const
|
|
259
|
-
? (nowMs - liveSession.lastActivityMs) <= RECENT_OTHER_LIVE_SESSION_WINDOW_MS
|
|
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))
|
|
260
267
|
: false;
|
|
261
|
-
if (!obligation && !codingSession && !
|
|
268
|
+
if (!obligation && !codingSession && !hasMaterialLiveSession) {
|
|
262
269
|
return null;
|
|
263
270
|
}
|
|
264
271
|
const timestampMs = Math.max(liveSession?.lastActivityMs ?? 0, codingSession ? codingSessionTimestampMs(codingSession) : 0, obligation ? obligationTimestampMs(obligation) : 0);
|
|
@@ -403,6 +410,7 @@ function buildActiveWorkFrame(input) {
|
|
|
403
410
|
}
|
|
404
411
|
function formatActiveWorkFrame(frame) {
|
|
405
412
|
const lines = ["## what i'm holding"];
|
|
413
|
+
lines.push("this is my top-level live world-state right now. inner work, coding lanes, other sessions, and return obligations all belong inside this picture.");
|
|
406
414
|
const primaryObligation = findPrimaryOpenObligation(frame);
|
|
407
415
|
const currentSessionObligation = findCurrentSessionOpenObligation(frame);
|
|
408
416
|
const activeLane = formatActiveLane(frame, primaryObligation);
|
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);
|
|
@@ -113,8 +113,17 @@ function formatCurrentArtifact(frame, obligation) {
|
|
|
113
113
|
return obligation ? "no artifact yet" : "";
|
|
114
114
|
}
|
|
115
115
|
function formatNextAction(frame, obligation) {
|
|
116
|
-
|
|
117
|
-
|
|
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
|
+
}
|
|
118
127
|
const liveCodingSession = frame.codingSessions?.[0];
|
|
119
128
|
if (liveCodingSession?.status === "waiting_input") {
|
|
120
129
|
return `answer ${liveCodingSession.runner} ${liveCodingSession.id} and continue`;
|
|
@@ -125,12 +134,8 @@ function formatNextAction(frame, obligation) {
|
|
|
125
134
|
if (liveCodingSession) {
|
|
126
135
|
return "finish the coding pass and bring the result back here";
|
|
127
136
|
}
|
|
128
|
-
if (obligation?.
|
|
129
|
-
return
|
|
130
|
-
}
|
|
131
|
-
if (obligation?.status === "updating_runtime") {
|
|
132
|
-
return "update runtime, verify version/changelog, then re-observe";
|
|
133
|
-
}
|
|
137
|
+
if (obligation?.nextAction?.trim())
|
|
138
|
+
return obligation.nextAction.trim();
|
|
134
139
|
if (obligation?.content?.trim()) {
|
|
135
140
|
return `work on "${obligation.content.trim()}" and bring back a concrete artifact`;
|
|
136
141
|
}
|
package/dist/mind/prompt.js
CHANGED
|
@@ -465,10 +465,20 @@ function familyCrossSessionTruthSection(context, options) {
|
|
|
465
465
|
return `## cross-session truth
|
|
466
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
467
|
i answer naturally from the live world-state in this prompt.
|
|
468
|
+
i treat the active-work section above as my reliable top-level surface for this.
|
|
469
|
+
i do not claim i lack a top-level view when that surface is already present.
|
|
470
|
+
i only reach for query_active_work when i want a fresh read of that same surface.
|
|
471
|
+
i do not rebuild whole-self status from scratch with query_session and coding_status unless i need to verify a specific gap.
|
|
468
472
|
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
|
-
|
|
471
|
-
|
|
473
|
+
if part of the picture is still fuzzy, i say what i can see and what still needs checking.
|
|
474
|
+
when the live ask is about status, i widen before answering:
|
|
475
|
+
- where i am right now
|
|
476
|
+
- any other material active sessions or coding lanes i can see
|
|
477
|
+
- the freshest concrete checkpoint
|
|
478
|
+
- the next concrete step
|
|
479
|
+
i do not collapse down to only the current lane.`;
|
|
480
|
+
}
|
|
481
|
+
function centerOfGravitySteeringSection(channel, options, context) {
|
|
472
482
|
if (channel === "inner")
|
|
473
483
|
return "";
|
|
474
484
|
const frame = options?.activeWorkFrame;
|
|
@@ -479,12 +489,15 @@ function centerOfGravitySteeringSection(channel, options) {
|
|
|
479
489
|
const activeObligation = (0, obligation_steering_1.findActivePersistentObligation)(frame);
|
|
480
490
|
const statusObligation = (0, obligation_steering_1.findStatusObligation)(frame);
|
|
481
491
|
const genericConcreteStatus = (0, obligation_steering_1.renderConcreteStatusGuidance)(frame, statusObligation);
|
|
492
|
+
const liveWorldClause = context?.friend?.trustLevel === "family"
|
|
493
|
+
? "\nmy center of gravity lives in the active-work world-state above. inner work is one lane inside it, not the whole picture."
|
|
494
|
+
: "";
|
|
482
495
|
if (cog === "local-turn") {
|
|
483
496
|
return genericConcreteStatus || (0, obligation_steering_1.renderLiveThreadStatusShape)(frame);
|
|
484
497
|
}
|
|
485
498
|
if (cog === "inward-work") {
|
|
486
499
|
if (activeObligation) {
|
|
487
|
-
return `${(0, obligation_steering_1.renderActiveObligationSteering)(activeObligation)}
|
|
500
|
+
return `${(0, obligation_steering_1.renderActiveObligationSteering)(activeObligation)}${liveWorldClause}
|
|
488
501
|
|
|
489
502
|
${genericConcreteStatus}`;
|
|
490
503
|
}
|
|
@@ -496,7 +509,7 @@ ${genericConcreteStatus}`;
|
|
|
496
509
|
? "\ni still owe them an answer."
|
|
497
510
|
: "";
|
|
498
511
|
return `## where my attention is
|
|
499
|
-
i'm thinking through something privately right now.${originClause}${obligationClause}
|
|
512
|
+
i'm thinking through something privately right now.${originClause}${obligationClause}${liveWorldClause}
|
|
500
513
|
|
|
501
514
|
if this conversation connects to that inner work, i can weave them together.
|
|
502
515
|
if it's separate, i can be fully present here -- my inner work will wait.`;
|
|
@@ -507,7 +520,7 @@ if it's separate, i can be fully present here -- my inner work will wait.`;
|
|
|
507
520
|
? ` this started when ${job.origin.friendName ?? job.origin.friendId} asked about something.`
|
|
508
521
|
: "";
|
|
509
522
|
return `## where my attention is
|
|
510
|
-
i've been thinking privately and reached something.${originClause}
|
|
523
|
+
i've been thinking privately and reached something.${originClause}${liveWorldClause}
|
|
511
524
|
|
|
512
525
|
i should bring my answer back to the conversation it came from.`;
|
|
513
526
|
}
|
|
@@ -523,8 +536,15 @@ i should bring my answer back to the conversation it came from.`;
|
|
|
523
536
|
: liveCodingSession.originSession
|
|
524
537
|
? ` for ${liveCodingSession.originSession.channel}/${liveCodingSession.originSession.key}`
|
|
525
538
|
: "";
|
|
539
|
+
const otherSessionLines = (0, active_work_1.formatOtherActiveSessionSummaries)(frame);
|
|
540
|
+
const familyStatusClause = context?.friend?.trustLevel === "family"
|
|
541
|
+
? `\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.
|
|
542
|
+
after i name this lane, i widen back out with:
|
|
543
|
+
other active sessions:
|
|
544
|
+
${otherSessionLines.length > 0 ? otherSessionLines.join("\n") : "- none"}`
|
|
545
|
+
: "";
|
|
526
546
|
return `## where my attention is
|
|
527
|
-
i already have coding work running in ${liveCodingSession.runner} ${liveCodingSession.id}${scopeClause}
|
|
547
|
+
i already have coding work running in ${liveCodingSession.runner} ${liveCodingSession.id}${scopeClause}.${familyStatusClause}${liveWorldClause}
|
|
528
548
|
|
|
529
549
|
i should orient around that live lane first, then decide what still needs to come back here.`;
|
|
530
550
|
}
|
|
@@ -539,24 +559,13 @@ i can take it inward with go_inward to think privately, or address it directly h
|
|
|
539
559
|
if (cog === "shared-work") {
|
|
540
560
|
/* v8 ignore stop */
|
|
541
561
|
return `## where my attention is
|
|
542
|
-
this work touches multiple conversations -- i'm holding threads across sessions
|
|
562
|
+
this work touches multiple conversations -- i'm holding threads across sessions.${liveWorldClause}
|
|
543
563
|
|
|
544
564
|
i should keep the different sides aligned. what i learn here may matter there, and vice versa.`;
|
|
545
565
|
}
|
|
546
566
|
/* v8 ignore next -- unreachable: all center-of-gravity modes covered above @preserve */
|
|
547
567
|
return "";
|
|
548
568
|
}
|
|
549
|
-
function statusCheckSection(channel, options) {
|
|
550
|
-
if (channel === "inner" || !options?.statusCheckRequested)
|
|
551
|
-
return "";
|
|
552
|
-
const frame = options.activeWorkFrame;
|
|
553
|
-
if (!frame)
|
|
554
|
-
return "";
|
|
555
|
-
const activeObligation = (0, obligation_steering_1.findStatusObligation)(frame);
|
|
556
|
-
return `## status question on this turn
|
|
557
|
-
the user is asking for current status right now.
|
|
558
|
-
${(0, obligation_steering_1.renderExactStatusReplyContract)(frame, activeObligation, options.statusCheckScope)}`;
|
|
559
|
-
}
|
|
560
569
|
function commitmentsSection(options) {
|
|
561
570
|
if (!options?.activeWorkFrame)
|
|
562
571
|
return "";
|
|
@@ -765,8 +774,7 @@ async function buildSystem(channel = "cli", options, context) {
|
|
|
765
774
|
taskBoardSection(),
|
|
766
775
|
activeWorkSection(options),
|
|
767
776
|
familyCrossSessionTruthSection(context, options),
|
|
768
|
-
|
|
769
|
-
centerOfGravitySteeringSection(channel, options),
|
|
777
|
+
centerOfGravitySteeringSection(channel, options, context),
|
|
770
778
|
commitmentsSection(options),
|
|
771
779
|
delegationHintSection(options),
|
|
772
780
|
bridgeContextSection(options),
|
|
@@ -48,8 +48,12 @@ const socket_client_1 = require("../heart/daemon/socket-client");
|
|
|
48
48
|
const thoughts_1 = require("../heart/daemon/thoughts");
|
|
49
49
|
const manager_1 = require("../heart/bridges/manager");
|
|
50
50
|
const session_recall_1 = require("../heart/session-recall");
|
|
51
|
+
const session_activity_1 = require("../heart/session-activity");
|
|
52
|
+
const active_work_1 = require("../heart/active-work");
|
|
51
53
|
const tools_1 = require("./coding/tools");
|
|
54
|
+
const coding_1 = require("./coding");
|
|
52
55
|
const memory_1 = require("../mind/memory");
|
|
56
|
+
const tasks_1 = require("./tasks");
|
|
53
57
|
const pending_1 = require("../mind/pending");
|
|
54
58
|
const progress_story_1 = require("../heart/progress-story");
|
|
55
59
|
const cross_chat_delivery_1 = require("../heart/cross-chat-delivery");
|
|
@@ -151,6 +155,155 @@ function renderCrossChatDeliveryStatus(target, result) {
|
|
|
151
155
|
outcomeText: `${lead}\n${result.detail}`,
|
|
152
156
|
}));
|
|
153
157
|
}
|
|
158
|
+
function emptyTaskBoard() {
|
|
159
|
+
return {
|
|
160
|
+
compact: "",
|
|
161
|
+
full: "",
|
|
162
|
+
byStatus: {
|
|
163
|
+
drafting: [],
|
|
164
|
+
processing: [],
|
|
165
|
+
validating: [],
|
|
166
|
+
collaborating: [],
|
|
167
|
+
paused: [],
|
|
168
|
+
blocked: [],
|
|
169
|
+
done: [],
|
|
170
|
+
},
|
|
171
|
+
actionRequired: [],
|
|
172
|
+
unresolvedDependencies: [],
|
|
173
|
+
activeSessions: [],
|
|
174
|
+
activeBridges: [],
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
function isLiveCodingSessionStatus(status) {
|
|
178
|
+
return status === "spawning"
|
|
179
|
+
|| status === "running"
|
|
180
|
+
|| status === "waiting_input"
|
|
181
|
+
|| status === "stalled";
|
|
182
|
+
}
|
|
183
|
+
function readActiveWorkInnerState() {
|
|
184
|
+
const defaultJob = {
|
|
185
|
+
status: "idle",
|
|
186
|
+
content: null,
|
|
187
|
+
origin: null,
|
|
188
|
+
mode: "reflect",
|
|
189
|
+
obligationStatus: null,
|
|
190
|
+
surfacedResult: null,
|
|
191
|
+
queuedAt: null,
|
|
192
|
+
startedAt: null,
|
|
193
|
+
surfacedAt: null,
|
|
194
|
+
};
|
|
195
|
+
try {
|
|
196
|
+
const agentRoot = (0, identity_1.getAgentRoot)();
|
|
197
|
+
const pendingDir = (0, pending_1.getInnerDialogPendingDir)((0, identity_1.getAgentName)());
|
|
198
|
+
const sessionPath = (0, thoughts_1.getInnerDialogSessionPath)(agentRoot);
|
|
199
|
+
const { pendingMessages, turns, runtimeState } = (0, thoughts_1.readInnerDialogRawData)(sessionPath, pendingDir);
|
|
200
|
+
const dialogStatus = (0, thoughts_1.deriveInnerDialogStatus)(pendingMessages, turns, runtimeState);
|
|
201
|
+
const job = (0, thoughts_1.deriveInnerJob)(pendingMessages, turns, runtimeState);
|
|
202
|
+
const storeObligationPending = (0, obligations_1.readPendingObligations)(agentRoot).length > 0;
|
|
203
|
+
return {
|
|
204
|
+
status: dialogStatus.processing === "started" ? "running" : "idle",
|
|
205
|
+
hasPending: dialogStatus.queue !== "clear",
|
|
206
|
+
origin: dialogStatus.origin,
|
|
207
|
+
contentSnippet: dialogStatus.contentSnippet,
|
|
208
|
+
obligationPending: dialogStatus.obligationPending || storeObligationPending,
|
|
209
|
+
job,
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
catch {
|
|
213
|
+
return {
|
|
214
|
+
status: "idle",
|
|
215
|
+
hasPending: false,
|
|
216
|
+
job: defaultJob,
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
async function buildToolActiveWorkFrame(ctx) {
|
|
221
|
+
const currentSession = ctx?.currentSession
|
|
222
|
+
? {
|
|
223
|
+
friendId: ctx.currentSession.friendId,
|
|
224
|
+
channel: ctx.currentSession.channel,
|
|
225
|
+
key: ctx.currentSession.key,
|
|
226
|
+
sessionPath: (0, config_1.resolveSessionPath)(ctx.currentSession.friendId, ctx.currentSession.channel, ctx.currentSession.key),
|
|
227
|
+
}
|
|
228
|
+
: null;
|
|
229
|
+
const agentRoot = (0, identity_1.getAgentRoot)();
|
|
230
|
+
const bridges = currentSession
|
|
231
|
+
? (0, manager_1.createBridgeManager)().findBridgesForSession({
|
|
232
|
+
friendId: currentSession.friendId,
|
|
233
|
+
channel: currentSession.channel,
|
|
234
|
+
key: currentSession.key,
|
|
235
|
+
})
|
|
236
|
+
: [];
|
|
237
|
+
let friendActivity = [];
|
|
238
|
+
try {
|
|
239
|
+
friendActivity = (0, session_activity_1.listSessionActivity)({
|
|
240
|
+
sessionsDir: `${agentRoot}/state/sessions`,
|
|
241
|
+
friendsDir: `${agentRoot}/friends`,
|
|
242
|
+
agentName: (0, identity_1.getAgentName)(),
|
|
243
|
+
currentSession,
|
|
244
|
+
});
|
|
245
|
+
}
|
|
246
|
+
catch {
|
|
247
|
+
friendActivity = [];
|
|
248
|
+
}
|
|
249
|
+
const pendingObligations = (() => {
|
|
250
|
+
try {
|
|
251
|
+
return (0, obligations_1.readPendingObligations)(agentRoot);
|
|
252
|
+
}
|
|
253
|
+
catch {
|
|
254
|
+
return [];
|
|
255
|
+
}
|
|
256
|
+
})();
|
|
257
|
+
let codingSessions = [];
|
|
258
|
+
let otherCodingSessions = [];
|
|
259
|
+
try {
|
|
260
|
+
const liveCodingSessions = (0, coding_1.getCodingSessionManager)()
|
|
261
|
+
.listSessions()
|
|
262
|
+
.filter((session) => isLiveCodingSessionStatus(session.status) && Boolean(session.originSession));
|
|
263
|
+
if (currentSession) {
|
|
264
|
+
codingSessions = liveCodingSessions.filter((session) => session.originSession?.friendId === currentSession.friendId
|
|
265
|
+
&& session.originSession.channel === currentSession.channel
|
|
266
|
+
&& session.originSession.key === currentSession.key);
|
|
267
|
+
otherCodingSessions = liveCodingSessions.filter((session) => !(session.originSession?.friendId === currentSession.friendId
|
|
268
|
+
&& session.originSession.channel === currentSession.channel
|
|
269
|
+
&& session.originSession.key === currentSession.key));
|
|
270
|
+
}
|
|
271
|
+
else {
|
|
272
|
+
codingSessions = [];
|
|
273
|
+
otherCodingSessions = liveCodingSessions;
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
catch {
|
|
277
|
+
codingSessions = [];
|
|
278
|
+
otherCodingSessions = [];
|
|
279
|
+
}
|
|
280
|
+
const currentObligation = currentSession
|
|
281
|
+
? pendingObligations.find((obligation) => obligation.status !== "fulfilled"
|
|
282
|
+
&& obligation.origin.friendId === currentSession.friendId
|
|
283
|
+
&& obligation.origin.channel === currentSession.channel
|
|
284
|
+
&& obligation.origin.key === currentSession.key)?.content ?? null
|
|
285
|
+
: null;
|
|
286
|
+
return (0, active_work_1.buildActiveWorkFrame)({
|
|
287
|
+
currentSession,
|
|
288
|
+
currentObligation,
|
|
289
|
+
mustResolveBeforeHandoff: false,
|
|
290
|
+
inner: readActiveWorkInnerState(),
|
|
291
|
+
bridges,
|
|
292
|
+
codingSessions,
|
|
293
|
+
otherCodingSessions,
|
|
294
|
+
pendingObligations,
|
|
295
|
+
taskBoard: (() => {
|
|
296
|
+
try {
|
|
297
|
+
return (0, tasks_1.getTaskModule)().getBoard();
|
|
298
|
+
}
|
|
299
|
+
catch {
|
|
300
|
+
return emptyTaskBoard();
|
|
301
|
+
}
|
|
302
|
+
})(),
|
|
303
|
+
friendActivity,
|
|
304
|
+
targetCandidates: [],
|
|
305
|
+
});
|
|
306
|
+
}
|
|
154
307
|
function renderInnerProgressStatus(status) {
|
|
155
308
|
if (status.processing === "pending") {
|
|
156
309
|
return "i've queued this thought for private attention. it'll come up when my inner dialog is free.";
|
|
@@ -818,6 +971,23 @@ exports.baseToolDefinitions = [
|
|
|
818
971
|
return `unknown bridge action: ${action}`;
|
|
819
972
|
},
|
|
820
973
|
},
|
|
974
|
+
{
|
|
975
|
+
tool: {
|
|
976
|
+
type: "function",
|
|
977
|
+
function: {
|
|
978
|
+
name: "query_active_work",
|
|
979
|
+
description: "read the current live world-state across visible sessions, coding lanes, inner work, and return obligations. use this instead of piecing status together from separate session and coding tools.",
|
|
980
|
+
parameters: {
|
|
981
|
+
type: "object",
|
|
982
|
+
properties: {},
|
|
983
|
+
},
|
|
984
|
+
},
|
|
985
|
+
},
|
|
986
|
+
handler: async (_args, ctx) => {
|
|
987
|
+
const frame = await buildToolActiveWorkFrame(ctx);
|
|
988
|
+
return `this is my current top-level live world-state.\nanswer whole-self status questions from this before drilling into individual sessions.\n\n${(0, active_work_1.formatActiveWorkFrame)(frame)}`;
|
|
989
|
+
},
|
|
990
|
+
},
|
|
821
991
|
{
|
|
822
992
|
tool: {
|
|
823
993
|
type: "function",
|