pi-openai-toolkit 0.14.5 → 0.14.6

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 (35) hide show
  1. package/docs/internals.md +42 -21
  2. package/package.json +1 -1
  3. package/src/auto-mode/classifier.ts +165 -165
  4. package/src/auto-mode/policy.ts +146 -146
  5. package/src/auto-mode/prompt.ts +279 -279
  6. package/src/auto-mode/reviewer.ts +325 -325
  7. package/src/auto-mode/transcript.ts +133 -133
  8. package/src/auto-mode/types.ts +137 -137
  9. package/src/codex-astra/effort-planner.ts +175 -175
  10. package/src/codex-astra/extension.ts +122 -122
  11. package/src/context-management/codex-provider.ts +20 -20
  12. package/src/context-management/history-notes.ts +32 -0
  13. package/src/context-management/messages.ts +112 -106
  14. package/src/context-management/namespace-tools.ts +426 -426
  15. package/src/context-management/tool-contract.ts +23 -23
  16. package/src/context-management/tools.ts +306 -311
  17. package/src/context-management/types.ts +7 -0
  18. package/src/context-management/window-budget.ts +83 -83
  19. package/src/context-management/window-manager.ts +60 -51
  20. package/src/context-management/window-request.ts +125 -125
  21. package/src/debug.ts +1 -1
  22. package/src/extension-runtime.ts +34 -9
  23. package/src/image-generation/artifacts.ts +237 -237
  24. package/src/image-generation/client.ts +248 -248
  25. package/src/image-generation/eligibility.ts +18 -18
  26. package/src/image-generation/references.ts +194 -194
  27. package/src/image-generation/render.ts +252 -252
  28. package/src/model-scope.ts +17 -17
  29. package/src/provider-headers.ts +23 -23
  30. package/src/responses-headers.ts +76 -11
  31. package/src/runtime.ts +37 -1
  32. package/src/web-search/extension.ts +80 -80
  33. package/src/web-search/payload.ts +96 -96
  34. package/src/web-search/prompt.ts +20 -20
  35. package/src/web-search/types.ts +45 -45
