@henryqw/pi-task-models 1.0.0 → 1.0.2

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
@@ -38,7 +38,7 @@ Package also exports config and route-resolution helpers for consumers.
38
38
 
39
39
  ## Config
40
40
 
41
- `~/.pi/agent/config/pi-task-models.json`
41
+ Single shared JSON file at the exact package-owned path `~/.pi/agent/config/pi-task-models.json`. Consumers read it but never write it; only explicit `/task-models` actions save it.
42
42
 
43
43
  ```json
44
44
  {
@@ -68,24 +68,19 @@ Package also exports config and route-resolution helpers for consumers.
68
68
  }
69
69
  ```
70
70
 
71
- Each configured profile needs one primary model and thinking level. Fallback is optional. Model references use canonical `provider/model`; numbered `openai-codex-N` routes store as `openai-codex/model`.
71
+ | Field | Required | Possible values | Default |
72
+ | --- | --- | --- | --- |
73
+ | `profiles` | No | Object keyed by `fast`, `balanced`, `frontier`, `fav`; unknown profile names are rejected | `{}` (no profiles configured) |
74
+ | `profiles.<profile>.primary.model` | Yes within a configured profile's `primary` | Canonical `provider/model` reference without whitespace or NUL; available models come from Pi's model registry (or session-scoped models) at resolution time, not from this file | — |
75
+ | `profiles.<profile>.primary.thinkingLevel` | Yes within a configured profile's `primary` | `off`, `minimal`, `low`, `medium`, `high`, `xhigh`, `max`; the model must support the level when the route resolves | — |
76
+ | `profiles.<profile>.fallback` | No | When present, requires both `model` and `thinkingLevel` with the corresponding `primary.*` values; not allowed for `fav` | Omitted |
77
+ | `tasks` | No | Object mapping task IDs (`<package>/<task>`) to a profile name | Built-in defaults listed in the example above |
78
+ | `tasks.<taskId>` | Value required if the key is present | `fast`, `balanced`, `frontier`, `fav` | The built-in default for that task, if any |
72
79
 
73
- Profile thinking is authoritative for task routes.
74
-
75
- Reads are strict. Malformed or unknown values fail visibly and never rewrite the file. Only explicit `/task-models` actions write config.
76
-
77
- Consumers can call `resolveConfiguredTaskRoute(ctx, taskId)` for the first usable route or `resolveConfiguredTaskRoutes(ctx, taskId)` for primary and fallback routes. Both read strict shared config and fail with `/task-models` guidance when assignment, profile, or route is unavailable.
80
+ Model references use canonical `provider/model`; numbered Codex account aliases (`openai-codex-N`) resolve through Pi's registry and store canonically as `openai-codex/<model>`.
78
81
 
79
- ## Remove
82
+ Reads are strict. A missing file yields no profiles and the built-in default task assignments; malformed JSON, unknown keys, invalid task IDs, unknown profiles, or invalid profile or route values fail visibly with `/task-models` guidance and never rewrite the file.
80
83
 
81
- ```bash
82
- pi remove npm:@henryqw/pi-task-models
83
- ```
84
-
85
- ## Development
84
+ Profile thinking is authoritative for task routes.
86
85
 
87
- ```bash
88
- npm test --workspace @henryqw/pi-task-models
89
- npm run typecheck --workspace @henryqw/pi-task-models
90
- npm run pack:check --workspace @henryqw/pi-task-models
91
- ```
86
+ Consumers can call `resolveConfiguredTaskRoute(ctx, taskId)` for the first usable route or `resolveConfiguredTaskRoutes(ctx, taskId)` for primary and fallback routes. Both read strict shared config and fail with `/task-models` guidance when assignment, profile, or route is unavailable.
package/dist/index.d.ts CHANGED
@@ -45,7 +45,6 @@ export declare function modelReference(model: {
45
45
  }): string;
46
46
  export declare function dedupeAvailableModels(models: readonly AvailableModel[], preferredProvider?: string): AvailableModel[];
47
47
  export declare function resolveAvailableModel(models: readonly AvailableModel[], reference: string, preferredProvider?: string): AvailableModel | undefined;
