pi-openai-toolkit 0.20.8 → 0.21.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.
@@ -1,6 +1,6 @@
1
1
  import { resolveToolkitConfig } from "../config";
2
2
  import type { LoadedToolkitConfig } from "../types";
3
- import type { ConfigOrigin } from "./policy";
3
+ import { RETIRED_AUTO_MODE_ISSUE, RETIRED_AUTO_MODE_MESSAGE, type ConfigOrigin } from "./policy";
4
4
  import { resolveV2Config } from "./v2";
5
5
 
6
6
  export type MigrationPreview = {
@@ -21,7 +21,11 @@ function modelRef(key: string): { provider: string; id: string; api: string } {
21
21
 
22
22
  /** Read-only analysis: never edits a source file or claims a lossy candidate is equivalent. */
23
23
  export function previewToolkitMigration(loaded: LoadedToolkitConfig): MigrationPreview {
24
- if (loaded.document?.format === "v2") return { status: "already-v2", reasons: ["The document already uses schemaVersion 2."], unmappedPaths: [] };
24
+ if (loaded.document?.format === "v2") {
25
+ const retired = resolveToolkitConfig(loaded).issues.filter((issue) => issue.code === RETIRED_AUTO_MODE_ISSUE);
26
+ return { status: "already-v2", reasons: ["The document already uses schemaVersion 2.",
27
+ ...(retired.length ? [RETIRED_AUTO_MODE_MESSAGE] : [])], unmappedPaths: retired.map((issue) => issue.path) };
28
+ }
25
29
  if (loaded.document?.format === "invalid" || loaded.document?.format === "missing") {
26
30
  return { status: "unavailable", reasons: ["A readable legacy document is required; no candidate was produced."], unmappedPaths: [] };
27
31
  }
@@ -38,14 +42,12 @@ export function previewToolkitMigration(loaded: LoadedToolkitConfig): MigrationP
38
42
  const keys = new Set([
39
43
  ...legacy.webSearch.models,
40
44
  ...Object.keys(legacy.webSearch.routes ?? {}),
41
- ...legacy.autoMode.models,
42
45
  ...legacy.compaction.gatewayContextModels,
43
46
  ]);
44
47
  for (const key of keys) {
45
48
  const resolved = resolveToolkitConfig(loaded, modelRef(key));
46
49
  const override: Record<string, unknown> = {};
47
50
  if (resolved.policy.webSearch.route !== defaults.webSearch.route) override.webSearch = resolved.policy.webSearch;
48
- if (resolved.policy.autoMode.available !== defaults.autoMode.available) override.autoMode = { available: resolved.policy.autoMode.available };
49
51
  if (resolved.policy.compatibility.transport !== "standard") override.compatibility = resolved.policy.compatibility;
50
52
  if (Object.keys(override).length > 0) {
51
53
  models[key] = override;
@@ -59,6 +61,11 @@ export function previewToolkitMigration(loaded: LoadedToolkitConfig): MigrationP
59
61
  }
60
62
  const candidate = { schemaVersion: 2, defaults, models, diagnostics };
61
63
  const reasons: string[] = [];
64
+ // Retired sections are never migrated; their presence is a controlled removal reason.
65
+ if (baseline.issues.some((issue) => issue.code === RETIRED_AUTO_MODE_ISSUE)) {
66
+ reasons.push(RETIRED_AUTO_MODE_MESSAGE + " No Auto Mode settings were migrated; review the removal before applying this candidate.");
67
+ unmappedPaths.add("autoMode");
68
+ }
62
69
  if (loaded.warnings.length || baseline.issues.length) {
63
70
  reasons.push("Legacy warnings, unknown fields or normalized invalid values require review. Their original contents remain in the untouched source file.");
64
71
  }
@@ -76,10 +83,6 @@ export function previewToolkitMigration(loaded: LoadedToolkitConfig): MigrationP
76
83
  legacy.webSearch.models.some((key) => Object.hasOwn(legacy.webSearch.routes ?? {}, key)))) {
77
84
  unmappedPaths.add("webSearch.models");
78
85
  }
79
- if (!legacy.autoMode.enabled && legacy.autoMode.models.length) {
80
- reasons.push("Disabled legacy auto mode contains a dormant eligibility list; keep the original file for review.");
81
- unmappedPaths.add("autoMode.models");
82
- }
83
86
  if (!legacy.compaction.enabled && legacy.compaction.contextManagement === "remote") {
84
87
  reasons.push("Disabled legacy context management retains a dormant remote mode; the candidate selects Pi ownership.");
85
88
  unmappedPaths.add("compaction.contextManagement");
@@ -1,28 +1,36 @@
1
- import type { ExtensionContext } from "@earendil-works/pi-coding-agent";
2
- import type { ResolvedToolkitConfig } from "../config";
3
- import type { ConfigIssue } from "./policy";
4
- import { redactValue } from "../debug";
5
-
6
- const lastNotice = new WeakMap<object, string>();
7
-
8
- export function formatConfigIssues(issues: readonly ConfigIssue[], limit = 12): string {
9
- const lines = issues.slice(0, limit).map((issue) => `${issue.severity}: ${issue.path.slice(0, 220)} — ${issue.code}`);
10
- if (issues.length > limit) lines.push(`${issues.length - limit} more issue(s); inspect the configuration file.`);
11
- return String(redactValue(lines.join("\n")));
12
- }
13
-
14
- /** Per-session bounded notice, independent of feature enablement/debug. Never logs raw config. */
15
- export function notifyConfigIssues(ctx: ExtensionContext, resolved: ResolvedToolkitConfig): void {
16
- const owner = ctx.sessionManager ?? ctx;
17
- if (resolved.issues.length === 0) {
18
- lastNotice.delete(owner);
19
- return;
20
- }
21
- if (!ctx.hasUI || typeof ctx.ui?.notify !== "function") return;
22
- const message = formatConfigIssues(resolved.issues, 4);
23
- const fingerprint = `${resolved.source ?? "defaults"}\n${resolved.modelKey ?? ""}\n${message}`;
24
- if (lastNotice.get(owner) === fingerprint) return;
25
- lastNotice.set(owner, fingerprint);
26
- ctx.ui.notify(`Toolkit configuration:\n${message}\nUse /toolkit-config validate for details.`,
27
- resolved.issues.some((issue) => issue.severity === "error") ? "error" : "warning");
28
- }
1
+ import type { ExtensionContext } from "@earendil-works/pi-coding-agent";
2
+ import type { ResolvedToolkitConfig } from "../config";
3
+ import { RETIRED_AUTO_MODE_ISSUE, RETIRED_AUTO_MODE_MESSAGE, type ConfigIssue } from "./policy";
4
+ import { redactValue } from "../debug";
5
+
6
+ const lastNotice = new WeakMap<object, string>();
7
+
8
+ /** Controlled human text for a known code; never built from user-supplied configuration values. */
9
+ function issueExplanation(issue: ConfigIssue): string {
10
+ return issue.code === RETIRED_AUTO_MODE_ISSUE
11
+ ? RETIRED_AUTO_MODE_MESSAGE
12
+ : issue.code;
13
+ }
14
+
15
+ export function formatConfigIssues(issues: readonly ConfigIssue[], limit = 12): string {
16
+ const lines = issues.slice(0, limit).map((issue) =>
17
+ `${issue.severity}: ${issue.path.slice(0, 220)} — ${issueExplanation(issue)}`);
18
+ if (issues.length > limit) lines.push(`${issues.length - limit} more issue(s); inspect the configuration file.`);
19
+ return String(redactValue(lines.join("\n")));
20
+ }
21
+
22
+ /** Per-session bounded notice, independent of feature enablement/debug. Never logs raw config. */
23
+ export function notifyConfigIssues(ctx: ExtensionContext, resolved: ResolvedToolkitConfig): void {
24
+ const owner = ctx.sessionManager ?? ctx;
25
+ if (resolved.issues.length === 0) {
26
+ lastNotice.delete(owner);
27
+ return;
28
+ }
29
+ if (!ctx.hasUI || typeof ctx.ui?.notify !== "function") return;
30
+ const message = formatConfigIssues(resolved.issues, 4);
31
+ const fingerprint = `${resolved.source ?? "defaults"}\n${resolved.modelKey ?? ""}\n${message}`;
32
+ if (lastNotice.get(owner) === fingerprint) return;
33
+ lastNotice.set(owner, fingerprint);
34
+ ctx.ui.notify(`Toolkit configuration:\n${message}\nUse /toolkit-config validate for details.`,
35
+ resolved.issues.some((issue) => issue.severity === "error") ? "error" : "warning");
36
+ }
@@ -1,14 +1,12 @@
1
1
  import {
2
- DEFAULT_AUTO_MODE_CONFIG,
3
2
  DEFAULT_COMPACTION_CONFIG,
4
3
  DEFAULT_IMAGE_GENERATION_MODEL,
5
- type AutoModeConfig,
6
4
  type LeaveManagedModePolicy,
7
5
  type NativeFallbackConfig,
8
6
  type RemoteV2ContextSource,
9
7
  } from "../types";
10
8
 
11
- export type ConfigFeature = "context" | "webSearch" | "imageGeneration" | "autoMode" | "compatibility" | "responsesWebSocket" | "diagnostics";
9
+ export type ConfigFeature = "context" | "webSearch" | "imageGeneration" | "compatibility" | "responsesWebSocket" | "diagnostics";
12
10
  export type SearchRoute = "unmanaged" | "local" | "hosted" | "standalone-alpha";
13
11
  export type DiagnosticsConfig = {
14
12
  level: "error" | "warn" | "info" | "debug";
@@ -33,17 +31,11 @@ export type ContextPolicy = {
33
31
  reminderThresholdPercent: number;
34
32
  };
35
33
  };
36
- export type AutoModePolicy = Omit<AutoModeConfig, "enabled" | "models" | "reviewerModel" | "classifier"> & {
37
- available: boolean;
38
- reviewerModel: string | null;
39
- classifier: Omit<AutoModeConfig["classifier"], "model"> & { model: string | null };
40
- };
41
34
  export type EffectiveToolkitPolicy = {
42
35
  context: ContextPolicy;
43
36
  webSearch: { route: SearchRoute };
44
37
  imageGeneration: { enabled: boolean; defaultModel: string; allowedModels: string[] };
45
38
  responsesWebSocket: { enabled: boolean };
46
- autoMode: AutoModePolicy;
47
39
  compatibility: { transport: "standard" | "codex-gateway" };
48
40
  diagnostics: DiagnosticsConfig;
49
41
  };
@@ -61,6 +53,14 @@ export type ConfigIssue = {
61
53
  /** Issues for a different model do not invalidate the selected model. */
62
54
  modelKey?: string;
63
55
  };
56
+ /**
57
+ * Stable code for a configuration section that was removed from the Toolkit. A retired section is
58
+ * ignored in any shape and must never invalidate another feature, so it is reported as a warning.
59
+ */
60
+ export const RETIRED_AUTO_MODE_ISSUE = "retired.autoMode" as const;
61
+ /** Controlled explanation of the retirement; never contains user-supplied values. */
62
+ export const RETIRED_AUTO_MODE_MESSAGE =
63
+ "Auto Mode has been removed; these settings are ignored and tool calls are no longer reviewed by it.";
64
64
  export type ResolvedToolkitPolicy = {
65
65
  policy: EffectiveToolkitPolicy;
66
66
  origins: Record<string, ConfigOrigin>;
@@ -75,14 +75,12 @@ export type ConfigDocumentSnapshot = {
75
75
  issues: ConfigIssue[];
76
76
  };
77
77
  export const CONFIG_FEATURES: readonly ConfigFeature[] = [
78
- "context", "webSearch", "imageGeneration", "autoMode", "compatibility", "responsesWebSocket", "diagnostics",
78
+ "context", "webSearch", "imageGeneration", "compatibility", "responsesWebSocket", "diagnostics",
79
79
  ];
80
80
 
81
81
  /** Independent per-operation defaults, preserving the existing shipped policy. */
82
82
  export function createPolicyDefaults(): EffectiveToolkitPolicy {
83
83
  const context = DEFAULT_COMPACTION_CONFIG;
84
- const auto = structuredClone(DEFAULT_AUTO_MODE_CONFIG);
85
- const { enabled: _enabled, models: _models, reviewerModel, classifier, ...autoOptions } = auto;
86
84
  return {
87
85
  context: {
88
86
  mode: "remote-compaction",
@@ -105,12 +103,6 @@ export function createPolicyDefaults(): EffectiveToolkitPolicy {
105
103
  allowedModels: [DEFAULT_IMAGE_GENERATION_MODEL],
106
104
  },
107
105
  responsesWebSocket: { enabled: false },
108
- autoMode: {
109
- ...autoOptions,
110
- available: false,
111
- reviewerModel: reviewerModel ?? null,
112
- classifier: { ...classifier, model: classifier.model ?? null },
113
- },
114
106
  compatibility: { transport: "standard" },
115
107
  diagnostics: {
116
108
  level: "info",