@poncho-ai/cli 0.32.3 → 0.32.5
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/.turbo/turbo-build.log +7 -7
- package/CHANGELOG.md +14 -0
- package/dist/{chunk-TQRPRFR3.js → chunk-LVWNWMNE.js} +729 -455
- package/dist/cli.js +1 -1
- package/dist/index.d.ts +81 -3
- package/dist/index.js +3 -1
- package/dist/{run-interactive-ink-GD3IRICQ.js → run-interactive-ink-VGKSZJDO.js} +1 -1
- package/package.json +1 -1
- package/src/index.ts +768 -440
- package/src/web-ui-client.ts +70 -8
- package/test/run-orchestration.test.ts +171 -0
|
@@ -1861,6 +1861,7 @@ var getWebUiClientScript = (markedSource2) => `
|
|
|
1861
1861
|
todoPanelCollapsed: false,
|
|
1862
1862
|
cronSectionCollapsed: true,
|
|
1863
1863
|
cronShowAll: false,
|
|
1864
|
+
subagentPollInFlight: {},
|
|
1864
1865
|
};
|
|
1865
1866
|
|
|
1866
1867
|
const agentInitial = document.body.dataset.agentInitial || "A";
|
|
@@ -2320,11 +2321,20 @@ var getWebUiClientScript = (markedSource2) => `
|
|
|
2320
2321
|
return null;
|
|
2321
2322
|
}
|
|
2322
2323
|
const toolName = item && typeof item.tool === "string" ? item.tool : "tool";
|
|
2324
|
+
const decision =
|
|
2325
|
+
item && typeof item.decision === "string" ? item.decision : null;
|
|
2326
|
+
const isResolved = decision === "approved" || decision === "denied";
|
|
2323
2327
|
return {
|
|
2324
2328
|
approvalId,
|
|
2325
2329
|
tool: toolName,
|
|
2326
2330
|
input: item?.input ?? {},
|
|
2327
|
-
state: "pending",
|
|
2331
|
+
state: isResolved ? "resolved" : "pending",
|
|
2332
|
+
resolvedDecision:
|
|
2333
|
+
decision === "approved"
|
|
2334
|
+
? "approve"
|
|
2335
|
+
: decision === "denied"
|
|
2336
|
+
? "deny"
|
|
2337
|
+
: null,
|
|
2328
2338
|
};
|
|
2329
2339
|
})
|
|
2330
2340
|
.filter(Boolean);
|
|
@@ -3374,8 +3384,8 @@ var getWebUiClientScript = (markedSource2) => `
|
|
|
3374
3384
|
updateContextRing();
|
|
3375
3385
|
renderMessages(state.activeMessages, payload.hasActiveRun);
|
|
3376
3386
|
}
|
|
3377
|
-
if (payload.hasActiveRun) {
|
|
3378
|
-
if (window._connectBrowserStream) window._connectBrowserStream();
|
|
3387
|
+
if (payload.hasActiveRun || payload.hasRunningSubagents) {
|
|
3388
|
+
if (payload.hasActiveRun && window._connectBrowserStream) window._connectBrowserStream();
|
|
3379
3389
|
setTimeout(poll, 2000);
|
|
3380
3390
|
} else {
|
|
3381
3391
|
setStreaming(false);
|
|
@@ -3390,9 +3400,15 @@ var getWebUiClientScript = (markedSource2) => `
|
|
|
3390
3400
|
};
|
|
3391
3401
|
|
|
3392
3402
|
const pollForSubagentResults = (conversationId) => {
|
|
3403
|
+
if (state.subagentPollInFlight[conversationId]) return;
|
|
3404
|
+
state.subagentPollInFlight[conversationId] = true;
|
|
3393
3405
|
let lastMessageCount = state.activeMessages ? state.activeMessages.length : 0;
|
|
3406
|
+
let lastUpdatedAt = 0;
|
|
3394
3407
|
const poll = async () => {
|
|
3395
|
-
if (state.activeConversationId !== conversationId)
|
|
3408
|
+
if (state.activeConversationId !== conversationId) {
|
|
3409
|
+
delete state.subagentPollInFlight[conversationId];
|
|
3410
|
+
return;
|
|
3411
|
+
}
|
|
3396
3412
|
try {
|
|
3397
3413
|
var payload = await api("/api/conversations/" + encodeURIComponent(conversationId));
|
|
3398
3414
|
if (state.activeConversationId !== conversationId) return;
|
|
@@ -3413,13 +3429,17 @@ var getWebUiClientScript = (markedSource2) => `
|
|
|
3413
3429
|
});
|
|
3414
3430
|
});
|
|
3415
3431
|
}
|
|
3416
|
-
|
|
3432
|
+
const conversationUpdatedAt =
|
|
3433
|
+
typeof payload.conversation.updatedAt === "number" ? payload.conversation.updatedAt : 0;
|
|
3434
|
+
if (messages.length > lastMessageCount || conversationUpdatedAt > lastUpdatedAt) {
|
|
3417
3435
|
lastMessageCount = messages.length;
|
|
3436
|
+
lastUpdatedAt = conversationUpdatedAt;
|
|
3418
3437
|
state.activeMessages = hydratePendingApprovals(messages, allPending);
|
|
3419
3438
|
renderMessages(state.activeMessages, payload.hasActiveRun || payload.hasRunningSubagents);
|
|
3420
3439
|
}
|
|
3421
3440
|
if (payload.hasActiveRun) {
|
|
3422
3441
|
// Parent agent started its continuation run \u2014 switch to live stream
|
|
3442
|
+
delete state.subagentPollInFlight[conversationId];
|
|
3423
3443
|
setStreaming(true);
|
|
3424
3444
|
state.activeMessages = hydratePendingApprovals(messages, allPending);
|
|
3425
3445
|
streamConversationEvents(conversationId, { liveOnly: true }).finally(() => {
|
|
@@ -3432,6 +3452,7 @@ var getWebUiClientScript = (markedSource2) => `
|
|
|
3432
3452
|
} else {
|
|
3433
3453
|
renderMessages(state.activeMessages, false);
|
|
3434
3454
|
await loadConversations();
|
|
3455
|
+
delete state.subagentPollInFlight[conversationId];
|
|
3435
3456
|
}
|
|
3436
3457
|
}
|
|
3437
3458
|
} catch {
|
|
@@ -4359,6 +4380,7 @@ var getWebUiClientScript = (markedSource2) => `
|
|
|
4359
4380
|
let _maxSteps = 0;
|
|
4360
4381
|
let _receivedTerminalEvent = false;
|
|
4361
4382
|
let _shouldContinue = false;
|
|
4383
|
+
let _pendingSubagentsConversation = null;
|
|
4362
4384
|
|
|
4363
4385
|
// Helper to read an SSE stream from a fetch response
|
|
4364
4386
|
const readSseStream = async (response) => {
|
|
@@ -4676,7 +4698,7 @@ var getWebUiClientScript = (markedSource2) => `
|
|
|
4676
4698
|
assistantMessage.content = String(payload.result?.response || "");
|
|
4677
4699
|
}
|
|
4678
4700
|
if (payload.pendingSubagents) {
|
|
4679
|
-
|
|
4701
|
+
_pendingSubagentsConversation = conversationId;
|
|
4680
4702
|
}
|
|
4681
4703
|
renderIfActiveConversation(false);
|
|
4682
4704
|
}
|
|
@@ -4804,6 +4826,19 @@ var getWebUiClientScript = (markedSource2) => `
|
|
|
4804
4826
|
}
|
|
4805
4827
|
elements.prompt.focus();
|
|
4806
4828
|
}
|
|
4829
|
+
|
|
4830
|
+
// Subagent callback: after sendMessage fully completes (including
|
|
4831
|
+
// finally cleanup), reload the conversation. loadConversation is
|
|
4832
|
+
// the exact same code path as a manual refresh \u2014 if the callback
|
|
4833
|
+
// is still running it connects to the event stream; if it already
|
|
4834
|
+
// finished it just renders the final persisted state.
|
|
4835
|
+
if (_pendingSubagentsConversation && state.activeConversationId === _pendingSubagentsConversation) {
|
|
4836
|
+
const cbConvId = _pendingSubagentsConversation;
|
|
4837
|
+
await new Promise(r => setTimeout(r, 1200));
|
|
4838
|
+
if (state.activeConversationId === cbConvId && !state.isStreaming) {
|
|
4839
|
+
await loadConversation(cbConvId);
|
|
4840
|
+
}
|
|
4841
|
+
}
|
|
4807
4842
|
};
|
|
4808
4843
|
|
|
4809
4844
|
const requireAuth = async () => {
|
|
@@ -5037,9 +5072,22 @@ var getWebUiClientScript = (markedSource2) => `
|
|
|
5037
5072
|
}));
|
|
5038
5073
|
return api("/api/approvals/" + encodeURIComponent(approvalId), {
|
|
5039
5074
|
method: "POST",
|
|
5040
|
-
body: JSON.stringify({
|
|
5075
|
+
body: JSON.stringify({
|
|
5076
|
+
approved: decision === "approve",
|
|
5077
|
+
conversationId: state.activeConversationId || undefined,
|
|
5078
|
+
}),
|
|
5041
5079
|
}).catch((error) => {
|
|
5042
5080
|
const isStale = error && error.payload && error.payload.code === "APPROVAL_NOT_FOUND";
|
|
5081
|
+
const isNotReady = error && error.payload && error.payload.code === "APPROVAL_NOT_READY";
|
|
5082
|
+
if (isNotReady) {
|
|
5083
|
+
updatePendingApproval(approvalId, (request) => ({
|
|
5084
|
+
...request,
|
|
5085
|
+
state: "pending",
|
|
5086
|
+
pendingDecision: null,
|
|
5087
|
+
resolvedDecision: null,
|
|
5088
|
+
}));
|
|
5089
|
+
return;
|
|
5090
|
+
}
|
|
5043
5091
|
if (isStale) {
|
|
5044
5092
|
updatePendingApproval(approvalId, () => null);
|
|
5045
5093
|
} else {
|
|
@@ -5110,9 +5158,23 @@ var getWebUiClientScript = (markedSource2) => `
|
|
|
5110
5158
|
for (const aid of pending) {
|
|
5111
5159
|
await api("/api/approvals/" + encodeURIComponent(aid), {
|
|
5112
5160
|
method: "POST",
|
|
5113
|
-
body: JSON.stringify({
|
|
5161
|
+
body: JSON.stringify({
|
|
5162
|
+
approved: decision === "approve",
|
|
5163
|
+
conversationId: state.activeConversationId || undefined,
|
|
5164
|
+
}),
|
|
5114
5165
|
}).catch((error) => {
|
|
5115
5166
|
const isStale = error && error.payload && error.payload.code === "APPROVAL_NOT_FOUND";
|
|
5167
|
+
const isNotReady = error && error.payload && error.payload.code === "APPROVAL_NOT_READY";
|
|
5168
|
+
if (isNotReady) {
|
|
5169
|
+
updatePendingApproval(aid, (request) => ({
|
|
5170
|
+
...request,
|
|
5171
|
+
state: "pending",
|
|
5172
|
+
pendingDecision: null,
|
|
5173
|
+
resolvedDecision: null,
|
|
5174
|
+
}));
|
|
5175
|
+
renderMessages(state.activeMessages, state.isStreaming);
|
|
5176
|
+
return;
|
|
5177
|
+
}
|
|
5116
5178
|
if (isStale) {
|
|
5117
5179
|
updatePendingApproval(aid, () => null);
|
|
5118
5180
|
} else {
|
|
@@ -7412,6 +7474,13 @@ var readRequestBody = async (request) => {
|
|
|
7412
7474
|
const body = Buffer.concat(chunks).toString("utf8");
|
|
7413
7475
|
return body.length > 0 ? JSON.parse(body) : {};
|
|
7414
7476
|
};
|
|
7477
|
+
var parseTelegramMessageThreadIdFromPlatformThreadId = (platformThreadId, chatId) => {
|
|
7478
|
+
if (!platformThreadId || !chatId) return void 0;
|
|
7479
|
+
const parts = platformThreadId.split(":");
|
|
7480
|
+
if (parts.length !== 3 || parts[0] !== chatId) return void 0;
|
|
7481
|
+
const threadId = Number(parts[1]);
|
|
7482
|
+
return Number.isInteger(threadId) ? threadId : void 0;
|
|
7483
|
+
};
|
|
7415
7484
|
var MAX_UPLOAD_SIZE = 25 * 1024 * 1024;
|
|
7416
7485
|
var parseMultipartRequest = (request) => new Promise((resolve4, reject) => {
|
|
7417
7486
|
const result = { message: "", files: [] };
|
|
@@ -7528,6 +7597,227 @@ var parseParams = (values) => {
|
|
|
7528
7597
|
}
|
|
7529
7598
|
return params;
|
|
7530
7599
|
};
|
|
7600
|
+
var normalizeMessageForClient = (message) => {
|
|
7601
|
+
if (message.role !== "assistant" || typeof message.content !== "string") {
|
|
7602
|
+
return message;
|
|
7603
|
+
}
|
|
7604
|
+
try {
|
|
7605
|
+
const parsed = JSON.parse(message.content);
|
|
7606
|
+
const text = typeof parsed.text === "string" ? parsed.text : void 0;
|
|
7607
|
+
const toolCalls = Array.isArray(parsed.tool_calls) ? parsed.tool_calls : void 0;
|
|
7608
|
+
if (typeof text === "string" && toolCalls) {
|
|
7609
|
+
return {
|
|
7610
|
+
...message,
|
|
7611
|
+
content: text
|
|
7612
|
+
};
|
|
7613
|
+
}
|
|
7614
|
+
} catch {
|
|
7615
|
+
}
|
|
7616
|
+
return message;
|
|
7617
|
+
};
|
|
7618
|
+
var isMessageArray = (value) => Array.isArray(value) && value.every((entry) => {
|
|
7619
|
+
if (!entry || typeof entry !== "object") return false;
|
|
7620
|
+
const row = entry;
|
|
7621
|
+
const role = row.role;
|
|
7622
|
+
const content = row.content;
|
|
7623
|
+
const roleOk = role === "system" || role === "user" || role === "assistant" || role === "tool";
|
|
7624
|
+
const contentOk = typeof content === "string" || Array.isArray(content);
|
|
7625
|
+
return roleOk && contentOk;
|
|
7626
|
+
});
|
|
7627
|
+
var loadCanonicalHistory = (conversation) => {
|
|
7628
|
+
if (isMessageArray(conversation._harnessMessages) && conversation._harnessMessages.length > 0) {
|
|
7629
|
+
return { messages: [...conversation._harnessMessages], source: "harness" };
|
|
7630
|
+
}
|
|
7631
|
+
return { messages: [...conversation.messages], source: "messages" };
|
|
7632
|
+
};
|
|
7633
|
+
var loadRunHistory = (conversation, options) => {
|
|
7634
|
+
if (options?.preferContinuation && isMessageArray(conversation._continuationMessages) && conversation._continuationMessages.length > 0) {
|
|
7635
|
+
return {
|
|
7636
|
+
messages: [...conversation._continuationMessages],
|
|
7637
|
+
source: "continuation",
|
|
7638
|
+
shouldRebuildCanonical: !isMessageArray(conversation._harnessMessages) || conversation._harnessMessages.length === 0
|
|
7639
|
+
};
|
|
7640
|
+
}
|
|
7641
|
+
const canonical = loadCanonicalHistory(conversation);
|
|
7642
|
+
return {
|
|
7643
|
+
...canonical,
|
|
7644
|
+
shouldRebuildCanonical: canonical.source !== "harness"
|
|
7645
|
+
};
|
|
7646
|
+
};
|
|
7647
|
+
var createTurnDraftState = () => ({
|
|
7648
|
+
assistantResponse: "",
|
|
7649
|
+
toolTimeline: [],
|
|
7650
|
+
sections: [],
|
|
7651
|
+
currentTools: [],
|
|
7652
|
+
currentText: ""
|
|
7653
|
+
});
|
|
7654
|
+
var cloneSections = (sections) => sections.map((section) => ({
|
|
7655
|
+
type: section.type,
|
|
7656
|
+
content: Array.isArray(section.content) ? [...section.content] : section.content
|
|
7657
|
+
}));
|
|
7658
|
+
var flushTurnDraft = (draft) => {
|
|
7659
|
+
if (draft.currentTools.length > 0) {
|
|
7660
|
+
draft.sections.push({ type: "tools", content: draft.currentTools });
|
|
7661
|
+
draft.currentTools = [];
|
|
7662
|
+
}
|
|
7663
|
+
if (draft.currentText.length > 0) {
|
|
7664
|
+
draft.sections.push({ type: "text", content: draft.currentText });
|
|
7665
|
+
draft.currentText = "";
|
|
7666
|
+
}
|
|
7667
|
+
};
|
|
7668
|
+
var recordStandardTurnEvent = (draft, event) => {
|
|
7669
|
+
if (event.type === "model:chunk") {
|
|
7670
|
+
if (draft.currentTools.length > 0) {
|
|
7671
|
+
draft.sections.push({ type: "tools", content: draft.currentTools });
|
|
7672
|
+
draft.currentTools = [];
|
|
7673
|
+
if (draft.assistantResponse.length > 0 && !/\s$/.test(draft.assistantResponse)) {
|
|
7674
|
+
draft.assistantResponse += " ";
|
|
7675
|
+
}
|
|
7676
|
+
}
|
|
7677
|
+
draft.assistantResponse += event.content;
|
|
7678
|
+
draft.currentText += event.content;
|
|
7679
|
+
return;
|
|
7680
|
+
}
|
|
7681
|
+
if (event.type === "tool:started") {
|
|
7682
|
+
if (draft.currentText.length > 0) {
|
|
7683
|
+
draft.sections.push({ type: "text", content: draft.currentText });
|
|
7684
|
+
draft.currentText = "";
|
|
7685
|
+
}
|
|
7686
|
+
const toolText = `- start \`${event.tool}\``;
|
|
7687
|
+
draft.toolTimeline.push(toolText);
|
|
7688
|
+
draft.currentTools.push(toolText);
|
|
7689
|
+
return;
|
|
7690
|
+
}
|
|
7691
|
+
if (event.type === "tool:completed") {
|
|
7692
|
+
const toolText = `- done \`${event.tool}\` (${event.duration}ms)`;
|
|
7693
|
+
draft.toolTimeline.push(toolText);
|
|
7694
|
+
draft.currentTools.push(toolText);
|
|
7695
|
+
return;
|
|
7696
|
+
}
|
|
7697
|
+
if (event.type === "tool:error") {
|
|
7698
|
+
const toolText = `- error \`${event.tool}\`: ${event.error}`;
|
|
7699
|
+
draft.toolTimeline.push(toolText);
|
|
7700
|
+
draft.currentTools.push(toolText);
|
|
7701
|
+
}
|
|
7702
|
+
};
|
|
7703
|
+
var buildAssistantMetadata = (draft, sectionsOverride) => {
|
|
7704
|
+
const sections = sectionsOverride ?? cloneSections(draft.sections);
|
|
7705
|
+
if (draft.toolTimeline.length === 0 && sections.length === 0) return void 0;
|
|
7706
|
+
return {
|
|
7707
|
+
toolActivity: [...draft.toolTimeline],
|
|
7708
|
+
sections: sections.length > 0 ? sections : void 0
|
|
7709
|
+
};
|
|
7710
|
+
};
|
|
7711
|
+
var executeConversationTurn = async ({
|
|
7712
|
+
harness,
|
|
7713
|
+
runInput,
|
|
7714
|
+
initialContextTokens = 0,
|
|
7715
|
+
initialContextWindow = 0,
|
|
7716
|
+
onEvent
|
|
7717
|
+
}) => {
|
|
7718
|
+
const draft = createTurnDraftState();
|
|
7719
|
+
let latestRunId = "";
|
|
7720
|
+
let runCancelled = false;
|
|
7721
|
+
let runContinuation = false;
|
|
7722
|
+
let runContinuationMessages;
|
|
7723
|
+
let runHarnessMessages;
|
|
7724
|
+
let runContextTokens = initialContextTokens;
|
|
7725
|
+
let runContextWindow = initialContextWindow;
|
|
7726
|
+
let runSteps = 0;
|
|
7727
|
+
let runMaxSteps;
|
|
7728
|
+
for await (const event of harness.runWithTelemetry(runInput)) {
|
|
7729
|
+
recordStandardTurnEvent(draft, event);
|
|
7730
|
+
if (event.type === "run:started") {
|
|
7731
|
+
latestRunId = event.runId;
|
|
7732
|
+
}
|
|
7733
|
+
if (event.type === "run:cancelled") {
|
|
7734
|
+
runCancelled = true;
|
|
7735
|
+
}
|
|
7736
|
+
if (event.type === "run:completed") {
|
|
7737
|
+
runContinuation = event.result.continuation === true;
|
|
7738
|
+
runContinuationMessages = event.result.continuationMessages;
|
|
7739
|
+
runHarnessMessages = event.result.continuationMessages;
|
|
7740
|
+
runContextTokens = event.result.contextTokens ?? runContextTokens;
|
|
7741
|
+
runContextWindow = event.result.contextWindow ?? runContextWindow;
|
|
7742
|
+
runSteps = event.result.steps;
|
|
7743
|
+
if (typeof event.result.maxSteps === "number") {
|
|
7744
|
+
runMaxSteps = event.result.maxSteps;
|
|
7745
|
+
}
|
|
7746
|
+
if (draft.assistantResponse.length === 0 && event.result.response) {
|
|
7747
|
+
draft.assistantResponse = event.result.response;
|
|
7748
|
+
}
|
|
7749
|
+
}
|
|
7750
|
+
if (event.type === "run:error") {
|
|
7751
|
+
draft.assistantResponse = draft.assistantResponse || `[Error: ${event.error.message}]`;
|
|
7752
|
+
}
|
|
7753
|
+
if (onEvent) {
|
|
7754
|
+
await onEvent(event, draft);
|
|
7755
|
+
}
|
|
7756
|
+
}
|
|
7757
|
+
return {
|
|
7758
|
+
latestRunId,
|
|
7759
|
+
runCancelled,
|
|
7760
|
+
runContinuation,
|
|
7761
|
+
runContinuationMessages,
|
|
7762
|
+
runHarnessMessages,
|
|
7763
|
+
runContextTokens,
|
|
7764
|
+
runContextWindow,
|
|
7765
|
+
runSteps,
|
|
7766
|
+
runMaxSteps,
|
|
7767
|
+
draft
|
|
7768
|
+
};
|
|
7769
|
+
};
|
|
7770
|
+
var normalizePendingToolCalls = (value) => {
|
|
7771
|
+
if (!Array.isArray(value)) return [];
|
|
7772
|
+
return value.filter((entry) => {
|
|
7773
|
+
if (!entry || typeof entry !== "object") return false;
|
|
7774
|
+
const row = entry;
|
|
7775
|
+
return typeof row.id === "string" && typeof row.name === "string" && typeof row.input === "object" && row.input !== null;
|
|
7776
|
+
}).map((entry) => ({ id: entry.id, name: entry.name, input: entry.input }));
|
|
7777
|
+
};
|
|
7778
|
+
var normalizeApprovalCheckpoint = (approval, fallbackMessages) => ({
|
|
7779
|
+
...approval,
|
|
7780
|
+
checkpointMessages: isMessageArray(approval.checkpointMessages) ? approval.checkpointMessages : [...fallbackMessages],
|
|
7781
|
+
baseMessageCount: typeof approval.baseMessageCount === "number" && approval.baseMessageCount >= 0 ? approval.baseMessageCount : 0,
|
|
7782
|
+
pendingToolCalls: normalizePendingToolCalls(approval.pendingToolCalls)
|
|
7783
|
+
});
|
|
7784
|
+
var buildApprovalCheckpoints = ({
|
|
7785
|
+
approvals,
|
|
7786
|
+
runId,
|
|
7787
|
+
checkpointMessages,
|
|
7788
|
+
baseMessageCount,
|
|
7789
|
+
pendingToolCalls
|
|
7790
|
+
}) => approvals.map((approval) => ({
|
|
7791
|
+
approvalId: approval.approvalId,
|
|
7792
|
+
runId,
|
|
7793
|
+
tool: approval.tool,
|
|
7794
|
+
toolCallId: approval.toolCallId,
|
|
7795
|
+
input: approval.input,
|
|
7796
|
+
checkpointMessages,
|
|
7797
|
+
baseMessageCount,
|
|
7798
|
+
pendingToolCalls
|
|
7799
|
+
}));
|
|
7800
|
+
var resolveRunRequest = (conversation, request) => {
|
|
7801
|
+
const resolved = loadRunHistory(conversation, {
|
|
7802
|
+
preferContinuation: request.preferContinuation
|
|
7803
|
+
});
|
|
7804
|
+
return {
|
|
7805
|
+
source: resolved.source,
|
|
7806
|
+
shouldRebuildCanonical: resolved.shouldRebuildCanonical,
|
|
7807
|
+
messages: resolved.messages.length > 0 ? resolved.messages : request.messages
|
|
7808
|
+
};
|
|
7809
|
+
};
|
|
7810
|
+
var __internalRunOrchestration = {
|
|
7811
|
+
isMessageArray,
|
|
7812
|
+
loadCanonicalHistory,
|
|
7813
|
+
loadRunHistory,
|
|
7814
|
+
normalizeApprovalCheckpoint,
|
|
7815
|
+
buildApprovalCheckpoints,
|
|
7816
|
+
resolveRunRequest,
|
|
7817
|
+
createTurnDraftState,
|
|
7818
|
+
recordStandardTurnEvent,
|
|
7819
|
+
executeConversationTurn
|
|
7820
|
+
};
|
|
7531
7821
|
var AGENT_TEMPLATE = (name, id, options) => `---
|
|
7532
7822
|
name: ${name}
|
|
7533
7823
|
id: ${id}
|
|
@@ -8711,6 +9001,60 @@ data: ${JSON.stringify(statusPayload)}
|
|
|
8711
9001
|
const activeSubagentRuns = /* @__PURE__ */ new Map();
|
|
8712
9002
|
const pendingSubagentApprovals = /* @__PURE__ */ new Map();
|
|
8713
9003
|
const approvalDecisionTracker = /* @__PURE__ */ new Map();
|
|
9004
|
+
const findPendingApproval = async (approvalId, owner) => {
|
|
9005
|
+
const searchedConversationIds = /* @__PURE__ */ new Set();
|
|
9006
|
+
const scan = async (conversations) => {
|
|
9007
|
+
for (const conv of conversations) {
|
|
9008
|
+
if (searchedConversationIds.has(conv.conversationId)) continue;
|
|
9009
|
+
searchedConversationIds.add(conv.conversationId);
|
|
9010
|
+
if (!Array.isArray(conv.pendingApprovals)) continue;
|
|
9011
|
+
const match = conv.pendingApprovals.find((approval) => approval.approvalId === approvalId);
|
|
9012
|
+
if (match) {
|
|
9013
|
+
return { conversation: conv, approval: match };
|
|
9014
|
+
}
|
|
9015
|
+
}
|
|
9016
|
+
return void 0;
|
|
9017
|
+
};
|
|
9018
|
+
const ownerScoped = await scan(await conversationStore.list(owner));
|
|
9019
|
+
if (ownerScoped) return ownerScoped;
|
|
9020
|
+
if (owner === "local-owner") {
|
|
9021
|
+
return await scan(await conversationStore.list());
|
|
9022
|
+
}
|
|
9023
|
+
return void 0;
|
|
9024
|
+
};
|
|
9025
|
+
const hasRunningSubagentsForParent = async (parentConversationId, owner) => {
|
|
9026
|
+
let hasRunning = Array.from(activeSubagentRuns.values()).some(
|
|
9027
|
+
(run) => run.parentConversationId === parentConversationId
|
|
9028
|
+
);
|
|
9029
|
+
if (hasRunning) return true;
|
|
9030
|
+
const summaries = await conversationStore.listSummaries(owner);
|
|
9031
|
+
for (const summary of summaries) {
|
|
9032
|
+
if (summary.parentConversationId !== parentConversationId) continue;
|
|
9033
|
+
const childConversation = await conversationStore.get(summary.conversationId);
|
|
9034
|
+
if (childConversation?.subagentMeta?.status === "running") {
|
|
9035
|
+
hasRunning = true;
|
|
9036
|
+
break;
|
|
9037
|
+
}
|
|
9038
|
+
}
|
|
9039
|
+
return hasRunning;
|
|
9040
|
+
};
|
|
9041
|
+
const hasPendingSubagentWorkForParent = async (parentConversationId, owner) => {
|
|
9042
|
+
if (await hasRunningSubagentsForParent(parentConversationId, owner)) {
|
|
9043
|
+
return true;
|
|
9044
|
+
}
|
|
9045
|
+
if (pendingCallbackNeeded.has(parentConversationId)) {
|
|
9046
|
+
return true;
|
|
9047
|
+
}
|
|
9048
|
+
const parentConversation = await conversationStore.get(parentConversationId);
|
|
9049
|
+
if (!parentConversation) return false;
|
|
9050
|
+
if (Array.isArray(parentConversation.pendingSubagentResults) && parentConversation.pendingSubagentResults.length > 0) {
|
|
9051
|
+
return true;
|
|
9052
|
+
}
|
|
9053
|
+
if (typeof parentConversation.runningCallbackSince === "number" && parentConversation.runningCallbackSince > 0) {
|
|
9054
|
+
return true;
|
|
9055
|
+
}
|
|
9056
|
+
return false;
|
|
9057
|
+
};
|
|
8714
9058
|
const getSubagentDepth = async (conversationId) => {
|
|
8715
9059
|
let depth = 0;
|
|
8716
9060
|
let current = await conversationStore.get(conversationId);
|
|
@@ -8754,7 +9098,9 @@ data: ${JSON.stringify(statusPayload)}
|
|
|
8754
9098
|
const resumeSubagentFromCheckpoint = async (subagentId) => {
|
|
8755
9099
|
const conv = await conversationStore.get(subagentId);
|
|
8756
9100
|
if (!conv || !conv.parentConversationId) return;
|
|
8757
|
-
const allApprovals = conv.pendingApprovals ?? []
|
|
9101
|
+
const allApprovals = (conv.pendingApprovals ?? []).map(
|
|
9102
|
+
(approval) => normalizeApprovalCheckpoint(approval, conv.messages)
|
|
9103
|
+
);
|
|
8758
9104
|
if (allApprovals.length === 0) return;
|
|
8759
9105
|
const allDecided = allApprovals.every((a) => a.decision != null);
|
|
8760
9106
|
if (!allDecided) return;
|
|
@@ -8825,7 +9171,11 @@ data: ${JSON.stringify(statusPayload)}
|
|
|
8825
9171
|
if (conversation.subagentMeta?.status === "stopped") return;
|
|
8826
9172
|
conversation.lastActivityAt = Date.now();
|
|
8827
9173
|
await conversationStore.update(conversation);
|
|
8828
|
-
const
|
|
9174
|
+
const runOutcome = resolveRunRequest(conversation, {
|
|
9175
|
+
conversationId: childConversationId,
|
|
9176
|
+
messages: conversation.messages
|
|
9177
|
+
});
|
|
9178
|
+
const harnessMessages = [...runOutcome.messages];
|
|
8829
9179
|
for await (const event of childHarness.runWithTelemetry({
|
|
8830
9180
|
task,
|
|
8831
9181
|
conversationId: childConversationId,
|
|
@@ -8887,16 +9237,13 @@ data: ${JSON.stringify(statusPayload)}
|
|
|
8887
9237
|
if (event.type === "tool:approval:checkpoint") {
|
|
8888
9238
|
const cpConv = await conversationStore.get(childConversationId);
|
|
8889
9239
|
if (cpConv) {
|
|
8890
|
-
const allCpData =
|
|
8891
|
-
|
|
9240
|
+
const allCpData = buildApprovalCheckpoints({
|
|
9241
|
+
approvals: event.approvals,
|
|
8892
9242
|
runId: latestRunId,
|
|
8893
|
-
tool: a.tool,
|
|
8894
|
-
toolCallId: a.toolCallId,
|
|
8895
|
-
input: a.input,
|
|
8896
9243
|
checkpointMessages: [...harnessMessages, ...event.checkpointMessages],
|
|
8897
9244
|
baseMessageCount: 0,
|
|
8898
9245
|
pendingToolCalls: event.pendingToolCalls
|
|
8899
|
-
})
|
|
9246
|
+
});
|
|
8900
9247
|
cpConv.pendingApprovals = allCpData;
|
|
8901
9248
|
cpConv.updatedAt = Date.now();
|
|
8902
9249
|
await conversationStore.update(cpConv);
|
|
@@ -8911,7 +9258,7 @@ data: ${JSON.stringify(statusPayload)}
|
|
|
8911
9258
|
});
|
|
8912
9259
|
}
|
|
8913
9260
|
});
|
|
8914
|
-
const checkpointRef = allCpData[0];
|
|
9261
|
+
const checkpointRef = normalizeApprovalCheckpoint(allCpData[0], [...harnessMessages]);
|
|
8915
9262
|
const toolContext = {
|
|
8916
9263
|
runId: checkpointRef.runId,
|
|
8917
9264
|
agentId: identity.id,
|
|
@@ -9033,6 +9380,8 @@ data: ${JSON.stringify(statusPayload)}
|
|
|
9033
9380
|
}
|
|
9034
9381
|
if (runResult?.continuationMessages) {
|
|
9035
9382
|
conv._harnessMessages = runResult.continuationMessages;
|
|
9383
|
+
} else if (runOutcome.shouldRebuildCanonical) {
|
|
9384
|
+
conv._harnessMessages = conv.messages;
|
|
9036
9385
|
}
|
|
9037
9386
|
conv._toolResultArchive = childHarness.getToolResultArchive(childConversationId);
|
|
9038
9387
|
conv.lastActivityAt = Date.now();
|
|
@@ -9175,6 +9524,7 @@ ${resultBody}`,
|
|
|
9175
9524
|
metadata: { _subagentCallback: true, subagentId: pr.subagentId, task: pr.task, timestamp: pr.timestamp }
|
|
9176
9525
|
});
|
|
9177
9526
|
}
|
|
9527
|
+
conversation._harnessMessages = [...conversation.messages];
|
|
9178
9528
|
conversation.updatedAt = Date.now();
|
|
9179
9529
|
await conversationStore.update(conversation);
|
|
9180
9530
|
if (callbackCount > MAX_SUBAGENT_CALLBACK_COUNT) {
|
|
@@ -9203,109 +9553,70 @@ ${resultBody}`,
|
|
|
9203
9553
|
finished: false
|
|
9204
9554
|
});
|
|
9205
9555
|
}
|
|
9206
|
-
const
|
|
9207
|
-
|
|
9208
|
-
|
|
9209
|
-
|
|
9210
|
-
|
|
9211
|
-
|
|
9212
|
-
|
|
9213
|
-
|
|
9214
|
-
|
|
9215
|
-
|
|
9216
|
-
let currentTools = [];
|
|
9217
|
-
let currentText = "";
|
|
9556
|
+
const historySelection = resolveRunRequest(conversation, {
|
|
9557
|
+
conversationId,
|
|
9558
|
+
messages: conversation.messages,
|
|
9559
|
+
preferContinuation: isContinuationResume
|
|
9560
|
+
});
|
|
9561
|
+
const historyMessages = [...historySelection.messages];
|
|
9562
|
+
console.info(
|
|
9563
|
+
`[poncho][subagent-callback] conversation="${conversationId}" history_source=${historySelection.source}`
|
|
9564
|
+
);
|
|
9565
|
+
let execution;
|
|
9218
9566
|
try {
|
|
9219
|
-
|
|
9220
|
-
|
|
9221
|
-
|
|
9222
|
-
|
|
9223
|
-
|
|
9224
|
-
|
|
9225
|
-
|
|
9226
|
-
|
|
9227
|
-
|
|
9228
|
-
|
|
9229
|
-
|
|
9230
|
-
|
|
9231
|
-
|
|
9232
|
-
|
|
9233
|
-
|
|
9234
|
-
|
|
9235
|
-
|
|
9236
|
-
|
|
9237
|
-
currentTools = [];
|
|
9238
|
-
if (assistantResponse.length > 0 && !/\s$/.test(assistantResponse)) {
|
|
9239
|
-
assistantResponse += " ";
|
|
9240
|
-
}
|
|
9241
|
-
}
|
|
9242
|
-
assistantResponse += event.content;
|
|
9243
|
-
currentText += event.content;
|
|
9244
|
-
}
|
|
9245
|
-
if (event.type === "tool:started") {
|
|
9246
|
-
if (currentText.length > 0) {
|
|
9247
|
-
sections.push({ type: "text", content: currentText });
|
|
9248
|
-
currentText = "";
|
|
9249
|
-
}
|
|
9250
|
-
const toolText = `- start \`${event.tool}\``;
|
|
9251
|
-
toolTimeline.push(toolText);
|
|
9252
|
-
currentTools.push(toolText);
|
|
9253
|
-
}
|
|
9254
|
-
if (event.type === "tool:completed") {
|
|
9255
|
-
const toolText = `- done \`${event.tool}\` (${event.duration}ms)`;
|
|
9256
|
-
toolTimeline.push(toolText);
|
|
9257
|
-
currentTools.push(toolText);
|
|
9258
|
-
}
|
|
9259
|
-
if (event.type === "tool:error") {
|
|
9260
|
-
const toolText = `- error \`${event.tool}\`: ${event.error}`;
|
|
9261
|
-
toolTimeline.push(toolText);
|
|
9262
|
-
currentTools.push(toolText);
|
|
9263
|
-
}
|
|
9264
|
-
if (event.type === "run:completed") {
|
|
9265
|
-
if (assistantResponse.length === 0 && event.result.response) {
|
|
9266
|
-
assistantResponse = event.result.response;
|
|
9267
|
-
}
|
|
9268
|
-
runContextTokens = event.result.contextTokens ?? runContextTokens;
|
|
9269
|
-
runContextWindow = event.result.contextWindow ?? runContextWindow;
|
|
9270
|
-
if (event.result.continuationMessages) {
|
|
9271
|
-
runHarnessMessages = event.result.continuationMessages;
|
|
9272
|
-
}
|
|
9273
|
-
if (event.result.continuation) {
|
|
9274
|
-
runContinuation2 = true;
|
|
9275
|
-
if (event.result.continuationMessages) {
|
|
9276
|
-
runContinuationMessages = event.result.continuationMessages;
|
|
9277
|
-
}
|
|
9567
|
+
execution = await executeConversationTurn({
|
|
9568
|
+
harness,
|
|
9569
|
+
runInput: {
|
|
9570
|
+
task: void 0,
|
|
9571
|
+
conversationId,
|
|
9572
|
+
parameters: withToolResultArchiveParam({
|
|
9573
|
+
__activeConversationId: conversationId,
|
|
9574
|
+
__ownerId: conversation.ownerId
|
|
9575
|
+
}, conversation),
|
|
9576
|
+
messages: historyMessages,
|
|
9577
|
+
abortSignal: abortController.signal
|
|
9578
|
+
},
|
|
9579
|
+
initialContextTokens: conversation.contextTokens ?? 0,
|
|
9580
|
+
initialContextWindow: conversation.contextWindow ?? 0,
|
|
9581
|
+
onEvent: (event) => {
|
|
9582
|
+
if (event.type === "run:started") {
|
|
9583
|
+
const active = activeConversationRuns.get(conversationId);
|
|
9584
|
+
if (active) active.runId = event.runId;
|
|
9278
9585
|
}
|
|
9586
|
+
broadcastEvent(conversationId, event);
|
|
9279
9587
|
}
|
|
9280
|
-
|
|
9281
|
-
|
|
9282
|
-
|
|
9283
|
-
if (
|
|
9284
|
-
if (runContinuationMessages || assistantResponse.length > 0 || toolTimeline.length > 0) {
|
|
9588
|
+
});
|
|
9589
|
+
flushTurnDraft(execution.draft);
|
|
9590
|
+
const callbackNeedsContinuation = execution.runContinuation && execution.runContinuationMessages;
|
|
9591
|
+
if (callbackNeedsContinuation || execution.draft.assistantResponse.length > 0 || execution.draft.toolTimeline.length > 0) {
|
|
9285
9592
|
const freshConv = await conversationStore.get(conversationId);
|
|
9286
9593
|
if (freshConv) {
|
|
9287
|
-
if (
|
|
9288
|
-
freshConv._continuationMessages = runContinuationMessages;
|
|
9594
|
+
if (callbackNeedsContinuation) {
|
|
9595
|
+
freshConv._continuationMessages = execution.runContinuationMessages;
|
|
9289
9596
|
} else {
|
|
9290
9597
|
freshConv._continuationMessages = void 0;
|
|
9291
9598
|
freshConv.messages.push({
|
|
9292
9599
|
role: "assistant",
|
|
9293
|
-
content: assistantResponse,
|
|
9294
|
-
metadata:
|
|
9600
|
+
content: execution.draft.assistantResponse,
|
|
9601
|
+
metadata: buildAssistantMetadata(execution.draft)
|
|
9295
9602
|
});
|
|
9296
9603
|
}
|
|
9297
|
-
if (runHarnessMessages) {
|
|
9298
|
-
freshConv._harnessMessages = runHarnessMessages;
|
|
9604
|
+
if (callbackNeedsContinuation && execution.runHarnessMessages) {
|
|
9605
|
+
freshConv._harnessMessages = execution.runHarnessMessages;
|
|
9606
|
+
} else if (historySelection.shouldRebuildCanonical) {
|
|
9607
|
+
freshConv._harnessMessages = freshConv.messages;
|
|
9608
|
+
} else {
|
|
9609
|
+
freshConv._harnessMessages = freshConv.messages;
|
|
9299
9610
|
}
|
|
9300
9611
|
freshConv._toolResultArchive = harness.getToolResultArchive(conversationId);
|
|
9301
|
-
freshConv.runtimeRunId = latestRunId || freshConv.runtimeRunId;
|
|
9612
|
+
freshConv.runtimeRunId = execution.latestRunId || freshConv.runtimeRunId;
|
|
9302
9613
|
freshConv.runningCallbackSince = void 0;
|
|
9303
9614
|
freshConv.runStatus = "idle";
|
|
9304
|
-
if (runContextTokens > 0) freshConv.contextTokens = runContextTokens;
|
|
9305
|
-
if (runContextWindow > 0) freshConv.contextWindow = runContextWindow;
|
|
9615
|
+
if (execution.runContextTokens > 0) freshConv.contextTokens = execution.runContextTokens;
|
|
9616
|
+
if (execution.runContextWindow > 0) freshConv.contextWindow = execution.runContextWindow;
|
|
9306
9617
|
freshConv.updatedAt = Date.now();
|
|
9307
9618
|
await conversationStore.update(freshConv);
|
|
9308
|
-
if (freshConv.channelMeta && assistantResponse.length > 0) {
|
|
9619
|
+
if (freshConv.channelMeta && execution.draft.assistantResponse.length > 0) {
|
|
9309
9620
|
const adapter = messagingAdapters.get(freshConv.channelMeta.platform);
|
|
9310
9621
|
if (adapter) {
|
|
9311
9622
|
try {
|
|
@@ -9314,7 +9625,7 @@ ${resultBody}`,
|
|
|
9314
9625
|
channelId: freshConv.channelMeta.channelId,
|
|
9315
9626
|
platformThreadId: freshConv.channelMeta.platformThreadId
|
|
9316
9627
|
},
|
|
9317
|
-
assistantResponse
|
|
9628
|
+
execution.draft.assistantResponse
|
|
9318
9629
|
);
|
|
9319
9630
|
} catch (sendErr) {
|
|
9320
9631
|
console.error(`[poncho][subagent-callback] Messaging notify failed:`, sendErr instanceof Error ? sendErr.message : sendErr);
|
|
@@ -9323,7 +9634,7 @@ ${resultBody}`,
|
|
|
9323
9634
|
}
|
|
9324
9635
|
}
|
|
9325
9636
|
}
|
|
9326
|
-
if (
|
|
9637
|
+
if (execution.runContinuation) {
|
|
9327
9638
|
if (isServerless) {
|
|
9328
9639
|
const work = selfFetchWithRetry(`/api/internal/conversations/${encodeURIComponent(conversationId)}/subagent-callback`).catch(
|
|
9329
9640
|
(err) => console.error(`[poncho][subagent-callback] Continuation self-fetch failed:`, err instanceof Error ? err.message : err)
|
|
@@ -9345,10 +9656,15 @@ ${resultBody}`,
|
|
|
9345
9656
|
}
|
|
9346
9657
|
} finally {
|
|
9347
9658
|
activeConversationRuns.delete(conversationId);
|
|
9348
|
-
finishConversationStream(conversationId);
|
|
9349
9659
|
const hadDeferredTrigger = pendingCallbackNeeded.delete(conversationId);
|
|
9350
9660
|
const freshConv = await conversationStore.get(conversationId);
|
|
9351
9661
|
const hasPendingInStore = !!freshConv?.pendingSubagentResults?.length;
|
|
9662
|
+
const hasRunningCallbackChildren = Array.from(activeSubagentRuns.values()).some(
|
|
9663
|
+
(run) => run.parentConversationId === conversationId
|
|
9664
|
+
);
|
|
9665
|
+
if (!hadDeferredTrigger && !hasPendingInStore && !hasRunningCallbackChildren) {
|
|
9666
|
+
finishConversationStream(conversationId);
|
|
9667
|
+
}
|
|
9352
9668
|
if (hadDeferredTrigger || hasPendingInStore) {
|
|
9353
9669
|
if (isServerless) {
|
|
9354
9670
|
selfFetchWithRetry(`/api/internal/conversations/${encodeURIComponent(conversationId)}/subagent-callback`).catch(
|
|
@@ -9496,8 +9812,9 @@ ${resultBody}`,
|
|
|
9496
9812
|
let runContextTokens = conversation.contextTokens ?? 0;
|
|
9497
9813
|
let runContextWindow = conversation.contextWindow ?? 0;
|
|
9498
9814
|
let resumeHarnessMessages;
|
|
9499
|
-
const
|
|
9500
|
-
const
|
|
9815
|
+
const normalizedCheckpoint = normalizeApprovalCheckpoint(checkpoint, conversation.messages);
|
|
9816
|
+
const baseMessages = normalizedCheckpoint.baseMessageCount != null ? conversation.messages.slice(0, normalizedCheckpoint.baseMessageCount) : [];
|
|
9817
|
+
const fullCheckpointMessages = [...baseMessages, ...normalizedCheckpoint.checkpointMessages];
|
|
9501
9818
|
let resumeToolResultMsg;
|
|
9502
9819
|
const lastCpMsg = fullCheckpointMessages[fullCheckpointMessages.length - 1];
|
|
9503
9820
|
if (lastCpMsg?.role === "assistant") {
|
|
@@ -9578,24 +9895,26 @@ ${resultBody}`,
|
|
|
9578
9895
|
if (event.type === "tool:approval:checkpoint") {
|
|
9579
9896
|
const conv = await conversationStore.get(conversationId);
|
|
9580
9897
|
if (conv) {
|
|
9581
|
-
conv.pendingApprovals =
|
|
9582
|
-
|
|
9898
|
+
conv.pendingApprovals = buildApprovalCheckpoints({
|
|
9899
|
+
approvals: event.approvals,
|
|
9583
9900
|
runId: latestRunId,
|
|
9584
|
-
tool: a.tool,
|
|
9585
|
-
toolCallId: a.toolCallId,
|
|
9586
|
-
input: a.input,
|
|
9587
9901
|
checkpointMessages: [...fullCheckpointWithResults, ...event.checkpointMessages],
|
|
9588
9902
|
baseMessageCount: 0,
|
|
9589
9903
|
pendingToolCalls: event.pendingToolCalls
|
|
9590
|
-
})
|
|
9904
|
+
});
|
|
9591
9905
|
conv.updatedAt = Date.now();
|
|
9592
9906
|
await conversationStore.update(conv);
|
|
9593
9907
|
if (conv.channelMeta?.platform === "telegram") {
|
|
9594
9908
|
const tgAdapter = messagingAdapters.get("telegram");
|
|
9595
9909
|
if (tgAdapter) {
|
|
9910
|
+
const messageThreadId = parseTelegramMessageThreadIdFromPlatformThreadId(
|
|
9911
|
+
conv.channelMeta.platformThreadId,
|
|
9912
|
+
conv.channelMeta.channelId
|
|
9913
|
+
);
|
|
9596
9914
|
void tgAdapter.sendApprovalRequest(
|
|
9597
9915
|
conv.channelMeta.channelId,
|
|
9598
|
-
event.approvals.map((a) => ({ approvalId: a.approvalId, tool: a.tool, input: a.input }))
|
|
9916
|
+
event.approvals.map((a) => ({ approvalId: a.approvalId, tool: a.tool, input: a.input })),
|
|
9917
|
+
{ message_thread_id: messageThreadId }
|
|
9599
9918
|
).catch(() => {
|
|
9600
9919
|
});
|
|
9601
9920
|
}
|
|
@@ -9673,6 +9992,8 @@ ${resultBody}`,
|
|
|
9673
9992
|
}
|
|
9674
9993
|
if (resumeHarnessMessages) {
|
|
9675
9994
|
conv._harnessMessages = resumeHarnessMessages;
|
|
9995
|
+
} else {
|
|
9996
|
+
conv._harnessMessages = conv.messages;
|
|
9676
9997
|
}
|
|
9677
9998
|
conv.runtimeRunId = latestRunId || conv.runtimeRunId;
|
|
9678
9999
|
conv.pendingApprovals = [];
|
|
@@ -9690,7 +10011,6 @@ ${resultBody}`,
|
|
|
9690
10011
|
await conversationStore.update(conv);
|
|
9691
10012
|
}
|
|
9692
10013
|
}
|
|
9693
|
-
finishConversationStream(conversationId);
|
|
9694
10014
|
activeConversationRuns.delete(conversationId);
|
|
9695
10015
|
if (latestRunId) {
|
|
9696
10016
|
runOwners.delete(latestRunId);
|
|
@@ -9699,7 +10019,14 @@ ${resultBody}`,
|
|
|
9699
10019
|
console.log("[resume-run] complete for", conversationId);
|
|
9700
10020
|
const hadDeferred = pendingCallbackNeeded.delete(conversationId);
|
|
9701
10021
|
const postConv = await conversationStore.get(conversationId);
|
|
9702
|
-
|
|
10022
|
+
const needsResumeCallback = hadDeferred || !!postConv?.pendingSubagentResults?.length;
|
|
10023
|
+
const hasRunningResumeChildren = Array.from(activeSubagentRuns.values()).some(
|
|
10024
|
+
(run) => run.parentConversationId === conversationId
|
|
10025
|
+
);
|
|
10026
|
+
if (!needsResumeCallback && !hasRunningResumeChildren) {
|
|
10027
|
+
finishConversationStream(conversationId);
|
|
10028
|
+
}
|
|
10029
|
+
if (needsResumeCallback) {
|
|
9703
10030
|
processSubagentCallback(conversationId, true).catch(
|
|
9704
10031
|
(err) => console.error(`[poncho][subagent-callback] Post-resume callback failed:`, err instanceof Error ? err.message : err)
|
|
9705
10032
|
);
|
|
@@ -9726,7 +10053,7 @@ ${resultBody}`,
|
|
|
9726
10053
|
};
|
|
9727
10054
|
await conversationStore.update(existing);
|
|
9728
10055
|
}
|
|
9729
|
-
return { messages: existing.
|
|
10056
|
+
return { messages: loadCanonicalHistory(existing).messages };
|
|
9730
10057
|
}
|
|
9731
10058
|
const now = Date.now();
|
|
9732
10059
|
const channelMeta = meta.channelId ? {
|
|
@@ -9748,10 +10075,15 @@ ${resultBody}`,
|
|
|
9748
10075
|
return { messages: [] };
|
|
9749
10076
|
},
|
|
9750
10077
|
async run(conversationId, input2) {
|
|
10078
|
+
const latestConversation = await conversationStore.get(conversationId);
|
|
10079
|
+
const canonicalHistory = latestConversation ? loadCanonicalHistory(latestConversation) : { messages: [...input2.messages], source: "messages" };
|
|
10080
|
+
const shouldRebuildCanonical = canonicalHistory.source !== "harness";
|
|
9751
10081
|
const isContinuation = input2.task == null;
|
|
9752
|
-
console.log(
|
|
9753
|
-
|
|
9754
|
-
|
|
10082
|
+
console.log(
|
|
10083
|
+
`[messaging-runner] starting run for ${conversationId} ${isContinuation ? "(continuation)" : `task: ${input2.task.slice(0, 80)}`} history_source=${canonicalHistory.source}`
|
|
10084
|
+
);
|
|
10085
|
+
const historyMessages = [...canonicalHistory.messages];
|
|
10086
|
+
const preRunMessages = [...canonicalHistory.messages];
|
|
9755
10087
|
const userContent = input2.task;
|
|
9756
10088
|
const updateConversation = async (patch) => {
|
|
9757
10089
|
const fresh = await conversationStore.get(conversationId);
|
|
@@ -9767,11 +10099,7 @@ ${resultBody}`,
|
|
|
9767
10099
|
c.runStatus = "running";
|
|
9768
10100
|
});
|
|
9769
10101
|
let latestRunId = "";
|
|
9770
|
-
|
|
9771
|
-
const toolTimeline = [];
|
|
9772
|
-
const sections = [];
|
|
9773
|
-
let currentTools = [];
|
|
9774
|
-
let currentText = "";
|
|
10102
|
+
const draft = createTurnDraftState();
|
|
9775
10103
|
let checkpointedRun = false;
|
|
9776
10104
|
let runContextTokens = 0;
|
|
9777
10105
|
let runContextWindow = 0;
|
|
@@ -9780,20 +10108,15 @@ ${resultBody}`,
|
|
|
9780
10108
|
let runSteps = 0;
|
|
9781
10109
|
let runMaxSteps;
|
|
9782
10110
|
const buildMessages = () => {
|
|
9783
|
-
const draftSections =
|
|
9784
|
-
|
|
9785
|
-
|
|
9786
|
-
content: Array.isArray(s.content) ? [...s.content] : s.content
|
|
9787
|
-
}))
|
|
9788
|
-
];
|
|
9789
|
-
if (currentTools.length > 0) {
|
|
9790
|
-
draftSections.push({ type: "tools", content: [...currentTools] });
|
|
10111
|
+
const draftSections = cloneSections(draft.sections);
|
|
10112
|
+
if (draft.currentTools.length > 0) {
|
|
10113
|
+
draftSections.push({ type: "tools", content: [...draft.currentTools] });
|
|
9791
10114
|
}
|
|
9792
|
-
if (currentText.length > 0) {
|
|
9793
|
-
draftSections.push({ type: "text", content: currentText });
|
|
10115
|
+
if (draft.currentText.length > 0) {
|
|
10116
|
+
draftSections.push({ type: "text", content: draft.currentText });
|
|
9794
10117
|
}
|
|
9795
10118
|
const userTurn = userContent != null ? [{ role: "user", content: userContent }] : [];
|
|
9796
|
-
const hasDraftContent = assistantResponse.length > 0 || toolTimeline.length > 0 || draftSections.length > 0;
|
|
10119
|
+
const hasDraftContent = draft.assistantResponse.length > 0 || draft.toolTimeline.length > 0 || draftSections.length > 0;
|
|
9797
10120
|
if (!hasDraftContent) {
|
|
9798
10121
|
return [...historyMessages, ...userTurn];
|
|
9799
10122
|
}
|
|
@@ -9802,16 +10125,13 @@ ${resultBody}`,
|
|
|
9802
10125
|
...userTurn,
|
|
9803
10126
|
{
|
|
9804
10127
|
role: "assistant",
|
|
9805
|
-
content: assistantResponse,
|
|
9806
|
-
metadata:
|
|
9807
|
-
toolActivity: [...toolTimeline],
|
|
9808
|
-
sections: draftSections.length > 0 ? draftSections : void 0
|
|
9809
|
-
} : void 0
|
|
10128
|
+
content: draft.assistantResponse,
|
|
10129
|
+
metadata: buildAssistantMetadata(draft, draftSections)
|
|
9810
10130
|
}
|
|
9811
10131
|
];
|
|
9812
10132
|
};
|
|
9813
10133
|
const persistDraftAssistantTurn = async () => {
|
|
9814
|
-
if (assistantResponse.length === 0 && toolTimeline.length === 0) return;
|
|
10134
|
+
if (draft.assistantResponse.length === 0 && draft.toolTimeline.length === 0) return;
|
|
9815
10135
|
await updateConversation((c) => {
|
|
9816
10136
|
c.messages = buildMessages();
|
|
9817
10137
|
});
|
|
@@ -9819,139 +10139,107 @@ ${resultBody}`,
|
|
|
9819
10139
|
const runInput = {
|
|
9820
10140
|
task: input2.task,
|
|
9821
10141
|
conversationId,
|
|
9822
|
-
messages:
|
|
10142
|
+
messages: historyMessages,
|
|
9823
10143
|
files: input2.files,
|
|
9824
|
-
parameters:
|
|
9825
|
-
|
|
9826
|
-
|
|
9827
|
-
|
|
9828
|
-
|
|
9829
|
-
|
|
10144
|
+
parameters: {
|
|
10145
|
+
...input2.metadata ? {
|
|
10146
|
+
__messaging_platform: input2.metadata.platform,
|
|
10147
|
+
__messaging_sender_id: input2.metadata.sender.id,
|
|
10148
|
+
__messaging_sender_name: input2.metadata.sender.name ?? "",
|
|
10149
|
+
__messaging_thread_id: input2.metadata.threadId
|
|
10150
|
+
} : {},
|
|
10151
|
+
__activeConversationId: conversationId
|
|
10152
|
+
}
|
|
9830
10153
|
};
|
|
9831
10154
|
try {
|
|
9832
|
-
|
|
9833
|
-
|
|
9834
|
-
|
|
9835
|
-
|
|
9836
|
-
|
|
9837
|
-
|
|
9838
|
-
|
|
9839
|
-
|
|
9840
|
-
|
|
9841
|
-
|
|
9842
|
-
|
|
9843
|
-
|
|
9844
|
-
|
|
10155
|
+
const execution = await executeConversationTurn({
|
|
10156
|
+
harness,
|
|
10157
|
+
runInput,
|
|
10158
|
+
onEvent: async (event, eventDraft) => {
|
|
10159
|
+
draft.assistantResponse = eventDraft.assistantResponse;
|
|
10160
|
+
draft.toolTimeline = eventDraft.toolTimeline;
|
|
10161
|
+
draft.sections = eventDraft.sections;
|
|
10162
|
+
draft.currentTools = eventDraft.currentTools;
|
|
10163
|
+
draft.currentText = eventDraft.currentText;
|
|
10164
|
+
if (event.type === "run:started") {
|
|
10165
|
+
latestRunId = event.runId;
|
|
10166
|
+
runOwners.set(event.runId, "local-owner");
|
|
10167
|
+
runConversations.set(event.runId, conversationId);
|
|
9845
10168
|
}
|
|
9846
|
-
|
|
9847
|
-
|
|
9848
|
-
}
|
|
9849
|
-
if (event.type === "tool:started") {
|
|
9850
|
-
if (currentText.length > 0) {
|
|
9851
|
-
sections.push({ type: "text", content: currentText });
|
|
9852
|
-
currentText = "";
|
|
10169
|
+
if (event.type === "step:completed") {
|
|
10170
|
+
await persistDraftAssistantTurn();
|
|
9853
10171
|
}
|
|
9854
|
-
|
|
9855
|
-
|
|
9856
|
-
|
|
9857
|
-
|
|
9858
|
-
|
|
9859
|
-
const toolText = `- done \`${event.tool}\` (${event.duration}ms)`;
|
|
9860
|
-
toolTimeline.push(toolText);
|
|
9861
|
-
currentTools.push(toolText);
|
|
9862
|
-
}
|
|
9863
|
-
if (event.type === "tool:error") {
|
|
9864
|
-
const toolText = `- error \`${event.tool}\`: ${event.error}`;
|
|
9865
|
-
toolTimeline.push(toolText);
|
|
9866
|
-
currentTools.push(toolText);
|
|
9867
|
-
}
|
|
9868
|
-
if (event.type === "step:completed") {
|
|
9869
|
-
await persistDraftAssistantTurn();
|
|
9870
|
-
}
|
|
9871
|
-
if (event.type === "tool:approval:required") {
|
|
9872
|
-
const toolText = `- approval required \`${event.tool}\``;
|
|
9873
|
-
toolTimeline.push(toolText);
|
|
9874
|
-
currentTools.push(toolText);
|
|
9875
|
-
await persistDraftAssistantTurn();
|
|
9876
|
-
}
|
|
9877
|
-
if (event.type === "tool:approval:checkpoint") {
|
|
9878
|
-
await updateConversation((c) => {
|
|
9879
|
-
c.messages = buildMessages();
|
|
9880
|
-
c.pendingApprovals = event.approvals.map((a) => ({
|
|
9881
|
-
approvalId: a.approvalId,
|
|
9882
|
-
runId: latestRunId,
|
|
9883
|
-
tool: a.tool,
|
|
9884
|
-
toolCallId: a.toolCallId,
|
|
9885
|
-
input: a.input,
|
|
9886
|
-
checkpointMessages: event.checkpointMessages,
|
|
9887
|
-
baseMessageCount: historyMessages.length,
|
|
9888
|
-
pendingToolCalls: event.pendingToolCalls
|
|
9889
|
-
}));
|
|
9890
|
-
});
|
|
9891
|
-
checkpointedRun = true;
|
|
9892
|
-
const conv = await conversationStore.get(conversationId);
|
|
9893
|
-
if (conv?.channelMeta?.platform === "telegram") {
|
|
9894
|
-
const tgAdapter = messagingAdapters.get("telegram");
|
|
9895
|
-
if (tgAdapter) {
|
|
9896
|
-
const approvals = event.approvals.map((a) => ({
|
|
9897
|
-
approvalId: a.approvalId,
|
|
9898
|
-
tool: a.tool,
|
|
9899
|
-
input: a.input
|
|
9900
|
-
}));
|
|
9901
|
-
void tgAdapter.sendApprovalRequest(
|
|
9902
|
-
conv.channelMeta.channelId,
|
|
9903
|
-
approvals
|
|
9904
|
-
).catch((err) => {
|
|
9905
|
-
console.error("[messaging-runner] failed to send Telegram approval request:", err instanceof Error ? err.message : err);
|
|
9906
|
-
});
|
|
9907
|
-
}
|
|
10172
|
+
if (event.type === "tool:approval:required") {
|
|
10173
|
+
const toolText = `- approval required \`${event.tool}\``;
|
|
10174
|
+
draft.toolTimeline.push(toolText);
|
|
10175
|
+
draft.currentTools.push(toolText);
|
|
10176
|
+
await persistDraftAssistantTurn();
|
|
9908
10177
|
}
|
|
9909
|
-
|
|
9910
|
-
if (event.type === "compaction:completed") {
|
|
9911
|
-
if (event.compactedMessages) {
|
|
9912
|
-
historyMessages.length = 0;
|
|
9913
|
-
historyMessages.push(...event.compactedMessages);
|
|
9914
|
-
const preservedFromHistory = historyMessages.length - 1;
|
|
9915
|
-
const removedCount = preRunMessages.length - Math.max(0, preservedFromHistory);
|
|
10178
|
+
if (event.type === "tool:approval:checkpoint") {
|
|
9916
10179
|
await updateConversation((c) => {
|
|
9917
|
-
|
|
9918
|
-
c.
|
|
9919
|
-
|
|
9920
|
-
|
|
9921
|
-
|
|
10180
|
+
c.messages = buildMessages();
|
|
10181
|
+
c.pendingApprovals = buildApprovalCheckpoints({
|
|
10182
|
+
approvals: event.approvals,
|
|
10183
|
+
runId: latestRunId,
|
|
10184
|
+
checkpointMessages: event.checkpointMessages,
|
|
10185
|
+
baseMessageCount: historyMessages.length,
|
|
10186
|
+
pendingToolCalls: event.pendingToolCalls
|
|
10187
|
+
});
|
|
9922
10188
|
});
|
|
10189
|
+
checkpointedRun = true;
|
|
10190
|
+
const conv = await conversationStore.get(conversationId);
|
|
10191
|
+
if (conv?.channelMeta?.platform === "telegram") {
|
|
10192
|
+
const tgAdapter = messagingAdapters.get("telegram");
|
|
10193
|
+
if (tgAdapter) {
|
|
10194
|
+
const approvals = event.approvals.map((a) => ({
|
|
10195
|
+
approvalId: a.approvalId,
|
|
10196
|
+
tool: a.tool,
|
|
10197
|
+
input: a.input
|
|
10198
|
+
}));
|
|
10199
|
+
const messageThreadId = parseTelegramMessageThreadIdFromPlatformThreadId(
|
|
10200
|
+
conv.channelMeta.platformThreadId,
|
|
10201
|
+
conv.channelMeta.channelId
|
|
10202
|
+
);
|
|
10203
|
+
void tgAdapter.sendApprovalRequest(
|
|
10204
|
+
conv.channelMeta.channelId,
|
|
10205
|
+
approvals,
|
|
10206
|
+
{ message_thread_id: messageThreadId }
|
|
10207
|
+
).catch((err) => {
|
|
10208
|
+
console.error("[messaging-runner] failed to send Telegram approval request:", err instanceof Error ? err.message : err);
|
|
10209
|
+
});
|
|
10210
|
+
}
|
|
10211
|
+
}
|
|
9923
10212
|
}
|
|
9924
|
-
|
|
9925
|
-
|
|
9926
|
-
|
|
9927
|
-
|
|
9928
|
-
|
|
9929
|
-
|
|
9930
|
-
|
|
9931
|
-
|
|
10213
|
+
if (event.type === "compaction:completed") {
|
|
10214
|
+
if (event.compactedMessages) {
|
|
10215
|
+
historyMessages.length = 0;
|
|
10216
|
+
historyMessages.push(...event.compactedMessages);
|
|
10217
|
+
const preservedFromHistory = historyMessages.length - 1;
|
|
10218
|
+
const removedCount = preRunMessages.length - Math.max(0, preservedFromHistory);
|
|
10219
|
+
await updateConversation((c) => {
|
|
10220
|
+
const existingHistory = c.compactedHistory ?? [];
|
|
10221
|
+
c.compactedHistory = [
|
|
10222
|
+
...existingHistory,
|
|
10223
|
+
...preRunMessages.slice(0, removedCount)
|
|
10224
|
+
];
|
|
10225
|
+
});
|
|
10226
|
+
}
|
|
9932
10227
|
}
|
|
9933
|
-
|
|
9934
|
-
if (typeof event.result.maxSteps === "number") runMaxSteps = event.result.maxSteps;
|
|
9935
|
-
runContextTokens = event.result.contextTokens ?? runContextTokens;
|
|
9936
|
-
runContextWindow = event.result.contextWindow ?? runContextWindow;
|
|
9937
|
-
}
|
|
9938
|
-
if (event.type === "run:error") {
|
|
9939
|
-
assistantResponse = assistantResponse || `[Error: ${event.error.message}]`;
|
|
10228
|
+
broadcastEvent(conversationId, event);
|
|
9940
10229
|
}
|
|
9941
|
-
|
|
9942
|
-
|
|
10230
|
+
});
|
|
10231
|
+
runContinuation2 = execution.runContinuation;
|
|
10232
|
+
runContinuationMessages = execution.runContinuationMessages;
|
|
10233
|
+
runSteps = execution.runSteps;
|
|
10234
|
+
runMaxSteps = execution.runMaxSteps;
|
|
10235
|
+
runContextTokens = execution.runContextTokens;
|
|
10236
|
+
runContextWindow = execution.runContextWindow;
|
|
10237
|
+
latestRunId = execution.latestRunId || latestRunId;
|
|
9943
10238
|
} catch (err) {
|
|
9944
10239
|
console.error("[messaging-runner] run failed:", err instanceof Error ? err.message : err);
|
|
9945
|
-
assistantResponse = assistantResponse || `[Error: ${err instanceof Error ? err.message : "Unknown error"}]`;
|
|
9946
|
-
}
|
|
9947
|
-
if (currentTools.length > 0) {
|
|
9948
|
-
sections.push({ type: "tools", content: currentTools });
|
|
9949
|
-
currentTools = [];
|
|
9950
|
-
}
|
|
9951
|
-
if (currentText.length > 0) {
|
|
9952
|
-
sections.push({ type: "text", content: currentText });
|
|
9953
|
-
currentText = "";
|
|
10240
|
+
draft.assistantResponse = draft.assistantResponse || `[Error: ${err instanceof Error ? err.message : "Unknown error"}]`;
|
|
9954
10241
|
}
|
|
10242
|
+
flushTurnDraft(draft);
|
|
9955
10243
|
if (!checkpointedRun) {
|
|
9956
10244
|
await updateConversation((c) => {
|
|
9957
10245
|
if (runContinuation2 && runContinuationMessages) {
|
|
@@ -9962,6 +10250,10 @@ ${resultBody}`,
|
|
|
9962
10250
|
}
|
|
9963
10251
|
if (runContinuationMessages) {
|
|
9964
10252
|
c._harnessMessages = runContinuationMessages;
|
|
10253
|
+
} else if (shouldRebuildCanonical) {
|
|
10254
|
+
c._harnessMessages = c.messages;
|
|
10255
|
+
} else {
|
|
10256
|
+
c._harnessMessages = c.messages;
|
|
9965
10257
|
}
|
|
9966
10258
|
c.runtimeRunId = latestRunId || c.runtimeRunId;
|
|
9967
10259
|
c.pendingApprovals = [];
|
|
@@ -9971,6 +10263,9 @@ ${resultBody}`,
|
|
|
9971
10263
|
});
|
|
9972
10264
|
} else {
|
|
9973
10265
|
await updateConversation((c) => {
|
|
10266
|
+
if (shouldRebuildCanonical && !c._harnessMessages?.length) {
|
|
10267
|
+
c._harnessMessages = c.messages;
|
|
10268
|
+
}
|
|
9974
10269
|
c.runStatus = "idle";
|
|
9975
10270
|
});
|
|
9976
10271
|
}
|
|
@@ -9979,8 +10274,8 @@ ${resultBody}`,
|
|
|
9979
10274
|
runOwners.delete(latestRunId);
|
|
9980
10275
|
runConversations.delete(latestRunId);
|
|
9981
10276
|
}
|
|
9982
|
-
console.log("[messaging-runner] run complete, response length:", assistantResponse.length, runContinuation2 ? "(continuation)" : "");
|
|
9983
|
-
const response = assistantResponse;
|
|
10277
|
+
console.log("[messaging-runner] run complete, response length:", draft.assistantResponse.length, runContinuation2 ? "(continuation)" : "");
|
|
10278
|
+
const response = draft.assistantResponse;
|
|
9984
10279
|
return {
|
|
9985
10280
|
response,
|
|
9986
10281
|
continuation: runContinuation2,
|
|
@@ -10113,6 +10408,7 @@ ${resultBody}`,
|
|
|
10113
10408
|
async function* runContinuation(conversationId) {
|
|
10114
10409
|
const conversation = await conversationStore.get(conversationId);
|
|
10115
10410
|
if (!conversation) return;
|
|
10411
|
+
if (Array.isArray(conversation.pendingApprovals) && conversation.pendingApprovals.length > 0) return;
|
|
10116
10412
|
if (!conversation._continuationMessages?.length) return;
|
|
10117
10413
|
if (conversation.runStatus === "running") return;
|
|
10118
10414
|
const count = (conversation._continuationCount ?? 0) + 1;
|
|
@@ -10261,7 +10557,11 @@ ${resultBody}`,
|
|
|
10261
10557
|
freshConv._continuationMessages = void 0;
|
|
10262
10558
|
freshConv._continuationCount = void 0;
|
|
10263
10559
|
}
|
|
10264
|
-
if (nextHarnessMessages)
|
|
10560
|
+
if (nextHarnessMessages) {
|
|
10561
|
+
freshConv._harnessMessages = nextHarnessMessages;
|
|
10562
|
+
} else {
|
|
10563
|
+
freshConv._harnessMessages = freshConv.messages;
|
|
10564
|
+
}
|
|
10265
10565
|
freshConv._toolResultArchive = harness.getToolResultArchive(conversationId);
|
|
10266
10566
|
freshConv.runtimeRunId = latestRunId || freshConv.runtimeRunId;
|
|
10267
10567
|
freshConv.pendingApprovals = [];
|
|
@@ -10383,6 +10683,8 @@ ${resultBody}`,
|
|
|
10383
10683
|
}
|
|
10384
10684
|
if (runResult?.continuationMessages) {
|
|
10385
10685
|
conv._harnessMessages = runResult.continuationMessages;
|
|
10686
|
+
} else {
|
|
10687
|
+
conv._harnessMessages = conv.messages;
|
|
10386
10688
|
}
|
|
10387
10689
|
conv._toolResultArchive = childHarness.getToolResultArchive(conversationId);
|
|
10388
10690
|
conv.lastActivityAt = Date.now();
|
|
@@ -10575,29 +10877,23 @@ ${resultBody}`,
|
|
|
10575
10877
|
}
|
|
10576
10878
|
return;
|
|
10577
10879
|
}
|
|
10578
|
-
const
|
|
10579
|
-
let foundConversation;
|
|
10580
|
-
let foundApproval;
|
|
10581
|
-
for (const conv of conversations) {
|
|
10582
|
-
if (!Array.isArray(conv.pendingApprovals)) continue;
|
|
10583
|
-
const match = conv.pendingApprovals.find((a) => a.approvalId === approvalId);
|
|
10584
|
-
if (match) {
|
|
10585
|
-
foundConversation = conv;
|
|
10586
|
-
foundApproval = match;
|
|
10587
|
-
break;
|
|
10588
|
-
}
|
|
10589
|
-
}
|
|
10880
|
+
const found = await findPendingApproval(approvalId, "local-owner");
|
|
10881
|
+
let foundConversation = found?.conversation;
|
|
10882
|
+
let foundApproval = found?.approval;
|
|
10590
10883
|
if (!foundConversation || !foundApproval) {
|
|
10591
10884
|
console.warn("[telegram-approval] approval not found:", approvalId);
|
|
10592
10885
|
return;
|
|
10593
10886
|
}
|
|
10887
|
+
foundApproval = normalizeApprovalCheckpoint(foundApproval, foundConversation.messages);
|
|
10594
10888
|
await adapter.updateApprovalMessage(approvalId, approved ? "approved" : "denied", foundApproval.tool);
|
|
10595
10889
|
foundApproval.decision = approved ? "approved" : "denied";
|
|
10596
10890
|
broadcastEvent(
|
|
10597
10891
|
foundConversation.conversationId,
|
|
10598
10892
|
approved ? { type: "tool:approval:granted", approvalId } : { type: "tool:approval:denied", approvalId }
|
|
10599
10893
|
);
|
|
10600
|
-
const allApprovals = foundConversation.pendingApprovals ?? []
|
|
10894
|
+
const allApprovals = (foundConversation.pendingApprovals ?? []).map(
|
|
10895
|
+
(approval) => normalizeApprovalCheckpoint(approval, foundConversation.messages)
|
|
10896
|
+
);
|
|
10601
10897
|
const allDecided = allApprovals.length > 0 && allApprovals.every((a) => a.decision != null);
|
|
10602
10898
|
if (!allDecided) {
|
|
10603
10899
|
await conversationStore.update(foundConversation);
|
|
@@ -10946,6 +11242,9 @@ ${resultBody}`,
|
|
|
10946
11242
|
return;
|
|
10947
11243
|
}
|
|
10948
11244
|
if (requireAuth && session && !hasBearerToken && requiresCsrfValidation && pathname !== "/api/auth/login" && request.headers["x-csrf-token"] !== session?.csrfToken) {
|
|
11245
|
+
console.warn(
|
|
11246
|
+
`[poncho][csrf] blocked request method=${request.method} path="${pathname}" session=${session.sessionId}`
|
|
11247
|
+
);
|
|
10949
11248
|
writeJson(response, 403, {
|
|
10950
11249
|
code: "CSRF_ERROR",
|
|
10951
11250
|
message: "Invalid CSRF token"
|
|
@@ -11141,6 +11440,7 @@ data: ${JSON.stringify(frame)}
|
|
|
11141
11440
|
const approvalId = decodeURIComponent(approvalMatch[1] ?? "");
|
|
11142
11441
|
const body = await readRequestBody(request);
|
|
11143
11442
|
const approved = body.approved === true;
|
|
11443
|
+
const hintedConversationId = typeof body.conversationId === "string" && body.conversationId.trim().length > 0 ? body.conversationId.trim() : void 0;
|
|
11144
11444
|
const pendingSubagent = pendingSubagentApprovals.get(approvalId);
|
|
11145
11445
|
if (pendingSubagent) {
|
|
11146
11446
|
pendingSubagent.checkpoint.decision = approved ? "approved" : "denied";
|
|
@@ -11166,18 +11466,23 @@ data: ${JSON.stringify(frame)}
|
|
|
11166
11466
|
writeJson(response, 200, { ok: true, approvalId, approved });
|
|
11167
11467
|
return;
|
|
11168
11468
|
}
|
|
11169
|
-
const conversations = await conversationStore.list(ownerId);
|
|
11170
11469
|
let foundConversation;
|
|
11171
11470
|
let foundApproval;
|
|
11172
|
-
|
|
11173
|
-
|
|
11174
|
-
|
|
11175
|
-
|
|
11176
|
-
|
|
11177
|
-
|
|
11178
|
-
|
|
11471
|
+
if (hintedConversationId) {
|
|
11472
|
+
const hintedConversation = await conversationStore.get(hintedConversationId);
|
|
11473
|
+
if (hintedConversation && hintedConversation.ownerId === ownerId && Array.isArray(hintedConversation.pendingApprovals)) {
|
|
11474
|
+
const hintedMatch = hintedConversation.pendingApprovals.find((approval) => approval.approvalId === approvalId);
|
|
11475
|
+
if (hintedMatch) {
|
|
11476
|
+
foundConversation = hintedConversation;
|
|
11477
|
+
foundApproval = hintedMatch;
|
|
11478
|
+
}
|
|
11179
11479
|
}
|
|
11180
11480
|
}
|
|
11481
|
+
if (!foundConversation || !foundApproval) {
|
|
11482
|
+
const found = await findPendingApproval(approvalId, ownerId);
|
|
11483
|
+
foundConversation = found?.conversation;
|
|
11484
|
+
foundApproval = found?.approval;
|
|
11485
|
+
}
|
|
11181
11486
|
if (!foundConversation || !foundApproval) {
|
|
11182
11487
|
writeJson(response, 404, {
|
|
11183
11488
|
code: "APPROVAL_NOT_FOUND",
|
|
@@ -11186,37 +11491,32 @@ data: ${JSON.stringify(frame)}
|
|
|
11186
11491
|
return;
|
|
11187
11492
|
}
|
|
11188
11493
|
const conversationId = foundConversation.conversationId;
|
|
11494
|
+
foundApproval = normalizeApprovalCheckpoint(foundApproval, foundConversation.messages);
|
|
11189
11495
|
if (!foundApproval.checkpointMessages || !foundApproval.toolCallId) {
|
|
11190
|
-
|
|
11191
|
-
|
|
11192
|
-
|
|
11193
|
-
code: "APPROVAL_NOT_FOUND",
|
|
11194
|
-
message: "Approval request is no longer active (no checkpoint data)"
|
|
11496
|
+
writeJson(response, 409, {
|
|
11497
|
+
code: "APPROVAL_NOT_READY",
|
|
11498
|
+
message: "Approval checkpoint is not ready yet. Please retry shortly."
|
|
11195
11499
|
});
|
|
11196
11500
|
return;
|
|
11197
11501
|
}
|
|
11198
|
-
|
|
11199
|
-
|
|
11200
|
-
|
|
11201
|
-
|
|
11202
|
-
|
|
11203
|
-
batchDecisions.set(approvalId, approved);
|
|
11204
|
-
foundApproval.decision = approved ? "approved" : "denied";
|
|
11502
|
+
const approvalDecision = approved ? "approved" : "denied";
|
|
11503
|
+
foundConversation.pendingApprovals = (foundConversation.pendingApprovals ?? []).map(
|
|
11504
|
+
(approval) => approval.approvalId === approvalId ? { ...normalizeApprovalCheckpoint(approval, foundConversation.messages), decision: approvalDecision } : normalizeApprovalCheckpoint(approval, foundConversation.messages)
|
|
11505
|
+
);
|
|
11506
|
+
await conversationStore.update(foundConversation);
|
|
11205
11507
|
broadcastEvent(
|
|
11206
11508
|
conversationId,
|
|
11207
11509
|
approved ? { type: "tool:approval:granted", approvalId } : { type: "tool:approval:denied", approvalId }
|
|
11208
11510
|
);
|
|
11209
|
-
const
|
|
11210
|
-
const
|
|
11511
|
+
const refreshedConversation = await conversationStore.get(conversationId);
|
|
11512
|
+
const allApprovals = (refreshedConversation?.pendingApprovals ?? []).map(
|
|
11513
|
+
(approval) => normalizeApprovalCheckpoint(approval, refreshedConversation.messages)
|
|
11514
|
+
);
|
|
11515
|
+
const allDecided = allApprovals.length > 0 && allApprovals.every((a) => a.decision != null);
|
|
11211
11516
|
if (!allDecided) {
|
|
11212
|
-
await conversationStore.update(foundConversation);
|
|
11213
11517
|
writeJson(response, 200, { ok: true, approvalId, approved, batchComplete: false });
|
|
11214
11518
|
return;
|
|
11215
11519
|
}
|
|
11216
|
-
for (const a of allApprovals) {
|
|
11217
|
-
const d = batchDecisions.get(a.approvalId);
|
|
11218
|
-
if (d != null) a.decision = d ? "approved" : "denied";
|
|
11219
|
-
}
|
|
11220
11520
|
approvalDecisionTracker.delete(conversationId);
|
|
11221
11521
|
foundConversation.pendingApprovals = [];
|
|
11222
11522
|
foundConversation.runStatus = "running";
|
|
@@ -11421,7 +11721,8 @@ data: ${JSON.stringify(frame)}
|
|
|
11421
11721
|
approvalId: a.approvalId,
|
|
11422
11722
|
runId: a.runId,
|
|
11423
11723
|
tool: a.tool,
|
|
11424
|
-
input: a.input
|
|
11724
|
+
input: a.input,
|
|
11725
|
+
decision: a.decision
|
|
11425
11726
|
})) : [];
|
|
11426
11727
|
const subagentPending = [];
|
|
11427
11728
|
if (!conversation.parentConversationId) {
|
|
@@ -11438,25 +11739,14 @@ data: ${JSON.stringify(frame)}
|
|
|
11438
11739
|
}
|
|
11439
11740
|
const activeStream = conversationEventStreams.get(conversationId);
|
|
11440
11741
|
const hasActiveRun = !!activeStream && !activeStream.finished || conversation.runStatus === "running";
|
|
11441
|
-
|
|
11442
|
-
(r) => r.parentConversationId === conversationId
|
|
11443
|
-
);
|
|
11444
|
-
if (!hasRunningSubagents && !conversation.parentConversationId) {
|
|
11445
|
-
const summaries = await conversationStore.listSummaries(conversation.ownerId);
|
|
11446
|
-
for (const s of summaries) {
|
|
11447
|
-
if (s.parentConversationId !== conversationId) continue;
|
|
11448
|
-
const c = await conversationStore.get(s.conversationId);
|
|
11449
|
-
if (c?.subagentMeta?.status === "running") {
|
|
11450
|
-
hasRunningSubagents = true;
|
|
11451
|
-
break;
|
|
11452
|
-
}
|
|
11453
|
-
}
|
|
11454
|
-
}
|
|
11742
|
+
const hasRunningSubagents = !conversation.parentConversationId ? await hasRunningSubagentsForParent(conversationId, conversation.ownerId) : false;
|
|
11455
11743
|
const hasPendingCallbackResults = Array.isArray(conversation.pendingSubagentResults) && conversation.pendingSubagentResults.length > 0;
|
|
11456
|
-
const
|
|
11744
|
+
const hasPendingApprovals = Array.isArray(conversation.pendingApprovals) && conversation.pendingApprovals.length > 0;
|
|
11745
|
+
const needsContinuation = !hasActiveRun && Array.isArray(conversation._continuationMessages) && conversation._continuationMessages.length > 0 && !hasPendingApprovals;
|
|
11457
11746
|
writeJson(response, 200, {
|
|
11458
11747
|
conversation: {
|
|
11459
11748
|
...conversation,
|
|
11749
|
+
messages: conversation.messages.map(normalizeMessageForClient),
|
|
11460
11750
|
pendingApprovals: storedPending,
|
|
11461
11751
|
_continuationMessages: void 0,
|
|
11462
11752
|
_harnessMessages: void 0
|
|
@@ -11666,11 +11956,9 @@ data: ${JSON.stringify(frame)}
|
|
|
11666
11956
|
eventCount++;
|
|
11667
11957
|
let sseEvent = event;
|
|
11668
11958
|
if (sseEvent.type === "run:completed") {
|
|
11669
|
-
const
|
|
11670
|
-
(r) => r.parentConversationId === conversationId
|
|
11671
|
-
);
|
|
11959
|
+
const hasPendingSubagents = await hasPendingSubagentWorkForParent(conversationId, ownerId);
|
|
11672
11960
|
const stripped = { ...sseEvent, result: { ...sseEvent.result, continuationMessages: void 0 } };
|
|
11673
|
-
sseEvent =
|
|
11961
|
+
sseEvent = hasPendingSubagents ? { ...stripped, pendingSubagents: true } : stripped;
|
|
11674
11962
|
}
|
|
11675
11963
|
try {
|
|
11676
11964
|
response.write(formatSseEvent(sseEvent));
|
|
@@ -11698,7 +11986,7 @@ data: ${JSON.stringify(frame)}
|
|
|
11698
11986
|
}
|
|
11699
11987
|
} else {
|
|
11700
11988
|
const freshConv = await conversationStore.get(conversationId);
|
|
11701
|
-
if (freshConv?._continuationMessages?.length) {
|
|
11989
|
+
if (freshConv?._continuationMessages?.length && (!Array.isArray(freshConv.pendingApprovals) || freshConv.pendingApprovals.length === 0)) {
|
|
11702
11990
|
doWaitUntil(
|
|
11703
11991
|
new Promise((r) => setTimeout(r, 3e3)).then(
|
|
11704
11992
|
() => selfFetchWithRetry(`/api/internal/continue/${encodeURIComponent(conversationId)}`)
|
|
@@ -11780,9 +12068,17 @@ data: ${JSON.stringify(frame)}
|
|
|
11780
12068
|
Connection: "keep-alive",
|
|
11781
12069
|
"X-Accel-Buffering": "no"
|
|
11782
12070
|
});
|
|
11783
|
-
const
|
|
12071
|
+
const canonicalHistory = resolveRunRequest(conversation, {
|
|
12072
|
+
conversationId,
|
|
12073
|
+
messages: conversation.messages
|
|
12074
|
+
});
|
|
12075
|
+
const shouldRebuildCanonical = canonicalHistory.shouldRebuildCanonical;
|
|
12076
|
+
const harnessMessages = [...canonicalHistory.messages];
|
|
11784
12077
|
const historyMessages = [...conversation.messages];
|
|
11785
12078
|
const preRunMessages = [...conversation.messages];
|
|
12079
|
+
console.info(
|
|
12080
|
+
`[poncho] conversation="${conversationId}" history_source=${canonicalHistory.source}`
|
|
12081
|
+
);
|
|
11786
12082
|
let latestRunId = conversation.runtimeRunId ?? "";
|
|
11787
12083
|
let assistantResponse = "";
|
|
11788
12084
|
const toolTimeline = [];
|
|
@@ -11977,6 +12273,24 @@ data: ${JSON.stringify(frame)}
|
|
|
11977
12273
|
const toolText = `- approval required \`${event.tool}\``;
|
|
11978
12274
|
toolTimeline.push(toolText);
|
|
11979
12275
|
currentTools.push(toolText);
|
|
12276
|
+
const existingApprovals = Array.isArray(conversation.pendingApprovals) ? conversation.pendingApprovals : [];
|
|
12277
|
+
if (!existingApprovals.some((approval) => approval.approvalId === event.approvalId)) {
|
|
12278
|
+
conversation.pendingApprovals = [
|
|
12279
|
+
...existingApprovals,
|
|
12280
|
+
{
|
|
12281
|
+
approvalId: event.approvalId,
|
|
12282
|
+
runId: latestRunId || conversation.runtimeRunId || "",
|
|
12283
|
+
tool: event.tool,
|
|
12284
|
+
toolCallId: void 0,
|
|
12285
|
+
input: event.input ?? {},
|
|
12286
|
+
checkpointMessages: void 0,
|
|
12287
|
+
baseMessageCount: historyMessages.length,
|
|
12288
|
+
pendingToolCalls: []
|
|
12289
|
+
}
|
|
12290
|
+
];
|
|
12291
|
+
conversation.updatedAt = Date.now();
|
|
12292
|
+
await conversationStore.update(conversation);
|
|
12293
|
+
}
|
|
11980
12294
|
await persistDraftAssistantTurn();
|
|
11981
12295
|
}
|
|
11982
12296
|
if (event.type === "tool:approval:checkpoint") {
|
|
@@ -11996,16 +12310,13 @@ data: ${JSON.stringify(frame)}
|
|
|
11996
12310
|
metadata: toolTimeline.length > 0 || checkpointSections.length > 0 ? { toolActivity: [...toolTimeline], sections: checkpointSections.length > 0 ? checkpointSections : void 0 } : void 0
|
|
11997
12311
|
}] : []
|
|
11998
12312
|
];
|
|
11999
|
-
conversation.pendingApprovals =
|
|
12000
|
-
|
|
12313
|
+
conversation.pendingApprovals = buildApprovalCheckpoints({
|
|
12314
|
+
approvals: event.approvals,
|
|
12001
12315
|
runId: latestRunId,
|
|
12002
|
-
tool: a.tool,
|
|
12003
|
-
toolCallId: a.toolCallId,
|
|
12004
|
-
input: a.input,
|
|
12005
12316
|
checkpointMessages: event.checkpointMessages,
|
|
12006
12317
|
baseMessageCount: historyMessages.length,
|
|
12007
12318
|
pendingToolCalls: event.pendingToolCalls
|
|
12008
|
-
})
|
|
12319
|
+
});
|
|
12009
12320
|
conversation._toolResultArchive = harness.getToolResultArchive(conversationId);
|
|
12010
12321
|
conversation.updatedAt = Date.now();
|
|
12011
12322
|
await conversationStore.update(conversation);
|
|
@@ -12036,26 +12347,28 @@ data: ${JSON.stringify(frame)}
|
|
|
12036
12347
|
conversation._harnessMessages = runContinuationMessages;
|
|
12037
12348
|
conversation._toolResultArchive = harness.getToolResultArchive(conversationId);
|
|
12038
12349
|
conversation.runtimeRunId = latestRunId || conversation.runtimeRunId;
|
|
12039
|
-
|
|
12350
|
+
if (!checkpointedRun) {
|
|
12351
|
+
conversation.pendingApprovals = [];
|
|
12352
|
+
}
|
|
12040
12353
|
if (runContextTokens > 0) conversation.contextTokens = runContextTokens;
|
|
12041
12354
|
if (runContextWindow > 0) conversation.contextWindow = runContextWindow;
|
|
12042
12355
|
conversation.updatedAt = Date.now();
|
|
12043
12356
|
await conversationStore.update(conversation);
|
|
12044
|
-
|
|
12045
|
-
|
|
12046
|
-
() =>
|
|
12047
|
-
|
|
12048
|
-
|
|
12357
|
+
if (!checkpointedRun) {
|
|
12358
|
+
doWaitUntil(
|
|
12359
|
+
new Promise((r) => setTimeout(r, 3e3)).then(
|
|
12360
|
+
() => selfFetchWithRetry(`/api/internal/continue/${encodeURIComponent(conversationId)}`)
|
|
12361
|
+
)
|
|
12362
|
+
);
|
|
12363
|
+
}
|
|
12049
12364
|
}
|
|
12050
12365
|
}
|
|
12051
12366
|
await telemetry.emit(event);
|
|
12052
12367
|
let sseEvent = event.type === "compaction:completed" && event.compactedMessages ? { ...event, compactedMessages: void 0 } : event;
|
|
12053
12368
|
if (sseEvent.type === "run:completed") {
|
|
12054
|
-
const
|
|
12055
|
-
(r) => r.parentConversationId === conversationId
|
|
12056
|
-
);
|
|
12369
|
+
const hasPendingSubagents = await hasPendingSubagentWorkForParent(conversationId, ownerId);
|
|
12057
12370
|
const stripped = { ...sseEvent, result: { ...sseEvent.result, continuationMessages: void 0 } };
|
|
12058
|
-
if (
|
|
12371
|
+
if (hasPendingSubagents) {
|
|
12059
12372
|
sseEvent = { ...stripped, pendingSubagents: true };
|
|
12060
12373
|
} else {
|
|
12061
12374
|
sseEvent = stripped;
|
|
@@ -12092,6 +12405,10 @@ data: ${JSON.stringify(frame)}
|
|
|
12092
12405
|
conversation._continuationMessages = void 0;
|
|
12093
12406
|
if (runHarnessMessages) {
|
|
12094
12407
|
conversation._harnessMessages = runHarnessMessages;
|
|
12408
|
+
} else if (shouldRebuildCanonical) {
|
|
12409
|
+
conversation._harnessMessages = conversation.messages;
|
|
12410
|
+
} else {
|
|
12411
|
+
conversation._harnessMessages = conversation.messages;
|
|
12095
12412
|
}
|
|
12096
12413
|
conversation._toolResultArchive = harness.getToolResultArchive(conversationId);
|
|
12097
12414
|
conversation.runtimeRunId = latestRunId || conversation.runtimeRunId;
|
|
@@ -12126,7 +12443,9 @@ data: ${JSON.stringify(frame)}
|
|
|
12126
12443
|
conversation.updatedAt = Date.now();
|
|
12127
12444
|
await conversationStore.update(conversation);
|
|
12128
12445
|
}
|
|
12129
|
-
|
|
12446
|
+
if (!checkpointedRun) {
|
|
12447
|
+
await clearPendingApprovalsForConversation(conversationId);
|
|
12448
|
+
}
|
|
12130
12449
|
return;
|
|
12131
12450
|
}
|
|
12132
12451
|
try {
|
|
@@ -12171,18 +12490,24 @@ data: ${JSON.stringify(frame)}
|
|
|
12171
12490
|
if (active && active.abortController === abortController) {
|
|
12172
12491
|
activeConversationRuns.delete(conversationId);
|
|
12173
12492
|
}
|
|
12174
|
-
finishConversationStream(conversationId);
|
|
12175
12493
|
if (latestRunId) {
|
|
12176
12494
|
runOwners.delete(latestRunId);
|
|
12177
12495
|
runConversations.delete(latestRunId);
|
|
12178
12496
|
}
|
|
12497
|
+
const hadDeferred = pendingCallbackNeeded.delete(conversationId);
|
|
12498
|
+
const freshConv = await conversationStore.get(conversationId);
|
|
12499
|
+
const needsCallback = hadDeferred || !!freshConv?.pendingSubagentResults?.length;
|
|
12500
|
+
const hasRunningChildren = Array.from(activeSubagentRuns.values()).some(
|
|
12501
|
+
(run) => run.parentConversationId === conversationId
|
|
12502
|
+
);
|
|
12503
|
+
if (!needsCallback && !hasRunningChildren) {
|
|
12504
|
+
finishConversationStream(conversationId);
|
|
12505
|
+
}
|
|
12179
12506
|
try {
|
|
12180
12507
|
response.end();
|
|
12181
12508
|
} catch {
|
|
12182
12509
|
}
|
|
12183
|
-
|
|
12184
|
-
const freshConv = await conversationStore.get(conversationId);
|
|
12185
|
-
if (hadDeferred || freshConv?.pendingSubagentResults?.length) {
|
|
12510
|
+
if (needsCallback) {
|
|
12186
12511
|
processSubagentCallback(conversationId, true).catch(
|
|
12187
12512
|
(err) => console.error(`[poncho][subagent-callback] Post-run callback failed:`, err instanceof Error ? err.message : err)
|
|
12188
12513
|
);
|
|
@@ -12239,43 +12564,41 @@ data: ${JSON.stringify(frame)}
|
|
|
12239
12564
|
if (!conv) continue;
|
|
12240
12565
|
const task = `[Scheduled: ${jobName}]
|
|
12241
12566
|
${cronJob.task}`;
|
|
12242
|
-
const
|
|
12567
|
+
const historySelection = resolveRunRequest(conv, {
|
|
12568
|
+
conversationId: conv.conversationId,
|
|
12569
|
+
messages: conv.messages
|
|
12570
|
+
});
|
|
12571
|
+
const historyMessages = [...historySelection.messages];
|
|
12243
12572
|
try {
|
|
12244
|
-
|
|
12245
|
-
|
|
12246
|
-
|
|
12247
|
-
|
|
12248
|
-
|
|
12249
|
-
|
|
12250
|
-
|
|
12251
|
-
|
|
12252
|
-
|
|
12253
|
-
|
|
12254
|
-
|
|
12255
|
-
|
|
12256
|
-
|
|
12257
|
-
assistantResponse += event.content;
|
|
12258
|
-
}
|
|
12259
|
-
if (event.type === "run:completed") {
|
|
12260
|
-
steps = event.result.steps;
|
|
12261
|
-
if (!assistantResponse && event.result.response) {
|
|
12262
|
-
assistantResponse = event.result.response;
|
|
12263
|
-
}
|
|
12264
|
-
if (event.result.continuationMessages) {
|
|
12265
|
-
cronHarnessMessages = event.result.continuationMessages;
|
|
12266
|
-
}
|
|
12573
|
+
const execution = await executeConversationTurn({
|
|
12574
|
+
harness,
|
|
12575
|
+
runInput: {
|
|
12576
|
+
task,
|
|
12577
|
+
conversationId: conv.conversationId,
|
|
12578
|
+
parameters: withToolResultArchiveParam(
|
|
12579
|
+
{ __activeConversationId: conv.conversationId },
|
|
12580
|
+
conv
|
|
12581
|
+
),
|
|
12582
|
+
messages: historyMessages
|
|
12583
|
+
},
|
|
12584
|
+
onEvent: async (event) => {
|
|
12585
|
+
await telemetry.emit(event);
|
|
12267
12586
|
}
|
|
12268
|
-
|
|
12269
|
-
|
|
12587
|
+
});
|
|
12588
|
+
const assistantResponse = execution.draft.assistantResponse;
|
|
12270
12589
|
conv.messages = [
|
|
12271
12590
|
...historyMessages,
|
|
12272
12591
|
{ role: "user", content: task },
|
|
12273
12592
|
...assistantResponse ? [{ role: "assistant", content: assistantResponse }] : []
|
|
12274
12593
|
];
|
|
12275
|
-
if (
|
|
12276
|
-
conv._harnessMessages =
|
|
12594
|
+
if (execution.runHarnessMessages) {
|
|
12595
|
+
conv._harnessMessages = execution.runHarnessMessages;
|
|
12596
|
+
} else if (historySelection.shouldRebuildCanonical) {
|
|
12597
|
+
conv._harnessMessages = conv.messages;
|
|
12277
12598
|
}
|
|
12278
12599
|
conv._toolResultArchive = harness.getToolResultArchive(conv.conversationId);
|
|
12600
|
+
if (execution.runContextTokens > 0) conv.contextTokens = execution.runContextTokens;
|
|
12601
|
+
if (execution.runContextWindow > 0) conv.contextWindow = execution.runContextWindow;
|
|
12279
12602
|
conv.updatedAt = Date.now();
|
|
12280
12603
|
await conversationStore.update(conv);
|
|
12281
12604
|
if (assistantResponse) {
|
|
@@ -12291,7 +12614,7 @@ ${cronJob.task}`;
|
|
|
12291
12614
|
console.error(`[cron] ${jobName}: send to ${chatId} failed:`, sendError instanceof Error ? sendError.message : sendError);
|
|
12292
12615
|
}
|
|
12293
12616
|
}
|
|
12294
|
-
chatResults.push({ chatId, status: "completed", steps });
|
|
12617
|
+
chatResults.push({ chatId, status: "completed", steps: execution.runSteps });
|
|
12295
12618
|
} catch (runError) {
|
|
12296
12619
|
chatResults.push({ chatId, status: "error" });
|
|
12297
12620
|
console.error(`[cron] ${jobName}: run for chat ${chatId} failed:`, runError instanceof Error ? runError.message : runError);
|
|
@@ -12540,86 +12863,30 @@ var startDevServer = async (port, options) => {
|
|
|
12540
12863
|
const { Cron } = await import("croner");
|
|
12541
12864
|
let activeJobs = [];
|
|
12542
12865
|
const runCronAgent = async (harnessRef, task, conversationId, historyMessages, toolResultArchive, onEvent) => {
|
|
12543
|
-
|
|
12544
|
-
|
|
12545
|
-
|
|
12546
|
-
|
|
12547
|
-
|
|
12548
|
-
|
|
12549
|
-
|
|
12550
|
-
|
|
12551
|
-
|
|
12552
|
-
|
|
12553
|
-
task,
|
|
12554
|
-
conversationId,
|
|
12555
|
-
parameters: {
|
|
12556
|
-
__activeConversationId: conversationId,
|
|
12557
|
-
[TOOL_RESULT_ARCHIVE_PARAM]: toolResultArchive ?? {}
|
|
12866
|
+
const execution = await executeConversationTurn({
|
|
12867
|
+
harness: harnessRef,
|
|
12868
|
+
runInput: {
|
|
12869
|
+
task,
|
|
12870
|
+
conversationId,
|
|
12871
|
+
parameters: {
|
|
12872
|
+
__activeConversationId: conversationId,
|
|
12873
|
+
[TOOL_RESULT_ARCHIVE_PARAM]: toolResultArchive ?? {}
|
|
12874
|
+
},
|
|
12875
|
+
messages: historyMessages
|
|
12558
12876
|
},
|
|
12559
|
-
|
|
12560
|
-
})
|
|
12561
|
-
|
|
12562
|
-
|
|
12563
|
-
|
|
12564
|
-
sections.push({ type: "tools", content: currentTools });
|
|
12565
|
-
currentTools = [];
|
|
12566
|
-
if (assistantResponse.length > 0 && !/\s$/.test(assistantResponse)) {
|
|
12567
|
-
assistantResponse += " ";
|
|
12568
|
-
}
|
|
12569
|
-
}
|
|
12570
|
-
assistantResponse += event.content;
|
|
12571
|
-
currentText += event.content;
|
|
12572
|
-
}
|
|
12573
|
-
if (event.type === "tool:started") {
|
|
12574
|
-
if (currentText.length > 0) {
|
|
12575
|
-
sections.push({ type: "text", content: currentText });
|
|
12576
|
-
currentText = "";
|
|
12577
|
-
}
|
|
12578
|
-
const toolText = `- start \`${event.tool}\``;
|
|
12579
|
-
toolTimeline.push(toolText);
|
|
12580
|
-
currentTools.push(toolText);
|
|
12581
|
-
}
|
|
12582
|
-
if (event.type === "tool:completed") {
|
|
12583
|
-
const toolText = `- done \`${event.tool}\` (${event.duration}ms)`;
|
|
12584
|
-
toolTimeline.push(toolText);
|
|
12585
|
-
currentTools.push(toolText);
|
|
12586
|
-
}
|
|
12587
|
-
if (event.type === "tool:error") {
|
|
12588
|
-
const toolText = `- error \`${event.tool}\`: ${event.error}`;
|
|
12589
|
-
toolTimeline.push(toolText);
|
|
12590
|
-
currentTools.push(toolText);
|
|
12591
|
-
}
|
|
12592
|
-
if (event.type === "run:completed") {
|
|
12593
|
-
steps = event.result.steps;
|
|
12594
|
-
contextTokens = event.result.contextTokens ?? 0;
|
|
12595
|
-
contextWindow = event.result.contextWindow ?? 0;
|
|
12596
|
-
if (event.result.continuationMessages) {
|
|
12597
|
-
harnessMessages = event.result.continuationMessages;
|
|
12598
|
-
}
|
|
12599
|
-
if (!assistantResponse && event.result.response) {
|
|
12600
|
-
assistantResponse = event.result.response;
|
|
12601
|
-
}
|
|
12602
|
-
}
|
|
12603
|
-
}
|
|
12604
|
-
if (currentTools.length > 0) {
|
|
12605
|
-
sections.push({ type: "tools", content: currentTools });
|
|
12606
|
-
}
|
|
12607
|
-
if (currentText.length > 0) {
|
|
12608
|
-
sections.push({ type: "text", content: currentText });
|
|
12609
|
-
}
|
|
12610
|
-
const hasContent = assistantResponse.length > 0 || toolTimeline.length > 0;
|
|
12611
|
-
const assistantMetadata = toolTimeline.length > 0 || sections.length > 0 ? {
|
|
12612
|
-
toolActivity: [...toolTimeline],
|
|
12613
|
-
sections: sections.length > 0 ? sections : void 0
|
|
12614
|
-
} : void 0;
|
|
12877
|
+
onEvent
|
|
12878
|
+
});
|
|
12879
|
+
flushTurnDraft(execution.draft);
|
|
12880
|
+
const hasContent = execution.draft.assistantResponse.length > 0 || execution.draft.toolTimeline.length > 0;
|
|
12881
|
+
const assistantMetadata = buildAssistantMetadata(execution.draft);
|
|
12615
12882
|
return {
|
|
12616
|
-
response: assistantResponse,
|
|
12617
|
-
steps,
|
|
12883
|
+
response: execution.draft.assistantResponse,
|
|
12884
|
+
steps: execution.runSteps,
|
|
12618
12885
|
assistantMetadata,
|
|
12619
12886
|
hasContent,
|
|
12620
|
-
contextTokens,
|
|
12621
|
-
contextWindow,
|
|
12622
|
-
harnessMessages,
|
|
12887
|
+
contextTokens: execution.runContextTokens,
|
|
12888
|
+
contextWindow: execution.runContextWindow,
|
|
12889
|
+
harnessMessages: execution.runHarnessMessages,
|
|
12623
12890
|
toolResultArchive: harnessRef.getToolResultArchive(conversationId)
|
|
12624
12891
|
};
|
|
12625
12892
|
};
|
|
@@ -12680,7 +12947,11 @@ var startDevServer = async (port, options) => {
|
|
|
12680
12947
|
if (!conversation) continue;
|
|
12681
12948
|
const task = `[Scheduled: ${jobName}]
|
|
12682
12949
|
${config.task}`;
|
|
12683
|
-
const
|
|
12950
|
+
const historySelection = resolveRunRequest(conversation, {
|
|
12951
|
+
conversationId: conversation.conversationId,
|
|
12952
|
+
messages: conversation.messages
|
|
12953
|
+
});
|
|
12954
|
+
const historyMessages = [...historySelection.messages];
|
|
12684
12955
|
const convId = conversation.conversationId;
|
|
12685
12956
|
activeRuns?.set(convId, {
|
|
12686
12957
|
ownerId: "local-owner",
|
|
@@ -12703,6 +12974,8 @@ ${config.task}`;
|
|
|
12703
12974
|
freshConv.messages = buildCronMessages(task, historyMessages, result);
|
|
12704
12975
|
if (result.harnessMessages) {
|
|
12705
12976
|
freshConv._harnessMessages = result.harnessMessages;
|
|
12977
|
+
} else if (historySelection.shouldRebuildCanonical) {
|
|
12978
|
+
freshConv._harnessMessages = freshConv.messages;
|
|
12706
12979
|
}
|
|
12707
12980
|
if (result.toolResultArchive) {
|
|
12708
12981
|
freshConv._toolResultArchive = result.toolResultArchive;
|
|
@@ -12920,7 +13193,7 @@ var runInteractive = async (workingDir, params) => {
|
|
|
12920
13193
|
await harness.initialize();
|
|
12921
13194
|
const identity = await ensureAgentIdentity2(workingDir);
|
|
12922
13195
|
try {
|
|
12923
|
-
const { runInteractiveInk } = await import("./run-interactive-ink-
|
|
13196
|
+
const { runInteractiveInk } = await import("./run-interactive-ink-VGKSZJDO.js");
|
|
12924
13197
|
await runInteractiveInk({
|
|
12925
13198
|
harness,
|
|
12926
13199
|
params,
|
|
@@ -13654,6 +13927,7 @@ export {
|
|
|
13654
13927
|
inferConversationTitle,
|
|
13655
13928
|
consumeFirstRunIntro,
|
|
13656
13929
|
resolveHarnessEnvironment,
|
|
13930
|
+
__internalRunOrchestration,
|
|
13657
13931
|
initProject,
|
|
13658
13932
|
updateAgentGuidance,
|
|
13659
13933
|
createRequestHandler,
|