@dimi-agent/cli 0.6.1 → 0.6.2
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/main.mjs +146 -84
- package/package.json +4 -4
package/dist/main.mjs
CHANGED
|
@@ -378194,6 +378194,21 @@ var init_tool_call = __esmMin((() => {
|
|
|
378194
378194
|
get toolCallView() {
|
|
378195
378195
|
return this.toolCall;
|
|
378196
378196
|
}
|
|
378197
|
+
/**
|
|
378198
|
+
* Whether this call has reached a terminal state. Ordinary tools finish when
|
|
378199
|
+
* their result lands; agent and read cards derive their phase from events
|
|
378200
|
+
* (subagent lifecycle / read status), falling back to the result. Used by
|
|
378201
|
+
* transcript folding to avoid collapsing calls the user still needs to
|
|
378202
|
+
* watch (a running agent would otherwise disappear into the summary line).
|
|
378203
|
+
*/
|
|
378204
|
+
isFinished() {
|
|
378205
|
+
if (this.toolCall.name === "Agent" || this.toolCall.name === "AgentSwarm") {
|
|
378206
|
+
const phase = this.getSubagentSnapshot().phase;
|
|
378207
|
+
return phase === "done" || phase === "failed" || phase === "backgrounded";
|
|
378208
|
+
}
|
|
378209
|
+
if (this.toolCall.name === "Read") return this.getReadSnapshot().phase !== "pending";
|
|
378210
|
+
return this.result !== void 0;
|
|
378211
|
+
}
|
|
378197
378212
|
/** Notifies the listener when internal state changes, if a group is attached. */
|
|
378198
378213
|
notifySnapshotChange() {
|
|
378199
378214
|
this.onSnapshotChange?.();
|
|
@@ -387216,6 +387231,82 @@ var init_terminal_notification = __esmMin((() => {
|
|
|
387216
387231
|
init_terminal();
|
|
387217
387232
|
}));
|
|
387218
387233
|
//#endregion
|
|
387234
|
+
//#region src/tui/utils/transcript-window.ts
|
|
387235
|
+
/**
|
|
387236
|
+
* Read a non-negative integer env var, falling back to `fallback` when it is
|
|
387237
|
+
* unset, empty, negative, or not an integer. `0` is a valid value (call sites
|
|
387238
|
+
* treat it as "feature disabled").
|
|
387239
|
+
*/
|
|
387240
|
+
function readEnvInt(name, fallback) {
|
|
387241
|
+
const raw = process.env[name];
|
|
387242
|
+
if (raw === void 0 || raw.trim() === "") return fallback;
|
|
387243
|
+
const value = Number(raw);
|
|
387244
|
+
if (!Number.isInteger(value) || value < 0) return fallback;
|
|
387245
|
+
return value;
|
|
387246
|
+
}
|
|
387247
|
+
/**
|
|
387248
|
+
* Group consecutive entries into turns by `turnId`. Entries with the same
|
|
387249
|
+
* non-undefined `turnId` that are adjacent belong to the same turn.
|
|
387250
|
+
*
|
|
387251
|
+
* Entries with an undefined `turnId` are buffered and attached to the *next*
|
|
387252
|
+
* defined turn. This matters because a user message is appended (with
|
|
387253
|
+
* `turnId: undefined`) before its turn actually starts, so without this
|
|
387254
|
+
* buffering every user message would become its own single-entry turn at the
|
|
387255
|
+
* front and get trimmed first. Any undefined entries left at the tail (no
|
|
387256
|
+
* following turn) become their own turn.
|
|
387257
|
+
*/
|
|
387258
|
+
function groupTurns(entries) {
|
|
387259
|
+
const turns = [];
|
|
387260
|
+
let current;
|
|
387261
|
+
let pendingUndefined = [];
|
|
387262
|
+
for (const entry of entries) {
|
|
387263
|
+
const turnId = entry.turnId;
|
|
387264
|
+
if (turnId === void 0) {
|
|
387265
|
+
pendingUndefined.push(entry);
|
|
387266
|
+
continue;
|
|
387267
|
+
}
|
|
387268
|
+
if (current !== void 0 && current.turnId === turnId) current.entries.push(entry);
|
|
387269
|
+
else {
|
|
387270
|
+
current = {
|
|
387271
|
+
turnId,
|
|
387272
|
+
entries: [...pendingUndefined, entry]
|
|
387273
|
+
};
|
|
387274
|
+
pendingUndefined = [];
|
|
387275
|
+
turns.push(current);
|
|
387276
|
+
}
|
|
387277
|
+
}
|
|
387278
|
+
if (pendingUndefined.length > 0) turns.push({
|
|
387279
|
+
turnId: void 0,
|
|
387280
|
+
entries: pendingUndefined
|
|
387281
|
+
});
|
|
387282
|
+
return turns;
|
|
387283
|
+
}
|
|
387284
|
+
/**
|
|
387285
|
+
* Decide which entries to destroy so the remaining turns fit within
|
|
387286
|
+
* `maxTurns`. Returns an empty set when the turn count is within
|
|
387287
|
+
* `maxTurns + hysteresis`. Oldest turns are removed first; the most recent
|
|
387288
|
+
* turn is never removed (it is the active / just-finished turn).
|
|
387289
|
+
*/
|
|
387290
|
+
function turnsToTrim(turns, maxTurns, hysteresis) {
|
|
387291
|
+
const toRemove = /* @__PURE__ */ new Set();
|
|
387292
|
+
if (turns.length <= maxTurns + hysteresis) return toRemove;
|
|
387293
|
+
let remaining = turns.length;
|
|
387294
|
+
for (let i = 0; i < turns.length - 1 && remaining > maxTurns; i++) {
|
|
387295
|
+
const turn = turns[i];
|
|
387296
|
+
for (const entry of turn.entries) toRemove.add(entry);
|
|
387297
|
+
remaining--;
|
|
387298
|
+
}
|
|
387299
|
+
return toRemove;
|
|
387300
|
+
}
|
|
387301
|
+
var TRANSCRIPT_MAX_TURNS, TRANSCRIPT_EXPAND_TURNS, TRANSCRIPT_HYSTERESIS, TRANSCRIPT_KEEP_RECENT_STEPS, TRANSCRIPT_KEEP_TRAILING_TOOL_CALLS;
|
|
387302
|
+
var init_transcript_window = __esmMin((() => {
|
|
387303
|
+
TRANSCRIPT_MAX_TURNS = readEnvInt("DIMI_CODE_TUI_MAX_TURNS", 15);
|
|
387304
|
+
TRANSCRIPT_EXPAND_TURNS = readEnvInt("DIMI_CODE_TUI_EXPAND_TURNS", 3);
|
|
387305
|
+
TRANSCRIPT_HYSTERESIS = readEnvInt("DIMI_CODE_TUI_HYSTERESIS", 5);
|
|
387306
|
+
TRANSCRIPT_KEEP_RECENT_STEPS = readEnvInt("DIMI_CODE_TUI_KEEP_RECENT_STEPS", 30);
|
|
387307
|
+
TRANSCRIPT_KEEP_TRAILING_TOOL_CALLS = readEnvInt("DIMI_CODE_TUI_KEEP_TRAILING_TOOL_CALLS", 2);
|
|
387308
|
+
}));
|
|
387309
|
+
//#endregion
|
|
387219
387310
|
//#region src/tui/controllers/streaming-ui.ts
|
|
387220
387311
|
var StreamingUIController;
|
|
387221
387312
|
var init_streaming_ui = __esmMin((() => {
|
|
@@ -387231,6 +387322,7 @@ var init_streaming_ui = __esmMin((() => {
|
|
|
387231
387322
|
init_event_payload();
|
|
387232
387323
|
init_terminal_notification();
|
|
387233
387324
|
init_transcript_id();
|
|
387325
|
+
init_transcript_window();
|
|
387234
387326
|
StreamingUIController = class {
|
|
387235
387327
|
host;
|
|
387236
387328
|
flushTimer;
|
|
@@ -387714,6 +387806,7 @@ var init_streaming_ui = __esmMin((() => {
|
|
|
387714
387806
|
state.transcriptContainer.addChild(tc);
|
|
387715
387807
|
state.ui.requestRender();
|
|
387716
387808
|
}
|
|
387809
|
+
this.host.foldTrailingToolCalls(TRANSCRIPT_KEEP_TRAILING_TOOL_CALLS);
|
|
387717
387810
|
if (toolCall.name === "ExitPlanMode" && typeof toolCall.args["plan"] !== "string") {
|
|
387718
387811
|
const session = this.host.requireSession();
|
|
387719
387812
|
(async () => {
|
|
@@ -390462,81 +390555,6 @@ var init_tmux_keyboard = __esmMin((() => {
|
|
|
390462
390555
|
TMUX_EXTENDED_KEYS_FORMAT_XTERM_WARNING = "tmux extended-keys-format is xterm. Dimi works best with csi-u. Add `set -g extended-keys-format csi-u` to ~/.tmux.conf and restart tmux.";
|
|
390463
390556
|
}));
|
|
390464
390557
|
//#endregion
|
|
390465
|
-
//#region src/tui/utils/transcript-window.ts
|
|
390466
|
-
/**
|
|
390467
|
-
* Read a non-negative integer env var, falling back to `fallback` when it is
|
|
390468
|
-
* unset, empty, negative, or not an integer. `0` is a valid value (call sites
|
|
390469
|
-
* treat it as "feature disabled").
|
|
390470
|
-
*/
|
|
390471
|
-
function readEnvInt(name, fallback) {
|
|
390472
|
-
const raw = process.env[name];
|
|
390473
|
-
if (raw === void 0 || raw.trim() === "") return fallback;
|
|
390474
|
-
const value = Number(raw);
|
|
390475
|
-
if (!Number.isInteger(value) || value < 0) return fallback;
|
|
390476
|
-
return value;
|
|
390477
|
-
}
|
|
390478
|
-
/**
|
|
390479
|
-
* Group consecutive entries into turns by `turnId`. Entries with the same
|
|
390480
|
-
* non-undefined `turnId` that are adjacent belong to the same turn.
|
|
390481
|
-
*
|
|
390482
|
-
* Entries with an undefined `turnId` are buffered and attached to the *next*
|
|
390483
|
-
* defined turn. This matters because a user message is appended (with
|
|
390484
|
-
* `turnId: undefined`) before its turn actually starts, so without this
|
|
390485
|
-
* buffering every user message would become its own single-entry turn at the
|
|
390486
|
-
* front and get trimmed first. Any undefined entries left at the tail (no
|
|
390487
|
-
* following turn) become their own turn.
|
|
390488
|
-
*/
|
|
390489
|
-
function groupTurns(entries) {
|
|
390490
|
-
const turns = [];
|
|
390491
|
-
let current;
|
|
390492
|
-
let pendingUndefined = [];
|
|
390493
|
-
for (const entry of entries) {
|
|
390494
|
-
const turnId = entry.turnId;
|
|
390495
|
-
if (turnId === void 0) {
|
|
390496
|
-
pendingUndefined.push(entry);
|
|
390497
|
-
continue;
|
|
390498
|
-
}
|
|
390499
|
-
if (current !== void 0 && current.turnId === turnId) current.entries.push(entry);
|
|
390500
|
-
else {
|
|
390501
|
-
current = {
|
|
390502
|
-
turnId,
|
|
390503
|
-
entries: [...pendingUndefined, entry]
|
|
390504
|
-
};
|
|
390505
|
-
pendingUndefined = [];
|
|
390506
|
-
turns.push(current);
|
|
390507
|
-
}
|
|
390508
|
-
}
|
|
390509
|
-
if (pendingUndefined.length > 0) turns.push({
|
|
390510
|
-
turnId: void 0,
|
|
390511
|
-
entries: pendingUndefined
|
|
390512
|
-
});
|
|
390513
|
-
return turns;
|
|
390514
|
-
}
|
|
390515
|
-
/**
|
|
390516
|
-
* Decide which entries to destroy so the remaining turns fit within
|
|
390517
|
-
* `maxTurns`. Returns an empty set when the turn count is within
|
|
390518
|
-
* `maxTurns + hysteresis`. Oldest turns are removed first; the most recent
|
|
390519
|
-
* turn is never removed (it is the active / just-finished turn).
|
|
390520
|
-
*/
|
|
390521
|
-
function turnsToTrim(turns, maxTurns, hysteresis) {
|
|
390522
|
-
const toRemove = /* @__PURE__ */ new Set();
|
|
390523
|
-
if (turns.length <= maxTurns + hysteresis) return toRemove;
|
|
390524
|
-
let remaining = turns.length;
|
|
390525
|
-
for (let i = 0; i < turns.length - 1 && remaining > maxTurns; i++) {
|
|
390526
|
-
const turn = turns[i];
|
|
390527
|
-
for (const entry of turn.entries) toRemove.add(entry);
|
|
390528
|
-
remaining--;
|
|
390529
|
-
}
|
|
390530
|
-
return toRemove;
|
|
390531
|
-
}
|
|
390532
|
-
var TRANSCRIPT_MAX_TURNS, TRANSCRIPT_EXPAND_TURNS, TRANSCRIPT_HYSTERESIS, TRANSCRIPT_KEEP_RECENT_STEPS;
|
|
390533
|
-
var init_transcript_window = __esmMin((() => {
|
|
390534
|
-
TRANSCRIPT_MAX_TURNS = readEnvInt("DIMI_CODE_TUI_MAX_TURNS", 15);
|
|
390535
|
-
TRANSCRIPT_EXPAND_TURNS = readEnvInt("DIMI_CODE_TUI_EXPAND_TURNS", 3);
|
|
390536
|
-
TRANSCRIPT_HYSTERESIS = readEnvInt("DIMI_CODE_TUI_HYSTERESIS", 5);
|
|
390537
|
-
TRANSCRIPT_KEEP_RECENT_STEPS = readEnvInt("DIMI_CODE_TUI_KEEP_RECENT_STEPS", 30);
|
|
390538
|
-
}));
|
|
390539
|
-
//#endregion
|
|
390540
390558
|
//#region src/tui/dimi-tui.ts
|
|
390541
390559
|
function loadingTipKind(mode) {
|
|
390542
390560
|
if (mode === "waiting" || mode === "tool") return "moon";
|
|
@@ -391895,6 +391913,7 @@ var init_dimi_tui = __esmMin((() => {
|
|
|
391895
391913
|
markTranscriptComponent(component, entry);
|
|
391896
391914
|
this.state.transcriptContainer.addChild(component);
|
|
391897
391915
|
}
|
|
391916
|
+
if (entry.kind === "tool_call") this.foldTrailingToolCalls(TRANSCRIPT_KEEP_TRAILING_TOOL_CALLS);
|
|
391898
391917
|
const trimmed = this.trimTranscriptWindow();
|
|
391899
391918
|
const merged = this.mergeCurrentTurnSteps();
|
|
391900
391919
|
if (component || trimmed || merged) this.state.ui.requestRender();
|
|
@@ -391999,6 +392018,21 @@ var init_dimi_tui = __esmMin((() => {
|
|
|
391999
392018
|
return this.foldCurrentTurnSteps(TRANSCRIPT_KEEP_RECENT_STEPS);
|
|
392000
392019
|
}
|
|
392001
392020
|
collapseTrailingToolCalls() {
|
|
392021
|
+
this.foldTrailingToolCalls(0);
|
|
392022
|
+
}
|
|
392023
|
+
/**
|
|
392024
|
+
* Fold the trailing contiguous run of tool calls, keeping the most recent
|
|
392025
|
+
* `keepExpanded` calls expanded. `keepExpanded = 0` collapses the whole run
|
|
392026
|
+
* (used when visible content follows, e.g. an assistant message or turn
|
|
392027
|
+
* end); a positive cap folds progressively while the run is still growing
|
|
392028
|
+
* so older calls merge into the summary immediately instead of staying
|
|
392029
|
+
* expanded until the run ends.
|
|
392030
|
+
*
|
|
392031
|
+
* Only finished calls fold — a call that is still running (streaming args,
|
|
392032
|
+
* a live subagent, a pending read) stays visible because its progress is
|
|
392033
|
+
* live information the user is watching.
|
|
392034
|
+
*/
|
|
392035
|
+
foldTrailingToolCalls(keepExpanded) {
|
|
392002
392036
|
const children = this.state.transcriptContainer.children;
|
|
392003
392037
|
let start = children.length;
|
|
392004
392038
|
const toolCalls = [];
|
|
@@ -392020,21 +392054,49 @@ var init_dimi_tui = __esmMin((() => {
|
|
|
392020
392054
|
const standaloneNames = new Set(["AllDone", "WaitFor"]);
|
|
392021
392055
|
const standaloneCalls = new Set(toolCalls.filter((call) => standaloneNames.has(call.toolCallView.name)));
|
|
392022
392056
|
const sequenceCalls = toolCalls.filter((call) => !standaloneCalls.has(call));
|
|
392057
|
+
if (sequenceCalls.length === 0) return;
|
|
392058
|
+
const foldCount = sequenceCalls.length - keepExpanded;
|
|
392059
|
+
if (foldCount <= 0) return;
|
|
392023
392060
|
const components = children.slice(start);
|
|
392024
392061
|
const standalone = [];
|
|
392025
392062
|
const sequenceComponents = [];
|
|
392063
|
+
const keptComponents = [];
|
|
392064
|
+
let remainingToFold = foldCount;
|
|
392065
|
+
let stoppedAtUnfinished = false;
|
|
392026
392066
|
for (const component of components) {
|
|
392027
|
-
if (
|
|
392028
|
-
|
|
392029
|
-
component.clear();
|
|
392067
|
+
if (stoppedAtUnfinished) {
|
|
392068
|
+
keptComponents.push(component);
|
|
392030
392069
|
continue;
|
|
392031
392070
|
}
|
|
392032
|
-
if (component instanceof ToolCallComponent && standaloneCalls.has(component))
|
|
392033
|
-
|
|
392034
|
-
|
|
392035
|
-
|
|
392036
|
-
|
|
392037
|
-
|
|
392071
|
+
if (component instanceof ToolCallComponent && standaloneCalls.has(component)) {
|
|
392072
|
+
standalone.push(component);
|
|
392073
|
+
continue;
|
|
392074
|
+
}
|
|
392075
|
+
const calls = toolCallsIn(component);
|
|
392076
|
+
const callCount = calls?.filter((call) => !standaloneCalls.has(call)).length ?? 0;
|
|
392077
|
+
const hasUnfinished = calls?.some((call) => !call.isFinished()) ?? false;
|
|
392078
|
+
if (remainingToFold > 0 && hasUnfinished) {
|
|
392079
|
+
keptComponents.push(component);
|
|
392080
|
+
stoppedAtUnfinished = true;
|
|
392081
|
+
continue;
|
|
392082
|
+
}
|
|
392083
|
+
if (remainingToFold > 0) {
|
|
392084
|
+
if (component instanceof ToolCallSequenceComponent) {
|
|
392085
|
+
sequenceComponents.push(...component.children);
|
|
392086
|
+
component.clear();
|
|
392087
|
+
} else sequenceComponents.push(component);
|
|
392088
|
+
remainingToFold -= callCount;
|
|
392089
|
+
} else keptComponents.push(component);
|
|
392090
|
+
}
|
|
392091
|
+
if (sequenceComponents.length === 0) return;
|
|
392092
|
+
const foldedCalls = [];
|
|
392093
|
+
for (const component of sequenceComponents) {
|
|
392094
|
+
const componentCalls = toolCallsIn(component);
|
|
392095
|
+
if (componentCalls !== void 0) foldedCalls.push(...componentCalls.filter((call) => !standaloneCalls.has(call)));
|
|
392096
|
+
}
|
|
392097
|
+
if (foldedCalls.length === 0) return;
|
|
392098
|
+
const sequence = new ToolCallSequenceComponent(sequenceComponents, foldedCalls, this.state.toolDisplayMode);
|
|
392099
|
+
children.splice(start, components.length, sequence, ...standalone, ...keptComponents);
|
|
392038
392100
|
this.state.transcriptContainer.invalidate();
|
|
392039
392101
|
}
|
|
392040
392102
|
foldCurrentTurnSteps(keepSteps) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dimi-agent/cli",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.2",
|
|
4
4
|
"description": "The Starting Point for Next-Gen Agents",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"agent",
|
|
@@ -60,12 +60,12 @@
|
|
|
60
60
|
"tsx": "^4.21.0",
|
|
61
61
|
"yazl": "^3.3.1",
|
|
62
62
|
"zod": "^4.3.6",
|
|
63
|
-
"@dimi-agent/
|
|
64
|
-
"@dimi-agent/dimi-telemetry": "^0.1.0",
|
|
63
|
+
"@dimi-agent/dimi-oauth": "^0.1.0",
|
|
65
64
|
"@dimi-agent/dimi-sdk": "^0.2.0",
|
|
66
65
|
"@dimi-agent/dimi-web": "^0.1.0",
|
|
66
|
+
"@dimi-agent/agent-core-v2": "^0.1.0",
|
|
67
|
+
"@dimi-agent/dimi-telemetry": "^0.1.0",
|
|
67
68
|
"@dimi-agent/kap-server": "^0.1.0",
|
|
68
|
-
"@dimi-agent/dimi-oauth": "^0.1.0",
|
|
69
69
|
"@dimi-agent/pi-tui": "^0.1.0",
|
|
70
70
|
"@dimi-agent/remote": "^0.1.0"
|
|
71
71
|
},
|