@code-yeongyu/senpi 2026.5.13 → 2026.5.15

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 (156) hide show
  1. package/CHANGELOG.md +1105 -1063
  2. package/dist/core/agent-session.d.ts.map +1 -1
  3. package/dist/core/agent-session.js +12 -5
  4. package/dist/core/agent-session.js.map +1 -1
  5. package/dist/core/bash-executor.d.ts.map +1 -1
  6. package/dist/core/bash-executor.js +1 -1
  7. package/dist/core/bash-executor.js.map +1 -1
  8. package/dist/core/compaction/compaction.d.ts.map +1 -1
  9. package/dist/core/compaction/compaction.js +2 -2
  10. package/dist/core/compaction/compaction.js.map +1 -1
  11. package/dist/core/export-html/index.d.ts.map +1 -1
  12. package/dist/core/export-html/index.js +8 -1
  13. package/dist/core/export-html/index.js.map +1 -1
  14. package/dist/core/extensions/builtin/anthropic-web-search/index.d.ts.map +1 -1
  15. package/dist/core/extensions/builtin/anthropic-web-search/index.js +20 -0
  16. package/dist/core/extensions/builtin/anthropic-web-search/index.js.map +1 -1
  17. package/dist/core/extensions/builtin/background-task/notification.d.ts +1 -1
  18. package/dist/core/extensions/builtin/background-task/notification.d.ts.map +1 -1
  19. package/dist/core/extensions/builtin/background-task/notification.js.map +1 -1
  20. package/dist/core/extensions/builtin/background-task/types.d.ts +2 -2
  21. package/dist/core/extensions/builtin/background-task/types.d.ts.map +1 -1
  22. package/dist/core/extensions/builtin/background-task/types.js +2 -2
  23. package/dist/core/extensions/builtin/background-task/types.js.map +1 -1
  24. package/dist/core/extensions/builtin/index.d.ts.map +1 -1
  25. package/dist/core/extensions/builtin/index.js +0 -18
  26. package/dist/core/extensions/builtin/index.js.map +1 -1
  27. package/dist/core/extensions/builtin/openai-web-search/index.d.ts.map +1 -1
  28. package/dist/core/extensions/builtin/openai-web-search/index.js +28 -0
  29. package/dist/core/extensions/builtin/openai-web-search/index.js.map +1 -1
  30. package/dist/core/extensions/builtin/system-messages.d.ts +6 -6
  31. package/dist/core/extensions/builtin/system-messages.d.ts.map +1 -1
  32. package/dist/core/extensions/builtin/system-messages.js +10 -10
  33. package/dist/core/extensions/builtin/system-messages.js.map +1 -1
  34. package/dist/core/extensions/builtin/todotools/continuation/prompt.d.ts +1 -1
  35. package/dist/core/extensions/builtin/todotools/continuation/prompt.d.ts.map +1 -1
  36. package/dist/core/extensions/builtin/todotools/continuation/prompt.js +1 -1
  37. package/dist/core/extensions/builtin/todotools/continuation/prompt.js.map +1 -1
  38. package/dist/core/extensions/builtin/todotools/state.d.ts +1 -1
  39. package/dist/core/extensions/builtin/todotools/state.d.ts.map +1 -1
  40. package/dist/core/extensions/builtin/todotools/state.js +2 -2
  41. package/dist/core/extensions/builtin/todotools/state.js.map +1 -1
  42. package/dist/core/extensions/builtin/todotools/system-messages.d.ts +3 -3
  43. package/dist/core/extensions/builtin/todotools/system-messages.d.ts.map +1 -1
  44. package/dist/core/extensions/builtin/todotools/system-messages.js +6 -6
  45. package/dist/core/extensions/builtin/todotools/system-messages.js.map +1 -1
  46. package/dist/core/resource-loader.d.ts.map +1 -1
  47. package/dist/core/resource-loader.js +0 -9
  48. package/dist/core/resource-loader.js.map +1 -1
  49. package/dist/core/sdk.d.ts +1 -1
  50. package/dist/core/sdk.d.ts.map +1 -1
  51. package/dist/core/sdk.js +1 -1
  52. package/dist/core/sdk.js.map +1 -1
  53. package/dist/core/session-manager.d.ts.map +1 -1
  54. package/dist/core/session-manager.js.map +1 -1
  55. package/dist/core/tools/render-utils.d.ts.map +1 -1
  56. package/dist/core/tools/render-utils.js +1 -1
  57. package/dist/core/tools/render-utils.js.map +1 -1
  58. package/dist/main.d.ts.map +1 -1
  59. package/dist/main.js +3 -2
  60. package/dist/main.js.map +1 -1
  61. package/dist/modes/interactive/components/assistant-message.d.ts +0 -3
  62. package/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
  63. package/dist/modes/interactive/components/assistant-message.js +3 -22
  64. package/dist/modes/interactive/components/assistant-message.js.map +1 -1
  65. package/dist/modes/interactive/components/bash-execution.d.ts.map +1 -1
  66. package/dist/modes/interactive/components/bash-execution.js +1 -1
  67. package/dist/modes/interactive/components/bash-execution.js.map +1 -1
  68. package/dist/modes/interactive/components/extension-selector.d.ts +2 -0
  69. package/dist/modes/interactive/components/extension-selector.d.ts.map +1 -1
  70. package/dist/modes/interactive/components/extension-selector.js +6 -1
  71. package/dist/modes/interactive/components/extension-selector.js.map +1 -1
  72. package/dist/modes/interactive/interactive-mode.d.ts +12 -0
  73. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  74. package/dist/modes/interactive/interactive-mode.js +43 -5
  75. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  76. package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
  77. package/dist/modes/interactive/theme/theme.js +2 -2
  78. package/dist/modes/interactive/theme/theme.js.map +1 -1
  79. package/dist/modes/print-mode.d.ts.map +1 -1
  80. package/dist/modes/print-mode.js +3 -11
  81. package/dist/modes/print-mode.js.map +1 -1
  82. package/dist/modes/provider-native-rendering.d.ts +5 -0
  83. package/dist/modes/provider-native-rendering.d.ts.map +1 -0
  84. package/dist/modes/provider-native-rendering.js +247 -0
  85. package/dist/modes/provider-native-rendering.js.map +1 -0
  86. package/dist/utils/ansi.d.ts +2 -0
  87. package/dist/utils/ansi.d.ts.map +1 -0
  88. package/dist/utils/ansi.js +52 -0
  89. package/dist/utils/ansi.js.map +1 -0
  90. package/dist/utils/html.d.ts +7 -0
  91. package/dist/utils/html.d.ts.map +1 -0
  92. package/dist/utils/html.js +40 -0
  93. package/dist/utils/html.js.map +1 -0
  94. package/dist/utils/mime.d.ts +1 -0
  95. package/dist/utils/mime.d.ts.map +1 -1
  96. package/dist/utils/mime.js +59 -16
  97. package/dist/utils/mime.js.map +1 -1
  98. package/dist/utils/syntax-highlight.d.ts +12 -0
  99. package/dist/utils/syntax-highlight.d.ts.map +1 -0
  100. package/dist/utils/syntax-highlight.js +118 -0
  101. package/dist/utils/syntax-highlight.js.map +1 -0
  102. package/dist/utils/tools-manager.d.ts.map +1 -1
  103. package/dist/utils/tools-manager.js +76 -7
  104. package/dist/utils/tools-manager.js.map +1 -1
  105. package/docs/agents.md +1 -1
  106. package/docs/sdk.md +25 -43
  107. package/examples/sdk/01-minimal.ts +14 -10
  108. package/examples/sdk/02-custom-model.ts +12 -8
  109. package/examples/sdk/03-custom-prompt.ts +24 -16
  110. package/examples/sdk/04-skills.ts +2 -2
  111. package/examples/sdk/05-tools.ts +8 -4
  112. package/examples/sdk/06-extensions.ts +11 -7
  113. package/examples/sdk/07-context-files.ts +2 -2
  114. package/examples/sdk/08-prompt-templates.ts +2 -2
  115. package/examples/sdk/09-api-keys-and-oauth.ts +8 -4
  116. package/examples/sdk/10-settings.ts +4 -4
  117. package/examples/sdk/11-sessions.ts +4 -0
  118. package/examples/sdk/12-full-control.ts +11 -7
  119. package/examples/sdk/README.md +6 -9
  120. package/package.json +7 -12
  121. package/dist/core/extensions/builtin/anthropic-code-execution/index.d.ts +0 -7
  122. package/dist/core/extensions/builtin/anthropic-code-execution/index.d.ts.map +0 -1
  123. package/dist/core/extensions/builtin/anthropic-code-execution/index.js +0 -79
  124. package/dist/core/extensions/builtin/anthropic-code-execution/index.js.map +0 -1
  125. package/dist/core/extensions/builtin/anthropic-computer-use/index.d.ts +0 -53
  126. package/dist/core/extensions/builtin/anthropic-computer-use/index.d.ts.map +0 -1
  127. package/dist/core/extensions/builtin/anthropic-computer-use/index.js +0 -676
  128. package/dist/core/extensions/builtin/anthropic-computer-use/index.js.map +0 -1
  129. package/dist/core/extensions/builtin/anthropic-text-editor/index.d.ts +0 -25
  130. package/dist/core/extensions/builtin/anthropic-text-editor/index.d.ts.map +0 -1
  131. package/dist/core/extensions/builtin/anthropic-text-editor/index.js +0 -244
  132. package/dist/core/extensions/builtin/anthropic-text-editor/index.js.map +0 -1
  133. package/dist/core/extensions/builtin/anthropic-tool-search/index.d.ts +0 -6
  134. package/dist/core/extensions/builtin/anthropic-tool-search/index.d.ts.map +0 -1
  135. package/dist/core/extensions/builtin/anthropic-tool-search/index.js +0 -112
  136. package/dist/core/extensions/builtin/anthropic-tool-search/index.js.map +0 -1
  137. package/dist/core/extensions/builtin/google-code-execution/index.d.ts +0 -7
  138. package/dist/core/extensions/builtin/google-code-execution/index.d.ts.map +0 -1
  139. package/dist/core/extensions/builtin/google-code-execution/index.js +0 -73
  140. package/dist/core/extensions/builtin/google-code-execution/index.js.map +0 -1
  141. package/dist/core/extensions/builtin/google-google-search/index.d.ts +0 -7
  142. package/dist/core/extensions/builtin/google-google-search/index.d.ts.map +0 -1
  143. package/dist/core/extensions/builtin/google-google-search/index.js +0 -83
  144. package/dist/core/extensions/builtin/google-google-search/index.js.map +0 -1
  145. package/dist/core/extensions/builtin/google-url-context/index.d.ts +0 -7
  146. package/dist/core/extensions/builtin/google-url-context/index.d.ts.map +0 -1
  147. package/dist/core/extensions/builtin/google-url-context/index.js +0 -82
  148. package/dist/core/extensions/builtin/google-url-context/index.js.map +0 -1
  149. package/dist/core/extensions/builtin/openai-api-parallel-tool-calls/index.d.ts +0 -6
  150. package/dist/core/extensions/builtin/openai-api-parallel-tool-calls/index.d.ts.map +0 -1
  151. package/dist/core/extensions/builtin/openai-api-parallel-tool-calls/index.js +0 -57
  152. package/dist/core/extensions/builtin/openai-api-parallel-tool-calls/index.js.map +0 -1
  153. package/dist/core/extensions/builtin/openai-code-interpreter/index.d.ts +0 -10
  154. package/dist/core/extensions/builtin/openai-code-interpreter/index.d.ts.map +0 -1
  155. package/dist/core/extensions/builtin/openai-code-interpreter/index.js +0 -95
  156. package/dist/core/extensions/builtin/openai-code-interpreter/index.js.map +0 -1
