openfox 1.6.14 → 1.6.16
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/{auto-compaction-C4PMBB24.js → auto-compaction-2RKC6DC2.js} +5 -5
- package/dist/{chat-handler-US3QOOE4.js → chat-handler-IY2XVOO6.js} +26 -56
- package/dist/{chunk-7HLRI6JM.js → chunk-2KP34IDL.js} +161 -204
- package/dist/{chunk-N25QUEPO.js → chunk-4OI4VPZ6.js} +434 -812
- package/dist/{chunk-XFXOSPYH.js → chunk-55N6FAAZ.js} +1 -1
- package/dist/{chunk-5GE3QJSZ.js → chunk-6L3X7T4K.js} +82 -160
- package/dist/{chunk-QDEKU5RL.js → chunk-F54ZJN4X.js} +38 -2
- package/dist/{chunk-UL4JYQKK.js → chunk-IN5EP4ZB.js} +2 -2
- package/dist/{chunk-OOIRCXAY.js → chunk-KOUMYBYM.js} +53 -112
- package/dist/{chunk-3JU6H6A4.js → chunk-NN65D5SI.js} +426 -448
- package/dist/{chunk-3XZ23PXM.js → chunk-OVLFEBRR.js} +76 -92
- package/dist/chunk-SN7OBEVL.js +44 -0
- package/dist/{chunk-PCOG5FQD.js → chunk-T5PBG2PE.js} +6 -6
- package/dist/{chunk-H22VHHQ4.js → chunk-U54QVKL2.js} +4 -4
- package/dist/{chunk-J2DHVXRX.js → chunk-ZDNXCVW4.js} +2 -2
- package/dist/cli/dev.js +1 -1
- package/dist/cli/index.js +1 -1
- package/dist/{config-DEM6ASQM.js → config-67AX6CNS.js} +5 -5
- package/dist/{events-VDAC7E7K.js → events-2ETDOE5B.js} +3 -3
- package/dist/{folding-NDFQCISZ.js → folding-M7FMUBOL.js} +6 -4
- package/dist/{orchestrator-KZI7B5IS.js → orchestrator-U5VCLBYQ.js} +6 -6
- package/dist/package.json +13 -3
- package/dist/{processor-KBSF2HFD.js → processor-VUEJM73B.js} +24 -49
- package/dist/{provider-K3PHZO27.js → provider-DKGBQHUS.js} +7 -7
- package/dist/{serve-DERN4AB6.js → serve-GOLQMQFA.js} +12 -12
- package/dist/server/index.d.ts +2 -0
- package/dist/server/index.js +10 -10
- package/dist/{tools-PLVK22CF.js → tools-55YICCVH.js} +5 -5
- package/dist/{vision-fallback-NOC3YYIB.js → vision-fallback-ADYRFFD4.js} +2 -2
- package/dist/web/assets/index-CZBXRYpK.js +150 -0
- package/dist/web/assets/{index-MCWDS5UQ.css → index-D4V7Gtvt.css} +1 -1
- package/dist/web/index.html +2 -2
- package/dist/web/sw.js +1 -1
- package/package.json +13 -3
- package/dist/web/assets/index-Ccy2Csbl.js +0 -150
- /package/dist/{command-defaults → server/commands/defaults}/commit-push.command.md +0 -0
- /package/dist/{command-defaults → server/commands/defaults}/init.command.md +0 -0
- /package/dist/{command-defaults → server/commands/defaults}/test-ui.command.md +0 -0
- /package/dist/{skill-defaults → server/skills/defaults}/browser.skill.md +0 -0
|
@@ -13,12 +13,12 @@ import {
|
|
|
13
13
|
} from "./chunk-574HZVLE.js";
|
|
14
14
|
import {
|
|
15
15
|
streamWithSegments
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-55N6FAAZ.js";
|
|
17
17
|
import {
|
|
18
18
|
getContextMessages,
|
|
19
19
|
getCurrentContextWindowId,
|
|
20
20
|
getEventStore
|
|
21
|
-
} from "./chunk-
|
|
21
|
+
} from "./chunk-6L3X7T4K.js";
|
|
22
22
|
import {
|
|
23
23
|
createChatDoneMessage,
|
|
24
24
|
createChatMessageMessage,
|
|
@@ -34,6 +34,7 @@ import {
|
|
|
34
34
|
} from "./chunk-22CTURMH.js";
|
|
35
35
|
import {
|
|
36
36
|
SETTINGS_KEYS,
|
|
37
|
+
deleteSetting,
|
|
37
38
|
getSetting,
|
|
38
39
|
setSetting
|
|
39
40
|
} from "./chunk-7IOZFJBW.js";
|
|
@@ -375,6 +376,31 @@ You may use available tools to read files and verify changes if needed.`;
|
|
|
375
376
|
var FORMAT_CORRECTION_PROMPT = `IMPORTANT: You MUST use the JSON function calling API. Do NOT output XML tags like <tool_call>, <function=>, or <parameter=>. Your previous attempt was stopped because you used the wrong format. Use the proper tool_calls format.`;
|
|
376
377
|
|
|
377
378
|
// src/server/chat/request-context.ts
|
|
379
|
+
function minimalMessagesToRequestContextMessages(messages, source = "history") {
|
|
380
|
+
return messages.map((message) => minimalMessageToRequestContextMessage(message, source));
|
|
381
|
+
}
|
|
382
|
+
function spreadMessageProps(message) {
|
|
383
|
+
return {
|
|
384
|
+
...message.toolCalls ? { toolCalls: message.toolCalls } : {},
|
|
385
|
+
...message.toolCallId ? { toolCallId: message.toolCallId } : {},
|
|
386
|
+
...message.attachments ? { attachments: message.attachments } : {}
|
|
387
|
+
};
|
|
388
|
+
}
|
|
389
|
+
function minimalMessageToRequestContextMessage(message, source = "history") {
|
|
390
|
+
return {
|
|
391
|
+
role: message.role,
|
|
392
|
+
content: message.content,
|
|
393
|
+
source,
|
|
394
|
+
...spreadMessageProps(message)
|
|
395
|
+
};
|
|
396
|
+
}
|
|
397
|
+
function messageToMinimal(message) {
|
|
398
|
+
return {
|
|
399
|
+
role: message.role,
|
|
400
|
+
content: message.content,
|
|
401
|
+
...spreadMessageProps(message)
|
|
402
|
+
};
|
|
403
|
+
}
|
|
378
404
|
function getTriggerUserMessage(messages) {
|
|
379
405
|
const stripRuntimeReminders = (content) => {
|
|
380
406
|
return content.replace(/\n*<system-reminder>[\s\S]*<\/system-reminder>\s*/gi, "").trim();
|
|
@@ -396,12 +422,8 @@ function createPromptContext(input) {
|
|
|
396
422
|
injectedFiles: input.injectedFiles,
|
|
397
423
|
userMessage: input.userMessage ?? getTriggerUserMessage(input.messages),
|
|
398
424
|
messages: input.messages.map((message) => ({
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
source: message.source,
|
|
402
|
-
...message.toolCalls ? { toolCalls: message.toolCalls } : {},
|
|
403
|
-
...message.toolCallId ? { toolCallId: message.toolCallId } : {},
|
|
404
|
-
...message.attachments ? { attachments: message.attachments } : {}
|
|
425
|
+
...messageToMinimal(message),
|
|
426
|
+
source: message.source
|
|
405
427
|
})),
|
|
406
428
|
tools: input.requestTools.map((tool) => ({
|
|
407
429
|
name: tool.function.name,
|
|
@@ -419,19 +441,25 @@ function createAssemblyResult(input) {
|
|
|
419
441
|
const messagesForLLM = input.messages.filter((m) => m.source !== "runtime");
|
|
420
442
|
return {
|
|
421
443
|
systemPrompt: input.systemPrompt,
|
|
422
|
-
messages: messagesForLLM.map((message) => (
|
|
423
|
-
role: message.role,
|
|
424
|
-
content: message.content,
|
|
425
|
-
...message.toolCalls ? { toolCalls: message.toolCalls } : {},
|
|
426
|
-
...message.toolCallId ? { toolCallId: message.toolCallId } : {},
|
|
427
|
-
...message.attachments ? { attachments: message.attachments } : {}
|
|
428
|
-
})),
|
|
444
|
+
messages: messagesForLLM.map((message) => messageToMinimal(message)),
|
|
429
445
|
promptContext: createPromptContext({
|
|
430
446
|
...input,
|
|
431
447
|
userMessage: triggerUserMessage
|
|
432
448
|
})
|
|
433
449
|
};
|
|
434
450
|
}
|
|
451
|
+
function buildAssemblyInput(systemPrompt, baseInput) {
|
|
452
|
+
return createAssemblyResult({
|
|
453
|
+
systemPrompt,
|
|
454
|
+
messages: baseInput.messages,
|
|
455
|
+
injectedFiles: baseInput.injectedFiles,
|
|
456
|
+
requestTools: baseInput.requestTools ?? baseInput.promptTools,
|
|
457
|
+
toolChoice: baseInput.toolChoice ?? "auto",
|
|
458
|
+
disableThinking: baseInput.disableThinking ?? false,
|
|
459
|
+
...baseInput.customInstructions ? { customInstructions: baseInput.customInstructions } : {},
|
|
460
|
+
...baseInput.skills && baseInput.skills.length > 0 ? { skills: baseInput.skills } : {}
|
|
461
|
+
});
|
|
462
|
+
}
|
|
435
463
|
function assembleAgentRequest(input) {
|
|
436
464
|
const { agentDef, subAgentDefs, ...baseInput } = input;
|
|
437
465
|
if (agentDef.metadata.subagent) {
|
|
@@ -440,14 +468,7 @@ function assembleAgentRequest(input) {
|
|
|
440
468
|
agentDef,
|
|
441
469
|
baseInput.skills
|
|
442
470
|
);
|
|
443
|
-
return
|
|
444
|
-
systemPrompt: systemPrompt2,
|
|
445
|
-
messages: baseInput.messages,
|
|
446
|
-
injectedFiles: baseInput.injectedFiles,
|
|
447
|
-
requestTools: baseInput.requestTools ?? baseInput.promptTools,
|
|
448
|
-
toolChoice: baseInput.toolChoice ?? "auto",
|
|
449
|
-
disableThinking: baseInput.disableThinking ?? false
|
|
450
|
-
});
|
|
471
|
+
return buildAssemblyInput(systemPrompt2, baseInput);
|
|
451
472
|
}
|
|
452
473
|
const systemPrompt = buildTopLevelSystemPrompt(
|
|
453
474
|
baseInput.workdir,
|
|
@@ -455,14 +476,25 @@ function assembleAgentRequest(input) {
|
|
|
455
476
|
baseInput.skills,
|
|
456
477
|
subAgentDefs
|
|
457
478
|
);
|
|
458
|
-
return
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
479
|
+
return buildAssemblyInput(systemPrompt, baseInput);
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
// src/server/chat/stream-utils.ts
|
|
483
|
+
function buildStreamRequestObject(params) {
|
|
484
|
+
const { messages, tools, toolChoice, disableThinking, signal, onVisionFallbackStart, onVisionFallbackDone } = params;
|
|
485
|
+
const streamRequest = {
|
|
486
|
+
messages,
|
|
487
|
+
...tools && { tools },
|
|
488
|
+
...toolChoice && { toolChoice },
|
|
489
|
+
disableThinking: disableThinking ?? false,
|
|
490
|
+
...signal && { signal }
|
|
491
|
+
};
|
|
492
|
+
if (onVisionFallbackStart) streamRequest.onVisionFallbackStart = onVisionFallbackStart;
|
|
493
|
+
if (onVisionFallbackDone) streamRequest.onVisionFallbackDone = onVisionFallbackDone;
|
|
494
|
+
return streamRequest;
|
|
495
|
+
}
|
|
496
|
+
function buildStreamRequest(client, options) {
|
|
497
|
+
return streamWithSegments(client, buildStreamRequestObject(options));
|
|
466
498
|
}
|
|
467
499
|
|
|
468
500
|
// src/server/chat/stats.ts
|
|
@@ -483,19 +515,29 @@ function computeAggregatedStats(input) {
|
|
|
483
515
|
}
|
|
484
516
|
|
|
485
517
|
// src/server/chat/stream-pure.ts
|
|
518
|
+
function createEmptyStreamResult(aborted, xmlFormatError) {
|
|
519
|
+
return {
|
|
520
|
+
content: "",
|
|
521
|
+
toolCalls: [],
|
|
522
|
+
segments: [],
|
|
523
|
+
usage: { promptTokens: 0, completionTokens: 0 },
|
|
524
|
+
timing: { ttft: 0, completionTime: 0, tps: 0, prefillTps: 0 },
|
|
525
|
+
aborted,
|
|
526
|
+
xmlFormatError
|
|
527
|
+
};
|
|
528
|
+
}
|
|
486
529
|
async function* streamLLMPure(options) {
|
|
487
530
|
const { messageId, systemPrompt, llmClient, messages, tools, toolChoice, signal, disableThinking, onVisionFallbackStart, onVisionFallbackDone } = options;
|
|
488
531
|
const llmMessages = [{ role: "system", content: systemPrompt }, ...messages];
|
|
489
|
-
const
|
|
532
|
+
const stream = buildStreamRequest(llmClient, {
|
|
490
533
|
messages: llmMessages,
|
|
491
|
-
|
|
492
|
-
|
|
534
|
+
tools,
|
|
535
|
+
toolChoice,
|
|
493
536
|
disableThinking: disableThinking ?? false,
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
const stream = streamWithSegments(llmClient, streamRequest);
|
|
537
|
+
signal,
|
|
538
|
+
onVisionFallbackStart,
|
|
539
|
+
onVisionFallbackDone
|
|
540
|
+
});
|
|
499
541
|
const seenToolIndices = /* @__PURE__ */ new Set();
|
|
500
542
|
const toolNames = /* @__PURE__ */ new Map();
|
|
501
543
|
const toolIds = /* @__PURE__ */ new Map();
|
|
@@ -594,15 +636,7 @@ async function* streamLLMPure(options) {
|
|
|
594
636
|
}
|
|
595
637
|
}
|
|
596
638
|
if (!result) {
|
|
597
|
-
return
|
|
598
|
-
content: "",
|
|
599
|
-
toolCalls: [],
|
|
600
|
-
segments: [],
|
|
601
|
-
usage: { promptTokens: 0, completionTokens: 0 },
|
|
602
|
-
timing: { ttft: 0, completionTime: 0, tps: 0, prefillTps: 0 },
|
|
603
|
-
aborted,
|
|
604
|
-
xmlFormatError
|
|
605
|
-
};
|
|
639
|
+
return createEmptyStreamResult(aborted, xmlFormatError);
|
|
606
640
|
}
|
|
607
641
|
const baseResult = {
|
|
608
642
|
content: result.content,
|
|
@@ -768,15 +802,7 @@ async function consumeStreamWithToolLoop(options) {
|
|
|
768
802
|
let iterations = 0;
|
|
769
803
|
for (; ; ) {
|
|
770
804
|
if (signal?.aborted) {
|
|
771
|
-
return
|
|
772
|
-
content: "",
|
|
773
|
-
toolCalls: [],
|
|
774
|
-
segments: [],
|
|
775
|
-
usage: { promptTokens: 0, completionTokens: 0 },
|
|
776
|
-
timing: { ttft: 0, completionTime: 0, tps: 0, prefillTps: 0 },
|
|
777
|
-
aborted: true,
|
|
778
|
-
xmlFormatError: false
|
|
779
|
-
};
|
|
805
|
+
return createEmptyStreamResult(true, false);
|
|
780
806
|
}
|
|
781
807
|
if (++iterations > MAX_TOOL_LOOP_ITERATIONS) {
|
|
782
808
|
throw new Error("Max tool loop iterations exceeded during compaction");
|
|
@@ -844,7 +870,7 @@ async function consumeStreamWithToolLoop(options) {
|
|
|
844
870
|
}
|
|
845
871
|
async function executeToolBatchWithContext(assistantMsgId, toolCalls, ctx, onEvent) {
|
|
846
872
|
const toolMessages = [];
|
|
847
|
-
|
|
873
|
+
const criteriaChanged = false;
|
|
848
874
|
for (const toolCall of toolCalls) {
|
|
849
875
|
if (ctx.signal?.aborted) {
|
|
850
876
|
throw new Error("Aborted");
|
|
@@ -884,7 +910,7 @@ Error: ${toolResult.error}` : `Error: ${toolResult.error}`;
|
|
|
884
910
|
}
|
|
885
911
|
|
|
886
912
|
// src/server/agents/registry.ts
|
|
887
|
-
import { readdir, readFile as readFile2, writeFile,
|
|
913
|
+
import { readdir, readFile as readFile2, writeFile, mkdir, access as access2, unlink } from "fs/promises";
|
|
888
914
|
import { join as join2, dirname as dirname2 } from "path";
|
|
889
915
|
import { constants as constants2 } from "fs";
|
|
890
916
|
import { fileURLToPath } from "url";
|
|
@@ -904,37 +930,6 @@ async function pathExists(path) {
|
|
|
904
930
|
return false;
|
|
905
931
|
}
|
|
906
932
|
}
|
|
907
|
-
async function ensureDefaultAgents(configDir) {
|
|
908
|
-
const agentsDir = getAgentsDir(configDir);
|
|
909
|
-
if (!await pathExists(agentsDir)) {
|
|
910
|
-
await mkdir(agentsDir, { recursive: true });
|
|
911
|
-
}
|
|
912
|
-
let defaultFiles;
|
|
913
|
-
let sourceDir;
|
|
914
|
-
try {
|
|
915
|
-
defaultFiles = (await readdir(DEFAULTS_DIR)).filter((f) => f.endsWith(AGENT_EXTENSION));
|
|
916
|
-
sourceDir = DEFAULTS_DIR;
|
|
917
|
-
} catch {
|
|
918
|
-
try {
|
|
919
|
-
defaultFiles = (await readdir(DEFAULTS_DIR_ALT)).filter((f) => f.endsWith(AGENT_EXTENSION));
|
|
920
|
-
sourceDir = DEFAULTS_DIR_ALT;
|
|
921
|
-
} catch {
|
|
922
|
-
logger.warn("No bundled agent defaults found", { dir: DEFAULTS_DIR });
|
|
923
|
-
return;
|
|
924
|
-
}
|
|
925
|
-
}
|
|
926
|
-
for (const file of defaultFiles) {
|
|
927
|
-
const targetPath = join2(agentsDir, file);
|
|
928
|
-
if (!await pathExists(targetPath)) {
|
|
929
|
-
try {
|
|
930
|
-
await copyFile(join2(sourceDir, file), targetPath);
|
|
931
|
-
logger.info("Installed default agent", { file });
|
|
932
|
-
} catch (err) {
|
|
933
|
-
logger.error("Failed to copy default agent", { file, error: err instanceof Error ? err.message : String(err) });
|
|
934
|
-
}
|
|
935
|
-
}
|
|
936
|
-
}
|
|
937
|
-
}
|
|
938
933
|
function parseAgentFile(raw, filename) {
|
|
939
934
|
const { data, content } = matter(raw);
|
|
940
935
|
const meta = data;
|
|
@@ -977,13 +972,21 @@ async function loadAgentsFromDir(dir) {
|
|
|
977
972
|
}
|
|
978
973
|
return agents;
|
|
979
974
|
}
|
|
975
|
+
async function loadDefaultAgents() {
|
|
976
|
+
const agents = await loadAgentsFromDir(DEFAULTS_DIR);
|
|
977
|
+
if (agents.length > 0) return agents;
|
|
978
|
+
return loadAgentsFromDir(DEFAULTS_DIR_ALT);
|
|
979
|
+
}
|
|
980
|
+
async function loadUserAgents(configDir) {
|
|
981
|
+
return loadAgentsFromDir(getAgentsDir(configDir));
|
|
982
|
+
}
|
|
980
983
|
async function loadAllAgents(configDir) {
|
|
981
|
-
const [
|
|
982
|
-
|
|
983
|
-
|
|
984
|
+
const [defaultAgents, userAgents] = await Promise.all([
|
|
985
|
+
loadDefaultAgents(),
|
|
986
|
+
loadUserAgents(configDir)
|
|
984
987
|
]);
|
|
985
988
|
const agentMap = /* @__PURE__ */ new Map();
|
|
986
|
-
for (const agent of
|
|
989
|
+
for (const agent of defaultAgents) {
|
|
987
990
|
agentMap.set(agent.metadata.id, agent);
|
|
988
991
|
}
|
|
989
992
|
for (const agent of userAgents) {
|
|
@@ -996,14 +999,9 @@ async function loadAllAgentsDefault() {
|
|
|
996
999
|
const configDir = getGlobalConfigDir(getRuntimeConfig().mode ?? "production");
|
|
997
1000
|
return await loadAllAgents(configDir);
|
|
998
1001
|
} catch {
|
|
999
|
-
return
|
|
1002
|
+
return loadDefaultAgents();
|
|
1000
1003
|
}
|
|
1001
1004
|
}
|
|
1002
|
-
async function loadBuiltinAgents() {
|
|
1003
|
-
const agents = await loadAgentsFromDir(DEFAULTS_DIR);
|
|
1004
|
-
if (agents.length > 0) return agents;
|
|
1005
|
-
return loadAgentsFromDir(DEFAULTS_DIR_ALT);
|
|
1006
|
-
}
|
|
1007
1005
|
async function getDefaultAgentIds() {
|
|
1008
1006
|
for (const dir of [DEFAULTS_DIR, DEFAULTS_DIR_ALT]) {
|
|
1009
1007
|
try {
|
|
@@ -1014,48 +1012,20 @@ async function getDefaultAgentIds() {
|
|
|
1014
1012
|
}
|
|
1015
1013
|
return [];
|
|
1016
1014
|
}
|
|
1017
|
-
async function
|
|
1018
|
-
const
|
|
1019
|
-
|
|
1020
|
-
const userPath = join2(getAgentsDir(configDir), `${agentId}${AGENT_EXTENSION}`);
|
|
1021
|
-
try {
|
|
1022
|
-
await unlink(userPath);
|
|
1023
|
-
} catch {
|
|
1024
|
-
}
|
|
1025
|
-
return true;
|
|
1015
|
+
async function getDefaultAgentContent(agentId) {
|
|
1016
|
+
const defaults = await loadDefaultAgents();
|
|
1017
|
+
return defaults.find((a) => a.metadata.id === agentId) ?? null;
|
|
1026
1018
|
}
|
|
1027
|
-
async function
|
|
1019
|
+
async function isDefaultAgent(agentId) {
|
|
1028
1020
|
const defaultIds = await getDefaultAgentIds();
|
|
1029
|
-
|
|
1030
|
-
for (const id of defaultIds) {
|
|
1031
|
-
const filename = `${id}${AGENT_EXTENSION}`;
|
|
1032
|
-
const userPath = join2(getAgentsDir(configDir), filename);
|
|
1033
|
-
let bundledContent = null;
|
|
1034
|
-
for (const dir of [DEFAULTS_DIR, DEFAULTS_DIR_ALT]) {
|
|
1035
|
-
try {
|
|
1036
|
-
bundledContent = await readFile2(join2(dir, filename), "utf-8");
|
|
1037
|
-
break;
|
|
1038
|
-
} catch {
|
|
1039
|
-
}
|
|
1040
|
-
}
|
|
1041
|
-
if (!bundledContent) continue;
|
|
1042
|
-
try {
|
|
1043
|
-
const userContent = await readFile2(userPath, "utf-8");
|
|
1044
|
-
if (userContent !== bundledContent) {
|
|
1045
|
-
modified.push(id);
|
|
1046
|
-
}
|
|
1047
|
-
} catch {
|
|
1048
|
-
}
|
|
1049
|
-
}
|
|
1050
|
-
return modified;
|
|
1021
|
+
return defaultIds.includes(agentId);
|
|
1051
1022
|
}
|
|
1052
|
-
|
|
1053
|
-
const
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
return count;
|
|
1023
|
+
function getAgentFilePaths(agentsDir, agentId) {
|
|
1024
|
+
const hyphenated = agentId.replace(/_/g, "-");
|
|
1025
|
+
return [
|
|
1026
|
+
join2(agentsDir, `${agentId}${AGENT_EXTENSION}`),
|
|
1027
|
+
join2(agentsDir, `${hyphenated}${AGENT_EXTENSION}`)
|
|
1028
|
+
];
|
|
1059
1029
|
}
|
|
1060
1030
|
function findAgentById(agentId, agents) {
|
|
1061
1031
|
return agents.find((a) => a.metadata.id === agentId);
|
|
@@ -1065,11 +1035,7 @@ function getSubAgents(agents) {
|
|
|
1065
1035
|
}
|
|
1066
1036
|
async function agentExists(configDir, agentId) {
|
|
1067
1037
|
const agentsDir = getAgentsDir(configDir);
|
|
1068
|
-
const
|
|
1069
|
-
const paths = [
|
|
1070
|
-
join2(agentsDir, `${agentId}${AGENT_EXTENSION}`),
|
|
1071
|
-
join2(agentsDir, `${hyphenated}${AGENT_EXTENSION}`)
|
|
1072
|
-
];
|
|
1038
|
+
const paths = getAgentFilePaths(agentsDir, agentId);
|
|
1073
1039
|
for (const filePath of paths) {
|
|
1074
1040
|
if (await pathExists(filePath)) {
|
|
1075
1041
|
return true;
|
|
@@ -1087,21 +1053,21 @@ async function saveAgent(configDir, agent) {
|
|
|
1087
1053
|
await writeFile(filePath, content, "utf-8");
|
|
1088
1054
|
}
|
|
1089
1055
|
async function deleteAgent(configDir, agentId) {
|
|
1056
|
+
const isDefault = await isDefaultAgent(agentId);
|
|
1057
|
+
if (isDefault) {
|
|
1058
|
+
return { success: false, reason: "Cannot delete built-in defaults" };
|
|
1059
|
+
}
|
|
1090
1060
|
const agentsDir = getAgentsDir(configDir);
|
|
1091
|
-
const
|
|
1092
|
-
const paths = [
|
|
1093
|
-
join2(agentsDir, `${agentId}${AGENT_EXTENSION}`),
|
|
1094
|
-
join2(agentsDir, `${hyphenated}${AGENT_EXTENSION}`)
|
|
1095
|
-
];
|
|
1061
|
+
const paths = getAgentFilePaths(agentsDir, agentId);
|
|
1096
1062
|
for (const filePath of paths) {
|
|
1097
1063
|
try {
|
|
1098
1064
|
await unlink(filePath);
|
|
1099
|
-
return true;
|
|
1065
|
+
return { success: true };
|
|
1100
1066
|
} catch {
|
|
1101
1067
|
continue;
|
|
1102
1068
|
}
|
|
1103
1069
|
}
|
|
1104
|
-
return false;
|
|
1070
|
+
return { success: false };
|
|
1105
1071
|
}
|
|
1106
1072
|
|
|
1107
1073
|
// src/server/tools/read.ts
|
|
@@ -1461,6 +1427,39 @@ function cancelPathConfirmationsForSession(sessionId, reason) {
|
|
|
1461
1427
|
}
|
|
1462
1428
|
|
|
1463
1429
|
// src/server/tools/tool-helpers.ts
|
|
1430
|
+
function validateAction(action, allowed, startTime) {
|
|
1431
|
+
if (!action || !allowed.includes(action)) {
|
|
1432
|
+
return {
|
|
1433
|
+
success: false,
|
|
1434
|
+
error: `Invalid action: ${action}. Must be one of: ${allowed.join(", ")}`,
|
|
1435
|
+
durationMs: Date.now() - startTime,
|
|
1436
|
+
truncated: false
|
|
1437
|
+
};
|
|
1438
|
+
}
|
|
1439
|
+
return void 0;
|
|
1440
|
+
}
|
|
1441
|
+
function checkActionPermission(action, permittedActions, startTime) {
|
|
1442
|
+
if (action && permittedActions && !permittedActions.includes(action)) {
|
|
1443
|
+
return {
|
|
1444
|
+
success: false,
|
|
1445
|
+
error: `Action '${action}' not allowed. Available: ${permittedActions.join(", ")}`,
|
|
1446
|
+
durationMs: Date.now() - startTime,
|
|
1447
|
+
truncated: false
|
|
1448
|
+
};
|
|
1449
|
+
}
|
|
1450
|
+
return void 0;
|
|
1451
|
+
}
|
|
1452
|
+
function requireSession(sessionManager, sessionId) {
|
|
1453
|
+
return sessionManager.requireSession(sessionId);
|
|
1454
|
+
}
|
|
1455
|
+
function validateActionWithPermission(action, allowedActions, toolName, permittedActions, startTime) {
|
|
1456
|
+
const actionError = validateAction(action, allowedActions, startTime ?? Date.now());
|
|
1457
|
+
if (actionError) return actionError;
|
|
1458
|
+
const permittedToolActions = permittedActions?.[toolName];
|
|
1459
|
+
const permissionError = checkActionPermission(action, permittedToolActions, startTime ?? Date.now());
|
|
1460
|
+
if (permissionError) return permissionError;
|
|
1461
|
+
return void 0;
|
|
1462
|
+
}
|
|
1464
1463
|
function createTool(name, definition, handler2) {
|
|
1465
1464
|
return {
|
|
1466
1465
|
name,
|
|
@@ -2021,11 +2020,26 @@ Make sure whitespace and indentation match exactly.`
|
|
|
2021
2020
|
);
|
|
2022
2021
|
|
|
2023
2022
|
// src/server/tools/shell.ts
|
|
2024
|
-
import
|
|
2023
|
+
import "child_process";
|
|
2025
2024
|
import { resolve as resolve4, isAbsolute as isAbsolute2 } from "path";
|
|
2026
2025
|
|
|
2027
|
-
// src/server/utils/
|
|
2026
|
+
// src/server/utils/shell.ts
|
|
2028
2027
|
import { spawn } from "child_process";
|
|
2028
|
+
function checkAborted(signal) {
|
|
2029
|
+
return !!signal?.aborted;
|
|
2030
|
+
}
|
|
2031
|
+
function spawnShellProcess(command, cwd, signal, detached = false) {
|
|
2032
|
+
const shell = getPlatformShell();
|
|
2033
|
+
return spawn(shell.command, [...shell.args, command], {
|
|
2034
|
+
cwd,
|
|
2035
|
+
env: { ...process.env, FORCE_COLOR: "0" },
|
|
2036
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
2037
|
+
...detached ? { detached: true } : {}
|
|
2038
|
+
});
|
|
2039
|
+
}
|
|
2040
|
+
|
|
2041
|
+
// src/server/utils/process-tree.ts
|
|
2042
|
+
import { spawn as spawn2 } from "child_process";
|
|
2029
2043
|
import { setTimeout as sleep } from "timers/promises";
|
|
2030
2044
|
var SIGKILL_TIMEOUT_MS = 200;
|
|
2031
2045
|
async function terminateProcessTree(proc, options) {
|
|
@@ -2035,7 +2049,7 @@ async function terminateProcessTree(proc, options) {
|
|
|
2035
2049
|
}
|
|
2036
2050
|
if (process.platform === "win32") {
|
|
2037
2051
|
await new Promise((resolve6) => {
|
|
2038
|
-
const killer =
|
|
2052
|
+
const killer = spawn2("taskkill", ["/pid", String(pid), "/f", "/t"], {
|
|
2039
2053
|
stdio: "ignore",
|
|
2040
2054
|
windowsHide: true
|
|
2041
2055
|
});
|
|
@@ -2139,18 +2153,11 @@ ${result.stderr}`;
|
|
|
2139
2153
|
);
|
|
2140
2154
|
function executeCommand(command, cwd, timeout, signal, onProgress) {
|
|
2141
2155
|
return new Promise((resolve6, reject) => {
|
|
2142
|
-
if (signal
|
|
2156
|
+
if (checkAborted(signal)) {
|
|
2143
2157
|
reject(new Error("Command aborted before execution"));
|
|
2144
2158
|
return;
|
|
2145
2159
|
}
|
|
2146
|
-
const
|
|
2147
|
-
const proc = spawn2(shell.command, [...shell.args, command], {
|
|
2148
|
-
cwd,
|
|
2149
|
-
env: { ...process.env, FORCE_COLOR: "0" },
|
|
2150
|
-
stdio: ["ignore", "pipe", "pipe"],
|
|
2151
|
-
detached: true
|
|
2152
|
-
// Create new process group so we can kill all children
|
|
2153
|
-
});
|
|
2160
|
+
const proc = spawnShellProcess(command, cwd, signal, true);
|
|
2154
2161
|
let stdout = "";
|
|
2155
2162
|
let stderr = "";
|
|
2156
2163
|
let killed = false;
|
|
@@ -2168,12 +2175,12 @@ function executeCommand(command, cwd, timeout, signal, onProgress) {
|
|
|
2168
2175
|
}
|
|
2169
2176
|
};
|
|
2170
2177
|
signal?.addEventListener("abort", onAbort);
|
|
2171
|
-
proc.stdout
|
|
2178
|
+
proc.stdout?.on("data", (data) => {
|
|
2172
2179
|
const chunk = data.toString();
|
|
2173
2180
|
stdout += chunk;
|
|
2174
2181
|
onProgress?.(`[stdout] ${chunk}`);
|
|
2175
2182
|
});
|
|
2176
|
-
proc.stderr
|
|
2183
|
+
proc.stderr?.on("data", (data) => {
|
|
2177
2184
|
const chunk = data.toString();
|
|
2178
2185
|
stderr += chunk;
|
|
2179
2186
|
onProgress?.(`[stderr] ${chunk}`);
|
|
@@ -2216,10 +2223,27 @@ function formatCriteriaList(criteria) {
|
|
|
2216
2223
|
if (criteria.length === 0) return "No criteria defined.";
|
|
2217
2224
|
return criteria.map((c, i) => `${i + 1}. [${c.id}] ${c.description}`).join("\n");
|
|
2218
2225
|
}
|
|
2219
|
-
|
|
2220
|
-
|
|
2221
|
-
|
|
2222
|
-
|
|
2226
|
+
function completeCriterion(session, context, id, statusType, reason) {
|
|
2227
|
+
const criterion = session.criteria.find((c) => c.id === id);
|
|
2228
|
+
if (!criterion) {
|
|
2229
|
+
return { success: false, output: `Criterion "${id}" not found` };
|
|
2230
|
+
}
|
|
2231
|
+
const status = statusType === "passed" ? { type: "passed", verifiedAt: (/* @__PURE__ */ new Date()).toISOString(), ...reason && { reason } } : { type: "failed", failedAt: (/* @__PURE__ */ new Date()).toISOString(), reason };
|
|
2232
|
+
context.sessionManager.updateCriterionStatus(context.sessionId, id, status);
|
|
2233
|
+
context.sessionManager.addCriterionAttempt(context.sessionId, id, {
|
|
2234
|
+
attemptNumber: criterion.attempts.length + 1,
|
|
2235
|
+
status: statusType,
|
|
2236
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2237
|
+
...reason ? { details: reason } : {}
|
|
2238
|
+
});
|
|
2239
|
+
return {
|
|
2240
|
+
success: true,
|
|
2241
|
+
output: statusType === "passed" ? `Criterion "${id}" verified as PASSED.${reason ? ` Verification: ${reason}` : ""}` : `Criterion "${id}" marked as FAILED. Reason: ${reason}`
|
|
2242
|
+
};
|
|
2243
|
+
}
|
|
2244
|
+
var criterionTool = createTool(
|
|
2245
|
+
"criterion",
|
|
2246
|
+
{
|
|
2223
2247
|
type: "function",
|
|
2224
2248
|
function: {
|
|
2225
2249
|
name: "criterion",
|
|
@@ -2249,267 +2273,90 @@ var criterionTool = {
|
|
|
2249
2273
|
}
|
|
2250
2274
|
}
|
|
2251
2275
|
},
|
|
2252
|
-
async
|
|
2253
|
-
const
|
|
2254
|
-
|
|
2255
|
-
|
|
2256
|
-
|
|
2257
|
-
|
|
2258
|
-
|
|
2259
|
-
|
|
2260
|
-
|
|
2261
|
-
|
|
2262
|
-
|
|
2263
|
-
|
|
2264
|
-
|
|
2265
|
-
|
|
2266
|
-
|
|
2267
|
-
|
|
2268
|
-
if (permittedActions && !permittedActions.includes(action)) {
|
|
2269
|
-
return {
|
|
2270
|
-
success: false,
|
|
2271
|
-
error: `Action '${action}' not allowed. Available: ${permittedActions.join(", ")}`,
|
|
2272
|
-
durationMs: Date.now() - startTime,
|
|
2273
|
-
truncated: false
|
|
2274
|
-
};
|
|
2275
|
-
}
|
|
2276
|
-
const session = context.sessionManager.requireSession(context.sessionId);
|
|
2277
|
-
if (action === "get") {
|
|
2278
|
-
const criteria = session.criteria;
|
|
2279
|
-
return {
|
|
2280
|
-
success: true,
|
|
2281
|
-
output: criteria.length === 0 ? "No criteria defined yet." : JSON.stringify(criteria.map((c) => ({
|
|
2282
|
-
id: c.id,
|
|
2283
|
-
description: c.description
|
|
2284
|
-
})), null, 2),
|
|
2285
|
-
durationMs: Date.now() - startTime,
|
|
2286
|
-
truncated: false
|
|
2287
|
-
};
|
|
2288
|
-
}
|
|
2289
|
-
if (action === "add") {
|
|
2290
|
-
if (!description) {
|
|
2291
|
-
return {
|
|
2292
|
-
success: false,
|
|
2293
|
-
error: "Missing required field: description",
|
|
2294
|
-
durationMs: Date.now() - startTime,
|
|
2295
|
-
truncated: false
|
|
2296
|
-
};
|
|
2297
|
-
}
|
|
2298
|
-
const criterion = {
|
|
2299
|
-
id: id || "",
|
|
2300
|
-
description,
|
|
2301
|
-
status: { type: "pending" },
|
|
2302
|
-
attempts: []
|
|
2303
|
-
};
|
|
2304
|
-
const result = context.sessionManager.addCriterion(context.sessionId, criterion);
|
|
2305
|
-
if ("error" in result) {
|
|
2306
|
-
return { success: false, error: result.error, durationMs: Date.now() - startTime, truncated: false };
|
|
2307
|
-
}
|
|
2308
|
-
return {
|
|
2309
|
-
success: true,
|
|
2310
|
-
output: `Added criterion "${result.actualId}". Current criteria:
|
|
2311
|
-
${formatCriteriaList(result.criteria)}`,
|
|
2312
|
-
durationMs: Date.now() - startTime,
|
|
2313
|
-
truncated: false
|
|
2314
|
-
};
|
|
2315
|
-
}
|
|
2316
|
-
if (action === "update") {
|
|
2317
|
-
if (!id) {
|
|
2318
|
-
return {
|
|
2319
|
-
success: false,
|
|
2320
|
-
error: "Missing required field: id",
|
|
2321
|
-
durationMs: Date.now() - startTime,
|
|
2322
|
-
truncated: false
|
|
2323
|
-
};
|
|
2324
|
-
}
|
|
2325
|
-
if (!description) {
|
|
2326
|
-
return {
|
|
2327
|
-
success: false,
|
|
2328
|
-
error: "Missing required field: description",
|
|
2329
|
-
durationMs: Date.now() - startTime,
|
|
2330
|
-
truncated: false
|
|
2331
|
-
};
|
|
2332
|
-
}
|
|
2333
|
-
if (!session.criteria.find((c) => c.id === id)) {
|
|
2334
|
-
return {
|
|
2335
|
-
success: false,
|
|
2336
|
-
error: `Criterion "${id}" not found`,
|
|
2337
|
-
durationMs: Date.now() - startTime,
|
|
2338
|
-
truncated: false
|
|
2339
|
-
};
|
|
2340
|
-
}
|
|
2341
|
-
const criteria = context.sessionManager.updateCriterionFull(context.sessionId, id, { description });
|
|
2342
|
-
return {
|
|
2343
|
-
success: true,
|
|
2344
|
-
output: `Updated criterion "${id}". Current criteria:
|
|
2345
|
-
${formatCriteriaList(criteria)}`,
|
|
2346
|
-
durationMs: Date.now() - startTime,
|
|
2347
|
-
truncated: false
|
|
2348
|
-
};
|
|
2349
|
-
}
|
|
2350
|
-
if (action === "remove") {
|
|
2351
|
-
if (!id) {
|
|
2352
|
-
return {
|
|
2353
|
-
success: false,
|
|
2354
|
-
error: "Missing required field: id",
|
|
2355
|
-
durationMs: Date.now() - startTime,
|
|
2356
|
-
truncated: false
|
|
2357
|
-
};
|
|
2358
|
-
}
|
|
2359
|
-
if (!session.criteria.find((c) => c.id === id)) {
|
|
2360
|
-
return {
|
|
2361
|
-
success: false,
|
|
2362
|
-
error: `Criterion "${id}" not found`,
|
|
2363
|
-
durationMs: Date.now() - startTime,
|
|
2364
|
-
truncated: false
|
|
2365
|
-
};
|
|
2366
|
-
}
|
|
2367
|
-
const criteria = context.sessionManager.removeCriterion(context.sessionId, id);
|
|
2368
|
-
return {
|
|
2369
|
-
success: true,
|
|
2370
|
-
output: criteria.length === 0 ? `Removed criterion "${id}". No criteria remaining.` : `Removed criterion "${id}". Current criteria:
|
|
2371
|
-
${formatCriteriaList(criteria)}`,
|
|
2372
|
-
durationMs: Date.now() - startTime,
|
|
2373
|
-
truncated: false
|
|
2374
|
-
};
|
|
2375
|
-
}
|
|
2376
|
-
if (action === "complete") {
|
|
2377
|
-
if (!id) {
|
|
2378
|
-
return {
|
|
2379
|
-
success: false,
|
|
2380
|
-
error: "Missing required field: id",
|
|
2381
|
-
durationMs: Date.now() - startTime,
|
|
2382
|
-
truncated: false
|
|
2383
|
-
};
|
|
2384
|
-
}
|
|
2385
|
-
const criterion = session.criteria.find((c) => c.id === id);
|
|
2386
|
-
if (!criterion) {
|
|
2387
|
-
return {
|
|
2388
|
-
success: false,
|
|
2389
|
-
error: `Criterion "${id}" not found. Available: ${session.criteria.map((c) => c.id).join(", ")}`,
|
|
2390
|
-
durationMs: Date.now() - startTime,
|
|
2391
|
-
truncated: false
|
|
2392
|
-
};
|
|
2393
|
-
}
|
|
2394
|
-
const status = {
|
|
2395
|
-
type: "completed",
|
|
2396
|
-
completedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2397
|
-
...reason ? { reason } : {}
|
|
2398
|
-
};
|
|
2399
|
-
context.sessionManager.updateCriterionStatus(context.sessionId, id, status);
|
|
2400
|
-
return {
|
|
2401
|
-
success: true,
|
|
2402
|
-
output: `Criterion "${id}" marked as completed.${reason ? ` Reason: ${reason}` : ""}`,
|
|
2403
|
-
durationMs: Date.now() - startTime,
|
|
2404
|
-
truncated: false
|
|
2405
|
-
};
|
|
2406
|
-
}
|
|
2407
|
-
if (action === "pass") {
|
|
2408
|
-
if (!id) {
|
|
2409
|
-
return {
|
|
2410
|
-
success: false,
|
|
2411
|
-
error: "Missing required field: id",
|
|
2412
|
-
durationMs: Date.now() - startTime,
|
|
2413
|
-
truncated: false
|
|
2414
|
-
};
|
|
2415
|
-
}
|
|
2416
|
-
const criterion = session.criteria.find((c) => c.id === id);
|
|
2417
|
-
if (!criterion) {
|
|
2418
|
-
return {
|
|
2419
|
-
success: false,
|
|
2420
|
-
error: `Criterion "${id}" not found`,
|
|
2421
|
-
durationMs: Date.now() - startTime,
|
|
2422
|
-
truncated: false
|
|
2423
|
-
};
|
|
2424
|
-
}
|
|
2425
|
-
const status = {
|
|
2426
|
-
type: "passed",
|
|
2427
|
-
verifiedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2428
|
-
...reason ? { reason } : {}
|
|
2429
|
-
};
|
|
2430
|
-
context.sessionManager.updateCriterionStatus(context.sessionId, id, status);
|
|
2431
|
-
context.sessionManager.addCriterionAttempt(context.sessionId, id, {
|
|
2432
|
-
attemptNumber: criterion.attempts.length + 1,
|
|
2433
|
-
status: "passed",
|
|
2434
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2435
|
-
...reason && { details: reason }
|
|
2436
|
-
});
|
|
2437
|
-
return {
|
|
2438
|
-
success: true,
|
|
2439
|
-
output: `Criterion "${id}" verified as PASSED.${reason ? ` Verification: ${reason}` : ""}`,
|
|
2440
|
-
durationMs: Date.now() - startTime,
|
|
2441
|
-
truncated: false
|
|
2442
|
-
};
|
|
2443
|
-
}
|
|
2444
|
-
if (action === "fail") {
|
|
2445
|
-
if (!id) {
|
|
2446
|
-
return {
|
|
2447
|
-
success: false,
|
|
2448
|
-
error: "Missing required field: id",
|
|
2449
|
-
durationMs: Date.now() - startTime,
|
|
2450
|
-
truncated: false
|
|
2451
|
-
};
|
|
2452
|
-
}
|
|
2453
|
-
if (!reason) {
|
|
2454
|
-
return {
|
|
2455
|
-
success: false,
|
|
2456
|
-
error: "Missing required field: reason",
|
|
2457
|
-
durationMs: Date.now() - startTime,
|
|
2458
|
-
truncated: false
|
|
2459
|
-
};
|
|
2460
|
-
}
|
|
2461
|
-
const criterion = session.criteria.find((c) => c.id === id);
|
|
2462
|
-
if (!criterion) {
|
|
2463
|
-
return {
|
|
2464
|
-
success: false,
|
|
2465
|
-
error: `Criterion "${id}" not found`,
|
|
2466
|
-
durationMs: Date.now() - startTime,
|
|
2467
|
-
truncated: false
|
|
2468
|
-
};
|
|
2469
|
-
}
|
|
2470
|
-
const status = {
|
|
2471
|
-
type: "failed",
|
|
2472
|
-
failedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2473
|
-
reason
|
|
2474
|
-
};
|
|
2475
|
-
context.sessionManager.updateCriterionStatus(context.sessionId, id, status);
|
|
2476
|
-
context.sessionManager.addCriterionAttempt(context.sessionId, id, {
|
|
2477
|
-
attemptNumber: criterion.attempts.length + 1,
|
|
2478
|
-
status: "failed",
|
|
2479
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2480
|
-
details: reason
|
|
2481
|
-
});
|
|
2482
|
-
return {
|
|
2483
|
-
success: true,
|
|
2484
|
-
output: `Criterion "${id}" marked as FAILED. Reason: ${reason}`,
|
|
2485
|
-
durationMs: Date.now() - startTime,
|
|
2486
|
-
truncated: false
|
|
2487
|
-
};
|
|
2488
|
-
}
|
|
2489
|
-
return {
|
|
2490
|
-
success: false,
|
|
2491
|
-
error: "Unexpected error",
|
|
2492
|
-
durationMs: Date.now() - startTime,
|
|
2493
|
-
truncated: false
|
|
2494
|
-
};
|
|
2495
|
-
} catch (error) {
|
|
2496
|
-
return {
|
|
2497
|
-
success: false,
|
|
2498
|
-
error: error instanceof Error ? error.message : "Unknown error",
|
|
2499
|
-
durationMs: Date.now() - startTime,
|
|
2500
|
-
truncated: false
|
|
2276
|
+
async (args, context, helpers) => {
|
|
2277
|
+
const actionError = validateActionWithPermission(args.action, ["get", "add", "update", "remove", "complete", "pass", "fail"], "criterion", context.permittedActions);
|
|
2278
|
+
if (actionError) return actionError;
|
|
2279
|
+
const session = requireSession(context.sessionManager, context.sessionId);
|
|
2280
|
+
if (args.action === "get") {
|
|
2281
|
+
return helpers.success(
|
|
2282
|
+
session.criteria.length === 0 ? "No criteria defined yet." : JSON.stringify(session.criteria.map((c) => ({ id: c.id, description: c.description })), null, 2)
|
|
2283
|
+
);
|
|
2284
|
+
}
|
|
2285
|
+
if (args.action === "add") {
|
|
2286
|
+
if (!args.description) return helpers.error("Missing required field: description");
|
|
2287
|
+
const criterion = {
|
|
2288
|
+
id: args.id || "",
|
|
2289
|
+
description: args.description,
|
|
2290
|
+
status: { type: "pending" },
|
|
2291
|
+
attempts: []
|
|
2501
2292
|
};
|
|
2293
|
+
const result = context.sessionManager.addCriterion(context.sessionId, criterion);
|
|
2294
|
+
if ("error" in result) return helpers.error(result.error);
|
|
2295
|
+
return helpers.success(`Added criterion "${result.actualId}". Current criteria:
|
|
2296
|
+
${formatCriteriaList(result.criteria)}`);
|
|
2297
|
+
}
|
|
2298
|
+
if (args.action === "update") {
|
|
2299
|
+
if (!args.id) return helpers.error("Missing required field: id");
|
|
2300
|
+
if (!args.description) return helpers.error("Missing required field: description");
|
|
2301
|
+
if (!session.criteria.find((c) => c.id === args.id)) return helpers.error(`Criterion "${args.id}" not found`);
|
|
2302
|
+
const criteria = context.sessionManager.updateCriterionFull(context.sessionId, args.id, { description: args.description });
|
|
2303
|
+
return helpers.success(`Updated criterion "${args.id}". Current criteria:
|
|
2304
|
+
${formatCriteriaList(criteria)}`);
|
|
2305
|
+
}
|
|
2306
|
+
if (args.action === "remove") {
|
|
2307
|
+
if (!args.id) return helpers.error("Missing required field: id");
|
|
2308
|
+
if (!session.criteria.find((c) => c.id === args.id)) return helpers.error(`Criterion "${args.id}" not found`);
|
|
2309
|
+
const criteria = context.sessionManager.removeCriterion(context.sessionId, args.id);
|
|
2310
|
+
return helpers.success(
|
|
2311
|
+
criteria.length === 0 ? `Removed criterion "${args.id}". No criteria remaining.` : `Removed criterion "${args.id}". Current criteria:
|
|
2312
|
+
${formatCriteriaList(criteria)}`
|
|
2313
|
+
);
|
|
2314
|
+
}
|
|
2315
|
+
if (args.action === "complete") {
|
|
2316
|
+
if (!args.id) return helpers.error("Missing required field: id");
|
|
2317
|
+
const criterion = session.criteria.find((c) => c.id === args.id);
|
|
2318
|
+
if (!criterion) return helpers.error(`Criterion "${args.id}" not found. Available: ${session.criteria.map((c) => c.id).join(", ")}`);
|
|
2319
|
+
context.sessionManager.updateCriterionStatus(context.sessionId, args.id, {
|
|
2320
|
+
type: "completed",
|
|
2321
|
+
completedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2322
|
+
...args.reason ? { reason: args.reason } : {}
|
|
2323
|
+
});
|
|
2324
|
+
return helpers.success(`Criterion "${args.id}" marked as completed.${args.reason ? ` Reason: ${args.reason}` : ""}`);
|
|
2325
|
+
}
|
|
2326
|
+
if (args.action === "pass") {
|
|
2327
|
+
if (!args.id) return helpers.error("Missing required field: id");
|
|
2328
|
+
const result = completeCriterion(session, context, args.id, "passed", args.reason);
|
|
2329
|
+
return result.success ? helpers.success(result.output) : helpers.error(result.output);
|
|
2502
2330
|
}
|
|
2331
|
+
if (args.action === "fail") {
|
|
2332
|
+
if (!args.id) return helpers.error("Missing required field: id");
|
|
2333
|
+
if (!args.reason) return helpers.error("Missing required field: reason");
|
|
2334
|
+
const result = completeCriterion(session, context, args.id, "failed", args.reason);
|
|
2335
|
+
return result.success ? helpers.success(result.output) : helpers.error(result.output);
|
|
2336
|
+
}
|
|
2337
|
+
return helpers.error("Unexpected error");
|
|
2503
2338
|
}
|
|
2504
|
-
|
|
2339
|
+
);
|
|
2505
2340
|
|
|
2506
2341
|
// src/server/tools/todo.ts
|
|
2507
2342
|
var sessionTodos = /* @__PURE__ */ new Map();
|
|
2508
2343
|
var onTodoUpdate = null;
|
|
2509
|
-
|
|
2510
|
-
|
|
2511
|
-
|
|
2512
|
-
|
|
2344
|
+
function buildTaskListSummary(todosList) {
|
|
2345
|
+
const pending = todosList.filter((t) => t.status === "pending").length;
|
|
2346
|
+
const inProgress = todosList.filter((t) => t.status === "in_progress").length;
|
|
2347
|
+
const completed = todosList.filter((t) => t.status === "completed").length;
|
|
2348
|
+
return `${completed} completed, ${inProgress} in progress, ${pending} pending`;
|
|
2349
|
+
}
|
|
2350
|
+
function validateIndex(index, todosList, helpers) {
|
|
2351
|
+
if (index === void 0) return helpers.error("Missing required field: index");
|
|
2352
|
+
if (index < 0 || index >= todosList.length) {
|
|
2353
|
+
return helpers.error(`Index out of range: ${index}. Valid range: 0-${todosList.length - 1}`);
|
|
2354
|
+
}
|
|
2355
|
+
return todosList[index];
|
|
2356
|
+
}
|
|
2357
|
+
var todoTool = createTool(
|
|
2358
|
+
"todo",
|
|
2359
|
+
{
|
|
2513
2360
|
type: "function",
|
|
2514
2361
|
function: {
|
|
2515
2362
|
name: "todo",
|
|
@@ -2552,235 +2399,65 @@ var todoTool = {
|
|
|
2552
2399
|
}
|
|
2553
2400
|
}
|
|
2554
2401
|
},
|
|
2555
|
-
async
|
|
2556
|
-
const
|
|
2557
|
-
|
|
2558
|
-
|
|
2559
|
-
const
|
|
2560
|
-
|
|
2561
|
-
|
|
2562
|
-
|
|
2563
|
-
|
|
2564
|
-
|
|
2565
|
-
|
|
2566
|
-
|
|
2567
|
-
|
|
2568
|
-
|
|
2569
|
-
|
|
2570
|
-
|
|
2571
|
-
const permittedActions = context.permittedActions?.["todo"];
|
|
2572
|
-
if (permittedActions && !permittedActions.includes(action)) {
|
|
2573
|
-
return {
|
|
2574
|
-
success: false,
|
|
2575
|
-
error: `Action '${action}' not allowed. Available: ${permittedActions.join(", ")}`,
|
|
2576
|
-
durationMs: Date.now() - startTime,
|
|
2577
|
-
truncated: false
|
|
2578
|
-
};
|
|
2579
|
-
}
|
|
2580
|
-
if (action === "list") {
|
|
2581
|
-
const todosList = sessionTodos.get(context.sessionId) ?? [];
|
|
2582
|
-
return {
|
|
2583
|
-
success: true,
|
|
2584
|
-
output: todosList.length === 0 ? "No tasks defined yet." : JSON.stringify(todosList, null, 2),
|
|
2585
|
-
durationMs: Date.now() - startTime,
|
|
2586
|
-
truncated: false
|
|
2587
|
-
};
|
|
2588
|
-
}
|
|
2589
|
-
if (action === "write") {
|
|
2590
|
-
if (!todos) {
|
|
2591
|
-
return {
|
|
2592
|
-
success: false,
|
|
2593
|
-
error: "Missing required field: todos",
|
|
2594
|
-
durationMs: Date.now() - startTime,
|
|
2595
|
-
truncated: false
|
|
2596
|
-
};
|
|
2597
|
-
}
|
|
2598
|
-
if (!Array.isArray(todos)) {
|
|
2599
|
-
return {
|
|
2600
|
-
success: false,
|
|
2601
|
-
error: "todos must be an array",
|
|
2602
|
-
durationMs: Date.now() - startTime,
|
|
2603
|
-
truncated: false
|
|
2604
|
-
};
|
|
2605
|
-
}
|
|
2606
|
-
for (const todo of todos) {
|
|
2607
|
-
if (!todo.content || !todo.status) {
|
|
2608
|
-
return {
|
|
2609
|
-
success: false,
|
|
2610
|
-
error: "Each todo must have content and status",
|
|
2611
|
-
durationMs: Date.now() - startTime,
|
|
2612
|
-
truncated: false
|
|
2613
|
-
};
|
|
2614
|
-
}
|
|
2615
|
-
if (!["pending", "in_progress", "completed"].includes(todo.status)) {
|
|
2616
|
-
return {
|
|
2617
|
-
success: false,
|
|
2618
|
-
error: `Invalid status: ${todo.status}. Must be pending, in_progress, or completed`,
|
|
2619
|
-
durationMs: Date.now() - startTime,
|
|
2620
|
-
truncated: false
|
|
2621
|
-
};
|
|
2622
|
-
}
|
|
2623
|
-
}
|
|
2624
|
-
sessionTodos.set(context.sessionId, todos);
|
|
2625
|
-
if (onTodoUpdate) {
|
|
2626
|
-
onTodoUpdate(context.sessionId, todos);
|
|
2627
|
-
}
|
|
2628
|
-
const pending = todos.filter((t) => t.status === "pending").length;
|
|
2629
|
-
const inProgress = todos.filter((t) => t.status === "in_progress").length;
|
|
2630
|
-
const completed = todos.filter((t) => t.status === "completed").length;
|
|
2631
|
-
return {
|
|
2632
|
-
success: true,
|
|
2633
|
-
output: `Task list updated: ${completed} completed, ${inProgress} in progress, ${pending} pending`,
|
|
2634
|
-
durationMs: Date.now() - startTime,
|
|
2635
|
-
truncated: false
|
|
2636
|
-
};
|
|
2637
|
-
}
|
|
2638
|
-
if (action === "add") {
|
|
2639
|
-
if (!content) {
|
|
2640
|
-
return {
|
|
2641
|
-
success: false,
|
|
2642
|
-
error: "Missing required field: content",
|
|
2643
|
-
durationMs: Date.now() - startTime,
|
|
2644
|
-
truncated: false
|
|
2645
|
-
};
|
|
2646
|
-
}
|
|
2647
|
-
const todosList = sessionTodos.get(context.sessionId) ?? [];
|
|
2648
|
-
const newTodo = { content, status: "pending" };
|
|
2649
|
-
todosList.push(newTodo);
|
|
2650
|
-
sessionTodos.set(context.sessionId, todosList);
|
|
2651
|
-
if (onTodoUpdate) {
|
|
2652
|
-
onTodoUpdate(context.sessionId, todosList);
|
|
2653
|
-
}
|
|
2654
|
-
const pending = todosList.filter((t) => t.status === "pending").length;
|
|
2655
|
-
const inProgress = todosList.filter((t) => t.status === "in_progress").length;
|
|
2656
|
-
const completed = todosList.filter((t) => t.status === "completed").length;
|
|
2657
|
-
return {
|
|
2658
|
-
success: true,
|
|
2659
|
-
output: `Added task "${content}". Task list: ${completed} completed, ${inProgress} in progress, ${pending} pending`,
|
|
2660
|
-
durationMs: Date.now() - startTime,
|
|
2661
|
-
truncated: false
|
|
2662
|
-
};
|
|
2663
|
-
}
|
|
2664
|
-
if (action === "update") {
|
|
2665
|
-
if (index === void 0) {
|
|
2666
|
-
return {
|
|
2667
|
-
success: false,
|
|
2668
|
-
error: "Missing required field: index",
|
|
2669
|
-
durationMs: Date.now() - startTime,
|
|
2670
|
-
truncated: false
|
|
2671
|
-
};
|
|
2672
|
-
}
|
|
2673
|
-
if (!content && !status) {
|
|
2674
|
-
return {
|
|
2675
|
-
success: false,
|
|
2676
|
-
error: "update requires content or status",
|
|
2677
|
-
durationMs: Date.now() - startTime,
|
|
2678
|
-
truncated: false
|
|
2679
|
-
};
|
|
2680
|
-
}
|
|
2681
|
-
if (status && !["pending", "in_progress", "completed"].includes(status)) {
|
|
2682
|
-
return {
|
|
2683
|
-
success: false,
|
|
2684
|
-
error: `Invalid status: ${status}. Must be pending, in_progress, or completed`,
|
|
2685
|
-
durationMs: Date.now() - startTime,
|
|
2686
|
-
truncated: false
|
|
2687
|
-
};
|
|
2688
|
-
}
|
|
2689
|
-
const todosList = sessionTodos.get(context.sessionId) ?? [];
|
|
2690
|
-
if (index < 0 || index >= todosList.length) {
|
|
2691
|
-
return {
|
|
2692
|
-
success: false,
|
|
2693
|
-
error: `Index out of range: ${index}. Valid range: 0-${todosList.length - 1}`,
|
|
2694
|
-
durationMs: Date.now() - startTime,
|
|
2695
|
-
truncated: false
|
|
2696
|
-
};
|
|
2697
|
-
}
|
|
2698
|
-
const todo = todosList[index];
|
|
2699
|
-
if (!todo) {
|
|
2700
|
-
return {
|
|
2701
|
-
success: false,
|
|
2702
|
-
error: `Index out of range: ${index}. Valid range: 0-${todosList.length - 1}`,
|
|
2703
|
-
durationMs: Date.now() - startTime,
|
|
2704
|
-
truncated: false
|
|
2705
|
-
};
|
|
2706
|
-
}
|
|
2707
|
-
if (content) {
|
|
2708
|
-
todo.content = content;
|
|
2709
|
-
}
|
|
2710
|
-
if (status) {
|
|
2711
|
-
todo.status = status;
|
|
2712
|
-
}
|
|
2713
|
-
sessionTodos.set(context.sessionId, todosList);
|
|
2714
|
-
if (onTodoUpdate) {
|
|
2715
|
-
onTodoUpdate(context.sessionId, todosList);
|
|
2402
|
+
async (args, context, helpers) => {
|
|
2403
|
+
const actionError = validateActionWithPermission(args.action, ["list", "write", "add", "update", "remove"], "todo", context.permittedActions);
|
|
2404
|
+
if (actionError) return actionError;
|
|
2405
|
+
if (args.action === "list") {
|
|
2406
|
+
const todosList = sessionTodos.get(context.sessionId) ?? [];
|
|
2407
|
+
return helpers.success(
|
|
2408
|
+
todosList.length === 0 ? "No tasks defined yet." : JSON.stringify(todosList, null, 2)
|
|
2409
|
+
);
|
|
2410
|
+
}
|
|
2411
|
+
if (args.action === "write") {
|
|
2412
|
+
if (!args.todos) return helpers.error("Missing required field: todos");
|
|
2413
|
+
if (!Array.isArray(args.todos)) return helpers.error("todos must be an array");
|
|
2414
|
+
for (const todo of args.todos) {
|
|
2415
|
+
if (!todo.content || !todo.status) return helpers.error("Each todo must have content and status");
|
|
2416
|
+
if (!["pending", "in_progress", "completed"].includes(todo.status)) {
|
|
2417
|
+
return helpers.error(`Invalid status: ${todo.status}. Must be pending, in_progress, or completed`);
|
|
2716
2418
|
}
|
|
2717
|
-
const pending = todosList.filter((t) => t.status === "pending").length;
|
|
2718
|
-
const inProgress = todosList.filter((t) => t.status === "in_progress").length;
|
|
2719
|
-
const completed = todosList.filter((t) => t.status === "completed").length;
|
|
2720
|
-
return {
|
|
2721
|
-
success: true,
|
|
2722
|
-
output: `Updated task ${index}. Task list: ${completed} completed, ${inProgress} in progress, ${pending} pending`,
|
|
2723
|
-
durationMs: Date.now() - startTime,
|
|
2724
|
-
truncated: false
|
|
2725
|
-
};
|
|
2726
2419
|
}
|
|
2727
|
-
|
|
2728
|
-
|
|
2729
|
-
|
|
2730
|
-
|
|
2731
|
-
|
|
2732
|
-
|
|
2733
|
-
|
|
2734
|
-
|
|
2735
|
-
|
|
2736
|
-
|
|
2737
|
-
|
|
2738
|
-
|
|
2739
|
-
|
|
2740
|
-
|
|
2741
|
-
|
|
2742
|
-
|
|
2743
|
-
};
|
|
2744
|
-
}
|
|
2745
|
-
const removed = todosList.splice(index, 1)[0];
|
|
2746
|
-
sessionTodos.set(context.sessionId, todosList);
|
|
2747
|
-
if (onTodoUpdate) {
|
|
2748
|
-
onTodoUpdate(context.sessionId, todosList);
|
|
2749
|
-
}
|
|
2750
|
-
if (todosList.length === 0) {
|
|
2751
|
-
return {
|
|
2752
|
-
success: true,
|
|
2753
|
-
output: `Removed task "${removed.content}". No tasks remaining.`,
|
|
2754
|
-
durationMs: Date.now() - startTime,
|
|
2755
|
-
truncated: false
|
|
2756
|
-
};
|
|
2757
|
-
}
|
|
2758
|
-
const pending = todosList.filter((t) => t.status === "pending").length;
|
|
2759
|
-
const inProgress = todosList.filter((t) => t.status === "in_progress").length;
|
|
2760
|
-
const completed = todosList.filter((t) => t.status === "completed").length;
|
|
2761
|
-
return {
|
|
2762
|
-
success: true,
|
|
2763
|
-
output: `Removed task "${removed.content}". Task list: ${completed} completed, ${inProgress} in progress, ${pending} pending`,
|
|
2764
|
-
durationMs: Date.now() - startTime,
|
|
2765
|
-
truncated: false
|
|
2766
|
-
};
|
|
2420
|
+
sessionTodos.set(context.sessionId, args.todos);
|
|
2421
|
+
if (onTodoUpdate) onTodoUpdate(context.sessionId, args.todos);
|
|
2422
|
+
return helpers.success(`${args.todos.filter((t) => t.status === "completed").length} completed, ${args.todos.filter((t) => t.status === "in_progress").length} in progress, ${args.todos.filter((t) => t.status === "pending").length} pending`);
|
|
2423
|
+
}
|
|
2424
|
+
if (args.action === "add") {
|
|
2425
|
+
if (!args.content) return helpers.error("Missing required field: content");
|
|
2426
|
+
const todosList = sessionTodos.get(context.sessionId) ?? [];
|
|
2427
|
+
todosList.push({ content: args.content, status: "pending" });
|
|
2428
|
+
sessionTodos.set(context.sessionId, todosList);
|
|
2429
|
+
if (onTodoUpdate) onTodoUpdate(context.sessionId, todosList);
|
|
2430
|
+
return helpers.success(`Added task "${args.content}". Task list: ${buildTaskListSummary(todosList)}`);
|
|
2431
|
+
}
|
|
2432
|
+
if (args.action === "update") {
|
|
2433
|
+
if (!args.content && !args.status) return helpers.error("update requires content or status");
|
|
2434
|
+
if (args.status && !["pending", "in_progress", "completed"].includes(args.status)) {
|
|
2435
|
+
return helpers.error(`Invalid status: ${args.status}. Must be pending, in_progress, or completed`);
|
|
2767
2436
|
}
|
|
2768
|
-
|
|
2769
|
-
|
|
2770
|
-
|
|
2771
|
-
|
|
2772
|
-
|
|
2773
|
-
|
|
2774
|
-
|
|
2775
|
-
|
|
2776
|
-
|
|
2777
|
-
|
|
2778
|
-
|
|
2779
|
-
|
|
2780
|
-
|
|
2437
|
+
const todosList = sessionTodos.get(context.sessionId) ?? [];
|
|
2438
|
+
const indexResult = validateIndex(args.index, todosList, helpers);
|
|
2439
|
+
if ("success" in indexResult && !indexResult.success) return indexResult;
|
|
2440
|
+
const todo = indexResult;
|
|
2441
|
+
if (args.content) todo.content = args.content;
|
|
2442
|
+
if (args.status) todo.status = args.status;
|
|
2443
|
+
sessionTodos.set(context.sessionId, todosList);
|
|
2444
|
+
if (onTodoUpdate) onTodoUpdate(context.sessionId, todosList);
|
|
2445
|
+
return helpers.success(`Updated task ${args.index}. Task list: ${buildTaskListSummary(todosList)}`);
|
|
2446
|
+
}
|
|
2447
|
+
if (args.action === "remove") {
|
|
2448
|
+
const todosList = sessionTodos.get(context.sessionId) ?? [];
|
|
2449
|
+
const indexResult = validateIndex(args.index, todosList, helpers);
|
|
2450
|
+
if ("success" in indexResult && !indexResult.success) return indexResult;
|
|
2451
|
+
const removed = todosList.splice(args.index, 1)[0];
|
|
2452
|
+
sessionTodos.set(context.sessionId, todosList);
|
|
2453
|
+
if (onTodoUpdate) onTodoUpdate(context.sessionId, todosList);
|
|
2454
|
+
return helpers.success(
|
|
2455
|
+
todosList.length === 0 ? `Removed task "${removed.content}". No tasks remaining.` : `Removed task "${removed.content}". Task list: ${buildTaskListSummary(todosList)}`
|
|
2456
|
+
);
|
|
2781
2457
|
}
|
|
2458
|
+
return helpers.error("Unexpected error");
|
|
2782
2459
|
}
|
|
2783
|
-
|
|
2460
|
+
);
|
|
2784
2461
|
|
|
2785
2462
|
// src/server/chat/tool-streaming.ts
|
|
2786
2463
|
function parseProgressMessage(message) {
|
|
@@ -2800,7 +2477,7 @@ function createToolProgressHandler(messageId, callId, onMessage) {
|
|
|
2800
2477
|
}
|
|
2801
2478
|
|
|
2802
2479
|
// src/server/skills/registry.ts
|
|
2803
|
-
import { readdir as readdir2, readFile as readFile6, writeFile as writeFile4,
|
|
2480
|
+
import { readdir as readdir2, readFile as readFile6, writeFile as writeFile4, mkdir as mkdir3, access as access3, unlink as unlink2 } from "fs/promises";
|
|
2804
2481
|
import { join as join4, dirname as dirname4 } from "path";
|
|
2805
2482
|
import { constants as constants3 } from "fs";
|
|
2806
2483
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
@@ -2813,7 +2490,7 @@ var SKILL_SETTING_PREFIX = "skill.enabled.";
|
|
|
2813
2490
|
function getSkillsDir(configDir) {
|
|
2814
2491
|
return join4(configDir, "skills");
|
|
2815
2492
|
}
|
|
2816
|
-
async function
|
|
2493
|
+
async function pathExists2(path) {
|
|
2817
2494
|
try {
|
|
2818
2495
|
await access3(path, constants3.R_OK);
|
|
2819
2496
|
return true;
|
|
@@ -2821,56 +2498,40 @@ async function dirExists(path) {
|
|
|
2821
2498
|
return false;
|
|
2822
2499
|
}
|
|
2823
2500
|
}
|
|
2824
|
-
async function
|
|
2825
|
-
|
|
2826
|
-
if (!await dirExists(skillsDir)) {
|
|
2827
|
-
await mkdir3(skillsDir, { recursive: true });
|
|
2828
|
-
}
|
|
2829
|
-
let defaultFiles;
|
|
2830
|
-
let sourceDir;
|
|
2501
|
+
async function loadDefaultSkills() {
|
|
2502
|
+
let defaults = [];
|
|
2831
2503
|
try {
|
|
2832
|
-
|
|
2833
|
-
sourceDir = DEFAULTS_DIR2;
|
|
2504
|
+
defaults = await loadSkillsFromDir(DEFAULTS_DIR2);
|
|
2834
2505
|
} catch {
|
|
2506
|
+
}
|
|
2507
|
+
if (!defaults.length) {
|
|
2835
2508
|
try {
|
|
2836
|
-
|
|
2837
|
-
sourceDir = DEFAULTS_DIR_ALT2;
|
|
2509
|
+
defaults = await loadSkillsFromDir(DEFAULTS_DIR_ALT2);
|
|
2838
2510
|
} catch {
|
|
2839
|
-
logger.warn("No bundled skill defaults found", { dir: DEFAULTS_DIR2 });
|
|
2840
|
-
return;
|
|
2841
|
-
}
|
|
2842
|
-
}
|
|
2843
|
-
for (const file of defaultFiles) {
|
|
2844
|
-
const targetPath = join4(skillsDir, file);
|
|
2845
|
-
if (!await dirExists(targetPath)) {
|
|
2846
|
-
try {
|
|
2847
|
-
await copyFile2(join4(sourceDir, file), targetPath);
|
|
2848
|
-
logger.info("Installed default skill", { file });
|
|
2849
|
-
} catch (err) {
|
|
2850
|
-
logger.error("Failed to copy default skill", { file, error: err instanceof Error ? err.message : String(err) });
|
|
2851
|
-
}
|
|
2852
2511
|
}
|
|
2853
2512
|
}
|
|
2513
|
+
return defaults;
|
|
2854
2514
|
}
|
|
2855
|
-
async function
|
|
2856
|
-
|
|
2857
|
-
if (!await dirExists(skillsDir)) {
|
|
2515
|
+
async function loadSkillsFromDir(dir) {
|
|
2516
|
+
if (!await pathExists2(dir)) {
|
|
2858
2517
|
return [];
|
|
2859
2518
|
}
|
|
2860
2519
|
let files;
|
|
2861
2520
|
try {
|
|
2862
|
-
files = (await readdir2(
|
|
2521
|
+
files = (await readdir2(dir)).filter((f) => f.endsWith(SKILL_EXTENSION));
|
|
2863
2522
|
} catch {
|
|
2864
2523
|
return [];
|
|
2865
2524
|
}
|
|
2866
2525
|
const skills = [];
|
|
2867
2526
|
for (const file of files) {
|
|
2868
2527
|
try {
|
|
2869
|
-
const raw = await readFile6(join4(
|
|
2528
|
+
const raw = await readFile6(join4(dir, file), "utf-8");
|
|
2870
2529
|
const { data, content } = matter2(raw);
|
|
2871
|
-
|
|
2872
|
-
|
|
2873
|
-
|
|
2530
|
+
if (data.id && content.trim()) {
|
|
2531
|
+
skills.push({
|
|
2532
|
+
metadata: data,
|
|
2533
|
+
prompt: content.trim()
|
|
2534
|
+
});
|
|
2874
2535
|
} else {
|
|
2875
2536
|
logger.warn("Skipping invalid skill file", { file });
|
|
2876
2537
|
}
|
|
@@ -2880,6 +2541,23 @@ async function loadAllSkills(configDir) {
|
|
|
2880
2541
|
}
|
|
2881
2542
|
return skills;
|
|
2882
2543
|
}
|
|
2544
|
+
async function loadUserSkills(configDir) {
|
|
2545
|
+
return loadSkillsFromDir(getSkillsDir(configDir));
|
|
2546
|
+
}
|
|
2547
|
+
async function loadAllSkills(configDir) {
|
|
2548
|
+
const [defaultSkills, userSkills] = await Promise.all([
|
|
2549
|
+
loadDefaultSkills(),
|
|
2550
|
+
loadUserSkills(configDir)
|
|
2551
|
+
]);
|
|
2552
|
+
const skillMap = /* @__PURE__ */ new Map();
|
|
2553
|
+
for (const skill of defaultSkills) {
|
|
2554
|
+
skillMap.set(skill.metadata.id, skill);
|
|
2555
|
+
}
|
|
2556
|
+
for (const skill of userSkills) {
|
|
2557
|
+
skillMap.set(skill.metadata.id, skill);
|
|
2558
|
+
}
|
|
2559
|
+
return Array.from(skillMap.values());
|
|
2560
|
+
}
|
|
2883
2561
|
async function getEnabledSkills(configDir) {
|
|
2884
2562
|
const all = await loadAllSkills(configDir);
|
|
2885
2563
|
return all.filter((s) => isSkillEnabled(s.metadata.id));
|
|
@@ -2896,71 +2574,36 @@ function isSkillEnabled(skillId) {
|
|
|
2896
2574
|
function setSkillEnabled(skillId, enabled) {
|
|
2897
2575
|
setSetting(`${SKILL_SETTING_PREFIX}${skillId}`, String(enabled));
|
|
2898
2576
|
}
|
|
2899
|
-
async function
|
|
2900
|
-
|
|
2901
|
-
|
|
2902
|
-
|
|
2903
|
-
|
|
2904
|
-
|
|
2905
|
-
}
|
|
2577
|
+
async function getDefaultIds(dir, extension) {
|
|
2578
|
+
try {
|
|
2579
|
+
const files = (await readdir2(dir)).filter((f) => f.endsWith(extension));
|
|
2580
|
+
return files.map((f) => f.replace(extension, ""));
|
|
2581
|
+
} catch {
|
|
2582
|
+
return [];
|
|
2906
2583
|
}
|
|
2907
|
-
return [];
|
|
2908
2584
|
}
|
|
2909
|
-
async function
|
|
2910
|
-
const
|
|
2911
|
-
|
|
2912
|
-
|
|
2913
|
-
if (await dirExists(sourcePath)) {
|
|
2914
|
-
const targetPath = join4(getSkillsDir(configDir), filename);
|
|
2915
|
-
await copyFile2(sourcePath, targetPath);
|
|
2916
|
-
return true;
|
|
2917
|
-
}
|
|
2918
|
-
}
|
|
2919
|
-
return false;
|
|
2585
|
+
async function getDefaultSkillIds() {
|
|
2586
|
+
const ids = await getDefaultIds(DEFAULTS_DIR2, SKILL_EXTENSION);
|
|
2587
|
+
if (ids.length) return ids;
|
|
2588
|
+
return getDefaultIds(DEFAULTS_DIR_ALT2, SKILL_EXTENSION);
|
|
2920
2589
|
}
|
|
2921
|
-
async function
|
|
2922
|
-
const
|
|
2923
|
-
|
|
2924
|
-
for (const id of defaultIds) {
|
|
2925
|
-
const filename = `${id}${SKILL_EXTENSION}`;
|
|
2926
|
-
const userPath = join4(getSkillsDir(configDir), filename);
|
|
2927
|
-
let bundledContent = null;
|
|
2928
|
-
for (const dir of [DEFAULTS_DIR2, DEFAULTS_DIR_ALT2]) {
|
|
2929
|
-
try {
|
|
2930
|
-
bundledContent = await readFile6(join4(dir, filename), "utf-8");
|
|
2931
|
-
break;
|
|
2932
|
-
} catch {
|
|
2933
|
-
}
|
|
2934
|
-
}
|
|
2935
|
-
if (!bundledContent) continue;
|
|
2936
|
-
try {
|
|
2937
|
-
const userContent = await readFile6(userPath, "utf-8");
|
|
2938
|
-
if (userContent !== bundledContent) {
|
|
2939
|
-
modified.push(id);
|
|
2940
|
-
}
|
|
2941
|
-
} catch {
|
|
2942
|
-
}
|
|
2943
|
-
}
|
|
2944
|
-
return modified;
|
|
2590
|
+
async function getDefaultSkillContent(skillId) {
|
|
2591
|
+
const defaults = await loadDefaultSkills();
|
|
2592
|
+
return defaults.find((s) => s.metadata.id === skillId) ?? null;
|
|
2945
2593
|
}
|
|
2946
|
-
async function
|
|
2947
|
-
const
|
|
2948
|
-
|
|
2949
|
-
for (const id of ids) {
|
|
2950
|
-
if (await restoreDefaultSkill(configDir, id)) count++;
|
|
2951
|
-
}
|
|
2952
|
-
return count;
|
|
2594
|
+
async function isDefaultSkill(skillId) {
|
|
2595
|
+
const defaultIds = await getDefaultSkillIds();
|
|
2596
|
+
return defaultIds.includes(skillId);
|
|
2953
2597
|
}
|
|
2954
2598
|
function findSkillById(skillId, skills) {
|
|
2955
2599
|
return skills.find((s) => s.metadata.id === skillId);
|
|
2956
2600
|
}
|
|
2957
2601
|
async function skillExists(configDir, skillId) {
|
|
2958
|
-
|
|
2959
|
-
return dirExists(filePath);
|
|
2602
|
+
return pathExists2(join4(getSkillsDir(configDir), `${skillId}${SKILL_EXTENSION}`));
|
|
2960
2603
|
}
|
|
2961
2604
|
async function saveSkill(configDir, skill) {
|
|
2962
2605
|
const skillsDir = getSkillsDir(configDir);
|
|
2963
|
-
if (!await
|
|
2606
|
+
if (!await pathExists2(skillsDir)) {
|
|
2964
2607
|
await mkdir3(skillsDir, { recursive: true });
|
|
2965
2608
|
}
|
|
2966
2609
|
const filePath = join4(skillsDir, `${skill.metadata.id}${SKILL_EXTENSION}`);
|
|
@@ -2968,19 +2611,31 @@ async function saveSkill(configDir, skill) {
|
|
|
2968
2611
|
await writeFile4(filePath, content, "utf-8");
|
|
2969
2612
|
}
|
|
2970
2613
|
async function deleteSkill(configDir, skillId) {
|
|
2614
|
+
const isDefault = await isDefaultSkill(skillId);
|
|
2615
|
+
if (isDefault) {
|
|
2616
|
+
return { success: false, reason: "Cannot delete built-in defaults" };
|
|
2617
|
+
}
|
|
2971
2618
|
const filePath = join4(getSkillsDir(configDir), `${skillId}${SKILL_EXTENSION}`);
|
|
2972
2619
|
try {
|
|
2973
2620
|
await unlink2(filePath);
|
|
2974
|
-
const { deleteSetting } = await import("./settings-NCLN4JDZ.js");
|
|
2975
2621
|
deleteSetting(`${SKILL_SETTING_PREFIX}${skillId}`);
|
|
2976
|
-
return true;
|
|
2622
|
+
return { success: true };
|
|
2977
2623
|
} catch {
|
|
2978
|
-
return false;
|
|
2624
|
+
return { success: false };
|
|
2979
2625
|
}
|
|
2980
2626
|
}
|
|
2981
2627
|
|
|
2982
2628
|
// src/server/chat/agent-loop.ts
|
|
2983
2629
|
import stripAnsi from "strip-ansi";
|
|
2630
|
+
function emitPartialDoneEvents(sessionId, assistantMsgId, statsIdentity, mode, turnMetrics, promptContext, eventStore) {
|
|
2631
|
+
const stats = turnMetrics.buildStats(statsIdentity, mode);
|
|
2632
|
+
eventStore.append(sessionId, createMessageDoneEvent(assistantMsgId, {
|
|
2633
|
+
stats,
|
|
2634
|
+
partial: true,
|
|
2635
|
+
promptContext
|
|
2636
|
+
}));
|
|
2637
|
+
eventStore.append(sessionId, createChatDoneEvent(assistantMsgId, "stopped", stats));
|
|
2638
|
+
}
|
|
2984
2639
|
function getCurrentWindowMessageOptions(sessionId) {
|
|
2985
2640
|
const contextWindowId = getCurrentContextWindowId(sessionId);
|
|
2986
2641
|
return contextWindowId ? { contextWindowId } : void 0;
|
|
@@ -3211,13 +2866,7 @@ async function runTopLevelAgentLoop(config, turnMetrics) {
|
|
|
3211
2866
|
}
|
|
3212
2867
|
}
|
|
3213
2868
|
if (result.aborted) {
|
|
3214
|
-
|
|
3215
|
-
eventStore.append(sessionId, createMessageDoneEvent(assistantMsgId, {
|
|
3216
|
-
stats: stats2,
|
|
3217
|
-
partial: true,
|
|
3218
|
-
promptContext: assembledRequest.promptContext
|
|
3219
|
-
}));
|
|
3220
|
-
eventStore.append(sessionId, createChatDoneEvent(assistantMsgId, "stopped", stats2));
|
|
2869
|
+
emitPartialDoneEvents(sessionId, assistantMsgId, statsIdentity, mode, turnMetrics, assembledRequest.promptContext, eventStore);
|
|
3221
2870
|
throw new Error("Aborted");
|
|
3222
2871
|
}
|
|
3223
2872
|
turnMetrics.addLLMCall(result.timing, result.usage.promptTokens, result.usage.completionTokens);
|
|
@@ -3252,25 +2901,13 @@ async function runTopLevelAgentLoop(config, turnMetrics) {
|
|
|
3252
2901
|
}
|
|
3253
2902
|
} catch (error) {
|
|
3254
2903
|
if (error instanceof Error && error.message === "Aborted") {
|
|
3255
|
-
|
|
3256
|
-
eventStore.append(sessionId, createMessageDoneEvent(assistantMsgId, {
|
|
3257
|
-
stats: stats2,
|
|
3258
|
-
partial: true,
|
|
3259
|
-
promptContext: assembledRequest.promptContext
|
|
3260
|
-
}));
|
|
3261
|
-
eventStore.append(sessionId, createChatDoneEvent(assistantMsgId, "stopped", stats2));
|
|
2904
|
+
emitPartialDoneEvents(sessionId, assistantMsgId, statsIdentity, mode, turnMetrics, assembledRequest.promptContext, eventStore);
|
|
3262
2905
|
throw error;
|
|
3263
2906
|
}
|
|
3264
2907
|
throw error;
|
|
3265
2908
|
}
|
|
3266
2909
|
if (signal?.aborted) {
|
|
3267
|
-
|
|
3268
|
-
eventStore.append(sessionId, createMessageDoneEvent(assistantMsgId, {
|
|
3269
|
-
stats: stats2,
|
|
3270
|
-
partial: true,
|
|
3271
|
-
promptContext: assembledRequest.promptContext
|
|
3272
|
-
}));
|
|
3273
|
-
eventStore.append(sessionId, createChatDoneEvent(assistantMsgId, "stopped", stats2));
|
|
2910
|
+
emitPartialDoneEvents(sessionId, assistantMsgId, statsIdentity, mode, turnMetrics, assembledRequest.promptContext, eventStore);
|
|
3274
2911
|
throw new Error("Aborted");
|
|
3275
2912
|
}
|
|
3276
2913
|
const asapMessages = sessionManager.drainAsapMessages(sessionId);
|
|
@@ -3308,12 +2945,32 @@ async function runTopLevelAgentLoop(config, turnMetrics) {
|
|
|
3308
2945
|
};
|
|
3309
2946
|
}
|
|
3310
2947
|
|
|
2948
|
+
// src/server/context/nudge-helpers.ts
|
|
2949
|
+
function appendNudgeMessage(eventStore, sessionId, content, currentWindowMessageOptions, options) {
|
|
2950
|
+
const msgId = crypto.randomUUID();
|
|
2951
|
+
eventStore.append(sessionId, createMessageStartEvent(msgId, "user", content, {
|
|
2952
|
+
...currentWindowMessageOptions ?? {},
|
|
2953
|
+
isSystemGenerated: true,
|
|
2954
|
+
messageKind: "correction",
|
|
2955
|
+
subAgentId: options.subAgentId,
|
|
2956
|
+
subAgentType: options.subAgentType
|
|
2957
|
+
}));
|
|
2958
|
+
eventStore.append(sessionId, { type: "message.done", data: { messageId: msgId } });
|
|
2959
|
+
}
|
|
2960
|
+
|
|
3311
2961
|
// src/server/sub-agents/manager.ts
|
|
3312
2962
|
var RETURN_VALUE_INSTRUCTION = `
|
|
3313
2963
|
|
|
3314
2964
|
## RETURN VALUE
|
|
3315
2965
|
As the very last thing you do, call \`return_value\` ONCE with a structured summary of your work. This is how your findings get passed back to the calling agent. Do not finish without calling return_value.`;
|
|
3316
2966
|
var RETURN_VALUE_NUDGE = "You must call return_value with a summary of your findings before finishing. Call return_value now.";
|
|
2967
|
+
function buildSubAgentResult(returnValueContent, returnValueResult, subAgentType, failed, remaining) {
|
|
2968
|
+
return {
|
|
2969
|
+
content: returnValueContent ?? "",
|
|
2970
|
+
...returnValueResult !== null && returnValueResult !== void 0 ? { result: returnValueResult } : {},
|
|
2971
|
+
...subAgentType === "verifier" ? { allPassed: failed.length === 0 && remaining.length === 0, failed } : {}
|
|
2972
|
+
};
|
|
2973
|
+
}
|
|
3317
2974
|
async function resolveAgentDef(agentId) {
|
|
3318
2975
|
const allAgents = await loadAllAgentsDefault();
|
|
3319
2976
|
const def = findAgentById(agentId, allAgents);
|
|
@@ -3483,19 +3140,11 @@ async function executeSubAgent(options) {
|
|
|
3483
3140
|
if (consecutiveEmptyStops < nudgeConfig.maxConsecutiveNudges) {
|
|
3484
3141
|
consecutiveEmptyStops += 1;
|
|
3485
3142
|
const nudgeContent = nudgeConfig.buildNudgeContent(criteriaAwaiting);
|
|
3486
|
-
const nudgeMsgId = crypto.randomUUID();
|
|
3487
3143
|
eventStore.append(sessionId, createMessageDoneEvent(assistantMsgId, {
|
|
3488
3144
|
segments: result.segments,
|
|
3489
3145
|
promptContext
|
|
3490
3146
|
}));
|
|
3491
|
-
eventStore
|
|
3492
|
-
...currentWindowMessageOptions ?? {},
|
|
3493
|
-
isSystemGenerated: true,
|
|
3494
|
-
messageKind: "correction",
|
|
3495
|
-
subAgentId,
|
|
3496
|
-
subAgentType
|
|
3497
|
-
}));
|
|
3498
|
-
eventStore.append(sessionId, { type: "message.done", data: { messageId: nudgeMsgId } });
|
|
3147
|
+
appendNudgeMessage(eventStore, sessionId, nudgeContent, currentWindowMessageOptions, { subAgentId, subAgentType });
|
|
3499
3148
|
customMessages = [...customMessages, { role: "user", content: nudgeContent, source: "runtime" }];
|
|
3500
3149
|
continue;
|
|
3501
3150
|
}
|
|
@@ -3512,19 +3161,11 @@ async function executeSubAgent(options) {
|
|
|
3512
3161
|
}
|
|
3513
3162
|
if (!returnValueContent && !returnValueNudged) {
|
|
3514
3163
|
returnValueNudged = true;
|
|
3515
|
-
const nudgeMsgId = crypto.randomUUID();
|
|
3516
3164
|
eventStore.append(sessionId, createMessageDoneEvent(assistantMsgId, {
|
|
3517
3165
|
segments: result.segments,
|
|
3518
3166
|
promptContext
|
|
3519
3167
|
}));
|
|
3520
|
-
eventStore
|
|
3521
|
-
...currentWindowMessageOptions ?? {},
|
|
3522
|
-
isSystemGenerated: true,
|
|
3523
|
-
messageKind: "correction",
|
|
3524
|
-
subAgentId,
|
|
3525
|
-
subAgentType
|
|
3526
|
-
}));
|
|
3527
|
-
eventStore.append(sessionId, { type: "message.done", data: { messageId: nudgeMsgId } });
|
|
3168
|
+
appendNudgeMessage(eventStore, sessionId, RETURN_VALUE_NUDGE, currentWindowMessageOptions, { subAgentId, subAgentType });
|
|
3528
3169
|
customMessages = [...customMessages, { role: "user", content: RETURN_VALUE_NUDGE, source: "runtime" }];
|
|
3529
3170
|
continue;
|
|
3530
3171
|
}
|
|
@@ -3580,21 +3221,9 @@ async function executeSubAgent(options) {
|
|
|
3580
3221
|
subAgentId,
|
|
3581
3222
|
resultLength: finalContent.length
|
|
3582
3223
|
});
|
|
3583
|
-
|
|
3584
|
-
|
|
3585
|
-
|
|
3586
|
-
const failed = session.criteria.filter((c) => c.status.type === "failed").map((c) => ({
|
|
3587
|
-
id: c.id,
|
|
3588
|
-
reason: c.status.type === "failed" ? c.status.reason : "unknown"
|
|
3589
|
-
}));
|
|
3590
|
-
return {
|
|
3591
|
-
content: returnValueContent ?? finalContent,
|
|
3592
|
-
...returnValueResult ? { result: returnValueResult } : {},
|
|
3593
|
-
allPassed: failed.length === 0 && remaining.length === 0,
|
|
3594
|
-
failed
|
|
3595
|
-
};
|
|
3596
|
-
}
|
|
3597
|
-
return { content: returnValueContent ?? finalContent, ...returnValueResult ? { result: returnValueResult } : { result: "success" } };
|
|
3224
|
+
const failed = session.criteria.filter((c) => c.status.type === "failed").map((c) => ({ id: c.id, reason: c.status.reason ?? "unknown" }));
|
|
3225
|
+
const remaining = nudgeConfig?.getCriteriaAwaiting(session.criteria) ?? [];
|
|
3226
|
+
return buildSubAgentResult(returnValueContent ?? void 0, returnValueResult ?? (subAgentType !== "verifier" ? "success" : void 0), subAgentType, failed, remaining);
|
|
3598
3227
|
}
|
|
3599
3228
|
|
|
3600
3229
|
// src/server/tools/sub-agent.ts
|
|
@@ -3662,7 +3291,7 @@ var callSubAgentTool = {
|
|
|
3662
3291
|
};
|
|
3663
3292
|
}
|
|
3664
3293
|
try {
|
|
3665
|
-
const { getToolRegistryForAgent: getToolRegistryForAgent2 } = await import("./tools-
|
|
3294
|
+
const { getToolRegistryForAgent: getToolRegistryForAgent2 } = await import("./tools-55YICCVH.js");
|
|
3666
3295
|
const toolRegistry = getToolRegistryForAgent2(agentDef);
|
|
3667
3296
|
const turnMetrics = new TurnMetrics();
|
|
3668
3297
|
const result = await executeSubAgent({
|
|
@@ -3814,7 +3443,7 @@ function convertHTMLToMarkdown(html) {
|
|
|
3814
3443
|
return turndown.turndown(html);
|
|
3815
3444
|
}
|
|
3816
3445
|
function stripHTMLTags(html) {
|
|
3817
|
-
|
|
3446
|
+
const text = html.replace(/<(script|style|noscript|iframe|object|embed)[^>]*>[\s\S]*?<\/\1>/gi, "").replace(/<[^>]+>/g, " ").replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, '"').replace(/'/g, "'").replace(/ /g, " ").replace(/\s+/g, " ").trim();
|
|
3818
3447
|
return text;
|
|
3819
3448
|
}
|
|
3820
3449
|
var webFetchTool = createTool(
|
|
@@ -3916,7 +3545,7 @@ var webFetchTool = createTool(
|
|
|
3916
3545
|
);
|
|
3917
3546
|
|
|
3918
3547
|
// src/server/dev-server/manager.ts
|
|
3919
|
-
import { spawn as
|
|
3548
|
+
import { spawn as spawn4 } from "child_process";
|
|
3920
3549
|
import { readFile as readFile7, writeFile as writeFile5, mkdir as mkdir4 } from "fs/promises";
|
|
3921
3550
|
import { resolve as resolve5, join as join5 } from "path";
|
|
3922
3551
|
var MAX_LOG_LINES = 2e3;
|
|
@@ -4010,7 +3639,7 @@ var DevServerManager = class {
|
|
|
4010
3639
|
instance.exited = false;
|
|
4011
3640
|
const resolved = this.resolveWorkdir(workdir);
|
|
4012
3641
|
const shell = getPlatformShell();
|
|
4013
|
-
const proc =
|
|
3642
|
+
const proc = spawn4(shell.command, [...shell.args, config.command], {
|
|
4014
3643
|
cwd: resolved,
|
|
4015
3644
|
env: { ...process.env, FORCE_COLOR: "1" },
|
|
4016
3645
|
stdio: ["ignore", "pipe", "pipe"],
|
|
@@ -4582,14 +4211,7 @@ function getCurrentWindowMessageOptions3(sessionId) {
|
|
|
4582
4211
|
return contextWindowId ? { contextWindowId } : void 0;
|
|
4583
4212
|
}
|
|
4584
4213
|
function toRequestContextMessages2(messages) {
|
|
4585
|
-
return messages
|
|
4586
|
-
role: message.role,
|
|
4587
|
-
content: message.content,
|
|
4588
|
-
source: "history",
|
|
4589
|
-
...message.toolCalls ? { toolCalls: message.toolCalls } : {},
|
|
4590
|
-
...message.toolCallId ? { toolCallId: message.toolCallId } : {},
|
|
4591
|
-
...message.attachments ? { attachments: message.attachments } : {}
|
|
4592
|
-
}));
|
|
4214
|
+
return minimalMessagesToRequestContextMessages(messages, "history");
|
|
4593
4215
|
}
|
|
4594
4216
|
async function maybeAutoCompactContext(options) {
|
|
4595
4217
|
const config = getRuntimeConfig();
|
|
@@ -4744,13 +4366,14 @@ export {
|
|
|
4744
4366
|
PathAccessDeniedError,
|
|
4745
4367
|
providePathConfirmation,
|
|
4746
4368
|
cancelPathConfirmationsForSession,
|
|
4747
|
-
|
|
4369
|
+
checkAborted,
|
|
4370
|
+
spawnShellProcess,
|
|
4371
|
+
loadDefaultAgents,
|
|
4372
|
+
loadUserAgents,
|
|
4748
4373
|
loadAllAgents,
|
|
4749
4374
|
loadAllAgentsDefault,
|
|
4750
4375
|
getDefaultAgentIds,
|
|
4751
|
-
|
|
4752
|
-
getModifiedDefaultAgentIds,
|
|
4753
|
-
restoreAllDefaultAgents,
|
|
4376
|
+
getDefaultAgentContent,
|
|
4754
4377
|
findAgentById,
|
|
4755
4378
|
getSubAgents,
|
|
4756
4379
|
agentExists,
|
|
@@ -4767,15 +4390,14 @@ export {
|
|
|
4767
4390
|
createChatDoneEvent,
|
|
4768
4391
|
getAllInstructions,
|
|
4769
4392
|
assembleAgentRequest,
|
|
4770
|
-
|
|
4393
|
+
loadDefaultSkills,
|
|
4394
|
+
loadUserSkills,
|
|
4771
4395
|
loadAllSkills,
|
|
4772
4396
|
getEnabledSkillMetadata,
|
|
4773
4397
|
isSkillEnabled,
|
|
4774
4398
|
setSkillEnabled,
|
|
4775
4399
|
getDefaultSkillIds,
|
|
4776
|
-
|
|
4777
|
-
getModifiedDefaultSkillIds,
|
|
4778
|
-
restoreAllDefaultSkills,
|
|
4400
|
+
getDefaultSkillContent,
|
|
4779
4401
|
findSkillById,
|
|
4780
4402
|
skillExists,
|
|
4781
4403
|
saveSkill,
|
|
@@ -4795,4 +4417,4 @@ export {
|
|
|
4795
4417
|
getToolRegistryForAgent,
|
|
4796
4418
|
createToolRegistry
|
|
4797
4419
|
};
|
|
4798
|
-
//# sourceMappingURL=chunk-
|
|
4420
|
+
//# sourceMappingURL=chunk-4OI4VPZ6.js.map
|