pi-fabric 0.66.0 → 0.68.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 +1 -1
- package/dist/chunks/{chunk-NFW7H77W.js → chunk-VRYEGVHR.js} +15 -1
- package/dist/chunks/chunk-VRYEGVHR.js.map +7 -0
- package/dist/chunks/{dashboard-S3TINWGZ.js → dashboard-6HFBSZQ4.js} +2 -2
- package/dist/chunks/{fabric-runtime-state-FDTVRRCU.js → fabric-runtime-state-LG265P3R.js} +1 -1
- package/dist/chunks/{settings-E2RINXBO.js → settings-J26PVVBO.js} +238 -35
- package/dist/chunks/settings-J26PVVBO.js.map +7 -0
- package/dist/core/proxy-contract.d.ts +18 -0
- package/dist/core/proxy-contract.d.ts.map +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +244 -8
- package/dist/index.js.map +4 -4
- package/dist/runtime/core-tool-properties.d.ts +6 -0
- package/dist/runtime/core-tool-properties.d.ts.map +1 -0
- package/dist/type-error-guidance.d.ts.map +1 -1
- package/dist/ui/fabric-model-selector.d.ts +8 -0
- package/dist/ui/fabric-model-selector.d.ts.map +1 -1
- package/dist/ui/settings.d.ts.map +1 -1
- package/docs/capability-combustion.md +6 -0
- package/docs/configuration.md +1 -1
- package/docs/interface.md +1 -1
- package/package.json +1 -1
- package/dist/chunks/chunk-NFW7H77W.js.map +0 -7
- package/dist/chunks/settings-E2RINXBO.js.map +0 -7
- /package/dist/chunks/{dashboard-S3TINWGZ.js.map → dashboard-6HFBSZQ4.js.map} +0 -0
- /package/dist/chunks/{fabric-runtime-state-FDTVRRCU.js.map → fabric-runtime-state-LG265P3R.js.map} +0 -0
package/README.md
CHANGED
|
@@ -118,7 +118,7 @@ Fabric includes a live activity surface in Pi:
|
|
|
118
118
|
|
|
119
119
|
- A compact widget above the chat (like `pi-supervisor`) whose header follows the current phase while its rows show active/completed agents, active actors, and their recent nested tool or code-change activity.
|
|
120
120
|
- `/fabric` (or `/fabric dashboard`): opens the **Activity** and **Topology** views. The user-facing Pi session appears as **Main**. You can queue or steer participants and inspect the project topology.
|
|
121
|
-
- `/fabric settings`: mirrors Pi's `/settings` and writes changes to `fabric.json`.
|
|
121
|
+
- `/fabric settings`: mirrors Pi's `/settings` and writes changes to `fabric.json`. TUI hosts get the searchable settings component; RPC hosts get the same nested sections, value/input/model pickers, list editors, and project/global save scopes through native dialog primitives.
|
|
122
122
|
- `Tool display` (`compact` by default, or `full`) is configured under `/fabric settings` → **UI**; compact elevates the declared display intent, hides the outer TypeScript, and applies to the current transcript immediately. Pi's tool-expand keybinding (`ctrl+o` by default) expands a compact card to the full transcript.
|
|
123
123
|
|
|
124
124
|
See the [interface & commands reference](docs/interface.md) for every view, keybinding, and slash command.
|
|
@@ -91,6 +91,20 @@ var FabricModelSelector = class extends Container {
|
|
|
91
91
|
this.filterModels(this.searchInput.getValue());
|
|
92
92
|
}
|
|
93
93
|
}
|
|
94
|
+
rpcChoices() {
|
|
95
|
+
return this.allEntries.map((entry) => ({
|
|
96
|
+
value: entry.value,
|
|
97
|
+
label: entry.id,
|
|
98
|
+
description: entry.isModel ? `${entry.provider} \xB7 ${entry.name}` : entry.name,
|
|
99
|
+
current: entry.value === this.currentValue
|
|
100
|
+
}));
|
|
101
|
+
}
|
|
102
|
+
selectRpc(value) {
|
|
103
|
+
const entry = this.allEntries.find((candidate) => candidate.value === value);
|
|
104
|
+
if (!entry) return false;
|
|
105
|
+
this.handleSelect(entry);
|
|
106
|
+
return true;
|
|
107
|
+
}
|
|
94
108
|
handleSelect(entry) {
|
|
95
109
|
this.onSelectCallback(entry.value);
|
|
96
110
|
}
|
|
@@ -178,4 +192,4 @@ var FabricModelSelector = class extends Container {
|
|
|
178
192
|
export {
|
|
179
193
|
FabricModelSelector
|
|
180
194
|
};
|
|
181
|
-
//# sourceMappingURL=chunk-
|
|
195
|
+
//# sourceMappingURL=chunk-VRYEGVHR.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/ui/fabric-model-selector.ts"],
|
|
4
|
+
"sourcesContent": ["import type { Theme } from \"@earendil-works/pi-coding-agent\";\nimport {\n Container,\n type Focusable,\n fuzzyFilter,\n getKeybindings,\n Input,\n Spacer,\n Text,\n} from \"@earendil-works/pi-tui\";\nimport { INHERIT_VALUE, modelKey, sortByLastUsed, type ModelLike, type ModelSource } from \"./model-picker.js\";\n\n/** A single pickable row in the Fabric model selector. */\ninterface ModelEntry {\n /** Value persisted to fabric.json: \"Inherit\" or `provider/id`. */\n value: string;\n /** Main text shown for the row (the model id, or \"Inherit\"). */\n id: string;\n /** Provider badge shown after the id; empty for the Inherit row. */\n provider: string;\n /** Human-readable name shown in the footer line. */\n name: string;\n /** Whether this is a real model (vs. the Inherit sentinel). */\n isModel: boolean;\n}\n\nexport interface FabricModelSelectorChoice {\n value: string;\n label: string;\n description: string;\n current: boolean;\n}\n\nexport interface FabricModelSelectorOptions {\n theme: Theme;\n source: ModelSource;\n /** The currently configured canonical model key or \"Inherit\". */\n currentValue: string;\n onSelect: (value: string) => void;\n onCancel: () => void;\n /** Header line above the search input. Defaults to the global-default wording. */\n headerText?: string;\n /** Label shown for the unset/default row. Defaults to Inherit. */\n inheritLabel?: string;\n /** Description shown for the unset/default row's footer name. */\n inheritName?: string;\n}\n\n/**\n * A /model-style searchable model picker adapted for Fabric: same look\n * (search input, list with `[provider]` badges and a \u2713 on\n * the current row, scroll indicator, and a \"Model Name:\" footer) but it writes\n * the Fabric default-model setting instead of the host's default model, and\n * pins an unset/default row on top. Order respects pi-model-sort (most recently\n * used first); search filters by fuzzy match and re-sorts by recency, matching\n * pi-model-sort's patched /model behavior.\n */\nexport class FabricModelSelector extends Container implements Focusable {\n private readonly theme: Theme;\n private readonly allEntries: ModelEntry[];\n private filteredEntries: ModelEntry[];\n private readonly lastUsed: Record<string, number>;\n private readonly currentKey: string | null;\n private readonly currentValue: string;\n private selectedIndex = 0;\n private readonly searchInput: Input;\n private readonly listContainer = new Container();\n private readonly onSelectCallback: (value: string) => void;\n private readonly onCancelCallback: () => void;\n private readonly headerText: string;\n private readonly inheritLabel: string;\n private readonly inheritName: string;\n private _focused = false;\n\n constructor(options: FabricModelSelectorOptions) {\n super();\n this.theme = options.theme;\n this.lastUsed = options.source.lastUsed;\n this.currentValue = options.currentValue;\n this.currentKey = options.currentValue === INHERIT_VALUE ? null : options.currentValue;\n this.onSelectCallback = options.onSelect;\n this.onCancelCallback = options.onCancel;\n this.headerText =\n options.headerText ??\n \"Default model for Fabric agents and actors. Pick Inherit to use the host session's model.\";\n this.inheritLabel = options.inheritLabel ?? INHERIT_VALUE;\n this.inheritName = options.inheritName ?? \"Use the host session's default model\";\n\n this.allEntries = this.buildEntries(options.source.models);\n this.filteredEntries = this.allEntries;\n const current = this.allEntries.findIndex((entry) => entry.value === this.currentValue);\n this.selectedIndex = current >= 0 ? current : 0;\n\n this.addChild(\n new Text(\n this.theme.fg(\"muted\", this.headerText),\n 0,\n 0,\n ),\n );\n this.addChild(new Spacer(1));\n this.searchInput = new Input();\n this.searchInput.focused = true;\n this.searchInput.onSubmit = () => {\n const entry = this.filteredEntries[this.selectedIndex];\n if (entry) this.handleSelect(entry);\n };\n this.addChild(this.searchInput);\n this.addChild(new Spacer(1));\n this.addChild(this.listContainer);\n this.addChild(new Spacer(1));\n this.updateList();\n }\n\n get focused(): boolean {\n return this._focused;\n }\n\n set focused(value: boolean) {\n this._focused = value;\n this.searchInput.focused = value;\n }\n\n handleInput(keyData: string): void {\n const kb = getKeybindings();\n if (kb.matches(keyData, \"tui.select.up\")) {\n if (this.filteredEntries.length === 0) return;\n this.selectedIndex =\n this.selectedIndex === 0 ? this.filteredEntries.length - 1 : this.selectedIndex - 1;\n this.updateList();\n } else if (kb.matches(keyData, \"tui.select.down\")) {\n if (this.filteredEntries.length === 0) return;\n this.selectedIndex =\n this.selectedIndex === this.filteredEntries.length - 1 ? 0 : this.selectedIndex + 1;\n this.updateList();\n } else if (kb.matches(keyData, \"tui.select.confirm\")) {\n const entry = this.filteredEntries[this.selectedIndex];\n if (entry) this.handleSelect(entry);\n } else if (kb.matches(keyData, \"tui.select.cancel\")) {\n this.onCancelCallback();\n } else {\n this.searchInput.handleInput(keyData);\n this.filterModels(this.searchInput.getValue());\n }\n }\n\n rpcChoices(): FabricModelSelectorChoice[] {\n return this.allEntries.map((entry) => ({\n value: entry.value,\n label: entry.id,\n description: entry.isModel ? `${entry.provider} \u00B7 ${entry.name}` : entry.name,\n current: entry.value === this.currentValue,\n }));\n }\n\n selectRpc(value: string): boolean {\n const entry = this.allEntries.find((candidate) => candidate.value === value);\n if (!entry) return false;\n this.handleSelect(entry);\n return true;\n }\n\n private handleSelect(entry: ModelEntry): void {\n this.onSelectCallback(entry.value);\n }\n\n private buildEntries(models: ModelLike[]): ModelEntry[] {\n const sorted = sortByLastUsed(models, this.lastUsed, this.currentKey);\n const inherit: ModelEntry = {\n value: INHERIT_VALUE,\n id: this.inheritLabel,\n provider: \"\",\n name: this.inheritName,\n isModel: false,\n };\n const modelEntries: ModelEntry[] = sorted.map((model) => ({\n value: modelKey(model.provider, model.id),\n id: model.id,\n provider: model.provider,\n name: model.name ?? model.id,\n isModel: true,\n }));\n return [inherit, ...modelEntries];\n }\n\n /** Filter by fuzzy match, then re-sort by recency (mirrors pi-model-sort). */\n private sortEntries(entries: ModelEntry[]): ModelEntry[] {\n const inherit = entries.find((entry) => !entry.isModel);\n const models = entries.filter((entry) => entry.isModel);\n const sorted = sortByLastUsed(\n models.map((entry) => ({ provider: entry.provider, id: entry.id, entry })),\n this.lastUsed,\n this.currentKey,\n ).map((item) => item.entry);\n return inherit ? [inherit, ...sorted] : sorted;\n }\n\n private filterModels(query: string): void {\n const matches = query.trim()\n ? fuzzyFilter(this.allEntries, query, (entry) => this.searchText(entry))\n : this.allEntries;\n this.filteredEntries = this.sortEntries(matches);\n const current = this.filteredEntries.findIndex((entry) => entry.value === this.currentValue);\n this.selectedIndex =\n current >= 0\n ? current\n : Math.min(this.selectedIndex, Math.max(0, this.filteredEntries.length - 1));\n this.updateList();\n }\n\n /** Mirrors getModelSelectorSearchText from pi's /model selector. */\n private searchText(entry: ModelEntry): string {\n if (!entry.isModel) return `${entry.id} ${entry.name}`;\n return `${entry.provider} ${entry.provider}/${entry.id} ${entry.provider} ${entry.id} ${entry.name}`;\n }\n\n private updateList(): void {\n this.listContainer.clear();\n const maxVisible = 10;\n const total = this.filteredEntries.length;\n const startIndex = Math.max(\n 0,\n Math.min(this.selectedIndex - Math.floor(maxVisible / 2), total - maxVisible),\n );\n const endIndex = Math.min(startIndex + maxVisible, total);\n for (let i = startIndex; i < endIndex; i++) {\n const entry = this.filteredEntries[i];\n if (!entry) continue;\n const isSelected = i === this.selectedIndex;\n const isCurrent = entry.value === this.currentValue;\n const badge = entry.provider ? ` ${this.theme.fg(\"muted\", `[${entry.provider}]`)}` : \"\";\n const check = isCurrent ? this.theme.fg(\"success\", \" \u2713\") : \"\";\n const line = isSelected\n ? `${this.theme.fg(\"accent\", \"\\u2192 \")}${this.theme.fg(\"accent\", entry.id)}${badge}${check}`\n : ` ${entry.id}${badge}${check}`;\n this.listContainer.addChild(new Text(line, 0, 0));\n }\n if (startIndex > 0 || endIndex < total) {\n this.listContainer.addChild(\n new Text(this.theme.fg(\"muted\", ` (${this.selectedIndex + 1}/${total})`), 0, 0),\n );\n }\n if (total === 0) {\n this.listContainer.addChild(new Text(this.theme.fg(\"muted\", \" No matching models\"), 0, 0));\n } else {\n const selected = this.filteredEntries[this.selectedIndex];\n this.listContainer.addChild(new Spacer(1));\n this.listContainer.addChild(\n new Text(\n this.theme.fg(\"muted\", ` Model Name: ${selected ? selected.name : \"\"}`),\n 0,\n 0,\n ),\n );\n }\n }\n}\n"],
|
|
5
|
+
"mappings": ";;;;;;;AACA;AAAA,EACE;AAAA,EAEA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAgDA,IAAM,sBAAN,cAAkC,UAA+B;AAAA,EACrD;AAAA,EACA;AAAA,EACT;AAAA,EACS;AAAA,EACA;AAAA,EACA;AAAA,EACT,gBAAgB;AAAA,EACP;AAAA,EACA,gBAAgB,IAAI,UAAU;AAAA,EAC9B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACT,WAAW;AAAA,EAEnB,YAAY,SAAqC;AAC/C,UAAM;AACN,SAAK,QAAQ,QAAQ;AACrB,SAAK,WAAW,QAAQ,OAAO;AAC/B,SAAK,eAAe,QAAQ;AAC5B,SAAK,aAAa,QAAQ,iBAAiB,gBAAgB,OAAO,QAAQ;AAC1E,SAAK,mBAAmB,QAAQ;AAChC,SAAK,mBAAmB,QAAQ;AAChC,SAAK,aACH,QAAQ,cACR;AACF,SAAK,eAAe,QAAQ,gBAAgB;AAC5C,SAAK,cAAc,QAAQ,eAAe;AAE1C,SAAK,aAAa,KAAK,aAAa,QAAQ,OAAO,MAAM;AACzD,SAAK,kBAAkB,KAAK;AAC5B,UAAM,UAAU,KAAK,WAAW,UAAU,CAAC,UAAU,MAAM,UAAU,KAAK,YAAY;AACtF,SAAK,gBAAgB,WAAW,IAAI,UAAU;AAE9C,SAAK;AAAA,MACH,IAAI;AAAA,QACF,KAAK,MAAM,GAAG,SAAS,KAAK,UAAU;AAAA,QACtC;AAAA,QACA;AAAA,MACF;AAAA,IACF;AACA,SAAK,SAAS,IAAI,OAAO,CAAC,CAAC;AAC3B,SAAK,cAAc,IAAI,MAAM;AAC7B,SAAK,YAAY,UAAU;AAC3B,SAAK,YAAY,WAAW,MAAM;AAChC,YAAM,QAAQ,KAAK,gBAAgB,KAAK,aAAa;AACrD,UAAI,MAAO,MAAK,aAAa,KAAK;AAAA,IACpC;AACA,SAAK,SAAS,KAAK,WAAW;AAC9B,SAAK,SAAS,IAAI,OAAO,CAAC,CAAC;AAC3B,SAAK,SAAS,KAAK,aAAa;AAChC,SAAK,SAAS,IAAI,OAAO,CAAC,CAAC;AAC3B,SAAK,WAAW;AAAA,EAClB;AAAA,EAEA,IAAI,UAAmB;AACrB,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,IAAI,QAAQ,OAAgB;AAC1B,SAAK,WAAW;AAChB,SAAK,YAAY,UAAU;AAAA,EAC7B;AAAA,EAEA,YAAY,SAAuB;AACjC,UAAM,KAAK,eAAe;AAC1B,QAAI,GAAG,QAAQ,SAAS,eAAe,GAAG;AACxC,UAAI,KAAK,gBAAgB,WAAW,EAAG;AACvC,WAAK,gBACH,KAAK,kBAAkB,IAAI,KAAK,gBAAgB,SAAS,IAAI,KAAK,gBAAgB;AACpF,WAAK,WAAW;AAAA,IAClB,WAAW,GAAG,QAAQ,SAAS,iBAAiB,GAAG;AACjD,UAAI,KAAK,gBAAgB,WAAW,EAAG;AACvC,WAAK,gBACH,KAAK,kBAAkB,KAAK,gBAAgB,SAAS,IAAI,IAAI,KAAK,gBAAgB;AACpF,WAAK,WAAW;AAAA,IAClB,WAAW,GAAG,QAAQ,SAAS,oBAAoB,GAAG;AACpD,YAAM,QAAQ,KAAK,gBAAgB,KAAK,aAAa;AACrD,UAAI,MAAO,MAAK,aAAa,KAAK;AAAA,IACpC,WAAW,GAAG,QAAQ,SAAS,mBAAmB,GAAG;AACnD,WAAK,iBAAiB;AAAA,IACxB,OAAO;AACL,WAAK,YAAY,YAAY,OAAO;AACpC,WAAK,aAAa,KAAK,YAAY,SAAS,CAAC;AAAA,IAC/C;AAAA,EACF;AAAA,EAEA,aAA0C;AACxC,WAAO,KAAK,WAAW,IAAI,CAAC,WAAW;AAAA,MACrC,OAAO,MAAM;AAAA,MACb,OAAO,MAAM;AAAA,MACb,aAAa,MAAM,UAAU,GAAG,MAAM,QAAQ,SAAM,MAAM,IAAI,KAAK,MAAM;AAAA,MACzE,SAAS,MAAM,UAAU,KAAK;AAAA,IAChC,EAAE;AAAA,EACJ;AAAA,EAEA,UAAU,OAAwB;AAChC,UAAM,QAAQ,KAAK,WAAW,KAAK,CAAC,cAAc,UAAU,UAAU,KAAK;AAC3E,QAAI,CAAC,MAAO,QAAO;AACnB,SAAK,aAAa,KAAK;AACvB,WAAO;AAAA,EACT;AAAA,EAEQ,aAAa,OAAyB;AAC5C,SAAK,iBAAiB,MAAM,KAAK;AAAA,EACnC;AAAA,EAEQ,aAAa,QAAmC;AACtD,UAAM,SAAS,eAAe,QAAQ,KAAK,UAAU,KAAK,UAAU;AACpE,UAAM,UAAsB;AAAA,MAC1B,OAAO;AAAA,MACP,IAAI,KAAK;AAAA,MACT,UAAU;AAAA,MACV,MAAM,KAAK;AAAA,MACX,SAAS;AAAA,IACX;AACA,UAAM,eAA6B,OAAO,IAAI,CAAC,WAAW;AAAA,MACxD,OAAO,SAAS,MAAM,UAAU,MAAM,EAAE;AAAA,MACxC,IAAI,MAAM;AAAA,MACV,UAAU,MAAM;AAAA,MAChB,MAAM,MAAM,QAAQ,MAAM;AAAA,MAC1B,SAAS;AAAA,IACX,EAAE;AACF,WAAO,CAAC,SAAS,GAAG,YAAY;AAAA,EAClC;AAAA;AAAA,EAGQ,YAAY,SAAqC;AACvD,UAAM,UAAU,QAAQ,KAAK,CAAC,UAAU,CAAC,MAAM,OAAO;AACtD,UAAM,SAAS,QAAQ,OAAO,CAAC,UAAU,MAAM,OAAO;AACtD,UAAM,SAAS;AAAA,MACb,OAAO,IAAI,CAAC,WAAW,EAAE,UAAU,MAAM,UAAU,IAAI,MAAM,IAAI,MAAM,EAAE;AAAA,MACzE,KAAK;AAAA,MACL,KAAK;AAAA,IACP,EAAE,IAAI,CAAC,SAAS,KAAK,KAAK;AAC1B,WAAO,UAAU,CAAC,SAAS,GAAG,MAAM,IAAI;AAAA,EAC1C;AAAA,EAEQ,aAAa,OAAqB;AACxC,UAAM,UAAU,MAAM,KAAK,IACvB,YAAY,KAAK,YAAY,OAAO,CAAC,UAAU,KAAK,WAAW,KAAK,CAAC,IACrE,KAAK;AACT,SAAK,kBAAkB,KAAK,YAAY,OAAO;AAC/C,UAAM,UAAU,KAAK,gBAAgB,UAAU,CAAC,UAAU,MAAM,UAAU,KAAK,YAAY;AAC3F,SAAK,gBACH,WAAW,IACP,UACA,KAAK,IAAI,KAAK,eAAe,KAAK,IAAI,GAAG,KAAK,gBAAgB,SAAS,CAAC,CAAC;AAC/E,SAAK,WAAW;AAAA,EAClB;AAAA;AAAA,EAGQ,WAAW,OAA2B;AAC5C,QAAI,CAAC,MAAM,QAAS,QAAO,GAAG,MAAM,EAAE,IAAI,MAAM,IAAI;AACpD,WAAO,GAAG,MAAM,QAAQ,IAAI,MAAM,QAAQ,IAAI,MAAM,EAAE,IAAI,MAAM,QAAQ,IAAI,MAAM,EAAE,IAAI,MAAM,IAAI;AAAA,EACpG;AAAA,EAEQ,aAAmB;AACzB,SAAK,cAAc,MAAM;AACzB,UAAM,aAAa;AACnB,UAAM,QAAQ,KAAK,gBAAgB;AACnC,UAAM,aAAa,KAAK;AAAA,MACtB;AAAA,MACA,KAAK,IAAI,KAAK,gBAAgB,KAAK,MAAM,aAAa,CAAC,GAAG,QAAQ,UAAU;AAAA,IAC9E;AACA,UAAM,WAAW,KAAK,IAAI,aAAa,YAAY,KAAK;AACxD,aAAS,IAAI,YAAY,IAAI,UAAU,KAAK;AAC1C,YAAM,QAAQ,KAAK,gBAAgB,CAAC;AACpC,UAAI,CAAC,MAAO;AACZ,YAAM,aAAa,MAAM,KAAK;AAC9B,YAAM,YAAY,MAAM,UAAU,KAAK;AACvC,YAAM,QAAQ,MAAM,WAAW,IAAI,KAAK,MAAM,GAAG,SAAS,IAAI,MAAM,QAAQ,GAAG,CAAC,KAAK;AACrF,YAAM,QAAQ,YAAY,KAAK,MAAM,GAAG,WAAW,SAAI,IAAI;AAC3D,YAAM,OAAO,aACT,GAAG,KAAK,MAAM,GAAG,UAAU,SAAS,CAAC,GAAG,KAAK,MAAM,GAAG,UAAU,MAAM,EAAE,CAAC,GAAG,KAAK,GAAG,KAAK,KACzF,KAAK,MAAM,EAAE,GAAG,KAAK,GAAG,KAAK;AACjC,WAAK,cAAc,SAAS,IAAI,KAAK,MAAM,GAAG,CAAC,CAAC;AAAA,IAClD;AACA,QAAI,aAAa,KAAK,WAAW,OAAO;AACtC,WAAK,cAAc;AAAA,QACjB,IAAI,KAAK,KAAK,MAAM,GAAG,SAAS,MAAM,KAAK,gBAAgB,CAAC,IAAI,KAAK,GAAG,GAAG,GAAG,CAAC;AAAA,MACjF;AAAA,IACF;AACA,QAAI,UAAU,GAAG;AACf,WAAK,cAAc,SAAS,IAAI,KAAK,KAAK,MAAM,GAAG,SAAS,sBAAsB,GAAG,GAAG,CAAC,CAAC;AAAA,IAC5F,OAAO;AACL,YAAM,WAAW,KAAK,gBAAgB,KAAK,aAAa;AACxD,WAAK,cAAc,SAAS,IAAI,OAAO,CAAC,CAAC;AACzC,WAAK,cAAc;AAAA,QACjB,IAAI;AAAA,UACF,KAAK,MAAM,GAAG,SAAS,iBAAiB,WAAW,SAAS,OAAO,EAAE,EAAE;AAAA,UACvE;AAAA,UACA;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
FabricModelSelector
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-VRYEGVHR.js";
|
|
4
4
|
import {
|
|
5
5
|
INHERIT_VALUE
|
|
6
6
|
} from "./chunk-CQFP2RCP.js";
|
|
@@ -4567,4 +4567,4 @@ var FabricDashboard = class {
|
|
|
4567
4567
|
export {
|
|
4568
4568
|
FabricDashboard
|
|
4569
4569
|
};
|
|
4570
|
-
//# sourceMappingURL=dashboard-
|
|
4570
|
+
//# sourceMappingURL=dashboard-6HFBSZQ4.js.map
|
|
@@ -11707,4 +11707,4 @@ var deepAssign = (target, source) => {
|
|
|
11707
11707
|
export {
|
|
11708
11708
|
FabricRuntimeState
|
|
11709
11709
|
};
|
|
11710
|
-
//# sourceMappingURL=fabric-runtime-state-
|
|
11710
|
+
//# sourceMappingURL=fabric-runtime-state-LG265P3R.js.map
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
FabricModelSelector
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-VRYEGVHR.js";
|
|
4
4
|
import {
|
|
5
5
|
INHERIT_VALUE,
|
|
6
6
|
buildClaudeModelSource,
|
|
@@ -378,6 +378,10 @@ var IntegerInputSubmenu = class extends Container {
|
|
|
378
378
|
this.input.focused = true;
|
|
379
379
|
return super.render(width);
|
|
380
380
|
}
|
|
381
|
+
submitRpc(value) {
|
|
382
|
+
this.input.setValue(value);
|
|
383
|
+
this.input.handleInput("\r");
|
|
384
|
+
}
|
|
381
385
|
};
|
|
382
386
|
var StringInputSubmenu = class extends Container {
|
|
383
387
|
input;
|
|
@@ -403,11 +407,17 @@ var StringInputSubmenu = class extends Container {
|
|
|
403
407
|
this.input.focused = true;
|
|
404
408
|
return super.render(width);
|
|
405
409
|
}
|
|
410
|
+
submitRpc(value) {
|
|
411
|
+
this.input.setValue(value);
|
|
412
|
+
this.input.handleInput("\r");
|
|
413
|
+
}
|
|
406
414
|
};
|
|
407
415
|
var SelectSubmenu = class extends Container {
|
|
408
416
|
selectList;
|
|
417
|
+
options;
|
|
409
418
|
constructor(theme, title, description, options, currentValue, onSelect, onCancel) {
|
|
410
419
|
super();
|
|
420
|
+
this.options = options;
|
|
411
421
|
this.addChild(new Text(theme.bold(theme.fg("accent", title)), 0, 0));
|
|
412
422
|
if (description) {
|
|
413
423
|
this.addChild(new Spacer(1));
|
|
@@ -431,6 +441,12 @@ var SelectSubmenu = class extends Container {
|
|
|
431
441
|
handleInput(data) {
|
|
432
442
|
this.selectList.handleInput(data);
|
|
433
443
|
}
|
|
444
|
+
selectRpc(value) {
|
|
445
|
+
const option = this.options.find((candidate) => candidate.value === value);
|
|
446
|
+
if (!option) return false;
|
|
447
|
+
this.selectList.onSelect?.(option);
|
|
448
|
+
return true;
|
|
449
|
+
}
|
|
434
450
|
};
|
|
435
451
|
var CompactionThresholdSubmenu = class extends Container {
|
|
436
452
|
constructor(theme, currentValue, done) {
|
|
@@ -503,6 +519,9 @@ var CompactionThresholdSubmenu = class extends Container {
|
|
|
503
519
|
handleInput(data) {
|
|
504
520
|
this.active.handleInput(data);
|
|
505
521
|
}
|
|
522
|
+
completeRpc(selectedValue) {
|
|
523
|
+
this.done(selectedValue);
|
|
524
|
+
}
|
|
506
525
|
};
|
|
507
526
|
var thinkingSubmenu = (theme, overrides = {}) => (currentValue, done) => {
|
|
508
527
|
const canonicalCurrent = THINKING_LEVELS.find((level) => thinkingLabel(level) === currentValue) ?? currentValue;
|
|
@@ -543,8 +562,12 @@ var modelPickerSubmenu = (theme, source, options = {}) => (currentValue, done) =
|
|
|
543
562
|
};
|
|
544
563
|
var SectionSubmenu = class extends Container {
|
|
545
564
|
settingsList;
|
|
565
|
+
items;
|
|
566
|
+
applyChange;
|
|
546
567
|
constructor(theme, title, description, items, onChange, onCancel, enableSearch = false) {
|
|
547
568
|
super();
|
|
569
|
+
this.items = items;
|
|
570
|
+
this.applyChange = onChange;
|
|
548
571
|
this.addChild(new Text(theme.bold(theme.fg("accent", title)), 0, 0));
|
|
549
572
|
if (description) {
|
|
550
573
|
this.addChild(new Spacer(1));
|
|
@@ -1490,11 +1513,176 @@ var buildFabricSettingsItems = (theme, config, apply, options) => {
|
|
|
1490
1513
|
];
|
|
1491
1514
|
return markDrillIn(items);
|
|
1492
1515
|
};
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1516
|
+
var RPC_BACK = "\u2190 Back";
|
|
1517
|
+
var RPC_DONE = "Done";
|
|
1518
|
+
var RPC_SWITCH_SCOPE = "Switch save scope";
|
|
1519
|
+
var rpcTitle = (path, description) => description ? `${path}
|
|
1520
|
+
${description}` : path;
|
|
1521
|
+
var cleanSettingLabel = (label) => label.replace(/\s+›$/, "");
|
|
1522
|
+
var rpcSettingRow = (item) => {
|
|
1523
|
+
const label = cleanSettingLabel(item.label);
|
|
1524
|
+
const current = item.currentValue ? ` \xB7 ${item.currentValue}` : "";
|
|
1525
|
+
return item.description ? `${label}${current} \u2014 ${item.description}` : `${label}${current}`;
|
|
1526
|
+
};
|
|
1527
|
+
var rpcChoiceRow = (choice) => {
|
|
1528
|
+
const current = choice.current ? " \xB7 Current" : "";
|
|
1529
|
+
return choice.description ? `${choice.label}${current} \u2014 ${choice.description}` : `${choice.label}${current}`;
|
|
1530
|
+
};
|
|
1531
|
+
var selectRpcChoice = async (context, title, choices) => {
|
|
1532
|
+
const rows = choices.map(rpcChoiceRow);
|
|
1533
|
+
const selected = await context.ui.select(title, rows);
|
|
1534
|
+
if (selected === void 0) return void 0;
|
|
1535
|
+
const index = rows.indexOf(selected);
|
|
1536
|
+
return index < 0 ? void 0 : choices[index]?.value;
|
|
1537
|
+
};
|
|
1538
|
+
var browseRpcSettings = async (context, path, description, items, onChange) => {
|
|
1539
|
+
while (true) {
|
|
1540
|
+
const rows = items.map(rpcSettingRow);
|
|
1541
|
+
const selected = await context.ui.select(rpcTitle(path, description), [...rows, RPC_BACK]);
|
|
1542
|
+
if (selected === void 0 || selected === RPC_BACK) return;
|
|
1543
|
+
const index = rows.indexOf(selected);
|
|
1544
|
+
const item = index < 0 ? void 0 : items[index];
|
|
1545
|
+
if (!item) continue;
|
|
1546
|
+
await editRpcSetting(context, `${path} \u203A ${cleanSettingLabel(item.label)}`, item, onChange);
|
|
1547
|
+
}
|
|
1548
|
+
};
|
|
1549
|
+
var editRpcSetting = async (context, path, item, onChange) => {
|
|
1550
|
+
if (!item.submenu) {
|
|
1551
|
+
const values = item.values ?? [];
|
|
1552
|
+
if (values.length === 0) {
|
|
1553
|
+
context.ui.notify(`${cleanSettingLabel(item.label)} is read-only`, "info");
|
|
1554
|
+
return;
|
|
1555
|
+
}
|
|
1556
|
+
const selected = await selectRpcChoice(
|
|
1557
|
+
context,
|
|
1558
|
+
rpcTitle(path, item.description),
|
|
1559
|
+
unique([item.currentValue, ...values]).map((value) => ({
|
|
1560
|
+
value,
|
|
1561
|
+
label: value,
|
|
1562
|
+
current: value === item.currentValue
|
|
1563
|
+
}))
|
|
1564
|
+
);
|
|
1565
|
+
if (selected === void 0) return;
|
|
1566
|
+
item.currentValue = selected;
|
|
1567
|
+
onChange(item.id, selected);
|
|
1496
1568
|
return;
|
|
1497
1569
|
}
|
|
1570
|
+
let completed = false;
|
|
1571
|
+
let selectedValue;
|
|
1572
|
+
const component = item.submenu(item.currentValue, (value) => {
|
|
1573
|
+
completed = true;
|
|
1574
|
+
selectedValue = value;
|
|
1575
|
+
});
|
|
1576
|
+
if (component instanceof SectionSubmenu) {
|
|
1577
|
+
await browseRpcSettings(
|
|
1578
|
+
context,
|
|
1579
|
+
path,
|
|
1580
|
+
item.description,
|
|
1581
|
+
component.items,
|
|
1582
|
+
(id, value) => {
|
|
1583
|
+
const child = component.items.find((candidate) => candidate.id === id);
|
|
1584
|
+
if (child) child.currentValue = value;
|
|
1585
|
+
component.applyChange(id, value);
|
|
1586
|
+
}
|
|
1587
|
+
);
|
|
1588
|
+
return;
|
|
1589
|
+
}
|
|
1590
|
+
if (component instanceof SelectSubmenu) {
|
|
1591
|
+
const selected = await selectRpcChoice(
|
|
1592
|
+
context,
|
|
1593
|
+
rpcTitle(path, item.description),
|
|
1594
|
+
component.options.map((option) => ({
|
|
1595
|
+
value: option.value,
|
|
1596
|
+
label: option.label,
|
|
1597
|
+
...option.description ? { description: option.description } : {},
|
|
1598
|
+
current: option.value === item.currentValue || option.label === item.currentValue
|
|
1599
|
+
}))
|
|
1600
|
+
);
|
|
1601
|
+
if (selected === void 0 || !component.selectRpc(selected)) return;
|
|
1602
|
+
} else if (component instanceof IntegerInputSubmenu) {
|
|
1603
|
+
while (!completed) {
|
|
1604
|
+
const value = await context.ui.input(rpcTitle(path, item.description), component.input.getValue());
|
|
1605
|
+
if (value === void 0) return;
|
|
1606
|
+
if (!/^\d+$/.test(value.trim()) || !Number.isSafeInteger(Number(value.trim()))) {
|
|
1607
|
+
context.ui.notify("Enter a non-negative safe integer.", "warning");
|
|
1608
|
+
continue;
|
|
1609
|
+
}
|
|
1610
|
+
component.submitRpc(value);
|
|
1611
|
+
}
|
|
1612
|
+
} else if (component instanceof StringInputSubmenu) {
|
|
1613
|
+
const value = await context.ui.input(rpcTitle(path, item.description), component.input.getValue());
|
|
1614
|
+
if (value === void 0) return;
|
|
1615
|
+
component.submitRpc(value);
|
|
1616
|
+
} else if (component instanceof CompactionThresholdSubmenu) {
|
|
1617
|
+
const selected = await selectRpcChoice(
|
|
1618
|
+
context,
|
|
1619
|
+
rpcTitle(path, item.description),
|
|
1620
|
+
[
|
|
1621
|
+
{ value: COMPACTION_DEFAULT_THRESHOLD_LABEL, label: COMPACTION_DEFAULT_THRESHOLD_LABEL, current: item.currentValue === COMPACTION_DEFAULT_THRESHOLD_LABEL },
|
|
1622
|
+
{ value: COMPACTION_PERCENT_OPTION_LABEL, label: COMPACTION_PERCENT_OPTION_LABEL, current: item.currentValue.endsWith("%") },
|
|
1623
|
+
{ value: COMPACTION_TOKENS_OPTION_LABEL, label: COMPACTION_TOKENS_OPTION_LABEL, current: item.currentValue.endsWith(" tokens") }
|
|
1624
|
+
]
|
|
1625
|
+
);
|
|
1626
|
+
if (selected === void 0) return;
|
|
1627
|
+
if (selected === COMPACTION_DEFAULT_THRESHOLD_LABEL) {
|
|
1628
|
+
component.completeRpc(selected);
|
|
1629
|
+
} else {
|
|
1630
|
+
const percent = /^(\d+)%$/.exec(item.currentValue)?.[1] ?? "";
|
|
1631
|
+
const tokenText = /^(.+?) tokens$/.exec(item.currentValue)?.[1];
|
|
1632
|
+
const placeholder = selected === COMPACTION_PERCENT_OPTION_LABEL ? percent : tokenText === void 0 ? "" : String(parseFormattedNumericValue(tokenText));
|
|
1633
|
+
const input = await context.ui.input(rpcTitle(path, item.description), placeholder);
|
|
1634
|
+
if (input === void 0 || !/^\d+$/.test(input.trim())) return;
|
|
1635
|
+
const numeric = Number(input.trim());
|
|
1636
|
+
component.completeRpc(
|
|
1637
|
+
selected === COMPACTION_PERCENT_OPTION_LABEL ? `${clampCompactionPercentThreshold(numeric)}%` : `${formatTokens(clampCompactionTokenThreshold(numeric))} tokens`
|
|
1638
|
+
);
|
|
1639
|
+
}
|
|
1640
|
+
} else if (component instanceof FabricModelSelector) {
|
|
1641
|
+
const selected = await selectRpcChoice(
|
|
1642
|
+
context,
|
|
1643
|
+
rpcTitle(path, item.description),
|
|
1644
|
+
component.rpcChoices().map((choice) => ({
|
|
1645
|
+
value: choice.value,
|
|
1646
|
+
label: choice.label,
|
|
1647
|
+
description: choice.description,
|
|
1648
|
+
current: choice.current
|
|
1649
|
+
}))
|
|
1650
|
+
);
|
|
1651
|
+
if (selected === void 0 || !component.selectRpc(selected)) return;
|
|
1652
|
+
} else {
|
|
1653
|
+
context.ui.notify(`${cleanSettingLabel(item.label)} requires terminal UI`, "warning");
|
|
1654
|
+
return;
|
|
1655
|
+
}
|
|
1656
|
+
if (!completed || selectedValue === void 0) return;
|
|
1657
|
+
item.currentValue = selectedValue;
|
|
1658
|
+
onChange(item.id, selectedValue);
|
|
1659
|
+
};
|
|
1660
|
+
var openRpcFabricSettings = async (context, options) => {
|
|
1661
|
+
while (true) {
|
|
1662
|
+
const scope = options.getScope();
|
|
1663
|
+
const items = options.itemsForScope(scope);
|
|
1664
|
+
const rows = items.map(rpcSettingRow);
|
|
1665
|
+
const scopeDestination = scope === "project" ? "Project overrides (.pi/fabric.json)" : "Global defaults (~/.pi/agent/fabric.json)";
|
|
1666
|
+
const controls = [
|
|
1667
|
+
...options.projectScopeAvailable ? [`${RPC_SWITCH_SCOPE} \xB7 ${scope === "project" ? "Global defaults" : "Project overrides"}`] : [],
|
|
1668
|
+
RPC_DONE
|
|
1669
|
+
];
|
|
1670
|
+
const selected = await context.ui.select(
|
|
1671
|
+
rpcTitle("Fabric settings", `Editing: ${scopeDestination}`),
|
|
1672
|
+
[...rows, ...controls]
|
|
1673
|
+
);
|
|
1674
|
+
if (selected === void 0 || selected === RPC_DONE) return;
|
|
1675
|
+
if (selected.startsWith(RPC_SWITCH_SCOPE)) {
|
|
1676
|
+
options.setScope(scope === "project" ? "global" : "project");
|
|
1677
|
+
continue;
|
|
1678
|
+
}
|
|
1679
|
+
const index = rows.indexOf(selected);
|
|
1680
|
+
const item = index < 0 ? void 0 : items[index];
|
|
1681
|
+
if (!item) continue;
|
|
1682
|
+
await editRpcSetting(context, `Fabric settings \u203A ${cleanSettingLabel(item.label)}`, item, options.persist);
|
|
1683
|
+
}
|
|
1684
|
+
};
|
|
1685
|
+
async function openFabricSettings(context, deps) {
|
|
1498
1686
|
await deps.state.ensure(context);
|
|
1499
1687
|
const agentDir = resolveAgentDir();
|
|
1500
1688
|
const projectTrusted = context.isProjectTrusted();
|
|
@@ -1556,36 +1744,51 @@ async function openFabricSettings(context, deps) {
|
|
|
1556
1744
|
);
|
|
1557
1745
|
}
|
|
1558
1746
|
});
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1747
|
+
const itemsForScope = (scope, theme) => {
|
|
1748
|
+
settingsConfig = loadFabricConfigForScope(configLocation, scope);
|
|
1749
|
+
return buildFabricSettingsItems(theme, settingsConfig, apply, {
|
|
1750
|
+
keepVisibleCandidates,
|
|
1751
|
+
modelSource,
|
|
1752
|
+
claudeModelSource,
|
|
1753
|
+
...activeModelKey ? { activeModelKey } : {}
|
|
1754
|
+
});
|
|
1755
|
+
};
|
|
1756
|
+
if (context.mode === "rpc") {
|
|
1757
|
+
await openRpcFabricSettings(context, {
|
|
1758
|
+
projectScopeAvailable: projectTrusted,
|
|
1759
|
+
getScope: () => saveScope,
|
|
1760
|
+
setScope: (scope) => {
|
|
1761
|
+
saveScope = scope;
|
|
1762
|
+
},
|
|
1763
|
+
itemsForScope: (scope) => itemsForScope(scope, context.ui.theme),
|
|
1764
|
+
persist
|
|
1765
|
+
});
|
|
1766
|
+
} else if (context.mode !== "tui") {
|
|
1767
|
+
context.ui.notify("Fabric settings require an interactive UI", "warning");
|
|
1768
|
+
return;
|
|
1769
|
+
} else {
|
|
1770
|
+
await context.ui.custom(
|
|
1771
|
+
(tui, theme, _keybindings, done) => {
|
|
1772
|
+
const component = new FabricSettingsComponent(
|
|
1773
|
+
theme,
|
|
1774
|
+
itemsForScope(saveScope, theme),
|
|
1775
|
+
persist,
|
|
1776
|
+
() => done(),
|
|
1777
|
+
{
|
|
1778
|
+
initialSaveScope: saveScope,
|
|
1779
|
+
projectScopeAvailable: projectTrusted,
|
|
1780
|
+
onSaveScopeChange: (scope) => {
|
|
1781
|
+
saveScope = scope;
|
|
1782
|
+
tui.requestRender();
|
|
1783
|
+
},
|
|
1784
|
+
itemsForSaveScope: (scope) => itemsForScope(scope, theme)
|
|
1785
|
+
}
|
|
1786
|
+
);
|
|
1787
|
+
rootComponent = component;
|
|
1788
|
+
return component;
|
|
1789
|
+
}
|
|
1790
|
+
);
|
|
1791
|
+
}
|
|
1589
1792
|
if (dirty) {
|
|
1590
1793
|
deps.applyFabricMode();
|
|
1591
1794
|
const needsReload = [...changedSections].some((section) => RELOAD_SECTIONS.has(section));
|
|
@@ -1609,4 +1812,4 @@ export {
|
|
|
1609
1812
|
parseFormattedNumericValue,
|
|
1610
1813
|
populateClaudeModelSource
|
|
1611
1814
|
};
|
|
1612
|
-
//# sourceMappingURL=settings-
|
|
1815
|
+
//# sourceMappingURL=settings-J26PVVBO.js.map
|