hoomanjs 1.9.0 → 1.10.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 CHANGED
@@ -103,12 +103,6 @@ Use a specific session id:
103
103
  hooman exec "What changed?" --session my-session
104
104
  ```
105
105
 
106
- Choose a toolkit size:
107
-
108
- ```bash
109
- hooman exec "Summarize this repo" --toolkit lite
110
- ```
111
-
112
106
  Skip interactive tool approval (allows every tool call; use only when you trust the prompt and environment):
113
107
 
114
108
  ```bash
@@ -135,12 +129,6 @@ Resume or pin a session id:
135
129
  hooman chat --session my-session
136
130
  ```
137
131
 
138
- Choose a toolkit size:
139
-
140
- ```bash
141
- hooman chat --toolkit max
142
- ```
143
-
144
132
  Skip the in-chat tool approval UI (same semantics as `exec --yolo`):
145
133
 
146
134
  ```bash
@@ -161,27 +149,20 @@ Resume or pin a session id:
161
149
  hooman daemon --session my-daemon --channels
162
150
  ```
163
151
 
164
- Choose a toolkit size:
165
-
166
- ```bash
167
- hooman daemon --toolkit full --channels
168
- ```
169
-
170
152
  Skip remote channel permission relay and allow every tool call from daemon turns (same risk profile as `exec` / `chat` with `--yolo`):
171
153
 
172
154
  ```bash
173
155
  hooman daemon --channels --yolo
174
156
  ```
175
157
 
176
- ### Toolkit Levels
158
+ ### Feature Flags
177
159
 
178
- `exec`, `chat`, `daemon`, and `acp` support `-t, --toolkit <lite|full|max>`.
160
+ Runtime tools and prompt sections are controlled from `config.json` under `features`:
179
161
 
180
- - `lite` - time, fetch, long-term-memory, installed skills, and configured MCP server tools
181
- - `full` - `lite` plus filesystem, shell, and thinking tools
182
- - `max` - `full` plus skills management tools and MCP config management tools
183
-
184
- Prompt loading follows the same split: filesystem / shell / thinking instructions are only included from `full` upward, while skills guidance is always included.
162
+ - `features.fetch.enabled`
163
+ - `features.filesystem.enabled`
164
+ - `features.shell.enabled`
165
+ - `features.ltm.enabled`
185
166
 
186
167
  ### `hooman configure`
187
168
 
@@ -206,12 +187,6 @@ Run Hooman as an Agent Client Protocol (ACP) agent over stdio.
206
187
  hooman acp
207
188
  ```
208
189
 
209
- Choose a toolkit size for ACP-created sessions:
210
-
211
- ```bash
212
- hooman acp --toolkit max
213
- ```
214
-
215
190
  ACP notes:
216
191
 
217
192
  - ACP sessions are stored under the active Hooman data directory in `acp-sessions/`
@@ -252,12 +227,23 @@ This is the shape managed by `hooman configure`:
252
227
  "tools": {
253
228
  "allowed": []
254
229
  },