48
- export declare function supportedThinkingLevels(model: AvailableModel): ThinkingLevel[];
49
48
  export declare function availableTaskModels(ctx: ExtensionContext): AvailableModel[];
50
49
  export declare function taskThinkingLevels(ctx: ExtensionContext, model: AvailableModel): ThinkingLevel[];
51
50
  export declare function resolveTaskModelRoute(ctx: ExtensionContext, route: TaskModelRoute, agentDir?: string, thinking?: ThinkingLevel): ResolvedTaskRoute | undefined;
package/dist/index.js CHANGED
@@ -14,7 +14,6 @@ export const DEFAULT_TASK_ASSIGNMENTS = {
14
14
  };
15
15
  const CODEX_ALIAS = /^openai-codex-(?:[2-9]|[1-9]\d+)$/;
16
16
  const CONFIG_FILE = "pi-task-models.json";
17
- const defaultTaskAssignments = () => ({ ...DEFAULT_TASK_ASSIGNMENTS });
18
17
  export const configPath = (agentDir = getAgentDir()) => join(agentDir, "config", CONFIG_FILE);
19
18
  function isCodexProvider(provider) {
20
19
  return provider === "openai-codex" || Boolean(provider && CODEX_ALIAS.test(provider));
@@ -72,7 +71,7 @@ function parseConfig(value) {
72
71
  if (!hasOnlyKeys(record, ["profiles", "tasks"]))
73
72
  throw new Error("Config contains unknown settings.");
74
73
  const profiles = {};
75
- const tasks = defaultTaskAssignments();
74
+ const tasks = { ...DEFAULT_TASK_ASSIGNMENTS };
76
75
  if (record.profiles !== undefined) {
77
76
  if (!record.profiles || typeof record.profiles !== "object" || Array.isArray(record.profiles)) {
78
77
  throw new Error("profiles must be an object.");
@@ -110,7 +109,7 @@ export function readTaskModelsConfig(agentDir = getAgentDir()) {
110
109
  }
111
110
  catch (error) {
112
111
  if (error && typeof error === "object" && "code" in error && error.code === "ENOENT") {
113
- return { profiles: {}, tasks: defaultTaskAssignments() };
112
+ return { profiles: {}, tasks: { ...DEFAULT_TASK_ASSIGNMENTS } };
114
113
  }
115
114
  throw error;
116
115
  }
@@ -176,16 +175,13 @@ export function resolveAvailableModel(models, reference, preferredProvider) {
176
175
  ?? models.find((model) => CODEX_ALIAS.test(model.provider) && model.id === id)
177
176
  ?? models.find((model) => model.provider === "openai-codex" && model.id === id);
178
177
  }
179
- export function supportedThinkingLevels(model) {
180
- return getSupportedThinkingLevels(model);
181
- }
182
178
  export function availableTaskModels(ctx) {
183
179
  const scopedModels = ctx.scopedModels ?? [];
184
180
  return dedupeAvailableModels((scopedModels.length ? scopedModels.map(({ model }) => model) : ctx.modelRegistry.getAvailable())
185
181
  .filter((model) => model.input.includes("text")), ctx.model?.provider);
186
182
  }
187
183
  export function taskThinkingLevels(ctx, model) {
188
- const supported = supportedThinkingLevels(model);
184
+ const supported = getSupportedThinkingLevels(model);
189
185
  const pinned = (ctx.scopedModels ?? []).find(({ model: scoped }) => scoped.provider === model.provider && scoped.id === model.id)?.thinkingLevel;
190
186
  if (!pinned)
191
187
  return supported;
@@ -1,4 +1 @@
1
- export {
2
- createTaskModelsExtension as default,
3
- createTaskModelsExtension as registerTaskModelsExtension,
4
- } from "@henryqw/pi-task-models";
1
+ export { createTaskModelsExtension as default } from "@henryqw/pi-task-models";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@henryqw/pi-task-models",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "description": "Shared task model profiles and routing for HenryQW Pi extensions.",
5
5
  "keywords": [
6
6
  "pi-package",