farai 0.1.6 → 0.1.7
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/dist/cli/index.js +468 -80
- package/dist/cli/index.js.map +16 -14
- package/docker/kali/farai-proxy-init.sh +2 -0
- package/docker/kali/farai-proxy-teardown.sh +1 -0
- package/package.json +2 -2
package/dist/cli/index.js
CHANGED
|
@@ -3635,7 +3635,7 @@ function proxyConfig(value) {
|
|
|
3635
3635
|
}
|
|
3636
3636
|
function resolveProxyConfig(config) {
|
|
3637
3637
|
return {
|
|
3638
|
-
transparent: config.proxy?.transparent
|
|
3638
|
+
transparent: config.proxy?.transparent !== false,
|
|
3639
3639
|
ports: config.proxy?.ports?.length ? config.proxy.ports : DEFAULT_TRANSPARENT_PROXY_PORTS
|
|
3640
3640
|
};
|
|
3641
3641
|
}
|
|
@@ -3960,7 +3960,7 @@ function atomicWriteFile(path, content, mode) {
|
|
|
3960
3960
|
var DEFAULT_TRANSPARENT_PROXY_PORTS, LSP_SERVER_IDS, DEFAULT_CONFIG_TEMPLATE = `model = "big-pickle"
|
|
3961
3961
|
|
|
3962
3962
|
[proxy]
|
|
3963
|
-
transparent =
|
|
3963
|
+
transparent = true
|
|
3964
3964
|
|
|
3965
3965
|
[mcp_servers.mitmproxy-mcp]
|
|
3966
3966
|
command = "mitmproxy-mcp"
|
|
@@ -24103,6 +24103,17 @@ var init_tool_call_journal = () => {};
|
|
|
24103
24103
|
import { createHash as createHash4 } from "crypto";
|
|
24104
24104
|
import { existsSync as existsSync12, mkdirSync as mkdirSync6, realpathSync as realpathSync3, writeFileSync as writeFileSync7 } from "fs";
|
|
24105
24105
|
import { isAbsolute as isAbsolute4, join as join16, relative as relative6 } from "path";
|
|
24106
|
+
function shouldBufferInitialTextStream(text) {
|
|
24107
|
+
if (isInternalMetaReasoning(text))
|
|
24108
|
+
return true;
|
|
24109
|
+
if (text.includes(`
|
|
24110
|
+
`))
|
|
24111
|
+
return false;
|
|
24112
|
+
const normalized = text.trimStart().toLowerCase().replace(/\s+/g, " ");
|
|
24113
|
+
if (!normalized)
|
|
24114
|
+
return false;
|
|
24115
|
+
return INTERNAL_META_STREAM_PREFIXES.some((prefix) => prefix.startsWith(normalized));
|
|
24116
|
+
}
|
|
24106
24117
|
|
|
24107
24118
|
class AgentRuntime {
|
|
24108
24119
|
turnControllers = new Map;
|
|
@@ -25037,7 +25048,7 @@ class AgentRuntime {
|
|
|
25037
25048
|
this.autoCompactFailures.delete(sessionId);
|
|
25038
25049
|
this.fileState.clear(sessionId);
|
|
25039
25050
|
for (const turn of this.store.listTurns(sessionId, 1000)) {
|
|
25040
|
-
this.
|
|
25051
|
+
this.deleteStreamingParts(turn.id);
|
|
25041
25052
|
}
|
|
25042
25053
|
return this.store.clearSessionChat(sessionId);
|
|
25043
25054
|
}
|
|
@@ -25752,7 +25763,7 @@ This completion is already terminal and was delivered automatically. Do not call
|
|
|
25752
25763
|
} else if (action.kind === "respond") {
|
|
25753
25764
|
sawResponse = true;
|
|
25754
25765
|
if (hasToolAction && isInternalMetaReasoning(action.text)) {
|
|
25755
|
-
this.discardStreamingText(turn.id);
|
|
25766
|
+
this.discardStreamingText(session.id, turn.id);
|
|
25756
25767
|
shouldContinue = true;
|
|
25757
25768
|
continue;
|
|
25758
25769
|
}
|
|
@@ -25789,7 +25800,7 @@ This completion is already terminal and was delivered automatically. Do not call
|
|
|
25789
25800
|
});
|
|
25790
25801
|
const request = buildChatRequest(plannerInput, requestController.signal);
|
|
25791
25802
|
let lastError = "";
|
|
25792
|
-
this.
|
|
25803
|
+
this.deleteStreamingParts(turn.id);
|
|
25793
25804
|
try {
|
|
25794
25805
|
for (let attempt = 1;; attempt += 1) {
|
|
25795
25806
|
this.emitPlannerAttempt(session, turn, assistantMessage, plannerName, attempt, plannerInput, context);
|
|
@@ -25928,7 +25939,7 @@ This completion is already terminal and was delivered automatically. Do not call
|
|
|
25928
25939
|
shouldContinue: shouldContinue2
|
|
25929
25940
|
};
|
|
25930
25941
|
}
|
|
25931
|
-
this.prepareStreamingRetry(turn.id);
|
|
25942
|
+
this.prepareStreamingRetry(session.id, turn.id);
|
|
25932
25943
|
const retry = plannerRetryState(error, attempt, dispatched.length === 0);
|
|
25933
25944
|
const errorPayload = {
|
|
25934
25945
|
turnId: turn.id,
|
|
@@ -25997,7 +26008,7 @@ This completion is already terminal and was delivered automatically. Do not call
|
|
|
25997
26008
|
const rawRespondText = content.trim();
|
|
25998
26009
|
const respondText = dispatched.length > 0 && isInternalMetaReasoning(rawRespondText) ? "" : rawRespondText;
|
|
25999
26010
|
if (!respondText && rawRespondText && dispatched.length > 0)
|
|
26000
|
-
this.discardStreamingText(turn.id);
|
|
26011
|
+
this.discardStreamingText(session.id, turn.id);
|
|
26001
26012
|
const outcomes = await Promise.all(dispatched);
|
|
26002
26013
|
const toolCancelled = outcomes.some((outcome) => outcome.cancelled);
|
|
26003
26014
|
for (const outcome of outcomes) {
|
|
@@ -26151,9 +26162,11 @@ This completion is already terminal and was delivered automatically. Do not call
|
|
|
26151
26162
|
rationale: ""
|
|
26152
26163
|
});
|
|
26153
26164
|
if (state) {
|
|
26165
|
+
state.reasoningAccum = "";
|
|
26166
|
+
this.publishStreamingReasoning(session.id, turn.id, state);
|
|
26154
26167
|
delete state.reasoningPartId;
|
|
26155
26168
|
delete state.reasoningAccum;
|
|
26156
|
-
delete state.
|
|
26169
|
+
delete state.lastReasoningPersist;
|
|
26157
26170
|
}
|
|
26158
26171
|
return;
|
|
26159
26172
|
}
|
|
@@ -26162,13 +26175,15 @@ This completion is already terminal and was delivered automatically. Do not call
|
|
|
26162
26175
|
rationale
|
|
26163
26176
|
});
|
|
26164
26177
|
if (state?.reasoningPartId) {
|
|
26178
|
+
state.reasoningAccum = rationale;
|
|
26179
|
+
this.publishStreamingReasoning(session.id, turn.id, state);
|
|
26165
26180
|
this.store.updatePartPayload(state.reasoningPartId, {
|
|
26166
26181
|
planner: plannerName,
|
|
26167
26182
|
rationale
|
|
26168
26183
|
});
|
|
26169
26184
|
delete state.reasoningPartId;
|
|
26170
26185
|
delete state.reasoningAccum;
|
|
26171
|
-
delete state.
|
|
26186
|
+
delete state.lastReasoningPersist;
|
|
26172
26187
|
} else {
|
|
26173
26188
|
this.store.addPart({
|
|
26174
26189
|
sessionId: session.id,
|
|
@@ -26186,6 +26201,8 @@ This completion is already terminal and was delivered automatically. Do not call
|
|
|
26186
26201
|
responses.push(text);
|
|
26187
26202
|
const streamed = this.streamingParts.get(turn.id);
|
|
26188
26203
|
if (streamed?.textPartId) {
|
|
26204
|
+
streamed.textAccum = text;
|
|
26205
|
+
this.publishStreamingText(session.id, turn.id, streamed);
|
|
26189
26206
|
this.store.updatePartPayload(streamed.textPartId, {
|
|
26190
26207
|
text
|
|
26191
26208
|
});
|
|
@@ -26669,6 +26686,40 @@ This completion is already terminal and was delivered automatically. Do not call
|
|
|
26669
26686
|
};
|
|
26670
26687
|
}
|
|
26671
26688
|
}
|
|
26689
|
+
deleteStreamingParts(turnId) {
|
|
26690
|
+
this.streamingParts.delete(turnId);
|
|
26691
|
+
}
|
|
26692
|
+
publishStreamingText(sessionId, turnId, state) {
|
|
26693
|
+
if (!state.textPartId)
|
|
26694
|
+
return;
|
|
26695
|
+
this.store.publishTransientEvent({
|
|
26696
|
+
id: id(),
|
|
26697
|
+
sessionId,
|
|
26698
|
+
type: "stream_text",
|
|
26699
|
+
payload: {
|
|
26700
|
+
turnId,
|
|
26701
|
+
partId: state.textPartId,
|
|
26702
|
+
text: state.textAccum
|
|
26703
|
+
},
|
|
26704
|
+
createdAt: nowIso()
|
|
26705
|
+
});
|
|
26706
|
+
}
|
|
26707
|
+
publishStreamingReasoning(sessionId, turnId, state) {
|
|
26708
|
+
if (!state.reasoningPartId)
|
|
26709
|
+
return;
|
|
26710
|
+
const rationale = normalizeReasoningSummary(state.reasoningAccum ?? "");
|
|
26711
|
+
this.store.publishTransientEvent({
|
|
26712
|
+
id: id(),
|
|
26713
|
+
sessionId,
|
|
26714
|
+
type: "stream_reasoning",
|
|
26715
|
+
payload: {
|
|
26716
|
+
turnId,
|
|
26717
|
+
partId: state.reasoningPartId,
|
|
26718
|
+
rationale
|
|
26719
|
+
},
|
|
26720
|
+
createdAt: nowIso()
|
|
26721
|
+
});
|
|
26722
|
+
}
|
|
26672
26723
|
applyStreamEvent(session, turn, assistantMessage, event) {
|
|
26673
26724
|
const now = Date.now();
|
|
26674
26725
|
const state = this.streamingParts.get(turn.id) ?? {
|
|
@@ -26693,26 +26744,39 @@ This completion is already terminal and was delivered automatically. Do not call
|
|
|
26693
26744
|
}
|
|
26694
26745
|
});
|
|
26695
26746
|
state.reasoningPartId = part.id;
|
|
26696
|
-
state.
|
|
26697
|
-
} else if (now - (state.
|
|
26747
|
+
state.lastReasoningPersist = now;
|
|
26748
|
+
} else if (now - (state.lastReasoningPersist ?? 0) >= STREAM_PERSIST_INTERVAL_MS) {
|
|
26698
26749
|
this.store.updatePartPayload(state.reasoningPartId, {
|
|
26699
26750
|
rationale
|
|
26700
26751
|
});
|
|
26701
|
-
state.
|
|
26752
|
+
state.lastReasoningPersist = now;
|
|
26702
26753
|
}
|
|
26754
|
+
this.publishStreamingReasoning(session.id, turn.id, state);
|
|
26703
26755
|
this.streamingParts.set(turn.id, state);
|
|
26704
26756
|
return;
|
|
26705
26757
|
}
|
|
26706
26758
|
state.textAccum += event.delta;
|
|
26707
26759
|
if (!state.textPartId) {
|
|
26708
|
-
if (
|
|
26760
|
+
if (shouldBufferInitialTextStream(state.textAccum)) {
|
|
26709
26761
|
this.streamingParts.set(turn.id, state);
|
|
26710
26762
|
return;
|
|
26711
26763
|
}
|
|
26712
|
-
if (state.
|
|
26713
|
-
|
|
26714
|
-
|
|
26715
|
-
|
|
26764
|
+
if (!state.reasoningPartId && state.reasoningAccum) {
|
|
26765
|
+
const rationale = normalizeReasoningSummary(state.reasoningAccum);
|
|
26766
|
+
if (rationale) {
|
|
26767
|
+
const reasoningPart = this.store.addPart({
|
|
26768
|
+
sessionId: session.id,
|
|
26769
|
+
turnId: turn.id,
|
|
26770
|
+
messageId: assistantMessage.id,
|
|
26771
|
+
type: "reasoning_summary",
|
|
26772
|
+
payload: {
|
|
26773
|
+
rationale
|
|
26774
|
+
}
|
|
26775
|
+
});
|
|
26776
|
+
state.reasoningPartId = reasoningPart.id;
|
|
26777
|
+
state.lastReasoningPersist = now;
|
|
26778
|
+
this.publishStreamingReasoning(session.id, turn.id, state);
|
|
26779
|
+
}
|
|
26716
26780
|
}
|
|
26717
26781
|
const part = this.store.addPart({
|
|
26718
26782
|
sessionId: session.id,
|
|
@@ -26724,30 +26788,17 @@ This completion is already terminal and was delivered automatically. Do not call
|
|
|
26724
26788
|
}
|
|
26725
26789
|
});
|
|
26726
26790
|
state.textPartId = part.id;
|
|
26727
|
-
state.lastTextRender = now;
|
|
26728
26791
|
state.lastTextPersist = now;
|
|
26729
26792
|
} else if (now - (state.lastTextPersist ?? 0) >= STREAM_PERSIST_INTERVAL_MS) {
|
|
26730
26793
|
this.store.updatePartPayload(state.textPartId, {
|
|
26731
26794
|
text: state.textAccum
|
|
26732
26795
|
});
|
|
26733
|
-
state.lastTextRender = now;
|
|
26734
26796
|
state.lastTextPersist = now;
|
|
26735
|
-
} else if (now - (state.lastTextRender ?? 0) >= STREAM_RENDER_INTERVAL_MS) {
|
|
26736
|
-
this.store.publishTransientEvent({
|
|
26737
|
-
id: id(),
|
|
26738
|
-
sessionId: session.id,
|
|
26739
|
-
type: "stream_text",
|
|
26740
|
-
payload: {
|
|
26741
|
-
partId: state.textPartId,
|
|
26742
|
-
text: state.textAccum
|
|
26743
|
-
},
|
|
26744
|
-
createdAt: nowIso()
|
|
26745
|
-
});
|
|
26746
|
-
state.lastTextRender = now;
|
|
26747
26797
|
}
|
|
26798
|
+
this.publishStreamingText(session.id, turn.id, state);
|
|
26748
26799
|
this.streamingParts.set(turn.id, state);
|
|
26749
26800
|
}
|
|
26750
|
-
discardStreamingText(turnId) {
|
|
26801
|
+
discardStreamingText(sessionId, turnId) {
|
|
26751
26802
|
const state = this.streamingParts.get(turnId);
|
|
26752
26803
|
if (!state)
|
|
26753
26804
|
return;
|
|
@@ -26756,11 +26807,11 @@ This completion is already terminal and was delivered automatically. Do not call
|
|
|
26756
26807
|
text: ""
|
|
26757
26808
|
});
|
|
26758
26809
|
state.textAccum = "";
|
|
26810
|
+
this.publishStreamingText(sessionId, turnId, state);
|
|
26759
26811
|
delete state.textPartId;
|
|
26760
|
-
delete state.lastTextRender;
|
|
26761
26812
|
delete state.lastTextPersist;
|
|
26762
26813
|
}
|
|
26763
|
-
prepareStreamingRetry(turnId) {
|
|
26814
|
+
prepareStreamingRetry(sessionId, turnId) {
|
|
26764
26815
|
const state = this.streamingParts.get(turnId);
|
|
26765
26816
|
if (!state)
|
|
26766
26817
|
return;
|
|
@@ -26773,11 +26824,13 @@ This completion is already terminal and was delivered automatically. Do not call
|
|
|
26773
26824
|
rationale: ""
|
|
26774
26825
|
});
|
|
26775
26826
|
state.textAccum = "";
|
|
26827
|
+
state.reasoningAccum = "";
|
|
26828
|
+
this.publishStreamingText(sessionId, turnId, state);
|
|
26829
|
+
this.publishStreamingReasoning(sessionId, turnId, state);
|
|
26776
26830
|
delete state.reasoningPartId;
|
|
26777
26831
|
delete state.reasoningAccum;
|
|
26778
|
-
delete state.
|
|
26779
|
-
state.
|
|
26780
|
-
state.lastTextPersist = state.lastTextRender;
|
|
26832
|
+
delete state.lastReasoningPersist;
|
|
26833
|
+
state.lastTextPersist = Date.now();
|
|
26781
26834
|
}
|
|
26782
26835
|
async planWithRetry(planner, input, session, turn, assistantMessage, context, timeoutMs, allowEmpty = false) {
|
|
26783
26836
|
let lastError = "";
|
|
@@ -26786,7 +26839,7 @@ This completion is already terminal and was delivered automatically. Do not call
|
|
|
26786
26839
|
release,
|
|
26787
26840
|
timedOut
|
|
26788
26841
|
} = this.registerTurnController(turn.id, timeoutMs);
|
|
26789
|
-
this.
|
|
26842
|
+
this.deleteStreamingParts(turn.id);
|
|
26790
26843
|
const onStreamEvent = (event) => this.applyStreamEvent(session, turn, assistantMessage, event);
|
|
26791
26844
|
try {
|
|
26792
26845
|
for (let attempt = 1;; attempt += 1) {
|
|
@@ -26813,7 +26866,7 @@ This completion is already terminal and was delivered automatically. Do not call
|
|
|
26813
26866
|
lastError = "cancelled";
|
|
26814
26867
|
break;
|
|
26815
26868
|
}
|
|
26816
|
-
this.prepareStreamingRetry(turn.id);
|
|
26869
|
+
this.prepareStreamingRetry(session.id, turn.id);
|
|
26817
26870
|
const retry = plannerRetryState(error, attempt, true);
|
|
26818
26871
|
const errorPayload = {
|
|
26819
26872
|
turnId: turn.id,
|
|
@@ -26935,7 +26988,7 @@ This completion is already terminal and was delivered automatically. Do not call
|
|
|
26935
26988
|
} : {}
|
|
26936
26989
|
});
|
|
26937
26990
|
this.modelCallsByTurn.delete(turn.id);
|
|
26938
|
-
this.
|
|
26991
|
+
this.deleteStreamingParts(turn.id);
|
|
26939
26992
|
this.fireHooks({
|
|
26940
26993
|
id: turn.sessionId
|
|
26941
26994
|
}, "turn.stop", undefined, {
|
|
@@ -28405,7 +28458,7 @@ function sameExistingPath(left, right) {
|
|
|
28405
28458
|
return false;
|
|
28406
28459
|
}
|
|
28407
28460
|
}
|
|
28408
|
-
var REASONING_MAX_BYTES2,
|
|
28461
|
+
var REASONING_MAX_BYTES2, STREAM_PERSIST_INTERVAL_MS = 2000, LIVE_OUTPUT_MAX_BYTES, LIVE_OUTPUT_FLUSH_INTERVAL_MS = 150, LIVE_OUTPUT_INITIAL_DELAY_MS = 320, TOOL_HUMAN_RESULT_MAX_BYTES, LOOP_SUPERVISION_NO_PROGRESS_STEPS = 12, LOOP_SUPERVISION_STEER_INTERVAL = 5, LOOP_PATTERN_MAX_PERIOD = 8, PROGRESS_ACTION_TOOLS, AUTO_COMPACTION_CONTINUATION = "[internal continuation after context compaction: Continue the active user task from the compacted prior context. Do not repeat, regenerate, or explain the summary. Resume with the exact next useful action.]", WRAPUP_MODEL_TIMEOUT_MS = 15000, DEFAULT_SHUTDOWN_GRACE_PERIOD_MS = 2000, RUNTIME_LEASE_MS = 60000, RUNTIME_HEARTBEAT_MS = 15000, RESTART_TOOL_ERROR = "Interrupted by runtime restart; tool execution was not replayed.", STEP_LIMIT_WRAPUP_DIRECTIVE = "You have reached the maximum number of steps allowed for this turn, so tools are no longer available. Do not attempt to call any tool. In a few sentences, summarize what you accomplished, the key findings or evidence so far, any blockers, and the single most useful next step. This is your final message for this turn.", TIME_LIMIT_WRAPUP_DIRECTIVE = "You have reached the interactive wall-clock budget for this turn, so tools are no longer available. Do not attempt to call any tool. Concisely summarize completed work, proven evidence, active background jobs, remaining uncertainty, and the single best next action. This is your final message for this turn.", INTERNAL_META_STREAM_PREFIXES, IneffectiveCompactionError, ModelCallDeadlineError, PlannerOutputValidationError;
|
|
28409
28462
|
var init_runtime = __esm(() => {
|
|
28410
28463
|
init_sqlite_store();
|
|
28411
28464
|
init_registry4();
|
|
@@ -28453,6 +28506,7 @@ var init_runtime = __esm(() => {
|
|
|
28453
28506
|
LIVE_OUTPUT_MAX_BYTES = 2 * 1024;
|
|
28454
28507
|
TOOL_HUMAN_RESULT_MAX_BYTES = 24 * 1024;
|
|
28455
28508
|
PROGRESS_ACTION_TOOLS = new Set(["http_request", "subdomain_enum", "dir_enum", "port_scan", "nmap_scan", "fs_edit", "fs_write", "patch_apply", "code_write_script", "campaign_verify", "campaign_test", "callback_oast", "exploit_search"]);
|
|
28509
|
+
INTERNAL_META_STREAM_PREFIXES = ["the user", "user asked", "user wants", "user requested", "user said", "per my", "per the", "my communication", "my instruction", "my instructions", "my rules", "my task", "according to my", "according to the", "the tool search", "tool_search", "there's no dedicated tool", "there is no dedicated tool", "there's no specific tool", "there is no specific tool", "there's no matching tool", "there is no matching tool", "i have access to", "let me inspect the available tool", "let me check the available tool", "let me search the available tool", "i should report", "i will report", "i need to report", "i must report", "i can report", "we should report", "we will report", "we need to report", "we must report", "we can report"];
|
|
28456
28510
|
IneffectiveCompactionError = class IneffectiveCompactionError extends Error {
|
|
28457
28511
|
constructor(preTokens, postTokens) {
|
|
28458
28512
|
super(`compaction did not reduce active context: ${preTokens} -> ${postTokens} estimated tokens`);
|
|
@@ -32644,6 +32698,17 @@ function createRuntimePort(runtime, options = {}) {
|
|
|
32644
32698
|
return;
|
|
32645
32699
|
if (evt.type === "snapshot.changed" && pending.some((item) => item.type === "snapshot.changed" && item.sessionId === evt.sessionId))
|
|
32646
32700
|
return;
|
|
32701
|
+
const streamIdentity = transientStreamIdentity(evt);
|
|
32702
|
+
if (streamIdentity) {
|
|
32703
|
+
const existing = pending.length - 1;
|
|
32704
|
+
if (existing >= 0 && transientStreamIdentity(pending[existing]) === streamIdentity)
|
|
32705
|
+
pending[existing] = evt;
|
|
32706
|
+
else
|
|
32707
|
+
pending.push(evt);
|
|
32708
|
+
if (!flushTimer)
|
|
32709
|
+
flushTimer = setTimeout(flush, BATCH_DEBOUNCE_MS);
|
|
32710
|
+
return;
|
|
32711
|
+
}
|
|
32647
32712
|
if (evt.type === "activity.changed") {
|
|
32648
32713
|
const existing = pending.findIndex((item) => item.type === "activity.changed" && item.sessionId === evt.sessionId);
|
|
32649
32714
|
if (existing >= 0)
|
|
@@ -33249,6 +33314,16 @@ function createRuntimePort(runtime, options = {}) {
|
|
|
33249
33314
|
}
|
|
33250
33315
|
};
|
|
33251
33316
|
}
|
|
33317
|
+
function transientStreamIdentity(event) {
|
|
33318
|
+
if (event.type !== "event.appended")
|
|
33319
|
+
return;
|
|
33320
|
+
if (event.event.type !== "stream_text" && event.event.type !== "stream_reasoning")
|
|
33321
|
+
return;
|
|
33322
|
+
const payload = event.event.payload;
|
|
33323
|
+
if (typeof payload?.turnId !== "string" || typeof payload.partId !== "string")
|
|
33324
|
+
return;
|
|
33325
|
+
return `${event.sessionId}:${payload.turnId}:${event.event.type}:${payload.partId}`;
|
|
33326
|
+
}
|
|
33252
33327
|
function storeChangeIdentity(change) {
|
|
33253
33328
|
switch (change.kind) {
|
|
33254
33329
|
case "part":
|
|
@@ -34292,19 +34367,6 @@ function createActions(store, setStore) {
|
|
|
34292
34367
|
errorSet(message) {
|
|
34293
34368
|
setStore("ui", "lastError", message);
|
|
34294
34369
|
},
|
|
34295
|
-
streamTextUpdated(partId, text) {
|
|
34296
|
-
setStore(produce((s) => {
|
|
34297
|
-
for (const message of s.snapshot.messages) {
|
|
34298
|
-
const part = message.parts.find((item) => item.id === partId);
|
|
34299
|
-
if (!part)
|
|
34300
|
-
continue;
|
|
34301
|
-
part.payload = {
|
|
34302
|
-
text
|
|
34303
|
-
};
|
|
34304
|
-
return;
|
|
34305
|
-
}
|
|
34306
|
-
}));
|
|
34307
|
-
},
|
|
34308
34370
|
toolInputPreviewUpdated(preview) {
|
|
34309
34371
|
setStore(produce((s) => {
|
|
34310
34372
|
const index = s.snapshot.toolInputPreviews.findIndex((item) => item.id === preview.id);
|
|
@@ -34746,9 +34808,11 @@ async function handleTuiEvent(evt, ctx) {
|
|
|
34746
34808
|
}
|
|
34747
34809
|
switch (evt.type) {
|
|
34748
34810
|
case "turn.started":
|
|
34811
|
+
ctx.onTurnStarted?.(evt.turnId);
|
|
34749
34812
|
ctx.actions.turnStarted(evt.turnId, evt.startedAt);
|
|
34750
34813
|
break;
|
|
34751
34814
|
case "turn.finished":
|
|
34815
|
+
ctx.onTurnFinished?.(evt.turnId);
|
|
34752
34816
|
ctx.actions.turnFinished(evt.turnId);
|
|
34753
34817
|
await refreshSnapshot(evt.sessionId);
|
|
34754
34818
|
queueMicrotask(() => {
|
|
@@ -34779,8 +34843,14 @@ async function handleTuiEvent(evt, ctx) {
|
|
|
34779
34843
|
}
|
|
34780
34844
|
if (evt.event.type === "stream_text") {
|
|
34781
34845
|
const payload = evt.event.payload;
|
|
34782
|
-
if (typeof payload?.partId === "string" && typeof payload.text === "string") {
|
|
34783
|
-
ctx.
|
|
34846
|
+
if (typeof payload?.turnId === "string" && typeof payload.partId === "string" && typeof payload.text === "string") {
|
|
34847
|
+
ctx.onStreamText?.(payload.partId, payload.text, payload.turnId);
|
|
34848
|
+
}
|
|
34849
|
+
}
|
|
34850
|
+
if (evt.event.type === "stream_reasoning") {
|
|
34851
|
+
const payload = evt.event.payload;
|
|
34852
|
+
if (typeof payload?.turnId === "string" && typeof payload.partId === "string" && typeof payload.rationale === "string") {
|
|
34853
|
+
ctx.onStreamReasoning?.(payload.partId, payload.rationale, payload.turnId);
|
|
34784
34854
|
}
|
|
34785
34855
|
}
|
|
34786
34856
|
const detail = statusDetailFor(evt.event);
|
|
@@ -34986,6 +35056,243 @@ var init_runtime2 = __esm(() => {
|
|
|
34986
35056
|
RuntimeContext = createContext();
|
|
34987
35057
|
});
|
|
34988
35058
|
|
|
35059
|
+
// src/agent-tui/transcript/stream-engine.ts
|
|
35060
|
+
function createTranscriptStreamEngine() {
|
|
35061
|
+
const [state, setState] = createStore({
|
|
35062
|
+
text: {},
|
|
35063
|
+
reasoning: {},
|
|
35064
|
+
diagnostics: {
|
|
35065
|
+
revision: 0,
|
|
35066
|
+
flushes: 0,
|
|
35067
|
+
coalescedUpdates: 0,
|
|
35068
|
+
lastIntervalMs: BASE_FRAME_INTERVAL_MS,
|
|
35069
|
+
lastFlushAt: undefined
|
|
35070
|
+
}
|
|
35071
|
+
});
|
|
35072
|
+
const pending = new Map;
|
|
35073
|
+
let activeTurnId;
|
|
35074
|
+
let timer;
|
|
35075
|
+
let timerDueAt = 0;
|
|
35076
|
+
let lastFlushAt = 0;
|
|
35077
|
+
let updatesSinceFlush = 0;
|
|
35078
|
+
let coalescedUpdates = 0;
|
|
35079
|
+
let currentInterval = BASE_FRAME_INTERVAL_MS;
|
|
35080
|
+
let acceptingUpdates = false;
|
|
35081
|
+
let disposed = false;
|
|
35082
|
+
function key(kind, partId) {
|
|
35083
|
+
return `${kind}:${partId}`;
|
|
35084
|
+
}
|
|
35085
|
+
function intervalFor(contentLength, updateCount) {
|
|
35086
|
+
const sizePressure = Math.log2(1 + contentLength / 4096) * 8;
|
|
35087
|
+
const updatePressure = Math.max(0, updateCount - 3) * 2;
|
|
35088
|
+
return Math.round(Math.max(MIN_FRAME_INTERVAL_MS, Math.min(MAX_FRAME_INTERVAL_MS, BASE_FRAME_INTERVAL_MS + sizePressure + updatePressure)));
|
|
35089
|
+
}
|
|
35090
|
+
function schedule() {
|
|
35091
|
+
if (disposed || pending.size === 0)
|
|
35092
|
+
return;
|
|
35093
|
+
const now = Date.now();
|
|
35094
|
+
const maxLength = Math.max(0, ...[...pending.values()].map((entry) => entry.content.length));
|
|
35095
|
+
const interval = intervalFor(maxLength, updatesSinceFlush);
|
|
35096
|
+
currentInterval = interval;
|
|
35097
|
+
const elapsed = now - lastFlushAt;
|
|
35098
|
+
if (lastFlushAt === 0 || elapsed >= interval) {
|
|
35099
|
+
flush();
|
|
35100
|
+
return;
|
|
35101
|
+
}
|
|
35102
|
+
const dueAt = lastFlushAt + interval;
|
|
35103
|
+
if (timer && dueAt <= timerDueAt)
|
|
35104
|
+
return;
|
|
35105
|
+
if (timer)
|
|
35106
|
+
clearTimeout(timer);
|
|
35107
|
+
timerDueAt = dueAt;
|
|
35108
|
+
timer = setTimeout(flush, Math.max(0, dueAt - now));
|
|
35109
|
+
}
|
|
35110
|
+
function flush() {
|
|
35111
|
+
if (disposed)
|
|
35112
|
+
return;
|
|
35113
|
+
if (timer) {
|
|
35114
|
+
clearTimeout(timer);
|
|
35115
|
+
timer = undefined;
|
|
35116
|
+
}
|
|
35117
|
+
timerDueAt = 0;
|
|
35118
|
+
if (pending.size === 0)
|
|
35119
|
+
return;
|
|
35120
|
+
const entries = [...pending.values()];
|
|
35121
|
+
pending.clear();
|
|
35122
|
+
const now = Date.now();
|
|
35123
|
+
lastFlushAt = now;
|
|
35124
|
+
updatesSinceFlush = 0;
|
|
35125
|
+
setState(produce((draft) => {
|
|
35126
|
+
draft.diagnostics.revision += 1;
|
|
35127
|
+
draft.diagnostics.flushes += 1;
|
|
35128
|
+
draft.diagnostics.coalescedUpdates = coalescedUpdates;
|
|
35129
|
+
draft.diagnostics.lastIntervalMs = currentInterval;
|
|
35130
|
+
draft.diagnostics.lastFlushAt = now;
|
|
35131
|
+
const revision = draft.diagnostics.revision;
|
|
35132
|
+
for (const entry of entries) {
|
|
35133
|
+
const target = entry.kind === "text" ? draft.text : draft.reasoning;
|
|
35134
|
+
target[entry.partId] = {
|
|
35135
|
+
content: entry.content,
|
|
35136
|
+
revision
|
|
35137
|
+
};
|
|
35138
|
+
}
|
|
35139
|
+
}));
|
|
35140
|
+
}
|
|
35141
|
+
function clearVisible() {
|
|
35142
|
+
pending.clear();
|
|
35143
|
+
updatesSinceFlush = 0;
|
|
35144
|
+
if (timer) {
|
|
35145
|
+
clearTimeout(timer);
|
|
35146
|
+
timer = undefined;
|
|
35147
|
+
}
|
|
35148
|
+
timerDueAt = 0;
|
|
35149
|
+
setState(produce((draft) => {
|
|
35150
|
+
draft.text = {};
|
|
35151
|
+
draft.reasoning = {};
|
|
35152
|
+
}));
|
|
35153
|
+
}
|
|
35154
|
+
function update(kind, partId, content, turnId) {
|
|
35155
|
+
if (disposed || !acceptingUpdates || turnId !== activeTurnId)
|
|
35156
|
+
return;
|
|
35157
|
+
const pendingKey = key(kind, partId);
|
|
35158
|
+
const existing = pending.get(pendingKey);
|
|
35159
|
+
const visible = kind === "text" ? state.text[partId]?.content : state.reasoning[partId]?.content;
|
|
35160
|
+
if (existing?.content === content || !existing && visible === content)
|
|
35161
|
+
return;
|
|
35162
|
+
if (existing)
|
|
35163
|
+
coalescedUpdates += 1;
|
|
35164
|
+
pending.set(pendingKey, {
|
|
35165
|
+
kind,
|
|
35166
|
+
partId,
|
|
35167
|
+
content
|
|
35168
|
+
});
|
|
35169
|
+
updatesSinceFlush += 1;
|
|
35170
|
+
schedule();
|
|
35171
|
+
}
|
|
35172
|
+
function durableContent(messages, partId, kind) {
|
|
35173
|
+
for (const message of messages) {
|
|
35174
|
+
const part = message.parts.find((candidate2) => candidate2.id === partId);
|
|
35175
|
+
if (!part)
|
|
35176
|
+
continue;
|
|
35177
|
+
if (kind === "text") {
|
|
35178
|
+
if (typeof part.payload === "string")
|
|
35179
|
+
return part.payload;
|
|
35180
|
+
if (part.payload && typeof part.payload === "object" && "text" in part.payload) {
|
|
35181
|
+
const value = part.payload.text;
|
|
35182
|
+
return typeof value === "string" ? value : undefined;
|
|
35183
|
+
}
|
|
35184
|
+
return;
|
|
35185
|
+
}
|
|
35186
|
+
if (part.payload && typeof part.payload === "object") {
|
|
35187
|
+
const payload = part.payload;
|
|
35188
|
+
if (typeof payload.rationale === "string")
|
|
35189
|
+
return payload.rationale;
|
|
35190
|
+
if (typeof payload.text === "string")
|
|
35191
|
+
return payload.text;
|
|
35192
|
+
}
|
|
35193
|
+
return typeof part.payload === "string" ? part.payload : undefined;
|
|
35194
|
+
}
|
|
35195
|
+
return;
|
|
35196
|
+
}
|
|
35197
|
+
function reconciliationRemovals(kind, visible, messages) {
|
|
35198
|
+
const removals = [];
|
|
35199
|
+
for (const [partId, entry] of Object.entries(visible)) {
|
|
35200
|
+
const durable = durableContent(messages, partId, kind);
|
|
35201
|
+
if (durable === entry.content)
|
|
35202
|
+
removals.push(partId);
|
|
35203
|
+
}
|
|
35204
|
+
return removals;
|
|
35205
|
+
}
|
|
35206
|
+
function reconcile2(messages, runningTurnId) {
|
|
35207
|
+
if (disposed)
|
|
35208
|
+
return;
|
|
35209
|
+
if (!runningTurnId) {
|
|
35210
|
+
clearVisible();
|
|
35211
|
+
activeTurnId = undefined;
|
|
35212
|
+
acceptingUpdates = false;
|
|
35213
|
+
return;
|
|
35214
|
+
}
|
|
35215
|
+
if (activeTurnId && activeTurnId !== runningTurnId) {
|
|
35216
|
+
clearVisible();
|
|
35217
|
+
lastFlushAt = 0;
|
|
35218
|
+
currentInterval = BASE_FRAME_INTERVAL_MS;
|
|
35219
|
+
}
|
|
35220
|
+
if (activeTurnId !== runningTurnId)
|
|
35221
|
+
acceptingUpdates = true;
|
|
35222
|
+
activeTurnId = runningTurnId;
|
|
35223
|
+
const textRemovals = reconciliationRemovals("text", state.text, messages);
|
|
35224
|
+
const reasoningRemovals = reconciliationRemovals("reasoning", state.reasoning, messages);
|
|
35225
|
+
if (textRemovals.length === 0 && reasoningRemovals.length === 0)
|
|
35226
|
+
return;
|
|
35227
|
+
setState(produce((draft) => {
|
|
35228
|
+
for (const partId of textRemovals)
|
|
35229
|
+
delete draft.text[partId];
|
|
35230
|
+
for (const partId of reasoningRemovals)
|
|
35231
|
+
delete draft.reasoning[partId];
|
|
35232
|
+
}));
|
|
35233
|
+
}
|
|
35234
|
+
function beginTurn(turnId) {
|
|
35235
|
+
if (disposed)
|
|
35236
|
+
return;
|
|
35237
|
+
if (activeTurnId !== turnId) {
|
|
35238
|
+
clearVisible();
|
|
35239
|
+
lastFlushAt = 0;
|
|
35240
|
+
currentInterval = BASE_FRAME_INTERVAL_MS;
|
|
35241
|
+
}
|
|
35242
|
+
activeTurnId = turnId;
|
|
35243
|
+
acceptingUpdates = true;
|
|
35244
|
+
}
|
|
35245
|
+
function finishTurn(turnId) {
|
|
35246
|
+
if (disposed || activeTurnId !== turnId)
|
|
35247
|
+
return;
|
|
35248
|
+
flush();
|
|
35249
|
+
acceptingUpdates = false;
|
|
35250
|
+
}
|
|
35251
|
+
function reset2() {
|
|
35252
|
+
if (disposed)
|
|
35253
|
+
return;
|
|
35254
|
+
clearVisible();
|
|
35255
|
+
activeTurnId = undefined;
|
|
35256
|
+
acceptingUpdates = false;
|
|
35257
|
+
lastFlushAt = 0;
|
|
35258
|
+
coalescedUpdates = 0;
|
|
35259
|
+
currentInterval = BASE_FRAME_INTERVAL_MS;
|
|
35260
|
+
setState("diagnostics", {
|
|
35261
|
+
revision: 0,
|
|
35262
|
+
flushes: 0,
|
|
35263
|
+
coalescedUpdates: 0,
|
|
35264
|
+
lastIntervalMs: BASE_FRAME_INTERVAL_MS,
|
|
35265
|
+
lastFlushAt: undefined
|
|
35266
|
+
});
|
|
35267
|
+
}
|
|
35268
|
+
function dispose2() {
|
|
35269
|
+
if (disposed)
|
|
35270
|
+
return;
|
|
35271
|
+
clearVisible();
|
|
35272
|
+
disposed = true;
|
|
35273
|
+
}
|
|
35274
|
+
return {
|
|
35275
|
+
state,
|
|
35276
|
+
beginTurn,
|
|
35277
|
+
finishTurn,
|
|
35278
|
+
update,
|
|
35279
|
+
updateText(partId, content, turnId) {
|
|
35280
|
+
update("text", partId, content, turnId);
|
|
35281
|
+
},
|
|
35282
|
+
updateReasoning(partId, content, turnId) {
|
|
35283
|
+
update("reasoning", partId, content, turnId);
|
|
35284
|
+
},
|
|
35285
|
+
reconcile: reconcile2,
|
|
35286
|
+
reset: reset2,
|
|
35287
|
+
flush,
|
|
35288
|
+
dispose: dispose2
|
|
35289
|
+
};
|
|
35290
|
+
}
|
|
35291
|
+
var MIN_FRAME_INTERVAL_MS = 24, BASE_FRAME_INTERVAL_MS = 24, MAX_FRAME_INTERVAL_MS = 96;
|
|
35292
|
+
var init_stream_engine = __esm(() => {
|
|
35293
|
+
init_store2();
|
|
35294
|
+
});
|
|
35295
|
+
|
|
34989
35296
|
// src/agent-tui/reasoning.ts
|
|
34990
35297
|
function parseReasoning(text) {
|
|
34991
35298
|
const trimmed = normalizeReasoningSummary(text);
|
|
@@ -36475,6 +36782,34 @@ var init_renderers2 = __esm(() => {
|
|
|
36475
36782
|
TOOL_DETAIL_MAX_BYTES = 32 * 1024;
|
|
36476
36783
|
});
|
|
36477
36784
|
|
|
36785
|
+
// src/agent-tui/transcript/projection.ts
|
|
36786
|
+
function createTranscriptProjection(store, width) {
|
|
36787
|
+
const historyMessages = createMemo(() => {
|
|
36788
|
+
const runningTurnId = store.snapshot.runningTurnId;
|
|
36789
|
+
return runningTurnId ? store.snapshot.messages.filter((message) => message.turnId !== runningTurnId) : store.snapshot.messages;
|
|
36790
|
+
});
|
|
36791
|
+
const activeMessages = createMemo(() => {
|
|
36792
|
+
const runningTurnId = store.snapshot.runningTurnId;
|
|
36793
|
+
return runningTurnId ? store.snapshot.messages.filter((message) => message.turnId === runningTurnId) : [];
|
|
36794
|
+
});
|
|
36795
|
+
const activeMessageIds = createMemo(() => new Set(activeMessages().map((message) => message.id)));
|
|
36796
|
+
const historyToolCalls = createMemo(() => {
|
|
36797
|
+
const runningTurnId = store.snapshot.runningTurnId;
|
|
36798
|
+
return runningTurnId ? store.snapshot.toolCalls.filter((toolCall) => toolCall.turnId !== runningTurnId && (!toolCall.messageId || !activeMessageIds().has(toolCall.messageId))) : store.snapshot.toolCalls;
|
|
36799
|
+
});
|
|
36800
|
+
const activeToolCalls = createMemo(() => {
|
|
36801
|
+
const runningTurnId = store.snapshot.runningTurnId;
|
|
36802
|
+
return runningTurnId ? store.snapshot.toolCalls.filter((toolCall) => toolCall.turnId === runningTurnId || (toolCall.messageId ? activeMessageIds().has(toolCall.messageId) : toolCall.turnId === undefined)) : [];
|
|
36803
|
+
});
|
|
36804
|
+
const historyRows = createMemo(() => projectMessagesToRows(historyMessages(), width(), undefined, historyToolCalls()));
|
|
36805
|
+
const activeRows = createMemo(() => projectMessagesToRows(activeMessages(), width(), store.snapshot.runningTurnId, activeToolCalls(), store.snapshot.toolInputPreviews));
|
|
36806
|
+
return createMemo(() => [...historyRows(), ...activeRows()]);
|
|
36807
|
+
}
|
|
36808
|
+
var init_projection = __esm(() => {
|
|
36809
|
+
init_solid();
|
|
36810
|
+
init_renderers2();
|
|
36811
|
+
});
|
|
36812
|
+
|
|
36478
36813
|
// src/agent-tui/context/store.tsx
|
|
36479
36814
|
function proxyRefreshQuery() {
|
|
36480
36815
|
return {
|
|
@@ -36493,6 +36828,7 @@ function TuiStoreProvider(props) {
|
|
|
36493
36828
|
setStore: _set,
|
|
36494
36829
|
actions
|
|
36495
36830
|
} = createFaraiStore(workspace);
|
|
36831
|
+
const transcript = createTranscriptStreamEngine();
|
|
36496
36832
|
let statusTimer;
|
|
36497
36833
|
const proxyRefreshes = new Map;
|
|
36498
36834
|
const mcpRefreshes = new Map;
|
|
@@ -36514,7 +36850,7 @@ function TuiStoreProvider(props) {
|
|
|
36514
36850
|
actions.updateNoticeSet(notice);
|
|
36515
36851
|
});
|
|
36516
36852
|
}
|
|
36517
|
-
const timelineRows =
|
|
36853
|
+
const timelineRows = createTranscriptProjection(store, () => Math.max(1, dims().width - 4));
|
|
36518
36854
|
function setStatusDetail(detail, timeoutMs) {
|
|
36519
36855
|
if (disposed)
|
|
36520
36856
|
return;
|
|
@@ -36582,6 +36918,7 @@ function TuiStoreProvider(props) {
|
|
|
36582
36918
|
if (disposed || store.activeSessionId !== sid || snapshotGenerations.get(sid) !== generation)
|
|
36583
36919
|
return;
|
|
36584
36920
|
actions.snapshotApplied(snapshot);
|
|
36921
|
+
transcript.reconcile(snapshot.messages, snapshot.runningTurnId);
|
|
36585
36922
|
for (const entry2 of promptHistoryFromMessages(snapshot.messages)) {
|
|
36586
36923
|
actions.promptHistoryAdd(entry2, "session");
|
|
36587
36924
|
}
|
|
@@ -36611,12 +36948,16 @@ function TuiStoreProvider(props) {
|
|
|
36611
36948
|
return;
|
|
36612
36949
|
if (sessionId === store.activeSessionId)
|
|
36613
36950
|
return;
|
|
36951
|
+
transcript.reset();
|
|
36614
36952
|
actions.activeSessionSet(sessionId);
|
|
36615
36953
|
const pendingSubmission = promptSubmissions.get(sessionId);
|
|
36616
36954
|
if (pendingSubmission)
|
|
36617
36955
|
pendingSubmission.generation = actions.promptSubmissionStarted();
|
|
36618
36956
|
props.onActiveSessionChange?.(sessionId);
|
|
36619
36957
|
port.setActiveSession(sessionId);
|
|
36958
|
+
const runningTurnId = port.getRunningTurnId?.(sessionId);
|
|
36959
|
+
if (runningTurnId)
|
|
36960
|
+
transcript.beginTurn(runningTurnId);
|
|
36620
36961
|
try {
|
|
36621
36962
|
await requestSnapshotRefresh(sessionId);
|
|
36622
36963
|
} catch (error) {
|
|
@@ -37113,9 +37454,11 @@ function TuiStoreProvider(props) {
|
|
|
37113
37454
|
setStatusDetail,
|
|
37114
37455
|
refreshSnapshot: requestSnapshotRefresh,
|
|
37115
37456
|
refreshSessions,
|
|
37116
|
-
onSnapshot: () =>
|
|
37117
|
-
|
|
37118
|
-
|
|
37457
|
+
onSnapshot: (snapshot) => transcript.reconcile(snapshot.messages, snapshot.runningTurnId),
|
|
37458
|
+
onTurnStarted: (turnId) => transcript.beginTurn(turnId),
|
|
37459
|
+
onTurnFinished: (turnId) => transcript.finishTurn(turnId),
|
|
37460
|
+
onStreamText: (partId, text, turnId) => transcript.updateText(partId, text, turnId),
|
|
37461
|
+
onStreamReasoning: (partId, rationale, turnId) => transcript.updateReasoning(partId, rationale, turnId)
|
|
37119
37462
|
}, (error) => {
|
|
37120
37463
|
if (!disposed)
|
|
37121
37464
|
actions.errorSet(error instanceof Error ? error.message : String(error));
|
|
@@ -37123,8 +37466,9 @@ function TuiStoreProvider(props) {
|
|
|
37123
37466
|
const off = port.event.on((event) => {
|
|
37124
37467
|
if (disposed)
|
|
37125
37468
|
return;
|
|
37126
|
-
if (event.type === "store.changed" || event.type === "store.batch")
|
|
37469
|
+
if (event.type === "store.changed" || event.type === "store.batch" || event.type === "turn.started") {
|
|
37127
37470
|
invalidateSnapshot(event.sessionId);
|
|
37471
|
+
}
|
|
37128
37472
|
eventDispatcher.dispatch(event);
|
|
37129
37473
|
});
|
|
37130
37474
|
onCleanup(() => {
|
|
@@ -37135,6 +37479,7 @@ function TuiStoreProvider(props) {
|
|
|
37135
37479
|
mcpOverlayGeneration += 1;
|
|
37136
37480
|
off();
|
|
37137
37481
|
eventDispatcher.dispose();
|
|
37482
|
+
transcript.dispose();
|
|
37138
37483
|
if (statusTimer)
|
|
37139
37484
|
clearTimeout(statusTimer);
|
|
37140
37485
|
});
|
|
@@ -37180,6 +37525,7 @@ function TuiStoreProvider(props) {
|
|
|
37180
37525
|
store,
|
|
37181
37526
|
actions,
|
|
37182
37527
|
timelineRows,
|
|
37528
|
+
transcript,
|
|
37183
37529
|
submitPrompt,
|
|
37184
37530
|
submitUserInput,
|
|
37185
37531
|
answerUserInputQuestion,
|
|
@@ -37264,7 +37610,8 @@ var init_store4 = __esm(() => {
|
|
|
37264
37610
|
init_solid();
|
|
37265
37611
|
init_store3();
|
|
37266
37612
|
init_runtime2();
|
|
37267
|
-
|
|
37613
|
+
init_stream_engine();
|
|
37614
|
+
init_projection();
|
|
37268
37615
|
StoreContext = createContext();
|
|
37269
37616
|
});
|
|
37270
37617
|
|
|
@@ -39846,7 +40193,10 @@ function KeyboardController() {
|
|
|
39846
40193
|
for (const message of [...tui.store.snapshot.messages].reverse()) {
|
|
39847
40194
|
if (message.role !== "assistant")
|
|
39848
40195
|
continue;
|
|
39849
|
-
const parts = message.parts.map((part) => {
|
|
40196
|
+
const parts = message.parts.filter((part) => part.type === "text").map((part) => {
|
|
40197
|
+
const streamed = tui.transcript.state.text[part.id]?.content;
|
|
40198
|
+
if (streamed !== undefined)
|
|
40199
|
+
return streamed;
|
|
39850
40200
|
if (typeof part.payload === "string")
|
|
39851
40201
|
return part.payload;
|
|
39852
40202
|
if (part.payload && typeof part.payload === "object" && "text" in part.payload) {
|
|
@@ -40244,11 +40594,13 @@ function AssistantMessage(props) {
|
|
|
40244
40594
|
insertNode(_el$, _el$2);
|
|
40245
40595
|
setProp(_el$, "style", {
|
|
40246
40596
|
flexDirection: "column",
|
|
40597
|
+
flexShrink: 0,
|
|
40247
40598
|
marginBottom: 1
|
|
40248
40599
|
});
|
|
40249
40600
|
insertNode(_el$2, _el$3);
|
|
40250
40601
|
setProp(_el$2, "style", {
|
|
40251
40602
|
flexDirection: "row",
|
|
40603
|
+
flexShrink: 0,
|
|
40252
40604
|
minWidth: 0
|
|
40253
40605
|
});
|
|
40254
40606
|
insert(_el$2, createComponent2(TranscriptMarker, {
|
|
@@ -40264,23 +40616,23 @@ function AssistantMessage(props) {
|
|
|
40264
40616
|
minWidth: 0
|
|
40265
40617
|
});
|
|
40266
40618
|
setProp(_el$4, "width", "100%");
|
|
40619
|
+
setProp(_el$4, "streaming", true);
|
|
40620
|
+
setProp(_el$4, "internalBlockMode", "top-level");
|
|
40267
40621
|
setProp(_el$4, "tableOptions", {
|
|
40268
40622
|
style: "columns",
|
|
40269
40623
|
widthMode: "content",
|
|
40270
40624
|
cellPaddingX: 1
|
|
40271
40625
|
});
|
|
40272
40626
|
effect((_p$) => {
|
|
40273
|
-
var _v$ = props.
|
|
40627
|
+
var _v$ = props.streamedText ?? props.row.text, _v$2 = syntax(), _v$3 = COLOR.markdownText;
|
|
40274
40628
|
_v$ !== _p$.e && (_p$.e = setProp(_el$4, "content", _v$, _p$.e));
|
|
40275
|
-
_v$2 !== _p$.t && (_p$.t = setProp(_el$4, "
|
|
40276
|
-
_v$3 !== _p$.a && (_p$.a = setProp(_el$4, "
|
|
40277
|
-
_v$4 !== _p$.o && (_p$.o = setProp(_el$4, "fg", _v$4, _p$.o));
|
|
40629
|
+
_v$2 !== _p$.t && (_p$.t = setProp(_el$4, "syntaxStyle", _v$2, _p$.t));
|
|
40630
|
+
_v$3 !== _p$.a && (_p$.a = setProp(_el$4, "fg", _v$3, _p$.a));
|
|
40278
40631
|
return _p$;
|
|
40279
40632
|
}, {
|
|
40280
40633
|
e: undefined,
|
|
40281
40634
|
t: undefined,
|
|
40282
|
-
a: undefined
|
|
40283
|
-
o: undefined
|
|
40635
|
+
a: undefined
|
|
40284
40636
|
});
|
|
40285
40637
|
return _el$;
|
|
40286
40638
|
})();
|
|
@@ -40359,18 +40711,24 @@ function ReasoningRow(props) {
|
|
|
40359
40711
|
const tui = useTuiStore();
|
|
40360
40712
|
const dims = useTerminalDimensions();
|
|
40361
40713
|
const expanded = () => Boolean(tui.store.ui.expandedCells[props.row.id]);
|
|
40362
|
-
const
|
|
40714
|
+
const content = createMemo(() => props.streamedReasoning === undefined ? {
|
|
40715
|
+
title: props.row.title,
|
|
40716
|
+
body: props.row.body
|
|
40717
|
+
} : parseReasoning(props.streamedReasoning));
|
|
40718
|
+
const label = () => truncateLine2(content().title === "reasoning" ? "thinking" : content().title, Math.max(1, dims().width - 4));
|
|
40363
40719
|
const toggleClick = createPrimaryClickGesture(() => tui.actions.cellExpandedToggle(props.row.id));
|
|
40364
40720
|
return (() => {
|
|
40365
40721
|
var _el$ = createElement("box"), _el$2 = createElement("box"), _el$3 = createElement("text");
|
|
40366
40722
|
insertNode(_el$, _el$2);
|
|
40367
40723
|
setProp(_el$, "style", {
|
|
40368
40724
|
flexDirection: "column",
|
|
40725
|
+
flexShrink: 0,
|
|
40369
40726
|
marginBottom: 1
|
|
40370
40727
|
});
|
|
40371
40728
|
insertNode(_el$2, _el$3);
|
|
40372
40729
|
setProp(_el$2, "style", {
|
|
40373
|
-
flexDirection: "row"
|
|
40730
|
+
flexDirection: "row",
|
|
40731
|
+
flexShrink: 0
|
|
40374
40732
|
});
|
|
40375
40733
|
spread(_el$2, toggleClick, true);
|
|
40376
40734
|
insert(_el$2, createComponent2(TranscriptMarker, {
|
|
@@ -40384,24 +40742,24 @@ function ReasoningRow(props) {
|
|
|
40384
40742
|
insert(_el$3, label);
|
|
40385
40743
|
insert(_el$, createComponent2(Show, {
|
|
40386
40744
|
get when() {
|
|
40387
|
-
return memo2(() => !!expanded())() &&
|
|
40745
|
+
return memo2(() => !!expanded())() && content().body.trim();
|
|
40388
40746
|
},
|
|
40389
40747
|
get children() {
|
|
40390
40748
|
return createComponent2(ExpandedPanel, {
|
|
40391
40749
|
get children() {
|
|
40392
40750
|
var _el$4 = createElement("markdown");
|
|
40751
|
+
setProp(_el$4, "streaming", true);
|
|
40752
|
+
setProp(_el$4, "internalBlockMode", "top-level");
|
|
40393
40753
|
effect((_p$) => {
|
|
40394
|
-
var _v$ =
|
|
40754
|
+
var _v$ = content().body, _v$2 = syntax(), _v$3 = COLOR.dim;
|
|
40395
40755
|
_v$ !== _p$.e && (_p$.e = setProp(_el$4, "content", _v$, _p$.e));
|
|
40396
|
-
_v$2 !== _p$.t && (_p$.t = setProp(_el$4, "
|
|
40397
|
-
_v$3 !== _p$.a && (_p$.a = setProp(_el$4, "
|
|
40398
|
-
_v$4 !== _p$.o && (_p$.o = setProp(_el$4, "fg", _v$4, _p$.o));
|
|
40756
|
+
_v$2 !== _p$.t && (_p$.t = setProp(_el$4, "syntaxStyle", _v$2, _p$.t));
|
|
40757
|
+
_v$3 !== _p$.a && (_p$.a = setProp(_el$4, "fg", _v$3, _p$.a));
|
|
40399
40758
|
return _p$;
|
|
40400
40759
|
}, {
|
|
40401
40760
|
e: undefined,
|
|
40402
40761
|
t: undefined,
|
|
40403
|
-
a: undefined
|
|
40404
|
-
o: undefined
|
|
40762
|
+
a: undefined
|
|
40405
40763
|
});
|
|
40406
40764
|
return _el$4;
|
|
40407
40765
|
}
|
|
@@ -40430,6 +40788,7 @@ var init_reasoning_cell = __esm(() => {
|
|
|
40430
40788
|
init_expanded_panel();
|
|
40431
40789
|
init_transcript_marker();
|
|
40432
40790
|
init_mouse();
|
|
40791
|
+
init_reasoning();
|
|
40433
40792
|
});
|
|
40434
40793
|
|
|
40435
40794
|
// src/agent-tui/filetype.ts
|
|
@@ -42094,12 +42453,18 @@ function FaraiRow(props) {
|
|
|
42094
42453
|
return createComponent2(AssistantMessage, {
|
|
42095
42454
|
get row() {
|
|
42096
42455
|
return props.row;
|
|
42456
|
+
},
|
|
42457
|
+
get streamedText() {
|
|
42458
|
+
return props.streamedText;
|
|
42097
42459
|
}
|
|
42098
42460
|
});
|
|
42099
42461
|
case "thinking":
|
|
42100
42462
|
return createComponent2(ReasoningRow, {
|
|
42101
42463
|
get row() {
|
|
42102
42464
|
return props.row;
|
|
42465
|
+
},
|
|
42466
|
+
get streamedReasoning() {
|
|
42467
|
+
return props.streamedReasoning;
|
|
42103
42468
|
}
|
|
42104
42469
|
});
|
|
42105
42470
|
case "tool":
|
|
@@ -42225,7 +42590,16 @@ function Transcript() {
|
|
|
42225
42590
|
byId
|
|
42226
42591
|
};
|
|
42227
42592
|
});
|
|
42228
|
-
const rawRows = createMemo(() => tui.store.snapshot.messages.flatMap((message) => message.parts.map((part) =>
|
|
42593
|
+
const rawRows = createMemo(() => tui.store.snapshot.messages.flatMap((message) => message.parts.map((part) => {
|
|
42594
|
+
const streamText = tui.transcript.state.text[part.id]?.content;
|
|
42595
|
+
const streamReasoning = tui.transcript.state.reasoning[part.id]?.content;
|
|
42596
|
+
const payload = streamText !== undefined ? {
|
|
42597
|
+
text: streamText
|
|
42598
|
+
} : streamReasoning !== undefined ? {
|
|
42599
|
+
rationale: streamReasoning
|
|
42600
|
+
} : part.payload;
|
|
42601
|
+
return `${message.role}.${part.type} ${formatPayload(payload, 16000)}`;
|
|
42602
|
+
})));
|
|
42229
42603
|
createEffect(() => {
|
|
42230
42604
|
const request = tui.store.ui.messageNavigation;
|
|
42231
42605
|
const userIds = transcriptRows().filter((row) => row.kind === "user").map((row) => row.id);
|
|
@@ -42242,6 +42616,7 @@ function Transcript() {
|
|
|
42242
42616
|
typeof _ref$ === "function" ? use(_ref$, _el$) : scrollRef = _el$;
|
|
42243
42617
|
setProp(_el$, "stickyScroll", true);
|
|
42244
42618
|
setProp(_el$, "stickyStart", "bottom");
|
|
42619
|
+
setProp(_el$, "viewportCulling", true);
|
|
42245
42620
|
setProp(_el$, "scrollbarOptions", {
|
|
42246
42621
|
visible: false
|
|
42247
42622
|
});
|
|
@@ -42307,6 +42682,12 @@ function Transcript() {
|
|
|
42307
42682
|
children: (id2) => createComponent2(TranscriptRow, {
|
|
42308
42683
|
get row() {
|
|
42309
42684
|
return indexedRows().byId.get(id2);
|
|
42685
|
+
},
|
|
42686
|
+
get streamedText() {
|
|
42687
|
+
return tui.transcript.state.text[id2]?.content;
|
|
42688
|
+
},
|
|
42689
|
+
get streamedReasoning() {
|
|
42690
|
+
return tui.transcript.state.reasoning[id2]?.content;
|
|
42310
42691
|
}
|
|
42311
42692
|
})
|
|
42312
42693
|
});
|
|
@@ -42422,12 +42803,19 @@ function TranscriptRow(props) {
|
|
|
42422
42803
|
var _el$1 = createElement("box");
|
|
42423
42804
|
setProp(_el$1, "style", {
|
|
42424
42805
|
flexDirection: "column",
|
|
42806
|
+
flexShrink: 0,
|
|
42425
42807
|
paddingLeft: isUser ? 0 : 1,
|
|
42426
42808
|
paddingRight: isUser ? 0 : 1
|
|
42427
42809
|
});
|
|
42428
42810
|
insert(_el$1, createComponent2(FaraiRow, {
|
|
42429
42811
|
get row() {
|
|
42430
42812
|
return props.row;
|
|
42813
|
+
},
|
|
42814
|
+
get streamedText() {
|
|
42815
|
+
return props.streamedText;
|
|
42816
|
+
},
|
|
42817
|
+
get streamedReasoning() {
|
|
42818
|
+
return props.streamedReasoning;
|
|
42431
42819
|
}
|
|
42432
42820
|
}));
|
|
42433
42821
|
effect((_$p) => setProp(_el$1, "id", props.row.id, _$p));
|
|
@@ -49967,5 +50355,5 @@ Examples:
|
|
|
49967
50355
|
`);
|
|
49968
50356
|
}
|
|
49969
50357
|
|
|
49970
|
-
//# debugId=
|
|
50358
|
+
//# debugId=90702708DD95C63C64756E2164756E21
|
|
49971
50359
|
//# sourceMappingURL=index.js.map
|