my-pi-agent 0.1.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 (141) hide show
  1. package/README.md +318 -0
  2. package/package.json +45 -0
  3. package/pyproject.toml +50 -0
  4. package/src/my_agent_core/__init__.py +123 -0
  5. package/src/my_agent_core/agent.py +441 -0
  6. package/src/my_agent_core/background.py +121 -0
  7. package/src/my_agent_core/context.py +505 -0
  8. package/src/my_agent_core/events.py +153 -0
  9. package/src/my_agent_core/extensions/__init__.py +9 -0
  10. package/src/my_agent_core/extensions/core.py +197 -0
  11. package/src/my_agent_core/hooks.py +130 -0
  12. package/src/my_agent_core/loop.py +709 -0
  13. package/src/my_agent_core/main.py +134 -0
  14. package/src/my_agent_core/memory.py +241 -0
  15. package/src/my_agent_core/message_queue.py +110 -0
  16. package/src/my_agent_core/plugins.py +212 -0
  17. package/src/my_agent_core/registry.py +186 -0
  18. package/src/my_agent_core/session/__init__.py +79 -0
  19. package/src/my_agent_core/session/entries.py +197 -0
  20. package/src/my_agent_core/session/jsonl.py +60 -0
  21. package/src/my_agent_core/session/memory.py +137 -0
  22. package/src/my_agent_core/session/session.py +400 -0
  23. package/src/my_agent_core/session/storage.py +245 -0
  24. package/src/my_agent_core/session/store.py +131 -0
  25. package/src/my_agent_core/session/tree.py +86 -0
  26. package/src/my_agent_core/skills.py +149 -0
  27. package/src/my_agent_core/subagent_tasks.py +170 -0
  28. package/src/my_agent_core/subagents.py +148 -0
  29. package/src/my_agent_core/task_store.py +248 -0
  30. package/src/my_agent_core/tool_history.py +189 -0
  31. package/src/my_agent_core/tools/__init__.py +5 -0
  32. package/src/my_agent_core/tools/builtin/__init__.py +5 -0
  33. package/src/my_agent_core/tools/builtin/task.py +30 -0
  34. package/src/my_agent_core/tools/builtin/task_tools.py +215 -0
  35. package/src/my_agent_core/tools/core.py +239 -0
  36. package/src/my_agent_llm/__init__.py +45 -0
  37. package/src/my_agent_llm/auth/__init__.py +46 -0
  38. package/src/my_agent_llm/auth/antigravity.py +209 -0
  39. package/src/my_agent_llm/auth/manager.py +259 -0
  40. package/src/my_agent_llm/auth/quota.py +56 -0
  41. package/src/my_agent_llm/auth/schema.py +94 -0
  42. package/src/my_agent_llm/client.py +116 -0
  43. package/src/my_agent_llm/config.py +17 -0
  44. package/src/my_agent_llm/events.py +84 -0
  45. package/src/my_agent_llm/models.py +195 -0
  46. package/src/my_agent_llm/providers/__init__.py +4 -0
  47. package/src/my_agent_llm/providers/_base.py +94 -0
  48. package/src/my_agent_llm/providers/anthropic.py +298 -0
  49. package/src/my_agent_llm/providers/antigravity.py +480 -0
  50. package/src/my_agent_llm/providers/deepseek.py +196 -0
  51. package/src/my_agent_llm/providers/openai.py +364 -0
  52. package/src/my_agent_llm/providers/registry.py +16 -0
  53. package/src/my_agent_llm/stream.py +218 -0
  54. package/src/my_coding_agent/__init__.py +66 -0
  55. package/src/my_coding_agent/agent.py +208 -0
  56. package/src/my_coding_agent/cli.py +78 -0
  57. package/src/my_coding_agent/file_reference.py +80 -0
  58. package/src/my_coding_agent/macro.py +408 -0
  59. package/src/my_coding_agent/mcp.py +243 -0
  60. package/src/my_coding_agent/mutation_queue.py +37 -0
  61. package/src/my_coding_agent/paths.py +119 -0
  62. package/src/my_coding_agent/permissions.py +84 -0
  63. package/src/my_coding_agent/prompt.py +54 -0
  64. package/src/my_coding_agent/rpc_server.py +2817 -0
  65. package/src/my_coding_agent/settings.py +126 -0
  66. package/src/my_coding_agent/tools/__init__.py +55 -0
  67. package/src/my_coding_agent/tools/base.py +58 -0
  68. package/src/my_coding_agent/tools/bash.py +206 -0
  69. package/src/my_coding_agent/tools/edit.py +226 -0
  70. package/src/my_coding_agent/tools/find.py +118 -0
  71. package/src/my_coding_agent/tools/grep.py +177 -0
  72. package/src/my_coding_agent/tools/ls.py +112 -0
  73. package/src/my_coding_agent/tools/read.py +113 -0
  74. package/src/my_coding_agent/tools/write.py +72 -0
  75. package/tui/README.md +27 -0
  76. package/tui/bin/my-agent.js +98 -0
  77. package/tui/dist/app.d.ts +41 -0
  78. package/tui/dist/app.js +110 -0
  79. package/tui/dist/bridge/event-translator.d.ts +92 -0
  80. package/tui/dist/bridge/event-translator.js +216 -0
  81. package/tui/dist/bridge/kernel-bridge.d.ts +48 -0
  82. package/tui/dist/bridge/kernel-bridge.js +132 -0
  83. package/tui/dist/client.d.ts +63 -0
  84. package/tui/dist/client.js +239 -0
  85. package/tui/dist/components/assistant-message.d.ts +19 -0
  86. package/tui/dist/components/assistant-message.js +90 -0
  87. package/tui/dist/components/compaction-summary-message.d.ts +19 -0
  88. package/tui/dist/components/compaction-summary-message.js +46 -0
  89. package/tui/dist/components/custom-editor.d.ts +18 -0
  90. package/tui/dist/components/custom-editor.js +56 -0
  91. package/tui/dist/components/dynamic-border.d.ts +9 -0
  92. package/tui/dist/components/dynamic-border.js +14 -0
  93. package/tui/dist/components/footer.d.ts +39 -0
  94. package/tui/dist/components/footer.js +199 -0
  95. package/tui/dist/components/header.d.ts +4 -0
  96. package/tui/dist/components/header.js +21 -0
  97. package/tui/dist/components/keys.d.ts +5 -0
  98. package/tui/dist/components/keys.js +12 -0
  99. package/tui/dist/components/login-selector.d.ts +26 -0
  100. package/tui/dist/components/login-selector.js +181 -0
  101. package/tui/dist/components/logout-selector.d.ts +19 -0
  102. package/tui/dist/components/logout-selector.js +88 -0
  103. package/tui/dist/components/model-selector.d.ts +40 -0
  104. package/tui/dist/components/model-selector.js +268 -0
  105. package/tui/dist/components/session-selector.d.ts +54 -0
  106. package/tui/dist/components/session-selector.js +393 -0
  107. package/tui/dist/components/settings-selector.d.ts +24 -0
  108. package/tui/dist/components/settings-selector.js +146 -0
  109. package/tui/dist/components/status-indicator.d.ts +25 -0
  110. package/tui/dist/components/status-indicator.js +60 -0
  111. package/tui/dist/components/theme-selector.d.ts +14 -0
  112. package/tui/dist/components/theme-selector.js +77 -0
  113. package/tui/dist/components/thinking-selector.d.ts +21 -0
  114. package/tui/dist/components/thinking-selector.js +128 -0
  115. package/tui/dist/components/tool-execution.d.ts +31 -0
  116. package/tui/dist/components/tool-execution.js +206 -0
  117. package/tui/dist/components/tree-selector.d.ts +40 -0
  118. package/tui/dist/components/tree-selector.js +173 -0
  119. package/tui/dist/components/user-message-selector.d.ts +21 -0
  120. package/tui/dist/components/user-message-selector.js +103 -0
  121. package/tui/dist/components/user-message.d.ts +5 -0
  122. package/tui/dist/components/user-message.js +15 -0
  123. package/tui/dist/index.d.ts +11 -0
  124. package/tui/dist/index.js +11 -0
  125. package/tui/dist/interactive/chat-viewport.d.ts +19 -0
  126. package/tui/dist/interactive/chat-viewport.js +41 -0
  127. package/tui/dist/interactive/components.d.ts +1 -0
  128. package/tui/dist/interactive/components.js +1 -0
  129. package/tui/dist/interactive/interactive-mode.d.ts +89 -0
  130. package/tui/dist/interactive/interactive-mode.js +1625 -0
  131. package/tui/dist/interactive/theme.d.ts +1 -0
  132. package/tui/dist/interactive/theme.js +1 -0
  133. package/tui/dist/interactive/tui-renderer.d.ts +8 -0
  134. package/tui/dist/interactive/tui-renderer.js +10 -0
  135. package/tui/dist/protocol.d.ts +78 -0
  136. package/tui/dist/protocol.js +1 -0
  137. package/tui/dist/theme/dark.json +54 -0
  138. package/tui/dist/theme/light.json +71 -0
  139. package/tui/dist/theme/theme.d.ts +20 -0
  140. package/tui/dist/theme/theme.js +86 -0
  141. package/tui/package.json +25 -0
