deepclause-sdk 0.0.88 → 0.1.0
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/LICENSE +21 -0
- package/README.md +418 -914
- package/dist/agent.d.ts +19 -2
- package/dist/agent.d.ts.map +1 -1
- package/dist/agent.js +221 -4
- package/dist/agent.js.map +1 -1
- package/dist/cli/config.d.ts +323 -176
- package/dist/cli/config.d.ts.map +1 -1
- package/dist/cli/config.js +146 -188
- package/dist/cli/config.js.map +1 -1
- package/dist/cli/index.d.ts +3 -2
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +61 -425
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/login.d.ts +29 -0
- package/dist/cli/login.d.ts.map +1 -0
- package/dist/cli/login.js +184 -0
- package/dist/cli/login.js.map +1 -0
- package/dist/cli/readline.d.ts +6 -0
- package/dist/cli/readline.d.ts.map +1 -0
- package/dist/cli/readline.js +15 -0
- package/dist/cli/readline.js.map +1 -0
- package/dist/cli/repl-bin.d.ts +9 -0
- package/dist/cli/repl-bin.d.ts.map +1 -0
- package/dist/cli/repl-bin.js +16 -0
- package/dist/cli/repl-bin.js.map +1 -0
- package/dist/cli/repl.d.ts +191 -0
- package/dist/cli/repl.d.ts.map +1 -0
- package/dist/cli/repl.js +1232 -0
- package/dist/cli/repl.js.map +1 -0
- package/dist/cli/run.d.ts +17 -18
- package/dist/cli/run.d.ts.map +1 -1
- package/dist/cli/run.js +196 -183
- package/dist/cli/run.js.map +1 -1
- package/dist/cli/set-backend.d.ts +53 -0
- package/dist/cli/set-backend.d.ts.map +1 -0
- package/dist/cli/set-backend.js +259 -0
- package/dist/cli/set-backend.js.map +1 -0
- package/dist/cli/visualize.d.ts +38 -0
- package/dist/cli/visualize.d.ts.map +1 -0
- package/dist/cli/visualize.js +125 -0
- package/dist/cli/visualize.js.map +1 -0
- package/dist/compiler.d.ts +5 -52
- package/dist/compiler.d.ts.map +1 -1
- package/dist/compiler.js +4 -768
- package/dist/compiler.js.map +1 -1
- package/dist/index.d.ts +29 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +20 -2
- package/dist/index.js.map +1 -1
- package/dist/judge/index.d.ts +9 -0
- package/dist/judge/index.d.ts.map +1 -0
- package/dist/judge/index.js +6 -0
- package/dist/judge/index.js.map +1 -0
- package/dist/judge/jev.d.ts +21 -0
- package/dist/judge/jev.d.ts.map +1 -0
- package/dist/judge/jev.js +218 -0
- package/dist/judge/jev.js.map +1 -0
- package/dist/judge/llm.d.ts +23 -0
- package/dist/judge/llm.d.ts.map +1 -0
- package/dist/judge/llm.js +120 -0
- package/dist/judge/llm.js.map +1 -0
- package/dist/judge/marshal.d.ts +26 -0
- package/dist/judge/marshal.d.ts.map +1 -0
- package/dist/judge/marshal.js +266 -0
- package/dist/judge/marshal.js.map +1 -0
- package/dist/judge/mock.d.ts +28 -0
- package/dist/judge/mock.d.ts.map +1 -0
- package/dist/judge/mock.js +98 -0
- package/dist/judge/mock.js.map +1 -0
- package/dist/judge/types.d.ts +95 -0
- package/dist/judge/types.d.ts.map +1 -0
- package/dist/judge/types.js +23 -0
- package/dist/judge/types.js.map +1 -0
- package/dist/prolog/bridge.d.ts +5 -1
- package/dist/prolog/bridge.d.ts.map +1 -1
- package/dist/prolog/bridge.js +29 -1
- package/dist/prolog/bridge.js.map +1 -1
- package/dist/prolog-src/deepclause_analysis.pl +10 -2
- package/dist/prolog-src/deepclause_mi.pl +2522 -118
- package/dist/repl/agent.d.ts +72 -0
- package/dist/repl/agent.d.ts.map +1 -0
- package/dist/repl/agent.js +366 -0
- package/dist/repl/agent.js.map +1 -0
- package/dist/repl/auth.d.ts +45 -0
- package/dist/repl/auth.d.ts.map +1 -0
- package/dist/repl/auth.js +116 -0
- package/dist/repl/auth.js.map +1 -0
- package/dist/repl/backend.d.ts +290 -0
- package/dist/repl/backend.d.ts.map +1 -0
- package/dist/repl/backend.js +370 -0
- package/dist/repl/backend.js.map +1 -0
- package/dist/repl/compaction.d.ts +122 -0
- package/dist/repl/compaction.d.ts.map +1 -0
- package/dist/repl/compaction.js +318 -0
- package/dist/repl/compaction.js.map +1 -0
- package/dist/repl/export.d.ts +30 -0
- package/dist/repl/export.d.ts.map +1 -0
- package/dist/repl/export.js +23 -0
- package/dist/repl/export.js.map +1 -0
- package/dist/repl/frames.d.ts +21 -0
- package/dist/repl/frames.d.ts.map +1 -0
- package/dist/repl/frames.js +79 -0
- package/dist/repl/frames.js.map +1 -0
- package/dist/repl/harness-tools.d.ts +74 -0
- package/dist/repl/harness-tools.d.ts.map +1 -0
- package/dist/repl/harness-tools.js +121 -0
- package/dist/repl/harness-tools.js.map +1 -0
- package/dist/repl/highlight.d.ts +30 -0
- package/dist/repl/highlight.d.ts.map +1 -0
- package/dist/repl/highlight.js +285 -0
- package/dist/repl/highlight.js.map +1 -0
- package/dist/repl/history.d.ts +234 -0
- package/dist/repl/history.d.ts.map +1 -0
- package/dist/repl/history.js +661 -0
- package/dist/repl/history.js.map +1 -0
- package/dist/repl/index.d.ts +120 -0
- package/dist/repl/index.d.ts.map +1 -0
- package/dist/repl/index.js +107 -0
- package/dist/repl/index.js.map +1 -0
- package/dist/repl/judge.d.ts +51 -0
- package/dist/repl/judge.d.ts.map +1 -0
- package/dist/repl/judge.js +58 -0
- package/dist/repl/judge.js.map +1 -0
- package/dist/repl/markdown.d.ts +25 -0
- package/dist/repl/markdown.d.ts.map +1 -0
- package/dist/repl/markdown.js +103 -0
- package/dist/repl/markdown.js.map +1 -0
- package/dist/repl/picker.d.ts +34 -0
- package/dist/repl/picker.d.ts.map +1 -0
- package/dist/repl/picker.js +81 -0
- package/dist/repl/picker.js.map +1 -0
- package/dist/repl/project-context.d.ts +16 -0
- package/dist/repl/project-context.d.ts.map +1 -0
- package/dist/repl/project-context.js +23 -0
- package/dist/repl/project-context.js.map +1 -0
- package/dist/repl/render.d.ts +160 -0
- package/dist/repl/render.d.ts.map +1 -0
- package/dist/repl/render.js +715 -0
- package/dist/repl/render.js.map +1 -0
- package/dist/repl/session.d.ts +356 -0
- package/dist/repl/session.d.ts.map +1 -0
- package/dist/repl/session.js +1275 -0
- package/dist/repl/session.js.map +1 -0
- package/dist/repl/status.d.ts +100 -0
- package/dist/repl/status.d.ts.map +1 -0
- package/dist/repl/status.js +218 -0
- package/dist/repl/status.js.map +1 -0
- package/dist/repl/tools.d.ts +53 -0
- package/dist/repl/tools.d.ts.map +1 -0
- package/dist/repl/tools.js +307 -0
- package/dist/repl/tools.js.map +1 -0
- package/dist/repl/toolset.d.ts +32 -0
- package/dist/repl/toolset.d.ts.map +1 -0
- package/dist/repl/toolset.js +82 -0
- package/dist/repl/toolset.js.map +1 -0
- package/dist/repl/tui/editor.d.ts +17 -0
- package/dist/repl/tui/editor.d.ts.map +1 -0
- package/dist/repl/tui/editor.js +39 -0
- package/dist/repl/tui/editor.js.map +1 -0
- package/dist/repl/tui/status-bar.d.ts +26 -0
- package/dist/repl/tui/status-bar.d.ts.map +1 -0
- package/dist/repl/tui/status-bar.js +47 -0
- package/dist/repl/tui/status-bar.js.map +1 -0
- package/dist/repl/tui/theme.d.ts +30 -0
- package/dist/repl/tui/theme.d.ts.map +1 -0
- package/dist/repl/tui/theme.js +81 -0
- package/dist/repl/tui/theme.js.map +1 -0
- package/dist/repl/tui/transcript.d.ts +39 -0
- package/dist/repl/tui/transcript.d.ts.map +1 -0
- package/dist/repl/tui/transcript.js +123 -0
- package/dist/repl/tui/transcript.js.map +1 -0
- package/dist/runner.d.ts +145 -13
- package/dist/runner.d.ts.map +1 -1
- package/dist/runner.js +600 -282
- package/dist/runner.js.map +1 -1
- package/dist/sdk.d.ts.map +1 -1
- package/dist/sdk.js +56 -32
- package/dist/sdk.js.map +1 -1
- package/dist/system/assets/docs/AGENT_PROMPT.md +1373 -0
- package/dist/system/assets/docs/DML_AUTHORING.md +195 -0
- package/dist/system/assets/docs/DML_REFERENCE.md +393 -72
- package/dist/system/assets/docs/HARNESS_EXAMPLES.md +172 -0
- package/dist/system/assets/docs/HARNESS_PATTERNS.md +562 -0
- package/dist/system/assets/docs/META_PROMPT.md +68 -0
- package/dist/system/assets/docs/PROLOG_SNIPPETS.md +117 -0
- package/dist/system/assets/index.d.ts +9 -17
- package/dist/system/assets/index.d.ts.map +1 -1
- package/dist/system/assets/index.js +26 -85
- package/dist/system/assets/index.js.map +1 -1
- package/dist/system/runtime/agentvm-manager.d.ts +9 -2
- package/dist/system/runtime/agentvm-manager.d.ts.map +1 -1
- package/dist/system/runtime/agentvm-manager.js +70 -44
- package/dist/system/runtime/agentvm-manager.js.map +1 -1
- package/dist/system/runtime/media.d.ts +23 -0
- package/dist/system/runtime/media.d.ts.map +1 -0
- package/dist/system/runtime/media.js +55 -0
- package/dist/system/runtime/media.js.map +1 -0
- package/dist/system/runtime/shell-limits.d.ts +21 -0
- package/dist/system/runtime/shell-limits.d.ts.map +1 -0
- package/dist/system/runtime/shell-limits.js +39 -0
- package/dist/system/runtime/shell-limits.js.map +1 -0
- package/dist/system/runtime/shell-manager.d.ts +8 -3
- package/dist/system/runtime/shell-manager.d.ts.map +1 -1
- package/dist/system/runtime/shell-manager.js +56 -39
- package/dist/system/runtime/shell-manager.js.map +1 -1
- package/dist/system/runtime/shell-tool-events.js +5 -0
- package/dist/system/runtime/shell-tool-events.js.map +1 -1
- package/dist/system/runtime/token-usage.d.ts +2 -0
- package/dist/system/runtime/token-usage.d.ts.map +1 -1
- package/dist/system/runtime/token-usage.js +7 -0
- package/dist/system/runtime/token-usage.js.map +1 -1
- package/dist/tools.d.ts +3 -21
- package/dist/tools.d.ts.map +1 -1
- package/dist/tools.js +14 -168
- package/dist/tools.js.map +1 -1
- package/dist/types.d.ts +149 -118
- package/dist/types.d.ts.map +1 -1
- package/dist/validate.d.ts +19 -0
- package/dist/validate.d.ts.map +1 -0
- package/dist/validate.js +338 -0
- package/dist/validate.js.map +1 -0
- package/dist/visualize/index.d.ts +52 -0
- package/dist/visualize/index.d.ts.map +1 -0
- package/dist/visualize/index.js +189 -0
- package/dist/visualize/index.js.map +1 -0
- package/package.json +17 -15
- package/src/prolog-src/deepclause_analysis.pl +10 -2
- package/src/prolog-src/deepclause_mi.pl +2522 -118
- package/dist/cli/commands.d.ts +0 -42
- package/dist/cli/commands.d.ts.map +0 -1
- package/dist/cli/commands.js +0 -246
- package/dist/cli/commands.js.map +0 -1
- package/dist/cli/compile.d.ts +0 -99
- package/dist/cli/compile.d.ts.map +0 -1
- package/dist/cli/compile.js +0 -363
- package/dist/cli/compile.js.map +0 -1
- package/dist/cli/default-skills.d.ts +0 -10
- package/dist/cli/default-skills.d.ts.map +0 -1
- package/dist/cli/default-skills.js +0 -206
- package/dist/cli/default-skills.js.map +0 -1
- package/dist/cli/interactive.d.ts +0 -2
- package/dist/cli/interactive.d.ts.map +0 -1
- package/dist/cli/interactive.js +0 -20
- package/dist/cli/interactive.js.map +0 -1
- package/dist/cli/mcp.d.ts +0 -56
- package/dist/cli/mcp.d.ts.map +0 -1
- package/dist/cli/mcp.js +0 -138
- package/dist/cli/mcp.js.map +0 -1
- package/dist/cli/prompt.d.ts +0 -2
- package/dist/cli/prompt.d.ts.map +0 -1
- package/dist/cli/prompt.js +0 -2
- package/dist/cli/prompt.js.map +0 -1
- package/dist/cli/search.d.ts +0 -19
- package/dist/cli/search.d.ts.map +0 -1
- package/dist/cli/search.js +0 -189
- package/dist/cli/search.js.map +0 -1
- package/dist/cli/tool-args.d.ts +0 -2
- package/dist/cli/tool-args.d.ts.map +0 -1
- package/dist/cli/tool-args.js +0 -39
- package/dist/cli/tool-args.js.map +0 -1
- package/dist/cli/tools.d.ts +0 -36
- package/dist/cli/tools.d.ts.map +0 -1
- package/dist/cli/tools.js +0 -229
- package/dist/cli/tools.js.map +0 -1
- package/dist/cli/tui/index.d.ts +0 -22
- package/dist/cli/tui/index.d.ts.map +0 -1
- package/dist/cli/tui/index.js +0 -29
- package/dist/cli/tui/index.js.map +0 -1
- package/dist/cli/tui.d.ts +0 -167
- package/dist/cli/tui.d.ts.map +0 -1
- package/dist/cli/tui.js +0 -5228
- package/dist/cli/tui.js.map +0 -1
- package/dist/compiler_prompt.d.ts +0 -20
- package/dist/compiler_prompt.d.ts.map +0 -1
- package/dist/compiler_prompt.js +0 -870
- package/dist/compiler_prompt.js.map +0 -1
- package/dist/deepclause-cli.skill +0 -0
- package/dist/prolog-src/deepclause_mi.pl.bak +0 -570
- package/dist/system/assets/compactors/default-memory-compactor.dml +0 -6
- package/dist/system/assets/docs/CONDUCTOR_PROMPT.md +0 -105
- package/dist/system/assets/docs/DML_COMPILER_PROMPT.md +0 -700
- package/dist/system/assets/docs/TUI.md +0 -150
- package/dist/system/assets/recipes/deepclause-coding-workflow/SKILL.md +0 -100
- package/dist/system/assets/skills/conductor.dml +0 -76
- package/dist/system/assets/skills/deep-planner.dml +0 -412
- package/dist/system/assets/skills/plan.dml +0 -429
- package/dist/system/assets/skills/security-planner.dml +0 -337
- package/dist/system/assets/skills/skill-creator.dml +0 -187
- package/dist/system/runtime/catalog-recipes.d.ts +0 -24
- package/dist/system/runtime/catalog-recipes.d.ts.map +0 -1
- package/dist/system/runtime/catalog-recipes.js +0 -273
- package/dist/system/runtime/catalog-recipes.js.map +0 -1
- package/dist/system/runtime/catalog-skills.d.ts +0 -50
- package/dist/system/runtime/catalog-skills.d.ts.map +0 -1
- package/dist/system/runtime/catalog-skills.js +0 -152
- package/dist/system/runtime/catalog-skills.js.map +0 -1
- package/dist/system/runtime/conductor.d.ts +0 -105
- package/dist/system/runtime/conductor.d.ts.map +0 -1
- package/dist/system/runtime/conductor.js +0 -732
- package/dist/system/runtime/conductor.js.map +0 -1
- package/dist/system/runtime/console-capture.d.ts +0 -9
- package/dist/system/runtime/console-capture.d.ts.map +0 -1
- package/dist/system/runtime/console-capture.js +0 -67
- package/dist/system/runtime/console-capture.js.map +0 -1
- package/dist/system/runtime/dml-executor.d.ts +0 -52
- package/dist/system/runtime/dml-executor.d.ts.map +0 -1
- package/dist/system/runtime/dml-executor.js +0 -203
- package/dist/system/runtime/dml-executor.js.map +0 -1
- package/dist/system/runtime/runtime-tools.d.ts +0 -31
- package/dist/system/runtime/runtime-tools.d.ts.map +0 -1
- package/dist/system/runtime/runtime-tools.js +0 -312
- package/dist/system/runtime/runtime-tools.js.map +0 -1
- package/dist/system/runtime/skill-creator.d.ts +0 -38
- package/dist/system/runtime/skill-creator.d.ts.map +0 -1
- package/dist/system/runtime/skill-creator.js +0 -763
- package/dist/system/runtime/skill-creator.js.map +0 -1
- package/src/prolog-src/deepclause_mi.pl.bak +0 -570
|
@@ -1,732 +0,0 @@
|
|
|
1
|
-
import * as fs from 'fs/promises';
|
|
2
|
-
import * as path from 'path';
|
|
3
|
-
import { randomUUID } from 'crypto';
|
|
4
|
-
import { listCommands } from '../../cli/commands.js';
|
|
5
|
-
import { ensureWorkspaceDocSeeds, getDocsDir, getConfigDir, getToolsDir, loadConfig, resolveCompactionConfig, resolveModelSlot, } from '../../cli/config.js';
|
|
6
|
-
import { promptUser } from '../../cli/interactive.js';
|
|
7
|
-
import { createDeepClause } from '../../sdk.js';
|
|
8
|
-
import { resolveCompactorModelConfig, executeCompactor, getCompactionBindings, resolveCompactionOptions, } from '../../compaction.js';
|
|
9
|
-
import { getWorkspaceRecipeAssetsDir, readSystemPromptAsset, readSystemSkillAsset, } from '../assets/index.js';
|
|
10
|
-
import { listRecipeCatalog, searchRecipeCatalog } from './catalog-recipes.js';
|
|
11
|
-
import { executeDml } from './dml-executor.js';
|
|
12
|
-
import { compileWithSkillCreator, deriveSkillSlugFromMarkdown } from './skill-creator.js';
|
|
13
|
-
import { isTokenUsageEmpty, mergeTokenUsageMaps, recordTokenUsage, } from './token-usage.js';
|
|
14
|
-
const DEFAULT_SESSION_TITLE_PREFIX = 'Session';
|
|
15
|
-
export async function listConductorSessions(workspaceRoot = process.cwd()) {
|
|
16
|
-
const sessionsDir = getSessionsDir(workspaceRoot);
|
|
17
|
-
try {
|
|
18
|
-
const entries = await fs.readdir(sessionsDir, { withFileTypes: true });
|
|
19
|
-
const sessions = await Promise.all(entries
|
|
20
|
-
.filter((entry) => entry.isDirectory())
|
|
21
|
-
.map(async (entry) => readSessionMetadata(path.join(sessionsDir, entry.name))));
|
|
22
|
-
return sessions
|
|
23
|
-
.filter((session) => session !== null)
|
|
24
|
-
.sort((left, right) => right.updatedAt.localeCompare(left.updatedAt));
|
|
25
|
-
}
|
|
26
|
-
catch (error) {
|
|
27
|
-
if (error.code === 'ENOENT') {
|
|
28
|
-
return [];
|
|
29
|
-
}
|
|
30
|
-
throw error;
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
export async function createConductorSession(workspaceRoot = process.cwd(), title) {
|
|
34
|
-
const now = new Date().toISOString();
|
|
35
|
-
const metadata = {
|
|
36
|
-
id: randomUUID(),
|
|
37
|
-
title: title?.trim() || `${DEFAULT_SESSION_TITLE_PREFIX} ${now.slice(0, 16).replace('T', ' ')}`,
|
|
38
|
-
createdAt: now,
|
|
39
|
-
updatedAt: now,
|
|
40
|
-
};
|
|
41
|
-
const paths = getSessionPaths(workspaceRoot, metadata.id);
|
|
42
|
-
await fs.mkdir(paths.dir, { recursive: true });
|
|
43
|
-
await fs.writeFile(paths.metadataPath, JSON.stringify(metadata, null, 2) + '\n', 'utf8');
|
|
44
|
-
await fs.writeFile(paths.messagesPath, '', 'utf8');
|
|
45
|
-
await fs.writeFile(paths.assistantMemoryPath, '', 'utf8');
|
|
46
|
-
await fs.writeFile(paths.taskMemoryPath, '', 'utf8');
|
|
47
|
-
await fs.writeFile(paths.usagePath, '{}\n', 'utf8');
|
|
48
|
-
await fs.writeFile(paths.executionLogPath, '', 'utf8');
|
|
49
|
-
return metadata;
|
|
50
|
-
}
|
|
51
|
-
export async function getConductorSessionDetail(workspaceRoot = process.cwd(), sessionId) {
|
|
52
|
-
const paths = getSessionPaths(workspaceRoot, sessionId);
|
|
53
|
-
const metadata = await readRequiredSessionMetadata(paths.dir);
|
|
54
|
-
const messages = await readSessionMessages(paths.messagesPath);
|
|
55
|
-
const assistantMemory = await readOptionalText(paths.assistantMemoryPath);
|
|
56
|
-
const taskMemory = await readOptionalText(paths.taskMemoryPath);
|
|
57
|
-
const usageByModel = await readSessionUsage(paths.usagePath);
|
|
58
|
-
return {
|
|
59
|
-
...metadata,
|
|
60
|
-
messages,
|
|
61
|
-
assistantMemory,
|
|
62
|
-
taskMemory,
|
|
63
|
-
usageByModel,
|
|
64
|
-
executionLogPath: paths.executionLogPath,
|
|
65
|
-
};
|
|
66
|
-
}
|
|
67
|
-
export async function appendConductorSessionMessages(workspaceRoot = process.cwd(), sessionId, messages) {
|
|
68
|
-
if (messages.length === 0) {
|
|
69
|
-
return;
|
|
70
|
-
}
|
|
71
|
-
const paths = getSessionPaths(workspaceRoot, sessionId);
|
|
72
|
-
await readRequiredSessionMetadata(paths.dir);
|
|
73
|
-
let appended = false;
|
|
74
|
-
for (const message of messages) {
|
|
75
|
-
if ((message.role !== 'user' && message.role !== 'assistant') || !message.content.trim()) {
|
|
76
|
-
continue;
|
|
77
|
-
}
|
|
78
|
-
await appendSessionMessage(paths.messagesPath, {
|
|
79
|
-
role: message.role,
|
|
80
|
-
content: message.content,
|
|
81
|
-
timestamp: new Date().toISOString(),
|
|
82
|
-
});
|
|
83
|
-
appended = true;
|
|
84
|
-
}
|
|
85
|
-
if (appended) {
|
|
86
|
-
await touchSession(workspaceRoot, sessionId);
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
export async function runConductorTurn(userMessage, options = {}) {
|
|
90
|
-
const workspaceRoot = path.resolve(options.workspaceRoot ?? process.cwd());
|
|
91
|
-
const config = options.config ?? await loadConfig(workspaceRoot);
|
|
92
|
-
await ensureWorkspaceDocSeeds(workspaceRoot);
|
|
93
|
-
const workspacePath = path.resolve(options.workspacePath ?? config.workspace ?? './workspace');
|
|
94
|
-
await fs.mkdir(workspacePath, { recursive: true });
|
|
95
|
-
const session = await loadOrCreateSession(workspaceRoot, options.sessionId, options.sessionTitle);
|
|
96
|
-
const gatewaySelection = resolveModelSlot(config, 'gateway');
|
|
97
|
-
const compileSelection = resolveModelSlot(config, 'compile');
|
|
98
|
-
const runSelection = resolveModelSlot(config, 'run');
|
|
99
|
-
const systemPrompt = await buildConductorSystemPrompt({
|
|
100
|
-
workspaceRoot,
|
|
101
|
-
workspacePath,
|
|
102
|
-
session,
|
|
103
|
-
gatewayModelId: gatewaySelection.id,
|
|
104
|
-
compileModelId: compileSelection.id,
|
|
105
|
-
runModelId: runSelection.id,
|
|
106
|
-
});
|
|
107
|
-
const conductorDml = await readSystemSkillAsset('conductor', { workspaceRoot });
|
|
108
|
-
const onUserInput = options.onUserInput ?? promptUser;
|
|
109
|
-
const usageByModel = {};
|
|
110
|
-
const executionLog = createSessionExecutionLogWriter({
|
|
111
|
-
workspaceRoot,
|
|
112
|
-
sessionId: session.metadata.id,
|
|
113
|
-
executionKind: 'conductor',
|
|
114
|
-
inputText: userMessage,
|
|
115
|
-
modelId: gatewaySelection.id,
|
|
116
|
-
});
|
|
117
|
-
const emitLogEvent = (event) => {
|
|
118
|
-
if (event.event.type === 'usage') {
|
|
119
|
-
recordTokenUsage(usageByModel, event.modelId, event.event.usage);
|
|
120
|
-
}
|
|
121
|
-
executionLog.recordEvent(event);
|
|
122
|
-
options.onEvent?.(event);
|
|
123
|
-
};
|
|
124
|
-
const compactedSessionMessages = await maybeCompactSessionMessages({
|
|
125
|
-
config,
|
|
126
|
-
workspaceRoot,
|
|
127
|
-
workspacePath,
|
|
128
|
-
selection: gatewaySelection,
|
|
129
|
-
signal: options.signal,
|
|
130
|
-
verbose: options.verbose,
|
|
131
|
-
messagesPath: session.paths.messagesPath,
|
|
132
|
-
messages: session.messages,
|
|
133
|
-
onCompactionEvent: (event) => emitLogEvent({ scope: 'main', modelId: gatewaySelection.id, event }),
|
|
134
|
-
});
|
|
135
|
-
let result;
|
|
136
|
-
try {
|
|
137
|
-
result = await executeDml({
|
|
138
|
-
dmlCode: conductorDml,
|
|
139
|
-
config,
|
|
140
|
-
workspaceRoot,
|
|
141
|
-
workspacePath,
|
|
142
|
-
selection: gatewaySelection,
|
|
143
|
-
args: [userMessage],
|
|
144
|
-
params: {
|
|
145
|
-
system_prompt: systemPrompt,
|
|
146
|
-
},
|
|
147
|
-
gasLimit: options.gasLimit ?? 320,
|
|
148
|
-
verbose: options.verbose,
|
|
149
|
-
headless: options.headless ?? true,
|
|
150
|
-
stream: options.stream ?? false,
|
|
151
|
-
trace: options.trace,
|
|
152
|
-
sandbox: options.sandbox,
|
|
153
|
-
signal: options.signal,
|
|
154
|
-
toolAbortSignalRef: options.toolAbortSignalRef,
|
|
155
|
-
onUserInput,
|
|
156
|
-
initialMessages: compactedSessionMessages,
|
|
157
|
-
skillCatalog: {
|
|
158
|
-
workspaceRoot,
|
|
159
|
-
currentSkillSlug: '_conductor',
|
|
160
|
-
onChildEvent: (childSlug, event) => emitLogEvent({
|
|
161
|
-
scope: 'child',
|
|
162
|
-
childSlug,
|
|
163
|
-
modelId: gatewaySelection.id,
|
|
164
|
-
event,
|
|
165
|
-
}),
|
|
166
|
-
},
|
|
167
|
-
onEvent: (event) => emitLogEvent({ scope: 'main', modelId: gatewaySelection.id, event }),
|
|
168
|
-
registerAdditionalTools: async (sdk, context) => registerConductorTools(sdk, context, {
|
|
169
|
-
workspaceRoot,
|
|
170
|
-
workspacePath,
|
|
171
|
-
session,
|
|
172
|
-
config,
|
|
173
|
-
compileSelection,
|
|
174
|
-
runSelection,
|
|
175
|
-
stream: options.stream ?? false,
|
|
176
|
-
verbose: options.verbose,
|
|
177
|
-
sandbox: options.sandbox ?? false,
|
|
178
|
-
signal: options.signal,
|
|
179
|
-
onUserInput,
|
|
180
|
-
onEvent: emitLogEvent,
|
|
181
|
-
}),
|
|
182
|
-
});
|
|
183
|
-
}
|
|
184
|
-
catch (error) {
|
|
185
|
-
await mergeSessionUsage(workspaceRoot, session.metadata.id, usageByModel);
|
|
186
|
-
await executionLog.finish({
|
|
187
|
-
status: 'error',
|
|
188
|
-
error: error.message,
|
|
189
|
-
usageByModel: isTokenUsageEmpty(usageByModel) ? undefined : usageByModel,
|
|
190
|
-
});
|
|
191
|
-
throw error;
|
|
192
|
-
}
|
|
193
|
-
await maybeUpdateSessionTitle(workspaceRoot, session.metadata, userMessage);
|
|
194
|
-
await appendSessionMessage(session.paths.messagesPath, {
|
|
195
|
-
role: 'user',
|
|
196
|
-
content: userMessage,
|
|
197
|
-
timestamp: new Date().toISOString(),
|
|
198
|
-
});
|
|
199
|
-
const assistantContent = result.answer ?? result.error;
|
|
200
|
-
if (assistantContent) {
|
|
201
|
-
await appendSessionMessage(session.paths.messagesPath, {
|
|
202
|
-
role: 'assistant',
|
|
203
|
-
content: assistantContent,
|
|
204
|
-
timestamp: new Date().toISOString(),
|
|
205
|
-
});
|
|
206
|
-
}
|
|
207
|
-
await mergeSessionUsage(workspaceRoot, session.metadata.id, usageByModel);
|
|
208
|
-
await touchSession(workspaceRoot, session.metadata.id);
|
|
209
|
-
await executionLog.finish({
|
|
210
|
-
status: result.error ? 'error' : 'success',
|
|
211
|
-
answer: result.answer,
|
|
212
|
-
error: result.error,
|
|
213
|
-
outputCount: result.output.length,
|
|
214
|
-
usageByModel: isTokenUsageEmpty(usageByModel) ? undefined : usageByModel,
|
|
215
|
-
});
|
|
216
|
-
return {
|
|
217
|
-
sessionId: session.metadata.id,
|
|
218
|
-
output: result.output,
|
|
219
|
-
answer: result.answer,
|
|
220
|
-
error: result.error,
|
|
221
|
-
trace: result.trace,
|
|
222
|
-
};
|
|
223
|
-
}
|
|
224
|
-
async function registerConductorTools(sdk, _context, options) {
|
|
225
|
-
sdk.registerTool('create_skill', {
|
|
226
|
-
description: 'Create and publish a new local CLI skill into .deepclause/tools.',
|
|
227
|
-
parameters: {
|
|
228
|
-
type: 'object',
|
|
229
|
-
properties: {
|
|
230
|
-
spec: { type: 'string', description: 'Natural-language skill specification.' },
|
|
231
|
-
},
|
|
232
|
-
required: ['spec'],
|
|
233
|
-
},
|
|
234
|
-
execute: async (args) => createLocalSkill({
|
|
235
|
-
spec: String(args.spec ?? ''),
|
|
236
|
-
workspaceRoot: options.workspaceRoot,
|
|
237
|
-
workspacePath: options.workspacePath,
|
|
238
|
-
config: options.config,
|
|
239
|
-
compileSelection: options.compileSelection,
|
|
240
|
-
runSelection: options.runSelection,
|
|
241
|
-
sessionId: options.session.metadata.id,
|
|
242
|
-
verbose: options.verbose,
|
|
243
|
-
sandbox: options.sandbox,
|
|
244
|
-
signal: options.signal,
|
|
245
|
-
onUserInput: options.onUserInput,
|
|
246
|
-
onEvent: options.onEvent,
|
|
247
|
-
}),
|
|
248
|
-
});
|
|
249
|
-
sdk.registerTool('update_memory', {
|
|
250
|
-
description: 'Replace the current task memory markdown for this conductor session.',
|
|
251
|
-
parameters: {
|
|
252
|
-
type: 'object',
|
|
253
|
-
properties: {
|
|
254
|
-
content: { type: 'string', description: 'Complete updated task memory markdown.' },
|
|
255
|
-
},
|
|
256
|
-
required: ['content'],
|
|
257
|
-
},
|
|
258
|
-
execute: async (args) => updateTaskMemory(options.session.paths.taskMemoryPath, String(args.content ?? '')),
|
|
259
|
-
});
|
|
260
|
-
sdk.registerTool('consult_recipes', {
|
|
261
|
-
description: 'Search the recipe library for guidance on workflows, conventions, and how to approach a task in this workspace.',
|
|
262
|
-
parameters: {
|
|
263
|
-
type: 'object',
|
|
264
|
-
properties: {
|
|
265
|
-
query: { type: 'string', description: 'Natural-language description of the workflow or convention you need.' },
|
|
266
|
-
max_results: { type: 'number', description: 'Optional maximum number of matching recipes to return.' },
|
|
267
|
-
},
|
|
268
|
-
required: ['query'],
|
|
269
|
-
},
|
|
270
|
-
execute: async (args) => consultRecipes({
|
|
271
|
-
workspaceRoot: options.workspaceRoot,
|
|
272
|
-
query: String(args.query ?? ''),
|
|
273
|
-
maxResults: typeof args.max_results === 'number' ? args.max_results : undefined,
|
|
274
|
-
}),
|
|
275
|
-
});
|
|
276
|
-
}
|
|
277
|
-
export async function consultRecipes(options) {
|
|
278
|
-
const query = options.query.trim();
|
|
279
|
-
if (!query) {
|
|
280
|
-
throw new Error('query is required');
|
|
281
|
-
}
|
|
282
|
-
const [catalog, matches] = await Promise.all([
|
|
283
|
-
listRecipeCatalog(options.workspaceRoot),
|
|
284
|
-
searchRecipeCatalog(options.workspaceRoot, query, { maxResults: options.maxResults ?? 3 }),
|
|
285
|
-
]);
|
|
286
|
-
return {
|
|
287
|
-
success: true,
|
|
288
|
-
query,
|
|
289
|
-
total_recipes: catalog.length,
|
|
290
|
-
matches: matches.map((recipe) => ({
|
|
291
|
-
slug: recipe.slug,
|
|
292
|
-
name: recipe.name,
|
|
293
|
-
description: recipe.description,
|
|
294
|
-
tags: recipe.tags,
|
|
295
|
-
when_to_use: recipe.whenToUse,
|
|
296
|
-
when_not_to_use: recipe.whenNotToUse,
|
|
297
|
-
globs: recipe.globs,
|
|
298
|
-
priority: recipe.priority,
|
|
299
|
-
matched_on: recipe.matchedOn,
|
|
300
|
-
score: recipe.score,
|
|
301
|
-
source: recipe.source,
|
|
302
|
-
source_path: recipe.sourcePath,
|
|
303
|
-
content: recipe.content,
|
|
304
|
-
})),
|
|
305
|
-
};
|
|
306
|
-
}
|
|
307
|
-
export async function createLocalSkill(options) {
|
|
308
|
-
if (!options.spec.trim()) {
|
|
309
|
-
throw new Error('spec is required');
|
|
310
|
-
}
|
|
311
|
-
const slug = deriveSkillSlugFromMarkdown(options.spec, `skill-${Date.now().toString(36)}`);
|
|
312
|
-
const specDir = path.join(getSessionPaths(options.workspaceRoot, options.sessionId).dir, 'specs');
|
|
313
|
-
const specPath = path.join(specDir, `${slug}.md`);
|
|
314
|
-
await fs.mkdir(specDir, { recursive: true });
|
|
315
|
-
await fs.writeFile(specPath, options.spec, 'utf8');
|
|
316
|
-
const result = await compileWithSkillCreator(options.spec, {
|
|
317
|
-
sourcePath: specPath,
|
|
318
|
-
outputDir: getToolsDir(options.workspaceRoot),
|
|
319
|
-
baseName: slug,
|
|
320
|
-
workspaceRoot: options.workspaceRoot,
|
|
321
|
-
workspacePath: options.workspacePath,
|
|
322
|
-
config: options.config,
|
|
323
|
-
compileSelection: options.compileSelection,
|
|
324
|
-
runSelection: options.runSelection,
|
|
325
|
-
sandbox: options.sandbox,
|
|
326
|
-
verbose: options.verbose,
|
|
327
|
-
signal: options.signal,
|
|
328
|
-
onUserInput: options.onUserInput,
|
|
329
|
-
onEvent: (event) => options.onEvent?.({
|
|
330
|
-
scope: 'child',
|
|
331
|
-
childSlug: 'skill-creator',
|
|
332
|
-
modelId: options.compileSelection.id,
|
|
333
|
-
event,
|
|
334
|
-
}),
|
|
335
|
-
});
|
|
336
|
-
await mergeSessionUsage(options.workspaceRoot, options.sessionId, result.usageByModel);
|
|
337
|
-
const publishedSlug = path.basename(result.outputPath, path.extname(result.outputPath)) || slug;
|
|
338
|
-
return {
|
|
339
|
-
success: true,
|
|
340
|
-
slug: publishedSlug,
|
|
341
|
-
output_path: result.outputPath,
|
|
342
|
-
description: result.meta.description,
|
|
343
|
-
tools: result.tools,
|
|
344
|
-
};
|
|
345
|
-
}
|
|
346
|
-
async function updateTaskMemory(taskMemoryPath, content) {
|
|
347
|
-
await fs.writeFile(taskMemoryPath, content, 'utf8');
|
|
348
|
-
return {
|
|
349
|
-
success: true,
|
|
350
|
-
path: taskMemoryPath,
|
|
351
|
-
bytes: content.length,
|
|
352
|
-
};
|
|
353
|
-
}
|
|
354
|
-
async function buildConductorSystemPrompt(options) {
|
|
355
|
-
const template = await readSystemPromptAsset('conductor', { workspaceRoot: options.workspaceRoot });
|
|
356
|
-
const commands = await listCommands(options.workspaceRoot, { detailed: false });
|
|
357
|
-
const recipes = await listRecipeCatalog(options.workspaceRoot);
|
|
358
|
-
const catalog = commands.length > 0
|
|
359
|
-
? commands.map((command) => `- ${command.name}: ${command.description}`).join('\n')
|
|
360
|
-
: '- No compiled local skills are available yet.';
|
|
361
|
-
const recipeCatalog = recipes.length > 0
|
|
362
|
-
? recipes.map((recipe) => `- ${recipe.slug}: ${recipe.description}`).join('\n')
|
|
363
|
-
: '- No recipes are available yet.';
|
|
364
|
-
const assistantMemory = options.session.assistantMemory.trim()
|
|
365
|
-
|| 'No optional session context is recorded in assistant-memory.md for this session.';
|
|
366
|
-
const taskMemory = options.session.taskMemory.trim() || 'No task memory recorded yet.';
|
|
367
|
-
const localContext = [
|
|
368
|
-
'## Local CLI Runtime',
|
|
369
|
-
`- Workspace root: ${options.workspaceRoot}`,
|
|
370
|
-
`- Working directory for tools: ${options.workspacePath}`,
|
|
371
|
-
`- Skill catalog: ${getToolsDir(options.workspaceRoot)}`,
|
|
372
|
-
`- Recipe library: ${getWorkspaceRecipeAssetsDir(options.workspaceRoot)} plus packaged defaults`,
|
|
373
|
-
`- Docs directory: ${getDocsDir(options.workspaceRoot)}`,
|
|
374
|
-
`- TUI guide: ${path.join(getDocsDir(options.workspaceRoot), 'TUI.md')}`,
|
|
375
|
-
`- Session directory: ${options.session.paths.dir}`,
|
|
376
|
-
`- Session execution log: ${options.session.paths.executionLogPath}`,
|
|
377
|
-
`- Gateway model: ${options.gatewayModelId}`,
|
|
378
|
-
`- Run model: ${options.runModelId}`,
|
|
379
|
-
`- Compile model: ${options.compileModelId}`,
|
|
380
|
-
'- There is exactly one conductor in the CLI runtime. Do not invent hidden workers or extra orchestration layers.',
|
|
381
|
-
'',
|
|
382
|
-
'## Local Skill Catalog',
|
|
383
|
-
catalog,
|
|
384
|
-
'',
|
|
385
|
-
'## Recipe Library',
|
|
386
|
-
recipeCatalog,
|
|
387
|
-
'',
|
|
388
|
-
'## Optional Session Context (assistant-memory.md)',
|
|
389
|
-
assistantMemory,
|
|
390
|
-
'',
|
|
391
|
-
'## Task Memory',
|
|
392
|
-
taskMemory,
|
|
393
|
-
].join('\n');
|
|
394
|
-
return `${template
|
|
395
|
-
.replace('{ASSISTANT_NAME}', 'DeepClause')}\n\n${localContext}`;
|
|
396
|
-
}
|
|
397
|
-
async function loadOrCreateSession(workspaceRoot, sessionId, sessionTitle) {
|
|
398
|
-
if (!sessionId) {
|
|
399
|
-
const created = await createConductorSession(workspaceRoot, sessionTitle);
|
|
400
|
-
return loadSession(workspaceRoot, created.id);
|
|
401
|
-
}
|
|
402
|
-
return loadSession(workspaceRoot, sessionId);
|
|
403
|
-
}
|
|
404
|
-
async function loadSession(workspaceRoot, sessionId) {
|
|
405
|
-
const paths = getSessionPaths(workspaceRoot, sessionId);
|
|
406
|
-
const metadata = await readRequiredSessionMetadata(paths.dir);
|
|
407
|
-
const messages = await readSessionMessages(paths.messagesPath);
|
|
408
|
-
const assistantMemory = await readOptionalText(paths.assistantMemoryPath);
|
|
409
|
-
const taskMemory = await readOptionalText(paths.taskMemoryPath);
|
|
410
|
-
return {
|
|
411
|
-
metadata,
|
|
412
|
-
paths,
|
|
413
|
-
messages: messages.map((message) => ({ role: message.role, content: message.content })),
|
|
414
|
-
assistantMemory,
|
|
415
|
-
taskMemory,
|
|
416
|
-
};
|
|
417
|
-
}
|
|
418
|
-
function getSessionsDir(workspaceRoot) {
|
|
419
|
-
return path.join(getConfigDir(workspaceRoot), 'sessions');
|
|
420
|
-
}
|
|
421
|
-
function getSessionPaths(workspaceRoot, sessionId) {
|
|
422
|
-
const dir = path.join(getSessionsDir(workspaceRoot), sessionId);
|
|
423
|
-
return {
|
|
424
|
-
dir,
|
|
425
|
-
metadataPath: path.join(dir, 'session.json'),
|
|
426
|
-
messagesPath: path.join(dir, 'messages.jsonl'),
|
|
427
|
-
assistantMemoryPath: path.join(dir, 'assistant-memory.md'),
|
|
428
|
-
taskMemoryPath: path.join(dir, 'task-memory.md'),
|
|
429
|
-
usagePath: path.join(dir, 'usage.json'),
|
|
430
|
-
executionLogPath: path.join(dir, 'execution-log.jsonl'),
|
|
431
|
-
};
|
|
432
|
-
}
|
|
433
|
-
export function createSessionExecutionLogWriter(options) {
|
|
434
|
-
const logPath = getSessionPaths(options.workspaceRoot, options.sessionId).executionLogPath;
|
|
435
|
-
const executionId = randomUUID();
|
|
436
|
-
let writeChain = Promise.resolve();
|
|
437
|
-
let writeError = null;
|
|
438
|
-
const enqueue = (record) => {
|
|
439
|
-
writeChain = writeChain.then(async () => {
|
|
440
|
-
if (writeError) {
|
|
441
|
-
return;
|
|
442
|
-
}
|
|
443
|
-
try {
|
|
444
|
-
await fs.appendFile(logPath, JSON.stringify(record) + '\n', 'utf8');
|
|
445
|
-
}
|
|
446
|
-
catch (error) {
|
|
447
|
-
writeError = error;
|
|
448
|
-
}
|
|
449
|
-
});
|
|
450
|
-
};
|
|
451
|
-
enqueue({
|
|
452
|
-
timestamp: new Date().toISOString(),
|
|
453
|
-
sessionId: options.sessionId,
|
|
454
|
-
executionId,
|
|
455
|
-
entryType: 'execution_started',
|
|
456
|
-
executionKind: options.executionKind,
|
|
457
|
-
inputText: options.inputText,
|
|
458
|
-
skillName: options.skillName,
|
|
459
|
-
args: options.args,
|
|
460
|
-
modelId: options.modelId,
|
|
461
|
-
});
|
|
462
|
-
return {
|
|
463
|
-
executionId,
|
|
464
|
-
logPath,
|
|
465
|
-
recordEvent: (event) => enqueue({
|
|
466
|
-
timestamp: new Date().toISOString(),
|
|
467
|
-
sessionId: options.sessionId,
|
|
468
|
-
executionId,
|
|
469
|
-
entryType: 'event',
|
|
470
|
-
executionKind: options.executionKind,
|
|
471
|
-
scope: event.scope,
|
|
472
|
-
childSlug: event.childSlug,
|
|
473
|
-
modelId: event.modelId,
|
|
474
|
-
event: event.event,
|
|
475
|
-
}),
|
|
476
|
-
finish: async (summary) => {
|
|
477
|
-
enqueue({
|
|
478
|
-
timestamp: new Date().toISOString(),
|
|
479
|
-
sessionId: options.sessionId,
|
|
480
|
-
executionId,
|
|
481
|
-
entryType: 'execution_finished',
|
|
482
|
-
executionKind: options.executionKind,
|
|
483
|
-
status: summary.status,
|
|
484
|
-
answer: summary.answer,
|
|
485
|
-
error: summary.error,
|
|
486
|
-
outputCount: summary.outputCount,
|
|
487
|
-
usageByModel: summary.usageByModel,
|
|
488
|
-
});
|
|
489
|
-
await writeChain;
|
|
490
|
-
if (writeError) {
|
|
491
|
-
throw writeError;
|
|
492
|
-
}
|
|
493
|
-
},
|
|
494
|
-
flush: async () => {
|
|
495
|
-
await writeChain;
|
|
496
|
-
if (writeError) {
|
|
497
|
-
throw writeError;
|
|
498
|
-
}
|
|
499
|
-
},
|
|
500
|
-
};
|
|
501
|
-
}
|
|
502
|
-
async function readSessionMetadata(sessionDir) {
|
|
503
|
-
try {
|
|
504
|
-
const content = await fs.readFile(path.join(sessionDir, 'session.json'), 'utf8');
|
|
505
|
-
return JSON.parse(content);
|
|
506
|
-
}
|
|
507
|
-
catch {
|
|
508
|
-
return null;
|
|
509
|
-
}
|
|
510
|
-
}
|
|
511
|
-
async function readRequiredSessionMetadata(sessionDir) {
|
|
512
|
-
const metadata = await readSessionMetadata(sessionDir);
|
|
513
|
-
if (!metadata) {
|
|
514
|
-
throw new Error(`Unknown conductor session: ${path.basename(sessionDir)}`);
|
|
515
|
-
}
|
|
516
|
-
return metadata;
|
|
517
|
-
}
|
|
518
|
-
async function readSessionMessages(messagesPath) {
|
|
519
|
-
const content = await readOptionalText(messagesPath);
|
|
520
|
-
if (!content.trim()) {
|
|
521
|
-
return [];
|
|
522
|
-
}
|
|
523
|
-
return content
|
|
524
|
-
.split('\n')
|
|
525
|
-
.map((line) => line.trim())
|
|
526
|
-
.filter(Boolean)
|
|
527
|
-
.map((line) => JSON.parse(line))
|
|
528
|
-
.filter((message) => message.role === 'user' || message.role === 'assistant');
|
|
529
|
-
}
|
|
530
|
-
async function rewriteSessionMessages(messagesPath, messages) {
|
|
531
|
-
const content = messages.map((message) => JSON.stringify(message)).join('\n');
|
|
532
|
-
await fs.writeFile(messagesPath, content ? `${content}\n` : '', 'utf8');
|
|
533
|
-
}
|
|
534
|
-
async function readSessionUsage(usagePath) {
|
|
535
|
-
const content = await readOptionalText(usagePath);
|
|
536
|
-
if (!content.trim()) {
|
|
537
|
-
return {};
|
|
538
|
-
}
|
|
539
|
-
try {
|
|
540
|
-
const parsed = JSON.parse(content);
|
|
541
|
-
return parsed && typeof parsed === 'object' ? parsed : {};
|
|
542
|
-
}
|
|
543
|
-
catch {
|
|
544
|
-
return {};
|
|
545
|
-
}
|
|
546
|
-
}
|
|
547
|
-
async function appendSessionMessage(messagesPath, message) {
|
|
548
|
-
await fs.appendFile(messagesPath, JSON.stringify(message) + '\n', 'utf8');
|
|
549
|
-
}
|
|
550
|
-
function normalizeSessionCompactionMessages(messages) {
|
|
551
|
-
const timestamp = new Date().toISOString();
|
|
552
|
-
const normalized = [];
|
|
553
|
-
for (const message of messages) {
|
|
554
|
-
if ((message.role !== 'user' && message.role !== 'assistant') || typeof message.content !== 'string') {
|
|
555
|
-
return null;
|
|
556
|
-
}
|
|
557
|
-
normalized.push({
|
|
558
|
-
role: message.role,
|
|
559
|
-
content: message.content,
|
|
560
|
-
timestamp,
|
|
561
|
-
});
|
|
562
|
-
}
|
|
563
|
-
return normalized;
|
|
564
|
-
}
|
|
565
|
-
async function runSessionCompactorBinding(options) {
|
|
566
|
-
const binding = options.request.binding;
|
|
567
|
-
if (binding.compactor.inheritTools) {
|
|
568
|
-
return { error: 'Session compactors cannot inherit tools' };
|
|
569
|
-
}
|
|
570
|
-
const resolvedModel = resolveCompactorModelConfig({
|
|
571
|
-
binding,
|
|
572
|
-
selection: options.selection,
|
|
573
|
-
providerConfigs: options.config.providers,
|
|
574
|
-
});
|
|
575
|
-
const sdk = await createDeepClause({
|
|
576
|
-
model: resolvedModel.model,
|
|
577
|
-
provider: resolvedModel.provider,
|
|
578
|
-
apiKey: resolvedModel.apiKey,
|
|
579
|
-
baseUrl: resolvedModel.baseUrl,
|
|
580
|
-
temperature: resolvedModel.temperature,
|
|
581
|
-
debug: options.verbose,
|
|
582
|
-
maxTokens: resolvedModel.maxOutputTokens ?? 65536,
|
|
583
|
-
compaction: { enabled: false },
|
|
584
|
-
});
|
|
585
|
-
try {
|
|
586
|
-
let code = binding.compactor.source;
|
|
587
|
-
if (binding.compactor.sourceType !== 'inline') {
|
|
588
|
-
try {
|
|
589
|
-
code = await fs.readFile(binding.compactor.source, 'utf8');
|
|
590
|
-
}
|
|
591
|
-
catch (error) {
|
|
592
|
-
if (binding.compactor.sourceType === 'file') {
|
|
593
|
-
throw error;
|
|
594
|
-
}
|
|
595
|
-
}
|
|
596
|
-
}
|
|
597
|
-
let answer = '';
|
|
598
|
-
let error = '';
|
|
599
|
-
const usageByModel = {};
|
|
600
|
-
for await (const event of sdk.runDML(code, {
|
|
601
|
-
workspacePath: options.workspacePath,
|
|
602
|
-
gasLimit: binding.compactor.gasLimit,
|
|
603
|
-
params: options.request.params,
|
|
604
|
-
initialMessages: options.request.messages,
|
|
605
|
-
signal: options.signal,
|
|
606
|
-
onUserInput: async (prompt) => {
|
|
607
|
-
throw new Error(`Compactor requested unexpected input: ${prompt}`);
|
|
608
|
-
},
|
|
609
|
-
compaction: { enabled: false },
|
|
610
|
-
})) {
|
|
611
|
-
if (event.type === 'answer' && event.content) {
|
|
612
|
-
answer = event.content;
|
|
613
|
-
}
|
|
614
|
-
else if (event.type === 'error' && event.content) {
|
|
615
|
-
error = event.content;
|
|
616
|
-
}
|
|
617
|
-
else if (event.type === 'usage' && event.usage) {
|
|
618
|
-
recordTokenUsage(usageByModel, resolvedModel.modelId, event.usage);
|
|
619
|
-
}
|
|
620
|
-
}
|
|
621
|
-
return {
|
|
622
|
-
answer,
|
|
623
|
-
error: error || undefined,
|
|
624
|
-
usageByModel: Object.keys(usageByModel).length > 0 ? usageByModel : undefined,
|
|
625
|
-
};
|
|
626
|
-
}
|
|
627
|
-
finally {
|
|
628
|
-
await sdk.dispose();
|
|
629
|
-
}
|
|
630
|
-
}
|
|
631
|
-
async function maybeCompactSessionMessages(options) {
|
|
632
|
-
const resolvedConfig = resolveCompactionConfig(options.config, options.workspaceRoot);
|
|
633
|
-
const resolved = resolveCompactionOptions(resolvedConfig, undefined);
|
|
634
|
-
const bindings = getCompactionBindings(resolved, 'session', 'before_user_message');
|
|
635
|
-
if (bindings.length === 0) {
|
|
636
|
-
return options.messages;
|
|
637
|
-
}
|
|
638
|
-
let messages = options.messages.map((message) => ({
|
|
639
|
-
role: message.role,
|
|
640
|
-
content: message.content,
|
|
641
|
-
}));
|
|
642
|
-
for (const binding of bindings) {
|
|
643
|
-
const priorMessages = messages;
|
|
644
|
-
const result = await executeCompactor({
|
|
645
|
-
binding,
|
|
646
|
-
messages: priorMessages,
|
|
647
|
-
emitEvent: options.onCompactionEvent,
|
|
648
|
-
execute: (request) => runSessionCompactorBinding({
|
|
649
|
-
request,
|
|
650
|
-
config: options.config,
|
|
651
|
-
selection: options.selection,
|
|
652
|
-
workspacePath: options.workspacePath,
|
|
653
|
-
signal: options.signal,
|
|
654
|
-
verbose: options.verbose,
|
|
655
|
-
}),
|
|
656
|
-
});
|
|
657
|
-
const normalized = normalizeSessionCompactionMessages(result.messages);
|
|
658
|
-
if (!normalized) {
|
|
659
|
-
options.onCompactionEvent?.({
|
|
660
|
-
...result.event,
|
|
661
|
-
content: `compact ${binding.scope}.${binding.trigger} failed ${result.event.beforeTokens ?? 0} -> ${result.event.afterTokens ?? 0} tokens: session compactors must return only user/assistant messages`,
|
|
662
|
-
compactionAction: 'failed',
|
|
663
|
-
compactionError: 'Session compactors must return only user/assistant messages',
|
|
664
|
-
});
|
|
665
|
-
continue;
|
|
666
|
-
}
|
|
667
|
-
options.onCompactionEvent?.(result.event);
|
|
668
|
-
if (result.usageByModel) {
|
|
669
|
-
for (const totals of Object.values(result.usageByModel)) {
|
|
670
|
-
options.onCompactionEvent?.({ type: 'usage', usage: {
|
|
671
|
-
inputTokens: totals.inputTokens,
|
|
672
|
-
outputTokens: totals.outputTokens,
|
|
673
|
-
totalTokens: totals.totalTokens,
|
|
674
|
-
cacheReadTokens: totals.cacheReadTokens || undefined,
|
|
675
|
-
cacheWriteTokens: totals.cacheWriteTokens || undefined,
|
|
676
|
-
reasoningTokens: totals.reasoningTokens || undefined,
|
|
677
|
-
} });
|
|
678
|
-
}
|
|
679
|
-
}
|
|
680
|
-
const beforeSerialized = JSON.stringify(priorMessages);
|
|
681
|
-
const afterSerialized = JSON.stringify(normalized.map(({ role, content }) => ({ role, content })));
|
|
682
|
-
if (beforeSerialized !== afterSerialized) {
|
|
683
|
-
await rewriteSessionMessages(options.messagesPath, normalized);
|
|
684
|
-
}
|
|
685
|
-
messages = normalized.map((message) => ({ role: message.role, content: message.content }));
|
|
686
|
-
}
|
|
687
|
-
return messages.map((message) => ({ role: message.role, content: message.content }));
|
|
688
|
-
}
|
|
689
|
-
export async function mergeSessionUsage(workspaceRoot, sessionId, delta) {
|
|
690
|
-
if (isTokenUsageEmpty(delta)) {
|
|
691
|
-
return;
|
|
692
|
-
}
|
|
693
|
-
const paths = getSessionPaths(workspaceRoot, sessionId);
|
|
694
|
-
const current = await readSessionUsage(paths.usagePath);
|
|
695
|
-
const merged = mergeTokenUsageMaps(current, delta);
|
|
696
|
-
await fs.writeFile(paths.usagePath, JSON.stringify(merged, null, 2) + '\n', 'utf8');
|
|
697
|
-
}
|
|
698
|
-
async function touchSession(workspaceRoot, sessionId) {
|
|
699
|
-
const paths = getSessionPaths(workspaceRoot, sessionId);
|
|
700
|
-
const metadata = await readRequiredSessionMetadata(paths.dir);
|
|
701
|
-
metadata.updatedAt = new Date().toISOString();
|
|
702
|
-
await fs.writeFile(paths.metadataPath, JSON.stringify(metadata, null, 2) + '\n', 'utf8');
|
|
703
|
-
}
|
|
704
|
-
async function maybeUpdateSessionTitle(workspaceRoot, metadata, userMessage) {
|
|
705
|
-
if (!metadata.title.startsWith(DEFAULT_SESSION_TITLE_PREFIX)) {
|
|
706
|
-
return;
|
|
707
|
-
}
|
|
708
|
-
const nextTitle = summarizeTitle(userMessage);
|
|
709
|
-
if (!nextTitle) {
|
|
710
|
-
return;
|
|
711
|
-
}
|
|
712
|
-
const paths = getSessionPaths(workspaceRoot, metadata.id);
|
|
713
|
-
metadata.title = nextTitle;
|
|
714
|
-
metadata.updatedAt = new Date().toISOString();
|
|
715
|
-
await fs.writeFile(paths.metadataPath, JSON.stringify(metadata, null, 2) + '\n', 'utf8');
|
|
716
|
-
}
|
|
717
|
-
function summarizeTitle(message) {
|
|
718
|
-
const normalized = message.replace(/\s+/g, ' ').trim();
|
|
719
|
-
if (!normalized) {
|
|
720
|
-
return '';
|
|
721
|
-
}
|
|
722
|
-
return normalized.slice(0, 60);
|
|
723
|
-
}
|
|
724
|
-
async function readOptionalText(filePath) {
|
|
725
|
-
try {
|
|
726
|
-
return await fs.readFile(filePath, 'utf8');
|
|
727
|
-
}
|
|
728
|
-
catch {
|
|
729
|
-
return '';
|
|
730
|
-
}
|
|
731
|
-
}
|
|
732
|
-
//# sourceMappingURL=conductor.js.map
|