aiden-runtime 4.1.1 → 4.1.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/README.md +78 -26
- package/dist/cli/v4/aidenCLI.js +159 -9
- package/dist/cli/v4/callbacks.js +5 -2
- package/dist/cli/v4/chatSession.js +525 -15
- package/dist/cli/v4/commands/auth.js +6 -3
- package/dist/cli/v4/commands/help.js +4 -0
- package/dist/cli/v4/commands/index.js +10 -1
- package/dist/cli/v4/commands/reloadSoul.js +37 -0
- package/dist/cli/v4/commands/update.js +102 -0
- package/dist/cli/v4/defaultSoul.js +68 -2
- package/dist/cli/v4/display.js +28 -10
- package/dist/cli/v4/doctor.js +112 -0
- package/dist/cli/v4/doctorLiveness.js +65 -10
- package/dist/cli/v4/promotionPrompt.js +202 -0
- package/dist/cli/v4/providerBootSelector.js +144 -0
- package/dist/cli/v4/sessionSummaryGate.js +66 -0
- package/dist/cli/v4/toolPreview.js +139 -0
- package/dist/core/v4/aidenAgent.js +91 -29
- package/dist/core/v4/capabilities.js +89 -0
- package/dist/core/v4/contextCompressor.js +25 -8
- package/dist/core/v4/distillationIndex.js +167 -0
- package/dist/core/v4/distillationStore.js +98 -0
- package/dist/core/v4/logger/logger.js +40 -9
- package/dist/core/v4/promotionCandidates.js +234 -0
- package/dist/core/v4/promptBuilder.js +145 -1
- package/dist/core/v4/sessionDistiller.js +405 -0
- package/dist/core/v4/skillMining/skillMiner.js +43 -6
- package/dist/core/v4/skillOutcomeTracker.js +323 -0
- package/dist/core/v4/subsystemHealth.js +143 -0
- package/dist/core/v4/update/executeInstall.js +233 -0
- package/dist/core/version.js +1 -1
- package/dist/moat/memoryGuard.js +111 -0
- package/dist/moat/skillTeacher.js +14 -5
- package/dist/providers/v4/chatCompletionsAdapter.js +9 -0
- package/dist/providers/v4/errors.js +20 -4
- package/dist/providers/v4/modelDefaults.js +65 -0
- package/dist/providers/v4/registry.js +9 -2
- package/dist/providers/v4/runtimeResolver.js +6 -0
- package/dist/tools/v4/index.js +57 -1
- package/dist/tools/v4/memory/memoryRemove.js +57 -2
- package/dist/tools/v4/memory/sessionSummary.js +151 -0
- package/dist/tools/v4/sessions/recallSession.js +163 -0
- package/dist/tools/v4/sessions/sessionSearch.js +5 -1
- package/dist/tools/v4/system/_psHelpers.js +55 -0
- package/dist/tools/v4/system/aidenSelfUpdate.js +162 -0
- package/dist/tools/v4/system/appClose.js +79 -0
- package/dist/tools/v4/system/appLaunch.js +92 -0
- package/dist/tools/v4/system/clipboardRead.js +54 -0
- package/dist/tools/v4/system/clipboardWrite.js +84 -0
- package/dist/tools/v4/system/mediaKey.js +78 -0
- package/dist/tools/v4/system/osProcessList.js +99 -0
- package/dist/tools/v4/system/screenshot.js +106 -0
- package/dist/tools/v4/system/volumeSet.js +157 -0
- package/package.json +4 -1
- package/skills/system_control.md +135 -69
package/dist/core/version.js
CHANGED
package/dist/moat/memoryGuard.js
CHANGED
|
@@ -31,6 +31,7 @@
|
|
|
31
31
|
*/
|
|
32
32
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
33
33
|
exports.MemoryGuard = void 0;
|
|
34
|
+
exports.containsInSection = containsInSection;
|
|
34
35
|
class MemoryGuard {
|
|
35
36
|
constructor(memory) {
|
|
36
37
|
this.memory = memory;
|
|
@@ -113,6 +114,75 @@ class MemoryGuard {
|
|
|
113
114
|
}
|
|
114
115
|
return { ok: true, verified: true, fileLength: text.length };
|
|
115
116
|
}
|
|
117
|
+
/**
|
|
118
|
+
* Phase v4.1.2 alive-core: section-aware write. Replaces the body of
|
|
119
|
+
* a markdown `## <header>` section, creating the section at file end
|
|
120
|
+
* if it doesn't yet exist. Body lines below the header up to the
|
|
121
|
+
* next `## ` (or EOF) are replaced wholesale.
|
|
122
|
+
*
|
|
123
|
+
* Preserves the standard verify-on-disk contract: the post-write read
|
|
124
|
+
* confirms `newBody` is present and (when applicable) the previous
|
|
125
|
+
* section body is gone before returning `verified: true`.
|
|
126
|
+
*
|
|
127
|
+
* Additive — does not change `guardedAdd` / `guardedReplace` /
|
|
128
|
+
* `guardedRemove` semantics.
|
|
129
|
+
*/
|
|
130
|
+
async replaceSection(file, header, newBody) {
|
|
131
|
+
const headerTrim = header.trim();
|
|
132
|
+
if (!headerTrim.startsWith('## ')) {
|
|
133
|
+
return {
|
|
134
|
+
ok: false,
|
|
135
|
+
verified: false,
|
|
136
|
+
reason: 'header must start with "## " (markdown h2)',
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
const bodyTrim = newBody.trim();
|
|
140
|
+
if (!bodyTrim) {
|
|
141
|
+
return {
|
|
142
|
+
ok: false,
|
|
143
|
+
verified: false,
|
|
144
|
+
reason: 'newBody cannot be empty. Use guardedRemove() to drop a section.',
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
// Read current file state so we can compute the precise old block.
|
|
148
|
+
const snapBefore = await this.memory.loadSnapshot();
|
|
149
|
+
const before = pickFile(snapBefore, file);
|
|
150
|
+
// Match `<header>` and everything below it up to the next `## `
|
|
151
|
+
// line or EOF. No `m` flag — we want `$` to mean end-of-string;
|
|
152
|
+
// with `m`, the trailing-`$` lookahead would match at every line
|
|
153
|
+
// ending and chop off all but the first body line.
|
|
154
|
+
const escapedHeader = headerTrim.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
155
|
+
const sectionRe = new RegExp(`${escapedHeader}[^\\n]*(?:\\r?\\n[\\s\\S]*?)?(?=\\n## |$)`);
|
|
156
|
+
const match = before.match(sectionRe);
|
|
157
|
+
const newSection = `${headerTrim}\n${bodyTrim}`;
|
|
158
|
+
let mutation;
|
|
159
|
+
if (match && match[0]) {
|
|
160
|
+
mutation = await this.memory.replace(file, match[0], newSection);
|
|
161
|
+
}
|
|
162
|
+
else {
|
|
163
|
+
// Section doesn't exist — append at end with a blank-line gap.
|
|
164
|
+
const sep = before.length > 0 && !before.endsWith('\n') ? '\n\n' : '\n';
|
|
165
|
+
mutation = await this.memory.add(file, `${sep}${newSection}`);
|
|
166
|
+
}
|
|
167
|
+
if (!mutation.ok) {
|
|
168
|
+
return {
|
|
169
|
+
ok: false,
|
|
170
|
+
verified: false,
|
|
171
|
+
reason: mutation.reason ?? 'section write failed',
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
const snapAfter = await this.memory.loadSnapshot();
|
|
175
|
+
const after = pickFile(snapAfter, file);
|
|
176
|
+
if (!after.includes(headerTrim) || !after.includes(bodyTrim)) {
|
|
177
|
+
return {
|
|
178
|
+
ok: false,
|
|
179
|
+
verified: false,
|
|
180
|
+
reason: 'Section write claimed but header/body not found post-write',
|
|
181
|
+
fileLength: after.length,
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
return { ok: true, verified: true, fileLength: after.length };
|
|
185
|
+
}
|
|
116
186
|
async guardedRemove(file, text) {
|
|
117
187
|
const trimmed = text.trim();
|
|
118
188
|
if (!trimmed) {
|
|
@@ -144,3 +214,44 @@ exports.MemoryGuard = MemoryGuard;
|
|
|
144
214
|
function pickFile(snap, file) {
|
|
145
215
|
return file === 'user' ? snap.userMd : snap.memoryMd;
|
|
146
216
|
}
|
|
217
|
+
/**
|
|
218
|
+
* Phase v4.1.2-bug-X: section-aware containment check.
|
|
219
|
+
*
|
|
220
|
+
* Returns `true` if `target` appears anywhere within the body of the
|
|
221
|
+
* section identified by `sectionHeader` (e.g. `"## Durable facts"`).
|
|
222
|
+
* The section body runs from the line after the header to the line
|
|
223
|
+
* before the next `## ` header — or end-of-file, whichever comes
|
|
224
|
+
* first. Returns `false` when the section doesn't exist OR when the
|
|
225
|
+
* target sits outside it.
|
|
226
|
+
*
|
|
227
|
+
* Pure: no I/O, deterministic from inputs. Used by `memory_remove`
|
|
228
|
+
* to protect user-approved durable facts from autonomous deletion:
|
|
229
|
+
* the model proposed substring-match against MEMORY.md, but
|
|
230
|
+
* substring removal operates whole-file — partial protection would
|
|
231
|
+
* still nuke the durable copy as side-effect. STRICT containment
|
|
232
|
+
* (rejects if the substring appears ANYWHERE in the section body)
|
|
233
|
+
* is the honest guard.
|
|
234
|
+
*
|
|
235
|
+
* Case-sensitive: matches the existing `guardedRemove` semantics
|
|
236
|
+
* which use `String.prototype.includes` directly on the raw content.
|
|
237
|
+
*
|
|
238
|
+
* @param fileContent Full file content (e.g. MEMORY.md as one string).
|
|
239
|
+
* @param target Substring the caller intends to remove.
|
|
240
|
+
* @param sectionHeader Header line including the `## ` prefix.
|
|
241
|
+
*/
|
|
242
|
+
function containsInSection(fileContent, target, sectionHeader) {
|
|
243
|
+
if (!fileContent || !target || !sectionHeader)
|
|
244
|
+
return false;
|
|
245
|
+
const headerEscaped = sectionHeader.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
246
|
+
// Match the header line, then capture the body until the next `## `
|
|
247
|
+
// (any h2) or end-of-string. No `m` flag — the trailing-`$` would
|
|
248
|
+
// otherwise match every line ending and chop the body at the first
|
|
249
|
+
// newline (the same trap the slice2 sessionSummary regex already
|
|
250
|
+
// documents).
|
|
251
|
+
const sectionRe = new RegExp(`${headerEscaped}[^\\n]*\\n([\\s\\S]*?)(?=\\n## |$)`);
|
|
252
|
+
const m = fileContent.match(sectionRe);
|
|
253
|
+
if (!m)
|
|
254
|
+
return false;
|
|
255
|
+
const body = m[1] ?? '';
|
|
256
|
+
return body.includes(target);
|
|
257
|
+
}
|
|
@@ -97,7 +97,7 @@ class SkillTeacher {
|
|
|
97
97
|
/** Optional handler-resolver to look up toolset metadata for trace
|
|
98
98
|
* entries that don't carry their own toolset. Used for the 2-toolset
|
|
99
99
|
* diversity check. */
|
|
100
|
-
resolveHandler) {
|
|
100
|
+
resolveHandler, healthTracker) {
|
|
101
101
|
this.skillLoader = skillLoader;
|
|
102
102
|
this.skillManager = skillManager;
|
|
103
103
|
this.resolveHandler = resolveHandler;
|
|
@@ -107,6 +107,7 @@ class SkillTeacher {
|
|
|
107
107
|
this.qualityPath =
|
|
108
108
|
qualityFilePath ??
|
|
109
109
|
node_path_1.default.join(process.cwd(), '.aiden-skill-quality.json');
|
|
110
|
+
this.healthTracker = healthTracker;
|
|
110
111
|
}
|
|
111
112
|
setTier(tier) {
|
|
112
113
|
this.tier = tier;
|
|
@@ -203,9 +204,11 @@ class SkillTeacher {
|
|
|
203
204
|
name: proposal.proposedName,
|
|
204
205
|
content,
|
|
205
206
|
}, {});
|
|
207
|
+
this.healthTracker?.recordSuccess();
|
|
206
208
|
return { created: true, skillName: proposal.proposedName };
|
|
207
209
|
}
|
|
208
210
|
catch (e) {
|
|
211
|
+
this.healthTracker?.recordFailure(e);
|
|
209
212
|
const msg = e instanceof Error ? e.message : String(e);
|
|
210
213
|
return { created: false, reason: `create_failed: ${msg}` };
|
|
211
214
|
}
|
|
@@ -336,8 +339,11 @@ ${[...new Set(proposal.toolsUsed)].map((t) => `- ${t}`).join('\n')}
|
|
|
336
339
|
return this.qualityCache;
|
|
337
340
|
}
|
|
338
341
|
}
|
|
339
|
-
catch {
|
|
340
|
-
//
|
|
342
|
+
catch (e) {
|
|
343
|
+
// Phase v4.1.2-slice3: record corrupt-file / JSON parse / read
|
|
344
|
+
// failures into the health tracker. We still fall through to an
|
|
345
|
+
// empty cache so behavior is unchanged — telemetry is additive.
|
|
346
|
+
this.healthTracker?.recordFailure(e);
|
|
341
347
|
}
|
|
342
348
|
this.qualityCache = {};
|
|
343
349
|
return this.qualityCache;
|
|
@@ -346,8 +352,11 @@ ${[...new Set(proposal.toolsUsed)].map((t) => `- ${t}`).join('\n')}
|
|
|
346
352
|
try {
|
|
347
353
|
await node_fs_1.promises.writeFile(this.qualityPath, JSON.stringify(cache, null, 2), 'utf-8');
|
|
348
354
|
}
|
|
349
|
-
catch {
|
|
350
|
-
//
|
|
355
|
+
catch (e) {
|
|
356
|
+
// Phase v4.1.2-slice3: surface disk-write failures (EACCES,
|
|
357
|
+
// ENOSPC, EROFS) instead of silently dropping. Best-effort
|
|
358
|
+
// semantic preserved — we still return without throwing.
|
|
359
|
+
this.healthTracker?.recordFailure(e);
|
|
351
360
|
}
|
|
352
361
|
}
|
|
353
362
|
}
|
|
@@ -68,6 +68,7 @@ class ChatCompletionsAdapter {
|
|
|
68
68
|
this.timeoutMs = opts.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
69
69
|
this.maxRetries = opts.maxRetries ?? DEFAULT_MAX_RETRIES;
|
|
70
70
|
this.extraHeaders = opts.extraHeaders ?? {};
|
|
71
|
+
this.defaultExtraBody = opts.defaultExtraBody;
|
|
71
72
|
}
|
|
72
73
|
// ── Non-streaming ────────────────────────────────────────────────────
|
|
73
74
|
async call(input) {
|
|
@@ -127,6 +128,14 @@ class ChatCompletionsAdapter {
|
|
|
127
128
|
// the stream closes promptly and we get accurate token accounting.
|
|
128
129
|
body.stream_options = { include_usage: true };
|
|
129
130
|
}
|
|
131
|
+
// Phase v4.1.2-deepseek: merge order is base body → defaultExtraBody
|
|
132
|
+
// (model-mandated, from resolver lookup in MODEL_DEFAULTS) → per-call
|
|
133
|
+
// input.extraBody (caller). Per-call wins so a single request can
|
|
134
|
+
// override a default (e.g. disabling thinking on a probe). This
|
|
135
|
+
// matters because providers/v4/modelDefaults.ts sets thinking +
|
|
136
|
+
// reasoning_effort for deepseek-v4-pro on EVERY call.
|
|
137
|
+
if (this.defaultExtraBody)
|
|
138
|
+
Object.assign(body, this.defaultExtraBody);
|
|
130
139
|
if (input.extraBody)
|
|
131
140
|
Object.assign(body, input.extraBody);
|
|
132
141
|
return body;
|
|
@@ -19,10 +19,17 @@ exports.ProviderRateLimitError = exports.ProviderTimeoutError = exports.Provider
|
|
|
19
19
|
exports.formatRawForMessage = formatRawForMessage;
|
|
20
20
|
/**
|
|
21
21
|
* Format a raw response body for inclusion in the user-facing error
|
|
22
|
-
* message. Recognises
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
22
|
+
* message. Recognises three JSON envelope shapes and falls back to the
|
|
23
|
+
* raw string for plain-text bodies. Returns null when nothing useful is
|
|
24
|
+
* available so callers can omit the ": <detail>" tail entirely.
|
|
25
|
+
*
|
|
26
|
+
* Recognised envelopes (most-specific first):
|
|
27
|
+
* 1. OpenAI / Anthropic: `{ error: { message: "..." } }`
|
|
28
|
+
* 2. Top-level message: `{ message: "..." }`
|
|
29
|
+
* 3. Codex Responses: `{ detail: "..." }` (Phase v4.1.2-bug3 —
|
|
30
|
+
* surfaced by slice5: the Codex backend at chatgpt.com/backend-api/
|
|
31
|
+
* codex/responses returns 4xx bodies in this shape, e.g.
|
|
32
|
+
* `{"detail": "The 'gpt-5.1-codex-max' model is not supported..."}`)
|
|
26
33
|
*
|
|
27
34
|
* Truncates to 300 chars to keep multi-line responses from blowing
|
|
28
35
|
* up the user's terminal — full body remains on `error.raw` for
|
|
@@ -45,6 +52,15 @@ function formatRawForMessage(raw) {
|
|
|
45
52
|
if (typeof topMsg === 'string' && topMsg.length > 0) {
|
|
46
53
|
return topMsg.length > 300 ? `${topMsg.slice(0, 300)}…` : topMsg;
|
|
47
54
|
}
|
|
55
|
+
// Codex Responses envelope: { detail: "..." }. Distinct from the
|
|
56
|
+
// OpenAI shape — the Codex backend uses FastAPI-style validation
|
|
57
|
+
// errors that surface as `detail` (str) for tier/auth rejections
|
|
58
|
+
// and `detail: [{...}]` for schema errors. Only the string form is
|
|
59
|
+
// useful in the message tail; the array form is left to .raw.
|
|
60
|
+
const detail = raw.detail;
|
|
61
|
+
if (typeof detail === 'string' && detail.length > 0) {
|
|
62
|
+
return detail.length > 300 ? `${detail.slice(0, 300)}…` : detail;
|
|
63
|
+
}
|
|
48
64
|
return null;
|
|
49
65
|
}
|
|
50
66
|
// Plain string body.
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Copyright (c) 2026 Shiva Deore (Taracod).
|
|
4
|
+
* Licensed under AGPL-3.0. See LICENSE for details.
|
|
5
|
+
*
|
|
6
|
+
* Aiden — local-first agent.
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* providers/v4/modelDefaults.ts — Phase v4.1.2-deepseek.
|
|
10
|
+
*
|
|
11
|
+
* Per-model default request parameters. Keyed by `${providerId}:${modelId}`
|
|
12
|
+
* so the same model slug appearing under multiple providers doesn't
|
|
13
|
+
* collide (e.g. a future shared-slug case across compat endpoints).
|
|
14
|
+
*
|
|
15
|
+
* Today's only consumer:
|
|
16
|
+
* deepseek:deepseek-v4-pro → always send extra_body.thinking +
|
|
17
|
+
* reasoning_effort, per DeepSeek's V4-Pro API guidance:
|
|
18
|
+
*
|
|
19
|
+
* client.chat.completions.create(
|
|
20
|
+
* model="deepseek-v4-pro",
|
|
21
|
+
* messages=...,
|
|
22
|
+
* reasoning_effort="high",
|
|
23
|
+
* extra_body={"thinking": {"type": "enabled"}},
|
|
24
|
+
* )
|
|
25
|
+
*
|
|
26
|
+
* The defaults are merged into the wire body by ChatCompletionsAdapter:
|
|
27
|
+
* base body → defaultExtraBody (from this map) → per-call extraBody
|
|
28
|
+
* (from the caller's ProviderCallInput)
|
|
29
|
+
*
|
|
30
|
+
* Per-call extraBody wins so a caller can disable thinking on a single
|
|
31
|
+
* request without un-registering the model default.
|
|
32
|
+
*
|
|
33
|
+
* Adding a new entry: keep this file small. Per-model knowledge lives
|
|
34
|
+
* here so resolver / registry / adapter stay pure (credential
|
|
35
|
+
* resolution / provider facts / wire-format mechanics respectively).
|
|
36
|
+
*/
|
|
37
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
38
|
+
exports.MODEL_DEFAULTS = void 0;
|
|
39
|
+
exports.getModelDefaults = getModelDefaults;
|
|
40
|
+
/**
|
|
41
|
+
* Per-`${providerId}:${modelId}` defaults. `undefined` lookup means
|
|
42
|
+
* the model takes no special handling.
|
|
43
|
+
*/
|
|
44
|
+
exports.MODEL_DEFAULTS = Object.freeze({
|
|
45
|
+
// DeepSeek V4 Pro — thinking-mode flagship.
|
|
46
|
+
// Reference: https://api-docs.deepseek.com/ (verified 2026-05).
|
|
47
|
+
// deepseek-v4-flash exists too but is not wired this slice; its
|
|
48
|
+
// legacy aliases (deepseek-chat = v4-flash non-think,
|
|
49
|
+
// deepseek-reasoner = v4-flash think) stay un-defaulted to preserve
|
|
50
|
+
// the existing pass-through behavior for users who explicitly
|
|
51
|
+
// selected them.
|
|
52
|
+
'deepseek:deepseek-v4-pro': {
|
|
53
|
+
extraBody: {
|
|
54
|
+
thinking: { type: 'enabled' },
|
|
55
|
+
reasoning_effort: 'high',
|
|
56
|
+
},
|
|
57
|
+
},
|
|
58
|
+
});
|
|
59
|
+
/**
|
|
60
|
+
* Look up defaults for a (provider, model) pair. Returns `undefined`
|
|
61
|
+
* when no entry exists — caller skips the extraBody merge.
|
|
62
|
+
*/
|
|
63
|
+
function getModelDefaults(providerId, modelId) {
|
|
64
|
+
return exports.MODEL_DEFAULTS[`${providerId}:${modelId}`];
|
|
65
|
+
}
|
|
@@ -232,12 +232,19 @@ exports.PROVIDER_REGISTRY = {
|
|
|
232
232
|
apiMode: 'chat_completions',
|
|
233
233
|
baseUrl: 'https://api.deepseek.com/v1',
|
|
234
234
|
apiKeyEnvVar: 'DEEPSEEK_API_KEY',
|
|
235
|
-
description: 'DeepSeek direct API —
|
|
235
|
+
description: 'DeepSeek direct API — V4 Pro reasoning flagship + legacy aliases.',
|
|
236
236
|
tier: 'paid',
|
|
237
237
|
hasFreeTier: false,
|
|
238
238
|
docsUrl: 'https://api-docs.deepseek.com/',
|
|
239
239
|
supportsToolCalling: true,
|
|
240
|
-
|
|
240
|
+
// Phase v4.1.2-deepseek: `deepseek-v4-pro` prepended as the new
|
|
241
|
+
// flagship — becomes the auto-pick default for new users via
|
|
242
|
+
// pickProbeModel(). Legacy `deepseek-chat` and `deepseek-reasoner`
|
|
243
|
+
// retained for back-compat (still functional aliases of the V4
|
|
244
|
+
// flash family per DeepSeek docs; deprecated-but-live). Removal
|
|
245
|
+
// is its own deprecation slice. Per-call thinking + reasoning
|
|
246
|
+
// _effort defaults for v4-pro live in providers/v4/modelDefaults.ts.
|
|
247
|
+
modelIds: ['deepseek-v4-pro', 'deepseek-chat', 'deepseek-reasoner'],
|
|
241
248
|
},
|
|
242
249
|
mistral: {
|
|
243
250
|
id: 'mistral',
|
|
@@ -39,6 +39,7 @@ const chatCompletionsAdapter_1 = require("./chatCompletionsAdapter");
|
|
|
39
39
|
const anthropicAdapter_1 = require("./anthropicAdapter");
|
|
40
40
|
const codexResponsesAdapter_1 = require("./codexResponsesAdapter");
|
|
41
41
|
const ollamaPromptToolsAdapter_1 = require("./ollamaPromptToolsAdapter");
|
|
42
|
+
const modelDefaults_1 = require("./modelDefaults");
|
|
42
43
|
const tokenStore_1 = require("../../core/v4/auth/tokenStore");
|
|
43
44
|
class RuntimeResolver {
|
|
44
45
|
constructor(credentialResolver) {
|
|
@@ -61,6 +62,11 @@ class RuntimeResolver {
|
|
|
61
62
|
model: model.id,
|
|
62
63
|
providerName: entry.id,
|
|
63
64
|
extraHeaders: entry.extraHeaders,
|
|
65
|
+
// Phase v4.1.2-deepseek: per-model body defaults (e.g.
|
|
66
|
+
// DeepSeek V4-Pro's mandatory thinking + reasoning_effort).
|
|
67
|
+
// Undefined for models without registered defaults — adapter
|
|
68
|
+
// skips the merge in that case.
|
|
69
|
+
defaultExtraBody: (0, modelDefaults_1.getModelDefaults)(entry.id, model.id)?.extraBody,
|
|
64
70
|
});
|
|
65
71
|
case 'anthropic_messages':
|
|
66
72
|
if (!credentials.apiKey) {
|
package/dist/tools/v4/index.js
CHANGED
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
* Status: PHASE 8.
|
|
22
22
|
*/
|
|
23
23
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
24
|
-
exports.memoryRemoveTool = exports.memoryReplaceTool = exports.memoryAddTool = exports.processWaitTool = exports.processKillTool = exports.processLogReadTool = exports.processListTool = exports.processSpawnTool = exports.executeCodeTool = exports.shellExecTool = exports.naturalEventsTool = exports.nowPlayingTool = exports.systemInfoTool = exports.makeLookupToolSchema = exports.skillManageTool = exports.skillViewTool = exports.skillsListTool = exports.sessionListTool = exports.sessionSearchTool = exports.browserCloseTool = exports.browserScrollTool = exports.browserFillTool = exports.browserTypeTool = exports.browserClickTool = exports.browserNavigateTool = exports.browserGetUrlTool = exports.browserExtractTool = exports.browserScreenshotTool = exports.fileCopyTool = exports.fileMoveTool = exports.fileDeleteTool = exports.filePatchTool = exports.fileWriteTool = exports.fileListTool = exports.fileReadTool = exports.deepResearchTool = exports.webPageTool = exports.webFetchTool = exports.webSearchTool = exports.makeSubagentFanoutTool = void 0;
|
|
24
|
+
exports.sessionSummaryTool = exports.memoryRemoveTool = exports.memoryReplaceTool = exports.memoryAddTool = exports.processWaitTool = exports.processKillTool = exports.processLogReadTool = exports.processListTool = exports.processSpawnTool = exports.executeCodeTool = exports.shellExecTool = exports.clipboardWriteTool = exports.clipboardReadTool = exports.appCloseTool = exports.appLaunchTool = exports.volumeSetTool = exports.mediaKeyTool = exports.osProcessListTool = exports.screenshotTool = exports.naturalEventsTool = exports.nowPlayingTool = exports.systemInfoTool = exports.makeLookupToolSchema = exports.skillManageTool = exports.skillViewTool = exports.skillsListTool = exports.sessionListTool = exports.sessionSearchTool = exports.browserCloseTool = exports.browserScrollTool = exports.browserFillTool = exports.browserTypeTool = exports.browserClickTool = exports.browserNavigateTool = exports.browserGetUrlTool = exports.browserExtractTool = exports.browserScreenshotTool = exports.fileCopyTool = exports.fileMoveTool = exports.fileDeleteTool = exports.filePatchTool = exports.fileWriteTool = exports.fileListTool = exports.fileReadTool = exports.deepResearchTool = exports.webPageTool = exports.webFetchTool = exports.webSearchTool = exports.makeSubagentFanoutTool = void 0;
|
|
25
25
|
exports.registerReadOnlyTools = registerReadOnlyTools;
|
|
26
26
|
exports.registerWriteTools = registerWriteTools;
|
|
27
27
|
exports.registerAllTools = registerAllTools;
|
|
@@ -49,6 +49,7 @@ const browserScroll_1 = require("./browser/browserScroll");
|
|
|
49
49
|
const browserClose_1 = require("./browser/browserClose");
|
|
50
50
|
const sessionSearch_1 = require("./sessions/sessionSearch");
|
|
51
51
|
const sessionList_1 = require("./sessions/sessionList");
|
|
52
|
+
const recallSession_1 = require("./sessions/recallSession");
|
|
52
53
|
const skillsList_1 = require("./skills/skillsList");
|
|
53
54
|
const skillView_1 = require("./skills/skillView");
|
|
54
55
|
const skillManage_1 = require("./skills/skillManage");
|
|
@@ -56,6 +57,18 @@ const lookupToolSchema_1 = require("./skills/lookupToolSchema");
|
|
|
56
57
|
const systemInfo_1 = require("./system/systemInfo");
|
|
57
58
|
const nowPlaying_1 = require("./system/nowPlaying");
|
|
58
59
|
const naturalEvents_1 = require("./system/naturalEvents");
|
|
60
|
+
// Phase v4.1.2-followup-3 computer-control bundle.
|
|
61
|
+
const screenshot_1 = require("./system/screenshot");
|
|
62
|
+
const osProcessList_1 = require("./system/osProcessList");
|
|
63
|
+
const mediaKey_1 = require("./system/mediaKey");
|
|
64
|
+
const volumeSet_1 = require("./system/volumeSet");
|
|
65
|
+
const appLaunch_1 = require("./system/appLaunch");
|
|
66
|
+
const appClose_1 = require("./system/appClose");
|
|
67
|
+
const clipboardRead_1 = require("./system/clipboardRead");
|
|
68
|
+
const clipboardWrite_1 = require("./system/clipboardWrite");
|
|
69
|
+
// Phase v4.1.2-update — natural-language self-update entry point.
|
|
70
|
+
// Routes through the same shared executeInstall executor as `/update install`.
|
|
71
|
+
const aidenSelfUpdate_1 = require("./system/aidenSelfUpdate");
|
|
59
72
|
const shellExec_1 = require("./terminal/shellExec");
|
|
60
73
|
const executeCode_1 = require("./executeCode");
|
|
61
74
|
const processSpawn_1 = require("./process/processSpawn");
|
|
@@ -66,6 +79,7 @@ const processWait_1 = require("./process/processWait");
|
|
|
66
79
|
const memoryAdd_1 = require("./memory/memoryAdd");
|
|
67
80
|
const memoryReplace_1 = require("./memory/memoryReplace");
|
|
68
81
|
const memoryRemove_1 = require("./memory/memoryRemove");
|
|
82
|
+
const sessionSummary_1 = require("./memory/sessionSummary");
|
|
69
83
|
const subagentFanout_1 = require("./subagent/subagentFanout");
|
|
70
84
|
/**
|
|
71
85
|
* Register every read-only tool into `registry`. The
|
|
@@ -94,11 +108,21 @@ function registerReadOnlyTools(registry) {
|
|
|
94
108
|
registry.register(browserGetUrl_1.browserGetUrlTool);
|
|
95
109
|
registry.register(sessionSearch_1.sessionSearchTool);
|
|
96
110
|
registry.register(sessionList_1.sessionListTool);
|
|
111
|
+
// Phase v4.1.2-memory-C: recall_session reads SessionDistillation
|
|
112
|
+
// files written by Phase A+B. Sits alongside session_search — the
|
|
113
|
+
// two have distinct purposes (FTS5-over-messages vs ranked
|
|
114
|
+
// distillation summaries); descriptions force the right model
|
|
115
|
+
// choice.
|
|
116
|
+
registry.register(recallSession_1.recallSessionTool);
|
|
97
117
|
registry.register(skillsList_1.skillsListTool);
|
|
98
118
|
registry.register(skillView_1.skillViewTool);
|
|
99
119
|
registry.register(systemInfo_1.systemInfoTool);
|
|
100
120
|
registry.register(nowPlaying_1.nowPlayingTool);
|
|
101
121
|
registry.register(naturalEvents_1.naturalEventsTool);
|
|
122
|
+
// Phase v4.1.2-followup-3 — computer-control read-only tools.
|
|
123
|
+
registry.register(screenshot_1.screenshotTool);
|
|
124
|
+
registry.register(osProcessList_1.osProcessListTool);
|
|
125
|
+
registry.register(clipboardRead_1.clipboardReadTool);
|
|
102
126
|
registry.register((0, lookupToolSchema_1.makeLookupToolSchema)(registry));
|
|
103
127
|
// Phase v4.1-subagent — register a stub for subagent_fanout so its
|
|
104
128
|
// schema is visible to the agent loop, the MCP server, and the
|
|
@@ -158,9 +182,22 @@ function registerWriteTools(registry) {
|
|
|
158
182
|
registry.register(memoryAdd_1.memoryAddTool);
|
|
159
183
|
registry.register(memoryReplace_1.memoryReplaceTool);
|
|
160
184
|
registry.register(memoryRemove_1.memoryRemoveTool);
|
|
185
|
+
// Phase v4.1.2 alive-core: cross-session continuity via /quit auto-summary.
|
|
186
|
+
registry.register(sessionSummary_1.sessionSummaryTool);
|
|
161
187
|
// Phase 10: skill_manage — mutating, also goes through the approval
|
|
162
188
|
// engine. skills_list / skill_view stay in registerReadOnlyTools.
|
|
163
189
|
registry.register(skillManage_1.skillManageTool);
|
|
190
|
+
// Phase v4.1.2-update: natural-language entry to the same install
|
|
191
|
+
// executor that /update install uses. Two-step confirmation gate
|
|
192
|
+
// (confirm:false → status; confirm:true → install).
|
|
193
|
+
registry.register(aidenSelfUpdate_1.aidenSelfUpdateTool);
|
|
194
|
+
// Phase v4.1.2-followup-3 — computer-control mutating tools. All
|
|
195
|
+
// route through the approval engine like every other write.
|
|
196
|
+
registry.register(mediaKey_1.mediaKeyTool);
|
|
197
|
+
registry.register(volumeSet_1.volumeSetTool);
|
|
198
|
+
registry.register(appLaunch_1.appLaunchTool);
|
|
199
|
+
registry.register(appClose_1.appCloseTool);
|
|
200
|
+
registry.register(clipboardWrite_1.clipboardWriteTool);
|
|
164
201
|
}
|
|
165
202
|
/** Register every v4 tool. Most callers want this. */
|
|
166
203
|
function registerAllTools(registry) {
|
|
@@ -227,6 +264,23 @@ var nowPlaying_2 = require("./system/nowPlaying");
|
|
|
227
264
|
Object.defineProperty(exports, "nowPlayingTool", { enumerable: true, get: function () { return nowPlaying_2.nowPlayingTool; } });
|
|
228
265
|
var naturalEvents_2 = require("./system/naturalEvents");
|
|
229
266
|
Object.defineProperty(exports, "naturalEventsTool", { enumerable: true, get: function () { return naturalEvents_2.naturalEventsTool; } });
|
|
267
|
+
// Phase v4.1.2-followup-3 computer-control bundle exports.
|
|
268
|
+
var screenshot_2 = require("./system/screenshot");
|
|
269
|
+
Object.defineProperty(exports, "screenshotTool", { enumerable: true, get: function () { return screenshot_2.screenshotTool; } });
|
|
270
|
+
var osProcessList_2 = require("./system/osProcessList");
|
|
271
|
+
Object.defineProperty(exports, "osProcessListTool", { enumerable: true, get: function () { return osProcessList_2.osProcessListTool; } });
|
|
272
|
+
var mediaKey_2 = require("./system/mediaKey");
|
|
273
|
+
Object.defineProperty(exports, "mediaKeyTool", { enumerable: true, get: function () { return mediaKey_2.mediaKeyTool; } });
|
|
274
|
+
var volumeSet_2 = require("./system/volumeSet");
|
|
275
|
+
Object.defineProperty(exports, "volumeSetTool", { enumerable: true, get: function () { return volumeSet_2.volumeSetTool; } });
|
|
276
|
+
var appLaunch_2 = require("./system/appLaunch");
|
|
277
|
+
Object.defineProperty(exports, "appLaunchTool", { enumerable: true, get: function () { return appLaunch_2.appLaunchTool; } });
|
|
278
|
+
var appClose_2 = require("./system/appClose");
|
|
279
|
+
Object.defineProperty(exports, "appCloseTool", { enumerable: true, get: function () { return appClose_2.appCloseTool; } });
|
|
280
|
+
var clipboardRead_2 = require("./system/clipboardRead");
|
|
281
|
+
Object.defineProperty(exports, "clipboardReadTool", { enumerable: true, get: function () { return clipboardRead_2.clipboardReadTool; } });
|
|
282
|
+
var clipboardWrite_2 = require("./system/clipboardWrite");
|
|
283
|
+
Object.defineProperty(exports, "clipboardWriteTool", { enumerable: true, get: function () { return clipboardWrite_2.clipboardWriteTool; } });
|
|
230
284
|
var shellExec_2 = require("./terminal/shellExec");
|
|
231
285
|
Object.defineProperty(exports, "shellExecTool", { enumerable: true, get: function () { return shellExec_2.shellExecTool; } });
|
|
232
286
|
var executeCode_2 = require("./executeCode");
|
|
@@ -247,3 +301,5 @@ var memoryReplace_2 = require("./memory/memoryReplace");
|
|
|
247
301
|
Object.defineProperty(exports, "memoryReplaceTool", { enumerable: true, get: function () { return memoryReplace_2.memoryReplaceTool; } });
|
|
248
302
|
var memoryRemove_2 = require("./memory/memoryRemove");
|
|
249
303
|
Object.defineProperty(exports, "memoryRemoveTool", { enumerable: true, get: function () { return memoryRemove_2.memoryRemoveTool; } });
|
|
304
|
+
var sessionSummary_2 = require("./memory/sessionSummary");
|
|
305
|
+
Object.defineProperty(exports, "sessionSummaryTool", { enumerable: true, get: function () { return sessionSummary_2.sessionSummaryTool; } });
|
|
@@ -12,14 +12,37 @@
|
|
|
12
12
|
* Returns `verified: true` only after the post-write read confirms
|
|
13
13
|
* the text is gone from the file.
|
|
14
14
|
*
|
|
15
|
-
*
|
|
15
|
+
* Phase v4.1.2-bug-X: user-approved durable facts (anything in
|
|
16
|
+
* MEMORY.md `## Durable facts`) are protected from autonomous
|
|
17
|
+
* deletion. A subsequent session on a weak model (llama-3.3 in the
|
|
18
|
+
* smoke test) called memory_remove on a Phase-D-promoted fact with
|
|
19
|
+
* reasoning "outdated" — violating Phase D's opt-in trust contract.
|
|
20
|
+
*
|
|
21
|
+
* The guard is STRICT: if the requested substring appears ANYWHERE
|
|
22
|
+
* in the `## Durable facts` body, the call is rejected. Substring
|
|
23
|
+
* removal operates whole-file, so partial protection would still
|
|
24
|
+
* nuke the durable copy as side-effect. Hard rejection (vs propose-
|
|
25
|
+
* and-defer) is honest: model must surface to user; only the user
|
|
26
|
+
* (editing MEMORY.md directly, or via a future `/forget` slash
|
|
27
|
+
* command) can revoke durable content.
|
|
28
|
+
*
|
|
29
|
+
* Status: PHASE 9 (PHASE v4.1.2-bug-X: section protection).
|
|
16
30
|
*/
|
|
17
31
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
32
|
exports.memoryRemoveTool = void 0;
|
|
33
|
+
const memoryGuard_1 = require("../../../moat/memoryGuard");
|
|
34
|
+
/** Section in MEMORY.md that Phase D promotion writes to. */
|
|
35
|
+
const DURABLE_FACTS_HEADER = '## Durable facts';
|
|
19
36
|
exports.memoryRemoveTool = {
|
|
20
37
|
schema: {
|
|
21
38
|
name: 'memory_remove',
|
|
22
|
-
description: 'Remove an entry from MEMORY.md or USER.md by substring match.
|
|
39
|
+
description: 'Remove an entry from MEMORY.md or USER.md by substring match. ' +
|
|
40
|
+
'CANNOT remove entries in MEMORY.md `## Durable facts` — those are ' +
|
|
41
|
+
'user-approved facts the user explicitly promoted; only the user ' +
|
|
42
|
+
'can revoke them by editing MEMORY.md directly. If you think a ' +
|
|
43
|
+
'durable fact is outdated, surface that to the user and ask them ' +
|
|
44
|
+
'to confirm; do not propose autonomous removal. Returns ' +
|
|
45
|
+
'verified=true only after the change is confirmed on disk.',
|
|
23
46
|
inputSchema: {
|
|
24
47
|
type: 'object',
|
|
25
48
|
properties: {
|
|
@@ -42,6 +65,38 @@ exports.memoryRemoveTool = {
|
|
|
42
65
|
}
|
|
43
66
|
const file = args.file === 'user' ? 'user' : 'memory';
|
|
44
67
|
const text = String(args.text ?? '');
|
|
68
|
+
// Phase v4.1.2-bug-X: durable-section protection. Only applies
|
|
69
|
+
// to MEMORY.md (USER.md has no section structure today). The
|
|
70
|
+
// check requires snapshot access — when ctx.memory is not
|
|
71
|
+
// wired (test contexts, future surface refactors), we fall
|
|
72
|
+
// through to the existing guardedRemove behavior. Real CLI
|
|
73
|
+
// sessions wire memoryManager, so production paths get the
|
|
74
|
+
// guard. Documented intentional fall-through.
|
|
75
|
+
if (file === 'memory' && ctx.memory) {
|
|
76
|
+
try {
|
|
77
|
+
const snap = await ctx.memory.loadSnapshot();
|
|
78
|
+
const memoryMd = snap?.memoryMd ?? '';
|
|
79
|
+
if (memoryMd && (0, memoryGuard_1.containsInSection)(memoryMd, text, DURABLE_FACTS_HEADER)) {
|
|
80
|
+
const preview = text.length > 60
|
|
81
|
+
? `${text.slice(0, 60)}…`
|
|
82
|
+
: text;
|
|
83
|
+
return {
|
|
84
|
+
success: false,
|
|
85
|
+
verified: false,
|
|
86
|
+
error: `Cannot remove "${preview}" — it's in MEMORY.md ` +
|
|
87
|
+
`\`${DURABLE_FACTS_HEADER}\`, which holds user-approved facts. ` +
|
|
88
|
+
`Only the user can revoke these. Ask them to confirm removal ` +
|
|
89
|
+
`in their next message; do not propose autonomous deletion.`,
|
|
90
|
+
file,
|
|
91
|
+
protectedSection: DURABLE_FACTS_HEADER,
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
catch {
|
|
96
|
+
// Snapshot read failed — fall through to old behavior rather
|
|
97
|
+
// than block legitimate removals on transient I/O errors.
|
|
98
|
+
}
|
|
99
|
+
}
|
|
45
100
|
const r = await ctx.memoryGuard.guardedRemove(file, text);
|
|
46
101
|
return {
|
|
47
102
|
success: r.ok,
|