255
- "ltm": {
256
- "enabled": false,
257
- "chroma": {
258
- "url": "http://127.0.0.1:8000",
259
- "collection": {
260
- "memory": "memory"
230
+ "features": {
231
+ "fetch": {
232
+ "enabled": true
233
+ },
234
+ "filesystem": {
235
+ "enabled": true
236
+ },
237
+ "shell": {
238
+ "enabled": true
239
+ },
240
+ "ltm": {
241
+ "enabled": false,
242
+ "chroma": {
243
+ "url": "http://127.0.0.1:8000",
244
+ "collection": {
245
+ "memory": "memory"
246
+ }
261
247
  }
262
248
  }
263
249
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hoomanjs",
3
- "version": "1.9.0",
3
+ "version": "1.10.0",
4
4
  "description": "Bun-powered local AI agent CLI with chat, exec, ACP, MCP, and skills support.",
5
5
  "author": {
6
6
  "name": "Vaibhav Pandey",
@@ -16,8 +16,6 @@ import {
16
16
  } from "@agentclientprotocol/sdk";
17
17
  import type { Agent as StrandsAgent } from "@strands-agents/sdk";
18
18
  import {
19
- AfterToolCallEvent,
20
- AgentResultEvent,
21
19
  BeforeToolCallEvent,
22
20
  isModelStreamEvent,
23
21
  Message,
@@ -27,7 +25,6 @@ import {
27
25
  import type { StopReason as StrandsStopReason } from "@strands-agents/sdk";
28
26
  import { bootstrap } from "../core/index.ts";
29
27
  import { runWithCwd } from "../core/utils/cwd-context.ts";
30
- import type { Toolkit } from "../core/toolkit.ts";
31
28
  import { acpSessionsRootPath } from "./utils/paths.ts";
32
29
  import { inferToolKind } from "./utils/tool-kind.ts";
33
30
  import { toolResultToAcpContent } from "./utils/tool-result-content.ts";
@@ -172,13 +169,11 @@ export class AcpAgent implements AgentContract {
172
169
  readonly #connection: AgentSideConnection;
173
170
  readonly #sessions = new Map<string, SessionRecord>();
174
171
  readonly #acpRoot: string;
175
- readonly #toolkit: Toolkit;
176
172
  #version: string | null = null;
177
173
 
178
- constructor(connection: AgentSideConnection, toolkit: Toolkit) {
174
+ constructor(connection: AgentSideConnection) {
179
175
  this.#connection = connection;
180
176
  this.#acpRoot = acpSessionsRootPath();
181
- this.#toolkit = toolkit;
182
177
  queueMicrotask(() => {
183
178
  if (connection.signal.aborted) {
184
179
  void this.#disposeAllSessions();
@@ -342,7 +337,6 @@ export class AcpAgent implements AgentContract {
342
337
  {
343
338
  userId: bootstrapUserId,
344
339
  sessionId,
345
- toolkit: this.#toolkit,
346
340
  mcpServers,
347
341
  ...(clientSystemPrompt ? { systemPrompt: clientSystemPrompt } : {}),
348
342
  },
@@ -440,7 +434,6 @@ export class AcpAgent implements AgentContract {
440
434
  {
441
435
  userId: bootstrapUserId,
442
436
  sessionId: params.sessionId,
443
- toolkit: this.#toolkit,
444
437
  mcpServers,
445
438
  ...(clientSystemPrompt ? { systemPrompt: clientSystemPrompt } : {}),
446
439
  },
@@ -804,13 +797,13 @@ export class AcpAgent implements AgentContract {
804
797
  }
805
798
  }
806
799
 
807
- export async function runAcpStdio(toolkit: Toolkit = "full"): Promise<void> {
800
+ export async function runAcpStdio(): Promise<void> {
808
801
  const stream = ndJsonStream(
809
802
  Writable.toWeb(stdout) as unknown as WritableStream<Uint8Array>,
810
803
  Readable.toWeb(stdin) as unknown as ReadableStream<Uint8Array>,
811
804
  );
812
805
  const connection = new AgentSideConnection(
813
- (conn) => new AcpAgent(conn, toolkit),
806
+ (conn) => new AcpAgent(conn),
814
807
  stream,
815
808
  );
816
809
  await connection.closed;
@@ -45,11 +45,14 @@ export function applySessionConfigOption(
45
45
  }
46
46
  const chroma = config.ltm.chroma;
47
47
  config.update({
48
- ltm: {
49
- enabled: value === "on",
50
- chroma: {
51
- url: chroma.url,
52
- collection: { memory: chroma.collection.memory },
48
+ features: {
49
+ ...config.features,
50
+ ltm: {
51
+ enabled: value === "on",
52
+ chroma: {
53
+ url: chroma.url,
54
+ collection: { memory: chroma.collection.memory },
55
+ },
53
56
  },
54
57
  },
55
58
  });
package/src/cli.ts CHANGED
@@ -1,10 +1,8 @@
1
1
  #!/usr/bin/env bun
2
2
 
3
- import { Command, Option } from "commander";
3
+ import { Command } from "commander";
4
4
  import { BeforeToolCallEvent } from "@strands-agents/sdk";
5
5
  import { bootstrap } from "./core/index.ts";
6
- import { TOOLKITS } from "./core/toolkit.ts";
7
- import type { Toolkit } from "./core/toolkit.ts";
8
6
  import { createToolApprovalHandler } from "./exec/approvals.ts";
9
7
  import { chat } from "./chat/index.tsx";
10
8
  import { configure } from "./configure/index.tsx";
@@ -37,15 +35,6 @@ async function readPackageMeta(): Promise<{
37
35
  };
38
36
  }
39
37
 
40
- function createToolkitOption(): Option {
41
- return new Option(
42
- "-t, --toolkit <toolkit>",
43
- "Toolkit size to enable: lite, full, or max.",
44
- )
45
- .choices([...TOOLKITS])
46
- .default("full");
47
- }
48
-
49
38
  const packageMeta = await readPackageMeta();
50
39
 
51
40
  const program = new Command()
@@ -60,21 +49,14 @@ program
60
49
  .argument("<prompt>", "Prompt to run once.")
61
50
  .option("-s, --session <id>", "Session ID to use.")
62
51
  .option("--yolo", "Allow all tools without prompting for approval.")
63
- .addOption(createToolkitOption())
64
52
  .action(
65
- async (
66
- prompt: string,
67
- options: { session?: string; toolkit?: Toolkit; yolo?: boolean },
68
- ) => {
53
+ async (prompt: string, options: { session?: string; yolo?: boolean }) => {
69
54
  const sessionId = options.session?.trim() || crypto.randomUUID();
70
55
  const {
71
56
  config,
72
57
  agent,
73
58
  mcp: { manager },
74
- } = await bootstrap(
75
- { sessionId, toolkit: options.toolkit ?? "full" },
76
- true,
77
- );
59
+ } = await bootstrap({ sessionId }, true);
78
60
  agent.addHook(
79
61
  BeforeToolCallEvent,
80
62
  createToolApprovalHandler(config, { yolo: Boolean(options.yolo) }),
@@ -95,11 +77,10 @@ program
95
77
  .argument("[prompt]", "Optional initial prompt to run after startup.")
96
78
  .option("-s, --session <id>", "Session ID to use.")
97
79
  .option("--yolo", "Allow all tools without prompting for approval.")
98
- .addOption(createToolkitOption())
99
80
  .action(
100
81
  async (
101
82
  prompt: string | undefined,
102
- options: { session?: string; toolkit?: Toolkit; yolo?: boolean },
83
+ options: { session?: string; yolo?: boolean },
103
84
  ) => {
104
85
  const sessionId = options.session?.trim() || crypto.randomUUID();
105
86
  const {
@@ -107,10 +88,7 @@ program
107
88
  agent,
108
89
  mcp: { manager },
109
90
  registry,
110
- } = await bootstrap(
111
- { sessionId, toolkit: options.toolkit ?? "full" },
112
- false,
113
- );
91
+ } = await bootstrap({ sessionId }, false);
114
92
 
115
93
  try {
116
94
  await chat({
@@ -142,11 +120,9 @@ program
142
120
  "Log each MCP channel notification payload to the console.",
143
121
  )
144
122
  .option("--yolo", "Allow all tools without remote approval or prompts.")
145
- .addOption(createToolkitOption())
146
123
  .action(
147
124
  async (options: {
148
125
  session?: string;
149
- toolkit?: Toolkit;
150
126
  channels?: boolean;
151
127
  debug?: boolean;
152
128
  yolo?: boolean;
@@ -160,7 +136,6 @@ program
160
136
  {
161
137
  sessionId: session,
162
138
  userId: session,
163
- toolkit: options.toolkit ?? "full",
164
139
  },
165
140
  true,
166
141
  );
@@ -198,9 +173,8 @@ program
198
173
  .description(
199
174
  "Run as an Agent Client Protocol (ACP) agent on stdio for ACP-compatible clients.",
200
175
  )
201
- .addOption(createToolkitOption())
202
- .action(async (options: { toolkit?: Toolkit }) => {
203
- await runAcpStdio(options.toolkit ?? "full");
176
+ .action(async () => {
177
+ await runAcpStdio();
204
178
  });
205
179
 
206
180
  if (process.argv.slice(2).length === 0) {
@@ -131,7 +131,7 @@ export function ConfigureApp({
131
131
  name: config.name,
132
132
  llm: config.llm,
133
133
  tools: config.tools,
134
- ltm: config.ltm,
134
+ features: config.features,
135
135
  compaction: config.compaction,
136
136
  }) satisfies ConfigData,
137
137
  [config, revision],
@@ -445,27 +445,81 @@ export function ConfigureApp({
445
445
  }),
446
446
  },
447
447
  {
448
- label: `Long-term memory • ${configData.ltm.enabled ? "Enabled" : "Disabled"}`,
448
+ label: `Fetch feature • ${configData.features.fetch.enabled ? "Enabled" : "Disabled"}`,
449
449
  value: () => {
450
450
  updateConfig(
451
451
  {
452
- ltm: {
453
- ...config.ltm,
454
- enabled: !configData.ltm.enabled,
452
+ features: {
453
+ ...config.features,
454
+ fetch: {
455
+ enabled: !configData.features.fetch.enabled,
456
+ },
457
+ },
458
+ },
459
+ `Fetch feature ${configData.features.fetch.enabled ? "disabled" : "enabled"}.`,
460
+ );
461
+ setScreen({ kind: "config" });
462
+ },
463
+ },
464
+ {
465
+ label: `Filesystem feature • ${configData.features.filesystem.enabled ? "Enabled" : "Disabled"}`,
466
+ value: () => {
467
+ updateConfig(
468
+ {
469
+ features: {
470
+ ...config.features,
471
+ filesystem: {
472
+ enabled: !configData.features.filesystem.enabled,
473
+ },
474
+ },
475
+ },
476
+ `Filesystem feature ${configData.features.filesystem.enabled ? "disabled" : "enabled"}.`,
477
+ );
478
+ setScreen({ kind: "config" });
479
+ },
480
+ },
481
+ {
482
+ label: `Shell feature • ${configData.features.shell.enabled ? "Enabled" : "Disabled"}`,
483
+ value: () => {
484
+ updateConfig(
485
+ {
486
+ features: {
487
+ ...config.features,
488
+ shell: {
489
+ enabled: !configData.features.shell.enabled,
490
+ },
491
+ },
492
+ },
493
+ `Shell feature ${configData.features.shell.enabled ? "disabled" : "enabled"}.`,
494
+ );
495
+ setScreen({ kind: "config" });
496
+ },
497
+ },
498
+ {
499
+ label: `Long-term memory • ${configData.features.ltm.enabled ? "Enabled" : "Disabled"}`,
500
+ value: () => {
501
+ updateConfig(
502
+ {
503
+ features: {
504
+ ...config.features,
505
+ ltm: {
506
+ ...config.features.ltm,
507
+ enabled: !configData.features.ltm.enabled,
508
+ },
455
509
  },
456
510
  },
457
- `Long-term memory ${configData.ltm.enabled ? "disabled" : "enabled"}.`,
511
+ `Long-term memory ${configData.features.ltm.enabled ? "disabled" : "enabled"}.`,
458
512
  );
459
513
  setScreen({ kind: "config" });
460
514
  },
461
515
  },
462
516
  {
463
- label: `Chroma URL • ${configData.ltm.chroma.url}`,
517
+ label: `Chroma URL • ${configData.features.ltm.chroma.url}`,
464
518
  value: () =>
465
519
  promptValue({
466
520
  title: "Update Chroma URL",
467
521
  label: "URL",
468
- initialValue: configData.ltm.chroma.url,
522
+ initialValue: configData.features.ltm.chroma.url,
469
523
  onSubmit: async (value) => {
470
524
  const url = value.trim();
471
525
  if (!url) {
@@ -473,11 +527,14 @@ export function ConfigureApp({
473
527
  }
474
528
  updateConfig(
475
529
  {
476
- ltm: {
477
- ...config.ltm,
478
- chroma: {
479
- ...config.ltm.chroma,
480
- url,
530
+ features: {
531
+ ...config.features,
532
+ ltm: {
533
+ ...config.features.ltm,
534
+ chroma: {
535
+ ...config.features.ltm.chroma,
536
+ url,
537
+ },
481
538
  },
482
539
  },
483
540
  },
@@ -488,12 +545,12 @@ export function ConfigureApp({
488
545
  }),
489
546
  },
490
547
  {
491
- label: `Chroma memory collection • ${configData.ltm.chroma.collection.memory}`,
548
+ label: `Chroma memory collection • ${configData.features.ltm.chroma.collection.memory}`,
492
549
  value: () =>
493
550
  promptValue({
494
551
  title: "Update Chroma memory collection",
495
552
  label: "Collection name",
496
- initialValue: configData.ltm.chroma.collection.memory,
553
+ initialValue: configData.features.ltm.chroma.collection.memory,
497
554
  onSubmit: async (value) => {
498
555
  const memory = value.trim();
499
556
  if (!memory) {
@@ -501,11 +558,14 @@ export function ConfigureApp({
501
558
  }
502
559
  updateConfig(
503
560
  {
504
- ltm: {
505
- ...config.ltm,
506
- chroma: {
507
- ...config.ltm.chroma,
508
- collection: { memory },
561
+ features: {
562
+ ...config.features,
563
+ ltm: {
564
+ ...config.features.ltm,
565
+ chroma: {
566
+ ...config.features.ltm.chroma,
567
+ collection: { memory },
568
+ },
509
569
  },
510
570
  },
511
571
  },
@@ -1,11 +1,7 @@
1
1
  import { Agent } from "@strands-agents/sdk";
2
2
  import type { Config } from "../config.ts";
3
3
  import { modelProviders } from "../models";
4
- import {
5
- type Config as McpConfig,
6
- type Manager as McpManager,
7
- createMcpTools,
8
- } from "../mcp";
4
+ import { type Config as McpConfig, type Manager as McpManager } from "../mcp";
9
5
  import type { System as SystemPrompt } from "../prompts";
10
6
  import { skills as createSkillsPrompt } from "../prompts";
11
7
  import {
@@ -14,7 +10,6 @@ import {
14
10
  createLongTermMemoryTools,
15
11
  } from "../memory";
16
12
  import type { Registry } from "../skills";
17
- import { createSkillsTools } from "../skills";
18
13
  import {
19
14
  createFetchTools,
20
15
  createFilesystemTools,
@@ -22,8 +17,6 @@ import {
22
17
  createThinkingTools,
23
18
  createTimeTools,
24
19
  } from "../tools";
25
- import { toolkitAtLeast } from "../toolkit.ts";
26
- import type { Toolkit } from "../toolkit.ts";
27
20
 
28
21
  const SECTION_BREAK = "\n\n---\n\n";
29
22
 
@@ -37,15 +30,15 @@ export async function create(
37
30
  userId?: string;
38
31
  sessionId?: string;
39
32
  systemPrompt?: string;
40
- toolkit?: Toolkit;
41
33
  },
42
34
  ): Promise<Agent> {
43
35
  const sessionId = meta.sessionId;
44
36
  const userId = meta.userId ?? sessionId;
45
- const toolkit = meta.toolkit ?? "full";
46
37
  const llm = await modelProviders[config.llm.provider]!();
47
38
  const stm = createShortTermMemory(sessionId);
48
- const ltm = config.ltm.enabled ? createLongTermMemoryStore(config) : null;
39
+ const ltm = config.features.ltm.enabled
40
+ ? createLongTermMemoryStore(config)
41
+ : null;
49
42
  const skills = await createSkillsPrompt(registry);
50
43
  const tools = await mcp.manager.listPrefixedTools();
51
44
  const append = await mcp.manager.listServerInstructions();
@@ -62,13 +55,11 @@ export async function create(
62
55
  },
63
56
  tools: [
64
57
  ...createTimeTools(),
65
- ...createFetchTools(),
58
+ ...(config.features.fetch.enabled ? createFetchTools() : []),
66
59
  ...(ltm ? createLongTermMemoryTools(ltm) : []),
67
- ...(toolkitAtLeast(toolkit, "full") ? createFilesystemTools() : []), // > lite
68
- ...(toolkitAtLeast(toolkit, "full") ? createShellTools() : []),
69
- ...(toolkitAtLeast(toolkit, "full") ? createThinkingTools() : []),
70
- ...(toolkit === "max" ? createSkillsTools(registry) : []),
71
- ...(toolkit === "max" ? createMcpTools(mcp.config) : []),
60
+ ...(config.features.filesystem.enabled ? createFilesystemTools() : []),
61
+ ...(config.features.shell.enabled ? createShellTools() : []),
62
+ ...createThinkingTools(),
72
63
  ...tools,
73
64
  ],
74
65
  printer: print,
@@ -48,35 +48,70 @@ const LtmPartialSchema = z.object({
48
48
  chroma: ChromaPartialSchema.optional(),
49
49
  });
50
50
 
51
+ const FeatureTogglePartialSchema = z.object({
52
+ enabled: z.boolean().optional(),
53
+ });
54
+
55
+ const FeaturesPartialSchema = z.object({
56
+ fetch: FeatureTogglePartialSchema.optional(),
57
+ filesystem: FeatureTogglePartialSchema.optional(),
58
+ shell: FeatureTogglePartialSchema.optional(),
59
+ ltm: LtmPartialSchema.optional(),
60
+ });
61
+
51
62
  const ToolsPartialSchema = z.object({
52
63
  allowed: z.array(z.string().min(1)).default([]),
53
64
  });
54
65
 
55
- const ConfigSchema = z.object({
56
- name: z.string().min(1),
57
- llm: LlmSchema,
58
- tools: ToolsPartialSchema.default({ allowed: [] }),
59
- ltm: LtmPartialSchema.nullish().transform((ltm) => ({
60
- enabled: ltm?.enabled ?? false,
61
- chroma: {
62
- url: ltm?.chroma?.url ?? DEFAULT_CHROMA.url,
63
- collection: {
64
- memory:
65
- ltm?.chroma?.collection?.memory ?? DEFAULT_CHROMA.collection.memory,
66
+ const ConfigSchema = z
67
+ .object({
68
+ name: z.string().min(1),
69
+ llm: LlmSchema,
70
+ tools: ToolsPartialSchema.default({ allowed: [] }),
71
+ features: FeaturesPartialSchema.nullish(),
72
+ compaction: CompactionPartialSchema.nullish().transform((c) => ({
73
+ ratio: c?.ratio ?? DEFAULT_COMPACTION.ratio,
74
+ keep: c?.keep ?? DEFAULT_COMPACTION.keep,
75
+ })),
76
+ })
77
+ .transform((input) => {
78
+ const ltm = input.features?.ltm;
79
+ return {
80
+ name: input.name,
81
+ llm: input.llm,
82
+ tools: input.tools,
83
+ features: {
84
+ fetch: {
85
+ enabled: input.features?.fetch?.enabled ?? true,
86
+ },
87
+ filesystem: {
88
+ enabled: input.features?.filesystem?.enabled ?? true,
89
+ },
90
+ shell: {
91
+ enabled: input.features?.shell?.enabled ?? true,
92
+ },
93
+ ltm: {
94
+ enabled: ltm?.enabled ?? false,
95
+ chroma: {
96
+ url: ltm?.chroma?.url ?? DEFAULT_CHROMA.url,
97
+ collection: {
98
+ memory:
99
+ ltm?.chroma?.collection?.memory ??
100
+ DEFAULT_CHROMA.collection.memory,
101
+ },
102
+ },
103
+ },
66
104
  },
67
- },
68
- })),
69
- compaction: CompactionPartialSchema.nullish().transform((c) => ({
70
- ratio: c?.ratio ?? DEFAULT_COMPACTION.ratio,
71
- keep: c?.keep ?? DEFAULT_COMPACTION.keep,
72
- })),
73
- });
105
+ compaction: input.compaction,
106
+ };
107
+ });
74
108
 
75
109
  export type ConfigData = z.infer<typeof ConfigSchema>;
76
110
  export type LlmConfig = z.infer<typeof LlmSchema>;
77
111
  export type CompactionConfig = ConfigData["compaction"];
78
- export type LtmConfig = ConfigData["ltm"];
112
+ export type LtmConfig = ConfigData["features"]["ltm"];
79
113
  export type ToolsConfig = ConfigData["tools"];
114
+ export type FeaturesConfig = ConfigData["features"];
80
115
 
81
116
  const defaultConfigData = (): ConfigData => ({
82
117
  name: "Hooman",
@@ -88,11 +123,22 @@ const defaultConfigData = (): ConfigData => ({
88
123
  tools: {
89
124
  allowed: [],
90
125
  },
91
- ltm: {
92
- enabled: false,
93
- chroma: {
94
- url: "http://127.0.0.1:8000",
95
- collection: { memory: "memory" },
126
+ features: {
127
+ fetch: {
128
+ enabled: true,
129
+ },
130
+ filesystem: {
131
+ enabled: true,
132
+ },
133
+ shell: {
134
+ enabled: true,
135
+ },
136
+ ltm: {
137
+ enabled: false,
138
+ chroma: {
139
+ url: "http://127.0.0.1:8000",
140
+ collection: { memory: "memory" },
141
+ },
96
142
  },
97
143
  },
98
144
  compaction: {
@@ -129,8 +175,24 @@ export class Config {
129
175
  return this.data.compaction;
130
176
  }
131
177
 
178
+ get features(): FeaturesConfig {
179
+ return {
180
+ ...this.data.features,
181
+ fetch: { ...this.data.features.fetch },
182
+ filesystem: { ...this.data.features.filesystem },
183
+ shell: { ...this.data.features.shell },
184
+ ltm: {
185
+ ...this.data.features.ltm,
186
+ chroma: {
187
+ ...this.data.features.ltm.chroma,
188
+ collection: { ...this.data.features.ltm.chroma.collection },
189
+ },
190
+ },
191
+ };
192
+ }
193
+
132
194
  get ltm(): LtmConfig {
133
- return this.data.ltm;
195
+ return this.features.ltm;
134
196
  }
135
197
 
136
198
  private readJson(): unknown {
package/src/core/index.ts CHANGED
@@ -11,7 +11,6 @@ import {
11
11
  import { createSkillsRegistry } from "./skills/index.ts";
12
12
  import type { Registry } from "./skills/index.ts";
13
13
  import { system as createSystemPrompt } from "./prompts/index.ts";
14
- import type { Toolkit } from "./toolkit.ts";
15
14
  import {
16
15
  basePath,
17
16
  configJsonPath,
@@ -25,7 +24,6 @@ export async function bootstrap(
25
24
  sessionId?: string;
26
25
  systemPrompt?: string;
27
26
  mcpServers?: NamedMcpTransport[];
28
- toolkit?: Toolkit;
29
27
  },
30
28
  print: boolean = false,
31
29
  ): Promise<{
@@ -39,17 +37,11 @@ export async function bootstrap(
39
37
  const mcpManager = createMcpManager(mcpConfig, meta.mcpServers ?? []);
40
38
  const mcp = { config: mcpConfig, manager: mcpManager };
41
39
  const registry = createSkillsRegistry(basePath());
42
- const toolkit = meta.toolkit ?? "max";
43
- const system = await createSystemPrompt(
44
- instructionsMdPath(),
45
- config,
46
- toolkit,
47
- );
40
+ const system = await createSystemPrompt(instructionsMdPath(), config);
48
41
  const agent = await createAgent(config, system, registry, mcp, print, {
49
42
  userId: meta?.userId ?? meta?.sessionId,
50
43
  sessionId: meta?.sessionId,
51
44
  systemPrompt: meta?.systemPrompt,
52
- toolkit,
53
45
  });
54
46
  return { config, agent, mcp, registry };
55
47
  }
@@ -1,17 +1,12 @@
1
1
  import type { Config } from "../config.ts";
2
2
  import type { Registry } from "../skills/registry.ts";
3
- import type { Toolkit } from "../toolkit.ts";
4
3
  import { Skills } from "./skills.ts";
5
4
  import { System } from "./system.ts";
6
5
 
7
6
  export { Skills, System };
8
7
 
9
- export async function system(
10
- path: string,
11
- config: Config,
12
- toolkit: Toolkit,
13
- ): Promise<System> {
14
- const prompt = new System(path, config, toolkit);
8
+ export async function system(path: string, config: Config): Promise<System> {
9
+ const prompt = new System(path, config);
15
10
  await prompt.reload();
16
11
  return prompt;
17
12
  }
@@ -3,8 +3,6 @@ import { dirname, join } from "node:path";
3
3
  import { fileURLToPath } from "node:url";
4
4
  import { compile } from "handlebars";
5
5
  import type { Config } from "../config.ts";
6
- import type { Toolkit } from "../toolkit.ts";
7
- import { toolkitAtLeast } from "../toolkit.ts";
8
6
 
9
7
  /** Bundled markdown next to this module (`prompts/static/`). */
10
8
  const STATIC_PROMPT_FILES = [
@@ -26,26 +24,25 @@ const SECTION_BREAK = "\n\n---\n\n";
26
24
  export class System {
27
25
  private readonly path: string;
28
26
  private readonly config: Config;
29
- private readonly toolkit: Toolkit;
30
27
  private data = "";
31
28
 
32
- public constructor(path: string, config: Config, toolkit: Toolkit) {
29
+ public constructor(path: string, config: Config) {
33
30
  this.path = path;
34
31
  this.config = config;
35
- this.toolkit = toolkit;
36
32
  }
37
33
 
38
34
  private staticPromptFiles(): readonly (typeof STATIC_PROMPT_FILES)[number][] {
39
35
  return STATIC_PROMPT_FILES.filter((file) => {
40
36
  switch (file) {
41
37
  case "ltm.md":
42
- return this.config.ltm.enabled;
38
+ return this.config.features.ltm.enabled;
39
+ case "fetch.md":
40
+ return this.config.features.fetch.enabled;
43
41
  case "filesystem.md":
44
- case "thinking.md":
42
+ return this.config.features.filesystem.enabled;
45
43
  case "shell.md":
46
- return toolkitAtLeast(this.toolkit, "full");
47
- case "skills.md":
48
- return this.toolkit === "max";
44
+ return this.config.features.shell.enabled;
45
+ case "thinking.md":
49
46
  default:
50
47
  return true;
51
48
  }
@@ -96,7 +93,7 @@ export class System {
96
93
  return {
97
94
  name: this.config.name,
98
95
  llm: this.config.llm,
99
- ltm: this.config.ltm,
96
+ ltm: this.config.features.ltm,
100
97
  compaction: this.config.compaction,
101
98
  };
102
99
  }
@@ -1,13 +0,0 @@
1
- export const TOOLKITS = ["lite", "full", "max"] as const;
2
-
3
- export type Toolkit = (typeof TOOLKITS)[number];
4
-
5
- const TOOLKIT_RANK: Record<Toolkit, number> = {
6
- lite: 0,
7
- full: 1,
8
- max: 2,
9
- };
10
-
11
- export function toolkitAtLeast(actual: Toolkit, minimum: Toolkit): boolean {
12
- return TOOLKIT_RANK[actual] >= TOOLKIT_RANK[minimum];
13
- }