package/docs/sdk.md CHANGED
@@ -54,7 +54,7 @@ The main factory function for a single `AgentSession`.
54
54
  `createAgentSession()` uses a `ResourceLoader` to supply extensions, skills, prompt templates, themes, and context files. If you do not provide one, it uses `DefaultResourceLoader` with standard discovery.
55
55
 
56
56
  ```typescript
57
- import { createAgentSession } from "@code-yeongyu/senpi";
57
+ import { createAgentSession, SessionManager } from "@code-yeongyu/senpi";
58
58
 
59
59
  // Minimal: defaults with DefaultResourceLoader
60
60
  const { session } = await createAgentSession();
@@ -62,7 +62,7 @@ const { session } = await createAgentSession();
62
62
  // Custom: override specific options
63
63
  const { session } = await createAgentSession({
64
64
  model: myModel,
65
- tools: [readTool, bashTool],
65
+ tools: ["read", "bash"],
66
66
  sessionManager: SessionManager.inMemory(),
67
67
  });
68
68
  ```
@@ -466,63 +466,51 @@ const { session } = await createAgentSession({ resourceLoader: loader });
466
466
 
467
467
  ### Tools
468
468
 
469
+ Specify which built-in tools to enable:
470
+
471
+ - Built-in tool names: `read`, `bash`, `edit`, `write`, `grep`, `find`, `ls`
472
+ - Default built-ins: `read`, `bash`, `edit`, `write`
473
+ - `noTools: "all"` disables all tools
474
+ - `noTools: "builtin"` disables default built-ins while keeping extension and custom tools enabled
475
+
469
476
  ```typescript
470
- import {
471
- codingTools, // read, bash, edit, write (default)
472
- readOnlyTools, // read, grep, find, ls
473
- readTool, bashTool, editTool, writeTool,
474
- grepTool, findTool, lsTool,
475
- } from "@code-yeongyu/senpi";
477
+ import { createAgentSession } from "@code-yeongyu/senpi";
476
478
 
477
- // Use built-in tool set
479
+ // Read-only mode
478
480
  const { session } = await createAgentSession({
479
- tools: readOnlyTools,
481
+ tools: ["read", "grep", "find", "ls"],
480
482
  });
481
483
 
482
484
  // Pick specific tools
483
485
  const { session } = await createAgentSession({
484
- tools: [readTool, bashTool, grepTool],
486
+ tools: ["read", "bash", "grep"],
485
487
  });
486
488
  ```
