thoth-agents 0.1.18 → 0.2.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/README.md +55 -12
- package/dist/agents/prompt-dialects.d.ts +9 -0
- package/dist/{chunk-6K3ZXIMC.js → chunk-3NOVCFN7.js} +88 -29
- package/dist/chunk-4WYCZ5Z7.js +698 -0
- package/dist/{chunk-SOT5ZY53.js → chunk-WH3F3GWE.js} +1498 -350
- package/dist/cli/claude-code-install.d.ts +53 -0
- package/dist/cli/claude-code-paths.d.ts +31 -0
- package/dist/cli/codex-install.d.ts +1 -5
- package/dist/cli/commands.d.ts +1 -1
- package/dist/cli/index.js +85 -27
- package/dist/cli/managed-state-io.d.ts +16 -0
- package/dist/cli/operations/claude-code.d.ts +21 -0
- package/dist/cli/tui/index.js +87 -9
- package/dist/cli/tui/operations.d.ts +2 -0
- package/dist/cli/types.d.ts +3 -3
- package/dist/config/index.d.ts +1 -1
- package/dist/config/schema.d.ts +11 -0
- package/dist/config/utils.d.ts +5 -0
- package/dist/harness/adapters/claude-code.d.ts +24 -0
- package/dist/harness/core/memory-governance.d.ts +39 -4
- package/dist/harness/core/package-version.d.ts +7 -0
- package/dist/harness/types.d.ts +1 -1
- package/dist/harness/writers/claude-code-plugin-package.d.ts +32 -0
- package/dist/harness/writers/claude-code-skill-layout.d.ts +16 -0
- package/dist/harness/writers/claude-code-subagent.d.ts +26 -0
- package/dist/harness/writers/fs-skill-collect.d.ts +7 -0
- package/dist/hooks/phase-reminder/index.d.ts +2 -0
- package/dist/hooks/thoth-mem/protocol.d.ts +2 -2
- package/dist/index.js +54 -512
- package/package.json +1 -1
- package/src/skills/_shared/persistence-contract.md +18 -14
- package/src/skills/_shared/thoth-mem-convention.md +18 -18
- package/src/skills/executing-plans/SKILL.md +6 -4
- package/src/skills/plan-reviewer/SKILL.md +4 -2
- package/src/skills/thoth-mem-agents/SKILL.md +3 -0
- package/thoth-agents.schema.json +16 -0
- package/dist/chunk-DYGVRAMS.js +0 -182
package/dist/index.js
CHANGED
|
@@ -1,492 +1,24 @@
|
|
|
1
1
|
import {
|
|
2
|
+
createAgents,
|
|
3
|
+
renderOpenCodeAgentConfigs,
|
|
2
4
|
spawn,
|
|
3
5
|
spawnSync
|
|
4
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-4WYCZ5Z7.js";
|
|
5
7
|
import {
|
|
6
|
-
DEFAULT_MODELS,
|
|
7
8
|
DEFAULT_THOTH_COMMAND,
|
|
8
|
-
OPENCODE_PROMPT_DIALECT,
|
|
9
9
|
POLL_INTERVAL_BACKGROUND_MS,
|
|
10
|
-
SUBAGENT_NAMES,
|
|
11
|
-
appendPromptSections,
|
|
12
|
-
composeAgentPrompt,
|
|
13
10
|
context7,
|
|
14
|
-
createOrchestratorPromptSections,
|
|
15
|
-
createReadOnlySpecialistPromptSections,
|
|
16
|
-
createWriteCapableSpecialistPromptSections,
|
|
17
|
-
detectModelFamily,
|
|
18
11
|
exa,
|
|
19
|
-
getAgentOverride,
|
|
20
|
-
getModelFamilyPromptSection,
|
|
21
12
|
getOpenCodeConfigPaths,
|
|
22
|
-
getStepBudgetPromptSection,
|
|
23
13
|
grep_app,
|
|
24
14
|
installCustomSkills,
|
|
25
|
-
loadAgentPrompt,
|
|
26
15
|
loadPluginConfig,
|
|
27
|
-
renderRolePrompt,
|
|
28
16
|
stripJsonComments
|
|
29
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-3NOVCFN7.js";
|
|
30
18
|
|
|
31
19
|
// src/index.ts
|
|
32
20
|
import path4 from "path";
|
|
33
21
|
|
|
34
|
-
// src/agents/deep.ts
|
|
35
|
-
var DEEP_PROMPT = renderRolePrompt(
|
|
36
|
-
createWriteCapableSpecialistPromptSections("deep"),
|
|
37
|
-
OPENCODE_PROMPT_DIALECT
|
|
38
|
-
);
|
|
39
|
-
function createDeepAgent(model, customPrompt, customAppendPrompt) {
|
|
40
|
-
const prompt = composeAgentPrompt({
|
|
41
|
-
basePrompt: DEEP_PROMPT,
|
|
42
|
-
customPrompt,
|
|
43
|
-
customAppendPrompt: appendPromptSections(
|
|
44
|
-
getModelFamilyPromptSection("deep", model),
|
|
45
|
-
customAppendPrompt
|
|
46
|
-
)
|
|
47
|
-
});
|
|
48
|
-
return {
|
|
49
|
-
name: "deep",
|
|
50
|
-
description: "Synchronous write-capable implementation agent optimized for thorough context analysis, edge cases, and correctness \u2014 not for bulk mechanical changes.",
|
|
51
|
-
config: {
|
|
52
|
-
model,
|
|
53
|
-
temperature: 0.1,
|
|
54
|
-
prompt,
|
|
55
|
-
color: "secondary"
|
|
56
|
-
// steps: 80,
|
|
57
|
-
}
|
|
58
|
-
};
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
// src/agents/designer.ts
|
|
62
|
-
var DESIGNER_PROMPT = renderRolePrompt(
|
|
63
|
-
createWriteCapableSpecialistPromptSections("designer"),
|
|
64
|
-
OPENCODE_PROMPT_DIALECT
|
|
65
|
-
);
|
|
66
|
-
function createDesignerAgent(model, customPrompt, customAppendPrompt) {
|
|
67
|
-
const prompt = composeAgentPrompt({
|
|
68
|
-
basePrompt: DESIGNER_PROMPT,
|
|
69
|
-
customPrompt,
|
|
70
|
-
customAppendPrompt: appendPromptSections(
|
|
71
|
-
getModelFamilyPromptSection("designer", model),
|
|
72
|
-
customAppendPrompt
|
|
73
|
-
)
|
|
74
|
-
});
|
|
75
|
-
return {
|
|
76
|
-
name: "designer",
|
|
77
|
-
description: "Synchronous write-capable UI/UX implementation agent with ownership of approach, execution, and visual verification.",
|
|
78
|
-
config: {
|
|
79
|
-
model,
|
|
80
|
-
temperature: 0.4,
|
|
81
|
-
prompt,
|
|
82
|
-
color: "accent"
|
|
83
|
-
// steps: 50,
|
|
84
|
-
}
|
|
85
|
-
};
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
// src/agents/explorer.ts
|
|
89
|
-
var EXPLORER_PROMPT = renderRolePrompt(
|
|
90
|
-
createReadOnlySpecialistPromptSections("explorer"),
|
|
91
|
-
OPENCODE_PROMPT_DIALECT
|
|
92
|
-
);
|
|
93
|
-
function createExplorerAgent(model, customPrompt, customAppendPrompt) {
|
|
94
|
-
const prompt = composeAgentPrompt({
|
|
95
|
-
basePrompt: EXPLORER_PROMPT,
|
|
96
|
-
customPrompt,
|
|
97
|
-
customAppendPrompt: appendPromptSections(
|
|
98
|
-
getModelFamilyPromptSection("explorer", model),
|
|
99
|
-
customAppendPrompt
|
|
100
|
-
)
|
|
101
|
-
});
|
|
102
|
-
return {
|
|
103
|
-
name: "explorer",
|
|
104
|
-
description: "Read-only local discovery agent for fast codebase search, references, and repository mapping.",
|
|
105
|
-
config: {
|
|
106
|
-
model,
|
|
107
|
-
temperature: 0.1,
|
|
108
|
-
prompt,
|
|
109
|
-
color: "info"
|
|
110
|
-
}
|
|
111
|
-
};
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
// src/agents/librarian.ts
|
|
115
|
-
var LIBRARIAN_PROMPT = renderRolePrompt(
|
|
116
|
-
createReadOnlySpecialistPromptSections("librarian"),
|
|
117
|
-
OPENCODE_PROMPT_DIALECT
|
|
118
|
-
);
|
|
119
|
-
function createLibrarianAgent(model, customPrompt, customAppendPrompt) {
|
|
120
|
-
const prompt = composeAgentPrompt({
|
|
121
|
-
basePrompt: LIBRARIAN_PROMPT,
|
|
122
|
-
customPrompt,
|
|
123
|
-
customAppendPrompt: appendPromptSections(
|
|
124
|
-
getModelFamilyPromptSection("librarian", model),
|
|
125
|
-
customAppendPrompt
|
|
126
|
-
)
|
|
127
|
-
});
|
|
128
|
-
return {
|
|
129
|
-
name: "librarian",
|
|
130
|
-
description: "Read-only research agent for official docs, public examples, and externally sourced implementation guidance.",
|
|
131
|
-
config: {
|
|
132
|
-
model,
|
|
133
|
-
temperature: 0.1,
|
|
134
|
-
prompt,
|
|
135
|
-
color: "info"
|
|
136
|
-
}
|
|
137
|
-
};
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
// src/agents/oracle.ts
|
|
141
|
-
var ORACLE_PROMPT = renderRolePrompt(
|
|
142
|
-
createReadOnlySpecialistPromptSections("oracle"),
|
|
143
|
-
OPENCODE_PROMPT_DIALECT
|
|
144
|
-
);
|
|
145
|
-
function createOracleAgent(model, customPrompt, customAppendPrompt) {
|
|
146
|
-
const prompt = composeAgentPrompt({
|
|
147
|
-
basePrompt: ORACLE_PROMPT,
|
|
148
|
-
customPrompt,
|
|
149
|
-
customAppendPrompt: appendPromptSections(
|
|
150
|
-
getModelFamilyPromptSection("oracle", model),
|
|
151
|
-
customAppendPrompt
|
|
152
|
-
)
|
|
153
|
-
});
|
|
154
|
-
return {
|
|
155
|
-
name: "oracle",
|
|
156
|
-
description: "Synchronous read-only strategic advisor for debugging, architecture, code review, and SDD plan review.",
|
|
157
|
-
config: {
|
|
158
|
-
model,
|
|
159
|
-
temperature: 0.1,
|
|
160
|
-
prompt,
|
|
161
|
-
color: "warning"
|
|
162
|
-
}
|
|
163
|
-
};
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
// src/agents/orchestrator.ts
|
|
167
|
-
var ORCHESTRATOR_PROMPT = renderRolePrompt(
|
|
168
|
-
createOrchestratorPromptSections(),
|
|
169
|
-
OPENCODE_PROMPT_DIALECT
|
|
170
|
-
);
|
|
171
|
-
function createOrchestratorAgent(model, customPrompt, customAppendPrompt) {
|
|
172
|
-
const prompt = composeAgentPrompt({
|
|
173
|
-
basePrompt: ORCHESTRATOR_PROMPT,
|
|
174
|
-
customPrompt,
|
|
175
|
-
customAppendPrompt: appendPromptSections(
|
|
176
|
-
getModelFamilyPromptSection("orchestrator", model),
|
|
177
|
-
customAppendPrompt
|
|
178
|
-
)
|
|
179
|
-
});
|
|
180
|
-
const definition = {
|
|
181
|
-
name: "orchestrator",
|
|
182
|
-
description: "Delegate-first coordinator for SDD workflow, specialist dispatch, and root-session memory ownership.",
|
|
183
|
-
config: {
|
|
184
|
-
temperature: 0.1,
|
|
185
|
-
prompt,
|
|
186
|
-
color: "primary"
|
|
187
|
-
// steps: 100,
|
|
188
|
-
}
|
|
189
|
-
};
|
|
190
|
-
if (Array.isArray(model)) {
|
|
191
|
-
definition._modelArray = model.map(
|
|
192
|
-
(entry) => typeof entry === "string" ? { id: entry } : entry
|
|
193
|
-
);
|
|
194
|
-
} else if (typeof model === "string" && model) {
|
|
195
|
-
definition.config.model = model;
|
|
196
|
-
}
|
|
197
|
-
return definition;
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
// src/agents/quick.ts
|
|
201
|
-
var QUICK_PROMPT = renderRolePrompt(
|
|
202
|
-
createWriteCapableSpecialistPromptSections("quick"),
|
|
203
|
-
OPENCODE_PROMPT_DIALECT
|
|
204
|
-
);
|
|
205
|
-
function createQuickAgent(model, customPrompt, customAppendPrompt) {
|
|
206
|
-
const prompt = composeAgentPrompt({
|
|
207
|
-
basePrompt: QUICK_PROMPT,
|
|
208
|
-
customPrompt,
|
|
209
|
-
customAppendPrompt: appendPromptSections(
|
|
210
|
-
getModelFamilyPromptSection("quick", model),
|
|
211
|
-
customAppendPrompt
|
|
212
|
-
)
|
|
213
|
-
});
|
|
214
|
-
return {
|
|
215
|
-
name: "quick",
|
|
216
|
-
description: "Synchronous write-capable implementation agent optimized for fast, mechanical, well-bounded changes \u2014 including uniform patterns across multiple files.",
|
|
217
|
-
config: {
|
|
218
|
-
model,
|
|
219
|
-
temperature: 0.2,
|
|
220
|
-
prompt,
|
|
221
|
-
color: "success"
|
|
222
|
-
// steps: 30,
|
|
223
|
-
}
|
|
224
|
-
};
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
// src/agents/index.ts
|
|
228
|
-
var GEMINI_DEFAULT_STEPS = {
|
|
229
|
-
explorer: 120,
|
|
230
|
-
librarian: 80,
|
|
231
|
-
oracle: 80,
|
|
232
|
-
designer: 80,
|
|
233
|
-
quick: 40,
|
|
234
|
-
deep: 120
|
|
235
|
-
};
|
|
236
|
-
var BUILTIN_PERMISSION_PRESETS = {
|
|
237
|
-
orchestrator: {
|
|
238
|
-
read: "allow",
|
|
239
|
-
edit: "allow",
|
|
240
|
-
write: "allow",
|
|
241
|
-
glob: "allow",
|
|
242
|
-
grep: "allow",
|
|
243
|
-
list: "allow",
|
|
244
|
-
bash: "allow",
|
|
245
|
-
codesearch: "allow",
|
|
246
|
-
lsp: "allow",
|
|
247
|
-
skill: "allow",
|
|
248
|
-
question: "allow",
|
|
249
|
-
webfetch: "allow",
|
|
250
|
-
exa: "allow",
|
|
251
|
-
todowrite: "allow",
|
|
252
|
-
task: "allow",
|
|
253
|
-
external_directory: "allow"
|
|
254
|
-
},
|
|
255
|
-
explorer: {
|
|
256
|
-
read: "allow",
|
|
257
|
-
glob: "allow",
|
|
258
|
-
grep: "allow",
|
|
259
|
-
list: "allow",
|
|
260
|
-
codesearch: "allow",
|
|
261
|
-
lsp: "allow",
|
|
262
|
-
external_directory: "allow",
|
|
263
|
-
bash: "allow",
|
|
264
|
-
question: "allow",
|
|
265
|
-
skill: "allow",
|
|
266
|
-
edit: "deny",
|
|
267
|
-
todowrite: "deny",
|
|
268
|
-
task: "deny"
|
|
269
|
-
},
|
|
270
|
-
librarian: {
|
|
271
|
-
read: "allow",
|
|
272
|
-
glob: "allow",
|
|
273
|
-
grep: "allow",
|
|
274
|
-
external_directory: "allow",
|
|
275
|
-
bash: "allow",
|
|
276
|
-
webfetch: "allow",
|
|
277
|
-
exa: "allow",
|
|
278
|
-
codesearch: "allow",
|
|
279
|
-
question: "allow",
|
|
280
|
-
skill: "allow",
|
|
281
|
-
edit: "deny",
|
|
282
|
-
todowrite: "deny",
|
|
283
|
-
task: "deny"
|
|
284
|
-
},
|
|
285
|
-
oracle: {
|
|
286
|
-
read: "allow",
|
|
287
|
-
glob: "allow",
|
|
288
|
-
grep: "allow",
|
|
289
|
-
list: "allow",
|
|
290
|
-
lsp: "allow",
|
|
291
|
-
codesearch: "allow",
|
|
292
|
-
webfetch: "allow",
|
|
293
|
-
exa: "allow",
|
|
294
|
-
external_directory: "allow",
|
|
295
|
-
bash: "allow",
|
|
296
|
-
question: "allow",
|
|
297
|
-
skill: "allow",
|
|
298
|
-
edit: "deny",
|
|
299
|
-
todowrite: "deny",
|
|
300
|
-
task: "deny"
|
|
301
|
-
},
|
|
302
|
-
designer: {
|
|
303
|
-
read: "allow",
|
|
304
|
-
edit: "allow",
|
|
305
|
-
glob: "allow",
|
|
306
|
-
grep: "allow",
|
|
307
|
-
list: "allow",
|
|
308
|
-
bash: "allow",
|
|
309
|
-
codesearch: "allow",
|
|
310
|
-
lsp: "allow",
|
|
311
|
-
skill: "allow",
|
|
312
|
-
question: "allow",
|
|
313
|
-
todowrite: "deny",
|
|
314
|
-
task: "deny",
|
|
315
|
-
external_directory: {
|
|
316
|
-
"~/.config/opencode/skills/**": "allow"
|
|
317
|
-
}
|
|
318
|
-
},
|
|
319
|
-
quick: {
|
|
320
|
-
read: "allow",
|
|
321
|
-
edit: "allow",
|
|
322
|
-
glob: "allow",
|
|
323
|
-
grep: "allow",
|
|
324
|
-
list: "allow",
|
|
325
|
-
bash: "allow",
|
|
326
|
-
question: "allow",
|
|
327
|
-
codesearch: "allow",
|
|
328
|
-
lsp: "allow",
|
|
329
|
-
skill: "allow",
|
|
330
|
-
todowrite: "deny",
|
|
331
|
-
task: "deny",
|
|
332
|
-
external_directory: {
|
|
333
|
-
"~/.config/opencode/skills/**": "allow"
|
|
334
|
-
}
|
|
335
|
-
},
|
|
336
|
-
deep: {
|
|
337
|
-
read: "allow",
|
|
338
|
-
edit: "allow",
|
|
339
|
-
glob: "allow",
|
|
340
|
-
grep: "allow",
|
|
341
|
-
list: "allow",
|
|
342
|
-
bash: "allow",
|
|
343
|
-
codesearch: "allow",
|
|
344
|
-
lsp: "allow",
|
|
345
|
-
skill: "allow",
|
|
346
|
-
question: "allow",
|
|
347
|
-
webfetch: "allow",
|
|
348
|
-
exa: "allow",
|
|
349
|
-
todowrite: "deny",
|
|
350
|
-
task: "deny",
|
|
351
|
-
external_directory: {
|
|
352
|
-
"~/.config/opencode/skills/**": "allow"
|
|
353
|
-
}
|
|
354
|
-
}
|
|
355
|
-
};
|
|
356
|
-
function normalizeModelArray(model) {
|
|
357
|
-
return model.map(
|
|
358
|
-
(entry) => typeof entry === "string" ? { id: entry } : entry
|
|
359
|
-
);
|
|
360
|
-
}
|
|
361
|
-
function applyOverrides(agent, override) {
|
|
362
|
-
if (override.model) {
|
|
363
|
-
if (Array.isArray(override.model)) {
|
|
364
|
-
agent._modelArray = normalizeModelArray(override.model);
|
|
365
|
-
agent.config.model = void 0;
|
|
366
|
-
} else {
|
|
367
|
-
agent.config.model = override.model;
|
|
368
|
-
}
|
|
369
|
-
}
|
|
370
|
-
if (override.variant) {
|
|
371
|
-
agent.config.variant = override.variant;
|
|
372
|
-
}
|
|
373
|
-
if (override.temperature !== void 0) {
|
|
374
|
-
agent.config.temperature = override.temperature;
|
|
375
|
-
}
|
|
376
|
-
if (override.steps !== void 0) {
|
|
377
|
-
agent.config.steps = override.steps;
|
|
378
|
-
}
|
|
379
|
-
}
|
|
380
|
-
function applyStepBudgetPrompt(agent) {
|
|
381
|
-
const stepBudgetPrompt = getStepBudgetPromptSection(agent.config.steps);
|
|
382
|
-
if (!stepBudgetPrompt) {
|
|
383
|
-
return;
|
|
384
|
-
}
|
|
385
|
-
agent.config.prompt = appendPromptSections(
|
|
386
|
-
agent.config.prompt,
|
|
387
|
-
stepBudgetPrompt
|
|
388
|
-
);
|
|
389
|
-
}
|
|
390
|
-
function applyGeminiDefaultSteps(agent) {
|
|
391
|
-
if (!isSubagent(agent.name) || agent.config.steps !== void 0) {
|
|
392
|
-
return;
|
|
393
|
-
}
|
|
394
|
-
if (detectModelFamily(agent._modelArray ?? agent.config.model) !== "gemini") {
|
|
395
|
-
return;
|
|
396
|
-
}
|
|
397
|
-
agent.config.steps = GEMINI_DEFAULT_STEPS[agent.name];
|
|
398
|
-
}
|
|
399
|
-
function clonePermissionConfig(permission) {
|
|
400
|
-
if (typeof permission === "string") {
|
|
401
|
-
return permission;
|
|
402
|
-
}
|
|
403
|
-
return Object.fromEntries(
|
|
404
|
-
Object.entries(permission).map(([key, value]) => [
|
|
405
|
-
key,
|
|
406
|
-
value && typeof value === "object" && !Array.isArray(value) ? { ...value } : value
|
|
407
|
-
])
|
|
408
|
-
);
|
|
409
|
-
}
|
|
410
|
-
function getBuiltinPermissionPreset(name) {
|
|
411
|
-
return clonePermissionConfig(BUILTIN_PERMISSION_PRESETS[name]);
|
|
412
|
-
}
|
|
413
|
-
function getExplicitPermissionOverride(override) {
|
|
414
|
-
return override?.permission;
|
|
415
|
-
}
|
|
416
|
-
function getPrimaryModelForPrompt(model) {
|
|
417
|
-
if (Array.isArray(model)) {
|
|
418
|
-
const first = model[0];
|
|
419
|
-
return typeof first === "string" ? first : first?.id;
|
|
420
|
-
}
|
|
421
|
-
return model;
|
|
422
|
-
}
|
|
423
|
-
function isSubagent(name) {
|
|
424
|
-
return SUBAGENT_NAMES.includes(name);
|
|
425
|
-
}
|
|
426
|
-
var SUBAGENT_FACTORIES = {
|
|
427
|
-
explorer: createExplorerAgent,
|
|
428
|
-
librarian: createLibrarianAgent,
|
|
429
|
-
oracle: createOracleAgent,
|
|
430
|
-
designer: createDesignerAgent,
|
|
431
|
-
quick: createQuickAgent,
|
|
432
|
-
deep: createDeepAgent
|
|
433
|
-
};
|
|
434
|
-
function createAgents(config) {
|
|
435
|
-
const protoSubAgents = Object.entries(SUBAGENT_FACTORIES).map(([name, factory]) => {
|
|
436
|
-
const override = getAgentOverride(config, name);
|
|
437
|
-
const prompts = loadAgentPrompt(name, config?.preset);
|
|
438
|
-
const model = getPrimaryModelForPrompt(override?.model) ?? DEFAULT_MODELS[name];
|
|
439
|
-
return factory(model, prompts.prompt, prompts.appendPrompt);
|
|
440
|
-
});
|
|
441
|
-
const allSubAgents = protoSubAgents.map((agent) => {
|
|
442
|
-
const override = getAgentOverride(config, agent.name);
|
|
443
|
-
if (override) {
|
|
444
|
-
applyOverrides(agent, override);
|
|
445
|
-
}
|
|
446
|
-
applyGeminiDefaultSteps(agent);
|
|
447
|
-
applyStepBudgetPrompt(agent);
|
|
448
|
-
return agent;
|
|
449
|
-
});
|
|
450
|
-
const orchestratorOverride = getAgentOverride(config, "orchestrator");
|
|
451
|
-
const orchestratorPrompts = loadAgentPrompt("orchestrator", config?.preset);
|
|
452
|
-
const orchestrator = createOrchestratorAgent(
|
|
453
|
-
orchestratorOverride?.model ?? DEFAULT_MODELS.orchestrator,
|
|
454
|
-
orchestratorPrompts.prompt,
|
|
455
|
-
orchestratorPrompts.appendPrompt
|
|
456
|
-
);
|
|
457
|
-
if (orchestratorOverride) {
|
|
458
|
-
applyOverrides(orchestrator, orchestratorOverride);
|
|
459
|
-
}
|
|
460
|
-
applyStepBudgetPrompt(orchestrator);
|
|
461
|
-
return [orchestrator, ...allSubAgents];
|
|
462
|
-
}
|
|
463
|
-
function getAgentConfigs(config) {
|
|
464
|
-
const agents = createAgents(config);
|
|
465
|
-
return Object.fromEntries(
|
|
466
|
-
agents.map((agent) => {
|
|
467
|
-
const override = getAgentOverride(config, agent.name);
|
|
468
|
-
const sdkConfig = {
|
|
469
|
-
...agent.config,
|
|
470
|
-
description: agent.description
|
|
471
|
-
};
|
|
472
|
-
const builtinPermission = isSubagent(agent.name) ? getBuiltinPermissionPreset(agent.name) : agent.name === "orchestrator" ? getBuiltinPermissionPreset("orchestrator") : void 0;
|
|
473
|
-
const explicitPermissionOverride = getExplicitPermissionOverride(override);
|
|
474
|
-
sdkConfig.permission = explicitPermissionOverride ?? agent.config.permission ?? builtinPermission;
|
|
475
|
-
if (isSubagent(agent.name)) {
|
|
476
|
-
sdkConfig.mode = "subagent";
|
|
477
|
-
} else if (agent.name === "orchestrator") {
|
|
478
|
-
sdkConfig.mode = "primary";
|
|
479
|
-
}
|
|
480
|
-
return [agent.name, sdkConfig];
|
|
481
|
-
})
|
|
482
|
-
);
|
|
483
|
-
}
|
|
484
|
-
|
|
485
|
-
// src/harness/adapters/opencode.ts
|
|
486
|
-
function renderOpenCodeAgentConfigs(config) {
|
|
487
|
-
return getAgentConfigs(config);
|
|
488
|
-
}
|
|
489
|
-
|
|
490
22
|
// src/utils/logger.ts
|
|
491
23
|
import { createRequire } from "module";
|
|
492
24
|
var require2 = createRequire(import.meta.url);
|
|
@@ -1744,6 +1276,14 @@ Understand \u2192 split discovery into surgical probes with explorer/librarian \
|
|
|
1744
1276
|
If delegating, write sub-agent prompts in English and launch the specialist in the same turn you mention it. If multiple delegations are independent, emit all tool calls in a single response.
|
|
1745
1277
|
Before write-capable dispatch, give concrete scope, anchors, steps, non-goals, and verification.
|
|
1746
1278
|
In SDD, after oracle returns [OKAY], give a deep approved-plan overview, then ask the user before implementation.</reminder>`;
|
|
1279
|
+
var PHASE_REMINDER_SEPARATOR = "\n\n---\n\n";
|
|
1280
|
+
function stripPhaseReminder(text) {
|
|
1281
|
+
if (!text) {
|
|
1282
|
+
return "";
|
|
1283
|
+
}
|
|
1284
|
+
const prefix = `${PHASE_REMINDER}${PHASE_REMINDER_SEPARATOR}`;
|
|
1285
|
+
return text.startsWith(prefix) ? text.slice(prefix.length) : text;
|
|
1286
|
+
}
|
|
1747
1287
|
function createPhaseReminderHook() {
|
|
1748
1288
|
return {
|
|
1749
1289
|
"experimental.chat.messages.transform": async (_input, output) => {
|
|
@@ -1776,11 +1316,7 @@ function createPhaseReminderHook() {
|
|
|
1776
1316
|
if (originalText.includes(LITE_INTERNAL_INITIATOR_MARKER)) {
|
|
1777
1317
|
return;
|
|
1778
1318
|
}
|
|
1779
|
-
lastUserMessage.parts[textPartIndex].text = `${PHASE_REMINDER}
|
|
1780
|
-
|
|
1781
|
-
---
|
|
1782
|
-
|
|
1783
|
-
${originalText}`;
|
|
1319
|
+
lastUserMessage.parts[textPartIndex].text = `${PHASE_REMINDER}${PHASE_REMINDER_SEPARATOR}${originalText}`;
|
|
1784
1320
|
}
|
|
1785
1321
|
};
|
|
1786
1322
|
}
|
|
@@ -2013,8 +1549,8 @@ function createThothClient(options) {
|
|
|
2013
1549
|
|
|
2014
1550
|
// src/hooks/thoth-mem/protocol.ts
|
|
2015
1551
|
var SDD_TOPIC_KEY_FORMAT = "sdd/{change}/{artifact}";
|
|
2016
|
-
var FIRST_ACTION_INSTRUCTION = 'FIRST ACTION REQUIRED: Call
|
|
2017
|
-
var SESSION_SUMMARY_TEMPLATE = `Use this exact structure for \`
|
|
1552
|
+
var FIRST_ACTION_INSTRUCTION = 'FIRST ACTION REQUIRED: Call mem_session(action="summary") with the content of the compacted summary. This preserves what was accomplished before compaction. Do this BEFORE any other work. Then call mem_context(recall_query=...) for fused recent context, and use the recall funnel (mem_recall(mode="compact") -> mem_recall(mode="context") -> mem_get(...)) for precise retrieval.';
|
|
1553
|
+
var SESSION_SUMMARY_TEMPLATE = `Use this exact structure for \`mem_session(action="summary")\` content:
|
|
2018
1554
|
|
|
2019
1555
|
## Goal
|
|
2020
1556
|
[What we were working on this session]
|
|
@@ -2034,10 +1570,10 @@ var SESSION_SUMMARY_TEMPLATE = `Use this exact structure for \`mem_session_summa
|
|
|
2034
1570
|
## Relevant Files
|
|
2035
1571
|
- path/to/file.ts - [what it does or what changed]`;
|
|
2036
1572
|
function buildCompactionReminder(sessionID) {
|
|
2037
|
-
return `FIRST ACTION REQUIRED: this session was compacted. Call \`
|
|
1573
|
+
return `FIRST ACTION REQUIRED: this session was compacted. Call \`mem_session(action="summary")\` with the content of the compacted summary and \`session_id\` \`${sessionID}\`. This preserves what was accomplished before compaction. Do this BEFORE any other work. After that, call \`mem_context(recall_query=...)\` for fused recent context, and use the recall funnel (\`mem_recall(mode="compact")\` -> \`mem_recall(mode="context")\` -> \`mem_get(...)\`) for precise retrieval.`;
|
|
2038
1574
|
}
|
|
2039
1575
|
function buildCompactorInstruction(project) {
|
|
2040
|
-
return `CRITICAL INSTRUCTION: place this at the TOP of the compacted summary exactly as an action item for the resumed agent: "FIRST ACTION REQUIRED: Call
|
|
1576
|
+
return `CRITICAL INSTRUCTION: place this at the TOP of the compacted summary exactly as an action item for the resumed agent: "FIRST ACTION REQUIRED: Call mem_session(action="summary") with the content of this compacted summary. Use project: '${project}'. This preserves what was accomplished before compaction. Do this BEFORE any other work."`;
|
|
2041
1577
|
}
|
|
2042
1578
|
function buildMemoryInstructions(sessionID, project) {
|
|
2043
1579
|
return `
|
|
@@ -2045,18 +1581,20 @@ function buildMemoryInstructions(sessionID, project) {
|
|
|
2045
1581
|
Persistent memory is available through thoth-mem. Follow this protocol.
|
|
2046
1582
|
|
|
2047
1583
|
IMPORTANT: Your current session_id is \`${sessionID}\` and project is \`${project}\`.
|
|
2048
|
-
Always pass these values when calling memory tools that accept them
|
|
1584
|
+
Always pass these values when calling memory tools that accept them.
|
|
2049
1585
|
|
|
2050
1586
|
### CORE TOOLS
|
|
2051
|
-
mem_save,
|
|
1587
|
+
mem_save, mem_recall, mem_context, mem_get, mem_project, mem_session
|
|
2052
1588
|
|
|
2053
|
-
### SUBAGENT HANDOFF
|
|
2054
|
-
-
|
|
2055
|
-
-
|
|
2056
|
-
-
|
|
1589
|
+
### OWNERSHIP AND SUBAGENT HANDOFF
|
|
1590
|
+
- Root owns \`mem_session(action="start"|"checkpoint"|"summary")\` and \`mem_save(kind="prompt"|"session_summary")\`.
|
|
1591
|
+
- Start root memory-backed workflows with \`mem_session(action="start")\` before any other thoth-mem operation when tools and identity are available.
|
|
1592
|
+
- Save the real user prompt with \`mem_save(kind="prompt")\`; never save generated subagent prompts as user intent.
|
|
1593
|
+
- Before memory-dependent delegation, save the handoff body with \`mem_session(action="summary")\` or \`mem_save(kind="session_summary")\`.
|
|
1594
|
+
- Subagent handoff prompts carry parent \`session_id\`, \`project\`, permissions, and recovery instructions only; do not ask subagents to own session lifecycle actions or save prompts.
|
|
2057
1595
|
|
|
2058
1596
|
### WHEN TO SAVE
|
|
2059
|
-
Call \`mem_save\` IMMEDIATELY after ANY of these:
|
|
1597
|
+
Call \`mem_save(kind="observation")\` IMMEDIATELY after ANY of these:
|
|
2060
1598
|
- Architecture, design, or workflow decision made
|
|
2061
1599
|
- Bug fixed (include root cause)
|
|
2062
1600
|
- Non-obvious discovery, gotcha, or edge case found
|
|
@@ -2069,44 +1607,45 @@ Call \`mem_save\` IMMEDIATELY after ANY of these:
|
|
|
2069
1607
|
- Discussion concludes with a clear direction chosen
|
|
2070
1608
|
|
|
2071
1609
|
Use \`title\` as Verb + what changed or was learned.
|
|
1610
|
+
Use \`kind\` intentionally: \`observation\`, \`prompt\`, \`session_summary\`, or \`passive_learnings\`.
|
|
2072
1611
|
Use \`type\` from: bugfix | decision | architecture | discovery | pattern | config | learning | manual.
|
|
2073
1612
|
Set \`scope\` intentionally.
|
|
2074
|
-
Reuse \`topic_key\` for the same evolving topic. Do not overwrite unrelated topics.
|
|
2075
|
-
|
|
2076
|
-
If you need to modify a known observation by exact ID, call \`mem_update\` instead of creating a new record.
|
|
2077
|
-
Put the durable details in \`content\` with this structure:
|
|
1613
|
+
Reuse a stable \`topic_key\` for the same evolving topic. Do not overwrite unrelated topics.
|
|
1614
|
+
Put durable observation details in \`content\` with this structure:
|
|
2078
1615
|
- What: concise description of what changed or was learned
|
|
2079
1616
|
- Why: why it mattered or what problem it solved
|
|
2080
1617
|
- Where: files, paths, or systems involved
|
|
2081
1618
|
- Learned: edge cases, caveats, or follow-up notes
|
|
2082
1619
|
|
|
2083
|
-
**Self-check after EVERY task**: "Did I or the user just make a decision, confirm a recommendation, express a preference, fix a bug, learn something, or establish a convention? If yes \u2192 mem_save NOW."
|
|
1620
|
+
**Self-check after EVERY task**: "Did I or the user just make a decision, confirm a recommendation, express a preference, fix a bug, learn something, or establish a convention? If yes \u2192 mem_save(kind="observation") NOW."
|
|
2084
1621
|
|
|
2085
|
-
|
|
2086
|
-
|
|
2087
|
-
|
|
2088
|
-
|
|
2089
|
-
|
|
2090
|
-
|
|
2091
|
-
|
|
2092
|
-
|
|
2093
|
-
-
|
|
1622
|
+
### RECALL FUNNEL
|
|
1623
|
+
- Broad recovery (session start, after compaction): call \`mem_context(recall_query=...)\` for fused recent context when useful.
|
|
1624
|
+
- Targeted retrieval:
|
|
1625
|
+
1. Call \`mem_recall(mode="compact")\` to scan candidate IDs and titles.
|
|
1626
|
+
2. Call \`mem_recall(mode="context")\` to expand the strongest hits into retrieved context.
|
|
1627
|
+
3. Call \`mem_get(...)\` only for records you need in full.
|
|
1628
|
+
- Use HyDE/fused recall for semantic or ambiguous searches.
|
|
1629
|
+
- Set \`mem_recall\` \`limit\` from 1 to 20 for candidate/result count.
|
|
1630
|
+
- Narrow with \`topic_key\`, \`type\`, \`time_from\`, \`time_to\`, \`scope\`, \`project\`, and \`session_id\` filters.
|
|
1631
|
+
- Use \`mem_get\` with \`kind="observation"|"prompt"\`; use \`mem_get(include_timeline=true)\` with \`before\`/\`after\`, and \`offset\`/\`max_length\` for large content.
|
|
1632
|
+
- Use bounded \`mem_project(action="graph"|"topics"|"topic")\` for relationship and topic navigation; \`mem_project(action="graph")\` relations are \`HAS_TYPE\`, \`IN_PROJECT\`, \`HAS_TOPIC_KEY\`, \`HAS_WHAT\`, \`HAS_WHY\`, \`HAS_WHERE\`, and \`HAS_LEARNED\`; these calls supplement, not replace, the recall funnel.
|
|
2094
1633
|
- Search proactively on the first message about a project, feature, or problem when prior context may matter.
|
|
2095
1634
|
- Search before starting work that may have been done before.
|
|
2096
1635
|
- Search when the user mentions a topic that lacks enough local context.
|
|
2097
1636
|
|
|
2098
1637
|
### SESSION CLOSE PROTOCOL
|
|
2099
|
-
- Before ending the session, call \`
|
|
1638
|
+
- Before ending the session, call \`mem_session(action="summary")\` with this exact template.
|
|
2100
1639
|
- This is NOT optional. If you skip this, the next session starts blind.
|
|
2101
1640
|
- Do not claim memory was saved unless the tool call succeeded.
|
|
2102
|
-
- If your response includes \`## Key Learnings:\`,
|
|
1641
|
+
- If your response includes \`## Key Learnings:\`, preserve them with \`mem_save(kind="passive_learnings")\`.
|
|
2103
1642
|
|
|
2104
1643
|
${SESSION_SUMMARY_TEMPLATE}
|
|
2105
1644
|
|
|
2106
1645
|
### AFTER COMPACTION
|
|
2107
|
-
- IMMEDIATELY call \`
|
|
2108
|
-
- Then call \`mem_context\` for
|
|
2109
|
-
- Use the
|
|
1646
|
+
- IMMEDIATELY call \`mem_session(action="summary")\` with the compacted summary content.
|
|
1647
|
+
- Then call \`mem_context(recall_query=...)\` for fused recent context.
|
|
1648
|
+
- Use the recall funnel (\`mem_recall(mode="compact")\` -> \`mem_recall(mode="context")\` -> \`mem_get(...)\`) for precise artifact/prior-observation retrieval.
|
|
2110
1649
|
- Only then continue working.
|
|
2111
1650
|
|
|
2112
1651
|
### SDD TOPIC KEY CONVENTION
|
|
@@ -2155,11 +1694,15 @@ function truncate(str, max) {
|
|
|
2155
1694
|
return str.length > max ? `${str.slice(0, max)}...` : str;
|
|
2156
1695
|
}
|
|
2157
1696
|
function sanitizePromptText(text) {
|
|
2158
|
-
return truncate(stripPrivateTags(text), 2e3);
|
|
1697
|
+
return truncate(stripPrivateTags(stripPhaseReminder(text)), 2e3);
|
|
2159
1698
|
}
|
|
2160
|
-
function isSessionSummaryTool(toolName) {
|
|
1699
|
+
function isSessionSummaryTool(toolName, args) {
|
|
1700
|
+
if (!args || typeof args !== "object" || Array.isArray(args)) {
|
|
1701
|
+
return false;
|
|
1702
|
+
}
|
|
2161
1703
|
const normalized = toolName.toLowerCase();
|
|
2162
|
-
|
|
1704
|
+
const isMemSessionTool = normalized === "mem_session" || normalized.endsWith(".mem_session") || normalized.endsWith("_mem_session");
|
|
1705
|
+
return isMemSessionTool && args.action === "summary";
|
|
2163
1706
|
}
|
|
2164
1707
|
function isMemSaveTool(toolName) {
|
|
2165
1708
|
const normalized = toolName.toLowerCase();
|
|
@@ -2331,7 +1874,6 @@ function createThothMemHook(options) {
|
|
|
2331
1874
|
},
|
|
2332
1875
|
"tool.execute.after": async (input, output) => {
|
|
2333
1876
|
void input.callID;
|
|
2334
|
-
void input.args;
|
|
2335
1877
|
void output.title;
|
|
2336
1878
|
void output.output;
|
|
2337
1879
|
void output.metadata;
|
|
@@ -2342,7 +1884,7 @@ function createThothMemHook(options) {
|
|
|
2342
1884
|
lastMemSaveAt.set(input.sessionID, Date.now());
|
|
2343
1885
|
nudgePending.delete(input.sessionID);
|
|
2344
1886
|
}
|
|
2345
|
-
if (isSessionSummaryTool(input.tool)) {
|
|
1887
|
+
if (isSessionSummaryTool(input.tool, input.args)) {
|
|
2346
1888
|
needsCompactionFollowUp.delete(input.sessionID);
|
|
2347
1889
|
}
|
|
2348
1890
|
}
|
package/package.json
CHANGED