aegiscode 6.5.2 → 6.5.4
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/package.json +1 -1
- package/src/app.js +31 -2
- package/src/deps.js +9 -1
- package/vendor/desktop/lib/local/prompt.js +9 -2
- package/vendor/desktop/lib/local/tools.js +24 -39
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "aegiscode",
|
|
3
3
|
"productName": "AEGIS Code",
|
|
4
|
-
"version": "6.5.
|
|
4
|
+
"version": "6.5.4",
|
|
5
5
|
"description": "aegiscode \u2014 the command-line version of AEGIS Desktop. The shared tool surface in your shell, over the same thin transport and tool registry as the MCP plugin and the desktop app. Ships transport + UI only; no brain.",
|
|
6
6
|
"author": {
|
|
7
7
|
"name": "AEGIS Code",
|
package/src/app.js
CHANGED
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
const readline = require('node:readline');
|
|
22
22
|
const os = require('node:os');
|
|
23
23
|
const { randomUUID } = require('node:crypto');
|
|
24
|
-
const { createTools, createClient, usageTokens } = require('./deps.js');
|
|
24
|
+
const { createTools, createClient, usageTokens, buildSystemPrompt } = require('./deps.js');
|
|
25
25
|
const { createEngine } = require('./engine.js');
|
|
26
26
|
const { GLYPH, VERBS, themeOf, RESET, THEME_TABLE } = require('./theme.js');
|
|
27
27
|
const { LiveRegion, termWidth, w } = require('./screen.js');
|
|
@@ -41,6 +41,30 @@ const { fmtTokens, fmtEur, maskKey } = require('./format.js');
|
|
|
41
41
|
|
|
42
42
|
const VERSION = require('../package.json').version;
|
|
43
43
|
|
|
44
|
+
/**
|
|
45
|
+
* The persona for a turn this host did not get an explicit system prompt for.
|
|
46
|
+
*
|
|
47
|
+
* Built once and cached: it is the stable head of every request, and a prompt
|
|
48
|
+
* that changed between turns would defeat the provider's prompt cache for the
|
|
49
|
+
* whole conversation behind it.
|
|
50
|
+
*/
|
|
51
|
+
let _defaultSystem = null;
|
|
52
|
+
function defaultSystemPrompt() {
|
|
53
|
+
if (_defaultSystem === null) {
|
|
54
|
+
try {
|
|
55
|
+
_defaultSystem = buildSystemPrompt({
|
|
56
|
+
platform: process.platform,
|
|
57
|
+
arch: process.arch,
|
|
58
|
+
homedir: os.homedir(),
|
|
59
|
+
cwd: process.cwd(),
|
|
60
|
+
});
|
|
61
|
+
} catch {
|
|
62
|
+
_defaultSystem = ''; // never let persona construction break a turn
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
return _defaultSystem || undefined;
|
|
66
|
+
}
|
|
67
|
+
|
|
44
68
|
function createApp(options = {}) {
|
|
45
69
|
const opts = {
|
|
46
70
|
model: null,
|
|
@@ -458,7 +482,12 @@ function createApp(options = {}) {
|
|
|
458
482
|
prompt,
|
|
459
483
|
messages: history,
|
|
460
484
|
model: commandCtx.model || undefined,
|
|
461
|
-
system
|
|
485
|
+
// A caller-supplied system wins; otherwise the shared persona. Sent
|
|
486
|
+
// explicitly rather than left to the server, because the pooled
|
|
487
|
+
// route takes the system prompt from the request and the CLI was
|
|
488
|
+
// sending none — the model got tool schemas and no rule about when
|
|
489
|
+
// to use them.
|
|
490
|
+
system: opts.system || defaultSystemPrompt(),
|
|
462
491
|
maxTokens: opts.maxTokens,
|
|
463
492
|
// `effort` is the pooled budget control, and it travels on every turn
|
|
464
493
|
// — this host only ever runs the 'aegis' class, whose calls are sized
|
package/src/deps.js
CHANGED
|
@@ -59,12 +59,19 @@ const enginePath = resolveShared(path.join('desktop', 'lib', 'local', 'engine.js
|
|
|
59
59
|
// Subagent role presets (/agents lists these; the model's task tool delegates
|
|
60
60
|
// to them by name) — lives beside engine.js, staged into the same vendor dir.
|
|
61
61
|
const agentsPath = resolveShared(path.join('desktop', 'lib', 'local', 'agents.js'));
|
|
62
|
+
// The persona the tool loop runs under. The CLI sent NO system prompt at all,
|
|
63
|
+
// so a pooled turn reached the model as a bare user message plus tool schemas
|
|
64
|
+
// with nothing saying when a tool is appropriate — which is how "hey" started
|
|
65
|
+
// running shell commands. Same file as the GUI, for the same reason engine.js
|
|
66
|
+
// is: two personas would drift, and only one of them would get fixed.
|
|
67
|
+
const promptPath = resolveShared(path.join('desktop', 'lib', 'local', 'prompt.js'));
|
|
62
68
|
|
|
63
69
|
const { createClient } = require(clientPath);
|
|
64
70
|
const { createTools } = require(toolsPath);
|
|
65
71
|
const { usageTokens } = require(usagePath);
|
|
66
72
|
const { createLocalEngine } = require(enginePath);
|
|
67
73
|
const { agentRoles, agentRoleLabel } = require(agentsPath);
|
|
74
|
+
const { buildSystemPrompt } = require(promptPath);
|
|
68
75
|
|
|
69
76
|
module.exports = {
|
|
70
77
|
createClient,
|
|
@@ -73,6 +80,7 @@ module.exports = {
|
|
|
73
80
|
createLocalEngine,
|
|
74
81
|
agentRoles,
|
|
75
82
|
agentRoleLabel,
|
|
76
|
-
|
|
83
|
+
buildSystemPrompt,
|
|
84
|
+
paths: { client: clientPath, tools: toolsPath, usage: usagePath, engine: enginePath, agents: agentsPath, prompt: promptPath },
|
|
77
85
|
roots,
|
|
78
86
|
};
|
|
@@ -31,8 +31,15 @@ const MAIN_CHAT_PROMPT =
|
|
|
31
31
|
`- Use tools silently. A one-line reason is enough; do not narrate your plan as a story. ` +
|
|
32
32
|
`- Never claim what a tool found or what a command returned before the tool actually runs. ` +
|
|
33
33
|
` Report only the results you really received. ` +
|
|
34
|
-
`-
|
|
35
|
-
`
|
|
34
|
+
`- Match the response to the request. A greeting, a question about something you already ` +
|
|
35
|
+
` know, or a request for an opinion is answered in plain words with NO tools. Only reach ` +
|
|
36
|
+
` for a tool when the answer genuinely depends on something in this repo or on this ` +
|
|
37
|
+
` machine. "hey" is not a task.\n` +
|
|
38
|
+
`- WHEN THE USER HAS ASKED FOR WORK: act, don't just inspect. After at most 2 rounds of ` +
|
|
39
|
+
` reading or exploration, start making changes with writeFile or editFile. Reconnaissance ` +
|
|
40
|
+
` is not progress — implement, then verify. This rule is about HOW to carry out a task you ` +
|
|
41
|
+
` were given; it is never a reason to invent one. Never write or modify a file the user ` +
|
|
42
|
+
` did not ask you to touch.\n` +
|
|
36
43
|
`- When you have what you need, stop using tools and give a concise, direct answer to the ` +
|
|
37
44
|
` user's question. Never end your turn with an intention like "Let me check…" or "I'll now…" ` +
|
|
38
45
|
` — that is not an answer. ` +
|
|
@@ -81,14 +81,12 @@ const fail = (error) => ({ ok: false, error: cap(error) });
|
|
|
81
81
|
const SCHEMAS = {
|
|
82
82
|
readFile: {
|
|
83
83
|
name: 'readFile',
|
|
84
|
-
description:
|
|
85
|
-
'Reads a file from the local filesystem. The file_path parameter must be an absolute path. ' +
|
|
86
|
-
'Returns line-numbered content.',
|
|
84
|
+
description: 'Read a file. Absolute path. Returns line-numbered content.',
|
|
87
85
|
parameters: {
|
|
88
86
|
type: 'object',
|
|
89
87
|
properties: {
|
|
90
|
-
file_path: { type: 'string', description: '
|
|
91
|
-
offset: { type: 'number', description: '
|
|
88
|
+
file_path: { type: 'string', description: 'Absolute path' },
|
|
89
|
+
offset: { type: 'number', description: 'Start line (0-based)' },
|
|
92
90
|
limit: { type: 'number', description: `The number of lines to read (max 10000, default ${READ_LINE_CAP})` },
|
|
93
91
|
},
|
|
94
92
|
required: ['file_path'],
|
|
@@ -98,13 +96,12 @@ const SCHEMAS = {
|
|
|
98
96
|
writeFile: {
|
|
99
97
|
name: 'writeFile',
|
|
100
98
|
description:
|
|
101
|
-
'
|
|
102
|
-
'Use it to create or replace a whole file; it overwrites whatever was there.',
|
|
99
|
+
'Write a whole file, overwriting it. Parent dirs are created. Use editFile to change part of one.',
|
|
103
100
|
parameters: {
|
|
104
101
|
type: 'object',
|
|
105
102
|
properties: {
|
|
106
|
-
file_path: { type: 'string', description: '
|
|
107
|
-
content: { type: 'string', description: '
|
|
103
|
+
file_path: { type: 'string', description: 'Absolute path' },
|
|
104
|
+
content: { type: 'string', description: 'Full file contents' },
|
|
108
105
|
},
|
|
109
106
|
required: ['file_path', 'content'],
|
|
110
107
|
additionalProperties: false,
|
|
@@ -113,16 +110,15 @@ const SCHEMAS = {
|
|
|
113
110
|
editFile: {
|
|
114
111
|
name: 'editFile',
|
|
115
112
|
description:
|
|
116
|
-
'
|
|
117
|
-
'
|
|
118
|
-
'existing file — it fails loudly on a non-unique or missing match instead of guessing.',
|
|
113
|
+
'Exact string replacement. old_string must be unique unless replace_all. Fails loudly on a ' +
|
|
114
|
+
'missing or ambiguous match rather than guessing.',
|
|
119
115
|
parameters: {
|
|
120
116
|
type: 'object',
|
|
121
117
|
properties: {
|
|
122
|
-
file_path: { type: 'string', description: '
|
|
123
|
-
old_string: { type: 'string', description: '
|
|
124
|
-
new_string: { type: 'string', description: '
|
|
125
|
-
replace_all: { type: 'boolean', description: '
|
|
118
|
+
file_path: { type: 'string', description: 'Absolute path' },
|
|
119
|
+
old_string: { type: 'string', description: 'Text to replace; must be unique unless replace_all' },
|
|
120
|
+
new_string: { type: 'string', description: 'Replacement text' },
|
|
121
|
+
replace_all: { type: 'boolean', description: 'Replace every occurrence' },
|
|
126
122
|
},
|
|
127
123
|
required: ['file_path', 'old_string', 'new_string'],
|
|
128
124
|
additionalProperties: false,
|
|
@@ -130,9 +126,7 @@ const SCHEMAS = {
|
|
|
130
126
|
},
|
|
131
127
|
listDir: {
|
|
132
128
|
name: 'listDir',
|
|
133
|
-
description:
|
|
134
|
-
'Lists one directory (non-recursive). Directories are marked with a trailing slash. ' +
|
|
135
|
-
'Skips node_modules, .git and dist.',
|
|
129
|
+
description: 'List one directory (non-recursive). Skips node_modules, .git, dist.',
|
|
136
130
|
parameters: {
|
|
137
131
|
type: 'object',
|
|
138
132
|
properties: {
|
|
@@ -145,12 +139,12 @@ const SCHEMAS = {
|
|
|
145
139
|
glob: {
|
|
146
140
|
name: 'glob',
|
|
147
141
|
description:
|
|
148
|
-
'Find files
|
|
142
|
+
'Find files by glob (**, *, ?). Skips node_modules, .git, dist.',
|
|
149
143
|
parameters: {
|
|
150
144
|
type: 'object',
|
|
151
145
|
properties: {
|
|
152
|
-
pattern: { type: 'string', description: '
|
|
153
|
-
path: { type: 'string', description: '
|
|
146
|
+
pattern: { type: 'string', description: 'Glob, e.g. "**/*.test.js"' },
|
|
147
|
+
path: { type: 'string', description: 'Search root (default: cwd)' },
|
|
154
148
|
},
|
|
155
149
|
required: ['pattern'],
|
|
156
150
|
additionalProperties: false,
|
|
@@ -158,9 +152,7 @@ const SCHEMAS = {
|
|
|
158
152
|
},
|
|
159
153
|
grep: {
|
|
160
154
|
name: 'grep',
|
|
161
|
-
description:
|
|
162
|
-
'Search file contents using a regular expression. Returns file:line matches. ' +
|
|
163
|
-
'Skips node_modules, .git and dist by default.',
|
|
155
|
+
description: 'Search file contents by regex. Returns file:line matches. Skips node_modules, .git, dist.',
|
|
164
156
|
parameters: {
|
|
165
157
|
type: 'object',
|
|
166
158
|
properties: {
|
|
@@ -174,15 +166,13 @@ const SCHEMAS = {
|
|
|
174
166
|
exec: {
|
|
175
167
|
name: 'exec',
|
|
176
168
|
description:
|
|
177
|
-
'
|
|
178
|
-
'stdout+stderr
|
|
179
|
-
'within the same turn — it is a real session, not a fresh process each time. ' +
|
|
180
|
-
'Use for system operations, git commands and package management.',
|
|
169
|
+
'Run a shell command in a PERSISTENT session: cd and exported env carry across calls in ' +
|
|
170
|
+
'this turn. Returns stdout+stderr and the exit code. Use for git, packages, system ops.',
|
|
181
171
|
parameters: {
|
|
182
172
|
type: 'object',
|
|
183
173
|
properties: {
|
|
184
|
-
command: { type: 'string', description: '
|
|
185
|
-
cwd: { type: 'string', description: 'Run this one command
|
|
174
|
+
command: { type: 'string', description: 'Command to run' },
|
|
175
|
+
cwd: { type: 'string', description: 'Run this one command elsewhere; session cwd unchanged' },
|
|
186
176
|
timeout: { type: 'number', description: `Timeout in milliseconds (max ${EXEC_TIMEOUT_CAP}, default ${EXEC_TIMEOUT_DEFAULT})` },
|
|
187
177
|
description: { type: 'string', description: 'A brief description of what the command does (for display)' },
|
|
188
178
|
},
|
|
@@ -193,17 +183,12 @@ const SCHEMAS = {
|
|
|
193
183
|
task: {
|
|
194
184
|
name: 'task',
|
|
195
185
|
description:
|
|
196
|
-
'
|
|
197
|
-
'
|
|
198
|
-
'on the same model and returns a final report as the tool result. Use it to delegate work ' +
|
|
199
|
-
'like scanning for vulnerabilities, reviewing code, planning a refactor, or scaffolding a ' +
|
|
200
|
-
'component — give it a complete, self-contained prompt since it cannot ask follow-up ' +
|
|
201
|
-
'questions. Subagents can delegate further with task, so a large job can be split ' +
|
|
202
|
-
'hierarchically as deep as useful.',
|
|
186
|
+
'Delegate a focused multi-step sub-task to a subagent with its own tool loop; it returns a ' +
|
|
187
|
+
'final report. Give it a complete, self-contained prompt — it cannot ask follow-ups.',
|
|
203
188
|
parameters: {
|
|
204
189
|
type: 'object',
|
|
205
190
|
properties: {
|
|
206
|
-
description: { type: 'string', description: '
|
|
191
|
+
description: { type: 'string', description: 'Short label (3-5 words)' },
|
|
207
192
|
subagent_type: {
|
|
208
193
|
type: 'string',
|
|
209
194
|
enum: [...agentRoles(), 'general'],
|