@code-yeongyu/senpi-agent-core 2026.9.30 → 2026.10.1-3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +49 -20
- package/dist/agent-loop.d.ts +27 -3
- package/dist/agent-loop.js +192 -56
- package/dist/agent.d.ts +21 -7
- package/dist/agent.js +38 -18
- package/dist/harness/execution/tools.d.ts +1 -1
- package/dist/harness/execution/tools.js +0 -2
- package/dist/harness/messages.js +1 -0
- package/dist/harness/pico3/bash.d.ts +10 -0
- package/dist/harness/pico3/bash.js +25 -0
- package/dist/harness/pico3/bounded.d.ts +21 -0
- package/dist/harness/pico3/bounded.js +95 -0
- package/dist/harness/pico3/chord.d.ts +41 -0
- package/dist/harness/pico3/chord.js +147 -0
- package/dist/harness/pico3/context.d.ts +16 -0
- package/dist/harness/pico3/context.js +88 -0
- package/dist/harness/pico3/harness.d.ts +198 -0
- package/dist/harness/pico3/harness.js +645 -0
- package/dist/harness/pico3/hooks.d.ts +10 -0
- package/dist/harness/pico3/hooks.js +33 -0
- package/dist/harness/pico3/index.d.ts +19 -0
- package/dist/harness/pico3/index.js +15 -0
- package/dist/harness/pico3/jsonl.d.ts +58 -0
- package/dist/harness/pico3/jsonl.js +322 -0
- package/dist/harness/pico3/kinds/collapse.d.ts +49 -0
- package/dist/harness/pico3/kinds/collapse.js +191 -0
- package/dist/harness/pico3/kinds/entries.d.ts +78 -0
- package/dist/harness/pico3/kinds/entries.js +13 -0
- package/dist/harness/pico3/kinds/frames.d.ts +9 -0
- package/dist/harness/pico3/kinds/frames.js +75 -0
- package/dist/harness/pico3/kinds/generation.d.ts +94 -0
- package/dist/harness/pico3/kinds/generation.js +504 -0
- package/dist/harness/pico3/kinds/job.d.ts +44 -0
- package/dist/harness/pico3/kinds/job.js +143 -0
- package/dist/harness/pico3/kinds/plugin.d.ts +15 -0
- package/dist/harness/pico3/kinds/plugin.js +35 -0
- package/dist/harness/pico3/kinds/post-tools.d.ts +22 -0
- package/dist/harness/pico3/kinds/post-tools.js +145 -0
- package/dist/harness/pico3/kinds/task-api.d.ts +3 -0
- package/dist/harness/pico3/kinds/task-api.js +45 -0
- package/dist/harness/pico3/kinds/tool.d.ts +43 -0
- package/dist/harness/pico3/kinds/tool.js +373 -0
- package/dist/harness/pico3/legacy-tracker.d.ts +11 -0
- package/dist/harness/pico3/legacy-tracker.js +39 -0
- package/dist/harness/pico3/membrane.d.ts +23 -0
- package/dist/harness/pico3/membrane.js +140 -0
- package/dist/harness/pico3/memory.d.ts +53 -0
- package/dist/harness/pico3/memory.js +265 -0
- package/dist/harness/pico3/scheduler.d.ts +49 -0
- package/dist/harness/pico3/scheduler.js +437 -0
- package/dist/harness/pico3/session.d.ts +264 -0
- package/dist/harness/pico3/session.js +1328 -0
- package/dist/harness/pico3/system.d.ts +126 -0
- package/dist/harness/pico3/system.js +244 -0
- package/dist/harness/pico3/types.d.ts +973 -0
- package/dist/harness/pico3/types.js +94 -0
- package/dist/harness/pico3/view.d.ts +34 -0
- package/dist/harness/pico3/view.js +404 -0
- package/dist/harness/runtime/drive/tool-placement.js +2 -27
- package/dist/harness/telemetry.d.ts +36 -36
- package/dist/harness/tools/image.js +1 -1
- package/dist/proxy.d.ts +2 -2
- package/dist/types.d.ts +111 -34
- package/package.json +9 -5
|
@@ -128,6 +128,12 @@ export declare const HARNESS_TELEMETRY_SCHEMA: {
|
|
|
128
128
|
readonly kind: "root_or_external";
|
|
129
129
|
};
|
|
130
130
|
readonly startAttributes: {
|
|
131
|
+
readonly "pi.operation.kind": {
|
|
132
|
+
readonly type: "string";
|
|
133
|
+
readonly required: true;
|
|
134
|
+
readonly values: readonly ["run"];
|
|
135
|
+
readonly description: "Run operation kind";
|
|
136
|
+
};
|
|
131
137
|
readonly "pi.session.id": {
|
|
132
138
|
readonly type: "string";
|
|
133
139
|
readonly required: true;
|
|
@@ -151,12 +157,6 @@ export declare const HARNESS_TELEMETRY_SCHEMA: {
|
|
|
151
157
|
readonly required: true;
|
|
152
158
|
readonly description: "Whether this invocation resumes durable work";
|
|
153
159
|
};
|
|
154
|
-
readonly "pi.operation.kind": {
|
|
155
|
-
readonly type: "string";
|
|
156
|
-
readonly required: true;
|
|
157
|
-
readonly values: readonly ["run"];
|
|
158
|
-
readonly description: "Run operation kind";
|
|
159
|
-
};
|
|
160
160
|
};
|
|
161
161
|
readonly endAttributes: {
|
|
162
162
|
readonly "pi.error.code": {
|
|
@@ -186,6 +186,12 @@ export declare const HARNESS_TELEMETRY_SCHEMA: {
|
|
|
186
186
|
readonly kind: "root_or_external";
|
|
187
187
|
};
|
|
188
188
|
readonly startAttributes: {
|
|
189
|
+
readonly "pi.operation.kind": {
|
|
190
|
+
readonly type: "string";
|
|
191
|
+
readonly required: true;
|
|
192
|
+
readonly values: readonly ["compaction"];
|
|
193
|
+
readonly description: "Compaction operation kind";
|
|
194
|
+
};
|
|
189
195
|
readonly "pi.session.id": {
|
|
190
196
|
readonly type: "string";
|
|
191
197
|
readonly required: true;
|
|
@@ -209,12 +215,6 @@ export declare const HARNESS_TELEMETRY_SCHEMA: {
|
|
|
209
215
|
readonly required: true;
|
|
210
216
|
readonly description: "Whether this invocation resumes durable work";
|
|
211
217
|
};
|
|
212
|
-
readonly "pi.operation.kind": {
|
|
213
|
-
readonly type: "string";
|
|
214
|
-
readonly required: true;
|
|
215
|
-
readonly values: readonly ["compaction"];
|
|
216
|
-
readonly description: "Compaction operation kind";
|
|
217
|
-
};
|
|
218
218
|
};
|
|
219
219
|
readonly endAttributes: {
|
|
220
220
|
readonly "pi.error.code": {
|
|
@@ -244,6 +244,12 @@ export declare const HARNESS_TELEMETRY_SCHEMA: {
|
|
|
244
244
|
readonly kind: "root_or_external";
|
|
245
245
|
};
|
|
246
246
|
readonly startAttributes: {
|
|
247
|
+
readonly "pi.operation.kind": {
|
|
248
|
+
readonly type: "string";
|
|
249
|
+
readonly required: true;
|
|
250
|
+
readonly values: readonly ["navigation"];
|
|
251
|
+
readonly description: "Navigation operation kind";
|
|
252
|
+
};
|
|
247
253
|
readonly "pi.session.id": {
|
|
248
254
|
readonly type: "string";
|
|
249
255
|
readonly required: true;
|
|
@@ -267,12 +273,6 @@ export declare const HARNESS_TELEMETRY_SCHEMA: {
|
|
|
267
273
|
readonly required: true;
|
|
268
274
|
readonly description: "Whether this invocation resumes durable work";
|
|
269
275
|
};
|
|
270
|
-
readonly "pi.operation.kind": {
|
|
271
|
-
readonly type: "string";
|
|
272
|
-
readonly required: true;
|
|
273
|
-
readonly values: readonly ["navigation"];
|
|
274
|
-
readonly description: "Navigation operation kind";
|
|
275
|
-
};
|
|
276
276
|
};
|
|
277
277
|
readonly endAttributes: {
|
|
278
278
|
readonly "pi.error.code": {
|
|
@@ -738,6 +738,12 @@ export declare const AGENT_TELEMETRY_SCHEMAS: readonly [{
|
|
|
738
738
|
readonly kind: "root_or_external";
|
|
739
739
|
};
|
|
740
740
|
readonly startAttributes: {
|
|
741
|
+
readonly "pi.operation.kind": {
|
|
742
|
+
readonly type: "string";
|
|
743
|
+
readonly required: true;
|
|
744
|
+
readonly values: readonly ["run"];
|
|
745
|
+
readonly description: "Run operation kind";
|
|
746
|
+
};
|
|
741
747
|
readonly "pi.session.id": {
|
|
742
748
|
readonly type: "string";
|
|
743
749
|
readonly required: true;
|
|
@@ -761,12 +767,6 @@ export declare const AGENT_TELEMETRY_SCHEMAS: readonly [{
|
|
|
761
767
|
readonly required: true;
|
|
762
768
|
readonly description: "Whether this invocation resumes durable work";
|
|
763
769
|
};
|
|
764
|
-
readonly "pi.operation.kind": {
|
|
765
|
-
readonly type: "string";
|
|
766
|
-
readonly required: true;
|
|
767
|
-
readonly values: readonly ["run"];
|
|
768
|
-
readonly description: "Run operation kind";
|
|
769
|
-
};
|
|
770
770
|
};
|
|
771
771
|
readonly endAttributes: {
|
|
772
772
|
readonly "pi.error.code": {
|
|
@@ -796,6 +796,12 @@ export declare const AGENT_TELEMETRY_SCHEMAS: readonly [{
|
|
|
796
796
|
readonly kind: "root_or_external";
|
|
797
797
|
};
|
|
798
798
|
readonly startAttributes: {
|
|
799
|
+
readonly "pi.operation.kind": {
|
|
800
|
+
readonly type: "string";
|
|
801
|
+
readonly required: true;
|
|
802
|
+
readonly values: readonly ["compaction"];
|
|
803
|
+
readonly description: "Compaction operation kind";
|
|
804
|
+
};
|
|
799
805
|
readonly "pi.session.id": {
|
|
800
806
|
readonly type: "string";
|
|
801
807
|
readonly required: true;
|
|
@@ -819,12 +825,6 @@ export declare const AGENT_TELEMETRY_SCHEMAS: readonly [{
|
|
|
819
825
|
readonly required: true;
|
|
820
826
|
readonly description: "Whether this invocation resumes durable work";
|
|
821
827
|
};
|
|
822
|
-
readonly "pi.operation.kind": {
|
|
823
|
-
readonly type: "string";
|
|
824
|
-
readonly required: true;
|
|
825
|
-
readonly values: readonly ["compaction"];
|
|
826
|
-
readonly description: "Compaction operation kind";
|
|
827
|
-
};
|
|
828
828
|
};
|
|
829
829
|
readonly endAttributes: {
|
|
830
830
|
readonly "pi.error.code": {
|
|
@@ -854,6 +854,12 @@ export declare const AGENT_TELEMETRY_SCHEMAS: readonly [{
|
|
|
854
854
|
readonly kind: "root_or_external";
|
|
855
855
|
};
|
|
856
856
|
readonly startAttributes: {
|
|
857
|
+
readonly "pi.operation.kind": {
|
|
858
|
+
readonly type: "string";
|
|
859
|
+
readonly required: true;
|
|
860
|
+
readonly values: readonly ["navigation"];
|
|
861
|
+
readonly description: "Navigation operation kind";
|
|
862
|
+
};
|
|
857
863
|
readonly "pi.session.id": {
|
|
858
864
|
readonly type: "string";
|
|
859
865
|
readonly required: true;
|
|
@@ -877,12 +883,6 @@ export declare const AGENT_TELEMETRY_SCHEMAS: readonly [{
|
|
|
877
883
|
readonly required: true;
|
|
878
884
|
readonly description: "Whether this invocation resumes durable work";
|
|
879
885
|
};
|
|
880
|
-
readonly "pi.operation.kind": {
|
|
881
|
-
readonly type: "string";
|
|
882
|
-
readonly required: true;
|
|
883
|
-
readonly values: readonly ["navigation"];
|
|
884
|
-
readonly description: "Navigation operation kind";
|
|
885
|
-
};
|
|
886
886
|
};
|
|
887
887
|
readonly endAttributes: {
|
|
888
888
|
readonly "pi.error.code": {
|
|
@@ -4,7 +4,7 @@ export function detectSupportedImageMimeType(buffer) {
|
|
|
4
4
|
return buffer[3] === 0xf7 ? undefined : "image/jpeg";
|
|
5
5
|
if (startsWith(buffer, PNG_SIGNATURE))
|
|
6
6
|
return isPng(buffer) && !isAnimatedPng(buffer) ? "image/png" : undefined;
|
|
7
|
-
if (startsWithAscii(buffer, 0, "
|
|
7
|
+
if (startsWithAscii(buffer, 0, "GIF87a") || startsWithAscii(buffer, 0, "GIF89a"))
|
|
8
8
|
return "image/gif";
|
|
9
9
|
if (startsWithAscii(buffer, 0, "RIFF") && startsWithAscii(buffer, 8, "WEBP"))
|
|
10
10
|
return "image/webp";
|
package/dist/proxy.d.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Proxy stream function for apps that route LLM calls through a server.
|
|
3
3
|
* The server manages auth and proxies requests to LLM providers.
|
|
4
4
|
*/
|
|
5
|
-
import { type AssistantMessage, type AssistantMessageEvent,
|
|
5
|
+
import { type AssistantMessage, type AssistantMessageEvent, EventStream, type Model, type SimpleStreamOptions, type StopReason, type ToolCall, type TranscriptContext } from "@earendil-works/pi-ai";
|
|
6
6
|
declare class ProxyMessageEventStream extends EventStream<AssistantMessageEvent, AssistantMessage> {
|
|
7
7
|
constructor();
|
|
8
8
|
}
|
|
@@ -71,6 +71,6 @@ export interface ProxyStreamOptions extends ProxySerializableStreamOptions {
|
|
|
71
71
|
/** Proxy server URL (e.g., "https://genai.example.com") */
|
|
72
72
|
proxyUrl: string;
|
|
73
73
|
}
|
|
74
|
-
export declare function streamProxy(model: Model<any>, context:
|
|
74
|
+
export declare function streamProxy(model: Model<any>, context: TranscriptContext, options: ProxyStreamOptions): ProxyMessageEventStream;
|
|
75
75
|
export {};
|
|
76
76
|
//# sourceMappingURL=proxy.d.ts.map
|
package/dist/types.d.ts
CHANGED
|
@@ -1,16 +1,20 @@
|
|
|
1
|
-
import type { Api, AssistantMessage, AssistantMessageEvent, AssistantMessageEventStream,
|
|
1
|
+
import type { Api, AssistantMessage, AssistantMessageEvent, AssistantMessageEventStream, CursorExecHandlers, ImageContent, JsonValue, Message, Model, ProviderDiagnostic, SimpleStreamOptions, TextContent, ThinkingSelection, Tool, ToolResultMessage, TranscriptContext, Usage } from "@earendil-works/pi-ai";
|
|
2
2
|
import type { Static, TSchema } from "typebox";
|
|
3
3
|
/**
|
|
4
4
|
* Stream function used by the agent loop. `Models.streamSimple` satisfies
|
|
5
5
|
* this shape.
|
|
6
6
|
*
|
|
7
|
+
* The loop passes a normalized transcript: the system prompt and tool
|
|
8
|
+
* declarations are carried by the transcript's system messages, never by
|
|
9
|
+
* `context.systemPrompt` or `context.tools`.
|
|
10
|
+
*
|
|
7
11
|
* Contract:
|
|
8
12
|
* - Must not throw or return a rejected promise for request/model/runtime failures.
|
|
9
13
|
* - Must return an AssistantMessageEventStream.
|
|
10
14
|
* - Failures must be encoded in the returned stream via protocol events and a
|
|
11
15
|
* final AssistantMessage with stopReason "error" or "aborted" and errorMessage.
|
|
12
16
|
*/
|
|
13
|
-
export type StreamFn = (model: Model<Api>, context:
|
|
17
|
+
export type StreamFn = (model: Model<Api>, context: TranscriptContext, options?: SimpleStreamOptions) => AssistantMessageEventStream | Promise<AssistantMessageEventStream>;
|
|
14
18
|
/**
|
|
15
19
|
* Configuration for how tool calls from a single assistant message are executed.
|
|
16
20
|
*
|
|
@@ -57,13 +61,17 @@ export interface BeforeToolCallResult {
|
|
|
57
61
|
* - `isError`: if provided, replaces the tool result error flag
|
|
58
62
|
* - `usage`: if provided, replaces the tool result usage
|
|
59
63
|
* - `terminate`: if provided, replaces the early-termination hint
|
|
64
|
+
* - `structuredContent`: if provided, replaces the structured content. If `content` is provided
|
|
65
|
+
* without it, the structured content is dropped, because it may no longer match the content.
|
|
66
|
+
* Return it along with `content` to keep it.
|
|
60
67
|
*
|
|
61
|
-
*
|
|
68
|
+
* Other omitted fields keep the original executed tool result values.
|
|
62
69
|
* There is no deep merge for `content`, `details`, or `usage`.
|
|
63
70
|
*/
|
|
64
71
|
export interface AfterToolCallResult {
|
|
65
72
|
content?: (TextContent | ImageContent)[];
|
|
66
73
|
details?: unknown;
|
|
74
|
+
structuredContent?: JsonValue;
|
|
67
75
|
isError?: boolean;
|
|
68
76
|
/** Usage from the final tool execution itself, if available. Not used for main LLM context accounting. */
|
|
69
77
|
usage?: Usage;
|
|
@@ -99,21 +107,36 @@ export interface AfterToolCallContext {
|
|
|
99
107
|
/** Current agent context at the time the tool call is finalized. */
|
|
100
108
|
context: AgentContext;
|
|
101
109
|
}
|
|
102
|
-
/** Context passed to
|
|
103
|
-
export interface
|
|
110
|
+
/** Context passed to completed-turn callbacks. */
|
|
111
|
+
export interface AgentTurnContext {
|
|
104
112
|
/** The assistant message that completed the turn. */
|
|
105
113
|
message: AssistantMessage;
|
|
106
|
-
/** Tool result messages
|
|
114
|
+
/** Tool result messages emitted for the completed turn. */
|
|
107
115
|
toolResults: ToolResultMessage[];
|
|
108
116
|
/** Current agent context after the turn's assistant message and tool results have been appended. */
|
|
109
117
|
context: AgentContext;
|
|
110
118
|
/** Messages that this loop invocation will return if it exits at this point. Prompt runs include the initial prompt messages; continuation runs do not include pre-existing context messages. */
|
|
111
119
|
newMessages: AgentMessage[];
|
|
112
120
|
}
|
|
121
|
+
/** Decision returned by {@link FinishTurn}. Returning undefined preserves normal scheduling. */
|
|
122
|
+
export type AgentTurnDecision = {
|
|
123
|
+
action: "continue";
|
|
124
|
+
} | {
|
|
125
|
+
action: "end";
|
|
126
|
+
};
|
|
127
|
+
/**
|
|
128
|
+
* Called after a completed assistant turn and all of its tool-result messages, but before `turn_end`.
|
|
129
|
+
* On a normal turn, `{ action: "continue" }` ensures one next provider request. Tool-result, steering, or
|
|
130
|
+
* follow-up scheduling can satisfy that request and adds no extra request; otherwise the loop continues once
|
|
131
|
+
* with the current context. Error and aborted responses remain hard exits.
|
|
132
|
+
*/
|
|
133
|
+
export type FinishTurn = (turn: AgentTurnContext, signal?: AbortSignal) => AgentTurnDecision | void | Promise<AgentTurnDecision | undefined> | Promise<void>;
|
|
113
134
|
/** Replacement runtime state used by the agent loop before starting another provider request. */
|
|
114
135
|
export interface AgentLoopTurnUpdate {
|
|
115
136
|
/** Context for the next provider request. */
|
|
116
137
|
context?: AgentContext;
|
|
138
|
+
/** Messages to append before the next provider request, with normal lifecycle events. */
|
|
139
|
+
messages?: AgentMessage[];
|
|
117
140
|
/** Model for the next provider request. */
|
|
118
141
|
model?: Model<any>;
|
|
119
142
|
/** Thinking level for the next provider request. */
|
|
@@ -123,7 +146,20 @@ export interface AgentLoopTurnUpdate {
|
|
|
123
146
|
/** Whether the next provider request should abort a server-selected fallback. */
|
|
124
147
|
abortServerSideFallback?: boolean;
|
|
125
148
|
}
|
|
126
|
-
|
|
149
|
+
/** Runtime state available immediately before a conversational provider request. */
|
|
150
|
+
export interface PrepareRequestContext {
|
|
151
|
+
context: AgentContext;
|
|
152
|
+
model: Model<any>;
|
|
153
|
+
thinkingLevel: ThinkingLevel;
|
|
154
|
+
}
|
|
155
|
+
/** Replacement runtime state for the provider request being prepared. */
|
|
156
|
+
export type AgentRequestUpdate = Omit<AgentLoopTurnUpdate, "messages">;
|
|
157
|
+
/**
|
|
158
|
+
* Called immediately before every conversational provider request, including the first.
|
|
159
|
+
* Pending messages have already been appended and emitted when this callback runs.
|
|
160
|
+
*/
|
|
161
|
+
export type PrepareRequest = (request: PrepareRequestContext, signal?: AbortSignal) => AgentRequestUpdate | void | Promise<AgentRequestUpdate | undefined> | Promise<void>;
|
|
162
|
+
export interface PrepareNextTurnContext extends AgentTurnContext {
|
|
127
163
|
}
|
|
128
164
|
export interface AgentLoopConfig extends SimpleStreamOptions {
|
|
129
165
|
model: Model<any>;
|
|
@@ -154,7 +190,7 @@ export interface AgentLoopConfig extends SimpleStreamOptions {
|
|
|
154
190
|
/**
|
|
155
191
|
* Converts AgentMessage[] to LLM-compatible Message[] before each LLM call.
|
|
156
192
|
*
|
|
157
|
-
* Each AgentMessage must be converted to a UserMessage, AssistantMessage, or ToolResultMessage
|
|
193
|
+
* Each AgentMessage must be converted to a SystemMessage, UserMessage, AssistantMessage, or ToolResultMessage
|
|
158
194
|
* that the LLM can understand. AgentMessages that cannot be converted (e.g., UI-only notifications,
|
|
159
195
|
* status messages) should be filtered out.
|
|
160
196
|
*
|
|
@@ -209,30 +245,33 @@ export interface AgentLoopConfig extends SimpleStreamOptions {
|
|
|
209
245
|
*/
|
|
210
246
|
getApiKey?: (provider: string) => Promise<string | undefined> | string | undefined;
|
|
211
247
|
/**
|
|
212
|
-
* Called after
|
|
213
|
-
*
|
|
214
|
-
*
|
|
215
|
-
*
|
|
216
|
-
*
|
|
217
|
-
*
|
|
218
|
-
* Use this to request a graceful stop after the current turn, e.g. before context gets too full.
|
|
219
|
-
*
|
|
220
|
-
* Contract: must not throw or reject. Throwing interrupts the low-level agent loop without producing a normal event sequence.
|
|
248
|
+
* Called after the assistant message and all tool-result messages have been emitted, immediately before `turn_end`.
|
|
249
|
+
* `{ action: "end" }` ends the run without polling queues or preparing another request.
|
|
250
|
+
* On a normal turn, `{ action: "continue" }` ensures one next provider request. Tool-result, steering, or
|
|
251
|
+
* follow-up scheduling can satisfy that request and adds no extra request; otherwise the loop continues once
|
|
252
|
+
* with the current context. Returning undefined preserves normal scheduling. Error and aborted responses remain
|
|
253
|
+
* hard exits.
|
|
221
254
|
*/
|
|
222
|
-
|
|
255
|
+
finishTurn?: FinishTurn;
|
|
256
|
+
/**
|
|
257
|
+
* Called immediately before every conversational provider request, including the first.
|
|
258
|
+
* Pending messages have already been appended. The returned context, model, and thinking level
|
|
259
|
+
* replace the runtime values for this and later requests in the run. This hook does not poll queues.
|
|
260
|
+
*/
|
|
261
|
+
prepareRequest?: PrepareRequest;
|
|
223
262
|
/**
|
|
224
263
|
* Called after each completed assistant turn, including a normal stop response, before the loop decides whether another provider request starts.
|
|
225
264
|
* A terminating-tool continuation emits its `turn_start` boundary first so queue owners can clear
|
|
226
265
|
* or replace pending input before preparation finishes and the continuation is admitted.
|
|
227
|
-
* `
|
|
228
|
-
* Return replacement context/model/thinking state to affect the next turn.
|
|
266
|
+
* `finishTurn` returning `{ action: "end" }` and an empty terminating tool batch can end the run before preparation.
|
|
267
|
+
* Return replacement context/model/thinking state or messages to append to affect the next turn.
|
|
229
268
|
* Return undefined to keep using the current context/config.
|
|
230
269
|
*/
|
|
231
270
|
prepareNextTurn?: (context: PrepareNextTurnContext) => AgentLoopTurnUpdate | undefined | Promise<AgentLoopTurnUpdate | undefined>;
|
|
232
271
|
/**
|
|
233
272
|
* Returns steering messages to inject into the conversation mid-run.
|
|
234
273
|
*
|
|
235
|
-
* Called after the current assistant turn finishes executing its tool calls, unless `
|
|
274
|
+
* Called after the current assistant turn finishes executing its tool calls, unless `finishTurn` ends the run.
|
|
236
275
|
* If messages are returned, they are added to the context before the next LLM call.
|
|
237
276
|
* Tool calls from the current assistant message are not skipped.
|
|
238
277
|
*
|
|
@@ -339,7 +378,11 @@ export type AgentMessage = Message | CustomAgentMessages[keyof CustomAgentMessag
|
|
|
339
378
|
* assigned arrays before storing them.
|
|
340
379
|
*/
|
|
341
380
|
export interface AgentState {
|
|
342
|
-
/**
|
|
381
|
+
/**
|
|
382
|
+
* Base system prompt sent with each model request (fork: assignable; the loop folds it into the
|
|
383
|
+
* leading system message through `normalizeContext()`). Later transcript system messages with
|
|
384
|
+
* `content` or `sections` still apply on top of it.
|
|
385
|
+
*/
|
|
343
386
|
systemPrompt: string;
|
|
344
387
|
/** Active model used for future turns. */
|
|
345
388
|
model: Model<any>;
|
|
@@ -352,12 +395,21 @@ export interface AgentState {
|
|
|
352
395
|
thinkingSelection?: ThinkingSelection;
|
|
353
396
|
/** First reasoning effort on the branch, used to preserve Responses cache prefixes. */
|
|
354
397
|
reasoningBaseline?: string;
|
|
355
|
-
/**
|
|
398
|
+
/**
|
|
399
|
+
* Executable tools. Assigning a new array copies the top-level array.
|
|
400
|
+
*
|
|
401
|
+
* Differences from the tools declared in the transcript are announced to the model
|
|
402
|
+
* with a system message before the next request.
|
|
403
|
+
*/
|
|
356
404
|
set tools(tools: AgentTool<any>[]);
|
|
357
405
|
get tools(): AgentTool<any>[];
|
|
358
406
|
/** Tool list the provider receives when it differs from `tools`; see {@link AgentContext.declaredTools}. */
|
|
359
407
|
declaredTools?: AgentTool<any>[];
|
|
360
|
-
/**
|
|
408
|
+
/**
|
|
409
|
+
* Conversation transcript. Assigning a new array copies the top-level array.
|
|
410
|
+
*
|
|
411
|
+
* System messages in the transcript carry the prompt and tool declarations.
|
|
412
|
+
*/
|
|
361
413
|
set messages(messages: AgentMessage[]);
|
|
362
414
|
get messages(): AgentMessage[];
|
|
363
415
|
/**
|
|
@@ -376,25 +428,39 @@ export interface AgentState {
|
|
|
376
428
|
readonly providerDiagnostic?: ProviderDiagnostic;
|
|
377
429
|
}
|
|
378
430
|
/** Final or partial result produced by a tool. */
|
|
379
|
-
export interface AgentToolResult<T> {
|
|
431
|
+
export interface AgentToolResult<T = JsonValue | undefined> {
|
|
380
432
|
/** Text or image content returned to the model. */
|
|
381
433
|
content: (TextContent | ImageContent)[];
|
|
382
434
|
/** Arbitrary structured details for logs or UI rendering. */
|
|
383
435
|
details: T;
|
|
436
|
+
/**
|
|
437
|
+
* Machine-readable result matching the tool's `outputSchema`, for programmatic callers. Not sent
|
|
438
|
+
* to the model; `content` remains the model-facing result.
|
|
439
|
+
*/
|
|
440
|
+
structuredContent?: JsonValue;
|
|
384
441
|
/** Usage from the final tool execution itself, if available. Not used for main LLM context accounting. */
|
|
385
442
|
usage?: Usage;
|
|
386
|
-
/**
|
|
387
|
-
|
|
443
|
+
/**
|
|
444
|
+
* Report a failure without throwing. The model sees `content` as an error result, like a thrown
|
|
445
|
+
* error, but `details` and `structuredContent` are kept for the UI and programmatic callers.
|
|
446
|
+
*/
|
|
447
|
+
isError?: boolean;
|
|
388
448
|
/**
|
|
389
449
|
* Hint that the agent should stop after the current tool batch.
|
|
390
450
|
* Early termination only happens when every finalized tool result in the batch sets this to true.
|
|
391
451
|
*/
|
|
392
452
|
terminate?: boolean;
|
|
393
453
|
/**
|
|
394
|
-
*
|
|
395
|
-
*
|
|
454
|
+
* Names of tools introduced by this result and available from this transcript point onward
|
|
455
|
+
* (fork lazy-tool activation and tool-search native deferred loading).
|
|
396
456
|
*/
|
|
397
|
-
|
|
457
|
+
addedToolNames?: string[];
|
|
458
|
+
}
|
|
459
|
+
/** Final outcome of a tool call after hooks ran. */
|
|
460
|
+
export interface AgentToolCallOutcome {
|
|
461
|
+
toolCall: AgentToolCall;
|
|
462
|
+
result: AgentToolResult<any>;
|
|
463
|
+
isError: boolean;
|
|
398
464
|
}
|
|
399
465
|
/**
|
|
400
466
|
* Callback used by tools to stream partial execution updates.
|
|
@@ -412,7 +478,15 @@ export interface AgentTool<TParameters extends TSchema = TSchema, TDetails = any
|
|
|
412
478
|
* Must return an object that matches `TParameters`.
|
|
413
479
|
*/
|
|
414
480
|
prepareArguments?: (args: unknown) => Static<TParameters>;
|
|
415
|
-
/**
|
|
481
|
+
/**
|
|
482
|
+
* JSON Schema of `structuredContent` in successful results. Tools that declare it should always
|
|
483
|
+
* set `structuredContent`.
|
|
484
|
+
*/
|
|
485
|
+
outputSchema?: TSchema;
|
|
486
|
+
/**
|
|
487
|
+
* Execute the tool call. Throw on failure, or return a result with `isError: true`; do not only
|
|
488
|
+
* describe the failure in `content`.
|
|
489
|
+
*/
|
|
416
490
|
execute: (toolCallId: string, params: Static<TParameters>, signal?: AbortSignal, onUpdate?: AgentToolUpdateCallback<TDetails>) => Promise<AgentToolResult<TDetails>>;
|
|
417
491
|
/** Recovery policy for an effect whose durable intent exists but whose outcome is unknown. */
|
|
418
492
|
replay?: "never" | "safe";
|
|
@@ -427,11 +501,14 @@ export interface AgentTool<TParameters extends TSchema = TSchema, TDetails = any
|
|
|
427
501
|
}
|
|
428
502
|
/** Context snapshot passed into the low-level agent loop. */
|
|
429
503
|
export interface AgentContext {
|
|
430
|
-
/**
|
|
431
|
-
|
|
504
|
+
/**
|
|
505
|
+
* Fork shorthand for the leading system message; `buildProviderContext` folds it with
|
|
506
|
+
* `normalizeContext()`. Upstream-built contexts carry the prompt in transcript system messages.
|
|
507
|
+
*/
|
|
508
|
+
systemPrompt?: string;
|
|
432
509
|
/** Transcript visible to the model. */
|
|
433
510
|
messages: AgentMessage[];
|
|
434
|
-
/** Tools available for this run. */
|
|
511
|
+
/** Tools available for execution in this run. */
|
|
435
512
|
tools?: AgentTool<any>[];
|
|
436
513
|
/**
|
|
437
514
|
* Superset of `tools` to declare to the provider, keeping the tool prefix byte-stable while the
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@code-yeongyu/senpi-agent-core",
|
|
3
|
-
"version": "2026.
|
|
3
|
+
"version": "2026.10.1-3",
|
|
4
4
|
"description": "General-purpose agent with transport abstraction, state management, and attachment support",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -18,6 +18,10 @@
|
|
|
18
18
|
"types": "./dist/harness/context.d.ts",
|
|
19
19
|
"import": "./dist/harness/context.js"
|
|
20
20
|
},
|
|
21
|
+
"./experimental/pico3": {
|
|
22
|
+
"types": "./dist/harness/pico3/index.d.ts",
|
|
23
|
+
"import": "./dist/harness/pico3/index.js"
|
|
24
|
+
},
|
|
21
25
|
"./harness/env/nodejs": {
|
|
22
26
|
"types": "./dist/harness/env/nodejs.d.ts",
|
|
23
27
|
"import": "./dist/harness/env/nodejs.js"
|
|
@@ -46,7 +50,7 @@
|
|
|
46
50
|
"clean": "shx rm -rf dist",
|
|
47
51
|
"generate-telemetry-docs": "node scripts/generate-telemetry-docs.ts",
|
|
48
52
|
"check:telemetry-docs": "node scripts/generate-telemetry-docs.ts --check",
|
|
49
|
-
"build": "
|
|
53
|
+
"build": "tsc -p tsconfig.build.json",
|
|
50
54
|
"bench:session:timing": "vitest bench --config vitest.benchmark.config.ts",
|
|
51
55
|
"bench:session:memory": "tsx --tsconfig benchmark/tsconfig.json benchmark/session/loaded-footprint.ts",
|
|
52
56
|
"bench:session:allocations": "tsx --tsconfig benchmark/tsconfig.json benchmark/session/allocation-profile.ts",
|
|
@@ -57,9 +61,9 @@
|
|
|
57
61
|
"prepublishOnly": "npm run build"
|
|
58
62
|
},
|
|
59
63
|
"dependencies": {
|
|
60
|
-
"@earendil-works/chord": "0.
|
|
61
|
-
"@earendil-works/pi-ai": "npm:@code-yeongyu/senpi-ai@2026.
|
|
62
|
-
"@earendil-works/pi-telemetry": "npm:@code-yeongyu/senpi-telemetry@2026.
|
|
64
|
+
"@earendil-works/chord": "0.99.1",
|
|
65
|
+
"@earendil-works/pi-ai": "npm:@code-yeongyu/senpi-ai@2026.10.1-3",
|
|
66
|
+
"@earendil-works/pi-telemetry": "npm:@code-yeongyu/senpi-telemetry@2026.10.1-3",
|
|
63
67
|
"diff": "9.0.0",
|
|
64
68
|
"ignore": "7.0.9",
|
|
65
69
|
"typebox": "1.3.34",
|