@@ -1,146 +1,146 @@
1
- import { isExactModelAllowed } from "../model-scope";
2
- import type { AutoModeCircuitBreakerConfig, AutoModeConfig } from "../types";
3
- import {
4
- SIDE_EFFECT_TOOLS,
5
- type AutoModeGateSource,
6
- type AutoModeModelRef,
7
- } from "./types";
8
-
9
- export type AutoModeRuntimeState = {
10
- engaged: boolean;
11
- /** Gate currently in force: either the configured value or a session override. */
12
- gate: AutoModeGateSource;
13
- /** Session override from `/auto all` or `/auto side`; cleared on session start. */
14
- gateOverride?: AutoModeGateSource;
15
- extraTools: string[];
16
- };
17
-
18
- /**
19
- * Per-turn denial accounting, modelled on Codex's rejection circuit breaker. Without
20
- * it a denied action just becomes an infinite negotiation between the agent and the
21
- * reviewer, which is both expensive and the exact behaviour the anti-circumvention
22
- * clause is trying to stop.
23
- */
24
- export type RejectionBreakerState = {
25
- consecutiveDenials: number;
26
- recentDenials: boolean[];
27
- deniedTools: Set<string>;
28
- interrupted: boolean;
29
- };
30
-
31
- export function createRejectionBreaker(): RejectionBreakerState {
32
- return { consecutiveDenials: 0, recentDenials: [], deniedTools: new Set(), interrupted: false };
33
- }
34
-
35
- /** Clear at turn start: the breaker judges one turn's pattern, not the whole session. */
36
- export function resetRejectionBreaker(state: RejectionBreakerState): void {
37
- state.consecutiveDenials = 0;
38
- state.recentDenials = [];
39
- state.deniedTools.clear();
40
- state.interrupted = false;
41
- }
42
-
43
- function normalizeToolNames(names: readonly string[]): string[] {
44
- return [...new Set(names.map((name) => name.trim()).filter(Boolean))];
45
- }
46
-
47
- /**
48
- * Auto mode needs an allowlisted active model plus a configured reviewer. The
49
- * reviewer model itself is resolved later, so an unknown spec degrades through the
50
- * normal review-unavailable path instead of silently disabling the gate.
51
- */
52
- export function isAutoModeEligible(
53
- model: AutoModeModelRef | undefined,
54
- config: AutoModeConfig,
55
- ): boolean {
56
- if (!config.enabled) return false;
57
- if (!config.reviewerModel) return false;
58
- return isExactModelAllowed(model, config.models);
59
- }
60
-
61
- export function shouldReviewTool(toolName: string, state: AutoModeRuntimeState): boolean {
62
- if (state.gate === "all") return true;
63
- if ((SIDE_EFFECT_TOOLS as readonly string[]).includes(toolName)) return true;
64
- return normalizeToolNames(state.extraTools).includes(toolName);
65
- }
66
-
67
- export function describeGate(state: Pick<AutoModeRuntimeState, "gate" | "extraTools">): string {
68
- if (state.gate === "all") return "all tools";
69
- return [...new Set([...SIDE_EFFECT_TOOLS, ...normalizeToolNames(state.extraTools)])].join(", ");
70
- }
71
-
72
- export function createRuntimeState(config: AutoModeConfig): AutoModeRuntimeState {
73
- return {
74
- engaged: false,
75
- gate: config.gate,
76
- extraTools: normalizeToolNames(config.extraTools),
77
- };
78
- }
79
-
80
- /**
81
- * Refresh the configured gate and tool list without touching engagement: editing
82
- * config changes what gets reviewed, it never silently turns auto mode on or off.
83
- * An explicit `/auto` scope override wins until the next session start.
84
- */
85
- export function applyConfiguredGate(
86
- state: AutoModeRuntimeState,
87
- config: AutoModeConfig,
88
- ): AutoModeRuntimeState {
89
- state.gate = state.gateOverride ?? config.gate;
90
- state.extraTools = normalizeToolNames(config.extraTools);
91
- return state;
92
- }
93
-
94
- export function setGateOverride(
95
- state: AutoModeRuntimeState,
96
- config: AutoModeConfig,
97
- gate: AutoModeGateSource | undefined,
98
- ): AutoModeRuntimeState {
99
- state.gateOverride = gate;
100
- state.gate = gate ?? config.gate;
101
- return state;
102
- }
103
-
104
- /**
105
- * Record one genuine reviewer denial and report whether the turn should stop.
106
- *
107
- * Two independent triggers, matching Codex: a short run of consecutive denials
108
- * means the agent cannot get past the reviewer, and a high denial rate inside a
109
- * sliding window means it keeps trying different unsafe things.
110
- */
111
- export function recordDenial(
112
- state: RejectionBreakerState,
113
- config: AutoModeCircuitBreakerConfig,
114
- toolName: string,
115
- ): "continue" | "interrupt" {
116
- state.consecutiveDenials += 1;
117
- state.deniedTools.add(toolName);
118
- state.recentDenials.push(true);
119
- if (state.recentDenials.length > Math.max(1, config.windowSize)) {
120
- state.recentDenials.splice(0, state.recentDenials.length - config.windowSize);
121
- }
122
-
123
- const recentDenials = state.recentDenials.filter(Boolean).length;
124
- const consecutiveTripped = config.consecutiveDenials > 0 && state.consecutiveDenials >= config.consecutiveDenials;
125
- const rateTripped = config.recentDenials > 0 && recentDenials >= config.recentDenials;
126
- if (consecutiveTripped || rateTripped) {
127
- state.interrupted = true;
128
- return "interrupt";
129
- }
130
- return "continue";
131
- }
132
-
133
- /** Any allowed action resets the consecutive run, so one approval breaks a streak. */
134
- export function recordNonDenial(state: RejectionBreakerState): void {
135
- state.consecutiveDenials = 0;
136
- state.recentDenials.push(false);
137
- }
138
-
139
- /**
140
- * A repeat request for a tool that was already denied in this turn is the shape of
141
- * a workaround attempt, so it must be judged by the blocking reviewer rather than
142
- * accepted on the strength of an earlier low-risk classification.
143
- */
144
- export function wasDeniedThisTurn(state: RejectionBreakerState, toolName: string): boolean {
145
- return state.deniedTools.has(toolName);
146
- }
1
+ import { isExactModelAllowed } from "../model-scope";
2
+ import type { AutoModeCircuitBreakerConfig, AutoModeConfig } from "../types";
3
+ import {
4
+ SIDE_EFFECT_TOOLS,
5
+ type AutoModeGateSource,
6
+ type AutoModeModelRef,
7
+ } from "./types";
8
+
9
+ export type AutoModeRuntimeState = {
10
+ engaged: boolean;
11
+ /** Gate currently in force: either the configured value or a session override. */
12
+ gate: AutoModeGateSource;
13
+ /** Session override from `/auto all` or `/auto side`; cleared on session start. */
14
+ gateOverride?: AutoModeGateSource;
15
+ extraTools: string[];
16
+ };
17
+
18
+ /**
19
+ * Per-turn denial accounting, modelled on Codex's rejection circuit breaker. Without
20
+ * it a denied action just becomes an infinite negotiation between the agent and the
21
+ * reviewer, which is both expensive and the exact behaviour the anti-circumvention
22
+ * clause is trying to stop.
23
+ */
24
+ export type RejectionBreakerState = {
25
+ consecutiveDenials: number;
26
+ recentDenials: boolean[];
27
+ deniedTools: Set<string>;
28
+ interrupted: boolean;
29
+ };
30
+
31
+ export function createRejectionBreaker(): RejectionBreakerState {
32
+ return { consecutiveDenials: 0, recentDenials: [], deniedTools: new Set(), interrupted: false };
33
+ }
34
+
35
+ /** Clear at turn start: the breaker judges one turn's pattern, not the whole session. */
36
+ export function resetRejectionBreaker(state: RejectionBreakerState): void {
37
+ state.consecutiveDenials = 0;
38
+ state.recentDenials = [];
39
+ state.deniedTools.clear();
40
+ state.interrupted = false;
41
+ }
42
+
43
+ function normalizeToolNames(names: readonly string[]): string[] {
44
+ return [...new Set(names.map((name) => name.trim()).filter(Boolean))];
45
+ }
46
+
47
+ /**
48
+ * Auto mode needs an allowlisted active model plus a configured reviewer. The
49
+ * reviewer model itself is resolved later, so an unknown spec degrades through the
50
+ * normal review-unavailable path instead of silently disabling the gate.
51
+ */
52
+ export function isAutoModeEligible(
53
+ model: AutoModeModelRef | undefined,
54
+ config: AutoModeConfig,
55
+ ): boolean {
56
+ if (!config.enabled) return false;
57
+ if (!config.reviewerModel) return false;
58
+ return isExactModelAllowed(model, config.models);
59
+ }
60
+
61
+ export function shouldReviewTool(toolName: string, state: AutoModeRuntimeState): boolean {
62
+ if (state.gate === "all") return true;
63
+ if ((SIDE_EFFECT_TOOLS as readonly string[]).includes(toolName)) return true;
64
+ return normalizeToolNames(state.extraTools).includes(toolName);
65
+ }
66
+
67
+ export function describeGate(state: Pick<AutoModeRuntimeState, "gate" | "extraTools">): string {
68
+ if (state.gate === "all") return "all tools";
69
+ return [...new Set([...SIDE_EFFECT_TOOLS, ...normalizeToolNames(state.extraTools)])].join(", ");
70
+ }
71
+
72
+ export function createRuntimeState(config: AutoModeConfig): AutoModeRuntimeState {
73
+ return {
74
+ engaged: false,
75
+ gate: config.gate,
76
+ extraTools: normalizeToolNames(config.extraTools),
77
+ };
78
+ }
79
+
80
+ /**
81
+ * Refresh the configured gate and tool list without touching engagement: editing
82
+ * config changes what gets reviewed, it never silently turns auto mode on or off.
83
+ * An explicit `/auto` scope override wins until the next session start.
84
+ */
85
+ export function applyConfiguredGate(
86
+ state: AutoModeRuntimeState,
87
+ config: AutoModeConfig,
88
+ ): AutoModeRuntimeState {
89
+ state.gate = state.gateOverride ?? config.gate;
90
+ state.extraTools = normalizeToolNames(config.extraTools);
91
+ return state;
92
+ }
93
+
94
+ export function setGateOverride(
95
+ state: AutoModeRuntimeState,
96
+ config: AutoModeConfig,
97
+ gate: AutoModeGateSource | undefined,
98
+ ): AutoModeRuntimeState {
99
+ state.gateOverride = gate;
100
+ state.gate = gate ?? config.gate;
101
+ return state;
102
+ }
103
+
104
+ /**
105
+ * Record one genuine reviewer denial and report whether the turn should stop.
106
+ *
107
+ * Two independent triggers, matching Codex: a short run of consecutive denials
108
+ * means the agent cannot get past the reviewer, and a high denial rate inside a
109
+ * sliding window means it keeps trying different unsafe things.
110
+ */
111
+ export function recordDenial(
112
+ state: RejectionBreakerState,
113
+ config: AutoModeCircuitBreakerConfig,
114
+ toolName: string,
115
+ ): "continue" | "interrupt" {
116
+ state.consecutiveDenials += 1;
117
+ state.deniedTools.add(toolName);
118
+ state.recentDenials.push(true);
119
+ if (state.recentDenials.length > Math.max(1, config.windowSize)) {
120
+ state.recentDenials.splice(0, state.recentDenials.length - config.windowSize);
121
+ }
122
+
123
+ const recentDenials = state.recentDenials.filter(Boolean).length;
124
+ const consecutiveTripped = config.consecutiveDenials > 0 && state.consecutiveDenials >= config.consecutiveDenials;
125
+ const rateTripped = config.recentDenials > 0 && recentDenials >= config.recentDenials;
126
+ if (consecutiveTripped || rateTripped) {
127
+ state.interrupted = true;
128
+ return "interrupt";
129
+ }
130
+ return "continue";
131
+ }
132
+
133
+ /** Any allowed action resets the consecutive run, so one approval breaks a streak. */
134
+ export function recordNonDenial(state: RejectionBreakerState): void {
135
+ state.consecutiveDenials = 0;
136
+ state.recentDenials.push(false);
137
+ }
138
+
139
+ /**
140
+ * A repeat request for a tool that was already denied in this turn is the shape of
141
+ * a workaround attempt, so it must be judged by the blocking reviewer rather than
142
+ * accepted on the strength of an earlier low-risk classification.
143
+ */
144
+ export function wasDeniedThisTurn(state: RejectionBreakerState, toolName: string): boolean {
145
+ return state.deniedTools.has(toolName);
146
+ }