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 +2 -2
- package/dist/index.d.ts +1 -2
- package/dist/index.js +1 -33
- package/package.json +1 -1
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
|
-
|
|
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
|
-
|
|
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,
|
|
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.
|
|
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
|
};
|