@@ -0,0 +1,98 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { AgentApp } from "../dist/app.js";
4
+
5
+ function parseArgs() {
6
+ const args = process.argv.slice(2);
7
+ const options = {
8
+ workspace: process.env.INIT_CWD || process.cwd(),
9
+ model: undefined,
10
+ mode: "review",
11
+ continueSession: false,
12
+ resume: undefined,
13
+ sessionName: undefined,
14
+ thinking: undefined,
15
+ noSession: false,
16
+ newSession: false,
17
+ prompt: undefined,
18
+ pythonExecutable: undefined,
19
+ };
20
+
21
+ for (let i = 0; i < args.length; i++) {
22
+ const arg = args[i];
23
+ if (arg === "-w" || arg === "--workspace") {
24
+ options.workspace = args[++i];
25
+ } else if (arg === "--python-executable") {
26
+ options.pythonExecutable = args[++i];
27
+ } else if (arg === "-m" || arg === "--model") {
28
+ options.model = args[++i];
29
+ } else if (arg === "--mode") {
30
+ options.mode = args[++i];
31
+ } else if (arg === "-c" || arg === "--continue") {
32
+ options.continueSession = true;
33
+ } else if (arg === "-r" || arg === "--resume") {
34
+ const next = args[i + 1];
35
+ if (next && !next.startsWith("-")) {
36
+ options.resume = args[++i];
37
+ } else {
38
+ options.resume = true;
39
+ }
40
+ } else if (arg === "-n" || arg === "--name") {
41
+ options.sessionName = args[++i];
42
+ } else if (arg === "--thinking") {
43
+ options.thinking = args[++i];
44
+ } else if (arg === "--no-session") {
45
+ options.noSession = true;
46
+ } else if (arg === "--new-session") {
47
+ options.newSession = true;
48
+ } else if (arg === "-h" || arg === "--help") {
49
+ console.log(`
50
+ my-agent: High-fidelity Pi-TUI terminal shell for my-pi-agent
51
+
52
+ Usage:
53
+ my-agent [options] [prompt]
54
+
55
+ Options:
56
+ -c, --continue 一键续接当前项目最近一次历史会话
57
+ -r, --resume [id] 启动时直接打开交互式会话选择器或恢复指定会话
58
+ --new-session 强制开启全新会话 (默认)
59
+ -n, --name <title> 启动时直接为该会话命名
60
+ -m, --model <model> 指定生效模型 (如 deepseek-chat, gemini-3.8-flash)
61
+ --thinking <level> 指定思考深度等级 (off/minimal/low/medium/high/max)
62
+ --no-session 内存无痕沙箱模式 (不持久化 session 文件)
63
+ -w, --workspace <dir> 指定工作区目录 (默认: 当前目录)
64
+ --mode <mode> 权限安全模式: review (默认) | yolo | strict
65
+ -h, --help 查看帮助说明
66
+ `);
67
+ process.exit(0);
68
+ } else if (!arg.startsWith("-") && !options.prompt) {
69
+ options.prompt = arg;
70
+ }
71
+ }
72
+
73
+ return options;
74
+ }
75
+
76
+ async function main() {
77
+ const options = parseArgs();
78
+ const app = new AgentApp(options);
79
+
80
+ process.on("SIGINT", async () => {
81
+ await app.stop();
82
+ process.exit(0);
83
+ });
84
+
85
+ process.on("SIGTERM", async () => {
86
+ await app.stop();
87
+ process.exit(0);
88
+ });
89
+
90
+ try {
91
+ await app.start();
92
+ } catch (err) {
93
+ console.error("Fatal error starting agent:", err);
94
+ process.exit(1);
95
+ }
96
+ }
97
+
98
+ main();
@@ -0,0 +1,41 @@
1
+ import { type Container, type Editor, type TuiMainScreen } from "@earendil-works/pi-tui";
2
+ import { KernelBridge } from "./bridge/kernel-bridge.js";
3
+ import { PythonKernelClient, type PythonKernelClientOptions } from "./client.js";
4
+ import { type FooterComponent } from "./components/footer.js";
5
+ import { type ToolExecutionComponent } from "./components/tool-execution.js";
6
+ import { BUILTIN_SLASH_COMMANDS, InteractiveMode, type InteractiveModeOptions } from "./interactive/interactive-mode.js";
7
+ export { BUILTIN_SLASH_COMMANDS };
8
+ export interface AppOptions extends InteractiveModeOptions, PythonKernelClientOptions {
9
+ workspace?: string;
10
+ model?: string;
11
+ mode?: string;
12
+ continueSession?: boolean;
13
+ resume?: string | boolean;
14
+ sessionName?: string;
15
+ thinking?: string;
16
+ noSession?: boolean;
17
+ newSession?: boolean;
18
+ prompt?: string;
19
+ pythonExecutable?: string;
20
+ }
21
+ export declare class AgentApp {
22
+ readonly options: AppOptions;
23
+ readonly client: PythonKernelClient;
24
+ readonly bridge: KernelBridge;
25
+ readonly interactiveMode: InteractiveMode;
26
+ get activeSelectorComponent(): any;
27
+ get isBusy(): boolean;
28
+ set isBusy(val: boolean);
29
+ constructor(options?: AppOptions);
30
+ get tui(): TuiMainScreen;
31
+ get chatContainer(): Container;
32
+ get editor(): Editor;
33
+ get footer(): FooterComponent;
34
+ get activeTools(): Map<string, ToolExecutionComponent>;
35
+ get toolStartTimes(): Map<string, number>;
36
+ handleAgentEvent(event: any): void;
37
+ handleUserSubmit(input: string): Promise<void>;
38
+ renderSessionHistory(messages: any[], banner?: string): void;
39
+ start(): Promise<void>;
40
+ stop(): Promise<void>;
41
+ }
@@ -0,0 +1,110 @@
1
+ import { KernelBridge } from "./bridge/kernel-bridge.js";
2
+ import { PythonKernelClient, } from "./client.js";
3
+ import { BUILTIN_SLASH_COMMANDS, InteractiveMode, } from "./interactive/interactive-mode.js";
4
+ export { BUILTIN_SLASH_COMMANDS };
5
+ export class AgentApp {
6
+ options;
7
+ client;
8
+ bridge;
9
+ interactiveMode;
10
+ get activeSelectorComponent() {
11
+ return this.interactiveMode.activeSelectorComponent;
12
+ }
13
+ get isBusy() {
14
+ return this.interactiveMode.isStreaming;
15
+ }
16
+ set isBusy(val) {
17
+ this.interactiveMode.isStreaming = val;
18
+ }
19
+ constructor(options = {}) {
20
+ this.options = options;
21
+ this.client = new PythonKernelClient(options);
22
+ this.bridge = new KernelBridge(this.client);
23
+ this.interactiveMode = new InteractiveMode(this.bridge, options);
24
+ this.interactiveMode.onExit = async () => {
25
+ await this.client.shutdown();
26
+ };
27
+ const cleanupTerminal = () => {
28
+ try {
29
+ this.interactiveMode.ui.stop();
30
+ }
31
+ catch (err) {
32
+ void err;
33
+ }
34
+ };
35
+ process.once("exit", cleanupTerminal);
36
+ }
37
+ get tui() {
38
+ return this.interactiveMode.ui;
39
+ }
40
+ get chatContainer() {
41
+ return this.interactiveMode.chatContainer;
42
+ }
43
+ get editor() {
44
+ return this.interactiveMode.defaultEditor;
45
+ }
46
+ get footer() {
47
+ return this.interactiveMode.footer;
48
+ }
49
+ get activeTools() {
50
+ return this.interactiveMode.activeToolCalls;
51
+ }
52
+ get toolStartTimes() {
53
+ return this.interactiveMode.toolStartTimes;
54
+ }
55
+ handleAgentEvent(event) {
56
+ this.interactiveMode.handleAgentEvent(event);
57
+ }
58
+ async handleUserSubmit(input) {
59
+ await this.interactiveMode.handleUserInput(input);
60
+ }
61
+ renderSessionHistory(messages, banner) {
62
+ this.interactiveMode.renderSessionHistory(messages, banner);
63
+ }
64
+ async start() {
65
+ const initResult = await this.client.start();
66
+ await this.interactiveMode.init();
67
+ this.interactiveMode.start();
68
+ if (initResult?.session_name || initResult?.session_id) {
69
+ this.footer.update({
70
+ sessionName: initResult.session_name || initResult.session_id,
71
+ });
72
+ }
73
+ if (initResult?.context_window) {
74
+ this.footer.update({
75
+ contextWindow: initResult.context_window,
76
+ });
77
+ }
78
+ if (initResult?.model) {
79
+ this.footer.update({
80
+ modelName: initResult.model,
81
+ providerName: initResult.provider,
82
+ });
83
+ }
84
+ if (initResult?.thinking_level) {
85
+ this.footer.update({
86
+ thinkingLevel: initResult.thinking_level,
87
+ });
88
+ }
89
+ if (initResult?.usage) {
90
+ this.interactiveMode.updateFooterUsage(initResult.usage, initResult.context_window);
91
+ }
92
+ if (initResult?.messages && initResult.messages.length > 0) {
93
+ this.interactiveMode.renderSessionHistory(initResult.messages);
94
+ }
95
+ if (this.options.resume === true) {
96
+ await this.interactiveMode.handleSlashCommand("/resume");
97
+ }
98
+ else if (typeof this.options.resume === "string" && this.options.resume) {
99
+ await this.interactiveMode.handleSlashCommand(`/resume ${this.options.resume}`);
100
+ }
101
+ else if (this.options.prompt) {
102
+ await this.interactiveMode.handleUserInput(this.options.prompt);
103
+ }
104
+ this.tui.requestRender();
105
+ }
106
+ async stop() {
107
+ this.interactiveMode.stop();
108
+ await this.client.shutdown();
109
+ }
110
+ }
@@ -0,0 +1,92 @@
1
+ export interface ContentThinking {
2
+ type: "thinking";
3
+ thinking: string;
4
+ }
5
+ export interface ContentText {
6
+ type: "text";
7
+ text: string;
8
+ }
9
+ export interface ContentToolCall {
10
+ type: "toolCall";
11
+ id: string;
12
+ name: string;
13
+ arguments: Record<string, unknown>;
14
+ }
15
+ export type ContentBlock = ContentThinking | ContentText | ContentToolCall;
16
+ export interface AssistantMessageState {
17
+ role: "assistant";
18
+ content: ContentBlock[];
19
+ stopReason?: string;
20
+ errorMessage?: string;
21
+ }
22
+ export interface AgentStartSessionEvent {
23
+ type: "agent_start";
24
+ systemPrompt: string;
25
+ userInput: string;
26
+ }
27
+ export interface TurnStartSessionEvent {
28
+ type: "turn_start";
29
+ iteration: number;
30
+ }
31
+ export interface TurnEndSessionEvent {
32
+ type: "turn_end";
33
+ }
34
+ export interface MessageStartSessionEvent {
35
+ type: "message_start";
36
+ message: AssistantMessageState | Record<string, unknown>;
37
+ }
38
+ export interface MessageUpdateSessionEvent {
39
+ type: "message_update";
40
+ message: AssistantMessageState;
41
+ }
42
+ export interface MessageEndSessionEvent {
43
+ type: "message_end";
44
+ message: AssistantMessageState;
45
+ }
46
+ export interface ToolExecutionStartSessionEvent {
47
+ type: "tool_execution_start";
48
+ toolCallId: string;
49
+ toolName: string;
50
+ args: Record<string, unknown>;
51
+ }
52
+ export interface ToolExecutionUpdateSessionEvent {
53
+ type: "tool_execution_update";
54
+ toolCallId: string;
55
+ toolName: string;
56
+ partialResult: unknown;
57
+ }
58
+ export interface ToolExecutionEndSessionEvent {
59
+ type: "tool_execution_end";
60
+ toolCallId: string;
61
+ toolName: string;
62
+ result: unknown;
63
+ isError: boolean;
64
+ }
65
+ export interface AgentEndSessionEvent {
66
+ type: "agent_end";
67
+ iterations: number;
68
+ stopReason: string;
69
+ }
70
+ export interface ContextCompactedSessionEvent {
71
+ type: "context_compacted";
72
+ tokensBefore?: number;
73
+ tokensAfter?: number;
74
+ }
75
+ export type StandardSessionEvent = AgentStartSessionEvent | TurnStartSessionEvent | TurnEndSessionEvent | MessageStartSessionEvent | MessageUpdateSessionEvent | MessageEndSessionEvent | ToolExecutionStartSessionEvent | ToolExecutionUpdateSessionEvent | ToolExecutionEndSessionEvent | AgentEndSessionEvent | ContextCompactedSessionEvent | Record<string, unknown>;
76
+ export declare class EventTranslator {
77
+ private currentAssistantMessage;
78
+ /**
79
+ * Translates incoming Python RPC notifications or raw event objects
80
+ * into standardized Pi AgentSessionEvents while tracking in-flight message state.
81
+ */
82
+ translate(raw: unknown): StandardSessionEvent | null;
83
+ /**
84
+ * Returns a copy of the current in-flight assistant message state, or null if idle.
85
+ */
86
+ getCurrentAssistantMessage(): AssistantMessageState | null;
87
+ /**
88
+ * Resets internal tracking state.
89
+ */
90
+ reset(): void;
91
+ private cloneMessage;
92
+ }
@@ -0,0 +1,216 @@
1
+ export class EventTranslator {
2
+ currentAssistantMessage = null;
3
+ /**
4
+ * Translates incoming Python RPC notifications or raw event objects
5
+ * into standardized Pi AgentSessionEvents while tracking in-flight message state.
6
+ */
7
+ translate(raw) {
8
+ if (!raw || typeof raw !== "object") {
9
+ return null;
10
+ }
11
+ const payload = raw;
12
+ let event = payload;
13
+ if (payload.method === "event" &&
14
+ payload.params &&
15
+ typeof payload.params === "object") {
16
+ event = payload.params;
17
+ }
18
+ else if (payload.params &&
19
+ typeof payload.params === "object" &&
20
+ "type" in payload.params) {
21
+ event = payload.params;
22
+ }
23
+ if (!event.type || typeof event.type !== "string") {
24
+ return null;
25
+ }
26
+ switch (event.type) {
27
+ case "agent_start": {
28
+ this.currentAssistantMessage = null;
29
+ return {
30
+ type: "agent_start",
31
+ systemPrompt: String(event.system_prompt ?? event.systemPrompt ?? ""),
32
+ userInput: String(event.user_input ?? event.userInput ?? ""),
33
+ };
34
+ }
35
+ case "turn_start": {
36
+ return {
37
+ type: "turn_start",
38
+ iteration: Number(event.iteration ?? 1),
39
+ };
40
+ }
41
+ case "turn_end": {
42
+ return {
43
+ type: "turn_end",
44
+ };
45
+ }
46
+ case "message_start": {
47
+ const rawMsg = event.message;
48
+ const role = String(rawMsg?.role ?? "assistant");
49
+ if (role === "assistant") {
50
+ this.currentAssistantMessage = {
51
+ role: "assistant",
52
+ content: [],
53
+ };
54
+ return {
55
+ type: "message_start",
56
+ message: this.cloneMessage(this.currentAssistantMessage),
57
+ };
58
+ }
59
+ return {
60
+ type: "message_start",
61
+ message: rawMsg ?? { role, content: [] },
62
+ };
63
+ }
64
+ case "message_update": {
65
+ if (!this.currentAssistantMessage) {
66
+ this.currentAssistantMessage = {
67
+ role: "assistant",
68
+ content: [],
69
+ };
70
+ }
71
+ const reasoningDelta = event.reasoning_delta ?? event.reasoningDelta;
72
+ if (typeof reasoningDelta === "string" && reasoningDelta !== "") {
73
+ let thinkingBlock = this.currentAssistantMessage.content.find((b) => b.type === "thinking");
74
+ if (!thinkingBlock) {
75
+ thinkingBlock = { type: "thinking", thinking: "" };
76
+ this.currentAssistantMessage.content.push(thinkingBlock);
77
+ }
78
+ thinkingBlock.thinking += reasoningDelta;
79
+ }
80
+ const delta = event.delta;
81
+ if (typeof delta === "string" && delta !== "") {
82
+ let textBlock = this.currentAssistantMessage.content.find((b) => b.type === "text");
83
+ if (!textBlock) {
84
+ textBlock = { type: "text", text: "" };
85
+ this.currentAssistantMessage.content.push(textBlock);
86
+ }
87
+ textBlock.text += delta;
88
+ }
89
+ return {
90
+ type: "message_update",
91
+ message: this.cloneMessage(this.currentAssistantMessage),
92
+ };
93
+ }
94
+ case "message_end": {
95
+ const stopReason = String(event.stop_reason ?? event.stopReason ?? "stop");
96
+ if (this.currentAssistantMessage) {
97
+ this.currentAssistantMessage.stopReason = stopReason;
98
+ const completedMessage = this.cloneMessage(this.currentAssistantMessage);
99
+ this.currentAssistantMessage = null;
100
+ return {
101
+ type: "message_end",
102
+ message: completedMessage,
103
+ };
104
+ }
105
+ const rawMsg = event.message;
106
+ return {
107
+ type: "message_end",
108
+ message: rawMsg ?? { role: "assistant", content: [], stopReason },
109
+ };
110
+ }
111
+ case "tool_execution_start": {
112
+ const toolCallId = String(event.toolCallId ?? event.tool_call_id ?? "");
113
+ const toolName = String(event.toolName ?? event.tool_name ?? "");
114
+ const args = (event.args && typeof event.args === "object" ? event.args : {});
115
+ if (this.currentAssistantMessage) {
116
+ this.currentAssistantMessage.content.push({
117
+ type: "toolCall",
118
+ id: toolCallId,
119
+ name: toolName,
120
+ arguments: args,
121
+ });
122
+ }
123
+ return {
124
+ type: "tool_execution_start",
125
+ toolCallId,
126
+ toolName,
127
+ args,
128
+ };
129
+ }
130
+ case "tool_execution_update": {
131
+ return {
132
+ type: "tool_execution_update",
133
+ toolCallId: String(event.toolCallId ?? event.tool_call_id ?? ""),
134
+ toolName: String(event.toolName ?? event.tool_name ?? ""),
135
+ partialResult: event.partialResult ?? event.partial_result,
136
+ };
137
+ }
138
+ case "tool_execution_end": {
139
+ return {
140
+ type: "tool_execution_end",
141
+ toolCallId: String(event.toolCallId ?? event.tool_call_id ?? ""),
142
+ toolName: String(event.toolName ?? event.tool_name ?? ""),
143
+ result: event.result,
144
+ isError: Boolean(event.isError ?? event.is_error ?? false),
145
+ };
146
+ }
147
+ case "agent_end": {
148
+ this.currentAssistantMessage = null;
149
+ return {
150
+ type: "agent_end",
151
+ iterations: Number(event.iterations ?? 1),
152
+ stopReason: String(event.stop_reason ?? event.stopReason ?? "completed"),
153
+ };
154
+ }
155
+ case "context_compacted": {
156
+ const tokensBefore = typeof event.tokensBefore === "number"
157
+ ? event.tokensBefore
158
+ : typeof event.tokens_before === "number"
159
+ ? event.tokens_before
160
+ : undefined;
161
+ const tokensAfter = typeof event.tokensAfter === "number"
162
+ ? event.tokensAfter
163
+ : typeof event.tokens_after === "number"
164
+ ? event.tokens_after
165
+ : undefined;
166
+ return {
167
+ type: "context_compacted",
168
+ tokensBefore,
169
+ tokensAfter,
170
+ };
171
+ }
172
+ default: {
173
+ return { ...event };
174
+ }
175
+ }
176
+ }
177
+ /**
178
+ * Returns a copy of the current in-flight assistant message state, or null if idle.
179
+ */
180
+ getCurrentAssistantMessage() {
181
+ return this.currentAssistantMessage
182
+ ? this.cloneMessage(this.currentAssistantMessage)
183
+ : null;
184
+ }
185
+ /**
186
+ * Resets internal tracking state.
187
+ */
188
+ reset() {
189
+ this.currentAssistantMessage = null;
190
+ }
191
+ cloneMessage(msg) {
192
+ return {
193
+ role: msg.role,
194
+ content: msg.content.map((block) => {
195
+ if (block.type === "thinking") {
196
+ return { type: "thinking", thinking: block.thinking };
197
+ }
198
+ if (block.type === "text") {
199
+ return { type: "text", text: block.text };
200
+ }
201
+ if (block.type === "toolCall") {
202
+ return {
203
+ type: "toolCall",
204
+ id: block.id,
205
+ name: block.name,
206
+ arguments: { ...block.arguments },
207
+ };
208
+ }
209
+ const exhaustiveCheck = block;
210
+ return exhaustiveCheck;
211
+ }),
212
+ stopReason: msg.stopReason,
213
+ errorMessage: msg.errorMessage,
214
+ };
215
+ }
216
+ }
@@ -0,0 +1,48 @@
1
+ import { type StandardSessionEvent } from "./event-translator.js";
2
+ export interface PromptOptions {
3
+ streamingBehavior?: "steer" | "followUp";
4
+ [key: string]: unknown;
5
+ }
6
+ export interface RpcResponseData {
7
+ [key: string]: unknown;
8
+ }
9
+ export interface ClientLike {
10
+ request?(method: string, params?: Record<string, unknown>): Promise<unknown>;
11
+ sendRequest?(method: string, params?: Record<string, unknown>): Promise<unknown>;
12
+ on?(event: string, listener: (...args: any[]) => void): void;
13
+ off?(event: string, listener: (...args: any[]) => void): void;
14
+ removeListener?(event: string, listener: (...args: any[]) => void): void;
15
+ }
16
+ export interface TranslatorLike {
17
+ translate(event: unknown): StandardSessionEvent | null;
18
+ }
19
+ /**
20
+ * KernelBridge acts as a lightweight Session Adapter between the presentation
21
+ * layer and the PythonKernelClient.
22
+ */
23
+ export declare class KernelBridge {
24
+ readonly client: ClientLike;
25
+ readonly translator: TranslatorLike;
26
+ constructor(client: ClientLike, translator?: TranslatorLike);
27
+ private call;
28
+ prompt(text: string, options?: PromptOptions): Promise<RpcResponseData>;
29
+ abort(): Promise<RpcResponseData>;
30
+ steer(text: string): Promise<RpcResponseData>;
31
+ followUp(text: string): Promise<RpcResponseData>;
32
+ listModels(options?: Record<string, unknown>): Promise<RpcResponseData>;
33
+ switchModel(model: string, provider?: string): Promise<RpcResponseData>;
34
+ listSessions(options?: Record<string, unknown>): Promise<RpcResponseData>;
35
+ resumeSession(sessionId: string): Promise<RpcResponseData>;
36
+ deleteSession(sessionId: string): Promise<RpcResponseData>;
37
+ getSessionHistory(): Promise<RpcResponseData>;
38
+ newSession(options?: Record<string, unknown>): Promise<RpcResponseData>;
39
+ getTree(): Promise<RpcResponseData>;
40
+ getSessionStats(): Promise<RpcResponseData>;
41
+ branchSession(nodeId: string): Promise<RpcResponseData>;
42
+ setThinking(level: string): Promise<RpcResponseData>;
43
+ login(provider: string, key: string): Promise<RpcResponseData>;
44
+ logout(provider: string): Promise<RpcResponseData>;
45
+ getSettings(): Promise<RpcResponseData>;
46
+ setSetting(key: string, value: unknown): Promise<RpcResponseData>;
47
+ subscribe(listener: (event: StandardSessionEvent) => void): () => void;
48
+ }