@falkenslab/agent-kit 0.18.0 → 0.19.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/assets/extension-launcher.mjs +24 -0
- package/dist/chat/chatController.d.ts +264 -0
- package/dist/chat/chatController.js +510 -0
- package/dist/chat/extensions.d.ts +14 -0
- package/dist/chat/extensions.js +41 -0
- package/dist/chat/history.d.ts +17 -0
- package/dist/chat/history.js +39 -0
- package/dist/{tui → chat}/runs.d.ts +8 -1
- package/dist/{tui → chat}/runs.js +1 -1
- package/dist/core/agentSpec.d.ts +30 -16
- package/dist/core/extensions.d.ts +119 -0
- package/dist/core/extensions.js +97 -0
- package/dist/core/externalExtensions.d.ts +131 -0
- package/dist/core/externalExtensions.js +340 -0
- package/dist/core/hooks/planGate.d.ts +2 -0
- package/dist/core/hooks/planGate.js +1 -10
- package/dist/core/hooks/stepGate.d.ts +1 -1
- package/dist/core/hooks/stepGate.js +3 -3
- package/dist/core/messages/de.js +11 -32
- package/dist/core/messages/en.d.ts +13 -16
- package/dist/core/messages/en.js +11 -32
- package/dist/core/messages/es.js +11 -32
- package/dist/core/messages/fr.js +11 -32
- package/dist/core/messages/index.d.ts +6 -0
- package/dist/core/messages/index.js +12 -1
- package/dist/core/packaged.d.ts +10 -0
- package/dist/core/packaged.js +38 -0
- package/dist/core/pluginAgents.d.ts +20 -0
- package/dist/core/pluginAgents.js +76 -0
- package/dist/core/runner.js +16 -9
- package/dist/core/session.d.ts +30 -5
- package/dist/core/session.js +143 -94
- package/dist/core/sessionFacts.d.ts +80 -0
- package/dist/core/sessionFacts.js +48 -0
- package/dist/core/toolLabels.d.ts +24 -6
- package/dist/core/toolLabels.js +24 -39
- package/dist/extensions/awareness/index.d.ts +13 -0
- package/dist/extensions/awareness/index.js +39 -0
- package/dist/extensions/awareness/labels.d.ts +3 -0
- package/dist/extensions/awareness/labels.js +12 -0
- package/dist/extensions/awareness/tools.d.ts +5 -0
- package/dist/extensions/awareness/tools.js +54 -0
- package/dist/extensions/knowledge/index.d.ts +8 -0
- package/dist/extensions/knowledge/index.js +35 -0
- package/dist/{core → extensions/knowledge}/knowledgeStore.d.ts +1 -0
- package/dist/extensions/knowledge/labels.d.ts +3 -0
- package/dist/extensions/knowledge/labels.js +119 -0
- package/dist/{core/knowledge.d.ts → extensions/knowledge/prompt.d.ts} +1 -1
- package/dist/{core/knowledge.js → extensions/knowledge/prompt.js} +7 -4
- package/dist/{core/tools/knowledgeTools.d.ts → extensions/knowledge/tools.d.ts} +1 -1
- package/dist/{core/tools/knowledgeTools.js → extensions/knowledge/tools.js} +2 -2
- package/dist/extensions/memory/index.d.ts +12 -0
- package/dist/extensions/memory/index.js +56 -0
- package/dist/extensions/memory/labels.d.ts +3 -0
- package/dist/extensions/memory/labels.js +58 -0
- package/dist/extensions/memory/memoryStore.d.ts +53 -0
- package/dist/extensions/memory/memoryStore.js +88 -0
- package/dist/extensions/memory/tools.d.ts +9 -0
- package/dist/extensions/memory/tools.js +82 -0
- package/dist/extensions/sources/index.d.ts +9 -0
- package/dist/extensions/sources/index.js +40 -0
- package/dist/extensions/sources/labels.d.ts +3 -0
- package/dist/extensions/sources/labels.js +82 -0
- package/dist/{core/tools/saveToSources.d.ts → extensions/sources/tools.d.ts} +1 -1
- package/dist/{core/tools/saveToSources.js → extensions/sources/tools.js} +5 -5
- package/dist/index.d.ts +14 -9
- package/dist/index.js +11 -7
- package/dist/tui/chatTui.d.ts +11 -20
- package/dist/tui/chatTui.js +75 -230
- package/dist/tui/extensionCommand.d.ts +21 -0
- package/dist/tui/extensionCommand.js +133 -0
- package/dist/tui/ink/runChatInk.d.ts +4 -3
- package/dist/tui/ink/runChatInk.js +101 -217
- package/extensions/awareness/.claude-plugin/plugin.json +10 -0
- package/{assets/agent-help → extensions/awareness/skills/help}/SKILL.md +4 -3
- package/{assets/knowledge-plugin → extensions/knowledge}/.claude-plugin/plugin.json +7 -1
- package/extensions/memory/.claude-plugin/plugin.json +10 -0
- package/extensions/memory/commands/forget.md +8 -0
- package/extensions/memory/commands/list.md +5 -0
- package/extensions/sources/.claude-plugin/plugin.json +10 -0
- package/package.json +3 -2
- package/dist/core/agentHelp.d.ts +0 -30
- package/dist/core/agentHelp.js +0 -55
- /package/dist/{core → extensions/knowledge}/fileKnowledgeStore.d.ts +0 -0
- /package/dist/{core → extensions/knowledge}/fileKnowledgeStore.js +0 -0
- /package/dist/{core → extensions/knowledge}/knowledgeStore.js +0 -0
- /package/dist/{core → extensions/sources}/extractText.d.ts +0 -0
- /package/dist/{core → extensions/sources}/extractText.js +0 -0
- /package/dist/{core → extensions/sources}/sources.d.ts +0 -0
- /package/dist/{core → extensions/sources}/sources.js +0 -0
- /package/{assets/knowledge-plugin → extensions/knowledge}/commands/ingest.md +0 -0
- /package/{assets/knowledge-plugin → extensions/knowledge}/commands/lint.md +0 -0
- /package/{assets/knowledge-plugin → extensions/knowledge}/commands/query.md +0 -0
- /package/{assets/knowledge-plugin → extensions/knowledge}/skills/knowledge-ingest/SKILL.md +0 -0
- /package/{assets/knowledge-plugin → extensions/knowledge}/skills/knowledge-lint/SKILL.md +0 -0
- /package/{assets/knowledge-plugin → extensions/knowledge}/skills/knowledge-query/SKILL.md +0 -0
package/dist/core/messages/es.js
CHANGED
|
@@ -22,6 +22,17 @@ export const es = {
|
|
|
22
22
|
resumeHint: "↑/↓ elegir · Intro retomar · Esc cancelar",
|
|
23
23
|
resumeQuestion: "Número de la conversación que retomar (Intro para cancelar): ",
|
|
24
24
|
noEarlierRuns: "(no hay conversaciones anteriores que retomar)",
|
|
25
|
+
commandResume: "Elegir una conversación anterior para seguir con ella",
|
|
26
|
+
commandPlan: "Entrar en el modo plan, o volver",
|
|
27
|
+
commandExtensions: "Qué funciona, qué no y por qué; activar o desactivar una",
|
|
28
|
+
extensionsRunning: (names) => `Funcionando con: ${names}`,
|
|
29
|
+
extensionsNone: "(ninguna extensión)",
|
|
30
|
+
extensionOff: (name, reason) => `${name} está desactivada: ${reason}`,
|
|
31
|
+
extensionsInstalled: "Instaladas:",
|
|
32
|
+
extensionToggled: (name, enabled) => `(${name} ${enabled ? "activada" : "desactivada"}: la sesión se reabre, con la misma conversación)`,
|
|
33
|
+
extensionNotInstalled: (name) => `(${name} no está instalada: /extensions las lista)`,
|
|
34
|
+
extensionsUsage: "(uso: /extensions, /extensions enable <nombre>, /extensions disable <nombre>)",
|
|
35
|
+
extensionsCantReopen: "(este chat no puede reabrir su sesión: actívala o desactívala desde la terminal y vuelve a empezar)",
|
|
25
36
|
currentRun: "(esta)",
|
|
26
37
|
resumed: (date) => `(retomada la conversación del ${date})`,
|
|
27
38
|
suggestionKey: "tab",
|
|
@@ -91,22 +102,6 @@ export const es = {
|
|
|
91
102
|
Task: ["lanzó {n} subagente", "lanzó {n} subagentes"],
|
|
92
103
|
mcp__time__current_time: ["consultó la hora", "consultó la hora {n} veces"],
|
|
93
104
|
mcp__time__date_math: ["calculó fechas", "calculó fechas {n} veces"],
|
|
94
|
-
mcp__sourceFiles__list_sources: ["revisó las fuentes", "revisó las fuentes {n} veces"],
|
|
95
|
-
mcp__sourceFiles__extract_text: ["leyó {n} documento", "leyó {n} documentos"],
|
|
96
|
-
mcp__sourceFiles__save_to_sources: ["guardó {n} fuente", "guardó {n} fuentes"],
|
|
97
|
-
mcp__sourceFiles__download_to_sources: ["descargó {n} fuente", "descargó {n} fuentes"],
|
|
98
|
-
mcp__sourceFiles__request_file: ["pidió {n} fichero", "pidió {n} ficheros"],
|
|
99
|
-
mcp__sourceFiles__retire_source: ["retiró {n} fuente", "retiró {n} fuentes"],
|
|
100
|
-
mcp__knowledge__knowledge_index: ["leyó el índice", "leyó el índice {n} veces"],
|
|
101
|
-
mcp__knowledge__knowledge_search: ["buscó en la base de conocimiento", "buscó en la base de conocimiento {n} veces"],
|
|
102
|
-
mcp__knowledge__knowledge_read: ["leyó {n} página", "leyó {n} páginas"],
|
|
103
|
-
mcp__knowledge__knowledge_create: ["creó {n} página", "creó {n} páginas"],
|
|
104
|
-
mcp__knowledge__knowledge_edit: ["editó {n} página", "editó {n} páginas"],
|
|
105
|
-
mcp__knowledge__knowledge_rewrite: ["reescribió {n} página", "reescribió {n} páginas"],
|
|
106
|
-
mcp__knowledge__knowledge_supersede: ["sustituyó {n} página", "sustituyó {n} páginas"],
|
|
107
|
-
mcp__knowledge__knowledge_retire: ["retiró {n} página", "retiró {n} páginas"],
|
|
108
|
-
mcp__knowledge__knowledge_log: ["actualizó el registro", "actualizó el registro {n} veces"],
|
|
109
|
-
mcp__knowledge__knowledge_check: ["revisó la base de conocimiento", "revisó la base de conocimiento {n} veces"],
|
|
110
105
|
mcp__approvals__ask_human: ["hizo {n} pregunta", "hizo {n} preguntas"],
|
|
111
106
|
mcp__approvals__present_plan: ["presentó el plan", "presentó el plan {n} veces"],
|
|
112
107
|
},
|
|
@@ -120,7 +115,6 @@ export const es = {
|
|
|
120
115
|
labels: {
|
|
121
116
|
askingApproval: (summary) => `Pidiendo aprobación humana: ${summary}`,
|
|
122
117
|
waitingManual: "Esperando a que una persona intervenga a mano",
|
|
123
|
-
savingToSources: (destination) => `Guardando ${destination} en las fuentes`,
|
|
124
118
|
checkingTime: "Consultando la fecha y la hora",
|
|
125
119
|
calculatingDates: "Calculando fechas",
|
|
126
120
|
reading: (file) => `Leyendo ${file}`,
|
|
@@ -139,21 +133,6 @@ export const es = {
|
|
|
139
133
|
applyingSkill: (skill) => `Aplicando la skill "${skill}"`,
|
|
140
134
|
aSkill: "una skill",
|
|
141
135
|
updatingTasks: "Actualizando la lista de tareas",
|
|
142
|
-
listingSources: "Revisando las fuentes",
|
|
143
|
-
extractingText: (source) => `Leyendo ${source}`,
|
|
144
|
-
downloading: (url) => `Descargando ${url} a las fuentes`,
|
|
145
|
-
requestingFile: (description) => `Pidiendo un fichero: ${description}`,
|
|
146
|
-
retiringSource: (source) => `Retirando la fuente ${source}`,
|
|
147
|
-
knowledgeIndex: "Leyendo el índice de la base de conocimiento",
|
|
148
|
-
knowledgeSearch: (query) => `Buscando "${query}" en la base de conocimiento`,
|
|
149
|
-
knowledgeRead: (page) => `Leyendo ${page}`,
|
|
150
|
-
knowledgeCreate: (page) => `Creando ${page}`,
|
|
151
|
-
knowledgeEdit: (page) => `Editando ${page}`,
|
|
152
|
-
knowledgeRewrite: (page) => `Reescribiendo ${page}`,
|
|
153
|
-
knowledgeSupersede: (page) => `Marcando ${page} como sustituida`,
|
|
154
|
-
knowledgeRetire: (page) => `Retirando ${page}`,
|
|
155
|
-
knowledgeLog: "Actualizando el registro de la base de conocimiento",
|
|
156
|
-
knowledgeCheck: "Revisando la base de conocimiento",
|
|
157
136
|
askingHuman: (question) => `Preguntando: ${question}`,
|
|
158
137
|
presentingPlan: "Presentando el plan",
|
|
159
138
|
},
|
package/dist/core/messages/fr.js
CHANGED
|
@@ -22,6 +22,17 @@ export const fr = {
|
|
|
22
22
|
resumeHint: "↑/↓ choisir · Entrée reprendre · Échap annuler",
|
|
23
23
|
resumeQuestion: "Numéro de la conversation à reprendre (Entrée pour annuler) : ",
|
|
24
24
|
noEarlierRuns: "(aucune conversation précédente à reprendre)",
|
|
25
|
+
commandResume: "Choisir une conversation précédente pour la reprendre",
|
|
26
|
+
commandPlan: "Passer en mode plan, ou revenir",
|
|
27
|
+
commandExtensions: "Ce qui tourne, ce qui est éteint et pourquoi ; en activer ou désactiver une",
|
|
28
|
+
extensionsRunning: (names) => `En service : ${names}`,
|
|
29
|
+
extensionsNone: "(aucune extension)",
|
|
30
|
+
extensionOff: (name, reason) => `${name} est désactivée : ${reason}`,
|
|
31
|
+
extensionsInstalled: "Installées :",
|
|
32
|
+
extensionToggled: (name, enabled) => `(${name} ${enabled ? "activée" : "désactivée"} : la session se rouvre, avec la même conversation)`,
|
|
33
|
+
extensionNotInstalled: (name) => `(${name} n'est pas installée : /extensions les liste)`,
|
|
34
|
+
extensionsUsage: "(usage : /extensions, /extensions enable <nom>, /extensions disable <nom>)",
|
|
35
|
+
extensionsCantReopen: "(ce chat ne peut pas rouvrir sa session : activez-la ou désactivez-la depuis le terminal, puis recommencez)",
|
|
25
36
|
currentRun: "(celle-ci)",
|
|
26
37
|
resumed: (date) => `(conversation du ${date} reprise)`,
|
|
27
38
|
suggestionKey: "tab",
|
|
@@ -91,22 +102,6 @@ export const fr = {
|
|
|
91
102
|
Task: ["a lancé {n} sous-agent", "a lancé {n} sous-agents"],
|
|
92
103
|
mcp__time__current_time: ["a consulté l'heure", "a consulté l'heure {n} fois"],
|
|
93
104
|
mcp__time__date_math: ["a calculé des dates", "a calculé des dates {n} fois"],
|
|
94
|
-
mcp__sourceFiles__list_sources: ["a examiné les sources", "a examiné les sources {n} fois"],
|
|
95
|
-
mcp__sourceFiles__extract_text: ["a lu {n} document", "a lu {n} documents"],
|
|
96
|
-
mcp__sourceFiles__save_to_sources: ["a enregistré {n} source", "a enregistré {n} sources"],
|
|
97
|
-
mcp__sourceFiles__download_to_sources: ["a téléchargé {n} source", "a téléchargé {n} sources"],
|
|
98
|
-
mcp__sourceFiles__request_file: ["a demandé {n} fichier", "a demandé {n} fichiers"],
|
|
99
|
-
mcp__sourceFiles__retire_source: ["a retiré {n} source", "a retiré {n} sources"],
|
|
100
|
-
mcp__knowledge__knowledge_index: ["a lu l'index", "a lu l'index {n} fois"],
|
|
101
|
-
mcp__knowledge__knowledge_search: ["a cherché dans la base", "a cherché dans la base {n} fois"],
|
|
102
|
-
mcp__knowledge__knowledge_read: ["a lu {n} page", "a lu {n} pages"],
|
|
103
|
-
mcp__knowledge__knowledge_create: ["a créé {n} page", "a créé {n} pages"],
|
|
104
|
-
mcp__knowledge__knowledge_edit: ["a modifié {n} page", "a modifié {n} pages"],
|
|
105
|
-
mcp__knowledge__knowledge_rewrite: ["a réécrit {n} page", "a réécrit {n} pages"],
|
|
106
|
-
mcp__knowledge__knowledge_supersede: ["a remplacé {n} page", "a remplacé {n} pages"],
|
|
107
|
-
mcp__knowledge__knowledge_retire: ["a retiré {n} page", "a retiré {n} pages"],
|
|
108
|
-
mcp__knowledge__knowledge_log: ["a mis à jour le journal", "a mis à jour le journal {n} fois"],
|
|
109
|
-
mcp__knowledge__knowledge_check: ["a vérifié la base", "a vérifié la base {n} fois"],
|
|
110
105
|
mcp__approvals__ask_human: ["a posé {n} question", "a posé {n} questions"],
|
|
111
106
|
mcp__approvals__present_plan: ["a présenté le plan", "a présenté le plan {n} fois"],
|
|
112
107
|
},
|
|
@@ -120,7 +115,6 @@ export const fr = {
|
|
|
120
115
|
labels: {
|
|
121
116
|
askingApproval: (summary) => `Demande d'approbation humaine : ${summary}`,
|
|
122
117
|
waitingManual: "En attente d'une intervention manuelle",
|
|
123
|
-
savingToSources: (destination) => `Enregistrement de ${destination} dans les sources`,
|
|
124
118
|
checkingTime: "Consultation de la date et de l'heure",
|
|
125
119
|
calculatingDates: "Calcul de dates",
|
|
126
120
|
reading: (file) => `Lecture de ${file}`,
|
|
@@ -139,21 +133,6 @@ export const fr = {
|
|
|
139
133
|
applyingSkill: (skill) => `Application de la skill "${skill}"`,
|
|
140
134
|
aSkill: "une skill",
|
|
141
135
|
updatingTasks: "Mise à jour de la liste des tâches",
|
|
142
|
-
listingSources: "Examen des sources",
|
|
143
|
-
extractingText: (source) => `Lecture de ${source}`,
|
|
144
|
-
downloading: (url) => `Téléchargement de ${url} dans les sources`,
|
|
145
|
-
requestingFile: (description) => `Demande d'un fichier : ${description}`,
|
|
146
|
-
retiringSource: (source) => `Retrait de la source ${source}`,
|
|
147
|
-
knowledgeIndex: "Lecture de l'index de la base de connaissances",
|
|
148
|
-
knowledgeSearch: (query) => `Recherche de "${query}" dans la base de connaissances`,
|
|
149
|
-
knowledgeRead: (page) => `Lecture de ${page}`,
|
|
150
|
-
knowledgeCreate: (page) => `Création de ${page}`,
|
|
151
|
-
knowledgeEdit: (page) => `Modification de ${page}`,
|
|
152
|
-
knowledgeRewrite: (page) => `Réécriture de ${page}`,
|
|
153
|
-
knowledgeSupersede: (page) => `${page} marquée comme remplacée`,
|
|
154
|
-
knowledgeRetire: (page) => `Retrait de ${page}`,
|
|
155
|
-
knowledgeLog: "Mise à jour du journal de la base de connaissances",
|
|
156
|
-
knowledgeCheck: "Vérification de la base de connaissances",
|
|
157
136
|
askingHuman: (question) => `Question : ${question}`,
|
|
158
137
|
presentingPlan: "Présentation du plan",
|
|
159
138
|
},
|
|
@@ -17,6 +17,12 @@ export declare function getLanguage(): Language;
|
|
|
17
17
|
* once per process.
|
|
18
18
|
*/
|
|
19
19
|
export declare function chooseLanguage(option?: string): Language;
|
|
20
|
+
/**
|
|
21
|
+
* Switches the kit's language on purpose, e.g. the person picked another in a chat (#47): from
|
|
22
|
+
* then on it wins over `--language` and `config.language`, until switched again. The session
|
|
23
|
+
* says so to the model when it opens next (the controller's `setLanguage()` reopens it).
|
|
24
|
+
*/
|
|
25
|
+
export declare function switchLanguage(language: Language): void;
|
|
20
26
|
/** Warnings about unsupported language codes not shown yet (English, one line each). */
|
|
21
27
|
export declare function takeLanguageWarnings(): string[];
|
|
22
28
|
/** The kit's texts in the current language. */
|
|
@@ -23,6 +23,8 @@ export function withEnglishFallback(own) {
|
|
|
23
23
|
let current = "en";
|
|
24
24
|
let messages = en;
|
|
25
25
|
let chosen = false;
|
|
26
|
+
// A language switched to on purpose (switchLanguage()): kept over --language and options.
|
|
27
|
+
let switched = false;
|
|
26
28
|
let pendingWarnings = [];
|
|
27
29
|
const warned = new Set();
|
|
28
30
|
/** Sets the language of the kit's texts directly (a host that resolved it itself, tests). */
|
|
@@ -43,7 +45,7 @@ export function getLanguage() {
|
|
|
43
45
|
* once per process.
|
|
44
46
|
*/
|
|
45
47
|
export function chooseLanguage(option) {
|
|
46
|
-
if (chosen && option === undefined)
|
|
48
|
+
if (switched || (chosen && option === undefined))
|
|
47
49
|
return current;
|
|
48
50
|
const resolved = detectLanguage(option);
|
|
49
51
|
for (const warning of resolved.warnings) {
|
|
@@ -55,6 +57,15 @@ export function chooseLanguage(option) {
|
|
|
55
57
|
setLanguage(resolved.language);
|
|
56
58
|
return current;
|
|
57
59
|
}
|
|
60
|
+
/**
|
|
61
|
+
* Switches the kit's language on purpose, e.g. the person picked another in a chat (#47): from
|
|
62
|
+
* then on it wins over `--language` and `config.language`, until switched again. The session
|
|
63
|
+
* says so to the model when it opens next (the controller's `setLanguage()` reopens it).
|
|
64
|
+
*/
|
|
65
|
+
export function switchLanguage(language) {
|
|
66
|
+
setLanguage(language);
|
|
67
|
+
switched = true;
|
|
68
|
+
}
|
|
58
69
|
/** Warnings about unsupported language codes not shown yet (English, one line each). */
|
|
59
70
|
export function takeLanguageWarnings() {
|
|
60
71
|
const taken = pendingWarnings;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/** A path inside `…/app.asar/…`, as the unpacked copy next to it (`…/app.asar.unpacked/…`); any other path as it is. */
|
|
2
|
+
export declare function outsideArchive(file: string): string;
|
|
3
|
+
/**
|
|
4
|
+
* The SDK's CLI binary unpacked next to the archive, when the kit runs packaged: the SDK would
|
|
5
|
+
* resolve it inside `app.asar`, where it can't be executed, and its first turn would hang with
|
|
6
|
+
* no error (confirmed empirically). Looked up as the SDK does (`@anthropic-ai/claude-agent-sdk-
|
|
7
|
+
* <platform>-<arch>`, either libc on Linux), with `resolve` replaceable for tests. `undefined`
|
|
8
|
+
* when not packaged, or when the build didn't unpack it: then the SDK finds its own.
|
|
9
|
+
*/
|
|
10
|
+
export declare function unpackedClaudeExecutable(resolve?: (request: string) => string, platform?: NodeJS.Platform, arch?: string): string | undefined;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { existsSync } from "node:fs";
|
|
2
|
+
import { createRequire } from "node:module";
|
|
3
|
+
/**
|
|
4
|
+
* Running packaged in an archive (Electron's `app.asar`, ADR-026, #42). Electron reads files
|
|
5
|
+
* inside the archive for its own process, but another process can't: not the Claude Code CLI
|
|
6
|
+
* reading a plugin, not the binary itself. So every path the kit hands to another process goes
|
|
7
|
+
* through `outsideArchive()`, which points it at the copy the build unpacked (`asarUnpack`).
|
|
8
|
+
*/
|
|
9
|
+
const ARCHIVE = /([\\/])app\.asar([\\/])/;
|
|
10
|
+
/** A path inside `…/app.asar/…`, as the unpacked copy next to it (`…/app.asar.unpacked/…`); any other path as it is. */
|
|
11
|
+
export function outsideArchive(file) {
|
|
12
|
+
return file.replace(ARCHIVE, "$1app.asar.unpacked$2");
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* The SDK's CLI binary unpacked next to the archive, when the kit runs packaged: the SDK would
|
|
16
|
+
* resolve it inside `app.asar`, where it can't be executed, and its first turn would hang with
|
|
17
|
+
* no error (confirmed empirically). Looked up as the SDK does (`@anthropic-ai/claude-agent-sdk-
|
|
18
|
+
* <platform>-<arch>`, either libc on Linux), with `resolve` replaceable for tests. `undefined`
|
|
19
|
+
* when not packaged, or when the build didn't unpack it: then the SDK finds its own.
|
|
20
|
+
*/
|
|
21
|
+
export function unpackedClaudeExecutable(resolve = createRequire(import.meta.url).resolve, platform = process.platform, arch = process.arch) {
|
|
22
|
+
const packages = platform === "linux" ? [`linux-${arch}`, `linux-${arch}-musl`] : [`${platform}-${arch}`];
|
|
23
|
+
for (const suffix of packages) {
|
|
24
|
+
let file;
|
|
25
|
+
try {
|
|
26
|
+
file = resolve(`@anthropic-ai/claude-agent-sdk-${suffix}/claude${platform === "win32" ? ".exe" : ""}`);
|
|
27
|
+
}
|
|
28
|
+
catch {
|
|
29
|
+
continue;
|
|
30
|
+
}
|
|
31
|
+
if (!ARCHIVE.test(file))
|
|
32
|
+
return undefined;
|
|
33
|
+
const unpacked = outsideArchive(file);
|
|
34
|
+
if (existsSync(unpacked))
|
|
35
|
+
return unpacked;
|
|
36
|
+
}
|
|
37
|
+
return undefined;
|
|
38
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { AgentDefinition } from "@anthropic-ai/claude-agent-sdk";
|
|
2
|
+
/**
|
|
3
|
+
* A plugin's subagents (`agents/<file>.md`, ADR-025), read so the session registers them as it
|
|
4
|
+
* does an agent's own from `buildSubagents()`: in the type gate's allow-list, in the `Agent` and
|
|
5
|
+
* `Bash` decision, and with the reply-language line. The SDK loads them itself as
|
|
6
|
+
* `<plugin>:<name>`, the name from the frontmatter, not the file (confirmed empirically); a
|
|
7
|
+
* definition under that same key in `options.agents` replaces the plugin's (also confirmed), which
|
|
8
|
+
* is how the kit adds the line.
|
|
9
|
+
*/
|
|
10
|
+
/** A markdown file's frontmatter: `key: value`, with `[a, b]`, `a, b` or a YAML list for lists. */
|
|
11
|
+
export declare function frontmatter(text: string): {
|
|
12
|
+
fields: Record<string, string | string[]>;
|
|
13
|
+
body: string;
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* The subagents of the plugins in `roots`, by the name the SDK gives them (`<plugin>:<name>`):
|
|
17
|
+
* `description` and the body as the prompt, `tools` (none listed: it inherits the session's),
|
|
18
|
+
* `model` and `maxTurns` when given.
|
|
19
|
+
*/
|
|
20
|
+
export declare function pluginAgents(roots: readonly string[]): Promise<Record<string, AgentDefinition>>;
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { readdir, readFile } from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
/**
|
|
4
|
+
* A plugin's subagents (`agents/<file>.md`, ADR-025), read so the session registers them as it
|
|
5
|
+
* does an agent's own from `buildSubagents()`: in the type gate's allow-list, in the `Agent` and
|
|
6
|
+
* `Bash` decision, and with the reply-language line. The SDK loads them itself as
|
|
7
|
+
* `<plugin>:<name>`, the name from the frontmatter, not the file (confirmed empirically); a
|
|
8
|
+
* definition under that same key in `options.agents` replaces the plugin's (also confirmed), which
|
|
9
|
+
* is how the kit adds the line.
|
|
10
|
+
*/
|
|
11
|
+
/** A markdown file's frontmatter: `key: value`, with `[a, b]`, `a, b` or a YAML list for lists. */
|
|
12
|
+
export function frontmatter(text) {
|
|
13
|
+
const match = /^---\r?\n([\s\S]*?)\r?\n---\r?\n?/.exec(text);
|
|
14
|
+
if (!match)
|
|
15
|
+
return { fields: {}, body: text };
|
|
16
|
+
const fields = {};
|
|
17
|
+
const lines = match[1].split(/\r?\n/);
|
|
18
|
+
for (let i = 0; i < lines.length; i++) {
|
|
19
|
+
const kv = /^([A-Za-z_][\w-]*):\s*(.*)$/.exec(lines[i]);
|
|
20
|
+
if (!kv)
|
|
21
|
+
continue;
|
|
22
|
+
const [, key, raw] = kv;
|
|
23
|
+
if (raw === "") {
|
|
24
|
+
const items = [];
|
|
25
|
+
while (i + 1 < lines.length && /^\s+-\s/.test(lines[i + 1]))
|
|
26
|
+
items.push(lines[++i].replace(/^\s+-\s*/, ""));
|
|
27
|
+
fields[key] = items.map(unquote);
|
|
28
|
+
}
|
|
29
|
+
else if (/^\[.*\]$/.test(raw)) {
|
|
30
|
+
fields[key] = raw.slice(1, -1).split(",").map(unquote).filter(Boolean);
|
|
31
|
+
}
|
|
32
|
+
else {
|
|
33
|
+
fields[key] = unquote(raw);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return { fields, body: text.slice(match[0].length).trim() };
|
|
37
|
+
}
|
|
38
|
+
const unquote = (value) => value.trim().replace(/^["']|["']$/g, "");
|
|
39
|
+
/** A field as a list: a list as is, `a, b` split on commas. */
|
|
40
|
+
function list(value) {
|
|
41
|
+
if (value === undefined)
|
|
42
|
+
return undefined;
|
|
43
|
+
return Array.isArray(value) ? value : value.split(",").map(unquote).filter(Boolean);
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* The subagents of the plugins in `roots`, by the name the SDK gives them (`<plugin>:<name>`):
|
|
47
|
+
* `description` and the body as the prompt, `tools` (none listed: it inherits the session's),
|
|
48
|
+
* `model` and `maxTurns` when given.
|
|
49
|
+
*/
|
|
50
|
+
export async function pluginAgents(roots) {
|
|
51
|
+
const agents = {};
|
|
52
|
+
for (const root of roots) {
|
|
53
|
+
let plugin;
|
|
54
|
+
try {
|
|
55
|
+
plugin = JSON.parse(await readFile(path.join(root, ".claude-plugin", "plugin.json"), "utf8")).name;
|
|
56
|
+
}
|
|
57
|
+
catch {
|
|
58
|
+
continue;
|
|
59
|
+
}
|
|
60
|
+
const files = await readdir(path.join(root, "agents")).catch(() => []);
|
|
61
|
+
for (const file of files.filter((name) => name.endsWith(".md"))) {
|
|
62
|
+
const { fields, body } = frontmatter(await readFile(path.join(root, "agents", file), "utf8"));
|
|
63
|
+
const name = typeof fields.name === "string" && fields.name ? fields.name : file.replace(/\.md$/, "");
|
|
64
|
+
const tools = list(fields.tools);
|
|
65
|
+
const maxTurns = typeof fields.maxTurns === "string" ? Number(fields.maxTurns) : undefined;
|
|
66
|
+
agents[`${plugin}:${name}`] = {
|
|
67
|
+
description: typeof fields.description === "string" ? fields.description : "",
|
|
68
|
+
prompt: body,
|
|
69
|
+
...(tools ? { tools } : {}),
|
|
70
|
+
...(typeof fields.model === "string" ? { model: fields.model } : {}),
|
|
71
|
+
...(maxTurns && Number.isFinite(maxTurns) ? { maxTurns } : {}),
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
return agents;
|
|
76
|
+
}
|
package/dist/core/runner.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { query } from "@anthropic-ai/claude-agent-sdk";
|
|
2
|
+
import { sessionViewOf } from "./sessionFacts.js";
|
|
2
3
|
/**
|
|
3
4
|
* A turn's errors without the CLI's internal diagnostics: an interrupted turn ends with
|
|
4
5
|
* one like "[ede_diagnostic] result_type=user ... stop_reason=tool_use" (seen on Esc),
|
|
@@ -27,11 +28,16 @@ export function toolResultText(content) {
|
|
|
27
28
|
*/
|
|
28
29
|
export function runQuery(prompt, options) {
|
|
29
30
|
const result = query({ prompt, options });
|
|
31
|
+
// What the session is, for an extension that asks (sessionFacts.ts): the controls now, the
|
|
32
|
+
// tools and skills when the session starts.
|
|
33
|
+
const view = sessionViewOf(options);
|
|
34
|
+
view?.attach({ supportedCommands: () => result.supportedCommands(), contextUsage: () => contextUsage() });
|
|
30
35
|
// The main agent's tool calls by id, to name the results that come back for them.
|
|
31
36
|
const toolNames = new Map();
|
|
32
37
|
async function* generateEvents() {
|
|
33
38
|
for await (const message of result) {
|
|
34
39
|
if (message.type === "system" && message.subtype === "init") {
|
|
40
|
+
view?.attach({ tools: message.tools, skills: message.skills });
|
|
35
41
|
const failedServers = message.mcp_servers.filter((s) => s.status === "failed").map((s) => s.name);
|
|
36
42
|
if (failedServers.length > 0)
|
|
37
43
|
yield { type: "mcp-error", failedServers };
|
|
@@ -103,14 +109,15 @@ export function runQuery(prompt, options) {
|
|
|
103
109
|
interrupt: () => result.interrupt(),
|
|
104
110
|
close: () => result.close(),
|
|
105
111
|
supportedCommands: () => result.supportedCommands(),
|
|
106
|
-
contextUsage
|
|
107
|
-
try {
|
|
108
|
-
const usage = await result.getContextUsage();
|
|
109
|
-
return { percentage: usage.percentage, totalTokens: usage.totalTokens, maxTokens: usage.maxTokens };
|
|
110
|
-
}
|
|
111
|
-
catch {
|
|
112
|
-
return null;
|
|
113
|
-
}
|
|
114
|
-
},
|
|
112
|
+
contextUsage,
|
|
115
113
|
};
|
|
114
|
+
async function contextUsage() {
|
|
115
|
+
try {
|
|
116
|
+
const usage = await result.getContextUsage();
|
|
117
|
+
return { percentage: usage.percentage, totalTokens: usage.totalTokens, maxTokens: usage.maxTokens };
|
|
118
|
+
}
|
|
119
|
+
catch {
|
|
120
|
+
return null;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
116
123
|
}
|
package/dist/core/session.d.ts
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import type { Options, SDKUserMessage } from "@anthropic-ai/claude-agent-sdk";
|
|
2
2
|
import { type TranscriptLogger } from "./hooks/transcriptLogger.js";
|
|
3
3
|
import { type ModeControl } from "./modeControl.js";
|
|
4
|
-
import type { KnowledgeStore } from "
|
|
4
|
+
import type { KnowledgeStore } from "../extensions/knowledge/knowledgeStore.js";
|
|
5
|
+
import { type ExtensionDirs, type InstalledExtension } from "./externalExtensions.js";
|
|
6
|
+
import type { ToolLabels } from "./toolLabels.js";
|
|
5
7
|
import type { AgentSpec, BaseSessionConfig } from "./agentSpec.js";
|
|
6
8
|
import { type Language } from "./language.js";
|
|
7
9
|
import { type RunFolder } from "./runs.js";
|
|
@@ -12,9 +14,10 @@ import { type RunFolder } from "./runs.js";
|
|
|
12
14
|
* one-shot run or an `AsyncIterable` for a multi-turn chat).
|
|
13
15
|
*
|
|
14
16
|
* Everything actually *about the domain* (which system prompt, which MCP servers besides
|
|
15
|
-
* the generic human-in-the-loop
|
|
16
|
-
*
|
|
17
|
-
*
|
|
17
|
+
* the generic human-in-the-loop ones below, which plugin roots, which subagents) is behind
|
|
18
|
+
* `spec` (see agentSpec.ts), and the kit's optional parts (the knowledge base, the sources
|
|
19
|
+
* folder) are extensions whose contributions this function puts together (extensions.ts,
|
|
20
|
+
* ADR-025): it names none of them.
|
|
18
21
|
*
|
|
19
22
|
* The per-mode behavioral differences (whether the approval/manual-intervention tools
|
|
20
23
|
* exist, whether the interactive step gate or the plan gate decides) all fall out of
|
|
@@ -33,10 +36,32 @@ export declare function buildSessionOptions<TConfig extends BaseSessionConfig>(c
|
|
|
33
36
|
transcriptPath: string;
|
|
34
37
|
modeControl: ModeControl;
|
|
35
38
|
language: Language;
|
|
36
|
-
/**
|
|
39
|
+
/** How the chat shows the extensions' tools (`runChatInk()` takes them from a session opener). */
|
|
40
|
+
toolLabels: ToolLabels;
|
|
41
|
+
/** The installed extensions and what this session runs with, for `/extensions` (#37). */
|
|
42
|
+
extensions: ExtensionsStatus;
|
|
43
|
+
/** The knowledge base's store, when the knowledge extension is on (for a host that reads the knowledge base). */
|
|
37
44
|
knowledgeStore?: KnowledgeStore;
|
|
45
|
+
/** What each active extension hands the host (its contribution's `api`), by its name: the sources' `addSource`, the knowledge base's store. */
|
|
46
|
+
apis: Record<string, Record<string, unknown>>;
|
|
38
47
|
}>;
|
|
39
48
|
export { createModeControl, togglePlanMode, type ModeControl } from "./modeControl.js";
|
|
49
|
+
/** The extensions of a session: where they're installed, what's installed, what runs and what can't (with why). */
|
|
50
|
+
export interface ExtensionsStatus {
|
|
51
|
+
dirs: ExtensionDirs;
|
|
52
|
+
installed: InstalledExtension[];
|
|
53
|
+
/** The names of the extensions this session runs with, the kit's and the agent's too. */
|
|
54
|
+
active: string[];
|
|
55
|
+
/** What each active one is, from its manifest: for a view that lists them. */
|
|
56
|
+
about: Record<string, {
|
|
57
|
+
description: string;
|
|
58
|
+
provides: string[];
|
|
59
|
+
}>;
|
|
60
|
+
inactive: {
|
|
61
|
+
name: string;
|
|
62
|
+
reason: string;
|
|
63
|
+
}[];
|
|
64
|
+
}
|
|
40
65
|
/**
|
|
41
66
|
* The CLI's folder for a project, where it keeps each session's transcript and large tool
|
|
42
67
|
* results (`<session>/tool-results/`): the project's path with every character but letters
|