@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.
Files changed (96) hide show
  1. package/assets/extension-launcher.mjs +24 -0
  2. package/dist/chat/chatController.d.ts +264 -0
  3. package/dist/chat/chatController.js +510 -0
  4. package/dist/chat/extensions.d.ts +14 -0
  5. package/dist/chat/extensions.js +41 -0
  6. package/dist/chat/history.d.ts +17 -0
  7. package/dist/chat/history.js +39 -0
  8. package/dist/{tui → chat}/runs.d.ts +8 -1
  9. package/dist/{tui → chat}/runs.js +1 -1
  10. package/dist/core/agentSpec.d.ts +30 -16
  11. package/dist/core/extensions.d.ts +119 -0
  12. package/dist/core/extensions.js +97 -0
  13. package/dist/core/externalExtensions.d.ts +131 -0
  14. package/dist/core/externalExtensions.js +340 -0
  15. package/dist/core/hooks/planGate.d.ts +2 -0
  16. package/dist/core/hooks/planGate.js +1 -10
  17. package/dist/core/hooks/stepGate.d.ts +1 -1
  18. package/dist/core/hooks/stepGate.js +3 -3
  19. package/dist/core/messages/de.js +11 -32
  20. package/dist/core/messages/en.d.ts +13 -16
  21. package/dist/core/messages/en.js +11 -32
  22. package/dist/core/messages/es.js +11 -32
  23. package/dist/core/messages/fr.js +11 -32
  24. package/dist/core/messages/index.d.ts +6 -0
  25. package/dist/core/messages/index.js +12 -1
  26. package/dist/core/packaged.d.ts +10 -0
  27. package/dist/core/packaged.js +38 -0
  28. package/dist/core/pluginAgents.d.ts +20 -0
  29. package/dist/core/pluginAgents.js +76 -0
  30. package/dist/core/runner.js +16 -9
  31. package/dist/core/session.d.ts +30 -5
  32. package/dist/core/session.js +143 -94
  33. package/dist/core/sessionFacts.d.ts +80 -0
  34. package/dist/core/sessionFacts.js +48 -0
  35. package/dist/core/toolLabels.d.ts +24 -6
  36. package/dist/core/toolLabels.js +24 -39
  37. package/dist/extensions/awareness/index.d.ts +13 -0
  38. package/dist/extensions/awareness/index.js +39 -0
  39. package/dist/extensions/awareness/labels.d.ts +3 -0
  40. package/dist/extensions/awareness/labels.js +12 -0
  41. package/dist/extensions/awareness/tools.d.ts +5 -0
  42. package/dist/extensions/awareness/tools.js +54 -0
  43. package/dist/extensions/knowledge/index.d.ts +8 -0
  44. package/dist/extensions/knowledge/index.js +35 -0
  45. package/dist/{core → extensions/knowledge}/knowledgeStore.d.ts +1 -0
  46. package/dist/extensions/knowledge/labels.d.ts +3 -0
  47. package/dist/extensions/knowledge/labels.js +119 -0
  48. package/dist/{core/knowledge.d.ts → extensions/knowledge/prompt.d.ts} +1 -1
  49. package/dist/{core/knowledge.js → extensions/knowledge/prompt.js} +7 -4
  50. package/dist/{core/tools/knowledgeTools.d.ts → extensions/knowledge/tools.d.ts} +1 -1
  51. package/dist/{core/tools/knowledgeTools.js → extensions/knowledge/tools.js} +2 -2
  52. package/dist/extensions/memory/index.d.ts +12 -0
  53. package/dist/extensions/memory/index.js +56 -0
  54. package/dist/extensions/memory/labels.d.ts +3 -0
  55. package/dist/extensions/memory/labels.js +58 -0
  56. package/dist/extensions/memory/memoryStore.d.ts +53 -0
  57. package/dist/extensions/memory/memoryStore.js +88 -0
  58. package/dist/extensions/memory/tools.d.ts +9 -0
  59. package/dist/extensions/memory/tools.js +82 -0
  60. package/dist/extensions/sources/index.d.ts +9 -0
  61. package/dist/extensions/sources/index.js +40 -0
  62. package/dist/extensions/sources/labels.d.ts +3 -0
  63. package/dist/extensions/sources/labels.js +82 -0
  64. package/dist/{core/tools/saveToSources.d.ts → extensions/sources/tools.d.ts} +1 -1
  65. package/dist/{core/tools/saveToSources.js → extensions/sources/tools.js} +5 -5
  66. package/dist/index.d.ts +14 -9
  67. package/dist/index.js +11 -7
  68. package/dist/tui/chatTui.d.ts +11 -20
  69. package/dist/tui/chatTui.js +75 -230
  70. package/dist/tui/extensionCommand.d.ts +21 -0
  71. package/dist/tui/extensionCommand.js +133 -0
  72. package/dist/tui/ink/runChatInk.d.ts +4 -3
  73. package/dist/tui/ink/runChatInk.js +101 -217
  74. package/extensions/awareness/.claude-plugin/plugin.json +10 -0
  75. package/{assets/agent-help → extensions/awareness/skills/help}/SKILL.md +4 -3
  76. package/{assets/knowledge-plugin → extensions/knowledge}/.claude-plugin/plugin.json +7 -1
  77. package/extensions/memory/.claude-plugin/plugin.json +10 -0
  78. package/extensions/memory/commands/forget.md +8 -0
  79. package/extensions/memory/commands/list.md +5 -0
  80. package/extensions/sources/.claude-plugin/plugin.json +10 -0
  81. package/package.json +3 -2
  82. package/dist/core/agentHelp.d.ts +0 -30
  83. package/dist/core/agentHelp.js +0 -55
  84. /package/dist/{core → extensions/knowledge}/fileKnowledgeStore.d.ts +0 -0
  85. /package/dist/{core → extensions/knowledge}/fileKnowledgeStore.js +0 -0
  86. /package/dist/{core → extensions/knowledge}/knowledgeStore.js +0 -0
  87. /package/dist/{core → extensions/sources}/extractText.d.ts +0 -0
  88. /package/dist/{core → extensions/sources}/extractText.js +0 -0
  89. /package/dist/{core → extensions/sources}/sources.d.ts +0 -0
  90. /package/dist/{core → extensions/sources}/sources.js +0 -0
  91. /package/{assets/knowledge-plugin → extensions/knowledge}/commands/ingest.md +0 -0
  92. /package/{assets/knowledge-plugin → extensions/knowledge}/commands/lint.md +0 -0
  93. /package/{assets/knowledge-plugin → extensions/knowledge}/commands/query.md +0 -0
  94. /package/{assets/knowledge-plugin → extensions/knowledge}/skills/knowledge-ingest/SKILL.md +0 -0
  95. /package/{assets/knowledge-plugin → extensions/knowledge}/skills/knowledge-lint/SKILL.md +0 -0
  96. /package/{assets/knowledge-plugin → extensions/knowledge}/skills/knowledge-query/SKILL.md +0 -0
