@mariozechner/pi-coding-agent 0.64.0 → 0.65.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/CHANGELOG.md +96 -0
- package/README.md +11 -5
- package/dist/cli/args.d.ts +7 -4
- package/dist/cli/args.d.ts.map +1 -1
- package/dist/cli/args.js +37 -15
- package/dist/cli/args.js.map +1 -1
- package/dist/core/agent-session-runtime.d.ts +83 -0
- package/dist/core/agent-session-runtime.d.ts.map +1 -0
- package/dist/core/agent-session-runtime.js +232 -0
- package/dist/core/agent-session-runtime.js.map +1 -0
- package/dist/core/agent-session-services.d.ts +86 -0
- package/dist/core/agent-session-services.d.ts.map +1 -0
- package/dist/core/agent-session-services.js +116 -0
- package/dist/core/agent-session-services.js.map +1 -0
- package/dist/core/agent-session.d.ts +5 -42
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +46 -237
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/export-html/tool-renderer.d.ts +2 -0
- package/dist/core/export-html/tool-renderer.d.ts.map +1 -1
- package/dist/core/export-html/tool-renderer.js +2 -2
- package/dist/core/export-html/tool-renderer.js.map +1 -1
- package/dist/core/extensions/index.d.ts +2 -2
- package/dist/core/extensions/index.d.ts.map +1 -1
- package/dist/core/extensions/index.js +1 -1
- package/dist/core/extensions/index.js.map +1 -1
- package/dist/core/extensions/types.d.ts +16 -28
- package/dist/core/extensions/types.d.ts.map +1 -1
- package/dist/core/extensions/types.js +10 -0
- package/dist/core/extensions/types.js.map +1 -1
- package/dist/core/footer-data-provider.d.ts +5 -1
- package/dist/core/footer-data-provider.d.ts.map +1 -1
- package/dist/core/footer-data-provider.js +70 -8
- package/dist/core/footer-data-provider.js.map +1 -1
- package/dist/core/index.d.ts +3 -1
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +3 -1
- package/dist/core/index.js.map +1 -1
- package/dist/core/keybindings.d.ts +14 -1
- package/dist/core/keybindings.d.ts.map +1 -1
- package/dist/core/keybindings.js +13 -14
- package/dist/core/keybindings.js.map +1 -1
- package/dist/core/package-manager.d.ts +20 -0
- package/dist/core/package-manager.d.ts.map +1 -1
- package/dist/core/package-manager.js +32 -0
- package/dist/core/package-manager.js.map +1 -1
- package/dist/core/resource-loader.d.ts.map +1 -1
- package/dist/core/resource-loader.js +21 -0
- package/dist/core/resource-loader.js.map +1 -1
- package/dist/core/sdk.d.ts +4 -1
- package/dist/core/sdk.d.ts.map +1 -1
- package/dist/core/sdk.js +4 -1
- package/dist/core/sdk.js.map +1 -1
- package/dist/core/session-manager.d.ts +3 -0
- package/dist/core/session-manager.d.ts.map +1 -1
- package/dist/core/session-manager.js +13 -6
- package/dist/core/session-manager.js.map +1 -1
- package/dist/core/settings-manager.d.ts +1 -1
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js +2 -1
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -3
- package/dist/index.js.map +1 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +205 -427
- package/dist/main.js.map +1 -1
- package/dist/migrations.d.ts.map +1 -1
- package/dist/migrations.js +20 -0
- package/dist/migrations.js.map +1 -1
- package/dist/modes/interactive/components/footer.d.ts +1 -0
- package/dist/modes/interactive/components/footer.d.ts.map +1 -1
- package/dist/modes/interactive/components/footer.js +4 -1
- package/dist/modes/interactive/components/footer.js.map +1 -1
- package/dist/modes/interactive/components/tree-selector.d.ts +4 -2
- package/dist/modes/interactive/components/tree-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/tree-selector.js +48 -15
- package/dist/modes/interactive/components/tree-selector.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts +9 -4
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +124 -94
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
- package/dist/modes/interactive/theme/theme.js +6 -11
- package/dist/modes/interactive/theme/theme.js.map +1 -1
- package/dist/modes/print-mode.d.ts +2 -2
- package/dist/modes/print-mode.d.ts.map +1 -1
- package/dist/modes/print-mode.js +41 -36
- package/dist/modes/print-mode.js.map +1 -1
- package/dist/modes/rpc/rpc-mode.d.ts +2 -2
- package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-mode.js +92 -64
- package/dist/modes/rpc/rpc-mode.js.map +1 -1
- package/dist/package-manager-cli.d.ts +4 -0
- package/dist/package-manager-cli.d.ts.map +1 -0
- package/dist/package-manager-cli.js +234 -0
- package/dist/package-manager-cli.js.map +1 -0
- package/docs/extensions.md +72 -40
- package/docs/keybindings.md +2 -0
- package/docs/sdk.md +227 -74
- package/docs/settings.md +1 -1
- package/docs/tree.md +6 -3
- package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
- package/examples/extensions/custom-provider-anthropic/package.json +1 -1
- package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
- package/examples/extensions/custom-provider-qwen-cli/package.json +1 -1
- package/examples/extensions/hello.ts +18 -17
- package/examples/extensions/hidden-thinking-label.ts +0 -4
- package/examples/extensions/rpc-demo.ts +3 -9
- package/examples/extensions/status-line.ts +0 -8
- package/examples/extensions/todo.ts +0 -2
- package/examples/extensions/tools.ts +0 -5
- package/examples/extensions/widget-placement.ts +4 -12
- package/examples/extensions/with-deps/package-lock.json +2 -2
- package/examples/extensions/with-deps/package.json +1 -1
- package/examples/sdk/13-session-runtime.ts +67 -0
- package/examples/sdk/README.md +4 -1
- package/package.json +4 -4
package/docs/sdk.md
CHANGED
|
@@ -49,7 +49,7 @@ The SDK is included in the main package. No separate installation needed.
|
|
|
49
49
|
|
|
50
50
|
### createAgentSession()
|
|
51
51
|
|
|
52
|
-
The main factory function
|
|
52
|
+
The main factory function for a single `AgentSession`.
|
|
53
53
|
|
|
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
|
|
|
@@ -69,61 +69,117 @@ const { session } = await createAgentSession({
|
|
|
69
69
|
|
|
70
70
|
### AgentSession
|
|
71
71
|
|
|
72
|
-
The session manages
|
|
72
|
+
The session manages agent lifecycle, message history, model state, compaction, and event streaming.
|
|
73
73
|
|
|
74
74
|
```typescript
|
|
75
75
|
interface AgentSession {
|
|
76
76
|
// Send a prompt and wait for completion
|
|
77
|
-
// If streaming, requires streamingBehavior option to queue the message
|
|
78
77
|
prompt(text: string, options?: PromptOptions): Promise<void>;
|
|
79
|
-
|
|
78
|
+
|
|
80
79
|
// Queue messages during streaming
|
|
81
|
-
steer(text: string): Promise<void>;
|
|
82
|
-
followUp(text: string): Promise<void>;
|
|
83
|
-
|
|
80
|
+
steer(text: string): Promise<void>;
|
|
81
|
+
followUp(text: string): Promise<void>;
|
|
82
|
+
|
|
84
83
|
// Subscribe to events (returns unsubscribe function)
|
|
85
84
|
subscribe(listener: (event: AgentSessionEvent) => void): () => void;
|
|
86
|
-
|
|
85
|
+
|
|
87
86
|
// Session info
|
|
88
|
-
sessionFile: string | undefined;
|
|
87
|
+
sessionFile: string | undefined;
|
|
89
88
|
sessionId: string;
|
|
90
|
-
|
|
89
|
+
|
|
91
90
|
// Model control
|
|
92
91
|
setModel(model: Model): Promise<void>;
|
|
93
92
|
setThinkingLevel(level: ThinkingLevel): void;
|
|
94
93
|
cycleModel(): Promise<ModelCycleResult | undefined>;
|
|
95
94
|
cycleThinkingLevel(): ThinkingLevel | undefined;
|
|
96
|
-
|
|
95
|
+
|
|
97
96
|
// State access
|
|
98
97
|
agent: Agent;
|
|
99
98
|
model: Model | undefined;
|
|
100
99
|
thinkingLevel: ThinkingLevel;
|
|
101
100
|
messages: AgentMessage[];
|
|
102
101
|
isStreaming: boolean;
|
|
103
|
-
|
|
104
|
-
//
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
// Forking
|
|
109
|
-
fork(entryId: string): Promise<{ selectedText: string; cancelled: boolean }>; // Creates new session file
|
|
110
|
-
navigateTree(targetId: string, options?: { summarize?: boolean; customInstructions?: string; replaceInstructions?: boolean; label?: string }): Promise<{ editorText?: string; cancelled: boolean }>; // In-place navigation
|
|
111
|
-
|
|
112
|
-
// Hook message injection
|
|
113
|
-
sendHookMessage(message: HookMessage, triggerTurn?: boolean): Promise<void>;
|
|
114
|
-
|
|
102
|
+
|
|
103
|
+
// In-place tree navigation within the current session file
|
|
104
|
+
navigateTree(targetId: string, options?: { summarize?: boolean; customInstructions?: string; replaceInstructions?: boolean; label?: string }): Promise<{ editorText?: string; cancelled: boolean }>;
|
|
105
|
+
|
|
115
106
|
// Compaction
|
|
116
107
|
compact(customInstructions?: string): Promise<CompactionResult>;
|
|
117
108
|
abortCompaction(): void;
|
|
118
|
-
|
|
109
|
+
|
|
119
110
|
// Abort current operation
|
|
120
111
|
abort(): Promise<void>;
|
|
121
|
-
|
|
112
|
+
|
|
122
113
|
// Cleanup
|
|
123
114
|
dispose(): void;
|
|
124
115
|
}
|
|
125
116
|
```
|
|
126
117
|
|
|
118
|
+
Session replacement APIs such as new-session, resume, fork, and import live on `AgentSessionRuntime`, not on `AgentSession`.
|
|
119
|
+
|
|
120
|
+
### createAgentSessionRuntime() and AgentSessionRuntime
|
|
121
|
+
|
|
122
|
+
Use the runtime API when you need to replace the active session and rebuild cwd-bound runtime state.
|
|
123
|
+
This is the same layer used by the built-in interactive, print, and RPC modes.
|
|
124
|
+
|
|
125
|
+
`createAgentSessionRuntime()` takes a runtime factory plus the initial cwd/session target. The factory closes over process-global fixed inputs, recreates cwd-bound services for the effective cwd, resolves session options against those services, and returns a full runtime result.
|
|
126
|
+
|
|
127
|
+
```typescript
|
|
128
|
+
import {
|
|
129
|
+
type CreateAgentSessionRuntimeFactory,
|
|
130
|
+
createAgentSessionFromServices,
|
|
131
|
+
createAgentSessionRuntime,
|
|
132
|
+
createAgentSessionServices,
|
|
133
|
+
getAgentDir,
|
|
134
|
+
SessionManager,
|
|
135
|
+
} from "@mariozechner/pi-coding-agent";
|
|
136
|
+
|
|
137
|
+
const createRuntime: CreateAgentSessionRuntimeFactory = async ({ cwd, sessionManager, sessionStartEvent }) => {
|
|
138
|
+
const services = await createAgentSessionServices({ cwd });
|
|
139
|
+
return {
|
|
140
|
+
...(await createAgentSessionFromServices({
|
|
141
|
+
services,
|
|
142
|
+
sessionManager,
|
|
143
|
+
sessionStartEvent,
|
|
144
|
+
})),
|
|
145
|
+
services,
|
|
146
|
+
diagnostics: services.diagnostics,
|
|
147
|
+
};
|
|
148
|
+
};
|
|
149
|
+
|
|
150
|
+
const runtime = await createAgentSessionRuntime(createRuntime, {
|
|
151
|
+
cwd: process.cwd(),
|
|
152
|
+
agentDir: getAgentDir(),
|
|
153
|
+
sessionManager: SessionManager.create(process.cwd()),
|
|
154
|
+
});
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
`AgentSessionRuntime` owns replacement of the active runtime across:
|
|
158
|
+
|
|
159
|
+
- `newSession()`
|
|
160
|
+
- `switchSession()`
|
|
161
|
+
- `fork()`
|
|
162
|
+
- `importFromJsonl()`
|
|
163
|
+
|
|
164
|
+
Important behavior:
|
|
165
|
+
|
|
166
|
+
- `runtime.session` changes after those operations
|
|
167
|
+
- event subscriptions are attached to a specific `AgentSession`, so re-subscribe after replacement
|
|
168
|
+
- if you use extensions, call `runtime.session.bindExtensions(...)` again for the new session
|
|
169
|
+
- creation returns diagnostics on `runtime.diagnostics`
|
|
170
|
+
- if runtime creation or replacement fails, the method throws and the caller decides how to handle it
|
|
171
|
+
|
|
172
|
+
```typescript
|
|
173
|
+
let session = runtime.session;
|
|
174
|
+
let unsubscribe = session.subscribe(() => {});
|
|
175
|
+
|
|
176
|
+
await runtime.newSession();
|
|
177
|
+
|
|
178
|
+
unsubscribe();
|
|
179
|
+
session = runtime.session;
|
|
180
|
+
unsubscribe = session.subscribe(() => {});
|
|
181
|
+
```
|
|
182
|
+
|
|
127
183
|
### Prompting and Message Queueing
|
|
128
184
|
|
|
129
185
|
The `prompt()` method handles prompt templates, extension commands, and message sending:
|
|
@@ -171,10 +227,15 @@ const state = session.agent.state;
|
|
|
171
227
|
// state.model: Model - current model
|
|
172
228
|
// state.thinkingLevel: ThinkingLevel - current thinking level
|
|
173
229
|
// state.systemPrompt: string - system prompt
|
|
174
|
-
// state.tools:
|
|
230
|
+
// state.tools: AgentTool[] - available tools
|
|
231
|
+
// state.streamingMessage?: AgentMessage - current partial assistant message
|
|
232
|
+
// state.errorMessage?: string - latest assistant error
|
|
233
|
+
|
|
234
|
+
// Replace messages (useful for branching or restoration)
|
|
235
|
+
session.agent.state.messages = messages; // copies the top-level array
|
|
175
236
|
|
|
176
|
-
// Replace
|
|
177
|
-
session.agent.
|
|
237
|
+
// Replace tools
|
|
238
|
+
session.agent.state.tools = tools; // copies the top-level array
|
|
178
239
|
|
|
179
240
|
// Wait for agent to finish processing
|
|
180
241
|
await session.agent.waitForIdle();
|
|
@@ -447,21 +508,21 @@ const { session } = await createAgentSession({
|
|
|
447
508
|
|
|
448
509
|
```typescript
|
|
449
510
|
import { Type } from "@sinclair/typebox";
|
|
450
|
-
import { createAgentSession,
|
|
511
|
+
import { createAgentSession, defineTool } from "@mariozechner/pi-coding-agent";
|
|
451
512
|
|
|
452
513
|
// Inline custom tool
|
|
453
|
-
const myTool
|
|
514
|
+
const myTool = defineTool({
|
|
454
515
|
name: "my_tool",
|
|
455
516
|
label: "My Tool",
|
|
456
517
|
description: "Does something useful",
|
|
457
518
|
parameters: Type.Object({
|
|
458
519
|
input: Type.String({ description: "Input value" }),
|
|
459
520
|
}),
|
|
460
|
-
execute: async (
|
|
521
|
+
execute: async (_toolCallId, params) => ({
|
|
461
522
|
content: [{ type: "text", text: `Result: ${params.input}` }],
|
|
462
523
|
details: {},
|
|
463
524
|
}),
|
|
464
|
-
};
|
|
525
|
+
});
|
|
465
526
|
|
|
466
527
|
// Pass custom tools directly
|
|
467
528
|
const { session } = await createAgentSession({
|
|
@@ -469,6 +530,8 @@ const { session } = await createAgentSession({
|
|
|
469
530
|
});
|
|
470
531
|
```
|
|
471
532
|
|
|
533
|
+
Use `defineTool()` for standalone definitions and arrays like `customTools: [myTool]`. Inline `pi.registerTool({ ... })` already infers parameter types correctly.
|
|
534
|
+
|
|
472
535
|
Custom tools passed via `customTools` are combined with extension-registered tools. Extensions loaded by the ResourceLoader can also register tools via `pi.registerTool()`.
|
|
473
536
|
|
|
474
537
|
> See [examples/sdk/05-tools.ts](../examples/sdk/05-tools.ts)
|
|
@@ -597,7 +660,15 @@ const { session } = await createAgentSession({ resourceLoader: loader });
|
|
|
597
660
|
Sessions use a tree structure with `id`/`parentId` linking, enabling in-place branching.
|
|
598
661
|
|
|
599
662
|
```typescript
|
|
600
|
-
import {
|
|
663
|
+
import {
|
|
664
|
+
type CreateAgentSessionRuntimeFactory,
|
|
665
|
+
createAgentSession,
|
|
666
|
+
createAgentSessionFromServices,
|
|
667
|
+
createAgentSessionRuntime,
|
|
668
|
+
createAgentSessionServices,
|
|
669
|
+
getAgentDir,
|
|
670
|
+
SessionManager,
|
|
671
|
+
} from "@mariozechner/pi-coding-agent";
|
|
601
672
|
|
|
602
673
|
// In-memory (no persistence)
|
|
603
674
|
const { session } = await createAgentSession({
|
|
@@ -605,12 +676,12 @@ const { session } = await createAgentSession({
|
|
|
605
676
|
});
|
|
606
677
|
|
|
607
678
|
// New persistent session
|
|
608
|
-
const { session } = await createAgentSession({
|
|
679
|
+
const { session: persisted } = await createAgentSession({
|
|
609
680
|
sessionManager: SessionManager.create(process.cwd()),
|
|
610
681
|
});
|
|
611
682
|
|
|
612
683
|
// Continue most recent
|
|
613
|
-
const { session, modelFallbackMessage } = await createAgentSession({
|
|
684
|
+
const { session: continued, modelFallbackMessage } = await createAgentSession({
|
|
614
685
|
sessionManager: SessionManager.continueRecent(process.cwd()),
|
|
615
686
|
});
|
|
616
687
|
if (modelFallbackMessage) {
|
|
@@ -618,26 +689,42 @@ if (modelFallbackMessage) {
|
|
|
618
689
|
}
|
|
619
690
|
|
|
620
691
|
// Open specific file
|
|
621
|
-
const { session } = await createAgentSession({
|
|
692
|
+
const { session: opened } = await createAgentSession({
|
|
622
693
|
sessionManager: SessionManager.open("/path/to/session.jsonl"),
|
|
623
694
|
});
|
|
624
695
|
|
|
625
|
-
// List
|
|
626
|
-
const
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
696
|
+
// List sessions
|
|
697
|
+
const currentProjectSessions = await SessionManager.list(process.cwd());
|
|
698
|
+
const allSessions = await SessionManager.listAll(process.cwd());
|
|
699
|
+
|
|
700
|
+
// Session replacement API for /new, /resume, /fork, and import flows.
|
|
701
|
+
const createRuntime: CreateAgentSessionRuntimeFactory = async ({ cwd, sessionManager, sessionStartEvent }) => {
|
|
702
|
+
const services = await createAgentSessionServices({ cwd });
|
|
703
|
+
return {
|
|
704
|
+
...(await createAgentSessionFromServices({
|
|
705
|
+
services,
|
|
706
|
+
sessionManager,
|
|
707
|
+
sessionStartEvent,
|
|
708
|
+
})),
|
|
709
|
+
services,
|
|
710
|
+
diagnostics: services.diagnostics,
|
|
711
|
+
};
|
|
712
|
+
};
|
|
630
713
|
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
714
|
+
const runtime = await createAgentSessionRuntime(createRuntime, {
|
|
715
|
+
cwd: process.cwd(),
|
|
716
|
+
agentDir: getAgentDir(),
|
|
717
|
+
sessionManager: SessionManager.create(process.cwd()),
|
|
634
718
|
});
|
|
635
719
|
|
|
636
|
-
//
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
720
|
+
// Replace the active session with a fresh one
|
|
721
|
+
await runtime.newSession();
|
|
722
|
+
|
|
723
|
+
// Replace the active session with another saved session
|
|
724
|
+
await runtime.switchSession("/path/to/session.jsonl");
|
|
725
|
+
|
|
726
|
+
// Replace the active session with a fork from a specific entry
|
|
727
|
+
await runtime.fork("entry-id");
|
|
641
728
|
```
|
|
642
729
|
|
|
643
730
|
**SessionManager tree API:**
|
|
@@ -645,6 +732,10 @@ const { session } = await createAgentSession({
|
|
|
645
732
|
```typescript
|
|
646
733
|
const sm = SessionManager.open("/path/to/session.jsonl");
|
|
647
734
|
|
|
735
|
+
// Session listing
|
|
736
|
+
const currentProjectSessions = await SessionManager.list(process.cwd());
|
|
737
|
+
const allSessions = await SessionManager.listAll(process.cwd());
|
|
738
|
+
|
|
648
739
|
// Tree traversal
|
|
649
740
|
const entries = sm.getEntries(); // All entries (excludes header)
|
|
650
741
|
const tree = sm.getTree(); // Full tree structure
|
|
@@ -769,14 +860,14 @@ import { getModel } from "@mariozechner/pi-ai";
|
|
|
769
860
|
import { Type } from "@sinclair/typebox";
|
|
770
861
|
import {
|
|
771
862
|
AuthStorage,
|
|
863
|
+
bashTool,
|
|
772
864
|
createAgentSession,
|
|
773
865
|
DefaultResourceLoader,
|
|
866
|
+
defineTool,
|
|
774
867
|
ModelRegistry,
|
|
868
|
+
readTool,
|
|
775
869
|
SessionManager,
|
|
776
870
|
SettingsManager,
|
|
777
|
-
readTool,
|
|
778
|
-
bashTool,
|
|
779
|
-
type ToolDefinition,
|
|
780
871
|
} from "@mariozechner/pi-coding-agent";
|
|
781
872
|
|
|
782
873
|
// Set up auth storage (custom location)
|
|
@@ -791,7 +882,7 @@ if (process.env.MY_KEY) {
|
|
|
791
882
|
const modelRegistry = ModelRegistry.create(authStorage);
|
|
792
883
|
|
|
793
884
|
// Inline tool
|
|
794
|
-
const statusTool
|
|
885
|
+
const statusTool = defineTool({
|
|
795
886
|
name: "status",
|
|
796
887
|
label: "Status",
|
|
797
888
|
description: "Get system status",
|
|
@@ -800,7 +891,7 @@ const statusTool: ToolDefinition = {
|
|
|
800
891
|
content: [{ type: "text", text: `Uptime: ${process.uptime()}s` }],
|
|
801
892
|
details: {},
|
|
802
893
|
}),
|
|
803
|
-
};
|
|
894
|
+
});
|
|
804
895
|
|
|
805
896
|
const model = getModel("anthropic", "claude-opus-4-5");
|
|
806
897
|
if (!model) throw new Error("Model not found");
|
|
@@ -854,20 +945,39 @@ The SDK exports run mode utilities for building custom interfaces on top of `cre
|
|
|
854
945
|
Full TUI interactive mode with editor, chat history, and all built-in commands:
|
|
855
946
|
|
|
856
947
|
```typescript
|
|
857
|
-
import {
|
|
948
|
+
import {
|
|
949
|
+
type CreateAgentSessionRuntimeFactory,
|
|
950
|
+
createAgentSessionFromServices,
|
|
951
|
+
createAgentSessionRuntime,
|
|
952
|
+
createAgentSessionServices,
|
|
953
|
+
getAgentDir,
|
|
954
|
+
InteractiveMode,
|
|
955
|
+
SessionManager,
|
|
956
|
+
} from "@mariozechner/pi-coding-agent";
|
|
858
957
|
|
|
859
|
-
const
|
|
958
|
+
const createRuntime: CreateAgentSessionRuntimeFactory = async ({ cwd, sessionManager, sessionStartEvent }) => {
|
|
959
|
+
const services = await createAgentSessionServices({ cwd });
|
|
960
|
+
return {
|
|
961
|
+
...(await createAgentSessionFromServices({ services, sessionManager, sessionStartEvent })),
|
|
962
|
+
services,
|
|
963
|
+
diagnostics: services.diagnostics,
|
|
964
|
+
};
|
|
965
|
+
};
|
|
966
|
+
const runtime = await createAgentSessionRuntime(createRuntime, {
|
|
967
|
+
cwd: process.cwd(),
|
|
968
|
+
agentDir: getAgentDir(),
|
|
969
|
+
sessionManager: SessionManager.create(process.cwd()),
|
|
970
|
+
});
|
|
860
971
|
|
|
861
|
-
const mode = new InteractiveMode(
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
initialMessages: [], // Additional startup prompts
|
|
972
|
+
const mode = new InteractiveMode(runtime, {
|
|
973
|
+
migratedProviders: [],
|
|
974
|
+
modelFallbackMessage: undefined,
|
|
975
|
+
initialMessage: "Hello",
|
|
976
|
+
initialImages: [],
|
|
977
|
+
initialMessages: [],
|
|
868
978
|
});
|
|
869
979
|
|
|
870
|
-
await mode.run();
|
|
980
|
+
await mode.run();
|
|
871
981
|
```
|
|
872
982
|
|
|
873
983
|
### runPrintMode
|
|
@@ -875,15 +985,35 @@ await mode.run(); // Blocks until exit
|
|
|
875
985
|
Single-shot mode: send prompts, output result, exit:
|
|
876
986
|
|
|
877
987
|
```typescript
|
|
878
|
-
import {
|
|
988
|
+
import {
|
|
989
|
+
type CreateAgentSessionRuntimeFactory,
|
|
990
|
+
createAgentSessionFromServices,
|
|
991
|
+
createAgentSessionRuntime,
|
|
992
|
+
createAgentSessionServices,
|
|
993
|
+
getAgentDir,
|
|
994
|
+
runPrintMode,
|
|
995
|
+
SessionManager,
|
|
996
|
+
} from "@mariozechner/pi-coding-agent";
|
|
879
997
|
|
|
880
|
-
const
|
|
998
|
+
const createRuntime: CreateAgentSessionRuntimeFactory = async ({ cwd, sessionManager, sessionStartEvent }) => {
|
|
999
|
+
const services = await createAgentSessionServices({ cwd });
|
|
1000
|
+
return {
|
|
1001
|
+
...(await createAgentSessionFromServices({ services, sessionManager, sessionStartEvent })),
|
|
1002
|
+
services,
|
|
1003
|
+
diagnostics: services.diagnostics,
|
|
1004
|
+
};
|
|
1005
|
+
};
|
|
1006
|
+
const runtime = await createAgentSessionRuntime(createRuntime, {
|
|
1007
|
+
cwd: process.cwd(),
|
|
1008
|
+
agentDir: getAgentDir(),
|
|
1009
|
+
sessionManager: SessionManager.create(process.cwd()),
|
|
1010
|
+
});
|
|
881
1011
|
|
|
882
|
-
await runPrintMode(
|
|
883
|
-
mode: "text",
|
|
884
|
-
initialMessage: "Hello",
|
|
885
|
-
initialImages: [],
|
|
886
|
-
messages: ["Follow up"],
|
|
1012
|
+
await runPrintMode(runtime, {
|
|
1013
|
+
mode: "text",
|
|
1014
|
+
initialMessage: "Hello",
|
|
1015
|
+
initialImages: [],
|
|
1016
|
+
messages: ["Follow up"],
|
|
887
1017
|
});
|
|
888
1018
|
```
|
|
889
1019
|
|
|
@@ -892,11 +1022,31 @@ await runPrintMode(session, {
|
|
|
892
1022
|
JSON-RPC mode for subprocess integration:
|
|
893
1023
|
|
|
894
1024
|
```typescript
|
|
895
|
-
import {
|
|
1025
|
+
import {
|
|
1026
|
+
type CreateAgentSessionRuntimeFactory,
|
|
1027
|
+
createAgentSessionFromServices,
|
|
1028
|
+
createAgentSessionRuntime,
|
|
1029
|
+
createAgentSessionServices,
|
|
1030
|
+
getAgentDir,
|
|
1031
|
+
runRpcMode,
|
|
1032
|
+
SessionManager,
|
|
1033
|
+
} from "@mariozechner/pi-coding-agent";
|
|
896
1034
|
|
|
897
|
-
const
|
|
1035
|
+
const createRuntime: CreateAgentSessionRuntimeFactory = async ({ cwd, sessionManager, sessionStartEvent }) => {
|
|
1036
|
+
const services = await createAgentSessionServices({ cwd });
|
|
1037
|
+
return {
|
|
1038
|
+
...(await createAgentSessionFromServices({ services, sessionManager, sessionStartEvent })),
|
|
1039
|
+
services,
|
|
1040
|
+
diagnostics: services.diagnostics,
|
|
1041
|
+
};
|
|
1042
|
+
};
|
|
1043
|
+
const runtime = await createAgentSessionRuntime(createRuntime, {
|
|
1044
|
+
cwd: process.cwd(),
|
|
1045
|
+
agentDir: getAgentDir(),
|
|
1046
|
+
sessionManager: SessionManager.create(process.cwd()),
|
|
1047
|
+
});
|
|
898
1048
|
|
|
899
|
-
await runRpcMode(
|
|
1049
|
+
await runRpcMode(runtime);
|
|
900
1050
|
```
|
|
901
1051
|
|
|
902
1052
|
See [RPC documentation](rpc.md) for the JSON protocol.
|
|
@@ -929,6 +1079,8 @@ The main entry point exports:
|
|
|
929
1079
|
```typescript
|
|
930
1080
|
// Factory
|
|
931
1081
|
createAgentSession
|
|
1082
|
+
createAgentSessionRuntime
|
|
1083
|
+
AgentSessionRuntime
|
|
932
1084
|
|
|
933
1085
|
// Auth and Models
|
|
934
1086
|
AuthStorage
|
|
@@ -940,6 +1092,7 @@ type ResourceLoader
|
|
|
940
1092
|
createEventBus
|
|
941
1093
|
|
|
942
1094
|
// Helpers
|
|
1095
|
+
defineTool
|
|
943
1096
|
|
|
944
1097
|
// Session management
|
|
945
1098
|
SessionManager
|
package/docs/settings.md
CHANGED
|
@@ -137,7 +137,7 @@ When a provider requests a retry delay longer than `maxDelayMs` (e.g., Google's
|
|
|
137
137
|
{ "sessionDir": ".pi/sessions" }
|
|
138
138
|
```
|
|
139
139
|
|
|
140
|
-
When multiple sources specify a session directory, `--session-dir` CLI flag takes precedence
|
|
140
|
+
When multiple sources specify a session directory, `--session-dir` CLI flag takes precedence over `sessionDir` in settings.json.
|
|
141
141
|
|
|
142
142
|
### Model Cycling
|
|
143
143
|
|
package/docs/tree.md
CHANGED
|
@@ -13,7 +13,7 @@ Sessions are stored as trees where each entry has an `id` and `parentId`. The "l
|
|
|
13
13
|
| View | Flat list of user messages | Full tree structure |
|
|
14
14
|
| Action | Extracts path to **new session file** | Changes leaf in **same session** |
|
|
15
15
|
| Summary | Never | Optional (user prompted) |
|
|
16
|
-
| Events | `session_before_fork` / `
|
|
16
|
+
| Events | `session_before_fork` / `session_start` (`reason: "fork"`) | `session_before_tree` / `session_tree` |
|
|
17
17
|
|
|
18
18
|
## Tree UI
|
|
19
19
|
|
|
@@ -35,6 +35,8 @@ Sessions are stored as trees where each entry has an `id` and `parentId`. The "l
|
|
|
35
35
|
| ↑/↓ | Navigate (depth-first order) |
|
|
36
36
|
| ←/→ | Page up/down |
|
|
37
37
|
| Ctrl+←/Ctrl+→ or Alt+←/Alt+→ | Fold/unfold and jump between branch segments |
|
|
38
|
+
| Shift+L | Set or clear a label on the selected node |
|
|
39
|
+
| Shift+T | Toggle label timestamps |
|
|
38
40
|
| Enter | Select node |
|
|
39
41
|
| Escape/Ctrl+C | Cancel |
|
|
40
42
|
| Ctrl+U | Toggle: user messages only |
|
|
@@ -49,11 +51,12 @@ Sessions are stored as trees where each entry has an `id` and `parentId`. The "l
|
|
|
49
51
|
- Height: half terminal height
|
|
50
52
|
- Current leaf marked with `← active`
|
|
51
53
|
- Labels shown inline: `[label-name]`
|
|
54
|
+
- `Shift+T` shows the latest label-change timestamp next to labeled nodes
|
|
52
55
|
- Foldable branch starts show `⊟` in the connector. Folded branches show `⊞`
|
|
53
56
|
- Active path marker `•` appears after the fold indicator when applicable
|
|
54
57
|
- Search and filter changes reset all folds
|
|
55
58
|
- Default filter hides `label` and `custom` entries (shown in Ctrl+O mode)
|
|
56
|
-
-
|
|
59
|
+
- At each branch point, the active subtree is shown first; other sibling branches are sorted by timestamp (oldest first)
|
|
57
60
|
|
|
58
61
|
## Selection Behavior
|
|
59
62
|
|
|
@@ -141,7 +144,7 @@ Flow:
|
|
|
141
144
|
4. Fire `session_before_tree` event (hook can cancel or provide summary)
|
|
142
145
|
5. Run default summarizer if needed
|
|
143
146
|
6. Switch leaf via `branch()` or `branchWithSummary()`
|
|
144
|
-
7. Update agent: `agent.
|
|
147
|
+
7. Update agent: `agent.state.messages = sessionManager.buildSessionContext().messages`
|
|
145
148
|
8. Fire `session_tree` event
|
|
146
149
|
9. Notify custom tools via session event
|
|
147
150
|
10. Return result with `editorText` if user message was selected
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-extension-custom-provider",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.16.0",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "pi-extension-custom-provider",
|
|
9
|
-
"version": "1.
|
|
9
|
+
"version": "1.16.0",
|
|
10
10
|
"dependencies": {
|
|
11
11
|
"@anthropic-ai/sdk": "^0.52.0"
|
|
12
12
|
}
|
|
@@ -3,23 +3,24 @@
|
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
5
|
import { Type } from "@mariozechner/pi-ai";
|
|
6
|
-
import type
|
|
6
|
+
import { defineTool, type ExtensionAPI } from "@mariozechner/pi-coding-agent";
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
8
|
+
const helloTool = defineTool({
|
|
9
|
+
name: "hello",
|
|
10
|
+
label: "Hello",
|
|
11
|
+
description: "A simple greeting tool",
|
|
12
|
+
parameters: Type.Object({
|
|
13
|
+
name: Type.String({ description: "Name to greet" }),
|
|
14
|
+
}),
|
|
15
|
+
|
|
16
|
+
async execute(_toolCallId, params, _signal, _onUpdate, _ctx) {
|
|
17
|
+
return {
|
|
18
|
+
content: [{ type: "text", text: `Hello, ${params.name}!` }],
|
|
19
|
+
details: { greeted: params.name },
|
|
20
|
+
};
|
|
21
|
+
},
|
|
22
|
+
});
|
|
16
23
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
return {
|
|
20
|
-
content: [{ type: "text", text: `Hello, ${name}!` }],
|
|
21
|
-
details: { greeted: name },
|
|
22
|
-
};
|
|
23
|
-
},
|
|
24
|
-
});
|
|
24
|
+
export default function (pi: ExtensionAPI) {
|
|
25
|
+
pi.registerTool(helloTool);
|
|
25
26
|
}
|
|
@@ -33,10 +33,6 @@ export default function (pi: ExtensionAPI) {
|
|
|
33
33
|
applyLabel(ctx);
|
|
34
34
|
});
|
|
35
35
|
|
|
36
|
-
pi.on("session_switch", async (_event, ctx) => {
|
|
37
|
-
applyLabel(ctx);
|
|
38
|
-
});
|
|
39
|
-
|
|
40
36
|
pi.registerCommand("thinking-label", {
|
|
41
37
|
description: "Set the hidden thinking label. Use without args to reset.",
|
|
42
38
|
handler: async (args, ctx) => {
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
* - notify() - after each dialog completes
|
|
14
14
|
* - setStatus() - on turn_start/turn_end
|
|
15
15
|
* - setWidget() - on session_start
|
|
16
|
-
* - setTitle() - on session_start
|
|
16
|
+
* - setTitle() - on session_start
|
|
17
17
|
* - setEditorText() - via /rpc-prefill command
|
|
18
18
|
*/
|
|
19
19
|
|
|
@@ -24,18 +24,12 @@ export default function (pi: ExtensionAPI) {
|
|
|
24
24
|
|
|
25
25
|
// -- setTitle, setWidget, setStatus on session lifecycle --
|
|
26
26
|
|
|
27
|
-
pi.on("session_start", async (
|
|
28
|
-
ctx.ui.setTitle("pi RPC Demo");
|
|
27
|
+
pi.on("session_start", async (event, ctx) => {
|
|
28
|
+
ctx.ui.setTitle(event.reason === "new" ? "pi RPC Demo (new session)" : "pi RPC Demo");
|
|
29
29
|
ctx.ui.setWidget("rpc-demo", ["--- RPC Extension UI Demo ---", "Loaded and ready."]);
|
|
30
30
|
ctx.ui.setStatus("rpc-demo", `Turns: ${turnCount}`);
|
|
31
31
|
});
|
|
32
32
|
|
|
33
|
-
pi.on("session_switch", async (_event, ctx) => {
|
|
34
|
-
turnCount = 0;
|
|
35
|
-
ctx.ui.setTitle("pi RPC Demo (new session)");
|
|
36
|
-
ctx.ui.setStatus("rpc-demo", `Turns: ${turnCount}`);
|
|
37
|
-
});
|
|
38
|
-
|
|
39
33
|
// -- setStatus on turn lifecycle --
|
|
40
34
|
|
|
41
35
|
pi.on("turn_start", async (_event, ctx) => {
|
|
@@ -29,12 +29,4 @@ export default function (pi: ExtensionAPI) {
|
|
|
29
29
|
const text = theme.fg("dim", ` Turn ${turnCount} complete`);
|
|
30
30
|
ctx.ui.setStatus("status-demo", check + text);
|
|
31
31
|
});
|
|
32
|
-
|
|
33
|
-
pi.on("session_switch", async (event, ctx) => {
|
|
34
|
-
if (event.reason === "new") {
|
|
35
|
-
turnCount = 0;
|
|
36
|
-
const theme = ctx.ui.theme;
|
|
37
|
-
ctx.ui.setStatus("status-demo", theme.fg("dim", "Ready"));
|
|
38
|
-
}
|
|
39
|
-
});
|
|
40
32
|
}
|