@aexol/spectral 0.9.231 → 0.9.234
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/index.d.ts.map +1 -1
- package/dist/agent/index.js +89 -14
- package/dist/backend/generated-images.d.ts +1 -1
- package/dist/backend/generated-images.d.ts.map +1 -1
- package/dist/commands/serve.d.ts.map +1 -1
- package/dist/commands/serve.js +12 -1
- package/dist/extensions/logic-trace.d.ts +1 -1
- package/dist/extensions/logic-trace.d.ts.map +1 -1
- package/dist/extensions/logic-trace.js +199 -70
- package/dist/extensions/video-generation/index.d.ts +3 -0
- package/dist/extensions/video-generation/index.d.ts.map +1 -0
- package/dist/extensions/video-generation/index.js +299 -0
- package/dist/generated/zeus/const.d.ts.map +1 -1
- package/dist/generated/zeus/const.js +30 -0
- package/dist/generated/zeus/index.d.ts +140 -0
- package/dist/generated/zeus/index.d.ts.map +1 -1
- package/dist/generated/zeus/index.js +5 -0
- package/dist/relay/dispatcher.d.ts +13 -1
- package/dist/relay/dispatcher.d.ts.map +1 -1
- package/dist/relay/dispatcher.js +11 -0
- package/dist/sdk/agent-core/agent-loop.js +13 -3
- package/dist/sdk/agent-core/agent.d.ts +11 -4
- package/dist/sdk/agent-core/agent.d.ts.map +1 -1
- package/dist/sdk/agent-core/agent.js +16 -4
- package/dist/sdk/agent-core/tool-call-registry.d.ts +75 -0
- package/dist/sdk/agent-core/tool-call-registry.d.ts.map +1 -0
- package/dist/sdk/agent-core/tool-call-registry.js +131 -0
- package/dist/sdk/agent-core/tool-execution.d.ts.map +1 -1
- package/dist/sdk/agent-core/tool-execution.js +103 -4
- package/dist/sdk/agent-core/types.d.ts +15 -4
- package/dist/sdk/agent-core/types.d.ts.map +1 -1
- package/dist/sdk/ai/index.d.ts +3 -0
- package/dist/sdk/ai/index.d.ts.map +1 -1
- package/dist/sdk/ai/index.js +3 -0
- package/dist/sdk/ai/providers/faux.d.ts.map +1 -1
- package/dist/sdk/ai/providers/faux.js +3 -0
- package/dist/sdk/ai/providers/leaked-tool-call-parser.d.ts +39 -6
- package/dist/sdk/ai/providers/leaked-tool-call-parser.d.ts.map +1 -1
- package/dist/sdk/ai/providers/leaked-tool-call-parser.js +159 -18
- package/dist/sdk/ai/providers/openai-completions.d.ts.map +1 -1
- package/dist/sdk/ai/providers/openai-completions.js +22 -8
- package/dist/sdk/ai/providers/openrouter-videos.d.ts +3 -0
- package/dist/sdk/ai/providers/openrouter-videos.d.ts.map +1 -0
- package/dist/sdk/ai/providers/openrouter-videos.js +412 -0
- package/dist/sdk/ai/providers/register-builtins.d.ts.map +1 -1
- package/dist/sdk/ai/providers/register-builtins.js +6 -0
- package/dist/sdk/ai/providers/simple-options.d.ts +1 -6
- package/dist/sdk/ai/providers/simple-options.d.ts.map +1 -1
- package/dist/sdk/ai/providers/simple-options.js +0 -22
- package/dist/sdk/ai/providers/transform-messages.d.ts.map +1 -1
- package/dist/sdk/ai/providers/transform-messages.js +52 -1
- package/dist/sdk/ai/types.d.ts +91 -10
- package/dist/sdk/ai/types.d.ts.map +1 -1
- package/dist/sdk/ai/video-models.d.ts +10 -0
- package/dist/sdk/ai/video-models.d.ts.map +1 -0
- package/dist/sdk/ai/video-models.generated.d.ts +440 -0
- package/dist/sdk/ai/video-models.generated.d.ts.map +1 -0
- package/dist/sdk/ai/video-models.generated.js +441 -0
- package/dist/sdk/ai/video-models.js +22 -0
- package/dist/sdk/ai/videos-api-registry.d.ts +14 -0
- package/dist/sdk/ai/videos-api-registry.d.ts.map +1 -0
- package/dist/sdk/ai/videos-api-registry.js +21 -0
- package/dist/sdk/ai/videos.d.ts +4 -0
- package/dist/sdk/ai/videos.d.ts.map +1 -0
- package/dist/sdk/ai/videos.js +13 -0
- package/dist/sdk/coding-agent/core/agent-session.d.ts +8 -0
- package/dist/sdk/coding-agent/core/agent-session.d.ts.map +1 -1
- package/dist/sdk/coding-agent/core/agent-session.js +11 -0
- package/dist/sdk/coding-agent/core/extensions/loader.d.ts.map +1 -1
- package/dist/sdk/coding-agent/core/extensions/loader.js +14 -0
- package/dist/sdk/coding-agent/core/extensions/native-extensions.d.ts +26 -0
- package/dist/sdk/coding-agent/core/extensions/native-extensions.d.ts.map +1 -1
- package/dist/sdk/coding-agent/core/extensions/native-extensions.js +23 -0
- package/dist/sdk/coding-agent/core/extensions/session-events.d.ts +2 -2
- package/dist/sdk/coding-agent/core/extensions/session-events.d.ts.map +1 -1
- package/dist/sdk/coding-agent/core/extensions/types.d.ts +4 -2
- package/dist/sdk/coding-agent/core/extensions/types.d.ts.map +1 -1
- package/dist/sdk/coding-agent/core/messages.d.ts.map +1 -1
- package/dist/sdk/coding-agent/core/messages.js +42 -2
- package/dist/sdk/coding-agent/core/resource-loader.d.ts +11 -0
- package/dist/sdk/coding-agent/core/resource-loader.d.ts.map +1 -1
- package/dist/sdk/coding-agent/core/resource-loader.js +23 -6
- package/dist/sdk/coding-agent/core/sdk.d.ts +24 -2
- package/dist/sdk/coding-agent/core/sdk.d.ts.map +1 -1
- package/dist/sdk/coding-agent/core/sdk.js +15 -3
- package/dist/sdk/coding-agent/core/settings-manager.d.ts +0 -8
- package/dist/sdk/coding-agent/core/settings-manager.d.ts.map +1 -1
- package/dist/sdk/coding-agent/core/settings-manager.js +3 -3
- package/dist/sdk/coding-agent/index.d.ts +2 -2
- package/dist/sdk/coding-agent/index.d.ts.map +1 -1
- package/dist/sdk/coding-agent/index.js +1 -1
- package/dist/sdk-public.d.ts +96 -0
- package/dist/sdk-public.d.ts.map +1 -0
- package/dist/sdk-public.js +109 -0
- package/dist/server/agent-bridge/rehydrate.d.ts +2 -2
- package/dist/server/agent-bridge/rehydrate.d.ts.map +1 -1
- package/dist/server/agent-bridge/rehydrate.js +14 -0
- package/dist/server/agent-bridge.d.ts +8 -2
- package/dist/server/agent-bridge.d.ts.map +1 -1
- package/dist/server/agent-bridge.js +25 -2
- package/dist/server/session-stream.d.ts +19 -0
- package/dist/server/session-stream.d.ts.map +1 -1
- package/dist/server/session-stream.js +35 -0
- package/dist/server/wire.d.ts +13 -0
- package/dist/server/wire.d.ts.map +1 -1
- package/package.json +7 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/agent/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAEH,OAAO,KAAK,EAIX,SAAS,EAET,MAAM,4BAA4B,CAAC;AAqBpC,OAAO,EACN,KAAK,YAAY,EACjB,KAAK,gBAAgB,EAKrB,MAAM,8BAA8B,CAAC;AAItC,OAAO,EACN,KAAK,WAAW,EAKhB,MAAM,aAAa,CAAC;AAErB,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAQrD,OAAO,KAAK,EAAE,sBAAsB,EAAgB,MAAM,6CAA6C,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/agent/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAEH,OAAO,KAAK,EAIX,SAAS,EAET,MAAM,4BAA4B,CAAC;AAqBpC,OAAO,EACN,KAAK,YAAY,EACjB,KAAK,gBAAgB,EAKrB,MAAM,8BAA8B,CAAC;AAItC,OAAO,EACN,KAAK,WAAW,EAKhB,MAAM,aAAa,CAAC;AAErB,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAQrD,OAAO,KAAK,EAAE,sBAAsB,EAAgB,MAAM,6CAA6C,CAAC;AAyGxG;;;;;;;;;GASG;AACH,wBAAgB,yBAAyB,CACxC,gBAAgB,EAAE,MAAM,GAAG,SAAS,EACpC,KAAK,EAAE,IAAI,CAAC,WAAW,EAAE,MAAM,GAAG,aAAa,GAAG,cAAc,GAAG,OAAO,GAAG,QAAQ,CAAC,GACpF,MAAM,CAYR;AAiMD;;;GAGG;AACH,wBAAgB,oCAAoC,CACnD,cAAc,EAAE,gBAAgB,CAAC,gBAAgB,CAAC,GAChD,IAAI,CAAC,sBAAsB,EAAE,WAAW,GAAG,cAAc,CAAC,CAe5D;AA6BD,wBAAgB,oBAAoB,CACnC,GAAG,EAAE,MAAM,EACX,GAAG,EAAE,YAAY,EACjB,GAAG,EAAE,gBAAgB,GACnB,SAAS,EAAE,CAwCb;AAqHD,2FAA2F;AAC3F,wBAAgB,+BAA+B,CAC9C,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,IAAI,CAAC,GACtD,IAAI,CAEN;AAmBD;;;;;;GAMG;AACH,wBAAgB,0BAA0B,CACzC,QAAQ,EAAE,MAAM,GAAG,SAAS,EAC5B,QAAQ,EAAE;IAAE,OAAO,CAAC,EAAE,OAAO,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,GAC9D,MAAM,CAiBR;AAogBD,MAAM,CAAC,OAAO,UAAU,iBAAiB,CACxC,GAAG,EAAE,YAAY,EACjB,IAAI,CAAC,EAAE;IACN,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,iBAAiB,CAAC,EAAE,CAAC,KAAK,EAAE,WAAW,KAAK,IAAI,CAAC;IACjD,MAAM,CAAC,EAAE,MAAM,CAAC;CAChB,GACC,IAAI,CAqcN"}
|
package/dist/agent/index.js
CHANGED
|
@@ -53,6 +53,8 @@ import { compressSubagentToolResult } from "../memory/tool-output-compressor.js"
|
|
|
53
53
|
// ---------------------------------------------------------------------------
|
|
54
54
|
const MAX_PARALLEL_TASKS = 8;
|
|
55
55
|
const MAX_CONCURRENCY = 4;
|
|
56
|
+
/** Max steps in a chain call, mirroring the parallel batch cap. */
|
|
57
|
+
const MAX_CHAIN_STEPS = 8;
|
|
56
58
|
/**
|
|
57
59
|
* Per-subagent timeout. Each subagent invocation (single, parallel, chain)
|
|
58
60
|
* gets its own independent deadline so that no single subagent can
|
|
@@ -197,6 +199,40 @@ function truncateOutput(text, limit) {
|
|
|
197
199
|
}
|
|
198
200
|
return text;
|
|
199
201
|
}
|
|
202
|
+
/** Levenshtein edit distance between two strings (dependency-free). */
|
|
203
|
+
function levenshtein(a, b) {
|
|
204
|
+
const dp = [];
|
|
205
|
+
for (let i = 0; i <= a.length; i++)
|
|
206
|
+
dp[i] = [i];
|
|
207
|
+
for (let j = 0; j <= b.length; j++)
|
|
208
|
+
dp[0][j] = j;
|
|
209
|
+
for (let i = 1; i <= a.length; i++) {
|
|
210
|
+
for (let j = 1; j <= b.length; j++) {
|
|
211
|
+
const cost = a[i - 1] === b[j - 1] ? 0 : 1;
|
|
212
|
+
dp[i][j] = Math.min(dp[i - 1][j] + 1, dp[i][j - 1] + 1, dp[i - 1][j - 1] + cost);
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
return dp[a.length][b.length];
|
|
216
|
+
}
|
|
217
|
+
/**
|
|
218
|
+
* Suggests the closest known agent name for an unknown one.
|
|
219
|
+
* Case-insensitive prefix/substring match first, then Levenshtein ≤ 2.
|
|
220
|
+
*/
|
|
221
|
+
function suggestAgentName(unknownName, agents) {
|
|
222
|
+
const target = unknownName.toLowerCase();
|
|
223
|
+
let best;
|
|
224
|
+
for (const agent of agents) {
|
|
225
|
+
const name = agent.name.toLowerCase();
|
|
226
|
+
if (name.startsWith(target) || name.includes(target) || target.includes(name)) {
|
|
227
|
+
return agent.name;
|
|
228
|
+
}
|
|
229
|
+
const distance = levenshtein(target, name);
|
|
230
|
+
if (distance <= 2 && (!best || distance < best.distance)) {
|
|
231
|
+
best = { name: agent.name, distance };
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
return best?.name;
|
|
235
|
+
}
|
|
200
236
|
// ---------------------------------------------------------------------------
|
|
201
237
|
// Helpers — model resolution
|
|
202
238
|
// ---------------------------------------------------------------------------
|
|
@@ -441,14 +477,15 @@ async function runSingleAgent(defaultCwd, agents, agentName, task, cwd, step, si
|
|
|
441
477
|
const normalizedAgentName = agentName.replace(/^@/, "");
|
|
442
478
|
const agent = agents.find((a) => a.name === normalizedAgentName);
|
|
443
479
|
if (!agent) {
|
|
444
|
-
const available = agents.map((a) =>
|
|
480
|
+
const available = agents.map((a) => `${a.name} (${a.source})`).join(", ") || "none";
|
|
481
|
+
const suggestion = suggestAgentName(normalizedAgentName, agents);
|
|
445
482
|
return {
|
|
446
483
|
agent: agentName,
|
|
447
484
|
agentSource: "unknown",
|
|
448
485
|
task,
|
|
449
486
|
exitCode: 1,
|
|
450
487
|
messages: [],
|
|
451
|
-
stderr: `Unknown agent: "${agentName}". Available agents: ${available}
|
|
488
|
+
stderr: `Unknown agent: "${agentName}". Available agents: ${available}.${suggestion ? ` Did you mean "${suggestion}"?` : ""}`,
|
|
452
489
|
usage: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, cost: 0, contextTokens: 0, turns: 0 },
|
|
453
490
|
step,
|
|
454
491
|
};
|
|
@@ -788,14 +825,20 @@ async function runSingleAgent(defaultCwd, agents, agentName, task, cwd, step, si
|
|
|
788
825
|
// Tool parameter schemas
|
|
789
826
|
// ---------------------------------------------------------------------------
|
|
790
827
|
const TaskItem = Type.Object({
|
|
791
|
-
agent: Type.String({
|
|
792
|
-
|
|
828
|
+
agent: Type.String({
|
|
829
|
+
description: "Known agent name to invoke (use names from the available agents list)",
|
|
830
|
+
}),
|
|
831
|
+
task: Type.String({
|
|
832
|
+
description: "Full self-contained prompt text for the agent (plain string; subagents share no context with the caller)",
|
|
833
|
+
}),
|
|
793
834
|
cwd: Type.Optional(Type.String({ description: "Working directory for the agent process" })),
|
|
794
835
|
});
|
|
795
836
|
const ChainItem = Type.Object({
|
|
796
|
-
agent: Type.String({
|
|
837
|
+
agent: Type.String({
|
|
838
|
+
description: "Known agent name to invoke (use names from the available agents list)",
|
|
839
|
+
}),
|
|
797
840
|
task: Type.String({
|
|
798
|
-
description: "
|
|
841
|
+
description: "Full self-contained prompt text with an optional {previous} placeholder, substituted with the previous step's output",
|
|
799
842
|
}),
|
|
800
843
|
cwd: Type.Optional(Type.String({ description: "Working directory for the agent process" })),
|
|
801
844
|
});
|
|
@@ -804,13 +847,19 @@ const AgentScopeSchema = StringEnum(["user", "project", "both"], {
|
|
|
804
847
|
default: "both",
|
|
805
848
|
});
|
|
806
849
|
const SubagentParams = Type.Object({
|
|
807
|
-
agent: Type.Optional(Type.String({
|
|
808
|
-
|
|
850
|
+
agent: Type.Optional(Type.String({
|
|
851
|
+
description: "Known agent name to invoke (single mode; use names from the available agents list)",
|
|
852
|
+
})),
|
|
853
|
+
task: Type.Optional(Type.String({
|
|
854
|
+
description: "Full self-contained prompt text to delegate (single mode; plain string, subagents share no context with the caller)",
|
|
855
|
+
})),
|
|
809
856
|
tasks: Type.Optional(Type.Array(TaskItem, {
|
|
810
|
-
description: "
|
|
857
|
+
description: "Parallel batch of {agent, task} items for independent tasks (max 8, 4 run concurrently)",
|
|
858
|
+
minItems: 1,
|
|
811
859
|
})),
|
|
812
860
|
chain: Type.Optional(Type.Array(ChainItem, {
|
|
813
|
-
description: "
|
|
861
|
+
description: "Sequential steps of {agent, task}; {previous} substitutes the previous step's output (max 8 steps)",
|
|
862
|
+
minItems: 1,
|
|
814
863
|
})),
|
|
815
864
|
agentScope: Type.Optional(AgentScopeSchema),
|
|
816
865
|
confirmProjectAgents: Type.Optional(Type.Boolean({
|
|
@@ -837,11 +886,19 @@ export default function subagentExtension(ext, opts) {
|
|
|
837
886
|
"Delegate tasks to specialized subagents with isolated context.",
|
|
838
887
|
"Modes: single (agent + task), parallel (tasks array), chain (sequential with {previous} placeholder).",
|
|
839
888
|
'Default agent scope is "both" (user agents from ~/.spectral/agent/agents + project agents from .spectral/agents).',
|
|
840
|
-
'Set agentScope: "user" or "project" to limit scope.'
|
|
889
|
+
'Set agentScope: "user" or "project" to limit scope.',
|
|
890
|
+
"Exactly one mode per call.",
|
|
891
|
+
'Single (one task): {"agent":"researcher","task":"<full self-contained task text>"}',
|
|
892
|
+
'Parallel (independent tasks; max 8, 4 run concurrently): {"tasks":[{"agent":"researcher","task":"..."},{"agent":"executor","task":"..."}]}',
|
|
893
|
+
'Chain (dependent tasks; sequential): {"chain":[{"agent":"researcher","task":"..."},{"agent":"executor","task":"Implement {previous}"}]}',
|
|
894
|
+
"NEVER mix agent/task with tasks or chain in one call; never pass a single task via tasks (use single mode); task must be a plain string; use known agent names only.",
|
|
895
|
+
"Task texts must be fully self-contained prompts (subagents share no context with the caller).",
|
|
841
896
|
].join(" "),
|
|
842
897
|
promptSnippet: "Run a subagent to investigate, plan, review, or implement code changes",
|
|
843
898
|
promptGuidelines: [
|
|
844
899
|
"When the subagent tool is available, use it for non-trivial work where specialized delegation improves quality or speed, including bounded implementation, research, planning, review, and verification slices. Each subagent runs in an isolated context window.",
|
|
900
|
+
"Pick exactly one mode per call: one task → single {agent, task}; independent tasks → parallel {tasks: [...]} (max 8, 4 concurrent); dependent tasks → chain {chain: [...]} with {previous} substituting the prior step's output.",
|
|
901
|
+
"Task texts must be fully self-contained prompts (subagents share no context with the caller); never mix modes' fields (agent/task vs tasks/chain) in one call.",
|
|
845
902
|
],
|
|
846
903
|
parameters: SubagentParams,
|
|
847
904
|
async execute(_toolCallId, params, signal, onUpdate, ctx) {
|
|
@@ -951,7 +1008,7 @@ export default function subagentExtension(ext, opts) {
|
|
|
951
1008
|
content: [
|
|
952
1009
|
{
|
|
953
1010
|
type: "text",
|
|
954
|
-
text: `Invalid parameters. Provide exactly one mode.\nAvailable agents: ${available}`,
|
|
1011
|
+
text: `Invalid parameters. Provide exactly one mode.\nAvailable agents: ${available}\n\nExamples:\nSingle: {"agent":"researcher","task":"<full self-contained task text>"}\nParallel: {"tasks":[{"agent":"researcher","task":"..."},{"agent":"executor","task":"..."}]}\nChain: {"chain":[{"agent":"researcher","task":"..."},{"agent":"executor","task":"Implement {previous}"}]}\nRetry with exactly one of: agent+task | tasks | chain`,
|
|
955
1012
|
},
|
|
956
1013
|
],
|
|
957
1014
|
details: makeDetails("single")([]),
|
|
@@ -990,6 +1047,16 @@ export default function subagentExtension(ext, opts) {
|
|
|
990
1047
|
}
|
|
991
1048
|
// ── Chain mode ──────────────────────────────────────────────
|
|
992
1049
|
if (params.chain && params.chain.length > 0) {
|
|
1050
|
+
if (params.chain.length > MAX_CHAIN_STEPS)
|
|
1051
|
+
return {
|
|
1052
|
+
content: [
|
|
1053
|
+
{
|
|
1054
|
+
type: "text",
|
|
1055
|
+
text: `Too many chain steps (${params.chain.length}). Max is ${MAX_CHAIN_STEPS}.`,
|
|
1056
|
+
},
|
|
1057
|
+
],
|
|
1058
|
+
details: makeDetails("chain")([]),
|
|
1059
|
+
};
|
|
993
1060
|
const results = [];
|
|
994
1061
|
let previousOutput = "";
|
|
995
1062
|
for (let i = 0; i < params.chain.length; i++) {
|
|
@@ -1101,8 +1168,15 @@ export default function subagentExtension(ext, opts) {
|
|
|
1101
1168
|
});
|
|
1102
1169
|
const successCount = results.filter((r) => r.exitCode === 0).length;
|
|
1103
1170
|
const summaries = results.map((r) => {
|
|
1104
|
-
const
|
|
1105
|
-
const
|
|
1171
|
+
const completed = r.exitCode === 0;
|
|
1172
|
+
const finalOutput = getFinalOutput(r.messages);
|
|
1173
|
+
// Failed tasks with no transcript surface their error message /
|
|
1174
|
+
// stderr instead of a bare "(no output)" so the caller can see
|
|
1175
|
+
// why the task failed (e.g. unknown agent names).
|
|
1176
|
+
const output = truncateOutput(completed || finalOutput.trim()
|
|
1177
|
+
? finalOutput
|
|
1178
|
+
: r.errorMessage || r.stderr, SUBAGENT_OUTPUT_LIMIT);
|
|
1179
|
+
const status = completed
|
|
1106
1180
|
? "completed"
|
|
1107
1181
|
: r.attempts && r.attempts > 1
|
|
1108
1182
|
? `failed (after ${r.attempts} attempts)`
|
|
@@ -1117,6 +1191,7 @@ export default function subagentExtension(ext, opts) {
|
|
|
1117
1191
|
},
|
|
1118
1192
|
],
|
|
1119
1193
|
details: persistDetails(makeDetails("parallel")(results)),
|
|
1194
|
+
...(results.length > 0 && successCount === 0 ? { isError: true } : {}),
|
|
1120
1195
|
};
|
|
1121
1196
|
}
|
|
1122
1197
|
// ── Single mode ─────────────────────────────────────────────
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
*
|
|
35
35
|
* @module @spectral/backend/generated-images
|
|
36
36
|
*/
|
|
37
|
-
export type GeneratedImageKind = "generated" | "attachment";
|
|
37
|
+
export type GeneratedImageKind = "generated" | "attachment" | "video";
|
|
38
38
|
export type UploadStep = "upload-url" | "put" | "confirm";
|
|
39
39
|
export interface UploadImageOptions {
|
|
40
40
|
/** Backend base url, e.g. `https://api.aexol.ai` (no trailing slash needed). */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generated-images.d.ts","sourceRoot":"","sources":["../../src/backend/generated-images.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AAEH,MAAM,MAAM,kBAAkB,GAAG,WAAW,GAAG,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"generated-images.d.ts","sourceRoot":"","sources":["../../src/backend/generated-images.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"serve.d.ts","sourceRoot":"","sources":["../../src/commands/serve.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAwBH,OAAO,EAAE,WAAW,EAAmB,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"serve.d.ts","sourceRoot":"","sources":["../../src/commands/serve.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAwBH,OAAO,EAAE,WAAW,EAAmB,MAAM,oBAAoB,CAAC;AAclE,OAAO,KAAK,EAAE,aAAa,EAAc,MAAM,6BAA6B,CAAC;AAC7E,OAAO,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AAGnE,OAAO,EAAmB,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAarE;;;;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,CA8lBlF;AAmFD;;;GAGG;AACH,wBAAsB,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,cAAc,CAAC,CAc5E"}
|
package/dist/commands/serve.js
CHANGED
|
@@ -40,7 +40,7 @@ import { refreshCloudAgents as refreshCloudAgentsImpl } from "../agent/agents.js
|
|
|
40
40
|
import { requireLogin } from "../preflight.js";
|
|
41
41
|
import { RelayClient } from "../relay/client.js";
|
|
42
42
|
import { getFanoutManager } from "../server/fanout/fanout-manager.js";
|
|
43
|
-
import { detachAllSubscribers, handleAutoOptimizeFrame, handleAutoResearchFrame, handleCancelTurn, handleClientMessage, handleRestRequest, handleSubscribe, } from "../relay/dispatcher.js";
|
|
43
|
+
import { detachAllSubscribers, handleAutoOptimizeFrame, handleAutoResearchFrame, handleCancelTurn, handleClientMessage, handleRestRequest, handleStopToolCall, handleSubscribe, } from "../relay/dispatcher.js";
|
|
44
44
|
import { ensureMachineRegistered } from "../relay/registration.js";
|
|
45
45
|
import { saveMachine } from "../relay/machine-store.js";
|
|
46
46
|
import { SessionStreamManager } from "../server/session-stream.js";
|
|
@@ -350,6 +350,17 @@ export async function runServe(opts = {}) {
|
|
|
350
350
|
handleCancelTurn(frame, { manager });
|
|
351
351
|
return;
|
|
352
352
|
}
|
|
353
|
+
if (frame.kind === "stop_tool_call") {
|
|
354
|
+
// Per-tool-call stop: abort ONE hung tool call, keep the turn alive.
|
|
355
|
+
// Fire-and-forget with an internal catch — an unresolved settle must
|
|
356
|
+
// never hang the relay loop (the manager isolates per-call failures).
|
|
357
|
+
void handleStopToolCall(frame, {
|
|
358
|
+
manager,
|
|
359
|
+
}).catch((err) => {
|
|
360
|
+
process.stderr.write(`[serve] stop_tool_call failed: ${err instanceof Error ? err.message : String(err)}\n`);
|
|
361
|
+
});
|
|
362
|
+
return;
|
|
363
|
+
}
|
|
353
364
|
if (frame.kind === "auto_research") {
|
|
354
365
|
handleAutoResearchFrame(frame, {
|
|
355
366
|
store,
|
|
@@ -206,7 +206,7 @@ export interface LogicTraceExtensionOptions {
|
|
|
206
206
|
}
|
|
207
207
|
/**
|
|
208
208
|
* Logic trace extension entry point: automatic refresh hooks
|
|
209
|
-
* (`turn_end`, `session_before_compact`) plus the
|
|
209
|
+
* (`turn_end`, `session_before_compact`) plus the three agent tools.
|
|
210
210
|
*/
|
|
211
211
|
export declare function logicTraceExtension(ext: ExtensionAPI, options?: LogicTraceExtensionOptions): void;
|
|
212
212
|
export default logicTraceExtension;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"logic-trace.d.ts","sourceRoot":"","sources":["../../src/extensions/logic-trace.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"logic-trace.d.ts","sourceRoot":"","sources":["../../src/extensions/logic-trace.ts"],"names":[],"mappings":"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"}
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
* generic helpers from `../memory/` and never writes any memory state.
|
|
27
27
|
*/
|
|
28
28
|
import { existsSync, readFileSync, statSync } from "node:fs";
|
|
29
|
-
import { join } from "node:path";
|
|
29
|
+
import { isAbsolute, join } from "node:path";
|
|
30
30
|
import { Type } from "../sdk/ai/index.js";
|
|
31
31
|
import { agentLoop, uuidv7, } from "../sdk/agent-core/index.js";
|
|
32
32
|
import { getAgentDir, } from "../sdk/coding-agent/index.js";
|
|
@@ -776,6 +776,7 @@ async function attemptLogicTraceSync(deps) {
|
|
|
776
776
|
// ---------------------------------------------------------------------------
|
|
777
777
|
const LOGIC_TRACE_READ_TOOL_NAME = "remote_logic_trace_read";
|
|
778
778
|
const LOGIC_TRACE_WRITE_TOOL_NAME = "remote_logic_trace_write";
|
|
779
|
+
const LOGIC_TRACE_WRITE_FILE_TOOL_NAME = "remote_logic_trace_write_file";
|
|
779
780
|
const UNBOUND_TEXT = "No Aexol Studio project binding found in this directory.\n" +
|
|
780
781
|
"Use local_bind_project to link this directory to a Studio project (then read/write logic.aexol), " +
|
|
781
782
|
"or `spectral bind <project-id>` from the terminal.";
|
|
@@ -841,7 +842,9 @@ function buildWriteTool(ensureBackend) {
|
|
|
841
842
|
name: LOGIC_TRACE_WRITE_TOOL_NAME,
|
|
842
843
|
label: "Write Logic Trace",
|
|
843
844
|
description: `Manually upsert the ONE ${LOGIC_TRACE_REMOTE_PATH} file in the bound Aexol Studio project with a COMPLETE .aexol spec. ` +
|
|
844
|
-
`Merge, never append-only: read it first, then write the full updated file. Refresh it after meaningful business-logic changes
|
|
845
|
+
`Merge, never append-only: read it first, then write the full updated file. Refresh it after meaningful business-logic changes. ` +
|
|
846
|
+
`For large specs (roughly >150 lines) the inline \`content\` argument risks provider gateway timeouts while the whole merged spec streams as a single tool call — ` +
|
|
847
|
+
`instead write the merged spec to a local file (e.g. \`.aexol/logic.draft.aexol\`) and call ${LOGIC_TRACE_WRITE_FILE_TOOL_NAME}.`,
|
|
845
848
|
promptSnippet: `Use ${LOGIC_TRACE_WRITE_TOOL_NAME}(content, reason) to fully regenerate ${LOGIC_TRACE_REMOTE_PATH} (the ONE business-logic spec in the bound Studio project) after meaningful business-logic changes.`,
|
|
846
849
|
promptGuidelines: [
|
|
847
850
|
`There is EXACTLY ONE logic file per project: ${LOGIC_TRACE_REMOTE_PATH}. Never create extra spec files; never append changelogs into it.`,
|
|
@@ -849,87 +852,207 @@ function buildWriteTool(ensureBackend) {
|
|
|
849
852
|
"Only full-spec writes; this tool upserts (updates the existing file or creates it when missing) and never deletes it.",
|
|
850
853
|
"Use it after meaningful business-logic changes (new/changed types, enums, roles, workflows, agents); automatic refresh handles the rest.",
|
|
851
854
|
"The tool returns ✓ when the complete spec parses, and an Error with parser diagnostics when it does not.",
|
|
855
|
+
`For large specs (roughly >150 lines) the inline \`content\` argument risks provider timeouts — write the merged spec to a local file (e.g. \`.aexol/logic.draft.aexol\`) and use ${LOGIC_TRACE_WRITE_FILE_TOOL_NAME} instead.`,
|
|
852
856
|
],
|
|
853
857
|
parameters: WriteSchema,
|
|
854
858
|
async execute(_toolCallId, params, _signal, _onUpdate, ctx) {
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
}
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
859
|
+
return upsertLogicTraceFromAgent(ensureBackend, {
|
|
860
|
+
cwd: ctx.cwd,
|
|
861
|
+
content: params.content ?? "",
|
|
862
|
+
reason: params.reason ?? "",
|
|
863
|
+
hasUI: ctx.hasUI,
|
|
864
|
+
ui: ctx.ui,
|
|
865
|
+
});
|
|
866
|
+
},
|
|
867
|
+
};
|
|
868
|
+
}
|
|
869
|
+
/**
|
|
870
|
+
* Full manual-write flow shared by `remote_logic_trace_write`: resolve the
|
|
871
|
+
* bound backend, then run the shared upsert. Behavior and result messages are
|
|
872
|
+
* byte-identical to the pre-refactor single-tool implementation.
|
|
873
|
+
*/
|
|
874
|
+
async function upsertLogicTraceFromAgent(ensureBackend, input) {
|
|
875
|
+
const bound = await resolveBoundBackend(ensureBackend, input.cwd);
|
|
876
|
+
if (!bound.ok)
|
|
877
|
+
return bound.result;
|
|
878
|
+
return upsertLogicTrace({
|
|
879
|
+
backend: bound.backend,
|
|
880
|
+
binding: bound.binding,
|
|
881
|
+
cwd: input.cwd,
|
|
882
|
+
content: input.content,
|
|
883
|
+
reason: input.reason,
|
|
884
|
+
hasUI: input.hasUI,
|
|
885
|
+
ui: input.ui,
|
|
886
|
+
});
|
|
887
|
+
}
|
|
888
|
+
/**
|
|
889
|
+
* Shared prelude for the manual write tools: same explicit retry semantics as
|
|
890
|
+
* remote_logic_trace_read — this is the agent deliberately acting, so a
|
|
891
|
+
* memoized bootstrap failure may be re-attempted (and is unlocked on success).
|
|
892
|
+
*/
|
|
893
|
+
async function resolveBoundBackend(ensureBackend, cwd) {
|
|
894
|
+
const backend = await ensureBackend(cwd, { retry: true });
|
|
895
|
+
if (!backend.ok) {
|
|
896
|
+
return { ok: false, result: textResult(`Aexol backend unavailable: ${backend.message}`, true) };
|
|
897
|
+
}
|
|
898
|
+
const binding = await refreshBindingForCwd(cwd);
|
|
899
|
+
if (!binding)
|
|
900
|
+
return { ok: false, result: textResult(UNBOUND_TEXT, true) };
|
|
901
|
+
return { ok: true, backend, binding };
|
|
902
|
+
}
|
|
903
|
+
/**
|
|
904
|
+
* Shared tail for the manual write tools: trim → parser gate → mandatory
|
|
905
|
+
* list → update-or-create upsert → ack. Both `remote_logic_trace_write` and
|
|
906
|
+
* `remote_logic_trace_write_file` funnel through here so their remote
|
|
907
|
+
* behavior and result messages stay byte-identical.
|
|
908
|
+
*/
|
|
909
|
+
async function upsertLogicTrace(input) {
|
|
910
|
+
// EXPLICIT agent action: the content the agent deliberately wrote is
|
|
911
|
+
// stored verbatim (trim only) — the redaction pass is reserved for
|
|
912
|
+
// automatically drafted sync content, not for the agent's own
|
|
913
|
+
// deliberate full-spec write.
|
|
914
|
+
const content = input.content.trim();
|
|
915
|
+
if (!content) {
|
|
916
|
+
return textResult("Error: content (the complete .aexol spec) is required.", true);
|
|
917
|
+
}
|
|
918
|
+
// Parser-backed gate BEFORE any remote call: invalid content must
|
|
919
|
+
// neither mutate the cloud file nor even probe the project-file
|
|
920
|
+
// listing, so writes fail fast with parser diagnostics instead of
|
|
921
|
+
// storing a spec the Aexol toolchain cannot read.
|
|
922
|
+
const validation = validateLogicTraceSpec(content);
|
|
923
|
+
if (!validation.ok) {
|
|
924
|
+
return textResult("Error: content is not a valid .aexol spec.\n" + formatSpecErrors(validation), true);
|
|
925
|
+
}
|
|
926
|
+
try {
|
|
927
|
+
// Manual upsert: list (mandatory — create silently no-ops when the
|
|
928
|
+
// path already exists) then update-or-create. No LLM, no dedupe.
|
|
929
|
+
const remote = await fetchRemoteLogicFile(input.backend.client, input.binding.projectId, input.binding.teamId);
|
|
930
|
+
const state = stateFor(input.cwd);
|
|
931
|
+
state.remote = {
|
|
932
|
+
id: remote.id,
|
|
933
|
+
contentHash: remote.content !== undefined ? hashId(remote.content) : undefined,
|
|
934
|
+
};
|
|
935
|
+
// Every remote_* call carries the binding ids (projectId + teamId
|
|
936
|
+
// when present) so team access resolves to the BOUND project, not
|
|
937
|
+
// to the first team membership of the user token.
|
|
938
|
+
const teamArg = input.binding.teamId ? { teamId: input.binding.teamId } : {};
|
|
939
|
+
let id;
|
|
940
|
+
if (remote.id) {
|
|
941
|
+
const res = await input.backend.client.callTool("remote_update_project_file", {
|
|
942
|
+
id: remote.id,
|
|
943
|
+
content,
|
|
944
|
+
projectId: input.binding.projectId,
|
|
945
|
+
...teamArg,
|
|
946
|
+
});
|
|
947
|
+
if (res.isError)
|
|
948
|
+
return textResult(`Failed to update ${LOGIC_TRACE_REMOTE_PATH}: ${toolResultText(res)}`, true);
|
|
949
|
+
id = remote.id;
|
|
950
|
+
}
|
|
951
|
+
else {
|
|
952
|
+
const res = await input.backend.client.callTool("remote_create_project_file", {
|
|
953
|
+
path: LOGIC_TRACE_REMOTE_PATH,
|
|
954
|
+
content,
|
|
955
|
+
projectId: input.binding.projectId,
|
|
956
|
+
...teamArg,
|
|
957
|
+
});
|
|
958
|
+
if (res.isError)
|
|
959
|
+
return textResult(`Failed to create ${LOGIC_TRACE_REMOTE_PATH}: ${toolResultText(res)}`, true);
|
|
960
|
+
id = extractCreatedFileId(res.content);
|
|
961
|
+
}
|
|
962
|
+
const contentHash = hashId(content);
|
|
963
|
+
state.remote = { id: id ?? null, contentHash };
|
|
964
|
+
notifyWith({ hasUI: input.hasUI, ui: input.ui }, `logic.aexol updated in project ${input.binding.name ?? input.binding.projectId}`);
|
|
965
|
+
return textResult(`✓ ${LOGIC_TRACE_REMOTE_PATH} ${remote.id ? "updated" : "created"} ` +
|
|
966
|
+
`(project ${input.binding.name ?? input.binding.projectId}, reason: ${input.reason.trim()}).` +
|
|
967
|
+
(input.ackSuffix ?? ""));
|
|
968
|
+
}
|
|
969
|
+
catch (err) {
|
|
970
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
971
|
+
return textResult(`Failed to write ${LOGIC_TRACE_REMOTE_PATH}: ${msg}`, true);
|
|
972
|
+
}
|
|
973
|
+
}
|
|
974
|
+
/**
|
|
975
|
+
* The `-file` variant of the manual write: reads the COMPLETE merged spec
|
|
976
|
+
* from a LOCAL file instead of a giant inline `content` argument, so agents
|
|
977
|
+
* pushing large specs avoid the provider gateway timeouts that streaming one
|
|
978
|
+
* huge tool-call argument can trigger. Validation + upsert are identical to
|
|
979
|
+
* `remote_logic_trace_write` (same helpers, same messages).
|
|
980
|
+
*/
|
|
981
|
+
function buildWriteFileTool(ensureBackend) {
|
|
982
|
+
const WriteFileSchema = Type.Object({
|
|
983
|
+
path: Type.String({
|
|
984
|
+
minLength: 1,
|
|
985
|
+
description: "Path to a LOCAL file holding the COMPLETE merged .aexol spec (e.g. `.aexol/logic.draft.aexol`). Relative to the working directory or absolute.",
|
|
986
|
+
}),
|
|
987
|
+
reason: Type.String({
|
|
988
|
+
minLength: 1,
|
|
989
|
+
description: "Why this full-spec update is needed (echoed in the ack).",
|
|
990
|
+
}),
|
|
991
|
+
});
|
|
992
|
+
return {
|
|
993
|
+
name: LOGIC_TRACE_WRITE_FILE_TOOL_NAME,
|
|
994
|
+
label: "Write Logic Trace From File",
|
|
995
|
+
description: `Manually upsert the ONE ${LOGIC_TRACE_REMOTE_PATH} file in the bound Aexol Studio project from a LOCAL file on disk. ` +
|
|
996
|
+
`Reads the file, validates it with the same parser gate as ${LOGIC_TRACE_WRITE_TOOL_NAME}, then performs the identical list-first create/update upsert. ` +
|
|
997
|
+
`Merge, never append-only: read ${LOGIC_TRACE_REMOTE_PATH} first, write the FULL merged spec to a local file (e.g. \`.aexol/logic.draft.aexol\`), then call this tool. ` +
|
|
998
|
+
`PREFERRED for large specs (roughly >150 lines): passing the spec as a local file avoids the provider gateway timeouts a giant inline \`content\` argument risks while streaming a single tool call.`,
|
|
999
|
+
promptSnippet: `Use ${LOGIC_TRACE_WRITE_FILE_TOOL_NAME}(path, reason) to upsert ${LOGIC_TRACE_REMOTE_PATH} (the ONE business-logic spec in the bound Studio project) from a local .aexol file — the preferred path for large specs (>150 lines).`,
|
|
1000
|
+
promptGuidelines: [
|
|
1001
|
+
`There is EXACTLY ONE logic file per project: ${LOGIC_TRACE_REMOTE_PATH}. Never create extra spec files; never append changelogs into it.`,
|
|
1002
|
+
`Always ${LOGIC_TRACE_READ_TOOL_NAME} before writing, and write the FULL merged spec to the local file — not a diff, not an appendix.`,
|
|
1003
|
+
"Only full-spec writes; this tool upserts (updates the existing file or creates it when missing) and never deletes it.",
|
|
1004
|
+
`The tool returns ✓ (with the source file and its line count) when the complete spec parses, and an Error with parser diagnostics when it does not.`,
|
|
1005
|
+
`For large specs (roughly >150 lines) prefer this file-based write: giant inline \`content\` arguments on ${LOGIC_TRACE_WRITE_TOOL_NAME} risk provider timeouts.`,
|
|
1006
|
+
],
|
|
1007
|
+
parameters: WriteFileSchema,
|
|
1008
|
+
async execute(_toolCallId, params, _signal, _onUpdate, ctx) {
|
|
1009
|
+
const rawPath = (params.path ?? "").trim();
|
|
1010
|
+
if (!rawPath) {
|
|
1011
|
+
return textResult("Error: path (the local .aexol file holding the complete spec) is required.", true);
|
|
880
1012
|
}
|
|
1013
|
+
const filePath = isAbsolute(rawPath) ? rawPath : join(ctx.cwd, rawPath);
|
|
1014
|
+
// Same explicit retry semantics as the other manual tools (see
|
|
1015
|
+
// resolveBoundBackend).
|
|
1016
|
+
const bound = await resolveBoundBackend(ensureBackend, ctx.cwd);
|
|
1017
|
+
if (!bound.ok)
|
|
1018
|
+
return bound.result;
|
|
1019
|
+
let content;
|
|
881
1020
|
try {
|
|
882
|
-
|
|
883
|
-
// path already exists) then update-or-create. No LLM, no dedupe.
|
|
884
|
-
const remote = await fetchRemoteLogicFile(backend.client, binding.projectId, binding.teamId);
|
|
885
|
-
const state = stateFor(ctx.cwd);
|
|
886
|
-
state.remote = {
|
|
887
|
-
id: remote.id,
|
|
888
|
-
contentHash: remote.content !== undefined ? hashId(remote.content) : undefined,
|
|
889
|
-
};
|
|
890
|
-
// Every remote_* call carries the binding ids (projectId + teamId
|
|
891
|
-
// when present) so team access resolves to the BOUND project, not
|
|
892
|
-
// to the first team membership of the user token.
|
|
893
|
-
const teamArg = binding.teamId ? { teamId: binding.teamId } : {};
|
|
894
|
-
let id;
|
|
895
|
-
if (remote.id) {
|
|
896
|
-
const res = await backend.client.callTool("remote_update_project_file", {
|
|
897
|
-
id: remote.id,
|
|
898
|
-
content,
|
|
899
|
-
projectId: binding.projectId,
|
|
900
|
-
...teamArg,
|
|
901
|
-
});
|
|
902
|
-
if (res.isError)
|
|
903
|
-
return textResult(`Failed to update ${LOGIC_TRACE_REMOTE_PATH}: ${toolResultText(res)}`, true);
|
|
904
|
-
id = remote.id;
|
|
905
|
-
}
|
|
906
|
-
else {
|
|
907
|
-
const res = await backend.client.callTool("remote_create_project_file", {
|
|
908
|
-
path: LOGIC_TRACE_REMOTE_PATH,
|
|
909
|
-
content,
|
|
910
|
-
projectId: binding.projectId,
|
|
911
|
-
...teamArg,
|
|
912
|
-
});
|
|
913
|
-
if (res.isError)
|
|
914
|
-
return textResult(`Failed to create ${LOGIC_TRACE_REMOTE_PATH}: ${toolResultText(res)}`, true);
|
|
915
|
-
id = extractCreatedFileId(res.content);
|
|
916
|
-
}
|
|
917
|
-
const contentHash = hashId(content);
|
|
918
|
-
state.remote = { id: id ?? null, contentHash };
|
|
919
|
-
notifyWith({ hasUI: ctx.hasUI, ui: ctx.ui }, `logic.aexol updated in project ${binding.name ?? binding.projectId}`);
|
|
920
|
-
return textResult(`✓ ${LOGIC_TRACE_REMOTE_PATH} ${remote.id ? "updated" : "created"} ` +
|
|
921
|
-
`(project ${binding.name ?? binding.projectId}, reason: ${params.reason.trim()}).`);
|
|
1021
|
+
content = readFileSync(filePath, "utf-8");
|
|
922
1022
|
}
|
|
923
1023
|
catch (err) {
|
|
924
|
-
const
|
|
925
|
-
|
|
1024
|
+
const code = err.code;
|
|
1025
|
+
const detail = code === "ENOENT"
|
|
1026
|
+
? "file does not exist"
|
|
1027
|
+
: code === "EISDIR"
|
|
1028
|
+
? "path is a directory, not a file"
|
|
1029
|
+
: code === "EACCES" || code === "EPERM"
|
|
1030
|
+
? "file is not readable"
|
|
1031
|
+
: `failed to read (${code ?? "unknown error"})`;
|
|
1032
|
+
return textResult(`Error: cannot read "${rawPath}": ${detail}.`, true);
|
|
1033
|
+
}
|
|
1034
|
+
if (content.charCodeAt(0) === 0xfeff)
|
|
1035
|
+
content = content.slice(1); // strip BOM
|
|
1036
|
+
if (!content.trim()) {
|
|
1037
|
+
return textResult(`Error: "${rawPath}" is empty — no .aexol spec content to write.`, true);
|
|
926
1038
|
}
|
|
1039
|
+
const lineCount = content.split("\n").length;
|
|
1040
|
+
return upsertLogicTrace({
|
|
1041
|
+
backend: bound.backend,
|
|
1042
|
+
binding: bound.binding,
|
|
1043
|
+
cwd: ctx.cwd,
|
|
1044
|
+
content,
|
|
1045
|
+
reason: params.reason ?? "",
|
|
1046
|
+
hasUI: ctx.hasUI,
|
|
1047
|
+
ui: ctx.ui,
|
|
1048
|
+
ackSuffix: ` Source: ${filePath} (${lineCount} lines).`,
|
|
1049
|
+
});
|
|
927
1050
|
},
|
|
928
1051
|
};
|
|
929
1052
|
}
|
|
930
1053
|
/**
|
|
931
1054
|
* Logic trace extension entry point: automatic refresh hooks
|
|
932
|
-
* (`turn_end`, `session_before_compact`) plus the
|
|
1055
|
+
* (`turn_end`, `session_before_compact`) plus the three agent tools.
|
|
933
1056
|
*/
|
|
934
1057
|
export function logicTraceExtension(ext, options = {}) {
|
|
935
1058
|
const draftRunner = options.draftRunner ?? runLogicTraceDraft;
|
|
@@ -992,6 +1115,12 @@ export function logicTraceExtension(ext, options = {}) {
|
|
|
992
1115
|
catch (err) {
|
|
993
1116
|
process.stderr.write(`[logic-trace] Failed to register ${LOGIC_TRACE_WRITE_TOOL_NAME}: ${err instanceof Error ? err.message : String(err)}\n`);
|
|
994
1117
|
}
|
|
1118
|
+
try {
|
|
1119
|
+
ext.registerTool(buildWriteFileTool(ensureBackend));
|
|
1120
|
+
}
|
|
1121
|
+
catch (err) {
|
|
1122
|
+
process.stderr.write(`[logic-trace] Failed to register ${LOGIC_TRACE_WRITE_FILE_TOOL_NAME}: ${err instanceof Error ? err.message : String(err)}\n`);
|
|
1123
|
+
}
|
|
995
1124
|
ext.on("session_start", async (_event, ctx) => {
|
|
996
1125
|
const config = loadLogicTraceConfig(ctx.cwd);
|
|
997
1126
|
if (config.passive)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/extensions/video-generation/index.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAmB,YAAY,EAAkB,MAAM,iCAAiC,CAAC;AA+NrG,wBAA8B,wBAAwB,CAAC,GAAG,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAsGvF"}
|