@@ -0,0 +1,24 @@
1
+ // Starts an external extension's MCP server (ADR-025, #37) with a clean environment: the SDK
2
+ // merges a server's `env` with the agent's own (confirmed empirically), so the kit starts this
3
+ // launcher instead, which keeps only the variables the system needs and those the extension
4
+ // declares, then loads the server in this same process.
5
+ //
6
+ // Usage: node extension-launcher.mjs <server script> <JSON array of variable names it may see> [its arguments…]
7
+ import { pathToFileURL } from "node:url";
8
+
9
+ const [entry, declared = "[]", ...args] = process.argv.slice(2);
10
+ if (!entry) {
11
+ console.error("extension-launcher: no server entry given");
12
+ process.exit(1);
13
+ }
14
+
15
+ // What any process may need to run, on Windows and elsewhere; never a credential.
16
+ const SYSTEM = ["PATH", "PATHEXT", "SYSTEMROOT", "SYSTEMDRIVE", "WINDIR", "COMSPEC", "TEMP", "TMP", "TMPDIR", "HOME", "USERPROFILE", "APPDATA", "LOCALAPPDATA", "LANG", "LC_ALL", "TZ"];
17
+ const allowed = new Set([...SYSTEM, ...JSON.parse(declared)].map((name) => name.toUpperCase()));
18
+ for (const name of Object.keys(process.env)) {
19
+ if (!allowed.has(name.toUpperCase())) delete process.env[name];
20
+ }
21
+
22
+ // The server reads its own arguments from argv: its own, none of the launcher's.
23
+ process.argv = [process.argv[0], entry, ...args];
24
+ await import(pathToFileURL(entry).href);
@@ -0,0 +1,264 @@
1
+ import type { Options, SDKUserMessage } from "@anthropic-ai/claude-agent-sdk";
2
+ import type { Mode } from "../core/agentSpec.js";
3
+ import { type ApprovalPrompt, type ChoiceSettings } from "../core/interaction.js";
4
+ import { type Language } from "../core/language.js";
5
+ import { type AgentEvent, type AgentRun, type SessionUsage } from "../core/runner.js";
6
+ import { type RunFolder } from "../core/runs.js";
7
+ import { type ExtensionsStatus, type ModeControl } from "../core/session.js";
8
+ import { type Todo } from "../core/todos.js";
9
+ import { type ToolLabels } from "../core/toolLabels.js";
10
+ import type { ToolPhrase } from "../core/messages/index.js";
11
+ import { type SessionOpener } from "./runs.js";
12
+ /**
13
+ * The chat's logic without an interface (ADR-026, #39): opening, reopening and resuming the
14
+ * session, the input queue and the agent run, the person's lines (commands or turns), the
15
+ * session log and the history. A view (the terminal chats, the web page) draws its `state`, a
16
+ * plain-data snapshot, or follows its `events`, and sends it the person's actions.
17
+ */
18
+ /** What the controller needs besides the session: the chats' options it acts on. */
19
+ export interface ChatSettings {
20
+ /** Lines (trimmed, case-insensitive) that end the chat. Default `/exit`, `/quit`. */
21
+ exitCommands?: readonly string[];
22
+ /** The first turn, sent before the person types anything, unless the run resumes a conversation. */
23
+ initialPrompt?: string;
24
+ /** The session log without runs (with runs, each run's `session.log`). */
25
+ sessionLogPath?: string;
26
+ /** The label before the person's lines in the session log. */
27
+ promptLabel?: string;
28
+ /** The label before the agent's reply in the session log. */
29
+ agentLabel?: string;
30
+ /** The person's lines, kept across runs (↑/↓). */
31
+ historyPath?: string;
32
+ historyLimit?: number;
33
+ /** With a session opener: where the runs are (required then). */
34
+ runsDir?: string;
35
+ /** Without one, the session's mode control and tool labels. */
36
+ modeControl?: ModeControl;
37
+ toolLabels?: ToolLabels;
38
+ /** Tool call labels and folded-group phrases on top of the kit's and the extensions'. */
39
+ formatAction?: (toolName: string, input: unknown) => string;
40
+ toolPhrase?: (toolName: string) => ToolPhrase | undefined;
41
+ /** Runs the agent: the SDK's (`runQuery()`) by default; another for tests, or a host of its own. */
42
+ runQuery?: (prompt: AsyncIterable<SDKUserMessage>, options: Options) => AgentRun;
43
+ /** The SDK's prompt suggestions (on by default). */
44
+ promptSuggestions?: boolean;
45
+ /**
46
+ * How a choice in place of the prompt is asked (the conversations of `/resume`): a terminal
47
+ * view asks it its way; without it, it's the state's `choice`, answered with `choose()`.
48
+ */
49
+ pick?: (title: string, options: {
50
+ label: string;
51
+ value: string;
52
+ }[]) => Promise<string | null>;
53
+ /** The view's own commands, by name without the slash (a terminal's `/copy`): logged and kept in the history like any line, then run by the view. */
54
+ commands?: Record<string, () => void | Promise<void>>;
55
+ /**
56
+ * Who asks the person at a checkpoint: `"view"` (the default) leaves the interaction port to
57
+ * the view (a terminal's panels); `"state"` installs the controller's own, whose panel is the
58
+ * state's `panel`, answered with `answer()`.
59
+ */
60
+ panels?: "view" | "state";
61
+ }
62
+ /** One tool call in the transcript. */
63
+ export interface TranscriptCall {
64
+ id?: string;
65
+ toolName: string;
66
+ label: string;
67
+ result: {
68
+ isError: boolean;
69
+ text: string;
70
+ } | null;
71
+ /** What a subagent it started did, by label. */
72
+ children: string[];
73
+ }
74
+ /** One block of the conversation, as a view shows it. */
75
+ export type TranscriptEntry = {
76
+ id: number;
77
+ kind: "user";
78
+ text: string;
79
+ } | {
80
+ id: number;
81
+ kind: "agent";
82
+ text: string;
83
+ } | {
84
+ id: number;
85
+ kind: "tools";
86
+ calls: TranscriptCall[];
87
+ } | {
88
+ id: number;
89
+ kind: "notice";
90
+ tone: NoticeTone;
91
+ text: string;
92
+ } | {
93
+ id: number;
94
+ kind: "turn-summary";
95
+ seconds: number;
96
+ };
97
+ /** How a notice reads: plain (the agent's own text), dim (a kit's aside), a warning or an error. */
98
+ export type NoticeTone = "plain" | "dim" | "warn" | "error";
99
+ /** What a checkpoint asks: an approval, a confirmation after a manual step, free text, or a choice. */
100
+ export type ChatQuestion = {
101
+ kind: "decision" | "manual" | "text";
102
+ prompt: ApprovalPrompt;
103
+ } | {
104
+ kind: "choice";
105
+ prompt: ApprovalPrompt;
106
+ choice: ChoiceSettings;
107
+ };
108
+ /** A checkpoint waiting for the person's answer, with `panels: "state"`. */
109
+ export type ChatPanel = ChatQuestion & {
110
+ id: number;
111
+ };
112
+ /** The chat's state: plain data, the same for any view. */
113
+ export interface ChatState {
114
+ transcript: TranscriptEntry[];
115
+ /** A turn is running. */
116
+ busy: boolean;
117
+ turnStartedAt: number | null;
118
+ /** The label of the agent's latest action in this turn, and of a subagent's. */
119
+ activity: string | null;
120
+ subagentActivity: string | null;
121
+ /** The agent's task list while any task is open. */
122
+ todos: Todo[] | null;
123
+ mode: Mode | null;
124
+ /** The modes the person can switch between (none in autonomous mode). */
125
+ switchableModes: readonly Mode[];
126
+ turns: number;
127
+ usage: SessionUsage | null;
128
+ /** How full the context window is (0-100), after the latest turn. */
129
+ contextPercent: number | null;
130
+ /** The model's predicted next prompt. */
131
+ suggestion: string | null;
132
+ /** The slash commands the person can type: the session's and the chat's own. */
133
+ commands: string[];
134
+ /** The same, with what each does and what it takes after it, for a view that lists them. */
135
+ commandDetails: {
136
+ name: string;
137
+ description: string;
138
+ argumentHint: string;
139
+ }[];
140
+ /** The kit's language now (it can change: `setLanguage()`). */
141
+ language: Language;
142
+ /** The person's earlier lines, oldest first. */
143
+ history: string[];
144
+ /** A checkpoint waiting for an answer (`panels: "state"`). */
145
+ panel: ChatPanel | null;
146
+ /** A choice waiting for an answer (without `pick`). */
147
+ choice: {
148
+ title: string;
149
+ options: {
150
+ label: string;
151
+ value: string;
152
+ }[];
153
+ } | null;
154
+ /** The run in use, with runs. */
155
+ run: RunFolder | null;
156
+ extensions: ExtensionsStatus | null;
157
+ closed: boolean;
158
+ }
159
+ /** What happens in the chat, in order, for a view that draws as it goes (a terminal). */
160
+ export type ChatEvent = {
161
+ type: "agent";
162
+ event: AgentEvent;
163
+ } | {
164
+ type: "user";
165
+ text: string;
166
+ } | {
167
+ type: "notice";
168
+ tone: NoticeTone;
169
+ text: string;
170
+ } | {
171
+ type: "turn-start";
172
+ } | {
173
+ type: "turn-end";
174
+ seconds: number;
175
+ }
176
+ /** An earlier conversation to draw: the run's, at start or after `/resume`. */
177
+ | {
178
+ type: "conversation";
179
+ messages: {
180
+ role: "user" | "assistant";
181
+ text: string;
182
+ }[];
183
+ updatedAt: Date;
184
+ fromResume: boolean;
185
+ }
186
+ /** The mode changed (the person, or the agent leaving plan mode). */
187
+ | {
188
+ type: "mode";
189
+ mode: Mode;
190
+ }
191
+ /** The session was opened again (resumed, or an extension enabled or disabled). */
192
+ | {
193
+ type: "session";
194
+ };
195
+ /** A chat controller: its state, events and actions (see `createChatController()`). */
196
+ export type ChatController = Awaited<ReturnType<typeof createChatController>>;
197
+ /**
198
+ * Opens the chat's session (the first run with a session opener, `--continue` picking the
199
+ * latest) and loads the history; `start()` then draws the run's conversation and sends the
200
+ * initial prompt, `send()` each line the person types.
201
+ */
202
+ export declare function createChatController(options: Options | SessionOpener, settings?: ChatSettings): Promise<{
203
+ /** The state now. */
204
+ getState: () => ChatState;
205
+ /** Calls `listener` with every new state; returns how to stop. */
206
+ subscribe(listener: (state: ChatState) => void): () => void;
207
+ /** Calls `listener` with every event, in order; returns how to stop. */
208
+ onEvent(listener: (event: ChatEvent) => void): () => void;
209
+ /** Tool call labels and phrases with the extensions' (for a view that renders events itself). */
210
+ formatAction: (toolName: string, toolInput: unknown) => string;
211
+ toolPhrase: (toolName: string) => ToolPhrase | undefined;
212
+ /** The folder the session works in. */
213
+ cwd: () => string;
214
+ /** Draws the run's earlier conversation, then sends the initial prompt (for a new run). */
215
+ start(): Promise<void>;
216
+ /**
217
+ * A line the person sent: an exit command ("exit"), one of the chat's commands, or a turn,
218
+ * resolved when it ends. An unknown slash command is caught before it reaches the model.
219
+ */
220
+ send(raw: string): Promise<"exit" | void>;
221
+ /** Stops the turn running, if any. */
222
+ interrupt(): void;
223
+ /** Switches to a mode the session allows; says so when it can't. */
224
+ setMode(mode: Mode): void;
225
+ /** The next mode the session allows (Shift+Tab). */
226
+ cycleMode(): void;
227
+ /** Into plan mode, or back to the mode it was entered from (`/plan`). */
228
+ togglePlan(): void;
229
+ /** The runs to resume, newest first, labelled for a person. */
230
+ listRuns(): Promise<{
231
+ label: string;
232
+ dir: string;
233
+ }[]>;
234
+ /** `/resume`: with `dir`, switches to that run; without it, asks which. */
235
+ resume(dir?: string): Promise<void>;
236
+ /**
237
+ * Starts a new conversation in a new run, leaving the current one to resume later: what a
238
+ * graphical view offers instead of quitting and starting again.
239
+ */
240
+ newConversation(): Promise<void>;
241
+ /** Enables or disables an installed extension, and opens the session again with the same conversation. */
242
+ setExtension(name: string, enabled: boolean): Promise<void>;
243
+ /**
244
+ * Switches the kit's language (`switchLanguage()`) and opens the session again in it, keeping
245
+ * the conversation: the agent's next reply, the labels and the kit's notices come in it.
246
+ * `note` adds the host's own words to what the model is told (the agent's name in that
247
+ * language: the earlier conversation keeps pulling the old one).
248
+ */
249
+ setLanguage(language: Language, { note }?: {
250
+ note?: string;
251
+ }): Promise<void>;
252
+ /** What an active extension hands the host (its `api`), e.g. the sources' `addSource`; `undefined` when it isn't active. */
253
+ api<T = Record<string, unknown>>(extension: string): T | undefined;
254
+ /** Answers the state's panel (`panels: "state"`). */
255
+ answer(panelId: number, answer: string): void;
256
+ /** Answers the state's choice (`null`: cancelled). */
257
+ choose(value: string | null): void;
258
+ /** A notice from the view (a welcome): in the transcript and the session log. */
259
+ notice: (text: string, tone?: NoticeTone) => void;
260
+ /** The agent's text in the latest turn that ended, plain (for `/copy`). */
261
+ lastReply: () => string;
262
+ /** Ends the chat: the agent run, the session log, the controller's port. */
263
+ close(): void;
264
+ }>;