aiden-runtime 4.1.4 → 4.1.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/dist/cli/v4/aidenCLI.js +28 -0
- package/dist/cli/v4/callbacks.js +78 -0
- package/dist/cli/v4/chatSession.js +154 -1
- package/dist/cli/v4/defaultSoul.js +75 -3
- package/dist/cli/v4/display/progressBar.js +41 -8
- package/dist/cli/v4/display.js +248 -15
- package/dist/cli/v4/toolPreview.js +10 -0
- package/dist/core/toolRegistry.js +7 -1
- package/dist/core/v4/aidenAgent.js +63 -0
- package/dist/core/v4/loopTrace.js +257 -0
- package/dist/core/version.js +1 -1
- package/dist/core/webSearch.js +64 -24
- package/package.json +1 -1
- package/plugins/aiden-plugin-cdp-browser/.granted-permissions.json +8 -0
package/dist/cli/v4/aidenCLI.js
CHANGED
|
@@ -1057,6 +1057,34 @@ async function buildAgentRuntime(cliOpts, opts) {
|
|
|
1057
1057
|
// diagnostics must not break the loop
|
|
1058
1058
|
}
|
|
1059
1059
|
},
|
|
1060
|
+
// v4.1.5 Issue K — phase lifecycle hooks for the activity indicator
|
|
1061
|
+
// verb mutation. Each fires at a specific point in runConversation:
|
|
1062
|
+
// - onMemoryRefreshStart: before memory I/O begins
|
|
1063
|
+
// - onPromptBuilt: after system prompt assembly
|
|
1064
|
+
// - onProviderRequestStart: just before the HTTP request opens
|
|
1065
|
+
// chatSession registers handlers that call `indicator.setVerb()` so
|
|
1066
|
+
// the user sees the model's actual workflow phase during the gap.
|
|
1067
|
+
// All three are forwarded through `callbacks` so chatSession owns
|
|
1068
|
+
// the indicator handle (created per-turn). Defensive try/catch on
|
|
1069
|
+
// each — a misbehaving display sink never blocks the agent loop.
|
|
1070
|
+
onMemoryRefreshStart: () => {
|
|
1071
|
+
try {
|
|
1072
|
+
callbacks.onMemoryRefreshStart?.();
|
|
1073
|
+
}
|
|
1074
|
+
catch { /* defensive */ }
|
|
1075
|
+
},
|
|
1076
|
+
onPromptBuilt: (info) => {
|
|
1077
|
+
try {
|
|
1078
|
+
callbacks.onPromptBuilt?.(info);
|
|
1079
|
+
}
|
|
1080
|
+
catch { /* defensive */ }
|
|
1081
|
+
},
|
|
1082
|
+
onProviderRequestStart: (id) => {
|
|
1083
|
+
try {
|
|
1084
|
+
callbacks.onProviderRequestStart?.(id);
|
|
1085
|
+
}
|
|
1086
|
+
catch { /* defensive */ }
|
|
1087
|
+
},
|
|
1060
1088
|
// Phase 23.4b — feed the agent's Stage-0 intent pre-arm with the
|
|
1061
1089
|
// skill's `required_tools` from its SKILL.md frontmatter. Returns
|
|
1062
1090
|
// null when the skill is unknown / unloaded / empty so the agent
|
package/dist/cli/v4/callbacks.js
CHANGED
|
@@ -63,6 +63,29 @@ class CliCallbacks {
|
|
|
63
63
|
this.toolRows = new Map();
|
|
64
64
|
this.toolStartTimes = new Map();
|
|
65
65
|
this.firstToolFiredThisTurn = false;
|
|
66
|
+
// v4.1.5 Issue K — `firePhaseVerb` is the public entry point for the
|
|
67
|
+
// AidenCLI bridge. AidenAgent fires `onMemoryRefreshStart` etc.,
|
|
68
|
+
// aidenCLI's adapter calls into one of these `onPhase…` shims, each
|
|
69
|
+
// mapping a lifecycle event to a verb string. Defensive try/catch so
|
|
70
|
+
// a misbehaving display sink can't unwind the agent loop.
|
|
71
|
+
this.onMemoryRefreshStart = () => {
|
|
72
|
+
try {
|
|
73
|
+
this.phaseVerbHook?.('refreshing memory');
|
|
74
|
+
}
|
|
75
|
+
catch { /* defensive */ }
|
|
76
|
+
};
|
|
77
|
+
this.onPromptBuilt = (_info) => {
|
|
78
|
+
try {
|
|
79
|
+
this.phaseVerbHook?.('preparing prompt');
|
|
80
|
+
}
|
|
81
|
+
catch { /* defensive */ }
|
|
82
|
+
};
|
|
83
|
+
this.onProviderRequestStart = (_providerId) => {
|
|
84
|
+
try {
|
|
85
|
+
this.phaseVerbHook?.('calling provider');
|
|
86
|
+
}
|
|
87
|
+
catch { /* defensive */ }
|
|
88
|
+
};
|
|
66
89
|
/**
|
|
67
90
|
* Phase 23.5 — bound to AidenAgent.onToolCall. Emits one event row
|
|
68
91
|
* per tool call: prints `[running]` on `before`, mutates the bracket
|
|
@@ -91,6 +114,14 @@ class CliCallbacks {
|
|
|
91
114
|
this.beforeToolHook?.();
|
|
92
115
|
}
|
|
93
116
|
catch { /* defensive */ }
|
|
117
|
+
// v4.1.5+ Path A — fire the loop-trace sink BEFORE row writes.
|
|
118
|
+
// Captures every tool's call.id + name (including hidden ones
|
|
119
|
+
// suppressed from the visible trail) so the trace covers the
|
|
120
|
+
// full agent loop, not just user-visible work.
|
|
121
|
+
try {
|
|
122
|
+
this.toolTraceBeforeHook?.(call.id, call.name);
|
|
123
|
+
}
|
|
124
|
+
catch { /* defensive */ }
|
|
94
125
|
const handle = this.display.toolRow(call.name, call.arguments);
|
|
95
126
|
this.toolRows.set(call.id, handle);
|
|
96
127
|
this.toolStartTimes.set(call.id, Date.now());
|
|
@@ -109,12 +140,25 @@ class CliCallbacks {
|
|
|
109
140
|
this.afterEachToolHook?.(call.name);
|
|
110
141
|
}
|
|
111
142
|
catch { /* defensive */ }
|
|
143
|
+
// v4.1.5+ Path A — loop-trace sink fires even when handle was
|
|
144
|
+
// lost (rare; happens if before/after pairing slipped) so the
|
|
145
|
+
// trace never under-counts tool calls.
|
|
146
|
+
try {
|
|
147
|
+
this.toolTraceAfterHook?.(call.id, call.name, call.arguments);
|
|
148
|
+
}
|
|
149
|
+
catch { /* defensive */ }
|
|
112
150
|
return;
|
|
113
151
|
}
|
|
114
152
|
const ms = Date.now() - startedAt;
|
|
115
153
|
const err = result?.error;
|
|
116
154
|
if (typeof err === 'string' && err.includes('URL provenance gate')) {
|
|
117
155
|
handle.blocked();
|
|
156
|
+
// v4.1.5+ Path A — blocked path still needs the trace sink so
|
|
157
|
+
// the URL-provenance failure mode shows up in loop diagnostics.
|
|
158
|
+
try {
|
|
159
|
+
this.toolTraceAfterHook?.(call.id, call.name, call.arguments);
|
|
160
|
+
}
|
|
161
|
+
catch { /* defensive */ }
|
|
118
162
|
return;
|
|
119
163
|
}
|
|
120
164
|
// v4.1.4 reply-quality polish — Part 1.6. Helper used by ALL
|
|
@@ -127,6 +171,14 @@ class CliCallbacks {
|
|
|
127
171
|
this.afterEachToolHook?.(call.name);
|
|
128
172
|
}
|
|
129
173
|
catch { /* defensive */ }
|
|
174
|
+
// v4.1.5+ Path A — also fire the loop-trace `after` sink so the
|
|
175
|
+
// tracer can compute duration + capture args (hidden-from-trail
|
|
176
|
+
// tools still flow through here, by design — the trace must see
|
|
177
|
+
// them to detect lookup_tool_schema / skill_view loops).
|
|
178
|
+
try {
|
|
179
|
+
this.toolTraceAfterHook?.(call.id, call.name, call.arguments);
|
|
180
|
+
}
|
|
181
|
+
catch { /* defensive */ }
|
|
130
182
|
};
|
|
131
183
|
if (typeof err === 'string' && err.includes('URL provenance gate')) {
|
|
132
184
|
handle.blocked();
|
|
@@ -337,6 +389,32 @@ Reply with ONE word: safe, caution, or dangerous.`;
|
|
|
337
389
|
this.beforeToolHook = opts.beforeTool;
|
|
338
390
|
this.afterEachToolHook = opts.afterEachTool;
|
|
339
391
|
}
|
|
392
|
+
/**
|
|
393
|
+
* v4.1.5 Issue K — set/clear the phase-verb sink. chatSession
|
|
394
|
+
* registers a closure that captures the per-turn indicator handle
|
|
395
|
+
* and forwards calls to `indicator.setVerb(verb)`. Cleared between
|
|
396
|
+
* turns by passing `undefined`. Optional — non-indicator callers
|
|
397
|
+
* (test harnesses with stub displays) get no-op behaviour.
|
|
398
|
+
*/
|
|
399
|
+
setPhaseVerbHook(fn) {
|
|
400
|
+
this.phaseVerbHook = fn;
|
|
401
|
+
}
|
|
402
|
+
/**
|
|
403
|
+
* v4.1.5+ Path A — register a per-turn tool-trace sink for the
|
|
404
|
+
* loop-trace logger. `before` fires with the call's id+name BEFORE
|
|
405
|
+
* the row writes; `after` fires post-execution with the same id +
|
|
406
|
+
* the call's args (for skill-name extraction in trace context).
|
|
407
|
+
* Cleared between turns by passing `undefined`.
|
|
408
|
+
*
|
|
409
|
+
* Separate from `setActivityIndicatorHooks` because the activity
|
|
410
|
+
* hook is name-only and fires for visible-trail purposes; this
|
|
411
|
+
* one captures FULL call data including hidden tools (which the
|
|
412
|
+
* trail suppresses via TRAIL_HIDE_TOOLS but the trace must see).
|
|
413
|
+
*/
|
|
414
|
+
setToolTraceHook(opts) {
|
|
415
|
+
this.toolTraceBeforeHook = opts.before;
|
|
416
|
+
this.toolTraceAfterHook = opts.after;
|
|
417
|
+
}
|
|
340
418
|
}
|
|
341
419
|
exports.CliCallbacks = CliCallbacks;
|
|
342
420
|
// Tier-3.1 (v4.1-tier3.1): replaced 🟢/🟡/🔴 emoji badges with
|
|
@@ -69,6 +69,11 @@ exports.renderProgressBar = renderProgressBar;
|
|
|
69
69
|
exports.formatTokens = formatTokens;
|
|
70
70
|
exports.formatDuration = formatDuration;
|
|
71
71
|
exports.renderMemoryConfirmations = renderMemoryConfirmations;
|
|
72
|
+
// v4.1.5+ Path A: env-var-gated loop trace logger. Captures tool-call
|
|
73
|
+
// sequence + system prompt + memory hashes when a turn shows loop
|
|
74
|
+
// symptoms (10+ calls OR 5+ consecutive same-name). Default off via
|
|
75
|
+
// `AIDEN_DEBUG_LOOP=1` env-var. Zero overhead when disabled.
|
|
76
|
+
const loopTrace_1 = require("../../core/v4/loopTrace");
|
|
72
77
|
const display_1 = require("./display");
|
|
73
78
|
// v4.1.4 Part 1.6 — per-turn token progress bar. Fed by `onProgress`
|
|
74
79
|
// events from the streaming adapter; hidden when the adapter doesn't
|
|
@@ -934,6 +939,62 @@ class ChatSession {
|
|
|
934
939
|
const indicator = this.opts.display.activityIndicator('thinking');
|
|
935
940
|
let indicatorStopped = false;
|
|
936
941
|
let streamingActive = false;
|
|
942
|
+
// v4.1.5 Issue O — track whether this turn had any tool calls so
|
|
943
|
+
// we can emit a single muted rule between the tool trail and the
|
|
944
|
+
// reply header. Set true when the first tool's `before` phase
|
|
945
|
+
// fires (via the existing beforeFirstToolHook plumbing). Emitted
|
|
946
|
+
// once per turn — `separatorEmitted` gates idempotency against
|
|
947
|
+
// both streaming and non-streaming paths reaching the same hook.
|
|
948
|
+
//
|
|
949
|
+
// v4.1.5 Phase 1d (Q-OBV-b) — multi-tool separator regression:
|
|
950
|
+
// the prior v4.1.5 Phase 1c emission point was the streaming
|
|
951
|
+
// `onFirstDelta` callback, but that fires PER provider call
|
|
952
|
+
// (the agent resets `firstDeltaFired` each callProvider
|
|
953
|
+
// invocation), and on multi-tool turns where the model emits
|
|
954
|
+
// no preamble in early iterations + no preamble in the final
|
|
955
|
+
// reply iteration either, the relative ordering of "first
|
|
956
|
+
// delta" vs "first tool" could leave the flag/idempotency
|
|
957
|
+
// gate in an unexpected state. Definitive fix: tie emission
|
|
958
|
+
// to the FIRST STREAM BYTE LANDING ON SCREEN, which only
|
|
959
|
+
// happens once per turn regardless of how many provider
|
|
960
|
+
// iterations occurred. `firstStreamByteSeen` is the new gate;
|
|
961
|
+
// separator fires from inside `onDelta` BEFORE `streamPartial`
|
|
962
|
+
// writes the agent header.
|
|
963
|
+
let turnHadTools = false;
|
|
964
|
+
let separatorEmitted = false;
|
|
965
|
+
let firstStreamByteSeen = false;
|
|
966
|
+
// v4.1.5+ Path A: per-turn loop tracer (env-var gated, default off).
|
|
967
|
+
// Captures tool-call sequence + assembled system prompt + memory
|
|
968
|
+
// hashes + recent skills when a turn trips loop thresholds. The
|
|
969
|
+
// `onLoopWarning` callback surfaces a one-line dim hint to the
|
|
970
|
+
// user when consecutive-same-tool count crosses 8 — gives them a
|
|
971
|
+
// chance to Ctrl+C before the agent burns more budget.
|
|
972
|
+
const loopTracer = new loopTrace_1.LoopTracer({
|
|
973
|
+
paths: this.opts.paths,
|
|
974
|
+
providerId: this.currentProviderId,
|
|
975
|
+
modelId: this.currentModelId,
|
|
976
|
+
onLoopWarning: (line) => {
|
|
977
|
+
try {
|
|
978
|
+
this.opts.display.dim(line);
|
|
979
|
+
}
|
|
980
|
+
catch { /* defensive */ }
|
|
981
|
+
},
|
|
982
|
+
});
|
|
983
|
+
if (loopTracer.isEnabled()) {
|
|
984
|
+
loopTracer.setHistory(baseHistory);
|
|
985
|
+
}
|
|
986
|
+
const emitToolReplySeparator = () => {
|
|
987
|
+
if (separatorEmitted || !turnHadTools)
|
|
988
|
+
return;
|
|
989
|
+
separatorEmitted = true;
|
|
990
|
+
// Same chrome pattern as the existing pre-turn rule (line ~1100)
|
|
991
|
+
// and the post-reply rule (line ~1297): two-space indent + the
|
|
992
|
+
// body-width muted rule + newline. The 2-space indent is the
|
|
993
|
+
// legacy convention used by adjacent rules; the v4.1.5 frame
|
|
994
|
+
// gutter (3) is consciously NOT applied here so all three rules
|
|
995
|
+
// in a turn share one left edge.
|
|
996
|
+
this.opts.display.write(` ${this.opts.display.rule()}\n`);
|
|
997
|
+
};
|
|
937
998
|
const stopIndicatorOnce = () => {
|
|
938
999
|
if (indicatorStopped)
|
|
939
1000
|
return;
|
|
@@ -946,12 +1007,55 @@ class ChatSession {
|
|
|
946
1007
|
this.opts.callbacks.setActivityIndicatorHooks?.({});
|
|
947
1008
|
}
|
|
948
1009
|
catch { /* defensive */ }
|
|
1010
|
+
// v4.1.5 Issue K — also clear the phase-verb sink so lifecycle
|
|
1011
|
+
// events fired during async cleanup don't try to update a
|
|
1012
|
+
// stopped indicator.
|
|
1013
|
+
try {
|
|
1014
|
+
this.opts.callbacks.setPhaseVerbHook?.(undefined);
|
|
1015
|
+
}
|
|
1016
|
+
catch { /* defensive */ }
|
|
1017
|
+
// v4.1.5+ Path A — clear the loop-trace sink so subsequent
|
|
1018
|
+
// turns don't fire into a stale tracer. Note: this clears the
|
|
1019
|
+
// HOOK, not the tracer's accumulated state — finalize() still
|
|
1020
|
+
// runs at end-of-try below to write the snapshot if thresholds
|
|
1021
|
+
// tripped.
|
|
1022
|
+
try {
|
|
1023
|
+
this.opts.callbacks.setToolTraceHook?.({});
|
|
1024
|
+
}
|
|
1025
|
+
catch { /* defensive */ }
|
|
949
1026
|
};
|
|
1027
|
+
// v4.1.5 Issue K — wire the per-turn phase-verb sink. Each
|
|
1028
|
+
// AidenAgent lifecycle event (memory refresh start, prompt built,
|
|
1029
|
+
// provider request start) flows through CliCallbacks and lands
|
|
1030
|
+
// here as a verb string ("refreshing memory" / "preparing prompt"
|
|
1031
|
+
// / "calling provider"). The closure captures the per-turn
|
|
1032
|
+
// indicator handle so verb mutations stay scoped to this turn.
|
|
1033
|
+
this.opts.callbacks.setPhaseVerbHook?.((verb) => {
|
|
1034
|
+
if (indicatorStopped)
|
|
1035
|
+
return;
|
|
1036
|
+
indicator.setVerb(verb);
|
|
1037
|
+
});
|
|
1038
|
+
// v4.1.5+ Path A — wire the loop-trace sink. Fires for EVERY tool
|
|
1039
|
+
// call (including hidden ones) so the trace captures the full
|
|
1040
|
+
// agent loop. Defensive — when AIDEN_DEBUG_LOOP is unset, the
|
|
1041
|
+
// tracer's `startTool`/`endTool` short-circuit immediately.
|
|
1042
|
+
this.opts.callbacks.setToolTraceHook?.({
|
|
1043
|
+
before: (id, name) => loopTracer.startTool(id, name),
|
|
1044
|
+
after: (id, name, args) => loopTracer.endTool(id, name, args),
|
|
1045
|
+
});
|
|
950
1046
|
// Phase 23.5 carried forward: stop the indicator the moment the
|
|
951
1047
|
// first tool row prints — the row itself is the activity surface
|
|
952
1048
|
// during a tool. Part 1.6 then resumes via `afterEachTool` so the
|
|
953
1049
|
// post-tool gap has its own indicator paint.
|
|
954
|
-
|
|
1050
|
+
//
|
|
1051
|
+
// v4.1.5 Issue O — also flip `turnHadTools = true` so the
|
|
1052
|
+
// separator emits before the reply header. Single hook captures
|
|
1053
|
+
// "any tool ran this turn" cleanly (it only fires for the FIRST
|
|
1054
|
+
// tool of the turn — subsequent tools don't re-trigger).
|
|
1055
|
+
this.opts.callbacks.setBeforeFirstToolHook?.(() => {
|
|
1056
|
+
turnHadTools = true;
|
|
1057
|
+
stopIndicatorOnce();
|
|
1058
|
+
});
|
|
955
1059
|
// Part 1.6: pause/resume hooks around every tool row. The
|
|
956
1060
|
// `beforeTool` hook fires before EACH tool row writes (not just
|
|
957
1061
|
// the first), so multi-tool sequences also keep the indicator
|
|
@@ -991,10 +1095,32 @@ class ChatSession {
|
|
|
991
1095
|
? () => {
|
|
992
1096
|
stopIndicatorOnce();
|
|
993
1097
|
streamingActive = true;
|
|
1098
|
+
// v4.1.5 Phase 1d (Q-OBV-b) — separator emission MOVED
|
|
1099
|
+
// out of onFirstDelta because that callback fires per
|
|
1100
|
+
// provider-call iteration (firstDeltaFired resets each
|
|
1101
|
+
// callProvider invocation). The separator-emit now
|
|
1102
|
+
// lives in onDelta below, gated by `firstStreamByteSeen`
|
|
1103
|
+
// which only flips once per turn.
|
|
994
1104
|
}
|
|
995
1105
|
: undefined,
|
|
996
1106
|
onDelta: streamingEnabled
|
|
997
1107
|
? (text) => {
|
|
1108
|
+
// v4.1.5 Phase 1d (Q-OBV-b) — definitive separator
|
|
1109
|
+
// emission point. This is the FIRST text byte landing
|
|
1110
|
+
// on screen this turn. Fires the muted rule BEFORE
|
|
1111
|
+
// streamPartial writes the `┃ Aiden` header so the
|
|
1112
|
+
// visual order is:
|
|
1113
|
+
// ┊ tool rows...
|
|
1114
|
+
// ──────────── ← separator
|
|
1115
|
+
// ┃ Aiden
|
|
1116
|
+
// {text}
|
|
1117
|
+
// Idempotent via `firstStreamByteSeen` + the
|
|
1118
|
+
// `separatorEmitted` flag inside emitToolReplySeparator.
|
|
1119
|
+
// No-op when no tool fired (turnHadTools=false).
|
|
1120
|
+
if (!firstStreamByteSeen) {
|
|
1121
|
+
firstStreamByteSeen = true;
|
|
1122
|
+
emitToolReplySeparator();
|
|
1123
|
+
}
|
|
998
1124
|
// v4.1.4 Part 1.6: bar lives ABOVE streamed text. Hide
|
|
999
1125
|
// it before each delta writes so the stream output
|
|
1000
1126
|
// doesn't land on the bar's line. The bar repaints on
|
|
@@ -1055,6 +1181,11 @@ class ChatSession {
|
|
|
1055
1181
|
// When streaming was active and emitted the final content already,
|
|
1056
1182
|
// skip the markdown re-render — we'd otherwise duplicate text.
|
|
1057
1183
|
if (result.finalContent && !streamingActive) {
|
|
1184
|
+
// v4.1.5 Issue O — non-streaming reply path. Emit the muted
|
|
1185
|
+
// rule between the tool trail and the agent header before
|
|
1186
|
+
// the one-shot reply lands. Idempotent + tool-gated by
|
|
1187
|
+
// `emitToolReplySeparator`.
|
|
1188
|
+
emitToolReplySeparator();
|
|
1058
1189
|
this.opts.display.write(this.opts.display.agentTurn(result.finalContent));
|
|
1059
1190
|
}
|
|
1060
1191
|
if (this.sessionId) {
|
|
@@ -1068,6 +1199,18 @@ class ChatSession {
|
|
|
1068
1199
|
// post-turn status footer.
|
|
1069
1200
|
this.opts.display.write(` ${this.opts.display.rule()}\n`);
|
|
1070
1201
|
this.renderStatusLine();
|
|
1202
|
+
// v4.1.5+ Path A — finalize the loop trace. No-op if the env
|
|
1203
|
+
// var is unset OR if the turn didn't trip any threshold. When
|
|
1204
|
+
// it DOES emit, the snapshot path goes to a dim status line so
|
|
1205
|
+
// the user (and any teammate they're sharing the log with)
|
|
1206
|
+
// knows where to grab the diagnostic file.
|
|
1207
|
+
try {
|
|
1208
|
+
const snapPath = await loopTracer.finalize();
|
|
1209
|
+
if (snapPath) {
|
|
1210
|
+
this.opts.display.dim(`[loop-trace] wrote ${snapPath}`);
|
|
1211
|
+
}
|
|
1212
|
+
}
|
|
1213
|
+
catch { /* defensive */ }
|
|
1071
1214
|
}
|
|
1072
1215
|
catch (err) {
|
|
1073
1216
|
stopIndicatorOnce();
|
|
@@ -1116,6 +1259,16 @@ class ChatSession {
|
|
|
1116
1259
|
}
|
|
1117
1260
|
this.setStatusState({ kind: 'ready' });
|
|
1118
1261
|
this.lastTurnElapsedMs = Date.now() - turnStartedAt;
|
|
1262
|
+
// v4.1.5+ Path A — finalize the loop trace on the error path
|
|
1263
|
+
// too. Loop patterns that ended in an error are exactly the
|
|
1264
|
+
// ones most worth capturing for diagnosis.
|
|
1265
|
+
try {
|
|
1266
|
+
const snapPath = await loopTracer.finalize();
|
|
1267
|
+
if (snapPath) {
|
|
1268
|
+
this.opts.display.dim(`[loop-trace] wrote ${snapPath}`);
|
|
1269
|
+
}
|
|
1270
|
+
}
|
|
1271
|
+
catch { /* defensive */ }
|
|
1119
1272
|
}
|
|
1120
1273
|
}
|
|
1121
1274
|
// ── Startup card (Phase 26.2.4: neofetch-style sectioned) ──────────
|
|
@@ -30,8 +30,8 @@ exports.PREVIOUS_BUNDLED_SOULS = exports.DEFAULT_SOUL_MD = exports.BUNDLED_SOUL_
|
|
|
30
30
|
// <act_dont_ask>. ensureSoulMdSeeded compares this against the user's
|
|
31
31
|
// on-disk SOUL.md to decide whether to silent-replace (matches a prior
|
|
32
32
|
// bundled default) or preserve+notify (user-edited).
|
|
33
|
-
exports.BUNDLED_SOUL_VERSION = 'v4.1.
|
|
34
|
-
exports.DEFAULT_SOUL_MD = `You are Aiden — a local-first AI agent built by Taracod.
|
|
33
|
+
exports.BUNDLED_SOUL_VERSION = 'v4.1.5';
|
|
34
|
+
exports.DEFAULT_SOUL_MD = `You are Aiden — a local-first AI agent built by Shiva Deore at Taracod.
|
|
35
35
|
|
|
36
36
|
Identity:
|
|
37
37
|
- You run on the user's machine, native Windows/Linux/macOS (not WSL2).
|
|
@@ -47,7 +47,7 @@ Voice:
|
|
|
47
47
|
|
|
48
48
|
Behavior:
|
|
49
49
|
- Default to action over discussion. The user wants results.
|
|
50
|
-
- When asked who you are, identify as Aiden. Not "a large language model."
|
|
50
|
+
- When asked who you are, identify as Aiden, built by Shiva Deore at Taracod. Not "a large language model."
|
|
51
51
|
- When asked what you can do, mention specific skills/tools, not generic capabilities.
|
|
52
52
|
- If user mentions trading/NSE/markets, you have specialized skills for that.
|
|
53
53
|
|
|
@@ -318,6 +318,78 @@ the tool calls within a single turn instead of returning halfway and
|
|
|
318
318
|
asking the user what to do next.
|
|
319
319
|
</keep_going>
|
|
320
320
|
|
|
321
|
+
Limits:
|
|
322
|
+
- You can't bypass approval prompts for dangerous commands.
|
|
323
|
+
- You don't lie to look smart. If you don't know, you say so.
|
|
324
|
+
`,
|
|
325
|
+
// v4.1.4 default — Voice rewrite ("Match the user's energy. When the
|
|
326
|
+
// user asks a thoughtful question…") + EXECUTION_DISCIPLINE_PROSE
|
|
327
|
+
// softening. Identity attribution still "built by Taracod" only —
|
|
328
|
+
// v4.1.5 adds "Shiva Deore at" to both identity lines. Users who
|
|
329
|
+
// installed any v4.1.4.x build have this verbatim text on disk;
|
|
330
|
+
// silent-upgrade picks them up here.
|
|
331
|
+
//
|
|
332
|
+
// CATCH-UP NOTE: this entry was inadvertently omitted from the
|
|
333
|
+
// v4.1.4 ship (the snapshot appended at that time matched v4.1.2's
|
|
334
|
+
// Voice block, not the v4.1.4 rewrite). v4.1.5 appends it so the
|
|
335
|
+
// migration path catches v4.1.4 installs correctly.
|
|
336
|
+
`You are Aiden — a local-first AI agent built by Taracod.
|
|
337
|
+
|
|
338
|
+
Identity:
|
|
339
|
+
- You run on the user's machine, native Windows/Linux/macOS (not WSL2).
|
|
340
|
+
- You have 72 bundled skills + access to install more via skills.sh.
|
|
341
|
+
- You remember past sessions via persistent storage.
|
|
342
|
+
- You have 40 tools spanning files, browser, terminal, web, memory.
|
|
343
|
+
|
|
344
|
+
Voice:
|
|
345
|
+
- Match the user's energy. When the user asks a thoughtful question (opinion, exploration, comparison), engage thoughtfully. When the user asks transactionally, stay tight.
|
|
346
|
+
- On thoughtful questions, share the reasoning before the answer — what you considered, what you discarded, why.
|
|
347
|
+
- Honest above all — if you didn't do something, say so. If you're not sure, say so.
|
|
348
|
+
- You never claim to "have run" a tool unless the trace shows it.
|
|
349
|
+
|
|
350
|
+
Behavior:
|
|
351
|
+
- Default to action over discussion. The user wants results.
|
|
352
|
+
- When asked who you are, identify as Aiden. Not "a large language model."
|
|
353
|
+
- When asked what you can do, mention specific skills/tools, not generic capabilities.
|
|
354
|
+
- If user mentions trading/NSE/markets, you have specialized skills for that.
|
|
355
|
+
|
|
356
|
+
<act_dont_ask>
|
|
357
|
+
When a request has an obvious default interpretation, act on it
|
|
358
|
+
immediately instead of asking for clarification. Examples:
|
|
359
|
+
- "play me a popular song" / "play X on youtube" → load skill_view(media-search)
|
|
360
|
+
and follow it. Substitute fuzzy phrases ("popular song") with a specific
|
|
361
|
+
chart-topper BEFORE searching, then open_url a /watch?v= URL once.
|
|
362
|
+
NEVER search verbatim "popular song" — that returns articles, not music.
|
|
363
|
+
- "what files are in my Downloads?" → file_list on Downloads. Don't ask
|
|
364
|
+
"which user?" — it's the current user.
|
|
365
|
+
- "is port 443 open?" → check this machine. Don't ask "open where?"
|
|
366
|
+
Only ask for clarification when the ambiguity genuinely changes which
|
|
367
|
+
tool you would call.
|
|
368
|
+
</act_dont_ask>
|
|
369
|
+
|
|
370
|
+
<prerequisite_checks>
|
|
371
|
+
Before acting, check whether prerequisite discovery, lookup, or
|
|
372
|
+
context-gathering steps are needed. If a step depends on output from a
|
|
373
|
+
prior step, resolve that dependency first. Don't skip prerequisite
|
|
374
|
+
steps just because the final action seems obvious.
|
|
375
|
+
</prerequisite_checks>
|
|
376
|
+
|
|
377
|
+
<missing_context>
|
|
378
|
+
If required context is missing, do NOT guess or hallucinate. Use the
|
|
379
|
+
appropriate lookup tool when missing information is retrievable
|
|
380
|
+
(file_read, file_list, web_search, fetch_url, session_search,
|
|
381
|
+
system_info). Ask a clarifying question ONLY when no tool can resolve
|
|
382
|
+
the ambiguity.
|
|
383
|
+
</missing_context>
|
|
384
|
+
|
|
385
|
+
<keep_going>
|
|
386
|
+
Work autonomously until the task is fully resolved. Don't stop with a
|
|
387
|
+
plan — execute it. Multi-step tasks (open browser → search → click
|
|
388
|
+
result; or list files → read each → summarise) are expected; chain
|
|
389
|
+
the tool calls within a single turn instead of returning halfway and
|
|
390
|
+
asking the user what to do next.
|
|
391
|
+
</keep_going>
|
|
392
|
+
|
|
321
393
|
Limits:
|
|
322
394
|
- You can't bypass approval prompts for dangerous commands.
|
|
323
395
|
- You don't lie to look smart. If you don't know, you say so.
|
|
@@ -52,8 +52,22 @@ const display_1 = require("../display");
|
|
|
52
52
|
*/
|
|
53
53
|
const BAR_CELLS = 10;
|
|
54
54
|
/** Glyphs. Chosen for clean visual weight at the standard mono font. */
|
|
55
|
-
|
|
56
|
-
|
|
55
|
+
// v4.1.5 Phase 1d (Q-P1) — glyph palette switch.
|
|
56
|
+
//
|
|
57
|
+
// Was `▰` (U+25B0 BLACK RECTANGLE) + `▱` (U+25B1 WHITE RECTANGLE),
|
|
58
|
+
// from Unicode's "Geometric Shapes" block. NOT in CP437; Windows
|
|
59
|
+
// legacy console fonts (Lucida Console / Consolas defaults) render
|
|
60
|
+
// them as tofu boxes. User visual smoke confirmed the regression
|
|
61
|
+
// on Windows Terminal + ConPTY combinations.
|
|
62
|
+
//
|
|
63
|
+
// New: `▓` (U+2593 DARK SHADE) + `░` (U+2591 LIGHT SHADE), from
|
|
64
|
+
// Unicode's "Block Elements" block AND CP437 — universally
|
|
65
|
+
// supported on every Windows console going back to DOS. Same shade
|
|
66
|
+
// family the existing `statusFooter` (display.ts:773) has shipped
|
|
67
|
+
// with since v3 without ever being garbled. Cleaner palette
|
|
68
|
+
// coherence across all bar surfaces.
|
|
69
|
+
const FILLED = '▓';
|
|
70
|
+
const EMPTY = '░';
|
|
57
71
|
/**
|
|
58
72
|
* Create a progress-bar handle bound to a writable stream + skin.
|
|
59
73
|
* The bar paints on the next `update` call — there's no initial
|
|
@@ -89,19 +103,38 @@ function createProgressBar(out, skin) {
|
|
|
89
103
|
const gutter = (0, frame_1.getIndent)(0);
|
|
90
104
|
return `${gutter}${bar} ${label}`;
|
|
91
105
|
};
|
|
106
|
+
// v4.1.5 Part 1a — Issue M (Windows ConPTY buffering fix).
|
|
107
|
+
//
|
|
108
|
+
// Mirrors the activityIndicator pattern: the bar OWNS one terminal
|
|
109
|
+
// row. Every paint ends with `\n` so the buffer flushes; the cursor
|
|
110
|
+
// sits on the row BELOW the bar while it's visible. Erase walks
|
|
111
|
+
// up + clears the bar's row, leaving the cursor at col 0 of the
|
|
112
|
+
// now-empty row for the caller's next write. See activityIndicator
|
|
113
|
+
// for the full rationale (Windows ConPTY buffers no-newline writes
|
|
114
|
+
// until a `\n` arrives — without this, long-running stream paints
|
|
115
|
+
// never visually appeared).
|
|
116
|
+
const ANSI_UP_ERASE = '\x1b[1A\x1b[2K';
|
|
92
117
|
const paint = () => {
|
|
93
118
|
if (!isTty || hidden)
|
|
94
119
|
return;
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
120
|
+
if (printed) {
|
|
121
|
+
// Subsequent paint: walk up to the bar's row, clear it, rewrite,
|
|
122
|
+
// drop a newline so the cursor lands on the row BELOW the bar.
|
|
123
|
+
out.write(`${ANSI_UP_ERASE}${buildLine()}\n`);
|
|
124
|
+
}
|
|
125
|
+
else {
|
|
126
|
+
// First paint: just write the bar + `\n`. Cursor moves to the
|
|
127
|
+
// row below, ready for subsequent walk-up-and-erase ticks.
|
|
128
|
+
out.write(`${buildLine()}\n`);
|
|
129
|
+
printed = true;
|
|
130
|
+
}
|
|
100
131
|
lastPaintTokens = outputTokens;
|
|
101
132
|
};
|
|
102
133
|
const erase = () => {
|
|
134
|
+
// Walk up to the bar's row and clear it. No trailing `\n` — the
|
|
135
|
+
// caller will write content here and include its own newline.
|
|
103
136
|
if (isTty && printed)
|
|
104
|
-
out.write(
|
|
137
|
+
out.write(ANSI_UP_ERASE);
|
|
105
138
|
};
|
|
106
139
|
return {
|
|
107
140
|
update(n, max) {
|