487
489
 
488
490
  #### Tools with Custom cwd
489
491
 
490
- **Important:** The pre-built tool instances (`readTool`, `bashTool`, etc.) use `process.cwd()` for path resolution. When you specify a custom `cwd` AND provide explicit `tools`, you must use the tool factory functions to ensure paths resolve correctly:
492
+ When you pass a custom `cwd`, `createAgentSession()` builds selected built-in tools for that cwd.
491
493
 
492
494
  ```typescript
493
- import {
494
- createCodingTools, // Creates [read, bash, edit, write] for specific cwd
495
- createReadOnlyTools, // Creates [read, grep, find, ls] for specific cwd
496
- createReadTool,
497
- createBashTool,
498
- createEditTool,
499
- createWriteTool,
500
- createGrepTool,
501
- createFindTool,
502
- createLsTool,
503
- } from "@code-yeongyu/senpi";
495
+ import { createAgentSession, SessionManager } from "@code-yeongyu/senpi";
504
496
 
505
497
  const cwd = "/path/to/project";
506
498
 
507
- // Use factory for tool sets
499
+ // Use default tools for custom cwd
508
500
  const { session } = await createAgentSession({
509
501
  cwd,
510
- tools: createCodingTools(cwd), // Tools resolve paths relative to cwd
502
+ sessionManager: SessionManager.inMemory(cwd),
511
503
  });
512
504
 
513
- // Or pick specific tools
505
+ // Or pick specific tools for custom cwd
514
506
  const { session } = await createAgentSession({
515
507
  cwd,
516
- tools: [createReadTool(cwd), createBashTool(cwd), createGrepTool(cwd)],
508
+ tools: ["read", "bash", "grep"],
509
+ sessionManager: SessionManager.inMemory(cwd),
517
510
  });
518
511
  ```
519
512
 
520
- **When you don't need factories:**
521
- - If you omit `tools`, senpi automatically creates them with the correct `cwd`
522
- - If you use `process.cwd()` as your `cwd`, the pre-built instances work fine
523
-
524
- **When you must use factories:**
525
- - When you specify both `cwd` (different from `process.cwd()`) AND `tools`
513
+ `createAgentSession()` automatically builds selected built-in tools for the provided `cwd`. Factory helpers such as `createReadTool()` and `createCodingTools()` remain exported for lower-level composition, but most SDK users should pass tool names.
526
514
 
527
515
  > See [examples/sdk/05-tools.ts](../examples/sdk/05-tools.ts)
528
516
 
