@caupulican/pi-adaptative 0.80.93 → 0.80.95
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/CHANGELOG.md +30 -0
- package/dist/core/models/fitness-store.d.ts +2 -0
- package/dist/core/models/fitness-store.d.ts.map +1 -1
- package/dist/core/models/fitness-store.js +10 -0
- package/dist/core/models/fitness-store.js.map +1 -1
- package/dist/core/models/local-registration.d.ts +18 -0
- package/dist/core/models/local-registration.d.ts.map +1 -0
- package/dist/core/models/local-registration.js +83 -0
- package/dist/core/models/local-registration.js.map +1 -0
- package/dist/core/models/local-runtime.d.ts +84 -0
- package/dist/core/models/local-runtime.d.ts.map +1 -0
- package/dist/core/models/local-runtime.js +219 -0
- package/dist/core/models/local-runtime.js.map +1 -0
- package/dist/core/models/model-ref.d.ts +19 -0
- package/dist/core/models/model-ref.d.ts.map +1 -0
- package/dist/core/models/model-ref.js +61 -0
- package/dist/core/models/model-ref.js.map +1 -0
- package/dist/core/slash-commands.d.ts.map +1 -1
- package/dist/core/slash-commands.js +4 -0
- package/dist/core/slash-commands.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts +7 -0
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +192 -10
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
- package/examples/extensions/custom-provider-anthropic/package.json +1 -1
- package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
- package/examples/extensions/sandbox/package-lock.json +2 -2
- package/examples/extensions/sandbox/package.json +1 -1
- package/examples/extensions/with-deps/package-lock.json +2 -2
- package/examples/extensions/with-deps/package.json +1 -1
- package/npm-shrinkwrap.json +12 -12
- package/package.json +4 -4
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"local-runtime.js","sourceRoot":"","sources":["../../../src/core/models/local-runtime.ts"],"names":[],"mappings":"AAAA,OAAO,EAAqB,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAC9D,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAChD,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AA4C5C,MAAM,gBAAgB,GAAG,wBAAwB,CAAC;AAClD,MAAM,iBAAiB,GAAG,KAAK,CAAC;AAChC,MAAM,mBAAmB,GAAG,EAAE,CAAC;AAC/B,MAAM,sBAAsB,GAAG,GAAG,CAAC;AAEnC,MAAM,OAAO,aAAa;IACR,SAAS,CAAS;IAClB,QAAQ,CAAS;IACjB,MAAM,CAAe;IACrB,MAAM,CAA2C;IACjD,OAAO,CAA4B;IACnC,QAAQ,CAAS;IACjB,QAAQ,CAAS;IACjB,MAAM,CAAgC;IAC/C,MAAM,CAAkE;IAEhF,YAAY,IAAqE,EAAE;QAClF,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,QAAQ,CAAC;QAC/B,IAAI,CAAC,QAAQ,GAAG,CAAC,IAAI,CAAC,OAAO,IAAI,gBAAgB,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;QACtE,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,IAAI,EAAE,OAAO,IAAI,KAAK,CAAC;QAC1C,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,IAAI,EAAE,OAAO,IAAI,CAAC,CAAC,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,CAAC,KAAK,CAAC,OAAO,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC;QAChG,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,QAAQ,IAAI,UAAU,CAAC;QACjD,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,IAAI,EAAE,OAAO,IAAI,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,EAAE,CAAC;QAC7D,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,IAAI,EAAE,OAAO,IAAI,OAAO,EAAE,CAAC;QAChD,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,IAAI,EAAE,OAAO,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC;IAAA,CAChG;IAED,IAAI,OAAO,GAAW;QACrB,OAAO,IAAI,CAAC,QAAQ,CAAC;IAAA,CACrB;IAED,cAAc,GAAW;QACxB,OAAO,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAC;IAAA,CAChD;IAEO,WAAW,GAAyE;QAC3F,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,UAAU,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,CAAC,CAAC;QAC5E,IAAI,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC;YAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC;QACxE,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,aAAa,EAAE,KAAK,EAAE,QAAQ,CAAC,CAAC;QACzF,IAAI,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC;YAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC;QACxE,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,SAAS,CAAC,EAAE,CAAC;YAClD,IAAI,CAAC,GAAG;gBAAE,SAAS;YACnB,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;YACtC,IAAI,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC;gBAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC;QAC3E,CAAC;QACD,OAAO,SAAS,CAAC;IAAA,CACjB;IAEO,KAAK,CAAC,SAAS,GAAqB;QAC3C,IAAI,CAAC;YACJ,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC,QAAQ,WAAW,EAAE;gBAC/D,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,iBAAiB,CAAC;aAC9C,CAAC,CAAC;YACH,OAAO,QAAQ,CAAC,EAAE,CAAC;QACpB,CAAC;QAAC,MAAM,CAAC;YACR,OAAO,KAAK,CAAC;QACd,CAAC;IAAA,CACD;IAED,KAAK,CAAC,MAAM,GAAgC;QAC3C,MAAM,MAAM,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;QAClC,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,SAAS,EAAE,CAAC;QACxC,OAAO;YACN,UAAU,EAAE,MAAM,EAAE,IAAI;YACxB,YAAY,EAAE,MAAM,EAAE,MAAM;YAC5B,QAAQ;YACR,SAAS,EAAE,IAAI,CAAC,QAAQ;YACxB,WAAW,EAAE,IAAI,CAAC,MAAM,KAAK,SAAS,IAAI,QAAQ;YAClD,cAAc,EAAE,IAAI,CAAC,cAAc,EAAE;SACrC,CAAC;IAAA,CACF;IAED,yFAAyF;IACzF,YAAY,GAAa;QACxB,OAAO;YACN,kGAAgG;YAChG,6DAA6D;YAC7D,qGAAqG;YACrG,sBAAsB,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,aAAa,CAAC,EAAE;YAC7E,yEAAyE;YACzE,uGAAuG;SACvG,CAAC;IAAA,CACF;IAED;;;OAGG;IACH,KAAK,CAAC,KAAK,GAAkD;QAC5D,IAAI,MAAM,IAAI,CAAC,SAAS,EAAE,EAAE,CAAC;YAC5B,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,yBAAyB,CAAC,CAAC,CAAC,wBAAwB,EAAE,CAAC;QACvG,CAAC;QACD,MAAM,MAAM,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;QAClC,IAAI,CAAC,MAAM;YAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,gBAAgB,EAAE,CAAC;QACjE,SAAS,CAAC,IAAI,CAAC,cAAc,EAAE,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACtD,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,cAAc,EAAE,EAAE,CAAC,CAAC;QACvD,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,EAAE;YACjD,GAAG,EAAE;gBACJ,GAAG,OAAO,CAAC,GAAG;gBACd,WAAW,EAAE,IAAI;gBACjB,aAAa,EAAE,IAAI,CAAC,cAAc,EAAE;gBACpC,sBAAsB,EAAE,GAAG;gBAC3B,oBAAoB,EAAE,MAAM;gBAC5B,mBAAmB,EAAE,GAAG;gBACxB,wBAAwB,EAAE,GAAG;aAC7B;SACD,CAAC,CAAC;QACH,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,EAAE,CAAC;QACtB,KAAK,IAAI,OAAO,GAAG,CAAC,EAAE,OAAO,GAAG,mBAAmB,EAAE,OAAO,EAAE,EAAE,CAAC;YAChE,IAAI,MAAM,IAAI,CAAC,SAAS,EAAE;gBAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC;YACxE,MAAM,IAAI,CAAC,MAAM,CAAC,sBAAsB,CAAC,CAAC;QAC3C,CAAC;QACD,IAAI,CAAC,IAAI,EAAE,CAAC;QACZ,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,sBAAsB,EAAE,CAAC;IAAA,CAC1D;IAED,yFAAyF;IACzF,IAAI,GAAyB;QAC5B,IAAI,CAAC,IAAI,CAAC,MAAM;YAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;QAC5C,IAAI,CAAC;YACJ,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QAC7B,CAAC;QAAC,MAAM,CAAC;YACR,eAAe;QAChB,CAAC;QACD,IAAI,CAAC,MAAM,GAAG,SAAS,CAAC;QACxB,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;IAAA,CACzB;IAED,KAAK,CAAC,IAAI,GAAmC;QAC5C,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC,QAAQ,WAAW,EAAE,EAAE,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QACzG,IAAI,CAAC,QAAQ,CAAC,EAAE;YAAE,MAAM,IAAI,KAAK,CAAC,4BAA4B,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;QACjF,MAAM,IAAI,GAAG,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAyD,CAAC;QAC7F,OAAO,CAAC,IAAI,CAAC,MAAM,IAAI,EAAE,CAAC;aACxB,MAAM,CAAC,CAAC,KAAK,EAA4C,EAAE,CAAC,OAAO,KAAK,CAAC,IAAI,KAAK,QAAQ,CAAC;aAC3F,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,SAAS,EAAE,KAAK,CAAC,IAAI,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;IAAA,CACrE;IAED,qFAAqF;IACrF,KAAK,CAAC,IAAI,CAAC,GAAW,EAAE,UAAqC,EAA4C;QACxG,IAAI,CAAC;YACJ,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC,QAAQ,WAAW,EAAE;gBAC/D,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;gBAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;aAClD,CAAC,CAAC;YACH,IAAI,CAAC,QAAQ,CAAC,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;gBACpC,OAAO;oBACN,EAAE,EAAE,KAAK;oBACT,KAAK,EAAE,qBAAqB,QAAQ,CAAC,MAAM,IAAI,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,EAAE;iBACtF,CAAC;YACH,CAAC;YACD,MAAM,MAAM,GAAG,QAAQ,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC;YACzC,MAAM,OAAO,GAAG,IAAI,WAAW,EAAE,CAAC;YAClC,IAAI,MAAM,GAAG,EAAE,CAAC;YAChB,IAAI,UAAU,GAAG,EAAE,CAAC;YACpB,IAAI,YAAgC,CAAC;YACrC,MAAM,UAAU,GAAG,CAAC,IAAY,EAAQ,EAAE,CAAC;gBAC1C,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE;oBAAE,OAAO;gBACzB,IAAI,CAAC;oBACJ,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAwC,CAAC;oBACtE,IAAI,KAAK,CAAC,KAAK;wBAAE,YAAY,GAAG,KAAK,CAAC,KAAK,CAAC;oBAC5C,IAAI,KAAK,CAAC,MAAM,IAAI,KAAK,CAAC,MAAM,KAAK,UAAU,EAAE,CAAC;wBACjD,UAAU,GAAG,KAAK,CAAC,MAAM,CAAC;wBAC1B,UAAU,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;oBAC5B,CAAC;gBACF,CAAC;gBAAC,MAAM,CAAC;oBACR,qBAAqB;gBACtB,CAAC;YAAA,CACD,CAAC;YACF,SAAS,CAAC;gBACT,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,MAAM,MAAM,CAAC,IAAI,EAAE,CAAC;gBAC5C,IAAI,IAAI;oBAAE,MAAM;gBAChB,MAAM,IAAI,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;gBAClD,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;gBACjC,MAAM,GAAG,KAAK,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC;gBAC3B,KAAK,MAAM,IAAI,IAAI,KAAK;oBAAE,UAAU,CAAC,IAAI,CAAC,CAAC;YAC5C,CAAC;YACD,uFAAqF;YACrF,mFAAmF;YACnF,UAAU,CAAC,MAAM,CAAC,CAAC;YACnB,IAAI,YAAY;gBAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,YAAY,EAAE,CAAC;YAC5D,OAAO,UAAU,KAAK,SAAS;gBAC9B,CAAC,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE;gBACd,CAAC,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,oBAAoB,UAAU,IAAI,SAAS,EAAE,EAAE,CAAC;QACxE,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAChB,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;QACrF,CAAC;IAAA,CACD;IAED,6FAA2F;IAC3F,KAAK,CAAC,MAAM,CAAC,GAAW,EAA4C;QACnE,IAAI,CAAC;YACJ,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC,QAAQ,aAAa,EAAE;gBACjE,MAAM,EAAE,QAAQ;gBAChB,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;gBAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC;aACpC,CAAC,CAAC;YACH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;gBAClB,OAAO;oBACN,EAAE,EAAE,KAAK;oBACT,KAAK,EAAE,uBAAuB,QAAQ,CAAC,MAAM,IAAI,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,EAAE;iBACxF,CAAC;YACH,CAAC;YACD,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC;QACrB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAChB,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;QACrF,CAAC;IAAA,CACD;CACD","sourcesContent":["import { type ChildProcess, spawn } from \"node:child_process\";\nimport { existsSync, mkdirSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { delimiter, join } from \"node:path\";\n\n/**\n * Local model runtime manager (local-model-lifecycle-design.md): Ollama first, interface kept\n * runtime-agnostic. Pi SPAWNS the serve process itself with OWNED model storage\n * (`OLLAMA_MODELS=<agentDir>/models/ollama`) so every downloaded weight lives inside pi's tree —\n * per-model disk accounting is trivial and full cleanup is one directory. If a system server is\n * already running, pi uses it instead of double-installing, with the honest tradeoff surfaced:\n * storage then lives in the system daemon's dir and removal control is limited to `ollama rm`.\n *\n * Hard boundaries (design \"Hard boundaries\"): lifecycle actions are USER commands only — this\n * module is never exposed as a model-invokable tool; install is GUIDE MODE (exact manual steps,\n * never `curl | sh`); removal is explicit, disclosed, and never automatic.\n */\n\nexport interface LocalRuntimeStatus {\n\tbinaryPath?: string;\n\tbinarySource?: \"system\" | \"user\" | \"pi-owned\";\n\tserverUp: boolean;\n\tserverUrl: string;\n\t/** True when the responding server is a child process pi spawned (owned storage applies). */\n\tmanagedByPi: boolean;\n\t/** Owned weights directory (only meaningful for pi-managed serves). */\n\townedModelsDir: string;\n}\n\nexport interface InstalledLocalModel {\n\tname: string;\n\tsizeBytes: number;\n}\n\nexport interface LocalRuntimeDeps {\n\tfetchFn?: typeof fetch;\n\tspawnFn?: (\n\t\tcommand: string,\n\t\targs: string[],\n\t\toptions: { env: NodeJS.ProcessEnv },\n\t) => Pick<ChildProcess, \"pid\" | \"kill\" | \"unref\" | \"on\">;\n\texistsFn?: (path: string) => boolean;\n\tenvPath?: string;\n\thomeDir?: string;\n\tsleepFn?: (ms: number) => Promise<void>;\n}\n\nconst DEFAULT_BASE_URL = \"http://127.0.0.1:11434\";\nconst HEALTH_TIMEOUT_MS = 2_000;\nconst START_POLL_ATTEMPTS = 20;\nconst START_POLL_INTERVAL_MS = 500;\n\nexport class OllamaRuntime {\n\tprivate readonly _agentDir: string;\n\tprivate readonly _baseUrl: string;\n\tprivate readonly _fetch: typeof fetch;\n\tprivate readonly _spawn: NonNullable<LocalRuntimeDeps[\"spawnFn\"]>;\n\tprivate readonly _exists: (path: string) => boolean;\n\tprivate readonly _envPath: string;\n\tprivate readonly _homeDir: string;\n\tprivate readonly _sleep: (ms: number) => Promise<void>;\n\tprivate _child: Pick<ChildProcess, \"pid\" | \"kill\" | \"unref\" | \"on\"> | undefined;\n\n\tconstructor(args: { agentDir: string; baseUrl?: string; deps?: LocalRuntimeDeps }) {\n\t\tthis._agentDir = args.agentDir;\n\t\tthis._baseUrl = (args.baseUrl ?? DEFAULT_BASE_URL).replace(/\\/$/, \"\");\n\t\tthis._fetch = args.deps?.fetchFn ?? fetch;\n\t\tthis._spawn = args.deps?.spawnFn ?? ((command, argv, options) => spawn(command, argv, options));\n\t\tthis._exists = args.deps?.existsFn ?? existsSync;\n\t\tthis._envPath = args.deps?.envPath ?? process.env.PATH ?? \"\";\n\t\tthis._homeDir = args.deps?.homeDir ?? homedir();\n\t\tthis._sleep = args.deps?.sleepFn ?? ((ms) => new Promise((resolve) => setTimeout(resolve, ms)));\n\t}\n\n\tget baseUrl(): string {\n\t\treturn this._baseUrl;\n\t}\n\n\townedModelsDir(): string {\n\t\treturn join(this._agentDir, \"models\", \"ollama\");\n\t}\n\n\tprivate _findBinary(): { path: string; source: \"system\" | \"user\" | \"pi-owned\" } | undefined {\n\t\tconst piOwned = join(this._agentDir, \"runtimes\", \"ollama\", \"bin\", \"ollama\");\n\t\tif (this._exists(piOwned)) return { path: piOwned, source: \"pi-owned\" };\n\t\tconst userLevel = join(this._homeDir, \".local\", \"share\", \"ollama-dist\", \"bin\", \"ollama\");\n\t\tif (this._exists(userLevel)) return { path: userLevel, source: \"user\" };\n\t\tfor (const dir of this._envPath.split(delimiter)) {\n\t\t\tif (!dir) continue;\n\t\t\tconst candidate = join(dir, \"ollama\");\n\t\t\tif (this._exists(candidate)) return { path: candidate, source: \"system\" };\n\t\t}\n\t\treturn undefined;\n\t}\n\n\tprivate async _serverUp(): Promise<boolean> {\n\t\ttry {\n\t\t\tconst response = await this._fetch(`${this._baseUrl}/api/tags`, {\n\t\t\t\tsignal: AbortSignal.timeout(HEALTH_TIMEOUT_MS),\n\t\t\t});\n\t\t\treturn response.ok;\n\t\t} catch {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\tasync detect(): Promise<LocalRuntimeStatus> {\n\t\tconst binary = this._findBinary();\n\t\tconst serverUp = await this._serverUp();\n\t\treturn {\n\t\t\tbinaryPath: binary?.path,\n\t\t\tbinarySource: binary?.source,\n\t\t\tserverUp,\n\t\t\tserverUrl: this._baseUrl,\n\t\t\tmanagedByPi: this._child !== undefined && serverUp,\n\t\t\townedModelsDir: this.ownedModelsDir(),\n\t\t};\n\t}\n\n\t/** GUIDE MODE: exact manual steps, printed, never executed (no `curl | sh`, no sudo). */\n\tinstallGuide(): string[] {\n\t\treturn [\n\t\t\t\"Ollama is not installed. Pi never runs installers itself — manual steps (user-level, no sudo):\",\n\t\t\t\" 1. Download the pinned release archive for your platform:\",\n\t\t\t\" https://github.com/ollama/ollama/releases (asset: ollama-linux-amd64.tar.zst or your platform)\",\n\t\t\t` 2. Extract it to ${join(this._homeDir, \".local\", \"share\", \"ollama-dist\")}`,\n\t\t\t\" 3. Re-run your /models command - pi detects the binary automatically.\",\n\t\t\t\"Alternatively install system-wide from https://ollama.com/download and pi will use the system server.\",\n\t\t];\n\t}\n\n\t/**\n\t * Start a pi-managed serve with OWNED storage and the hardened env verified on this class of\n\t * hardware. No-op (reported) when a server already responds — pi never double-serves.\n\t */\n\tasync start(): Promise<{ started: boolean; reason: string }> {\n\t\tif (await this._serverUp()) {\n\t\t\treturn { started: false, reason: this._child ? \"already_running_managed\" : \"already_running_system\" };\n\t\t}\n\t\tconst binary = this._findBinary();\n\t\tif (!binary) return { started: false, reason: \"binary_missing\" };\n\t\tmkdirSync(this.ownedModelsDir(), { recursive: true });\n\t\tconst host = this._baseUrl.replace(/^https?:\\/\\//, \"\");\n\t\tthis._child = this._spawn(binary.path, [\"serve\"], {\n\t\t\tenv: {\n\t\t\t\t...process.env,\n\t\t\t\tOLLAMA_HOST: host,\n\t\t\t\tOLLAMA_MODELS: this.ownedModelsDir(),\n\t\t\t\tOLLAMA_FLASH_ATTENTION: \"1\",\n\t\t\t\tOLLAMA_KV_CACHE_TYPE: \"q8_0\",\n\t\t\t\tOLLAMA_NUM_PARALLEL: \"1\",\n\t\t\t\tOLLAMA_MAX_LOADED_MODELS: \"3\",\n\t\t\t},\n\t\t});\n\t\tthis._child.unref?.();\n\t\tfor (let attempt = 0; attempt < START_POLL_ATTEMPTS; attempt++) {\n\t\t\tif (await this._serverUp()) return { started: true, reason: \"started\" };\n\t\t\tawait this._sleep(START_POLL_INTERVAL_MS);\n\t\t}\n\t\tthis.stop();\n\t\treturn { started: false, reason: \"health_check_timeout\" };\n\t}\n\n\t/** Resource hygiene only: stops the pi-managed serve process; never deletes anything. */\n\tstop(): { stopped: boolean } {\n\t\tif (!this._child) return { stopped: false };\n\t\ttry {\n\t\t\tthis._child.kill(\"SIGTERM\");\n\t\t} catch {\n\t\t\t// already gone\n\t\t}\n\t\tthis._child = undefined;\n\t\treturn { stopped: true };\n\t}\n\n\tasync list(): Promise<InstalledLocalModel[]> {\n\t\tconst response = await this._fetch(`${this._baseUrl}/api/tags`, { signal: AbortSignal.timeout(10_000) });\n\t\tif (!response.ok) throw new Error(`ollama list failed: HTTP ${response.status}`);\n\t\tconst data = (await response.json()) as { models?: Array<{ name?: string; size?: number }> };\n\t\treturn (data.models ?? [])\n\t\t\t.filter((model): model is { name: string; size?: number } => typeof model.name === \"string\")\n\t\t\t.map((model) => ({ name: model.name, sizeBytes: model.size ?? 0 }));\n\t}\n\n\t/** Pull a model through the server API (weights land in the SERVER's models dir). */\n\tasync pull(ref: string, onProgress?: (status: string) => void): Promise<{ ok: boolean; error?: string }> {\n\t\ttry {\n\t\t\tconst response = await this._fetch(`${this._baseUrl}/api/pull`, {\n\t\t\t\tmethod: \"POST\",\n\t\t\t\theaders: { \"content-type\": \"application/json\" },\n\t\t\t\tbody: JSON.stringify({ model: ref, stream: true }),\n\t\t\t});\n\t\t\tif (!response.ok || !response.body) {\n\t\t\t\treturn {\n\t\t\t\t\tok: false,\n\t\t\t\t\terror: `pull failed: HTTP ${response.status} ${await response.text().catch(() => \"\")}`,\n\t\t\t\t};\n\t\t\t}\n\t\t\tconst reader = response.body.getReader();\n\t\t\tconst decoder = new TextDecoder();\n\t\t\tlet buffer = \"\";\n\t\t\tlet lastStatus = \"\";\n\t\t\tlet errorMessage: string | undefined;\n\t\t\tconst handleLine = (line: string): void => {\n\t\t\t\tif (!line.trim()) return;\n\t\t\t\ttry {\n\t\t\t\t\tconst event = JSON.parse(line) as { status?: string; error?: string };\n\t\t\t\t\tif (event.error) errorMessage = event.error;\n\t\t\t\t\tif (event.status && event.status !== lastStatus) {\n\t\t\t\t\t\tlastStatus = event.status;\n\t\t\t\t\t\tonProgress?.(event.status);\n\t\t\t\t\t}\n\t\t\t\t} catch {\n\t\t\t\t\t// partial line noise\n\t\t\t\t}\n\t\t\t};\n\t\t\tfor (;;) {\n\t\t\t\tconst { done, value } = await reader.read();\n\t\t\t\tif (done) break;\n\t\t\t\tbuffer += decoder.decode(value, { stream: true });\n\t\t\t\tconst lines = buffer.split(\"\\n\");\n\t\t\t\tbuffer = lines.pop() ?? \"\";\n\t\t\t\tfor (const line of lines) handleLine(line);\n\t\t\t}\n\t\t\t// The stream's FINAL line has no trailing newline — it stays in the buffer and holds\n\t\t\t// the terminal \"success\"/error event; dropping it misreports every completed pull.\n\t\t\thandleLine(buffer);\n\t\t\tif (errorMessage) return { ok: false, error: errorMessage };\n\t\t\treturn lastStatus === \"success\"\n\t\t\t\t? { ok: true }\n\t\t\t\t: { ok: false, error: `pull ended with: ${lastStatus || \"unknown\"}` };\n\t\t} catch (error) {\n\t\t\treturn { ok: false, error: error instanceof Error ? error.message : String(error) };\n\t\t}\n\t}\n\n\t/** EXPLICIT user action only — callers must have shown what gets deleted and confirmed. */\n\tasync remove(ref: string): Promise<{ ok: boolean; error?: string }> {\n\t\ttry {\n\t\t\tconst response = await this._fetch(`${this._baseUrl}/api/delete`, {\n\t\t\t\tmethod: \"DELETE\",\n\t\t\t\theaders: { \"content-type\": \"application/json\" },\n\t\t\t\tbody: JSON.stringify({ model: ref }),\n\t\t\t});\n\t\t\tif (!response.ok) {\n\t\t\t\treturn {\n\t\t\t\t\tok: false,\n\t\t\t\t\terror: `delete failed: HTTP ${response.status} ${await response.text().catch(() => \"\")}`,\n\t\t\t\t};\n\t\t\t}\n\t\t\treturn { ok: true };\n\t\t} catch (error) {\n\t\t\treturn { ok: false, error: error instanceof Error ? error.message : String(error) };\n\t\t}\n\t}\n}\n"]}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Model source normalizer (local-model-lifecycle-design.md, "one panel, three types"):
|
|
3
|
+
* everything a user can paste — an ollama tag, an hf.co GGUF ref, a full HuggingFace URL, a
|
|
4
|
+
* copied `ollama pull ...` install command, or an API `provider/model` name — normalizes to ONE
|
|
5
|
+
* typed source. Pure string work: pasted install commands are PARSED for their reference and
|
|
6
|
+
* NEVER executed as shell; unknown forms are rejected with the reason.
|
|
7
|
+
*/
|
|
8
|
+
export type ModelSource = {
|
|
9
|
+
type: "api";
|
|
10
|
+
ref: string;
|
|
11
|
+
} | {
|
|
12
|
+
type: "local";
|
|
13
|
+
pullRef: string;
|
|
14
|
+
} | {
|
|
15
|
+
type: "rejected";
|
|
16
|
+
reason: string;
|
|
17
|
+
};
|
|
18
|
+
export declare function normalizeModelSource(rawInput: string): ModelSource;
|
|
19
|
+
//# sourceMappingURL=model-ref.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"model-ref.d.ts","sourceRoot":"","sources":["../../../src/core/models/model-ref.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,MAAM,MAAM,WAAW,GACpB;IAAE,IAAI,EAAE,KAAK,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GAC5B;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GAClC;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAOxC,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,GAAG,WAAW,CAqDlE","sourcesContent":["/**\n * Model source normalizer (local-model-lifecycle-design.md, \"one panel, three types\"):\n * everything a user can paste — an ollama tag, an hf.co GGUF ref, a full HuggingFace URL, a\n * copied `ollama pull ...` install command, or an API `provider/model` name — normalizes to ONE\n * typed source. Pure string work: pasted install commands are PARSED for their reference and\n * NEVER executed as shell; unknown forms are rejected with the reason.\n */\n\nexport type ModelSource =\n\t| { type: \"api\"; ref: string }\n\t| { type: \"local\"; pullRef: string }\n\t| { type: \"rejected\"; reason: string };\n\nconst OLLAMA_TAG = /^[a-z0-9][a-z0-9._-]*(?::[A-Za-z0-9._-]+)?$/;\nconst HF_REF = /^hf\\.co\\/([\\w.-]+)\\/([\\w.-]+)(?::([\\w.-]+))?$/i;\nconst HF_URL = /^https?:\\/\\/(?:www\\.)?huggingface\\.co\\/([\\w.-]+)\\/([\\w.-]+)(?:\\/.*)?$/i;\nconst SHELL_METACHARS = /[;&|`$<>(){}\\\\]/;\n\nexport function normalizeModelSource(rawInput: string): ModelSource {\n\tconst input = rawInput.trim();\n\tif (input.length === 0) return { type: \"rejected\", reason: \"empty input\" };\n\tif (input.length > 500) return { type: \"rejected\", reason: \"input too long to be a model reference\" };\n\n\t// Pasted install command: extract the reference, never execute anything.\n\tconst installCommand = /^ollama\\s+(?:pull|run)\\s+(.+)$/i.exec(input);\n\tif (installCommand) {\n\t\tconst argument = installCommand[1]!.trim().split(/\\s+/)[0] ?? \"\";\n\t\tif (SHELL_METACHARS.test(argument)) {\n\t\t\treturn { type: \"rejected\", reason: \"install command argument contains shell metacharacters\" };\n\t\t}\n\t\tconst inner = normalizeModelSource(argument);\n\t\tif (inner.type === \"local\") return inner;\n\t\treturn { type: \"rejected\", reason: `could not extract a model reference from the install command` };\n\t}\n\n\tif (SHELL_METACHARS.test(input) || /\\s/.test(input)) {\n\t\treturn { type: \"rejected\", reason: \"not a recognized model reference (contains spaces or shell characters)\" };\n\t}\n\n\t// Full HuggingFace URL -> hf.co pull ref (org/repo; a :quant suffix must be given explicitly).\n\tconst hfUrl = HF_URL.exec(input);\n\tif (hfUrl) {\n\t\treturn { type: \"local\", pullRef: `hf.co/${hfUrl[1]}/${hfUrl[2]}` };\n\t}\n\n\t// hf.co/org/repo[:quant]\n\tconst hfRef = HF_REF.exec(input);\n\tif (hfRef) {\n\t\treturn { type: \"local\", pullRef: `hf.co/${hfRef[1]}/${hfRef[2]}${hfRef[3] ? `:${hfRef[3]}` : \"\"}` };\n\t}\n\n\tif (input.includes(\"://\")) {\n\t\treturn { type: \"rejected\", reason: \"only huggingface.co URLs are recognized as local model links\" };\n\t}\n\n\t// provider/model -> API-registered model (nothing to install; auth + selection only).\n\tif (input.includes(\"/\")) {\n\t\tconst [provider, ...rest] = input.split(\"/\");\n\t\tconst model = rest.join(\"/\");\n\t\tif (provider && model && !model.includes(\"/\")) {\n\t\t\treturn { type: \"api\", ref: `${provider}/${model}` };\n\t\t}\n\t\treturn { type: \"rejected\", reason: \"expected provider/model or hf.co/org/repo[:quant]\" };\n\t}\n\n\t// Bare ollama tag (\"qwen3:1.7b\", \"pi-lifter:latest\", \"llama3\").\n\tif (OLLAMA_TAG.test(input)) {\n\t\treturn { type: \"local\", pullRef: input };\n\t}\n\n\treturn { type: \"rejected\", reason: \"not a recognized model reference\" };\n}\n"]}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Model source normalizer (local-model-lifecycle-design.md, "one panel, three types"):
|
|
3
|
+
* everything a user can paste — an ollama tag, an hf.co GGUF ref, a full HuggingFace URL, a
|
|
4
|
+
* copied `ollama pull ...` install command, or an API `provider/model` name — normalizes to ONE
|
|
5
|
+
* typed source. Pure string work: pasted install commands are PARSED for their reference and
|
|
6
|
+
* NEVER executed as shell; unknown forms are rejected with the reason.
|
|
7
|
+
*/
|
|
8
|
+
const OLLAMA_TAG = /^[a-z0-9][a-z0-9._-]*(?::[A-Za-z0-9._-]+)?$/;
|
|
9
|
+
const HF_REF = /^hf\.co\/([\w.-]+)\/([\w.-]+)(?::([\w.-]+))?$/i;
|
|
10
|
+
const HF_URL = /^https?:\/\/(?:www\.)?huggingface\.co\/([\w.-]+)\/([\w.-]+)(?:\/.*)?$/i;
|
|
11
|
+
const SHELL_METACHARS = /[;&|`$<>(){}\\]/;
|
|
12
|
+
export function normalizeModelSource(rawInput) {
|
|
13
|
+
const input = rawInput.trim();
|
|
14
|
+
if (input.length === 0)
|
|
15
|
+
return { type: "rejected", reason: "empty input" };
|
|
16
|
+
if (input.length > 500)
|
|
17
|
+
return { type: "rejected", reason: "input too long to be a model reference" };
|
|
18
|
+
// Pasted install command: extract the reference, never execute anything.
|
|
19
|
+
const installCommand = /^ollama\s+(?:pull|run)\s+(.+)$/i.exec(input);
|
|
20
|
+
if (installCommand) {
|
|
21
|
+
const argument = installCommand[1].trim().split(/\s+/)[0] ?? "";
|
|
22
|
+
if (SHELL_METACHARS.test(argument)) {
|
|
23
|
+
return { type: "rejected", reason: "install command argument contains shell metacharacters" };
|
|
24
|
+
}
|
|
25
|
+
const inner = normalizeModelSource(argument);
|
|
26
|
+
if (inner.type === "local")
|
|
27
|
+
return inner;
|
|
28
|
+
return { type: "rejected", reason: `could not extract a model reference from the install command` };
|
|
29
|
+
}
|
|
30
|
+
if (SHELL_METACHARS.test(input) || /\s/.test(input)) {
|
|
31
|
+
return { type: "rejected", reason: "not a recognized model reference (contains spaces or shell characters)" };
|
|
32
|
+
}
|
|
33
|
+
// Full HuggingFace URL -> hf.co pull ref (org/repo; a :quant suffix must be given explicitly).
|
|
34
|
+
const hfUrl = HF_URL.exec(input);
|
|
35
|
+
if (hfUrl) {
|
|
36
|
+
return { type: "local", pullRef: `hf.co/${hfUrl[1]}/${hfUrl[2]}` };
|
|
37
|
+
}
|
|
38
|
+
// hf.co/org/repo[:quant]
|
|
39
|
+
const hfRef = HF_REF.exec(input);
|
|
40
|
+
if (hfRef) {
|
|
41
|
+
return { type: "local", pullRef: `hf.co/${hfRef[1]}/${hfRef[2]}${hfRef[3] ? `:${hfRef[3]}` : ""}` };
|
|
42
|
+
}
|
|
43
|
+
if (input.includes("://")) {
|
|
44
|
+
return { type: "rejected", reason: "only huggingface.co URLs are recognized as local model links" };
|
|
45
|
+
}
|
|
46
|
+
// provider/model -> API-registered model (nothing to install; auth + selection only).
|
|
47
|
+
if (input.includes("/")) {
|
|
48
|
+
const [provider, ...rest] = input.split("/");
|
|
49
|
+
const model = rest.join("/");
|
|
50
|
+
if (provider && model && !model.includes("/")) {
|
|
51
|
+
return { type: "api", ref: `${provider}/${model}` };
|
|
52
|
+
}
|
|
53
|
+
return { type: "rejected", reason: "expected provider/model or hf.co/org/repo[:quant]" };
|
|
54
|
+
}
|
|
55
|
+
// Bare ollama tag ("qwen3:1.7b", "pi-lifter:latest", "llama3").
|
|
56
|
+
if (OLLAMA_TAG.test(input)) {
|
|
57
|
+
return { type: "local", pullRef: input };
|
|
58
|
+
}
|
|
59
|
+
return { type: "rejected", reason: "not a recognized model reference" };
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=model-ref.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"model-ref.js","sourceRoot":"","sources":["../../../src/core/models/model-ref.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Model source normalizer (local-model-lifecycle-design.md, \"one panel, three types\"):\n * everything a user can paste — an ollama tag, an hf.co GGUF ref, a full HuggingFace URL, a\n * copied `ollama pull ...` install command, or an API `provider/model` name — normalizes to ONE\n * typed source. Pure string work: pasted install commands are PARSED for their reference and\n * NEVER executed as shell; unknown forms are rejected with the reason.\n */\n\nexport type ModelSource =\n\t| { type: \"api\"; ref: string }\n\t| { type: \"local\"; pullRef: string }\n\t| { type: \"rejected\"; reason: string };\n\nconst OLLAMA_TAG = /^[a-z0-9][a-z0-9._-]*(?::[A-Za-z0-9._-]+)?$/;\nconst HF_REF = /^hf\\.co\\/([\\w.-]+)\\/([\\w.-]+)(?::([\\w.-]+))?$/i;\nconst HF_URL = /^https?:\\/\\/(?:www\\.)?huggingface\\.co\\/([\\w.-]+)\\/([\\w.-]+)(?:\\/.*)?$/i;\nconst SHELL_METACHARS = /[;&|`$<>(){}\\\\]/;\n\nexport function normalizeModelSource(rawInput: string): ModelSource {\n\tconst input = rawInput.trim();\n\tif (input.length === 0) return { type: \"rejected\", reason: \"empty input\" };\n\tif (input.length > 500) return { type: \"rejected\", reason: \"input too long to be a model reference\" };\n\n\t// Pasted install command: extract the reference, never execute anything.\n\tconst installCommand = /^ollama\\s+(?:pull|run)\\s+(.+)$/i.exec(input);\n\tif (installCommand) {\n\t\tconst argument = installCommand[1]!.trim().split(/\\s+/)[0] ?? \"\";\n\t\tif (SHELL_METACHARS.test(argument)) {\n\t\t\treturn { type: \"rejected\", reason: \"install command argument contains shell metacharacters\" };\n\t\t}\n\t\tconst inner = normalizeModelSource(argument);\n\t\tif (inner.type === \"local\") return inner;\n\t\treturn { type: \"rejected\", reason: `could not extract a model reference from the install command` };\n\t}\n\n\tif (SHELL_METACHARS.test(input) || /\\s/.test(input)) {\n\t\treturn { type: \"rejected\", reason: \"not a recognized model reference (contains spaces or shell characters)\" };\n\t}\n\n\t// Full HuggingFace URL -> hf.co pull ref (org/repo; a :quant suffix must be given explicitly).\n\tconst hfUrl = HF_URL.exec(input);\n\tif (hfUrl) {\n\t\treturn { type: \"local\", pullRef: `hf.co/${hfUrl[1]}/${hfUrl[2]}` };\n\t}\n\n\t// hf.co/org/repo[:quant]\n\tconst hfRef = HF_REF.exec(input);\n\tif (hfRef) {\n\t\treturn { type: \"local\", pullRef: `hf.co/${hfRef[1]}/${hfRef[2]}${hfRef[3] ? `:${hfRef[3]}` : \"\"}` };\n\t}\n\n\tif (input.includes(\"://\")) {\n\t\treturn { type: \"rejected\", reason: \"only huggingface.co URLs are recognized as local model links\" };\n\t}\n\n\t// provider/model -> API-registered model (nothing to install; auth + selection only).\n\tif (input.includes(\"/\")) {\n\t\tconst [provider, ...rest] = input.split(\"/\");\n\t\tconst model = rest.join(\"/\");\n\t\tif (provider && model && !model.includes(\"/\")) {\n\t\t\treturn { type: \"api\", ref: `${provider}/${model}` };\n\t\t}\n\t\treturn { type: \"rejected\", reason: \"expected provider/model or hf.co/org/repo[:quant]\" };\n\t}\n\n\t// Bare ollama tag (\"qwen3:1.7b\", \"pi-lifter:latest\", \"llama3\").\n\tif (OLLAMA_TAG.test(input)) {\n\t\treturn { type: \"local\", pullRef: input };\n\t}\n\n\treturn { type: \"rejected\", reason: \"not a recognized model reference\" };\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"slash-commands.d.ts","sourceRoot":"","sources":["../../src/core/slash-commands.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAEnD,MAAM,MAAM,kBAAkB,GAAG,WAAW,GAAG,QAAQ,GAAG,OAAO,CAAC;AAElE,MAAM,WAAW,gBAAgB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,kBAAkB,CAAC;IAC3B,UAAU,EAAE,UAAU,CAAC;CACvB;AAED,MAAM,WAAW,mBAAmB;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;CACpB;AAED,eAAO,MAAM,sBAAsB,EAAE,aAAa,CAAC,mBAAmB,
|
|
1
|
+
{"version":3,"file":"slash-commands.d.ts","sourceRoot":"","sources":["../../src/core/slash-commands.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAEnD,MAAM,MAAM,kBAAkB,GAAG,WAAW,GAAG,QAAQ,GAAG,OAAO,CAAC;AAElE,MAAM,WAAW,gBAAgB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,kBAAkB,CAAC;IAC3B,UAAU,EAAE,UAAU,CAAC;CACvB;AAED,MAAM,WAAW,mBAAmB;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;CACpB;AAED,eAAO,MAAM,sBAAsB,EAAE,aAAa,CAAC,mBAAmB,CA0DrE,CAAC","sourcesContent":["import { APP_NAME } from \"../config.ts\";\nimport type { SourceInfo } from \"./source-info.ts\";\n\nexport type SlashCommandSource = \"extension\" | \"prompt\" | \"skill\";\n\nexport interface SlashCommandInfo {\n\tname: string;\n\tdescription?: string;\n\tsource: SlashCommandSource;\n\tsourceInfo: SourceInfo;\n}\n\nexport interface BuiltinSlashCommand {\n\tname: string;\n\tdescription: string;\n}\n\nexport const BUILTIN_SLASH_COMMANDS: ReadonlyArray<BuiltinSlashCommand> = [\n\t{ name: \"settings\", description: \"Open settings menu\" },\n\t{ name: \"autonomy\", description: \"Autonomy mode, diagnostics, research, fitness (/autonomy status)\" },\n\t{\n\t\tname: \"models\",\n\t\tdescription: \"Local model lifecycle: /models [list|add <ref-or-link>|remove <ref> confirm|stop]\",\n\t},\n\t{\n\t\tname: \"fitness\",\n\t\tdescription: \"Pick and probe a model for local/heavy-lifter roles, then assign it (/fitness [model] [trials])\",\n\t},\n\t{ name: \"context\", description: \"Context composition dashboard: what rides on every request\" },\n\t{ name: \"auto-learn\", description: \"Show Auto Learn/reflection status or run now (/auto-learn run)\" },\n\t{\n\t\tname: \"goal-continue\",\n\t\tdescription: \"Continue the current goal loop explicitly (/goal-continue [turns] [stalls])\",\n\t},\n\t{ name: \"model\", description: \"Select model (opens selector UI)\" },\n\t{ name: \"profiles\", description: \"Select a runtime profile for this session\" },\n\t{ name: \"scoped-models\", description: \"Enable/disable models for Ctrl+P cycling\" },\n\t{ name: \"export\", description: \"Export session (HTML default, or specify path: .html/.jsonl)\" },\n\t{ name: \"import\", description: \"Import and resume a session from a JSONL file\" },\n\t{ name: \"share\", description: \"Share session as a secret GitHub gist\" },\n\t{ name: \"copy\", description: \"Copy last agent message to clipboard\" },\n\t{ name: \"name\", description: \"Set session display name\" },\n\t{ name: \"session\", description: \"Show session info and stats\" },\n\t{ name: \"usage\", description: \"Show tokens, cost, and optimization controls\" },\n\t{ name: \"changelog\", description: \"Show changelog entries\" },\n\t{ name: \"hotkeys\", description: \"Show all keyboard shortcuts\" },\n\t{ name: \"fork\", description: \"Create a new fork from a previous user message (optional name: /fork <name>)\" },\n\t{\n\t\tname: \"clone\",\n\t\tdescription: \"Duplicate the current session at the current position (optional name: /clone <name>)\",\n\t},\n\t{ name: \"tree\", description: \"Navigate session tree (switch branches)\" },\n\t{ name: \"trust\", description: \"Trust or untrust this project folder\" },\n\t{ name: \"login\", description: \"Configure provider authentication\" },\n\t{ name: \"logout\", description: \"Remove provider authentication\" },\n\t{ name: \"new\", description: \"Start a new session (optional name: /new <name>)\" },\n\t{ name: \"compact\", description: \"Manually compact the session context\" },\n\t{ name: \"curate\", description: \"Review/archive stale or overlapping reflection-promoted skills\" },\n\t{ name: \"resume\", description: \"Resume a different session\" },\n\t{ name: \"reload\", description: \"Reload keybindings, extensions, skills, prompts, and themes\" },\n\t{ name: \"exit\", description: `Quit ${APP_NAME}` },\n\t{\n\t\tname: \"install-resources\",\n\t\tdescription:\n\t\t\t\"Copy resources from a trusted directory to user local settings (/install-resources <dir> [--force])\",\n\t},\n\t{\n\t\tname: \"config-backup\",\n\t\tdescription: \"Backup profiles and resource settings to a JSON file (/config-backup [file])\",\n\t},\n\t{\n\t\tname: \"config-restore\",\n\t\tdescription: \"Restore profiles and resource settings from a JSON file (/config-restore <file>)\",\n\t},\n\t{ name: \"quit\", description: `Quit ${APP_NAME}` },\n];\n"]}
|
|
@@ -2,6 +2,10 @@ import { APP_NAME } from "../config.js";
|
|
|
2
2
|
export const BUILTIN_SLASH_COMMANDS = [
|
|
3
3
|
{ name: "settings", description: "Open settings menu" },
|
|
4
4
|
{ name: "autonomy", description: "Autonomy mode, diagnostics, research, fitness (/autonomy status)" },
|
|
5
|
+
{
|
|
6
|
+
name: "models",
|
|
7
|
+
description: "Local model lifecycle: /models [list|add <ref-or-link>|remove <ref> confirm|stop]",
|
|
8
|
+
},
|
|
5
9
|
{
|
|
6
10
|
name: "fitness",
|
|
7
11
|
description: "Pick and probe a model for local/heavy-lifter roles, then assign it (/fitness [model] [trials])",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"slash-commands.js","sourceRoot":"","sources":["../../src/core/slash-commands.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAiBxC,MAAM,CAAC,MAAM,sBAAsB,GAAuC;IACzE,EAAE,IAAI,EAAE,UAAU,EAAE,WAAW,EAAE,oBAAoB,EAAE;IACvD,EAAE,IAAI,EAAE,UAAU,EAAE,WAAW,EAAE,kEAAkE,EAAE;IACrG;QACC,IAAI,EAAE,SAAS;QACf,WAAW,EAAE,iGAAiG;KAC9G;IACD,EAAE,IAAI,EAAE,SAAS,EAAE,WAAW,EAAE,4DAA4D,EAAE;IAC9F,EAAE,IAAI,EAAE,YAAY,EAAE,WAAW,EAAE,gEAAgE,EAAE;IACrG;QACC,IAAI,EAAE,eAAe;QACrB,WAAW,EAAE,6EAA6E;KAC1F;IACD,EAAE,IAAI,EAAE,OAAO,EAAE,WAAW,EAAE,kCAAkC,EAAE;IAClE,EAAE,IAAI,EAAE,UAAU,EAAE,WAAW,EAAE,2CAA2C,EAAE;IAC9E,EAAE,IAAI,EAAE,eAAe,EAAE,WAAW,EAAE,0CAA0C,EAAE;IAClF,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,8DAA8D,EAAE;IAC/F,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,+CAA+C,EAAE;IAChF,EAAE,IAAI,EAAE,OAAO,EAAE,WAAW,EAAE,uCAAuC,EAAE;IACvE,EAAE,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,sCAAsC,EAAE;IACrE,EAAE,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,0BAA0B,EAAE;IACzD,EAAE,IAAI,EAAE,SAAS,EAAE,WAAW,EAAE,6BAA6B,EAAE;IAC/D,EAAE,IAAI,EAAE,OAAO,EAAE,WAAW,EAAE,8CAA8C,EAAE;IAC9E,EAAE,IAAI,EAAE,WAAW,EAAE,WAAW,EAAE,wBAAwB,EAAE;IAC5D,EAAE,IAAI,EAAE,SAAS,EAAE,WAAW,EAAE,6BAA6B,EAAE;IAC/D,EAAE,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,8EAA8E,EAAE;IAC7G;QACC,IAAI,EAAE,OAAO;QACb,WAAW,EAAE,sFAAsF;KACnG;IACD,EAAE,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,yCAAyC,EAAE;IACxE,EAAE,IAAI,EAAE,OAAO,EAAE,WAAW,EAAE,sCAAsC,EAAE;IACtE,EAAE,IAAI,EAAE,OAAO,EAAE,WAAW,EAAE,mCAAmC,EAAE;IACnE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,gCAAgC,EAAE;IACjE,EAAE,IAAI,EAAE,KAAK,EAAE,WAAW,EAAE,kDAAkD,EAAE;IAChF,EAAE,IAAI,EAAE,SAAS,EAAE,WAAW,EAAE,sCAAsC,EAAE;IACxE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,gEAAgE,EAAE;IACjG,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,4BAA4B,EAAE;IAC7D,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,6DAA6D,EAAE;IAC9F,EAAE,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,QAAQ,QAAQ,EAAE,EAAE;IACjD;QACC,IAAI,EAAE,mBAAmB;QACzB,WAAW,EACV,qGAAqG;KACtG;IACD;QACC,IAAI,EAAE,eAAe;QACrB,WAAW,EAAE,8EAA8E;KAC3F;IACD;QACC,IAAI,EAAE,gBAAgB;QACtB,WAAW,EAAE,kFAAkF;KAC/F;IACD,EAAE,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,QAAQ,QAAQ,EAAE,EAAE;CACjD,CAAC","sourcesContent":["import { APP_NAME } from \"../config.ts\";\nimport type { SourceInfo } from \"./source-info.ts\";\n\nexport type SlashCommandSource = \"extension\" | \"prompt\" | \"skill\";\n\nexport interface SlashCommandInfo {\n\tname: string;\n\tdescription?: string;\n\tsource: SlashCommandSource;\n\tsourceInfo: SourceInfo;\n}\n\nexport interface BuiltinSlashCommand {\n\tname: string;\n\tdescription: string;\n}\n\nexport const BUILTIN_SLASH_COMMANDS: ReadonlyArray<BuiltinSlashCommand> = [\n\t{ name: \"settings\", description: \"Open settings menu\" },\n\t{ name: \"autonomy\", description: \"Autonomy mode, diagnostics, research, fitness (/autonomy status)\" },\n\t{\n\t\tname: \"fitness\",\n\t\tdescription: \"Pick and probe a model for local/heavy-lifter roles, then assign it (/fitness [model] [trials])\",\n\t},\n\t{ name: \"context\", description: \"Context composition dashboard: what rides on every request\" },\n\t{ name: \"auto-learn\", description: \"Show Auto Learn/reflection status or run now (/auto-learn run)\" },\n\t{\n\t\tname: \"goal-continue\",\n\t\tdescription: \"Continue the current goal loop explicitly (/goal-continue [turns] [stalls])\",\n\t},\n\t{ name: \"model\", description: \"Select model (opens selector UI)\" },\n\t{ name: \"profiles\", description: \"Select a runtime profile for this session\" },\n\t{ name: \"scoped-models\", description: \"Enable/disable models for Ctrl+P cycling\" },\n\t{ name: \"export\", description: \"Export session (HTML default, or specify path: .html/.jsonl)\" },\n\t{ name: \"import\", description: \"Import and resume a session from a JSONL file\" },\n\t{ name: \"share\", description: \"Share session as a secret GitHub gist\" },\n\t{ name: \"copy\", description: \"Copy last agent message to clipboard\" },\n\t{ name: \"name\", description: \"Set session display name\" },\n\t{ name: \"session\", description: \"Show session info and stats\" },\n\t{ name: \"usage\", description: \"Show tokens, cost, and optimization controls\" },\n\t{ name: \"changelog\", description: \"Show changelog entries\" },\n\t{ name: \"hotkeys\", description: \"Show all keyboard shortcuts\" },\n\t{ name: \"fork\", description: \"Create a new fork from a previous user message (optional name: /fork <name>)\" },\n\t{\n\t\tname: \"clone\",\n\t\tdescription: \"Duplicate the current session at the current position (optional name: /clone <name>)\",\n\t},\n\t{ name: \"tree\", description: \"Navigate session tree (switch branches)\" },\n\t{ name: \"trust\", description: \"Trust or untrust this project folder\" },\n\t{ name: \"login\", description: \"Configure provider authentication\" },\n\t{ name: \"logout\", description: \"Remove provider authentication\" },\n\t{ name: \"new\", description: \"Start a new session (optional name: /new <name>)\" },\n\t{ name: \"compact\", description: \"Manually compact the session context\" },\n\t{ name: \"curate\", description: \"Review/archive stale or overlapping reflection-promoted skills\" },\n\t{ name: \"resume\", description: \"Resume a different session\" },\n\t{ name: \"reload\", description: \"Reload keybindings, extensions, skills, prompts, and themes\" },\n\t{ name: \"exit\", description: `Quit ${APP_NAME}` },\n\t{\n\t\tname: \"install-resources\",\n\t\tdescription:\n\t\t\t\"Copy resources from a trusted directory to user local settings (/install-resources <dir> [--force])\",\n\t},\n\t{\n\t\tname: \"config-backup\",\n\t\tdescription: \"Backup profiles and resource settings to a JSON file (/config-backup [file])\",\n\t},\n\t{\n\t\tname: \"config-restore\",\n\t\tdescription: \"Restore profiles and resource settings from a JSON file (/config-restore <file>)\",\n\t},\n\t{ name: \"quit\", description: `Quit ${APP_NAME}` },\n];\n"]}
|
|
1
|
+
{"version":3,"file":"slash-commands.js","sourceRoot":"","sources":["../../src/core/slash-commands.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAiBxC,MAAM,CAAC,MAAM,sBAAsB,GAAuC;IACzE,EAAE,IAAI,EAAE,UAAU,EAAE,WAAW,EAAE,oBAAoB,EAAE;IACvD,EAAE,IAAI,EAAE,UAAU,EAAE,WAAW,EAAE,kEAAkE,EAAE;IACrG;QACC,IAAI,EAAE,QAAQ;QACd,WAAW,EAAE,mFAAmF;KAChG;IACD;QACC,IAAI,EAAE,SAAS;QACf,WAAW,EAAE,iGAAiG;KAC9G;IACD,EAAE,IAAI,EAAE,SAAS,EAAE,WAAW,EAAE,4DAA4D,EAAE;IAC9F,EAAE,IAAI,EAAE,YAAY,EAAE,WAAW,EAAE,gEAAgE,EAAE;IACrG;QACC,IAAI,EAAE,eAAe;QACrB,WAAW,EAAE,6EAA6E;KAC1F;IACD,EAAE,IAAI,EAAE,OAAO,EAAE,WAAW,EAAE,kCAAkC,EAAE;IAClE,EAAE,IAAI,EAAE,UAAU,EAAE,WAAW,EAAE,2CAA2C,EAAE;IAC9E,EAAE,IAAI,EAAE,eAAe,EAAE,WAAW,EAAE,0CAA0C,EAAE;IAClF,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,8DAA8D,EAAE;IAC/F,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,+CAA+C,EAAE;IAChF,EAAE,IAAI,EAAE,OAAO,EAAE,WAAW,EAAE,uCAAuC,EAAE;IACvE,EAAE,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,sCAAsC,EAAE;IACrE,EAAE,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,0BAA0B,EAAE;IACzD,EAAE,IAAI,EAAE,SAAS,EAAE,WAAW,EAAE,6BAA6B,EAAE;IAC/D,EAAE,IAAI,EAAE,OAAO,EAAE,WAAW,EAAE,8CAA8C,EAAE;IAC9E,EAAE,IAAI,EAAE,WAAW,EAAE,WAAW,EAAE,wBAAwB,EAAE;IAC5D,EAAE,IAAI,EAAE,SAAS,EAAE,WAAW,EAAE,6BAA6B,EAAE;IAC/D,EAAE,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,8EAA8E,EAAE;IAC7G;QACC,IAAI,EAAE,OAAO;QACb,WAAW,EAAE,sFAAsF;KACnG;IACD,EAAE,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,yCAAyC,EAAE;IACxE,EAAE,IAAI,EAAE,OAAO,EAAE,WAAW,EAAE,sCAAsC,EAAE;IACtE,EAAE,IAAI,EAAE,OAAO,EAAE,WAAW,EAAE,mCAAmC,EAAE;IACnE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,gCAAgC,EAAE;IACjE,EAAE,IAAI,EAAE,KAAK,EAAE,WAAW,EAAE,kDAAkD,EAAE;IAChF,EAAE,IAAI,EAAE,SAAS,EAAE,WAAW,EAAE,sCAAsC,EAAE;IACxE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,gEAAgE,EAAE;IACjG,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,4BAA4B,EAAE;IAC7D,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,6DAA6D,EAAE;IAC9F,EAAE,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,QAAQ,QAAQ,EAAE,EAAE;IACjD;QACC,IAAI,EAAE,mBAAmB;QACzB,WAAW,EACV,qGAAqG;KACtG;IACD;QACC,IAAI,EAAE,eAAe;QACrB,WAAW,EAAE,8EAA8E;KAC3F;IACD;QACC,IAAI,EAAE,gBAAgB;QACtB,WAAW,EAAE,kFAAkF;KAC/F;IACD,EAAE,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,QAAQ,QAAQ,EAAE,EAAE;CACjD,CAAC","sourcesContent":["import { APP_NAME } from \"../config.ts\";\nimport type { SourceInfo } from \"./source-info.ts\";\n\nexport type SlashCommandSource = \"extension\" | \"prompt\" | \"skill\";\n\nexport interface SlashCommandInfo {\n\tname: string;\n\tdescription?: string;\n\tsource: SlashCommandSource;\n\tsourceInfo: SourceInfo;\n}\n\nexport interface BuiltinSlashCommand {\n\tname: string;\n\tdescription: string;\n}\n\nexport const BUILTIN_SLASH_COMMANDS: ReadonlyArray<BuiltinSlashCommand> = [\n\t{ name: \"settings\", description: \"Open settings menu\" },\n\t{ name: \"autonomy\", description: \"Autonomy mode, diagnostics, research, fitness (/autonomy status)\" },\n\t{\n\t\tname: \"models\",\n\t\tdescription: \"Local model lifecycle: /models [list|add <ref-or-link>|remove <ref> confirm|stop]\",\n\t},\n\t{\n\t\tname: \"fitness\",\n\t\tdescription: \"Pick and probe a model for local/heavy-lifter roles, then assign it (/fitness [model] [trials])\",\n\t},\n\t{ name: \"context\", description: \"Context composition dashboard: what rides on every request\" },\n\t{ name: \"auto-learn\", description: \"Show Auto Learn/reflection status or run now (/auto-learn run)\" },\n\t{\n\t\tname: \"goal-continue\",\n\t\tdescription: \"Continue the current goal loop explicitly (/goal-continue [turns] [stalls])\",\n\t},\n\t{ name: \"model\", description: \"Select model (opens selector UI)\" },\n\t{ name: \"profiles\", description: \"Select a runtime profile for this session\" },\n\t{ name: \"scoped-models\", description: \"Enable/disable models for Ctrl+P cycling\" },\n\t{ name: \"export\", description: \"Export session (HTML default, or specify path: .html/.jsonl)\" },\n\t{ name: \"import\", description: \"Import and resume a session from a JSONL file\" },\n\t{ name: \"share\", description: \"Share session as a secret GitHub gist\" },\n\t{ name: \"copy\", description: \"Copy last agent message to clipboard\" },\n\t{ name: \"name\", description: \"Set session display name\" },\n\t{ name: \"session\", description: \"Show session info and stats\" },\n\t{ name: \"usage\", description: \"Show tokens, cost, and optimization controls\" },\n\t{ name: \"changelog\", description: \"Show changelog entries\" },\n\t{ name: \"hotkeys\", description: \"Show all keyboard shortcuts\" },\n\t{ name: \"fork\", description: \"Create a new fork from a previous user message (optional name: /fork <name>)\" },\n\t{\n\t\tname: \"clone\",\n\t\tdescription: \"Duplicate the current session at the current position (optional name: /clone <name>)\",\n\t},\n\t{ name: \"tree\", description: \"Navigate session tree (switch branches)\" },\n\t{ name: \"trust\", description: \"Trust or untrust this project folder\" },\n\t{ name: \"login\", description: \"Configure provider authentication\" },\n\t{ name: \"logout\", description: \"Remove provider authentication\" },\n\t{ name: \"new\", description: \"Start a new session (optional name: /new <name>)\" },\n\t{ name: \"compact\", description: \"Manually compact the session context\" },\n\t{ name: \"curate\", description: \"Review/archive stale or overlapping reflection-promoted skills\" },\n\t{ name: \"resume\", description: \"Resume a different session\" },\n\t{ name: \"reload\", description: \"Reload keybindings, extensions, skills, prompts, and themes\" },\n\t{ name: \"exit\", description: `Quit ${APP_NAME}` },\n\t{\n\t\tname: \"install-resources\",\n\t\tdescription:\n\t\t\t\"Copy resources from a trusted directory to user local settings (/install-resources <dir> [--force])\",\n\t},\n\t{\n\t\tname: \"config-backup\",\n\t\tdescription: \"Backup profiles and resource settings to a JSON file (/config-backup [file])\",\n\t},\n\t{\n\t\tname: \"config-restore\",\n\t\tdescription: \"Restore profiles and resource settings from a JSON file (/config-restore <file>)\",\n\t},\n\t{ name: \"quit\", description: `Quit ${APP_NAME}` },\n];\n"]}
|
|
@@ -470,6 +470,13 @@ export declare class InteractiveMode {
|
|
|
470
470
|
private formatAutoLearnStatus;
|
|
471
471
|
private formatAutonomyStatus;
|
|
472
472
|
private applyAutonomyMode;
|
|
473
|
+
private _localRuntime;
|
|
474
|
+
private get localRuntime();
|
|
475
|
+
private handleModelsCommand;
|
|
476
|
+
private ensureLocalServer;
|
|
477
|
+
private listLocalModels;
|
|
478
|
+
private addLocalModel;
|
|
479
|
+
private removeLocalModel;
|
|
473
480
|
/** /fitness with no args: pick a model from the configured registry, probe it, assign a role. */
|
|
474
481
|
private showFitnessModelSelector;
|
|
475
482
|
private runFitnessAndAssign;
|