@aexol/spectral 0.9.20 → 0.9.24
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/agent/agents.d.ts +17 -1
- package/dist/agent/agents.d.ts.map +1 -1
- package/dist/agent/agents.js +42 -2
- package/dist/agent/index.d.ts +3 -1
- package/dist/agent/index.d.ts.map +1 -1
- package/dist/agent/index.js +40 -12
- package/dist/cli.js +9 -3
- package/dist/commands/serve.d.ts.map +1 -1
- package/dist/commands/serve.js +14 -5
- package/dist/memory/index.d.ts.map +1 -1
- package/dist/memory/index.js +2 -0
- package/dist/memory/tool-output-compressor.d.ts +61 -0
- package/dist/memory/tool-output-compressor.d.ts.map +1 -0
- package/dist/memory/tool-output-compressor.js +569 -0
- package/dist/relay/dispatcher.d.ts +3 -1
- package/dist/relay/dispatcher.d.ts.map +1 -1
- package/dist/relay/dispatcher.js +23 -0
- package/dist/sdk/coding-agent/config.d.ts.map +1 -1
- package/dist/sdk/coding-agent/config.js +10 -1
- package/dist/server/agent-bridge.d.ts +8 -0
- package/dist/server/agent-bridge.d.ts.map +1 -1
- package/dist/server/agent-bridge.js +29 -1
- package/dist/server/handlers/agent-settings.d.ts +49 -0
- package/dist/server/handlers/agent-settings.d.ts.map +1 -0
- package/dist/server/handlers/agent-settings.js +109 -0
- package/dist/server/handlers/settings-lock.d.ts +36 -0
- package/dist/server/handlers/settings-lock.d.ts.map +1 -0
- package/dist/server/handlers/settings-lock.js +89 -0
- package/dist/server/handlers/settings.d.ts +0 -11
- package/dist/server/handlers/settings.d.ts.map +1 -1
- package/dist/server/handlers/settings.js +5 -85
- package/package.json +1 -1
package/dist/agent/agents.d.ts
CHANGED
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
* ---
|
|
7
7
|
* name: my-agent
|
|
8
8
|
* description: What this agent does
|
|
9
|
+
* mode: subagent # or "primary" to inject into the main system prompt
|
|
9
10
|
* tools: read, grep, find, ls
|
|
10
11
|
* model: claude-haiku-4-5
|
|
11
12
|
* ---
|
|
@@ -16,9 +17,11 @@
|
|
|
16
17
|
* .spectral/agents/*.md — Project-level (opt-in via agentScope)
|
|
17
18
|
*/
|
|
18
19
|
export type AgentScope = "user" | "project" | "both";
|
|
20
|
+
export type AgentMode = "primary" | "subagent";
|
|
19
21
|
export interface AgentConfig {
|
|
20
22
|
name: string;
|
|
21
23
|
description: string;
|
|
24
|
+
mode: AgentMode;
|
|
22
25
|
tools?: string[];
|
|
23
26
|
model?: string;
|
|
24
27
|
systemPrompt: string;
|
|
@@ -29,7 +32,20 @@ export interface AgentDiscoveryResult {
|
|
|
29
32
|
agents: AgentConfig[];
|
|
30
33
|
projectAgentsDir: string | null;
|
|
31
34
|
}
|
|
32
|
-
export declare function discoverAgents(cwd: string, scope: AgentScope): AgentDiscoveryResult;
|
|
35
|
+
export declare function discoverAgents(cwd: string, scope: AgentScope, agentDir?: string): AgentDiscoveryResult;
|
|
36
|
+
export declare function discoverPrimaryAgent(cwd: string, scope?: AgentScope, agentDir?: string): AgentConfig | null;
|
|
37
|
+
/**
|
|
38
|
+
* Prepend the primary agent's system prompt above the base system prompt.
|
|
39
|
+
*
|
|
40
|
+
* Used by the per-turn `before_agent_start` hook so the primary-agent
|
|
41
|
+
* toggle takes effect mid-session (on the next user message) rather than
|
|
42
|
+
* only at session start.
|
|
43
|
+
*
|
|
44
|
+
* - Returns the base unchanged when no primary agent is provided.
|
|
45
|
+
* - Idempotent: if the base already starts with the primary agent header,
|
|
46
|
+
* the base is returned unchanged (guards against double-injection).
|
|
47
|
+
*/
|
|
48
|
+
export declare function injectPrimaryAgentPrompt(base: string | undefined, primaryAgent: Pick<AgentConfig, "name" | "description" | "systemPrompt"> | null): string | undefined;
|
|
33
49
|
export declare function formatAgentList(agents: AgentConfig[], maxItems: number): {
|
|
34
50
|
text: string;
|
|
35
51
|
remaining: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agents.d.ts","sourceRoot":"","sources":["../../src/agent/agents.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"agents.d.ts","sourceRoot":"","sources":["../../src/agent/agents.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAOH,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG,SAAS,GAAG,MAAM,CAAC;AACrD,MAAM,MAAM,SAAS,GAAG,SAAS,GAAG,UAAU,CAAC;AAE/C,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,SAAS,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3B,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,WAAW,EAAE,CAAC;IACtB,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;CACjC;AA2ED,wBAAgB,cAAc,CAC5B,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,UAAU,EACjB,QAAQ,CAAC,EAAE,MAAM,GAChB,oBAAoB,CAoBtB;AAED,wBAAgB,oBAAoB,CAClC,GAAG,EAAE,MAAM,EACX,KAAK,GAAE,UAAmB,EAC1B,QAAQ,CAAC,EAAE,MAAM,GAChB,WAAW,GAAG,IAAI,CAgBpB;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,wBAAwB,CACtC,IAAI,EAAE,MAAM,GAAG,SAAS,EACxB,YAAY,EAAE,IAAI,CAAC,WAAW,EAAE,MAAM,GAAG,aAAa,GAAG,cAAc,CAAC,GAAG,IAAI,GAC9E,MAAM,GAAG,SAAS,CAOpB;AAED,wBAAgB,eAAe,CAC7B,MAAM,EAAE,WAAW,EAAE,EACrB,QAAQ,EAAE,MAAM,GACf;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAQrC"}
|
package/dist/agent/agents.js
CHANGED
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
* ---
|
|
7
7
|
* name: my-agent
|
|
8
8
|
* description: What this agent does
|
|
9
|
+
* mode: subagent # or "primary" to inject into the main system prompt
|
|
9
10
|
* tools: read, grep, find, ls
|
|
10
11
|
* model: claude-haiku-4-5
|
|
11
12
|
* ---
|
|
@@ -17,6 +18,7 @@
|
|
|
17
18
|
*/
|
|
18
19
|
import * as fs from "node:fs";
|
|
19
20
|
import * as path from "node:path";
|
|
21
|
+
import chalk from "chalk";
|
|
20
22
|
import { getAgentDir, parseFrontmatter } from "../sdk/coding-agent/index.js";
|
|
21
23
|
function loadAgentsFromDir(dir, source) {
|
|
22
24
|
const agents = [];
|
|
@@ -51,9 +53,11 @@ function loadAgentsFromDir(dir, source) {
|
|
|
51
53
|
?.split(",")
|
|
52
54
|
.map((t) => t.trim())
|
|
53
55
|
.filter(Boolean);
|
|
56
|
+
const mode = frontmatter.mode === "primary" ? "primary" : "subagent";
|
|
54
57
|
agents.push({
|
|
55
58
|
name: frontmatter.name,
|
|
56
59
|
description: frontmatter.description,
|
|
60
|
+
mode,
|
|
57
61
|
tools: tools && tools.length > 0 ? tools : undefined,
|
|
58
62
|
model: frontmatter.model,
|
|
59
63
|
systemPrompt: body,
|
|
@@ -83,8 +87,8 @@ function findNearestProjectAgentsDir(cwd) {
|
|
|
83
87
|
currentDir = parentDir;
|
|
84
88
|
}
|
|
85
89
|
}
|
|
86
|
-
export function discoverAgents(cwd, scope) {
|
|
87
|
-
const userDir = path.join(getAgentDir(), "agents");
|
|
90
|
+
export function discoverAgents(cwd, scope, agentDir) {
|
|
91
|
+
const userDir = path.join(agentDir ?? getAgentDir(), "agents");
|
|
88
92
|
const projectAgentsDir = findNearestProjectAgentsDir(cwd);
|
|
89
93
|
const userAgents = scope === "project" ? [] : loadAgentsFromDir(userDir, "user");
|
|
90
94
|
const projectAgents = scope === "user" || !projectAgentsDir ? [] : loadAgentsFromDir(projectAgentsDir, "project");
|
|
@@ -105,6 +109,42 @@ export function discoverAgents(cwd, scope) {
|
|
|
105
109
|
}
|
|
106
110
|
return { agents: Array.from(agentMap.values()), projectAgentsDir };
|
|
107
111
|
}
|
|
112
|
+
export function discoverPrimaryAgent(cwd, scope = "both", agentDir) {
|
|
113
|
+
const { agents } = discoverAgents(cwd, scope, agentDir);
|
|
114
|
+
const primaries = agents.filter((a) => a.mode === "primary");
|
|
115
|
+
if (primaries.length === 0)
|
|
116
|
+
return null;
|
|
117
|
+
if (primaries.length > 1) {
|
|
118
|
+
// User-level primary wins over project-level primary; otherwise first wins.
|
|
119
|
+
const userPrimary = primaries.find((a) => a.source === "user");
|
|
120
|
+
const chosen = userPrimary ?? primaries[0];
|
|
121
|
+
console.warn(chalk.yellow(`Multiple primary agents found (${primaries.map((a) => a.name).join(", ")}). Using "${chosen.name}".`));
|
|
122
|
+
return chosen;
|
|
123
|
+
}
|
|
124
|
+
return primaries[0];
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Prepend the primary agent's system prompt above the base system prompt.
|
|
128
|
+
*
|
|
129
|
+
* Used by the per-turn `before_agent_start` hook so the primary-agent
|
|
130
|
+
* toggle takes effect mid-session (on the next user message) rather than
|
|
131
|
+
* only at session start.
|
|
132
|
+
*
|
|
133
|
+
* - Returns the base unchanged when no primary agent is provided.
|
|
134
|
+
* - Idempotent: if the base already starts with the primary agent header,
|
|
135
|
+
* the base is returned unchanged (guards against double-injection).
|
|
136
|
+
*/
|
|
137
|
+
export function injectPrimaryAgentPrompt(base, primaryAgent) {
|
|
138
|
+
if (!primaryAgent)
|
|
139
|
+
return base;
|
|
140
|
+
const header = `# Primary Agent: ${primaryAgent.name}\n\n${primaryAgent.description}`;
|
|
141
|
+
const block = `${header}\n\n${primaryAgent.systemPrompt}`;
|
|
142
|
+
if (!base)
|
|
143
|
+
return block;
|
|
144
|
+
if (base.startsWith(header))
|
|
145
|
+
return base;
|
|
146
|
+
return `${block}\n\n---\n\n${base}`;
|
|
147
|
+
}
|
|
108
148
|
export function formatAgentList(agents, maxItems) {
|
|
109
149
|
if (agents.length === 0)
|
|
110
150
|
return { text: "none", remaining: 0 };
|
package/dist/agent/index.d.ts
CHANGED
|
@@ -25,5 +25,7 @@
|
|
|
25
25
|
* - Access to observational memory via the recall tool
|
|
26
26
|
*/
|
|
27
27
|
import { type ExtensionAPI } from "../sdk/coding-agent/index.js";
|
|
28
|
-
export default function subagentExtension(ext: ExtensionAPI
|
|
28
|
+
export default function subagentExtension(ext: ExtensionAPI, opts?: {
|
|
29
|
+
disabledAgents?: string[];
|
|
30
|
+
}): void;
|
|
29
31
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/agent/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAWH,OAAO,EACN,KAAK,YAAY,EAEjB,MAAM,8BAA8B,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/agent/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAWH,OAAO,EACN,KAAK,YAAY,EAEjB,MAAM,8BAA8B,CAAC;AAuetC,MAAM,CAAC,OAAO,UAAU,iBAAiB,CAAC,GAAG,EAAE,YAAY,EAAE,IAAI,CAAC,EAAE;IAAE,cAAc,CAAC,EAAE,MAAM,EAAE,CAAA;CAAE,GAAG,IAAI,CA+UvG"}
|
package/dist/agent/index.js
CHANGED
|
@@ -28,6 +28,7 @@ import { agentLoop } from "../sdk/agent-core/index.js";
|
|
|
28
28
|
import { StringEnum } from "../sdk/ai/index.js";
|
|
29
29
|
import { Type } from "typebox";
|
|
30
30
|
import { discoverAgents } from "./agents.js";
|
|
31
|
+
import { loadAgentSettings } from "../server/handlers/agent-settings.js";
|
|
31
32
|
// ---------------------------------------------------------------------------
|
|
32
33
|
// Built-in tool resolution (no spawn needed — tools are registered in-process)
|
|
33
34
|
// ---------------------------------------------------------------------------
|
|
@@ -175,7 +176,8 @@ async function mapWithConcurrencyLimit(items, concurrency, fn) {
|
|
|
175
176
|
// Core — run a single subagent in-process via agentLoop
|
|
176
177
|
// ---------------------------------------------------------------------------
|
|
177
178
|
async function runSingleAgent(defaultCwd, agents, agentName, task, cwd, step, signal, onUpdate, makeDetails, ext, ctx) {
|
|
178
|
-
const
|
|
179
|
+
const normalizedAgentName = agentName.replace(/^@/, "");
|
|
180
|
+
const agent = agents.find((a) => a.name === normalizedAgentName);
|
|
179
181
|
if (!agent) {
|
|
180
182
|
const available = agents.map((a) => `"${a.name}"`).join(", ") || "none";
|
|
181
183
|
return {
|
|
@@ -355,8 +357,8 @@ const ChainItem = Type.Object({
|
|
|
355
357
|
cwd: Type.Optional(Type.String({ description: "Working directory for the agent process" })),
|
|
356
358
|
});
|
|
357
359
|
const AgentScopeSchema = StringEnum(["user", "project", "both"], {
|
|
358
|
-
description: 'Which agent directories to use. Default: "
|
|
359
|
-
default: "
|
|
360
|
+
description: 'Which agent directories to use. Default: "both" (user + project agents).',
|
|
361
|
+
default: "both",
|
|
360
362
|
});
|
|
361
363
|
const SubagentParams = Type.Object({
|
|
362
364
|
agent: Type.Optional(Type.String({ description: "Name of the agent to invoke (for single mode)" })),
|
|
@@ -379,15 +381,15 @@ const SubagentParams = Type.Object({
|
|
|
379
381
|
// ---------------------------------------------------------------------------
|
|
380
382
|
// Extension entry point
|
|
381
383
|
// ---------------------------------------------------------------------------
|
|
382
|
-
export default function subagentExtension(ext) {
|
|
384
|
+
export default function subagentExtension(ext, opts) {
|
|
383
385
|
ext.registerTool({
|
|
384
386
|
name: "subagent",
|
|
385
387
|
label: "Subagent",
|
|
386
388
|
description: [
|
|
387
389
|
"Delegate tasks to specialized subagents with isolated context.",
|
|
388
390
|
"Modes: single (agent + task), parallel (tasks array), chain (sequential with {previous} placeholder).",
|
|
389
|
-
'Default agent scope is "
|
|
390
|
-
'
|
|
391
|
+
'Default agent scope is "both" (user agents from ~/.spectral/agent/agents + project agents from .spectral/agents).',
|
|
392
|
+
'Set agentScope: "user" or "project" to limit scope.'
|
|
391
393
|
].join(" "),
|
|
392
394
|
promptSnippet: "Run a subagent to investigate, plan, review, or implement code changes",
|
|
393
395
|
promptGuidelines: [
|
|
@@ -395,10 +397,36 @@ export default function subagentExtension(ext) {
|
|
|
395
397
|
],
|
|
396
398
|
parameters: SubagentParams,
|
|
397
399
|
async execute(_toolCallId, params, signal, onUpdate, ctx) {
|
|
398
|
-
|
|
400
|
+
// Re-load agent settings from disk on every call so that UI toggles
|
|
401
|
+
// (subagentsEnabled / disabledSubagents) take effect immediately on
|
|
402
|
+
// running sessions, not just on the next session start.
|
|
403
|
+
const liveSettings = loadAgentSettings(ctx.cwd);
|
|
404
|
+
if (!liveSettings.subagentsEnabled) {
|
|
405
|
+
return {
|
|
406
|
+
content: [
|
|
407
|
+
{
|
|
408
|
+
type: "text",
|
|
409
|
+
text: "Subagents are disabled in agent settings. Enable subagents via the agent settings panel to delegate tasks.",
|
|
410
|
+
},
|
|
411
|
+
],
|
|
412
|
+
details: {
|
|
413
|
+
mode: "single",
|
|
414
|
+
agentScope: (params.agentScope ?? "both"),
|
|
415
|
+
projectAgentsDir: null,
|
|
416
|
+
results: [],
|
|
417
|
+
},
|
|
418
|
+
};
|
|
419
|
+
}
|
|
420
|
+
const agentScope = params.agentScope ?? "both";
|
|
399
421
|
const discovery = discoverAgents(ctx.cwd, agentScope);
|
|
400
|
-
|
|
401
|
-
|
|
422
|
+
// Merge registration-time disabled list (from session start) with the
|
|
423
|
+
// live disabled list (just read from disk) so both are honored.
|
|
424
|
+
const disabledSet = new Set([
|
|
425
|
+
...(opts?.disabledAgents ?? []),
|
|
426
|
+
...(liveSettings.disabledSubagents ?? []),
|
|
427
|
+
]);
|
|
428
|
+
const agents = discovery.agents.filter((a) => !disabledSet.has(a.name));
|
|
429
|
+
const confirmProjectAgents = params.confirmProjectAgents ?? false;
|
|
402
430
|
const hasChain = (params.chain?.length ?? 0) > 0;
|
|
403
431
|
const hasTasks = (params.tasks?.length ?? 0) > 0;
|
|
404
432
|
const hasSingle = Boolean(params.agent && params.task);
|
|
@@ -430,12 +458,12 @@ export default function subagentExtension(ext) {
|
|
|
430
458
|
const requestedAgentNames = new Set();
|
|
431
459
|
if (params.chain)
|
|
432
460
|
for (const step of params.chain)
|
|
433
|
-
requestedAgentNames.add(step.agent);
|
|
461
|
+
requestedAgentNames.add(step.agent.replace(/^@/, ""));
|
|
434
462
|
if (params.tasks)
|
|
435
463
|
for (const t of params.tasks)
|
|
436
|
-
requestedAgentNames.add(t.agent);
|
|
464
|
+
requestedAgentNames.add(t.agent.replace(/^@/, ""));
|
|
437
465
|
if (params.agent)
|
|
438
|
-
requestedAgentNames.add(params.agent);
|
|
466
|
+
requestedAgentNames.add(params.agent.replace(/^@/, ""));
|
|
439
467
|
const projectAgentsRequested = Array.from(requestedAgentNames)
|
|
440
468
|
.map((name) => agents.find((a) => a.name === name))
|
|
441
469
|
.filter((a) => a?.source === "project");
|
package/dist/cli.js
CHANGED
|
@@ -18,9 +18,15 @@ import { dirname, resolve } from "node:path";
|
|
|
18
18
|
import { fileURLToPath } from "node:url";
|
|
19
19
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
20
20
|
// ---- Read our own version ----------------------------------------------------
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
const
|
|
21
|
+
let VERSION = process.env.npm_package_version ?? "0.0.0";
|
|
22
|
+
try {
|
|
23
|
+
const pkgPath = resolve(__dirname, "..", "package.json");
|
|
24
|
+
const pkg = JSON.parse(readFileSync(pkgPath, "utf8"));
|
|
25
|
+
VERSION = pkg.version;
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
// Standalone Bun binaries do not carry the source package.json.
|
|
29
|
+
}
|
|
24
30
|
const TAGLINE = "Coding agent that never sleeps";
|
|
25
31
|
// ---- Branded helpers ---------------------------------------------------------
|
|
26
32
|
function printVersion() {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"serve.d.ts","sourceRoot":"","sources":["../../src/commands/serve.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAsBH,OAAO,EAAE,WAAW,EAAmB,MAAM,oBAAoB,CAAC;AASlE,OAAO,KAAK,EAAE,aAAa,EAAc,MAAM,6BAA6B,CAAC;AAC7E,OAAO,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AAGnE,OAAO,EAAmB,YAAY,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"serve.d.ts","sourceRoot":"","sources":["../../src/commands/serve.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAsBH,OAAO,EAAE,WAAW,EAAmB,MAAM,oBAAoB,CAAC;AASlE,OAAO,KAAK,EAAE,aAAa,EAAc,MAAM,6BAA6B,CAAC;AAC7E,OAAO,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AAGnE,OAAO,EAAmB,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAsBrE;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAazD;AAED,MAAM,WAAW,eAAe;IAC9B,8CAA8C;IAC9C,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;OAGG;IACH,cAAc,EAAE,OAAO,CAAC;CACzB;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,eAAe,CA6B9D;AAED,MAAM,WAAW,eAAe;IAC9B,iEAAiE;IACjE,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,4CAA4C;IAC5C,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC,uCAAuC;IACvC,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,wCAAwC;IACxC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,yDAAyD;IACzD,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B,6EAA6E;IAC7E,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;OAGG;IACH,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B;;;OAGG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,4CAA4C;IAC5C,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;IACzB,+DAA+D;IAC/D,aAAa,CAAC,EAAE,qBAAqB,CAAC,OAAO,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC;CAC/E;AAED,MAAM,WAAW,cAAc;IAC7B,qCAAqC;IACrC,KAAK,EAAE,YAAY,CAAC;IACpB,wDAAwD;IACxD,OAAO,EAAE,oBAAoB,CAAC;IAC9B,4CAA4C;IAC5C,KAAK,EAAE,WAAW,CAAC;IACnB,+CAA+C;IAC/C,SAAS,EAAE,MAAM,CAAC;IAClB,4CAA4C;IAC5C,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB;AAED,wBAAsB,QAAQ,CAAC,IAAI,GAAE,eAAoB,GAAG,OAAO,CAAC,cAAc,CAAC,CAsWlF;AAiED;;;GAGG;AACH,wBAAsB,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,cAAc,CAAC,CAa5E"}
|
package/dist/commands/serve.js
CHANGED
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
* in-process fake backend.
|
|
29
29
|
*/
|
|
30
30
|
import { readFileSync } from "node:fs";
|
|
31
|
-
import {
|
|
31
|
+
import { hostname } from "node:os";
|
|
32
32
|
import { dirname, join, resolve } from "node:path";
|
|
33
33
|
import { fileURLToPath } from "node:url";
|
|
34
34
|
import { getConfigDir } from "../config.js";
|
|
@@ -49,9 +49,17 @@ const DEFAULT_BACKEND_URL = "https://api.aexol.ai";
|
|
|
49
49
|
function readPackageVersion() {
|
|
50
50
|
// dist/commands/serve.js → ../../package.json
|
|
51
51
|
// src/commands/serve.ts → ../../package.json (tsx / vitest)
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
52
|
+
// In a Bun standalone binary the source tree is not present, so the
|
|
53
|
+
// package.json lookup below fails. Return a fallback version instead of
|
|
54
|
+
// crashing the serve process.
|
|
55
|
+
try {
|
|
56
|
+
const pkgPath = resolve(__dirname, "..", "..", "package.json");
|
|
57
|
+
const pkg = JSON.parse(readFileSync(pkgPath, "utf8"));
|
|
58
|
+
return pkg.version;
|
|
59
|
+
}
|
|
60
|
+
catch {
|
|
61
|
+
return process.env.npm_package_version ?? "0.0.0";
|
|
62
|
+
}
|
|
55
63
|
}
|
|
56
64
|
/**
|
|
57
65
|
* Translate a backend HTTP(S) base URL to the relay WS(S) URL.
|
|
@@ -118,7 +126,7 @@ export function parseServeArgs(args) {
|
|
|
118
126
|
}
|
|
119
127
|
export async function runServe(opts = {}) {
|
|
120
128
|
const cfg = await requireLogin();
|
|
121
|
-
const cwd = opts.cwd ??
|
|
129
|
+
const cwd = opts.cwd ?? process.cwd();
|
|
122
130
|
const version = readPackageVersion();
|
|
123
131
|
const installSignalHandlers = opts.installSignalHandlers ?? true;
|
|
124
132
|
const silent = opts.silent ?? false;
|
|
@@ -227,6 +235,7 @@ export async function runServe(opts = {}) {
|
|
|
227
235
|
store,
|
|
228
236
|
manager,
|
|
229
237
|
cwd,
|
|
238
|
+
agentDir: getAgentDir(),
|
|
230
239
|
publishMetaEvent: deferredPublishMetaEvent,
|
|
231
240
|
mcpState: getLiveMcpState() ?? undefined,
|
|
232
241
|
}).then((response) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/memory/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/memory/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAejE,MAAM,CAAC,OAAO,UAAU,mBAAmB,CAAC,GAAG,EAAE,YAAY,QAoB5D"}
|
package/dist/memory/index.js
CHANGED
|
@@ -5,6 +5,7 @@ import { registerCompactionTrigger } from "./hooks/compaction-trigger.js";
|
|
|
5
5
|
import { registerInterAgentReceiver } from "./hooks/inter-agent-receiver.js";
|
|
6
6
|
import { registerObserverTrigger } from "./hooks/observer-trigger.js";
|
|
7
7
|
import { Runtime } from "./runtime.js";
|
|
8
|
+
import { registerToolOutputCompressor } from "./tool-output-compressor.js";
|
|
8
9
|
import { registerRecallTool } from "./tools/recall-observation.js";
|
|
9
10
|
import { registerReadProjectObservationsTool } from "./tools/read-project-observations.js";
|
|
10
11
|
import { registerReceiveAgentObservationsTool } from "./tools/receive-agent-observations.js";
|
|
@@ -17,6 +18,7 @@ export default function observationalMemory(ext) {
|
|
|
17
18
|
registerObserverTrigger(ext, runtime);
|
|
18
19
|
registerCompactionTrigger(ext, runtime);
|
|
19
20
|
registerCompactionHook(ext, runtime);
|
|
21
|
+
registerToolOutputCompressor(ext, runtime);
|
|
20
22
|
registerStatusCommand(ext, runtime);
|
|
21
23
|
registerViewCommand(ext, runtime);
|
|
22
24
|
registerRecallTool(ext);
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool Output Compressor — RTK-inspired pre-processing that intercepts
|
|
3
|
+
* tool results and compresses raw output before it enters the LLM context.
|
|
4
|
+
*
|
|
5
|
+
* This is complementary to the conversation-level compaction pipeline:
|
|
6
|
+
* - Compressor: compresses raw tool output (pre-context)
|
|
7
|
+
* - Compaction: summarizes + prunes conversation history (post-context)
|
|
8
|
+
* - Unified compaction: narrative summary + observation extraction (at compaction boundary)
|
|
9
|
+
*
|
|
10
|
+
* Strategies (mirroring RTK's four-pronged approach):
|
|
11
|
+
*
|
|
12
|
+
* 1. SMART FILTERING — strip noise from structured outputs
|
|
13
|
+
* - Code: remove comments, collapse whitespace, skip blank lines
|
|
14
|
+
* - Git: strip progress meters, hints, verbose enumerations
|
|
15
|
+
* - Shell: remove ANSI escape codes, carriage returns
|
|
16
|
+
*
|
|
17
|
+
* 2. GROUPING — aggregate similar items
|
|
18
|
+
* - ls/find: group files by directory
|
|
19
|
+
* - grep/rg: group matches by file, collapse repeated patterns
|
|
20
|
+
* - Lint errors: group by rule + file
|
|
21
|
+
*
|
|
22
|
+
* 3. TRUNCATION — keep relevant context, cut redundancy
|
|
23
|
+
* - Read: keep N lines with line-number markers
|
|
24
|
+
* - Bash: keep first + last N lines of long output
|
|
25
|
+
* - Test runners: keep only failures + summary
|
|
26
|
+
*
|
|
27
|
+
* 4. DEDUPLICATION — collapse repeated lines with counts
|
|
28
|
+
* - Log output: deduplicate repeated lines
|
|
29
|
+
* - Docker/build output: collapse progress lines
|
|
30
|
+
*/
|
|
31
|
+
import type { ExtensionAPI } from "../sdk/coding-agent/index.js";
|
|
32
|
+
import type { Runtime } from "./runtime.js";
|
|
33
|
+
export interface CompressorConfig {
|
|
34
|
+
/** Enable compression (default: true) */
|
|
35
|
+
enabled: boolean;
|
|
36
|
+
/** Maximum characters for any single tool result before truncation */
|
|
37
|
+
maxResultChars: number;
|
|
38
|
+
/** Maximum lines for read results before truncation */
|
|
39
|
+
maxReadLines: number;
|
|
40
|
+
/** Maximum lines for directory listings */
|
|
41
|
+
maxLsLines: number;
|
|
42
|
+
/** Maximum lines for grep/find results before grouping */
|
|
43
|
+
maxSearchLines: number;
|
|
44
|
+
/** Enable ANSI escape code stripping */
|
|
45
|
+
stripAnsi: boolean;
|
|
46
|
+
/** Enable comment stripping for code files */
|
|
47
|
+
stripComments: boolean;
|
|
48
|
+
/** Enable test-runner failure-only filtering */
|
|
49
|
+
testFailuresOnly: boolean;
|
|
50
|
+
/** Enable git output compacting */
|
|
51
|
+
compactGit: boolean;
|
|
52
|
+
}
|
|
53
|
+
export declare const DEFAULT_COMPRESSOR_CONFIG: CompressorConfig;
|
|
54
|
+
export interface CompressionStats {
|
|
55
|
+
originalChars: number;
|
|
56
|
+
compressedChars: number;
|
|
57
|
+
savingsPercent: number;
|
|
58
|
+
toolName: string;
|
|
59
|
+
}
|
|
60
|
+
export declare function registerToolOutputCompressor(ext: ExtensionAPI, runtime: Runtime): void;
|
|
61
|
+
//# sourceMappingURL=tool-output-compressor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tool-output-compressor.d.ts","sourceRoot":"","sources":["../../src/memory/tool-output-compressor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAUjE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAO5C,MAAM,WAAW,gBAAgB;IAChC,yCAAyC;IACzC,OAAO,EAAE,OAAO,CAAC;IACjB,sEAAsE;IACtE,cAAc,EAAE,MAAM,CAAC;IACvB,uDAAuD;IACvD,YAAY,EAAE,MAAM,CAAC;IACrB,2CAA2C;IAC3C,UAAU,EAAE,MAAM,CAAC;IACnB,0DAA0D;IAC1D,cAAc,EAAE,MAAM,CAAC;IACvB,wCAAwC;IACxC,SAAS,EAAE,OAAO,CAAC;IACnB,8CAA8C;IAC9C,aAAa,EAAE,OAAO,CAAC;IACvB,gDAAgD;IAChD,gBAAgB,EAAE,OAAO,CAAC;IAC1B,mCAAmC;IACnC,UAAU,EAAE,OAAO,CAAC;CACpB;AAED,eAAO,MAAM,yBAAyB,EAAE,gBAUvC,CAAC;AAghBF,MAAM,WAAW,gBAAgB;IAChC,aAAa,EAAE,MAAM,CAAC;IACtB,eAAe,EAAE,MAAM,CAAC;IACxB,cAAc,EAAE,MAAM,CAAC;IACvB,QAAQ,EAAE,MAAM,CAAC;CACjB;AAED,wBAAgB,4BAA4B,CAC3C,GAAG,EAAE,YAAY,EACjB,OAAO,EAAE,OAAO,GACd,IAAI,CA4HN"}
|