@oh-my-pi/pi-agent-core 18.14.0 → 18.14.1
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 +10 -0
- package/dist/types/compaction/compaction-v2-streaming.d.ts +1 -0
- package/dist/types/compaction/compaction.d.ts +2 -0
- package/dist/types/sent-tool-definitions.d.ts +6 -5
- package/package.json +8 -8
- package/src/agent-loop.ts +6 -15
- package/src/agent.ts +4 -5
- package/src/compaction/compaction-v2-streaming.ts +4 -0
- package/src/compaction/compaction.ts +4 -0
- package/src/sent-tool-definitions.ts +12 -5
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,16 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [18.14.1] - 2026-10-31
|
|
6
|
+
|
|
7
|
+
### Breaking Changes
|
|
8
|
+
|
|
9
|
+
- `SentToolDefinitions.inactiveFor(messages, tools)` is replaced by `withInactiveTools(context)`, which also clears a stale `inactiveTools`; `transformProviderContext` now receives the request's `inactiveTools` ([#17492](https://github.com/can1357/oh-my-pi/pull/17492))
|
|
10
|
+
|
|
11
|
+
### Fixed
|
|
12
|
+
|
|
13
|
+
- Long tool-call intents no longer block tool execution when intent tracing is enabled ([#13140](https://github.com/can1357/oh-my-pi/issues/13140)).
|
|
14
|
+
|
|
5
15
|
## [18.14.0] - 2026-10-29
|
|
6
16
|
|
|
7
17
|
### Breaking Changes
|
|
@@ -85,6 +85,7 @@ export declare function requestCompactionV2Streaming(model: Model, apiKey: strin
|
|
|
85
85
|
providerSessionState?: Map<string, ProviderSessionState>;
|
|
86
86
|
codexCompaction?: CodexCompactionContext;
|
|
87
87
|
preferWebsockets?: boolean;
|
|
88
|
+
codexAccessPrograms?: boolean;
|
|
88
89
|
}): Promise<CompactionV2Response>;
|
|
89
90
|
/** Build Codex-style V2 replacement history from retention candidates plus compaction output. */
|
|
90
91
|
export declare function buildCompactionV2ReplacementHistory(input: unknown[], compactionItem: Record<string, unknown>, retainedMessageBudget?: number): {
|
|
@@ -256,6 +256,8 @@ export interface SummaryOptions {
|
|
|
256
256
|
providerSessionState?: Map<string, ProviderSessionState>;
|
|
257
257
|
/** Whether Codex remote compaction should prefer the provider WebSocket transport. */
|
|
258
258
|
preferWebsockets?: boolean;
|
|
259
|
+
/** Daybreak Blue request on Codex remote compaction; see `StreamOptions.codexAccessPrograms`. */
|
|
260
|
+
codexAccessPrograms?: boolean;
|
|
259
261
|
/** Classification shared by every provider request in this logical compaction. */
|
|
260
262
|
codexCompaction?: CodexCompactionContext;
|
|
261
263
|
/** Provider-visible tools for remote compaction transports that replay native tool history. */
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { Context, Tool } from "@oh-my-pi/pi-ai";
|
|
2
2
|
/**
|
|
3
3
|
* Last wire definition this Agent sent for each tool name, so a provider that keeps
|
|
4
4
|
* withdrawn tools declared (Anthropic `tool_removal`) can re-declare them byte-identically.
|
|
@@ -9,9 +9,10 @@ export declare class SentToolDefinitions {
|
|
|
9
9
|
/** Remember the definitions a request is about to send. */
|
|
10
10
|
record(tools: readonly Tool[]): void;
|
|
11
11
|
/**
|
|
12
|
-
*
|
|
13
|
-
* that are not in `
|
|
14
|
-
*
|
|
12
|
+
* `context` with {@link Context.inactiveTools} set to the definitions for names the latest
|
|
13
|
+
* `requestControls.tools.declared` in its messages holds that are not in its `tools`; cleared when
|
|
14
|
+
* there are none or the request declares no tools. Names never sent by this Agent are skipped: the
|
|
15
|
+
* provider drops them from the declaration.
|
|
15
16
|
*/
|
|
16
|
-
|
|
17
|
+
withInactiveTools(context: Context): Context;
|
|
17
18
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"type": "module",
|
|
3
3
|
"name": "@oh-my-pi/pi-agent-core",
|
|
4
|
-
"version": "18.14.
|
|
4
|
+
"version": "18.14.1",
|
|
5
5
|
"description": "General-purpose agent with transport abstraction, state management, and attachment support",
|
|
6
6
|
"homepage": "https://omp.sh",
|
|
7
7
|
"author": {
|
|
@@ -38,16 +38,16 @@
|
|
|
38
38
|
"fmt": "oxfmt --no-error-on-unmatched-pattern 'src/**/*.{ts,tsx}' '{test,bench,examples,scripts}/**/*.ts' '*.ts'"
|
|
39
39
|
},
|
|
40
40
|
"dependencies": {
|
|
41
|
-
"@oh-my-pi/pi-ai": "18.14.
|
|
42
|
-
"@oh-my-pi/pi-catalog": "18.14.
|
|
43
|
-
"@oh-my-pi/pi-natives": "18.14.
|
|
44
|
-
"@oh-my-pi/pi-utils": "18.14.
|
|
45
|
-
"@oh-my-pi/pi-wire": "18.14.
|
|
46
|
-
"@oh-my-pi/snapcompact": "18.14.
|
|
41
|
+
"@oh-my-pi/pi-ai": "18.14.1",
|
|
42
|
+
"@oh-my-pi/pi-catalog": "18.14.1",
|
|
43
|
+
"@oh-my-pi/pi-natives": "18.14.1",
|
|
44
|
+
"@oh-my-pi/pi-utils": "18.14.1",
|
|
45
|
+
"@oh-my-pi/pi-wire": "18.14.1",
|
|
46
|
+
"@oh-my-pi/snapcompact": "18.14.1",
|
|
47
47
|
"@opentelemetry/api": "^1.9.1"
|
|
48
48
|
},
|
|
49
49
|
"devDependencies": {
|
|
50
|
-
"@oh-my-pi/omptype": "18.14.
|
|
50
|
+
"@oh-my-pi/omptype": "18.14.1",
|
|
51
51
|
"@opentelemetry/context-async-hooks": "^2.9.0",
|
|
52
52
|
"@opentelemetry/sdk-trace-base": "^2.9.0",
|
|
53
53
|
"@types/bun": "^1.3.14"
|
package/src/agent-loop.ts
CHANGED
|
@@ -1071,12 +1071,6 @@ function resolveIntentMode(intent: AgentTool["intent"]): "require" | "optional"
|
|
|
1071
1071
|
return "require";
|
|
1072
1072
|
}
|
|
1073
1073
|
|
|
1074
|
-
/**
|
|
1075
|
-
* Longest `i` value accepted as an intent; anything past this is a tool
|
|
1076
|
-
* payload the model put in the wrong field, not an intent.
|
|
1077
|
-
*/
|
|
1078
|
-
const MAX_INTENT_LENGTH = 200;
|
|
1079
|
-
|
|
1080
1074
|
function extractIntent(args: Record<string, unknown>): { intent?: string; strippedArgs: Record<string, unknown> } {
|
|
1081
1075
|
const { [INTENT_FIELD]: intent, ...strippedArgs } = args;
|
|
1082
1076
|
if (typeof intent !== "string") {
|
|
@@ -1976,6 +1970,9 @@ async function prepareProviderCall(
|
|
|
1976
1970
|
}),
|
|
1977
1971
|
};
|
|
1978
1972
|
}
|
|
1973
|
+
// Before the transform too, so a request-size clamp in it measures the withdrawn definitions the provider
|
|
1974
|
+
// re-declares; recomputed below against what the transform returns.
|
|
1975
|
+
if (config.sentToolDefinitions) llmContext = config.sentToolDefinitions.withInactiveTools(llmContext);
|
|
1979
1976
|
if (config.transformProviderContext) {
|
|
1980
1977
|
llmContext = await config.transformProviderContext(llmContext, model);
|
|
1981
1978
|
}
|
|
@@ -1991,10 +1988,9 @@ async function prepareProviderCall(
|
|
|
1991
1988
|
};
|
|
1992
1989
|
}
|
|
1993
1990
|
// After `transformProviderContext`, so the recorded definitions are exactly what the provider receives.
|
|
1994
|
-
if (config.sentToolDefinitions
|
|
1995
|
-
config.sentToolDefinitions.record(llmContext.tools);
|
|
1996
|
-
|
|
1997
|
-
if (inactiveTools) llmContext = { ...llmContext, inactiveTools };
|
|
1991
|
+
if (config.sentToolDefinitions) {
|
|
1992
|
+
if (llmContext.tools) config.sentToolDefinitions.record(llmContext.tools);
|
|
1993
|
+
llmContext = config.sentToolDefinitions.withInactiveTools(llmContext);
|
|
1998
1994
|
}
|
|
1999
1995
|
return { model, context: llmContext, promptToolWireTools, ownedDialect };
|
|
2000
1996
|
}
|
|
@@ -3105,11 +3101,6 @@ async function prepareToolCallDispatch(
|
|
|
3105
3101
|
? { intent: undefined, strippedArgs: argsForExecution }
|
|
3106
3102
|
: extractIntent(toolCall.arguments);
|
|
3107
3103
|
argsForExecution = strippedArgs;
|
|
3108
|
-
if (intent !== undefined && intent.length > MAX_INTENT_LENGTH && tool) {
|
|
3109
|
-
entry.args = strippedArgs;
|
|
3110
|
-
entry.validationErrorMessage = `\`${INTENT_FIELD}\` is a short intent label (at most ${MAX_INTENT_LENGTH} chars); the value you sent is ${intent.length} chars. The tool was not run. Put that content in the tool's own parameters and retry with a brief \`${INTENT_FIELD}\`.`;
|
|
3111
|
-
continue;
|
|
3112
|
-
}
|
|
3113
3104
|
if (intent) {
|
|
3114
3105
|
toolCall.intent = intent;
|
|
3115
3106
|
} else if (typeof tool?.intent === "function") {
|
package/src/agent.ts
CHANGED
|
@@ -959,12 +959,11 @@ export class Agent {
|
|
|
959
959
|
pruneDescriptions: this.#pruneToolDescriptions,
|
|
960
960
|
}) ?? []);
|
|
961
961
|
let context: Context = { systemPrompt, messages, tools };
|
|
962
|
+
// Side requests reuse the main loop's sent definitions without recording their own; attached before the
|
|
963
|
+
// transform too, so a request-size clamp in it measures them.
|
|
964
|
+
context = this.#sentToolDefinitions.withInactiveTools(context);
|
|
962
965
|
if (this.#transformProviderContext) context = await this.#transformProviderContext(context, model);
|
|
963
|
-
|
|
964
|
-
if (context.tools?.length) {
|
|
965
|
-
const inactiveTools = this.#sentToolDefinitions.inactiveFor(context.messages, context.tools);
|
|
966
|
-
if (inactiveTools) context = { ...context, inactiveTools };
|
|
967
|
-
}
|
|
966
|
+
context = this.#sentToolDefinitions.withInactiveTools(context);
|
|
968
967
|
return context;
|
|
969
968
|
}
|
|
970
969
|
|
|
@@ -274,6 +274,7 @@ export async function requestCompactionV2Streaming(
|
|
|
274
274
|
providerSessionState?: Map<string, ProviderSessionState>;
|
|
275
275
|
codexCompaction?: CodexCompactionContext;
|
|
276
276
|
preferWebsockets?: boolean;
|
|
277
|
+
codexAccessPrograms?: boolean;
|
|
277
278
|
},
|
|
278
279
|
): Promise<CompactionV2Response> {
|
|
279
280
|
let fetchImpl: FetchImpl = options?.fetch ?? globalThis.fetch;
|
|
@@ -316,6 +317,7 @@ export async function requestCompactionV2Streaming(
|
|
|
316
317
|
providerSessionState: options?.providerSessionState,
|
|
317
318
|
codexCompaction: options?.codexCompaction,
|
|
318
319
|
preferWebsockets: options?.preferWebsockets,
|
|
320
|
+
codexAccessPrograms: options?.codexAccessPrograms,
|
|
319
321
|
});
|
|
320
322
|
} catch (err) {
|
|
321
323
|
const error = err instanceof Error ? err : new Error(String(err));
|
|
@@ -352,6 +354,7 @@ async function attemptCompactionV2Streaming(
|
|
|
352
354
|
providerSessionState?: Map<string, ProviderSessionState>;
|
|
353
355
|
codexCompaction?: CodexCompactionContext;
|
|
354
356
|
preferWebsockets?: boolean;
|
|
357
|
+
codexAccessPrograms?: boolean;
|
|
355
358
|
},
|
|
356
359
|
): Promise<CompactionV2Response> {
|
|
357
360
|
// Faithful to Codex: append the compaction trigger as the final input item
|
|
@@ -377,6 +380,7 @@ async function attemptCompactionV2Streaming(
|
|
|
377
380
|
sessionId: request.sessionId,
|
|
378
381
|
providerSessionState: options.providerSessionState,
|
|
379
382
|
preferWebsockets: options.preferWebsockets,
|
|
383
|
+
codexAccessPrograms: options.codexAccessPrograms,
|
|
380
384
|
responsesLite: model.useResponsesLite,
|
|
381
385
|
codexCompaction: createOpenAICodexCompactionRequestContext({
|
|
382
386
|
context: options.codexCompaction,
|
|
@@ -750,6 +750,8 @@ export interface SummaryOptions {
|
|
|
750
750
|
providerSessionState?: Map<string, ProviderSessionState>;
|
|
751
751
|
/** Whether Codex remote compaction should prefer the provider WebSocket transport. */
|
|
752
752
|
preferWebsockets?: boolean;
|
|
753
|
+
/** Daybreak Blue request on Codex remote compaction; see `StreamOptions.codexAccessPrograms`. */
|
|
754
|
+
codexAccessPrograms?: boolean;
|
|
753
755
|
/** Classification shared by every provider request in this logical compaction. */
|
|
754
756
|
codexCompaction?: CodexCompactionContext;
|
|
755
757
|
/** Provider-visible tools for remote compaction transports that replay native tool history. */
|
|
@@ -1765,6 +1767,7 @@ export async function compact(
|
|
|
1765
1767
|
: options?.promptCacheKey,
|
|
1766
1768
|
providerSessionState: options?.providerSessionState,
|
|
1767
1769
|
preferWebsockets: options?.preferWebsockets,
|
|
1770
|
+
codexAccessPrograms: options?.codexAccessPrograms,
|
|
1768
1771
|
codexCompaction: options?.codexCompaction,
|
|
1769
1772
|
tools: options?.tools,
|
|
1770
1773
|
fetch: options?.fetch,
|
|
@@ -2000,6 +2003,7 @@ export async function compact(
|
|
|
2000
2003
|
fetch: summaryOptions.fetch,
|
|
2001
2004
|
providerSessionState: summaryOptions.providerSessionState,
|
|
2002
2005
|
preferWebsockets: summaryOptions.preferWebsockets,
|
|
2006
|
+
codexAccessPrograms: summaryOptions.codexAccessPrograms,
|
|
2003
2007
|
codexCompaction: summaryOptions.codexCompaction,
|
|
2004
2008
|
}),
|
|
2005
2009
|
{ signal },
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Message, Tool } from "@oh-my-pi/pi-ai";
|
|
1
|
+
import type { Context, Message, Tool } from "@oh-my-pi/pi-ai";
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Last wire definition this Agent sent for each tool name, so a provider that keeps
|
|
@@ -14,11 +14,18 @@ export class SentToolDefinitions {
|
|
|
14
14
|
}
|
|
15
15
|
|
|
16
16
|
/**
|
|
17
|
-
*
|
|
18
|
-
* that are not in `
|
|
19
|
-
*
|
|
17
|
+
* `context` with {@link Context.inactiveTools} set to the definitions for names the latest
|
|
18
|
+
* `requestControls.tools.declared` in its messages holds that are not in its `tools`; cleared when
|
|
19
|
+
* there are none or the request declares no tools. Names never sent by this Agent are skipped: the
|
|
20
|
+
* provider drops them from the declaration.
|
|
20
21
|
*/
|
|
21
|
-
|
|
22
|
+
withInactiveTools(context: Context): Context {
|
|
23
|
+
const inactiveTools = context.tools?.length ? this.#inactiveFor(context.messages, context.tools) : undefined;
|
|
24
|
+
if (!inactiveTools && !context.inactiveTools) return context;
|
|
25
|
+
return { ...context, inactiveTools };
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
#inactiveFor(messages: readonly Message[], active: readonly Tool[]): Tool[] | undefined {
|
|
22
29
|
let declared: readonly string[] | undefined;
|
|
23
30
|
for (let index = messages.length - 1; index >= 0; index--) {
|
|
24
31
|
const message = messages[index];
|