@cotal-ai/connector-opencode 0.10.0 → 0.10.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.
@@ -1 +1 @@
1
- {"version":3,"file":"extension.d.ts","sourceRoot":"","sources":["../src/extension.ts"],"names":[],"mappings":"AAEA,OAAO,EAA2B,KAAK,SAAS,EAAoC,MAAM,gBAAgB,CAAC;AAa3G;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,iBAAiB,EAAE,SA4G/B,CAAC"}
1
+ {"version":3,"file":"extension.d.ts","sourceRoot":"","sources":["../src/extension.ts"],"names":[],"mappings":"AAGA,OAAO,EAA2B,KAAK,SAAS,EAAuE,MAAM,gBAAgB,CAAC;AAuF9I;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,iBAAiB,EAAE,SAyH/B,CAAC"}
package/dist/extension.js CHANGED
@@ -1,3 +1,4 @@
1
+ import { execFileSync } from "node:child_process";
1
2
  import { fileURLToPath } from "node:url";
2
3
  import { resolve } from "node:path";
3
4
  import { loadAgentFile, registry } from "@cotal-ai/core";
@@ -10,6 +11,79 @@ const PLUGIN_ENTRY = fileURLToPath(new URL("./plugin.bundle.js", import.meta.url
10
11
  /** The launcher shim (`dist/serve.js`): starts `opencode serve` with the plugin, then attaches a
11
12
  * foreground `opencode` TUI to the exact session the plugin drives (see serve.ts). */
12
13
  const SERVE_SHIM = fileURLToPath(new URL("./serve.js", import.meta.url));
14
+ function discoveryEnv() {
15
+ const env = { ...process.env };
16
+ delete env.OPENCODE_CONFIG_CONTENT;
17
+ for (const k of Object.keys(env))
18
+ if (k.startsWith("COTAL_"))
19
+ delete env[k];
20
+ return env;
21
+ }
22
+ function execErrorMessage(e) {
23
+ const err = e;
24
+ const stderr = Buffer.isBuffer(err.stderr) ? err.stderr.toString("utf8") : err.stderr;
25
+ return (stderr?.trim() || err.message).replace(/\s+/g, " ");
26
+ }
27
+ function readJsonBlock(lines, start) {
28
+ const parts = [];
29
+ for (let i = start; i < lines.length; i++) {
30
+ parts.push(lines[i]);
31
+ try {
32
+ return { value: JSON.parse(parts.join("\n")), end: i };
33
+ }
34
+ catch {
35
+ // Keep accumulating the pretty-printed JSON object.
36
+ }
37
+ }
38
+ throw new Error("opencode models output ended before a model metadata JSON block closed");
39
+ }
40
+ function parseModels(stdout) {
41
+ const lines = stdout.split(/\r?\n/);
42
+ const models = [];
43
+ for (let i = 0; i < lines.length; i++) {
44
+ const id = lines[i].trim();
45
+ if (!/^[^\s/]+\/\S+$/.test(id))
46
+ continue;
47
+ let raw;
48
+ if (lines[i + 1]?.trim().startsWith("{")) {
49
+ const block = readJsonBlock(lines, i + 1);
50
+ i = block.end;
51
+ if (block.value && typeof block.value === "object" && !Array.isArray(block.value))
52
+ raw = block.value;
53
+ }
54
+ const variantsRaw = raw?.variants;
55
+ const variants = variantsRaw && typeof variantsRaw === "object" && !Array.isArray(variantsRaw)
56
+ ? Object.entries(variantsRaw)
57
+ .filter(([, v]) => !(v && typeof v === "object" && !Array.isArray(v) && v.disabled === true))
58
+ .map(([name, v]) => ({ name, ...(v && typeof v === "object" && !Array.isArray(v) ? { options: v } : {}) }))
59
+ : undefined;
60
+ const provider = typeof raw?.providerID === "string" ? raw.providerID : id.split("/", 1)[0];
61
+ models.push({
62
+ id,
63
+ provider,
64
+ ...(typeof raw?.name === "string" ? { name: raw.name } : {}),
65
+ ...(variants?.length ? { variants } : {}),
66
+ });
67
+ }
68
+ return models;
69
+ }
70
+ function listOpenCodeModels(opts = {}) {
71
+ const args = ["models", "--pure", "--verbose"];
72
+ if (opts.refresh)
73
+ args.push("--refresh");
74
+ try {
75
+ const stdout = execFileSync("opencode", args, {
76
+ encoding: "utf8",
77
+ env: discoveryEnv(),
78
+ stdio: ["ignore", "pipe", "pipe"],
79
+ maxBuffer: 16 * 1024 * 1024,
80
+ });
81
+ return { source: "opencode models --pure --verbose", models: parseModels(stdout) };
82
+ }
83
+ catch (e) {
84
+ throw new Error(`opencode models failed: ${execErrorMessage(e)}`);
85
+ }
86
+ }
13
87
  /**
14
88
  * The OpenCode connector: launches a watchable `opencode` TUI bound to the agent's session, using
15
89
  * OpenCode's client/server split (see serve.ts). The Cotal mesh bridge runs as an in-process plugin
@@ -29,6 +103,8 @@ export const opencodeConnector = {
29
103
  name: "opencode",
30
104
  transcriptChannel, // the shared `tr-<name>` convention (connector-core), exposed via the contract
31
105
  requires: ["opencode"],
106
+ supportsModelVariant: true,
107
+ listModels: listOpenCodeModels,
32
108
  buildLaunch(opts) {
33
109
  // Resuming an existing session isn't wired for opencode: the connector runs `opencode serve` +
34
110
  // a plugin that CREATES its own session then attaches a TUI, so a fork must plumb into
@@ -90,23 +166,34 @@ export const opencodeConnector = {
90
166
  },
91
167
  },
92
168
  };
93
- // An agent file carries identity (read in-session via COTAL_AGENT_FILE) plus persona + model.
94
- // The model is a config default (the session — and the attached TUI — use it); the persona is
169
+ // An agent file carries identity (read in-session via COTAL_AGENT_FILE) plus persona + model/variant.
170
+ // The model/variant are config defaults (the session — and the attached TUI — use them); the persona is
95
171
  // applied in-session by the plugin (opencode has no `--append-system-prompt`).
96
172
  let model = opts.model;
173
+ let variant = opts.variant;
97
174
  if (opts.configPath) {
98
175
  const path = resolve(opts.configPath);
99
176
  env.COTAL_AGENT_FILE = path; // plugin reads persona from it
100
177
  const def = loadAgentFile(path);
101
178
  model ??= def.model;
179
+ variant ??= def.variant;
102
180
  }
103
- // The `--model` flag wins over the agent file, and applies even with no agent file. Pin it to a
104
- // dedicated primary agent made the default, so an operator's own `default_agent` in
105
- // ~/.config/opencode (with its own model) can't override the model a Cotal spawn asks for — the
106
- // session the plugin drives runs the persona's model, not the operator's default agent's.
181
+ // The `--model` / `--variant` flags win over the agent file, and apply even with no agent file.
182
+ // Pin them to a dedicated primary agent made the default, so an operator's own `default_agent` in
183
+ // ~/.config/opencode (with its own model) can't override what a Cotal spawn asks for — the session
184
+ // the plugin drives runs the persona's selectors, not the operator's default agent's.
185
+ const cotalAgent = { mode: "primary" };
107
186
  if (model) {
108
187
  config.model = model;
109
- config.agent = { cotal: { mode: "primary", model } };
188
+ env.COTAL_MODEL = model;
189
+ cotalAgent.model = model;
190
+ }
191
+ if (variant) {
192
+ env.COTAL_VARIANT = variant;
193
+ cotalAgent.variant = variant;
194
+ }
195
+ if (model || variant) {
196
+ config.agent = { cotal: cotalAgent };
110
197
  config.default_agent = "cotal";
111
198
  }
112
199
  env.OPENCODE_CONFIG_CONTENT = JSON.stringify(config);
@@ -1 +1 @@
1
- {"version":3,"file":"extension.js","sourceRoot":"","sources":["../src/extension.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"extension.js","sourceRoot":"","sources":["../src/extension.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAuF,MAAM,gBAAgB,CAAC;AAC9I,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,eAAe,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAEtH;;;oCAGoC;AACpC,MAAM,YAAY,GAAG,aAAa,CAAC,IAAI,GAAG,CAAC,oBAAoB,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAEnF;uFACuF;AACvF,MAAM,UAAU,GAAG,aAAa,CAAC,IAAI,GAAG,CAAC,YAAY,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAEzE,SAAS,YAAY;IACnB,MAAM,GAAG,GAAG,EAAE,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;IAC/B,OAAO,GAAG,CAAC,uBAAuB,CAAC;IACnC,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC;QAAE,IAAI,CAAC,CAAC,UAAU,CAAC,QAAQ,CAAC;YAAE,OAAO,GAAG,CAAC,CAAC,CAAC,CAAC;IAC5E,OAAO,GAAG,CAAC;AACb,CAAC;AAED,SAAS,gBAAgB,CAAC,CAAU;IAClC,MAAM,GAAG,GAAG,CAAyC,CAAC;IACtD,MAAM,MAAM,GAAG,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC;IACtF,OAAO,CAAC,MAAM,EAAE,IAAI,EAAE,IAAI,GAAG,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;AAC9D,CAAC;AAED,SAAS,aAAa,CAAC,KAAe,EAAE,KAAa;IACnD,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,KAAK,IAAI,CAAC,GAAG,KAAK,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAC1C,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;QACrB,IAAI,CAAC;YACH,OAAO,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC;QACzD,CAAC;QAAC,MAAM,CAAC;YACP,oDAAoD;QACtD,CAAC;IACH,CAAC;IACD,MAAM,IAAI,KAAK,CAAC,wEAAwE,CAAC,CAAC;AAC5F,CAAC;AAED,SAAS,WAAW,CAAC,MAAc;IACjC,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IACpC,MAAM,MAAM,GAAgB,EAAE,CAAC;IAC/B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACtC,MAAM,EAAE,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QAC3B,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,EAAE,CAAC;YAAE,SAAS;QAEzC,IAAI,GAAwC,CAAC;QAC7C,IAAI,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;YACzC,MAAM,KAAK,GAAG,aAAa,CAAC,KAAK,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;YAC1C,CAAC,GAAG,KAAK,CAAC,GAAG,CAAC;YACd,IAAI,KAAK,CAAC,KAAK,IAAI,OAAO,KAAK,CAAC,KAAK,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC;gBAAE,GAAG,GAAG,KAAK,CAAC,KAAgC,CAAC;QAClI,CAAC;QAED,MAAM,WAAW,GAAG,GAAG,EAAE,QAAQ,CAAC;QAClC,MAAM,QAAQ,GAAG,WAAW,IAAI,OAAO,WAAW,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,WAAW,CAAC;YAC5F,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,WAAsC,CAAC;iBACrD,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,IAAK,CAA4B,CAAC,QAAQ,KAAK,IAAI,CAAC,CAAC;iBACxH,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,GAAG,CAAC,CAAC,IAAI,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAA4B,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;YACxI,CAAC,CAAC,SAAS,CAAC;QAEd,MAAM,QAAQ,GAAG,OAAO,GAAG,EAAE,UAAU,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAC5F,MAAM,CAAC,IAAI,CAAC;YACV,EAAE;YACF,QAAQ;YACR,GAAG,CAAC,OAAO,GAAG,EAAE,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC5D,GAAG,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SAC1C,CAAC,CAAC;IACL,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,SAAS,kBAAkB,CAAC,OAA8B,EAAE;IAC1D,MAAM,IAAI,GAAG,CAAC,QAAQ,EAAE,QAAQ,EAAE,WAAW,CAAC,CAAC;IAC/C,IAAI,IAAI,CAAC,OAAO;QAAE,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IACzC,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,YAAY,CAAC,UAAU,EAAE,IAAI,EAAE;YAC5C,QAAQ,EAAE,MAAM;YAChB,GAAG,EAAE,YAAY,EAAE;YACnB,KAAK,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC;YACjC,SAAS,EAAE,EAAE,GAAG,IAAI,GAAG,IAAI;SAC5B,CAAC,CAAC;QACH,OAAO,EAAE,MAAM,EAAE,kCAAkC,EAAE,MAAM,EAAE,WAAW,CAAC,MAAM,CAAC,EAAE,CAAC;IACrF,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,MAAM,IAAI,KAAK,CAAC,2BAA2B,gBAAgB,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IACpE,CAAC;AACH,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAc;IAC1C,IAAI,EAAE,WAAW;IACjB,IAAI,EAAE,UAAU;IAChB,iBAAiB,EAAE,+EAA+E;IAClG,QAAQ,EAAE,CAAC,UAAU,CAAC;IACtB,oBAAoB,EAAE,IAAI;IAC1B,UAAU,EAAE,kBAAkB;IAC9B,WAAW,CAAC,IAAgB;QAC1B,+FAA+F;QAC/F,uFAAuF;QACvF,0FAA0F;QAC1F,gEAAgE;QAChE,IAAI,IAAI,CAAC,MAAM;YACb,MAAM,IAAI,KAAK,CACb,0FAA0F;gBACxF,gFAAgF,CACnF,CAAC;QACJ,6FAA6F;QAC7F,+FAA+F;QAC/F,2FAA2F;QAC3F,wFAAwF;QACxF,IAAI,IAAI,CAAC,UAAU,IAAI,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,MAAM,GAAG,CAAC;YAC5D,MAAM,IAAI,KAAK,CACb,wFAAwF;gBACtF,wFAAwF;gBACxF,yFAAyF;gBACzF,wBAAwB,CAC3B,CAAC;QACJ,0FAA0F;QAC1F,8FAA8F;QAC9F,sFAAsF;QACtF,+FAA+F;QAC/F,gDAAgD;QAChD,MAAM,GAAG,GAA2B;YAClC,GAAG,SAAS,CAAC,EAAE,YAAY,EAAE,mBAAmB,EAAE,CAAC;YACnD,GAAG,MAAM,CAAC,IAAI,CAAC;YACf,WAAW,EAAE,IAAI,CAAC,KAAK;YACvB,UAAU,EAAE,IAAI,CAAC,IAAI;SACtB,CAAC;QACF,IAAI,IAAI,CAAC,IAAI;YAAE,GAAG,CAAC,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC;QAC1C,IAAI,IAAI,CAAC,EAAE;YAAE,GAAG,CAAC,QAAQ,GAAG,IAAI,CAAC,EAAE,CAAC;QACpC,IAAI,IAAI,CAAC,KAAK;YAAE,GAAG,CAAC,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC;QAC7C,IAAI,IAAI,CAAC,OAAO;YAAE,GAAG,CAAC,aAAa,GAAG,IAAI,CAAC,OAAO,CAAC;QACnD,IAAI,IAAI,CAAC,UAAU,KAAK,IAAI;YAAE,GAAG,CAAC,gBAAgB,GAAG,GAAG,CAAC,CAAC,2DAA2D;QACrH,uFAAuF;QACvF,6FAA6F;QAC7F,8FAA8F;QAC9F,4FAA4F;QAC5F,uEAAuE;QACvE,GAAG,CAAC,mBAAmB,GAAG,IAAI,CAAC,aAAa,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;QAE9D,MAAM,MAAM,GAA4B;YACtC,OAAO,EAAE,iCAAiC;YAC1C,UAAU,EAAE,OAAO;YACnB,MAAM,EAAE,CAAC,YAAY,CAAC;YACtB,qFAAqF;YACrF,sFAAsF;YACtF,yFAAyF;YACzF,uFAAuF;YACvF,0FAA0F;YAC1F,yFAAyF;YACzF,OAAO,EAAE;gBACP,SAAS,EAAE;oBACT,WAAW,EAAE,4EAA4E;oBACzF,QAAQ,EACN,qKAAqK;iBACxK;aACF;SACF,CAAC;QAEF,sGAAsG;QACtG,wGAAwG;QACxG,+EAA+E;QAC/E,IAAI,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC;QACvB,IAAI,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC;QAC3B,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;YACpB,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;YACtC,GAAG,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAAC,+BAA+B;YAC5D,MAAM,GAAG,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC;YAChC,KAAK,KAAK,GAAG,CAAC,KAAK,CAAC;YACpB,OAAO,KAAK,GAAG,CAAC,OAAO,CAAC;QAC1B,CAAC;QACD,gGAAgG;QAChG,kGAAkG;QAClG,mGAAmG;QACnG,sFAAsF;QACtF,MAAM,UAAU,GAA4B,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC;QAChE,IAAI,KAAK,EAAE,CAAC;YACV,MAAM,CAAC,KAAK,GAAG,KAAK,CAAC;YACrB,GAAG,CAAC,WAAW,GAAG,KAAK,CAAC;YACxB,UAAU,CAAC,KAAK,GAAG,KAAK,CAAC;QAC3B,CAAC;QACD,IAAI,OAAO,EAAE,CAAC;YACZ,GAAG,CAAC,aAAa,GAAG,OAAO,CAAC;YAC5B,UAAU,CAAC,OAAO,GAAG,OAAO,CAAC;QAC/B,CAAC;QACD,IAAI,KAAK,IAAI,OAAO,EAAE,CAAC;YACrB,MAAM,CAAC,KAAK,GAAG,EAAE,KAAK,EAAE,UAAU,EAAE,CAAC;YACrC,MAAM,CAAC,aAAa,GAAG,OAAO,CAAC;QACjC,CAAC;QAED,GAAG,CAAC,uBAAuB,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;QAErD,gGAAgG;QAChG,4FAA4F;QAC5F,kGAAkG;QAClG,+FAA+F;QAC/F,gGAAgG;QAChG,2FAA2F;QAC3F,MAAM,OAAO,GAAG,eAAe,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;QACvD,GAAG,CAAC,oBAAoB,GAAG,OAAO,CAAC,IAAI,CAAC;QACxC,GAAG,CAAC,mBAAmB,GAAG,OAAO,CAAC,KAAK,CAAC;QAExC,oFAAoF;QACpF,OAAO;YACL,OAAO,EAAE,OAAO,CAAC,QAAQ;YACzB,IAAI,EAAE,CAAC,UAAU,CAAC;YAClB,GAAG;YACH,OAAO;SACR,CAAC;IACJ,CAAC;CACF,CAAC;AAEF,QAAQ,CAAC,QAAQ,CAAC,iBAAiB,CAAC,CAAC"}
@@ -17019,7 +17019,7 @@ function loadAgentFile(path) {
17019
17019
  if (!channelInAllow(effAllow, ch))
17020
17020
  throw new Error(`agent file ${path}: ${field} channel "${ch}" is not within your read ACL / allowSubscribe [${effAllow.join(", ")}]`);
17021
17021
  }
17022
- const known = /* @__PURE__ */ new Set(["name", "role", "kind", "description", "tags", "subscribe", "allowSubscribe", "allowPublish", "quiet", "muted", "model", "capabilities", "owner"]);
17022
+ const known = /* @__PURE__ */ new Set(["name", "role", "kind", "description", "tags", "subscribe", "allowSubscribe", "allowPublish", "quiet", "muted", "model", "variant", "capabilities", "owner"]);
17023
17023
  const meta3 = {};
17024
17024
  for (const [k, v] of Object.entries(fm))
17025
17025
  if (!known.has(k) && typeof v === "string")
@@ -17036,6 +17036,7 @@ function loadAgentFile(path) {
17036
17036
  quiet,
17037
17037
  muted,
17038
17038
  model: str("model"),
17039
+ variant: str("variant"),
17039
17040
  capabilities: list("capabilities"),
17040
17041
  owner: str("owner"),
17041
17042
  meta: Object.keys(meta3).length ? meta3 : void 0,
@@ -19357,6 +19358,7 @@ function configFromEnv(env = process.env) {
19357
19358
  meta: def?.meta,
19358
19359
  capabilities: splitList(env.COTAL_CAPABILITIES).length ? splitList(env.COTAL_CAPABILITIES) : def?.capabilities,
19359
19360
  model: env.COTAL_MODEL?.trim() || def?.model || void 0,
19361
+ variant: env.COTAL_VARIANT?.trim() || def?.variant || void 0,
19360
19362
  servers: env.COTAL_SERVERS?.trim() || link?.servers || DEFAULT_SERVER,
19361
19363
  subscribe: resolvedSubscribe,
19362
19364
  allowSubscribe: resolvedAllowSub,
@@ -19382,6 +19384,8 @@ function buildMeta(config2) {
19382
19384
  const meta3 = { ...config2.meta ?? {} };
19383
19385
  if (config2.model)
19384
19386
  meta3.model = config2.model;
19387
+ if (config2.variant)
19388
+ meta3.variant = config2.variant;
19385
19389
  if (config2.connector)
19386
19390
  meta3.connector = config2.connector;
19387
19391
  return Object.keys(meta3).length ? meta3 : void 0;
@@ -19744,8 +19748,8 @@ var MeshAgent = class extends EventEmitter2 {
19744
19748
  * not the 5s op default.
19745
19749
  * How it lands — a detached PTY, a tmux window, a cmux tab — is the manager's
19746
19750
  * runtime; from here it just joins the mesh as a lateral peer. `opts.agent` picks
19747
- * the harness (default the manager's `COTAL_DEFAULT_AGENT`, else `cotal`/Claude), `opts.model` overrides the
19748
- * persona file's `model:`, and `opts.cwd` roots the new peer at a different folder/repo
19751
+ * the harness (default the manager's `COTAL_DEFAULT_AGENT`, else `cotal`/Claude), `opts.model` /
19752
+ * `opts.variant` override the persona file's model selectors, and `opts.cwd` roots the new peer at a different folder/repo
19749
19753
  * than the manager's workspace — the same knobs the operator's `cotal spawn --detach` carries, so
19750
19754
  * the agent and operator spawn doors share one control-op contract. (Session `resume` is
19751
19755
  * intentionally NOT forwarded here: forking a host-local `~/.claude` transcript is an
@@ -19754,7 +19758,7 @@ var MeshAgent = class extends EventEmitter2 {
19754
19758
  this.assertConnected();
19755
19759
  return this.ep.requestControl(CONTROL_PRIVILEGED, {
19756
19760
  op: "start",
19757
- args: { name, role, agent: opts?.agent, model: opts?.model, cwd: opts?.cwd }
19761
+ args: { name, role, agent: opts?.agent, model: opts?.model, variant: opts?.variant, cwd: opts?.cwd }
19758
19762
  }, SPAWN_TIMEOUT_MS);
19759
19763
  }
19760
19764
  /** Ask the manager to tear a teammate down (its `stop` op). Graceful by default —
@@ -34835,6 +34839,7 @@ ${info}${caught}`);
34835
34839
  role: external_exports.string().optional().describe("Optional role for the new peer (e.g. worker, reviewer); overrides the persona file's role."),
34836
34840
  agent: external_exports.string().optional().describe("Optional harness the new peer runs on \u2014 the agent/connector type (claude, opencode, hermes), NOT the persona to spawn (that's `name`). Defaults to the manager's COTAL_DEFAULT_AGENT, else Claude."),
34837
34841
  model: external_exports.string().optional().describe("Optional model override (e.g. opus, sonnet) \u2014 wins over the persona file's model:."),
34842
+ variant: external_exports.string().optional().describe("Optional model variant override (connector-defined; for OpenCode, a model variant such as high/max/low)."),
34838
34843
  cwd: external_exports.string().optional().describe("Optional working directory to root the new peer at (e.g. a different repo). A relative path resolves against the manager's workspace; omitted \u2192 it shares the manager's workspace.")
34839
34844
  // NOTE: session `resume` is deliberately NOT exposed here. Forking a host-local `~/.claude`
34840
34845
  // transcript is an operator-local intent; letting a spawn-capable mesh PEER name a host
@@ -34842,9 +34847,9 @@ ${info}${caught}`);
34842
34847
  // boundary. Resume lives only on the operator CLI (`cotal spawn --resume`, foreground or
34843
34848
  // --detach); a peer-facing, capability-gated resume is deferred (see #159).
34844
34849
  },
34845
- async run(agent, _config, { name, role, agent: agentType, model, cwd }) {
34850
+ async run(agent, _config, { name, role, agent: agentType, model, variant, cwd }) {
34846
34851
  try {
34847
- const reply = await agent.spawn(name, role, { agent: agentType, model, cwd });
34852
+ const reply = await agent.spawn(name, role, { agent: agentType, model, variant, cwd });
34848
34853
  if (!reply.ok)
34849
34854
  return err(`Couldn't spawn ${name}: ${reply.error ?? "manager refused"}`);
34850
34855
  const d = reply.data;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@cotal-ai/connector-opencode",
3
3
  "description": "Cotal connector for OpenCode: a native in-process plugin that joins a session to the mesh.",
4
- "version": "0.10.0",
4
+ "version": "0.10.1",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
7
7
  "type": "git",
@@ -18,7 +18,7 @@
18
18
  }
19
19
  },
20
20
  "dependencies": {
21
- "@cotal-ai/connector-core": "0.10.0"
21
+ "@cotal-ai/connector-core": "0.10.1"
22
22
  },
23
23
  "peerDependencies": {
24
24
  "@cotal-ai/core": ">=0.1.0",
@@ -30,7 +30,7 @@
30
30
  "@opencode-ai/sdk": "^1.16.2",
31
31
  "esbuild": "^0.28.0",
32
32
  "tsx": "^4.22.4",
33
- "@cotal-ai/core": "0.10.0"
33
+ "@cotal-ai/core": "0.10.1"
34
34
  },
35
35
  "files": [
36
36
  "dist"