avtc-claude-settings-ui 1.0.13 → 1.0.15

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 CHANGED
@@ -99,6 +99,8 @@ const tree = buildPaneTree(els, controller, { bodyColumns: e.props.bodyColumns }
99
99
  | `buildPaneTree(els, controller, options)` | Composes the render tree over the surface's element table |
100
100
  | `settingsFilePaths(name)` | Global/project file path helpers for the schema |
101
101
  | `registerSettingsCommand`, `loadSettingsHandle` | Wiring a `/name-settings`-style command and lazy handle load |
102
+ | `captureCtx` | Stash the host's models list / enabled-models patterns at pane-open (feeds the `model` type's presets) |
103
+ | `modelPairsFromSettings(settings, reservedValues)` | Labeled model rows for the host's own models from a Claude settings snapshot — `availableModels` entries plus `modelPicker`-only options, labels from the lineup; pass the engine values you already offer (aliases, spawn keywords) so they never duplicate |
102
104
  | `registerTypeDefinition` | Custom setting types |
103
105
  | Types | `SettingsSchema`, `SettingSchema`, `SettingsTabSchema`, `FsAdapter`, `EnvStore`, `PaneController`, `PaneTreeOptions`, … |
104
106
 
package/dist/index.d.ts CHANGED
@@ -2,6 +2,7 @@ export { captureCtx } from "./ctx-store.js";
2
2
  export type { EnvStore } from "./factory.js";
3
3
  export { createSettingsExtension } from "./factory.js";
4
4
  export type { FsAdapter } from "./fs-adapter.js";
5
+ export { modelPairsFromSettings } from "./model-presets.js";
5
6
  export type { PaneController, PaneControllerOptions, PaneHandle, PaneNotify, PaneStorageLevels, } from "./pane/controller.js";
6
7
  export { createPaneController } from "./pane/controller.js";
7
8
  export type { PaneElements, PaneTreeOptions } from "./pane/tree.js";
package/dist/index.js CHANGED
@@ -8,6 +8,10 @@
8
8
  export { captureCtx } from "./ctx-store.js";
9
9
  // The settings store — create the handle over injected fs/env seams.
10
10
  export { createSettingsExtension } from "./factory.js";
11
+ // Settings-derived model rows — labeled [label, value] pairs for the user's own
12
+ // models (availableModels entries + modelPicker-only options) from a settings
13
+ // snapshot; the host supplies the engine values it reserves for itself.
14
+ export { modelPairsFromSettings } from "./model-presets.js";
11
15
  // The pane — the interaction model + tree composition a host's ui.render hook drives.
12
16
  export { createPaneController } from "./pane/controller.js";
13
17
  export { buildPaneTree } from "./pane/tree.js";
@@ -16,6 +16,19 @@ export declare function splitModelId(value: string): {
16
16
  provider: string;
17
17
  id: string;
18
18
  } | null;
19
+ /** Labeled `[label, value]` rows for the user's own models, read from a Claude
20
+ * Code settings snapshot (the `$.settings.read` shape):
21
+ *
22
+ * - each `availableModels` entry becomes a row — the value verbatim (an id the
23
+ * host's own model selection accepts), labeled from `modelPicker.options`
24
+ * when the user named it there
25
+ * - `modelPicker.options` entries no `availableModels` entry names append after
26
+ * them (their own label, or the id), so a picker lineup alone still yields rows
27
+ *
28
+ * `reservedValues` are engine values the caller already offers its own way
29
+ * (aliases, spawn keywords) — they never become rows here. Malformed shapes
30
+ * (non-arrays, non-strings, bad options) collapse to zero rows; never throws. */
31
+ export declare function modelPairsFromSettings(settings: unknown, reservedValues: ReadonlySet<string>): PresetPair[];
19
32
  /**
20
33
  * Glob match over the minimatch subset patterns use: `*` (any run), `?`
21
34
  * (exactly one), everything else literal; case-insensitive. No brace
@@ -33,6 +33,69 @@ export function splitModelId(value) {
33
33
  return null;
34
34
  return { provider: value.slice(0, slash), id: value.slice(slash + 1) };
35
35
  }
36
+ /** Labeled `[label, value]` rows for the user's own models, read from a Claude
37
+ * Code settings snapshot (the `$.settings.read` shape):
38
+ *
39
+ * - each `availableModels` entry becomes a row — the value verbatim (an id the
40
+ * host's own model selection accepts), labeled from `modelPicker.options`
41
+ * when the user named it there
42
+ * - `modelPicker.options` entries no `availableModels` entry names append after
43
+ * them (their own label, or the id), so a picker lineup alone still yields rows
44
+ *
45
+ * `reservedValues` are engine values the caller already offers its own way
46
+ * (aliases, spawn keywords) — they never become rows here. Malformed shapes
47
+ * (non-arrays, non-strings, bad options) collapse to zero rows; never throws. */
48
+ export function modelPairsFromSettings(settings, reservedValues) {
49
+ if (settings === null || typeof settings !== "object")
50
+ return [];
51
+ const root = settings;
52
+ const pickerOptions = [];
53
+ const labels = new Map();
54
+ const picker = root.modelPicker;
55
+ if (picker !== null && typeof picker === "object") {
56
+ const options = picker.options;
57
+ if (Array.isArray(options)) {
58
+ for (const option of options) {
59
+ if (option === null || typeof option !== "object")
60
+ continue;
61
+ const model = option.model;
62
+ const label = option.label;
63
+ if (typeof model !== "string" || model.trim().length === 0)
64
+ continue;
65
+ const trimmedModel = model.trim();
66
+ const labelStr = typeof label === "string" && label.length > 0 ? label : undefined;
67
+ pickerOptions.push({ model: trimmedModel, label: labelStr });
68
+ if (labelStr)
69
+ labels.set(trimmedModel, labelStr);
70
+ }
71
+ }
72
+ }
73
+ const pairs = [];
74
+ const seen = new Set();
75
+ const raw = root.availableModels;
76
+ if (Array.isArray(raw)) {
77
+ for (const entry of raw) {
78
+ if (typeof entry !== "string")
79
+ continue;
80
+ const value = entry.trim();
81
+ if (value.length === 0 || seen.has(value))
82
+ continue;
83
+ if (reservedValues.has(value.toLowerCase()))
84
+ continue;
85
+ seen.add(value);
86
+ pairs.push([labels.get(value) ?? value, value]);
87
+ }
88
+ }
89
+ for (const option of pickerOptions) {
90
+ if (seen.has(option.model))
91
+ continue;
92
+ if (reservedValues.has(option.model.toLowerCase()))
93
+ continue;
94
+ seen.add(option.model);
95
+ pairs.push([option.label ?? option.model, option.model]);
96
+ }
97
+ return pairs;
98
+ }
36
99
  /**
37
100
  * Glob match over the minimatch subset patterns use: `*` (any run), `?`
38
101
  * (exactly one), everything else literal; case-insensitive. No brace
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "avtc-claude-settings-ui",
3
- "version": "1.0.13",
3
+ "version": "1.0.15",
4
4
  "description": "A schema-driven settings UI for Claude mods — define your settings, get a tabbed pane, a /<name>-settings command, and layered persistence.",
5
5
  "type": "module",
6
6
  "license": "MIT",