@@ -556,6 +544,8 @@ Use `defineTool()` for standalone definitions and arrays like `customTools: [myT
556
544
 
557
545
  Custom tools passed via `customTools` are combined with extension-registered tools. Extensions loaded by the ResourceLoader can also register tools via `pi.registerTool()`.
558
546
 
547
+ If you pass `tools`, include each custom or extension tool name you want enabled, for example `tools: ["read", "bash", "my_tool"]`.
548
+
559
549
  > See [examples/sdk/05-tools.ts](../examples/sdk/05-tools.ts)
560
550
 
561
551
  ### Extensions
@@ -885,12 +875,10 @@ import { getModel } from "@earendil-works/pi-ai";
885
875
  import { Type } from "typebox";
886
876
  import {
887
877
  AuthStorage,
888
- bashTool,
889
878
  createAgentSession,
890
879
  DefaultResourceLoader,
891
880
  defineTool,
892
881
  ModelRegistry,
893
- readTool,
894
882
  SessionManager,
895
883
  SettingsManager,
896
884
  } from "@code-yeongyu/senpi";
@@ -944,7 +932,7 @@ const { session } = await createAgentSession({
944
932
  authStorage,
945
933
  modelRegistry,
946
934
 
947
- tools: [readTool, bashTool],
935
+ tools: ["read", "bash", "status"],
948
936
  customTools: [statusTool],
949
937
  resourceLoader: loader,
950
938
 
@@ -1123,13 +1111,7 @@ defineTool
1123
1111
  SessionManager
1124
1112
  SettingsManager
1125
1113
 
1126
- // Built-in tools (use process.cwd())
1127
- codingTools
1128
- readOnlyTools
1129
- readTool, bashTool, editTool, writeTool
1130
- grepTool, findTool, lsTool
1131
-
1132
- // Tool factories (for custom cwd)
1114
+ // Tool factories
1133
1115
  createCodingTools
1134
1116
  createReadOnlyTools
1135
1117
  createReadTool, createBashTool, createEditTool, createWriteTool
@@ -9,14 +9,18 @@ import { createAgentSession } from "@code-yeongyu/senpi";
9
9
 
10
10
  const { session } = await createAgentSession();
11
11
 
12
- session.subscribe((event) => {
13
- if (event.type === "message_update" && event.assistantMessageEvent.type === "text_delta") {
14
- process.stdout.write(event.assistantMessageEvent.delta);
15
- }
16
- });
12
+ try {
13
+ session.subscribe((event) => {
14
+ if (event.type === "message_update" && event.assistantMessageEvent.type === "text_delta") {
15
+ process.stdout.write(event.assistantMessageEvent.delta);
16
+ }
17
+ });
17
18
 
18
- await session.prompt("What files are in the current directory?");
19
- session.state.messages.forEach((msg) => {
20
- console.log(msg);
21
- });
22
- console.log();
19
+ await session.prompt("What files are in the current directory?");
20
+ session.state.messages.forEach((msg) => {
21
+ console.log(msg);
22
+ });
23
+ console.log();
24
+ } finally {
25
+ session.dispose();
26
+ }
@@ -38,12 +38,16 @@ if (available.length > 0) {
38
38
  modelRegistry,
39
39
  });
40
40
 
41
- session.subscribe((event) => {
42
- if (event.type === "message_update" && event.assistantMessageEvent.type === "text_delta") {
43
- process.stdout.write(event.assistantMessageEvent.delta);
44
- }
45
- });
46
-
47
- await session.prompt("Say hello in one sentence.");
48
- console.log();
41
+ try {
42
+ session.subscribe((event) => {
43
+ if (event.type === "message_update" && event.assistantMessageEvent.type === "text_delta") {
44
+ process.stdout.write(event.assistantMessageEvent.delta);
45
+ }
46
+ });
47
+
48
+ await session.prompt("Say hello in one sentence.");
49
+ console.log();
50
+ } finally {
51
+ session.dispose();
52
+ }
49
53
  }
@@ -30,15 +30,19 @@ const { session: session1 } = await createAgentSession({
30
30
  sessionManager: SessionManager.inMemory(),
31
31
  });
32
32
 
33
- session1.subscribe((event) => {
34
- if (event.type === "message_update" && event.assistantMessageEvent.type === "text_delta") {
35
- process.stdout.write(event.assistantMessageEvent.delta);
36
- }
37
- });
33
+ try {
34
+ session1.subscribe((event) => {
35
+ if (event.type === "message_update" && event.assistantMessageEvent.type === "text_delta") {
36
+ process.stdout.write(event.assistantMessageEvent.delta);
37
+ }
38
+ });
38
39
 
39
- console.log("=== Replace prompt ===");
40
- await session1.prompt("What is 2 + 2?");
41
- console.log("\n");
40
+ console.log("=== Replace prompt ===");
41
+ await session1.prompt("What is 2 + 2?");
42
+ console.log("\n");
43
+ } finally {
44
+ session1.dispose();
45
+ }
42
46
 
43
47
  // Option 2: Append AGENTS-style instructions to the defaults
44
48
  const loader2 = new DefaultResourceLoader({
@@ -61,12 +65,16 @@ const { session: session2 } = await createAgentSession({
61
65
  sessionManager: SessionManager.inMemory(),
62
66
  });
63
67
 
64
- session2.subscribe((event) => {
65
- if (event.type === "message_update" && event.assistantMessageEvent.type === "text_delta") {
66
- process.stdout.write(event.assistantMessageEvent.delta);
67
- }
68
- });
68
+ try {
69
+ session2.subscribe((event) => {
70
+ if (event.type === "message_update" && event.assistantMessageEvent.type === "text_delta") {
71
+ process.stdout.write(event.assistantMessageEvent.delta);
72
+ }
73
+ });
69
74
 
70
- console.log("=== Modify prompt ===");
71
- await session2.prompt("List 3 benefits of TypeScript.");
72
- console.log();
75
+ console.log("=== Modify prompt ===");
76
+ await session2.prompt("List 3 benefits of TypeScript.");
77
+ console.log();
78
+ } finally {
79
+ session2.dispose();
80
+ }
@@ -47,9 +47,9 @@ if (diagnostics.length > 0) {
47
47
  console.log("Warnings:", diagnostics);
48
48
  }
49
49
 
50
- await createAgentSession({
50
+ const { session } = await createAgentSession({
51
51
  resourceLoader: loader,
52
52
  sessionManager: SessionManager.inMemory(),
53
53
  });
54
-
55
54
  console.log("Session created with filtered skills");
55
+ session.dispose();
@@ -13,32 +13,36 @@
13
13
  import { createAgentSession, SessionManager } from "@code-yeongyu/senpi";
14
14
 
15
15
  // Read-only mode (no edit/write)
16
- await createAgentSession({
16
+ const { session: readOnlySession } = await createAgentSession({
17
17
  tools: ["read", "grep", "find", "ls"],
18
18
  sessionManager: SessionManager.inMemory(),
19
19
  });
20
20
  console.log("Read-only session created");
21
+ readOnlySession.dispose();
21
22
 
22
23
  // Custom tool selection
23
- await createAgentSession({
24
+ const { session: customToolsSession } = await createAgentSession({
24
25
  tools: ["read", "bash", "grep"],
25
26
  sessionManager: SessionManager.inMemory(),
26
27
  });
27
28
  console.log("Custom tools session created");
29
+ customToolsSession.dispose();
28
30
 
29
31
  // With custom cwd
30
32
  const customCwd = "/path/to/project";
31
- await createAgentSession({
33
+ const { session: customCwdSession } = await createAgentSession({
32
34
  cwd: customCwd,
33
35
  tools: ["read", "bash", "edit", "write"],
34
36
  sessionManager: SessionManager.inMemory(customCwd),
35
37
  });
36
38
  console.log("Custom cwd session created");
39
+ customCwdSession.dispose();
37
40
 
38
41
  // Or pick specific tools for custom cwd
39
- await createAgentSession({
42
+ const { session: specificToolsSession } = await createAgentSession({
40
43
  cwd: customCwd,
41
44
  tools: ["read", "bash", "grep"],
42
45
  sessionManager: SessionManager.inMemory(customCwd),
43
46
  });
44
47
  console.log("Specific tools with custom cwd session created");
48
+ specificToolsSession.dispose();
@@ -37,14 +37,18 @@ const { session } = await createAgentSession({
37
37
  sessionManager: SessionManager.inMemory(),
38
38
  });
39
39
 
40
- session.subscribe((event) => {
41
- if (event.type === "message_update" && event.assistantMessageEvent.type === "text_delta") {
42
- process.stdout.write(event.assistantMessageEvent.delta);
43
- }
44
- });
40
+ try {
41
+ session.subscribe((event) => {
42
+ if (event.type === "message_update" && event.assistantMessageEvent.type === "text_delta") {
43
+ process.stdout.write(event.assistantMessageEvent.delta);
44
+ }
45
+ });
45
46
 
46
- await session.prompt("List files in the current directory.");
47
- console.log();
47
+ await session.prompt("List files in the current directory.");
48
+ console.log();
49
+ } finally {
50
+ session.dispose();
51
+ }
48
52
 
49
53
  // Example extension file (./my-logging-extension.ts):
50
54
  /*
@@ -34,9 +34,9 @@ for (const file of discovered) {
34
34
  console.log(` - ${file.path} (${file.content.length} chars)`);
35
35
  }
36
36
 
37
- await createAgentSession({
37
+ const { session } = await createAgentSession({
38
38
  resourceLoader: loader,
39
39
  sessionManager: SessionManager.inMemory(),
40
40
  });
41
-
42
41
  console.log(`Session created with ${discovered.length + 1} context files`);
42
+ session.dispose();
@@ -43,9 +43,9 @@ for (const template of discovered) {
43
43
  console.log(` /${template.name}: ${template.description}`);
44
44
  }
45
45
 
46
- await createAgentSession({
46
+ const { session } = await createAgentSession({
47
47
  resourceLoader: loader,
48
48
  sessionManager: SessionManager.inMemory(),
49
49
  });
50
-
51
50
  console.log(`Session created with ${discovered.length + 1} prompt templates`);
51
+ session.dispose();
@@ -11,38 +11,42 @@ import { AuthStorage, createAgentSession, ModelRegistry, SessionManager } from "
11
11
  const authStorage = AuthStorage.create();
12
12
  const modelRegistry = ModelRegistry.create(authStorage);
13
13
 
14
- await createAgentSession({
14
+ const { session: defaultAuthSession } = await createAgentSession({
15
15
  sessionManager: SessionManager.inMemory(),
16
16
  authStorage,
17
17
  modelRegistry,
18
18
  });
19
19
  console.log("Session with default auth storage and model registry");
20
+ defaultAuthSession.dispose();
20
21
 
21
22
  // Custom auth storage location
22
23
  const customAuthStorage = AuthStorage.create("/tmp/my-app/auth.json");
23
24
  const customModelRegistry = ModelRegistry.create(customAuthStorage, "/tmp/my-app/models.json");
24
25
 
25
- await createAgentSession({
26
+ const { session: customAuthSession } = await createAgentSession({
26
27
  sessionManager: SessionManager.inMemory(),
27
28
  authStorage: customAuthStorage,
28
29
  modelRegistry: customModelRegistry,
29
30
  });
30
31
  console.log("Session with custom auth storage location");
32
+ customAuthSession.dispose();
31
33
 
32
34
  // Runtime API key override (not persisted to disk)
33
35
  authStorage.setRuntimeApiKey("anthropic", "sk-my-temp-key");
34
- await createAgentSession({
36
+ const { session: runtimeKeySession } = await createAgentSession({
35
37
  sessionManager: SessionManager.inMemory(),
36
38
  authStorage,
37
39
  modelRegistry,
38
40
  });
39
41
  console.log("Session with runtime API key override");
42
+ runtimeKeySession.dispose();
40
43
 
41
44
  // No models.json - only built-in models
42
45
  const simpleRegistry = ModelRegistry.inMemory(authStorage);
43
- await createAgentSession({
46
+ const { session: builtInModelsSession } = await createAgentSession({
44
47
  sessionManager: SessionManager.inMemory(),
45
48
  authStorage,
46
49
  modelRegistry: simpleRegistry,
47
50
  });
48
51
  console.log("Session with only built-in models");
52
+ builtInModelsSession.dispose();
@@ -19,12 +19,12 @@ settingsManager.applyOverrides({
19
19
  retry: { enabled: true, maxRetries: 5, baseDelayMs: 1000 },
20
20
  });
21
21
 
22
- await createAgentSession({
22
+ const { session: customSettingsSession } = await createAgentSession({
23
23
  settingsManager,
24
24
  sessionManager: SessionManager.inMemory(),
25
25
  });
26
-
27
26
  console.log("Session created with custom settings");
27
+ customSettingsSession.dispose();
28
28
 
29
29
  // Setters update memory immediately and queue persistence writes.
30
30
  // Call flush() when you need a durability boundary.
@@ -45,9 +45,9 @@ const inMemorySettings = SettingsManager.inMemory({
45
45
  retry: { enabled: false },
46
46
  });
47
47
 
48
- await createAgentSession({
48
+ const { session: testSession } = await createAgentSession({
49
49
  settingsManager: inMemorySettings,
50
50
  sessionManager: SessionManager.inMemory(),
51
51
  });
52
-
53
52
  console.log("Test session created with in-memory settings");
53
+ testSession.dispose();
@@ -11,12 +11,14 @@ const { session: inMemory } = await createAgentSession({
11
11
  sessionManager: SessionManager.inMemory(),
12
12
  });
13
13
  console.log("In-memory session:", inMemory.sessionFile ?? "(none)");
14
+ inMemory.dispose();
14
15
 
15
16
  // New persistent session
16
17
  const { session: newSession } = await createAgentSession({
17
18
  sessionManager: SessionManager.create(process.cwd()),
18
19
  });
19
20
  console.log("New session file:", newSession.sessionFile);
21
+ newSession.dispose();
20
22
 
21
23
  // Continue most recent session (or create new if none)
22
24
  const { session: continued, modelFallbackMessage } = await createAgentSession({
@@ -24,6 +26,7 @@ const { session: continued, modelFallbackMessage } = await createAgentSession({
24
26
  });
25
27
  if (modelFallbackMessage) console.log("Note:", modelFallbackMessage);
26
28
  console.log("Continued session:", continued.sessionFile);
29
+ continued.dispose();
27
30
 
28
31
  // List and open specific session
29
32
  const sessions = await SessionManager.list(process.cwd());
@@ -37,6 +40,7 @@ if (sessions.length > 0) {
37
40
  sessionManager: SessionManager.open(sessions[0].path),
38
41
  });
39
42
  console.log(`\nOpened: ${opened.sessionId}`);
43
+ opened.dispose();
40
44
  }
41
45
 
42
46
  // Custom session directory (no cwd encoding)
@@ -63,11 +63,15 @@ const { session } = await createAgentSession({
63
63
  settingsManager,
64
64
  });
65
65
 
66
- session.subscribe((event) => {
67
- if (event.type === "message_update" && event.assistantMessageEvent.type === "text_delta") {
68
- process.stdout.write(event.assistantMessageEvent.delta);
69
- }
70
- });
66
+ try {
67
+ session.subscribe((event) => {
68
+ if (event.type === "message_update" && event.assistantMessageEvent.type === "text_delta") {
69
+ process.stdout.write(event.assistantMessageEvent.delta);
70
+ }
71
+ });
71
72
 
72
- await session.prompt("List files in the current directory.");
73
- console.log();
73
+ await session.prompt("List files in the current directory.");
74
+ console.log();
75
+ } finally {
76
+ session.dispose();
77
+ }
@@ -1,6 +1,6 @@
1
1
  # SDK Examples
2
2
 
3
- Programmatic usage of pi-coding-agent via `createAgentSession()` and `createAgentSessionRuntime()`.
3
+ Programmatic usage of senpi via `createAgentSession()` and `createAgentSessionRuntime()`.
4
4
 
5
5
  The runtime example shows how to build a recreate function that closes over process-global fixed inputs and recreates cwd-bound services and sessions as the active session cwd changes.
6
6
 
@@ -12,7 +12,7 @@ The runtime example shows how to build a recreate function that closes over proc
12
12
  | `02-custom-model.ts` | Select model and thinking level |
13
13
  | `03-custom-prompt.ts` | Replace or modify system prompt |
14
14
  | `04-skills.ts` | Discover, filter, or replace skills |
15
- | `05-tools.ts` | Built-in tools, custom tools |
15
+ | `05-tools.ts` | Built-in tool allowlists |
16
16
  | `06-extensions.ts` | Logging, blocking, result modification |
17
17
  | `07-context-files.ts` | AGENTS.md context files |
18
18
  | `08-slash-commands.ts` | File-based slash commands |
@@ -40,9 +40,6 @@ import {
40
40
  ModelRegistry,
41
41
  SessionManager,
42
42
  SettingsManager,
43
- codingTools,
44
- readOnlyTools,
45
- readTool, bashTool, editTool, writeTool,
46
43
  } from "@code-yeongyu/senpi";
47
44
 
48
45
  // Auth and models setup
@@ -64,7 +61,7 @@ await loader.reload();
64
61
  const { session } = await createAgentSession({ resourceLoader: loader, authStorage, modelRegistry });
65
62
 
66
63
  // Read-only
67
- const { session } = await createAgentSession({ tools: readOnlyTools, authStorage, modelRegistry });
64
+ const { session } = await createAgentSession({ tools: ["read", "grep", "find", "ls"], authStorage, modelRegistry });
68
65
 
69
66
  // In-memory
70
67
  const { session } = await createAgentSession({
@@ -92,8 +89,8 @@ const { session } = await createAgentSession({
92
89
  authStorage: customAuth,
93
90
  modelRegistry: customRegistry,
94
91
  resourceLoader,
95
- tools: [readTool, bashTool],
96
- customTools: [{ tool: myTool }],
92
+ tools: ["read", "bash", "my_tool"],
93
+ customTools: [myTool],
97
94
  sessionManager: SessionManager.inMemory(),
98
95
  settingsManager: SettingsManager.inMemory(),
99
96
  });
@@ -117,7 +114,7 @@ await session.prompt("Hello");
117
114
  | `agentDir` | `~/.senpi/agent` | Config directory |
118
115
  | `model` | From settings/first available | Model to use |
119
116
  | `thinkingLevel` | From settings/"off" | off, low, medium, high |
120
- | `tools` | `codingTools` | Built-in tools |
117
+ | `tools` | `["read", "bash", "edit", "write"]` built-ins | Allowlist tool names across built-in, extension, and custom tools |
121
118
  | `customTools` | `[]` | Additional tool definitions |
122
119
  | `resourceLoader` | DefaultResourceLoader | Resource loader for extensions, skills, prompts, themes |
123
120
  | `sessionManager` | `SessionManager.create(cwd)` | Persistence |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@code-yeongyu/senpi",
3
- "version": "2026.05.13",
3
+ "version": "2026.5.15",
4
4
  "description": "Coding agent CLI with read, bash, edit, write tools and session management",
5
5
  "type": "module",
6
6
  "piConfig": {
@@ -31,7 +31,7 @@
31
31
  "scripts": {
32
32
  "clean": "shx rm -rf dist",
33
33
  "dev": "tsgo -p tsconfig.build.json --watch --preserveWatchOutput",
34
- "build": "tsgo -p tsconfig.build.json && shx chmod +x dist/cli.js && shx cp dist/cli.js dist/senpi && shx chmod +x dist/senpi",
34
+ "build": "tsgo -p tsconfig.build.json && npm run copy-assets && shx chmod +x dist/cli.js && shx cp dist/cli.js dist/senpi && shx chmod +x dist/senpi",
35
35
  "build:binary": "npm --prefix ../tui run build && npm --prefix ../ai run build && npm --prefix ../agent run build && npm run build && bun build --compile ./dist/bun/cli.js --outfile dist/pi && npm run copy-binary-assets",
36
36
  "copy-assets": "shx mkdir -p dist/modes/interactive/theme && shx cp src/modes/interactive/theme/*.json dist/modes/interactive/theme/ && shx mkdir -p dist/modes/interactive/assets && shx cp src/modes/interactive/assets/*.png dist/modes/interactive/assets/ && shx mkdir -p dist/core/export-html/vendor && shx cp src/core/export-html/template.html src/core/export-html/template.css src/core/export-html/template.js dist/core/export-html/ && shx cp src/core/export-html/vendor/*.js dist/core/export-html/vendor/",
37
37
  "copy-binary-assets": "shx cp package.json dist/ && shx cp README.md dist/ && shx cp CHANGELOG.md dist/ && shx mkdir -p dist/theme && shx cp src/modes/interactive/theme/*.json dist/theme/ && shx mkdir -p dist/assets && shx cp src/modes/interactive/assets/*.png dist/assets/ && shx mkdir -p dist/export-html/vendor && shx cp src/core/export-html/template.html dist/export-html/ && shx cp src/core/export-html/vendor/*.js dist/export-html/vendor/ && shx cp -r docs dist/ && shx cp -r examples dist/ && shx cp ../../node_modules/@silvia-odwyer/photon-node/photon_rs_bg.wasm dist/",
@@ -40,26 +40,21 @@
40
40
  },
41
41
  "dependencies": {
42
42
  "@anthropic-ai/sdk": "^0.91.1",
43
- "@earendil-works/pi-agent-core": "^2026.05.13",
44
- "@earendil-works/pi-ai": "^2026.05.13",
45
- "@earendil-works/pi-tui": "^2026.05.13",
43
+ "@earendil-works/pi-agent-core": "^2026.5.15",
44
+ "@earendil-works/pi-ai": "^2026.5.15",
45
+ "@earendil-works/pi-tui": "^2026.5.15",
46
46
  "@silvia-odwyer/photon-node": "^0.3.4",
47
47
  "chalk": "^5.5.0",
48
- "cli-highlight": "^2.1.11",
49
48
  "diff": "^8.0.2",
50
- "extract-zip": "^2.0.1",
51
- "file-type": "^21.1.1",
52
49
  "glob": "^13.0.1",
50
+ "highlight.js": "^10.7.3",
53
51
  "hosted-git-info": "^9.0.2",
54
52
  "ignore": "^7.0.5",
55
53
  "jiti": "^2.7.0",
56
- "marked": "^15.0.12",
57
54
  "minimatch": "^10.2.3",
58
55
  "proper-lockfile": "^4.1.2",
59
- "strip-ansi": "^7.1.0",
60
56
  "typebox": "^1.1.24",
61
57
  "undici": "^7.19.1",
62
- "uuid": "^14.0.0",
63
58
  "yaml": "^2.8.2"
64
59
  },
65
60
  "overrides": {
@@ -97,6 +92,6 @@
97
92
  "directory": "packages/coding-agent"
98
93
  },
99
94
  "engines": {
100
- "node": ">=20.6.0"
95
+ "node": ">=24.0.0"
101
96
  }
102
97
  }
@@ -1,7 +0,0 @@
1
- import type { Api } from "@earendil-works/pi-ai";
2
- import type { ExtensionAPI } from "../../types.js";
3
- export declare function isCodeExecutionEnabled(): boolean;
4
- export declare function addAnthropicCodeExecutionToPayload(api: Api | undefined, payload: unknown): unknown;
5
- export declare const ANTHROPIC_CODE_EXECUTION_SECTION = "\n## Code Execution\n\nThe native code_execution tool is available in this session. The model\nruns Python (and shell commands via the bash subtool) inside an\nAnthropic-managed sandbox container. Prefer code_execution for\nnumerical work, file analysis, and one-off computations when explicit\nresults are needed.\n";
6
- export default function anthropicCodeExecutionExtension(pi: ExtensionAPI): void;
7
- //# sourceMappingURL=index.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/anthropic-code-execution/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,uBAAuB,CAAC;AACjD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAiCnD,wBAAgB,sBAAsB,IAAI,OAAO,CAQhD;AAED,wBAAgB,kCAAkC,CAAC,GAAG,EAAE,GAAG,GAAG,SAAS,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAwBlG;AAED,eAAO,MAAM,gCAAgC,iUAQ5C,CAAC;AAEF,MAAM,CAAC,OAAO,UAAU,+BAA+B,CAAC,EAAE,EAAE,YAAY,GAAG,IAAI,CAkB9E","sourcesContent":["import type { Api } from \"@earendil-works/pi-ai\";\nimport type { ExtensionAPI } from \"../../types.js\";\n\ntype ToolDefinition = Record<string, unknown>;\n\nconst CODE_EXECUTION_ENV = \"PI_ANTHROPIC_CODE_EXECUTION\";\nconst CODE_EXECUTION_TOOL = {\n\ttype: \"code_execution_20250825\",\n\tname: \"code_execution\",\n} as const;\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null;\n}\n\nfunction isCodeExecutionType(value: unknown): value is string {\n\treturn typeof value === \"string\" && value.startsWith(\"code_execution_\");\n}\n\nfunction sanitizeTools(tools: unknown[]): ToolDefinition[] {\n\tconst sanitizedTools: ToolDefinition[] = [];\n\tfor (const tool of tools) {\n\t\tif (!isRecord(tool)) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst shouldStripFunctionVariant = tool.name === \"code_execution\" && !isCodeExecutionType(tool.type);\n\t\tif (!shouldStripFunctionVariant) {\n\t\t\tsanitizedTools.push(tool);\n\t\t}\n\t}\n\treturn sanitizedTools;\n}\n\nexport function isCodeExecutionEnabled(): boolean {\n\tconst value = process.env[CODE_EXECUTION_ENV];\n\tif (!value) {\n\t\treturn false;\n\t}\n\n\tconst normalized = value.trim().toLowerCase();\n\treturn normalized === \"1\" || normalized === \"true\" || normalized === \"yes\" || normalized === \"on\";\n}\n\nexport function addAnthropicCodeExecutionToPayload(api: Api | undefined, payload: unknown): unknown {\n\tif (api !== \"anthropic-messages\") {\n\t\treturn payload;\n\t}\n\n\tif (!isCodeExecutionEnabled()) {\n\t\treturn payload;\n\t}\n\n\tif (!isRecord(payload)) {\n\t\treturn payload;\n\t}\n\n\tconst tools = Array.isArray(payload.tools) ? payload.tools : [];\n\tconst sanitizedTools = sanitizeTools(tools);\n\tconst hasNativeCodeExecution = sanitizedTools.some((tool) => isCodeExecutionType(tool.type));\n\tif (!hasNativeCodeExecution) {\n\t\tsanitizedTools.push(CODE_EXECUTION_TOOL);\n\t}\n\n\treturn {\n\t\t...payload,\n\t\ttools: sanitizedTools,\n\t};\n}\n\nexport const ANTHROPIC_CODE_EXECUTION_SECTION = `\n## Code Execution\n\nThe native code_execution tool is available in this session. The model\nruns Python (and shell commands via the bash subtool) inside an\nAnthropic-managed sandbox container. Prefer code_execution for\nnumerical work, file analysis, and one-off computations when explicit\nresults are needed.\n`;\n\nexport default function anthropicCodeExecutionExtension(pi: ExtensionAPI): void {\n\tpi.on(\"before_provider_request\", (event, ctx) => {\n\t\treturn addAnthropicCodeExecutionToPayload(ctx.model?.api, event.payload);\n\t});\n\n\tpi.on(\"before_agent_start\", async (event, ctx) => {\n\t\tif (ctx.model?.api !== \"anthropic-messages\") {\n\t\t\treturn undefined;\n\t\t}\n\n\t\tif (!isCodeExecutionEnabled()) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\treturn {\n\t\t\tsystemPrompt: `${event.systemPrompt}\\n${ANTHROPIC_CODE_EXECUTION_SECTION}`,\n\t\t};\n\t});\n}\n"]}