oc-agent-router 0.1.0 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -45,7 +45,7 @@ All configured models must already be available in OpenCode. Restart OpenCode af
45
45
 
46
46
  ## How It Works
47
47
 
48
- OpenCode's `task` tool does not accept a per-call model override. The plugin uses the documented `tool.execute.before` hook, calls `POST https://api.typesafe.ai/v1/systemone` with a Choice question whose only choices are your allowed models, then rewrites `subagent_type` to a hidden, model-bound copy of the requested subagent.
48
+ The plugin uses the documented `tool.execute.before` hook, calls `POST https://api.typesafe.ai/v1/systemone` with a Choice question whose only choices are your allowed models, then sets the task's `model` field. It leaves the task's original `subagent_type` and description unchanged.
49
49
 
50
50
  Task resumes (`task_id`) are deliberately not rerouted, so a resumed session keeps its original model. API failures never expand the configured model allowlist and use `fallbackModel` instead.
51
51
 
@@ -75,4 +75,4 @@ For example, a task that asks `general` to implement a parser sends the followin
75
75
  }
76
76
  ```
77
77
 
78
- The plugin routes the built-in `general` and `explore` agents plus subagents declared in `opencode.json` under `agent`. Markdown-only subagents are left unchanged because OpenCode's plugin hook does not expose their resolved definitions for safe cloning.
78
+ Every new task is eligible for routing, including configured and Markdown-defined subagents. Task resumes (`task_id`) retain their existing model.
package/dist/index.d.ts CHANGED
@@ -25,9 +25,8 @@ interface FetchResponse {
25
25
  }
26
26
  type Fetcher = (input: string, init: RequestInit) => Promise<FetchResponse>;
27
27
  declare function parseOptions(value: unknown): Required<RouterOptions>;
28
- declare function routedAgentName(agent: string, model: string): string;
29
28
  declare function selectModel(options: Required<RouterOptions>, args: TaskArgs, apiKey: string | undefined, fetcher?: Fetcher): Promise<string>;
30
29
 
31
30
  declare const plugin: Plugin;
32
31
 
33
- export { type RouterOptions, plugin as default, parseOptions, routedAgentName, selectModel };
32
+ export { type RouterOptions, plugin as default, parseOptions, selectModel };
package/dist/index.js CHANGED
@@ -17,9 +17,6 @@ function parseOptions(value) {
17
17
  fallbackModel
18
18
  };
19
19
  }
20
- function routedAgentName(agent, model) {
21
- return `oc-agent-router-${encode(agent)}-${encode(model)}`;
22
- }
23
20
  async function selectModel(options, args, apiKey, fetcher = fetch) {
24
21
  if (!apiKey) return options.fallbackModel;
25
22
  const controller = new AbortController();
@@ -55,9 +52,6 @@ async function selectModel(options, args, apiKey, fetcher = fetch) {
55
52
  clearTimeout(timeout);
56
53
  }
57
54
  }
58
- function encode(value) {
59
- return Array.from(value, (character) => character.codePointAt(0).toString(36)).join("-");
60
- }
61
55
  function isModel(value) {
62
56
  const separator = value.indexOf("/");
63
57
  return separator > 0 && separator < value.length - 1;
@@ -69,38 +63,13 @@ function isRecord(value) {
69
63
  // src/index.ts
70
64
  var plugin = async (_input, rawOptions) => {
71
65
  const options = parseOptions(rawOptions);
72
- const routeableAgents = /* @__PURE__ */ new Set();
73
66
  return {
74
- async config(config) {
75
- config.agent ??= {};
76
- const agents = config.agent;
77
- const sourceAgents = {
78
- general: agents.general ?? { mode: "subagent" },
79
- explore: agents.explore ?? { mode: "subagent" },
80
- ...Object.fromEntries(
81
- Object.entries(agents).filter(
82
- (entry) => Boolean(entry[1]) && entry[0] !== "build" && entry[0] !== "plan" && entry[1]?.mode !== "primary"
83
- )
84
- )
85
- };
86
- for (const [name, agent] of Object.entries(sourceAgents)) {
87
- if (name.startsWith("oc-agent-router-")) continue;
88
- routeableAgents.add(name);
89
- for (const model of options.models) {
90
- const routeName = routedAgentName(name, model);
91
- if (agents[routeName]) continue;
92
- agents[routeName] = { ...agent, model, mode: "subagent", hidden: true };
93
- }
94
- }
95
- },
96
67
  "tool.execute.before": async (input, output) => {
97
68
  if (input.tool !== "task") return;
98
69
  const args = output.args;
99
70
  if (typeof args.subagent_type !== "string" || typeof args.prompt !== "string" || args.task_id) return;
100
- if (args.subagent_type.startsWith("oc-agent-router-")) return;
101
- if (!routeableAgents.has(args.subagent_type)) return;
102
71
  const model = await selectModel(options, args, process.env[options.apiKeyEnv]);
103
- args.subagent_type = routedAgentName(args.subagent_type, model);
72
+ args.model = model;
104
73
  }
105
74
  };
106
75
  };
@@ -108,6 +77,5 @@ var index_default = plugin;
108
77
  export {
109
78
  index_default as default,
110
79
  parseOptions,
111
- routedAgentName,
112
80
  selectModel
113
81
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "oc-agent-router",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "Route OpenCode subagent tasks to configured models with Jev.",
5
5
  "type": "module",
6
6
  "license": "MIT",