pi-openai-toolkit 0.6.0 → 0.7.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/README.md +21 -3
- package/README_zh.md +21 -3
- package/package.json +6 -1
- package/src/config.ts +69 -0
- package/src/deferred-tool-carryover.ts +280 -0
- package/src/extension-runtime.ts +9 -1
- package/src/inline-compaction.ts +1264 -0
- package/src/payload-rewrite.ts +22 -16
- package/src/types.ts +94 -1
- package/tsconfig.check.json +2 -0
package/src/payload-rewrite.ts
CHANGED
|
@@ -7,6 +7,7 @@ import type {
|
|
|
7
7
|
SessionMessageEntry,
|
|
8
8
|
} from "@earendil-works/pi-coding-agent";
|
|
9
9
|
import type { ResponsesCompatibleRequestPayload } from "./runtime";
|
|
10
|
+
import { rewritePayloadWithDeferredToolCarryover } from "./deferred-tool-carryover";
|
|
10
11
|
import type { NativeCompactionEntry } from "./types";
|
|
11
12
|
import {
|
|
12
13
|
compareResponsesInputParity,
|
|
@@ -503,6 +504,25 @@ function buildNativeReplaySegmentsInternal<TApi extends Api>(args: {
|
|
|
503
504
|
postCompactionTailMessages,
|
|
504
505
|
actualPostCompactionTail,
|
|
505
506
|
);
|
|
507
|
+
const baseRewrittenPayload: ResponsesCompatibleRequestPayload = {
|
|
508
|
+
...args.payload,
|
|
509
|
+
...(freshPreamble.instructions !== undefined ? { instructions: freshPreamble.instructions } : {}),
|
|
510
|
+
input: [
|
|
511
|
+
...freshPreamble.leadingInput,
|
|
512
|
+
...compactedWindow,
|
|
513
|
+
...actualPostCompactionTail,
|
|
514
|
+
...freshPreamble.trailingInput,
|
|
515
|
+
],
|
|
516
|
+
};
|
|
517
|
+
const carryoverRewrite = rewritePayloadWithDeferredToolCarryover({
|
|
518
|
+
payload: baseRewrittenPayload,
|
|
519
|
+
carryover: details.deferredToolCarryover,
|
|
520
|
+
compactionEntryId: args.compactionEntry.id,
|
|
521
|
+
checkpointEndIndex: freshPreamble.leadingInput.length + compactedWindow.length,
|
|
522
|
+
compat: args.model.compat as
|
|
523
|
+
| { supportsAdditionalTools?: boolean; supportsToolSearch?: boolean }
|
|
524
|
+
| undefined,
|
|
525
|
+
});
|
|
506
526
|
|
|
507
527
|
return {
|
|
508
528
|
ok: true,
|
|
@@ -517,23 +537,9 @@ function buildNativeReplaySegmentsInternal<TApi extends Api>(args: {
|
|
|
517
537
|
compactedWindow,
|
|
518
538
|
postCompactionTail,
|
|
519
539
|
originalPiReplayInput,
|
|
520
|
-
replayInput:
|
|
521
|
-
...freshPreamble.leadingInput,
|
|
522
|
-
...compactedWindow,
|
|
523
|
-
...actualPostCompactionTail,
|
|
524
|
-
...freshPreamble.trailingInput,
|
|
525
|
-
],
|
|
526
|
-
},
|
|
527
|
-
rewrittenPayload: {
|
|
528
|
-
...args.payload,
|
|
529
|
-
...(freshPreamble.instructions !== undefined ? { instructions: freshPreamble.instructions } : {}),
|
|
530
|
-
input: [
|
|
531
|
-
...freshPreamble.leadingInput,
|
|
532
|
-
...compactedWindow,
|
|
533
|
-
...actualPostCompactionTail,
|
|
534
|
-
...freshPreamble.trailingInput,
|
|
535
|
-
],
|
|
540
|
+
replayInput: carryoverRewrite.payload.input,
|
|
536
541
|
},
|
|
542
|
+
rewrittenPayload: carryoverRewrite.payload,
|
|
537
543
|
};
|
|
538
544
|
}
|
|
539
545
|
|
package/src/types.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { ThinkingLevel } from "@earendil-works/pi-agent-core";
|
|
2
|
-
import type { CompactionEntry, CompactionResult, ExtensionContext } from "@earendil-works/pi-coding-agent";
|
|
2
|
+
import type { CompactionEntry, CompactionResult, ExtensionContext, SessionEntry } from "@earendil-works/pi-coding-agent";
|
|
3
3
|
|
|
4
4
|
export const TOOLKIT_ID = "pi-openai-toolkit";
|
|
5
5
|
export const COMPACTION_EXTENSION_ID = `${TOOLKIT_ID}:compaction`;
|
|
@@ -36,6 +36,15 @@ export type DebugArtifactKind =
|
|
|
36
36
|
| "compaction-event"
|
|
37
37
|
| "lifecycle";
|
|
38
38
|
|
|
39
|
+
export type CompactionContinuationMode = "inline" | "followUp" | "off";
|
|
40
|
+
|
|
41
|
+
export type AutoCompactionConfig = {
|
|
42
|
+
enabled: boolean;
|
|
43
|
+
continuation: CompactionContinuationMode;
|
|
44
|
+
unsupportedFallback: "followUp" | "off";
|
|
45
|
+
reserveTokens?: number;
|
|
46
|
+
};
|
|
47
|
+
|
|
39
48
|
export type CompactionConfig = {
|
|
40
49
|
enabled: boolean;
|
|
41
50
|
/**
|
|
@@ -55,6 +64,8 @@ export type CompactionConfig = {
|
|
|
55
64
|
model?: string;
|
|
56
65
|
/** Thinking level passed to pi's native compact() when the fallback model runs. */
|
|
57
66
|
thinkingLevel: ThinkingLevel;
|
|
67
|
+
/** Threshold-triggered compaction and same-tool-loop continuation policy. */
|
|
68
|
+
autoCompaction: AutoCompactionConfig;
|
|
58
69
|
/** Subset of RESPONSES_COMPACT_CAPABLE_APIS that should use remote compaction. */
|
|
59
70
|
responsesApis: string[];
|
|
60
71
|
notifyOnLoad: boolean;
|
|
@@ -135,10 +146,21 @@ export type NativeCompactionIdentity = {
|
|
|
135
146
|
baseUrl: string;
|
|
136
147
|
};
|
|
137
148
|
|
|
149
|
+
export const CACHE_STACK_ACTIVATION_ENTRY_TYPE = "pi-cache-stack.activation-state.v1" as const;
|
|
150
|
+
|
|
151
|
+
export type DeferredToolCarryoverV1 = {
|
|
152
|
+
version: 1;
|
|
153
|
+
source: typeof CACHE_STACK_ACTIVATION_ENTRY_TYPE;
|
|
154
|
+
toolNames: string[];
|
|
155
|
+
catalogHash?: string;
|
|
156
|
+
};
|
|
157
|
+
|
|
138
158
|
export type NativeCompactionDetails = NativeCompactionIdentity & {
|
|
139
159
|
strategy: NativeCompactionStrategy;
|
|
140
160
|
/** Actual producer of the opaque checkpoint; absent on legacy same-model entries. */
|
|
141
161
|
compactionModel?: NativeCompactionIdentity;
|
|
162
|
+
/** Cache-stack activation state captured at this opaque checkpoint. */
|
|
163
|
+
deferredToolCarryover?: DeferredToolCarryoverV1;
|
|
142
164
|
compactedWindow: unknown[];
|
|
143
165
|
compactResponseId?: string;
|
|
144
166
|
createdAt: string;
|
|
@@ -149,6 +171,7 @@ export type NativeCompactionEntry = CompactionEntry<NativeCompactionDetails>;
|
|
|
149
171
|
|
|
150
172
|
export type CreateNativeCompactionDetailsInput = NativeCompactionIdentity & {
|
|
151
173
|
compactionModel?: NativeCompactionIdentity;
|
|
174
|
+
deferredToolCarryover?: DeferredToolCarryoverV1;
|
|
152
175
|
compactedWindow: unknown[];
|
|
153
176
|
compactResponseId?: string;
|
|
154
177
|
createdAt?: string;
|
|
@@ -262,6 +285,64 @@ export function isNativeCompactionIdentity(value: unknown): value is NativeCompa
|
|
|
262
285
|
);
|
|
263
286
|
}
|
|
264
287
|
|
|
288
|
+
export function isDeferredToolCarryover(value: unknown): value is DeferredToolCarryoverV1 {
|
|
289
|
+
if (!isRecord(value) || value.version !== 1 || value.source !== CACHE_STACK_ACTIVATION_ENTRY_TYPE) {
|
|
290
|
+
return false;
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
return (
|
|
294
|
+
Array.isArray(value.toolNames) &&
|
|
295
|
+
value.toolNames.every((name) => isNonEmptyString(name)) &&
|
|
296
|
+
(value.catalogHash === undefined || typeof value.catalogHash === "string")
|
|
297
|
+
);
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
function normalizeDeferredToolCarryover(value: DeferredToolCarryoverV1): DeferredToolCarryoverV1 {
|
|
301
|
+
if (!isDeferredToolCarryover(value)) {
|
|
302
|
+
throw new Error("Invalid deferred tool carryover");
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
return {
|
|
306
|
+
version: 1,
|
|
307
|
+
source: CACHE_STACK_ACTIVATION_ENTRY_TYPE,
|
|
308
|
+
toolNames: [...new Set(value.toolNames.map((name) => name.trim()).filter(Boolean))].sort(),
|
|
309
|
+
...(typeof value.catalogHash === "string" ? { catalogHash: value.catalogHash } : {}),
|
|
310
|
+
};
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
function decodeCacheStackActivationState(value: unknown): DeferredToolCarryoverV1 | undefined {
|
|
314
|
+
if (!isRecord(value) || value.version !== 1 || typeof value.catalogHash !== "string") {
|
|
315
|
+
return undefined;
|
|
316
|
+
}
|
|
317
|
+
if (!Array.isArray(value.activatedTools) || !value.activatedTools.every((name) => typeof name === "string")) {
|
|
318
|
+
return undefined;
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
return normalizeDeferredToolCarryover({
|
|
322
|
+
version: 1,
|
|
323
|
+
source: CACHE_STACK_ACTIVATION_ENTRY_TYPE,
|
|
324
|
+
toolNames: value.activatedTools,
|
|
325
|
+
catalogHash: value.catalogHash,
|
|
326
|
+
});
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
/** Read only the latest valid cache-stack activation snapshot on this branch. */
|
|
330
|
+
export function getLatestDeferredToolCarryover(
|
|
331
|
+
entries: readonly SessionEntry[],
|
|
332
|
+
): DeferredToolCarryoverV1 | undefined {
|
|
333
|
+
for (let index = entries.length - 1; index >= 0; index -= 1) {
|
|
334
|
+
const entry = entries[index];
|
|
335
|
+
if (entry?.type !== "custom" || entry.customType !== CACHE_STACK_ACTIVATION_ENTRY_TYPE) {
|
|
336
|
+
continue;
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
const decoded = decodeCacheStackActivationState(entry.data);
|
|
340
|
+
if (decoded) return decoded;
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
return undefined;
|
|
344
|
+
}
|
|
345
|
+
|
|
265
346
|
export function isNativeCompactionDetails(value: unknown): value is NativeCompactionDetails {
|
|
266
347
|
if (!isRecord(value) || !isNativeCompactionIdentity(value)) {
|
|
267
348
|
return false;
|
|
@@ -272,6 +353,7 @@ export function isNativeCompactionDetails(value: unknown): value is NativeCompac
|
|
|
272
353
|
(candidate.strategy === LEGACY_NATIVE_COMPACTION_STRATEGY ||
|
|
273
354
|
candidate.strategy === REMOTE_V2_COMPACTION_STRATEGY) &&
|
|
274
355
|
(candidate.compactionModel === undefined || isNativeCompactionIdentity(candidate.compactionModel)) &&
|
|
356
|
+
(candidate.deferredToolCarryover === undefined || isDeferredToolCarryover(candidate.deferredToolCarryover)) &&
|
|
275
357
|
Array.isArray(candidate.compactedWindow) &&
|
|
276
358
|
candidate.compactedWindow.every(isCompactedWindowItem) &&
|
|
277
359
|
isNonEmptyString(candidate.createdAt) &&
|
|
@@ -299,6 +381,9 @@ export function createNativeCompactionDetails(input: CreateNativeCompactionDetai
|
|
|
299
381
|
baseUrl: normalizeString(input.compactionModel.baseUrl),
|
|
300
382
|
}
|
|
301
383
|
: undefined,
|
|
384
|
+
deferredToolCarryover: input.deferredToolCarryover
|
|
385
|
+
? normalizeDeferredToolCarryover(input.deferredToolCarryover)
|
|
386
|
+
: undefined,
|
|
302
387
|
compactedWindow: input.compactedWindow.map((item) => cloneStructuredValue(item)),
|
|
303
388
|
compactResponseId: isNonEmptyString(input.compactResponseId) ? normalizeString(input.compactResponseId) : undefined,
|
|
304
389
|
createdAt: isNonEmptyString(input.createdAt) ? normalizeString(input.createdAt) : new Date().toISOString(),
|
|
@@ -325,12 +410,20 @@ export function createNativeCompactionResult(
|
|
|
325
410
|
};
|
|
326
411
|
}
|
|
327
412
|
|
|
413
|
+
export const DEFAULT_AUTO_COMPACTION_CONFIG: AutoCompactionConfig = {
|
|
414
|
+
enabled: true,
|
|
415
|
+
continuation: "inline",
|
|
416
|
+
unsupportedFallback: "followUp",
|
|
417
|
+
reserveTokens: undefined,
|
|
418
|
+
};
|
|
419
|
+
|
|
328
420
|
export const DEFAULT_COMPACTION_CONFIG: CompactionConfig = {
|
|
329
421
|
enabled: true,
|
|
330
422
|
allowCompactionContinuityBreak: false,
|
|
331
423
|
remoteCompactModel: undefined,
|
|
332
424
|
model: undefined,
|
|
333
425
|
thinkingLevel: "off",
|
|
426
|
+
autoCompaction: { ...DEFAULT_AUTO_COMPACTION_CONFIG },
|
|
334
427
|
responsesApis: [...RESPONSES_COMPACT_CAPABLE_APIS],
|
|
335
428
|
notifyOnLoad: false,
|
|
336
429
|
debug: false,
|