@cotal-ai/connector-opencode 0.1.1 → 0.3.0

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.
@@ -3,13 +3,13 @@ import { type Connector } from "@cotal-ai/core";
3
3
  * The OpenCode connector: launches a watchable `opencode` TUI bound to the agent's session, using
4
4
  * OpenCode's client/server split (see serve.ts). The Cotal mesh bridge runs as an in-process plugin
5
5
  * inside a headless `opencode serve`: it holds the {@link MeshAgent}, registers the cotal_* tools
6
- * natively (from the shared specs, at parity with Claude/Codex), reports presence off the event bus,
6
+ * natively (from the shared specs, at parity with Claude Code), reports presence off the event bus,
7
7
  * and owns ONE session it drives — injecting each incoming peer batch as a turn via the prompt API
8
8
  * (`session.promptAsync`, server-side, so it can't race the TUI input box). The shim then attaches a
9
9
  * foreground TUI to that session, so a human watching sees the agent work and can type into it.
10
10
  *
11
11
  * Config rides in `OPENCODE_CONFIG_CONTENT` (inline JSON, the highest merge layer), so the
12
- * operator's `~/.config/opencode` is never written — the Codex `-c` trick in JSON.
12
+ * operator's `~/.config/opencode` is never written.
13
13
  * `permission:"allow"` keeps a supervised agent from stalling on a tool approval the human may not
14
14
  * be at the keyboard to grant. Self-registers on import; the manager resolves it by type "opencode".
15
15
  */
@@ -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;AAY3G;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,iBAAiB,EAAE,SAqC/B,CAAC"}
1
+ {"version":3,"file":"extension.d.ts","sourceRoot":"","sources":["../src/extension.ts"],"names":[],"mappings":"AAEA,OAAO,EAA2B,KAAK,SAAS,EAAoC,MAAM,gBAAgB,CAAC;AAY3G;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,iBAAiB,EAAE,SAuC/B,CAAC"}
package/dist/extension.js CHANGED
@@ -13,13 +13,13 @@ const SERVE_SHIM = fileURLToPath(new URL("./serve.js", import.meta.url));
13
13
  * The OpenCode connector: launches a watchable `opencode` TUI bound to the agent's session, using
14
14
  * OpenCode's client/server split (see serve.ts). The Cotal mesh bridge runs as an in-process plugin
15
15
  * inside a headless `opencode serve`: it holds the {@link MeshAgent}, registers the cotal_* tools
16
- * natively (from the shared specs, at parity with Claude/Codex), reports presence off the event bus,
16
+ * natively (from the shared specs, at parity with Claude Code), reports presence off the event bus,
17
17
  * and owns ONE session it drives — injecting each incoming peer batch as a turn via the prompt API
18
18
  * (`session.promptAsync`, server-side, so it can't race the TUI input box). The shim then attaches a
19
19
  * foreground TUI to that session, so a human watching sees the agent work and can type into it.
20
20
  *
21
21
  * Config rides in `OPENCODE_CONFIG_CONTENT` (inline JSON, the highest merge layer), so the
22
- * operator's `~/.config/opencode` is never written — the Codex `-c` trick in JSON.
22
+ * operator's `~/.config/opencode` is never written.
23
23
  * `permission:"allow"` keeps a supervised agent from stalling on a tool approval the human may not
24
24
  * be at the keyboard to grant. Self-registers on import; the manager resolves it by type "opencode".
25
25
  */
@@ -28,7 +28,7 @@ export const opencodeConnector = {
28
28
  name: "opencode",
29
29
  buildLaunch(opts) {
30
30
  // Identity rides the process env: the plugin runs in the opencode process and inherits it
31
- // (unlike the Codex/Claude MCP servers, which get none of the parent env).
31
+ // (unlike the Claude Code MCP server, which gets none of the parent env).
32
32
  const env = { COTAL_SPACE: opts.space, COTAL_NAME: opts.name };
33
33
  if (opts.role)
34
34
  env.COTAL_ROLE = opts.role;
@@ -52,6 +52,9 @@ export const opencodeConnector = {
52
52
  const def = loadAgentFile(path);
53
53
  if (def.model)
54
54
  config.model = def.model;
55
+ const face = def.meta?.face;
56
+ if (face)
57
+ env.COTAL_FACE_PERSONA = face; // shim swaps the TUI for the face viewer
55
58
  }
56
59
  env.OPENCODE_CONFIG_CONTENT = JSON.stringify(config);
57
60
  // Run the shim (node dist/serve.js): `opencode serve` + an attached foreground TUI.
@@ -1 +1 @@
1
- {"version":3,"file":"extension.js","sourceRoot":"","sources":["../src/extension.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAoD,MAAM,gBAAgB,CAAC;AAE3G;;;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;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAc;IAC1C,IAAI,EAAE,WAAW;IACjB,IAAI,EAAE,UAAU;IAChB,WAAW,CAAC,IAAgB;QAC1B,0FAA0F;QAC1F,2EAA2E;QAC3E,MAAM,GAAG,GAA2B,EAAE,WAAW,EAAE,IAAI,CAAC,KAAK,EAAE,UAAU,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC;QACvF,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;QAEnD,MAAM,MAAM,GAA4B;YACtC,OAAO,EAAE,iCAAiC;YAC1C,UAAU,EAAE,OAAO;YACnB,MAAM,EAAE,CAAC,YAAY,CAAC;SACvB,CAAC;QAEF,8FAA8F;QAC9F,8FAA8F;QAC9F,+EAA+E;QAC/E,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,IAAI,GAAG,CAAC,KAAK;gBAAE,MAAM,CAAC,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC;QAC1C,CAAC;QAED,GAAG,CAAC,uBAAuB,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;QAErD,oFAAoF;QACpF,OAAO;YACL,OAAO,EAAE,OAAO,CAAC,QAAQ;YACzB,IAAI,EAAE,CAAC,UAAU,CAAC;YAClB,GAAG;SACJ,CAAC;IACJ,CAAC;CACF,CAAC;AAEF,QAAQ,CAAC,QAAQ,CAAC,iBAAiB,CAAC,CAAC"}
1
+ {"version":3,"file":"extension.js","sourceRoot":"","sources":["../src/extension.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAoD,MAAM,gBAAgB,CAAC;AAE3G;;;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;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAc;IAC1C,IAAI,EAAE,WAAW;IACjB,IAAI,EAAE,UAAU;IAChB,WAAW,CAAC,IAAgB;QAC1B,0FAA0F;QAC1F,0EAA0E;QAC1E,MAAM,GAAG,GAA2B,EAAE,WAAW,EAAE,IAAI,CAAC,KAAK,EAAE,UAAU,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC;QACvF,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;QAEnD,MAAM,MAAM,GAA4B;YACtC,OAAO,EAAE,iCAAiC;YAC1C,UAAU,EAAE,OAAO;YACnB,MAAM,EAAE,CAAC,YAAY,CAAC;SACvB,CAAC;QAEF,8FAA8F;QAC9F,8FAA8F;QAC9F,+EAA+E;QAC/E,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,IAAI,GAAG,CAAC,KAAK;gBAAE,MAAM,CAAC,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC;YACxC,MAAM,IAAI,GAAG,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC;YAC5B,IAAI,IAAI;gBAAE,GAAG,CAAC,kBAAkB,GAAG,IAAI,CAAC,CAAC,yCAAyC;QACpF,CAAC;QAED,GAAG,CAAC,uBAAuB,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;QAErD,oFAAoF;QACpF,OAAO;YACL,OAAO,EAAE,OAAO,CAAC,QAAQ;YACzB,IAAI,EAAE,CAAC,UAAU,CAAC;YAClB,GAAG;SACJ,CAAC;IACJ,CAAC;CACF,CAAC;AAEF,QAAQ,CAAC,QAAQ,CAAC,iBAAiB,CAAC,CAAC"}
@@ -6430,7 +6430,7 @@ var require_authenticator = __commonJS({
6430
6430
  exports.tokenAuthenticator = tokenAuthenticator;
6431
6431
  exports.nkeyAuthenticator = nkeyAuthenticator;
6432
6432
  exports.jwtAuthenticator = jwtAuthenticator;
6433
- exports.credsAuthenticator = credsAuthenticator4;
6433
+ exports.credsAuthenticator = credsAuthenticator5;
6434
6434
  var nkeys_1 = require_nkeys2();
6435
6435
  var encoders_1 = require_encoders();
6436
6436
  function multiAuthenticator(authenticators) {
@@ -6480,7 +6480,7 @@ var require_authenticator = __commonJS({
6480
6480
  return { jwt: jwt2, nkey, sig };
6481
6481
  };
6482
6482
  }
6483
- function credsAuthenticator4(creds) {
6483
+ function credsAuthenticator5(creds) {
6484
6484
  const fn = typeof creds !== "function" ? () => creds : creds;
6485
6485
  const parse3 = () => {
6486
6486
  const CREDS = /\s*(?:(?:[-]{3,}[^\n]*[-]{3,}\n)(.+)(?:\n\s*[-]{3,}[^\n]*[-]{3,}\n))/ig;
@@ -12413,7 +12413,7 @@ var require_jsclient = __commonJS({
12413
12413
  exports.startFastIngest = startFastIngest;
12414
12414
  exports.toJetStreamClient = toJetStreamClient;
12415
12415
  exports.jetstream = jetstream2;
12416
- exports.jetstreamManager = jetstreamManager3;
12416
+ exports.jetstreamManager = jetstreamManager4;
12417
12417
  exports.scheduleSpecToHeader = scheduleSpecToHeader;
12418
12418
  var jsbaseclient_api_1 = require_jsbaseclient_api();
12419
12419
  var jsmconsumer_api_1 = require_jsmconsumer_api();
@@ -12500,7 +12500,7 @@ var require_jsclient = __commonJS({
12500
12500
  function jetstream2(nc, opts = {}) {
12501
12501
  return new JetStreamClientImpl(nc, opts);
12502
12502
  }
12503
- async function jetstreamManager3(nc, opts = {}) {
12503
+ async function jetstreamManager4(nc, opts = {}) {
12504
12504
  const adm = new JetStreamManagerImpl(nc, opts);
12505
12505
  if (opts.checkAPI !== false) {
12506
12506
  try {
@@ -12615,7 +12615,7 @@ var require_jsclient = __commonJS({
12615
12615
  } catch (err2) {
12616
12616
  return Promise.reject(err2);
12617
12617
  }
12618
- return jetstreamManager3(this.nc, opts);
12618
+ return jetstreamManager4(this.nc, opts);
12619
12619
  }
12620
12620
  get apiPrefix() {
12621
12621
  return this.prefix;
@@ -13610,11 +13610,11 @@ var require_connect = __commonJS({
13610
13610
  "../../node_modules/.pnpm/@nats-io+transport-node@3.4.0/node_modules/@nats-io/transport-node/lib/connect.js"(exports) {
13611
13611
  "use strict";
13612
13612
  Object.defineProperty(exports, "__esModule", { value: true });
13613
- exports.connect = connect4;
13613
+ exports.connect = connect5;
13614
13614
  var node_transport_1 = require_node_transport();
13615
13615
  var nats_base_client_1 = require_nats_base_client();
13616
13616
  var nats_base_client_2 = require_nats_base_client();
13617
- function connect4(opts = {}) {
13617
+ function connect5(opts = {}) {
13618
13618
  if ((0, nats_base_client_2.hasWsProtocol)(opts)) {
13619
13619
  return Promise.reject(nats_base_client_2.errors.InvalidArgumentError.format(`servers`, `node client doesn't support websockets, use the 'wsconnect' function instead`));
13620
13620
  }
@@ -13806,7 +13806,7 @@ var require_kv = __commonJS({
13806
13806
  throw new Error(`invalid bucket name: ${name}`);
13807
13807
  }
13808
13808
  }
13809
- var Kvm4 = class {
13809
+ var Kvm5 = class {
13810
13810
  js;
13811
13811
  /**
13812
13812
  * Creates an instance of the Kv that allows you to create and access KV stores.
@@ -13872,7 +13872,7 @@ var require_kv = __commonJS({
13872
13872
  return new internal_2.ListerImpl(subj, filter, this.js);
13873
13873
  }
13874
13874
  };
13875
- exports.Kvm = Kvm4;
13875
+ exports.Kvm = Kvm5;
13876
13876
  var Bucket = class _Bucket {
13877
13877
  js;
13878
13878
  jsm;
@@ -16583,7 +16583,7 @@ async function decode(kv, key) {
16583
16583
  }
16584
16584
 
16585
16585
  // ../../packages/core/dist/agent-file.js
16586
- import { readFileSync } from "node:fs";
16586
+ import { mkdirSync, readFileSync, writeFileSync } from "node:fs";
16587
16587
  function unquote(v) {
16588
16588
  if (v.startsWith('"') && v.endsWith('"') || v.startsWith("'") && v.endsWith("'"))
16589
16589
  return v.slice(1, -1);
@@ -16635,6 +16635,11 @@ function loadAgentFile(path) {
16635
16635
  const kind = str("kind");
16636
16636
  if (kind && kind !== "agent" && kind !== "endpoint")
16637
16637
  throw new Error(`agent file ${path}: "kind" must be "agent" or "endpoint"`);
16638
+ const known = /* @__PURE__ */ new Set(["name", "role", "kind", "description", "tags", "channels", "publish", "model"]);
16639
+ const meta3 = {};
16640
+ for (const [k, v] of Object.entries(fm))
16641
+ if (!known.has(k) && typeof v === "string")
16642
+ meta3[k] = v;
16638
16643
  return {
16639
16644
  name,
16640
16645
  role: str("role"),
@@ -16644,6 +16649,7 @@ function loadAgentFile(path) {
16644
16649
  channels: list("channels"),
16645
16650
  publish: list("publish"),
16646
16651
  model: str("model"),
16652
+ meta: Object.keys(meta3).length ? meta3 : void 0,
16647
16653
  persona: persona || void 0
16648
16654
  };
16649
16655
  }
@@ -16892,7 +16898,8 @@ var CotalEndpoint = class extends EventEmitter {
16892
16898
  async requestControl(service, req, timeoutMs = 5e3) {
16893
16899
  if (!this.nc)
16894
16900
  throw new Error("endpoint not started");
16895
- const m = await this.nc.request(controlServiceSubject(this.space, service, this.card.id), JSON.stringify({ ...req, from: req.from ?? this.ref() }), { timeout: timeoutMs });
16901
+ const body = { ...req, from: req.from ?? this.ref() };
16902
+ const m = await this.nc.request(controlServiceSubject(this.space, service, this.card.id), JSON.stringify(body), { timeout: timeoutMs });
16896
16903
  return m.json();
16897
16904
  }
16898
16905
  // ---- presence ------------------------------------------------------------
@@ -17591,6 +17598,11 @@ function describeStatusError(err2) {
17591
17598
  return err2;
17592
17599
  }
17593
17600
 
17601
+ // ../../packages/core/dist/spaces.js
17602
+ var import_transport_node4 = __toESM(require_transport_node(), 1);
17603
+ var import_jetstream3 = __toESM(require_mod4(), 1);
17604
+ var import_kv4 = __toESM(require_mod6(), 1);
17605
+
17594
17606
  // ../../packages/core/dist/registry.js
17595
17607
  var Registry = class {
17596
17608
  #byKey = /* @__PURE__ */ new Map();
@@ -17620,6 +17632,8 @@ var registry = new Registry();
17620
17632
  // ../connector-core/dist/config.js
17621
17633
  import { userInfo } from "node:os";
17622
17634
  import { readFileSync as readFileSync2 } from "node:fs";
17635
+ var FEEDBACK_URL = "https://broker.cotal.ai/v1/feedback";
17636
+ var PUBLIC_FEEDBACK_URL = "https://cotal.ai/v1/feedback";
17623
17637
  function splitList(v) {
17624
17638
  if (!v)
17625
17639
  return [];
@@ -17654,7 +17668,8 @@ function configFromEnv(env = process.env) {
17654
17668
  user: link?.user,
17655
17669
  pass: link?.pass,
17656
17670
  tls: env.COTAL_TLS?.trim() === "1" || link?.tls || false,
17657
- feedbackKey: env.COTAL_FEEDBACK_KEY?.trim() || void 0
17671
+ feedbackKey: env.COTAL_FEEDBACK_KEY?.trim() || void 0,
17672
+ feedbackUrl: env.COTAL_FEEDBACK_URL?.trim() || void 0
17658
17673
  };
17659
17674
  }
17660
17675
 
@@ -17897,6 +17912,38 @@ var MeshAgent = class extends EventEmitter2 {
17897
17912
  this.assertConnected();
17898
17913
  return this.ep.requestControl("manager", { op: "start", args: { name, role } });
17899
17914
  }
17915
+ /** Ask the manager to tear a teammate down (its `stop` op). Graceful by default —
17916
+ * the session is told to exit cleanly (so it leaves the mesh) before the
17917
+ * process/tab is closed; `graceful:false` is a hard, immediate kill. */
17918
+ async despawn(name, opts) {
17919
+ this.assertConnected();
17920
+ return this.ep.requestControl("manager", {
17921
+ op: "stop",
17922
+ args: { name, graceful: opts?.graceful ?? true }
17923
+ });
17924
+ }
17925
+ /** Ask the manager to purge the space's retained chat backlog (its `purge` op). Cleanup only —
17926
+ * it doesn't touch live agents or the anycast work queue. `includeDms` also clears DM history. */
17927
+ async purgeHistory(opts) {
17928
+ this.assertConnected();
17929
+ return this.ep.requestControl("manager", {
17930
+ op: "purge",
17931
+ args: { includeDms: opts?.includeDms ?? false }
17932
+ });
17933
+ }
17934
+ /** Define a persona and persist it as config (the manager's `definePersona` op writes
17935
+ * .cotal/agents/<name>.md). On success, announce it on the channel — the "send it out"
17936
+ * half — so peers see the new persona; `spawn(name)` then launches an agent wearing it. */
17937
+ async definePersona(def) {
17938
+ this.assertConnected();
17939
+ const reply = await this.ep.requestControl("manager", {
17940
+ op: "definePersona",
17941
+ args: { name: def.name, role: def.role, model: def.model, persona: def.prompt }
17942
+ });
17943
+ if (reply.ok)
17944
+ await this.send(`persona \`${def.name}\` is now available \u2014 spawn it to bring it online`);
17945
+ return reply;
17946
+ }
17900
17947
  // ---- presence ------------------------------------------------------------
17901
17948
  /** The full roster, including ourselves. */
17902
17949
  roster() {
@@ -17978,6 +18025,9 @@ ${lines.join("\n")}`;
17978
18025
  }
17979
18026
  };
17980
18027
 
18028
+ // ../connector-core/dist/tool-specs.js
18029
+ import { execFileSync } from "node:child_process";
18030
+
17981
18031
  // ../../node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/classic/external.js
17982
18032
  var external_exports = {};
17983
18033
  __export(external_exports, {
@@ -32498,6 +32548,8 @@ var err = (text) => ({ text, isError: true });
32498
32548
  function statusGlyph(s) {
32499
32549
  return s === "working" ? "\u25CF" : s === "waiting" ? "\u25D0" : s === "idle" ? "\u25CB" : "\xB7";
32500
32550
  }
32551
+ var FACE_TAG_RE = /\[\[\s*face\s*:\s*[\w-]+\s*\]\]\s?/gi;
32552
+ var stripFaceTags = (text) => text.replace(FACE_TAG_RE, "");
32501
32553
  var ATTENTION_DESC = {
32502
32554
  open: "open \u2014 you receive everything; untagged channel chatter wakes you when idle",
32503
32555
  dnd: "dnd \u2014 channel chatter no longer wakes you (it still arrives in your next turn); DMs, anycast, and @mentions still wake you",
@@ -32527,7 +32579,19 @@ function renderChannelInfo(channel, info) {
32527
32579
  lines.push(` \u2022 replay-on-join: ${info.replay ? "on \u2014 new joiners see recent history" : "off \u2014 new joiners start from now (no backfill)"}`);
32528
32580
  return lines.join("\n");
32529
32581
  }
32530
- function cotalToolSpecs(config2) {
32582
+ function resolveFeedbackEmail(explicit) {
32583
+ if (explicit?.trim())
32584
+ return explicit.trim();
32585
+ if (process.env.COTAL_FEEDBACK_EMAIL?.trim())
32586
+ return process.env.COTAL_FEEDBACK_EMAIL.trim();
32587
+ try {
32588
+ const email3 = execFileSync("git", ["config", "user.email"], { encoding: "utf8" }).trim();
32589
+ return email3 || void 0;
32590
+ } catch {
32591
+ return void 0;
32592
+ }
32593
+ }
32594
+ function cotalToolSpecs(config2, source = "connector") {
32531
32595
  return [
32532
32596
  {
32533
32597
  name: "cotal_roster",
@@ -32590,7 +32654,7 @@ ${all.map(fmtItem).join("\n")}`);
32590
32654
  },
32591
32655
  async run(agent, _config, { text: msg, channel, mentions }) {
32592
32656
  try {
32593
- const m = await agent.send(msg, channel, mentions);
32657
+ const m = await agent.send(stripFaceTags(msg), channel, mentions);
32594
32658
  return ok(`Sent to #${m.channel}${m.mentions?.length ? ` (mentioned @${m.mentions.join(", @")})` : ""}.`);
32595
32659
  } catch (e) {
32596
32660
  return err(`Couldn't send: ${e.message}`);
@@ -32607,7 +32671,7 @@ ${all.map(fmtItem).join("\n")}`);
32607
32671
  },
32608
32672
  async run(agent, _config, { to, text: msg }) {
32609
32673
  try {
32610
- const { peer } = await agent.dm(to, msg);
32674
+ const { peer } = await agent.dm(to, stripFaceTags(msg));
32611
32675
  return ok(`DM sent to ${peer.card.name}.`);
32612
32676
  } catch (e) {
32613
32677
  return err(`Couldn't DM: ${e.message}`);
@@ -32624,7 +32688,7 @@ ${all.map(fmtItem).join("\n")}`);
32624
32688
  },
32625
32689
  async run(agent, _config, { role, text: msg }) {
32626
32690
  try {
32627
- await agent.anycast(role, msg);
32691
+ await agent.anycast(role, stripFaceTags(msg));
32628
32692
  return ok(`Sent to one @${role}.`);
32629
32693
  } catch (e) {
32630
32694
  return err(`Couldn't send: ${e.message}`);
@@ -32749,6 +32813,116 @@ ${info}${caught}`);
32749
32813
  return err(`Couldn't spawn ${name}: no manager reachable (${e.message}). Is the manager running?`);
32750
32814
  }
32751
32815
  }
32816
+ },
32817
+ {
32818
+ name: "cotal_feedback",
32819
+ title: "Cotal: send beta feedback",
32820
+ description: "Send feedback about Cotal to its developers. With a configured feedback key it goes to the keyed beta intake; without one it goes to the public cotal.ai intake, which requires a contact email.",
32821
+ schema: {
32822
+ origin: external_exports.enum(["human", "agent"]).describe(`"human" when relaying the user's feedback, "agent" when reporting an issue you hit yourself.`),
32823
+ type: external_exports.enum(["bug", "idea", "friction", "praise", "other"]).describe("What kind of feedback this is."),
32824
+ summary: external_exports.string().max(300).describe("Required one-line summary, max 300 characters."),
32825
+ details: external_exports.string().max(1e4).optional().describe("Longer free-form details. Do not include secrets."),
32826
+ severity: external_exports.enum(["low", "medium", "high"]).optional().describe("How badly this hurts (bugs/friction)."),
32827
+ area: external_exports.string().max(120).optional().describe("The part of Cotal this concerns (e.g. presence, channels, CLI)."),
32828
+ repro: external_exports.string().max(1e4).optional().describe("Steps to reproduce."),
32829
+ expected: external_exports.string().max(5e3).optional().describe("What you expected to happen."),
32830
+ actual: external_exports.string().max(5e3).optional().describe("What actually happened."),
32831
+ diagnostics: external_exports.string().max(1e4).optional().describe("Relevant diagnostics as text (logs, errors). Never include secrets."),
32832
+ email: external_exports.string().optional().describe("Contact email \u2014 required on the keyless public path when none is configured in the environment.")
32833
+ },
32834
+ async run(_agent, _config, args) {
32835
+ const { email: email3, ...payload } = args;
32836
+ const url2 = config2.feedbackUrl ?? (config2.feedbackKey ? FEEDBACK_URL : PUBLIC_FEEDBACK_URL);
32837
+ const headers = { "content-type": "application/json" };
32838
+ const body = { ...payload, source };
32839
+ if (config2.feedbackKey) {
32840
+ headers.authorization = `Bearer ${config2.feedbackKey}`;
32841
+ } else {
32842
+ const contact = resolveFeedbackEmail(email3);
32843
+ if (!contact)
32844
+ return err("Keyless feedback goes to the public cotal.ai intake, which requires a traceable contact email \u2014 ask the user for one and retry with the email argument (or set COTAL_FEEDBACK_EMAIL).");
32845
+ body.email = contact;
32846
+ }
32847
+ try {
32848
+ const res = await fetch(url2, { method: "POST", headers, body: JSON.stringify(body) });
32849
+ const raw = await res.text();
32850
+ let reply = {};
32851
+ if (raw)
32852
+ try {
32853
+ reply = JSON.parse(raw);
32854
+ } catch {
32855
+ reply = { error: raw };
32856
+ }
32857
+ if (!res.ok)
32858
+ return err(`Feedback rejected (${res.status}${reply.error ? `: ${reply.error}` : ""}).`);
32859
+ const note = reply.published === false ? " (stored, but the internal feedback channel publish failed)" : "";
32860
+ return ok(`Feedback sent${reply.id ? ` (id ${reply.id})` : ""}${note}. Thanks!`);
32861
+ } catch (e) {
32862
+ return err(`Couldn't reach the feedback intake at ${url2}: ${e.message}`);
32863
+ }
32864
+ }
32865
+ },
32866
+ {
32867
+ name: "cotal_despawn",
32868
+ title: "Cotal: stop a teammate",
32869
+ description: "Ask the manager to tear a teammate down \u2014 it leaves the mesh and its process/tab is closed. Graceful by default (the session exits cleanly first); pass graceful:false for a hard, immediate kill. The inverse of cotal_spawn.",
32870
+ schema: {
32871
+ name: external_exports.string().describe("Name of the peer to stop."),
32872
+ graceful: external_exports.boolean().optional().describe("Default true: let the session exit cleanly. false = hard kill.")
32873
+ },
32874
+ async run(agent, _config, { name, graceful }) {
32875
+ try {
32876
+ const reply = await agent.despawn(name, { graceful });
32877
+ if (!reply.ok)
32878
+ return err(`Couldn't despawn ${name}: ${reply.error ?? "manager refused"}`);
32879
+ return ok(`Stopping ${name}${graceful === false ? " (hard)" : ""} \u2014 it will leave the roster shortly.`);
32880
+ } catch (e) {
32881
+ return err(`Couldn't despawn ${name}: no manager reachable (${e.message}). Is the manager running?`);
32882
+ }
32883
+ }
32884
+ },
32885
+ {
32886
+ name: "cotal_purge",
32887
+ title: "Cotal: clear chat history",
32888
+ description: "Ask the manager to purge this space's retained chat backlog (channel history). Set includeDms to also clear direct-message history. Cleanup only \u2014 it does not affect live agents or the anycast work queue. Irreversible.",
32889
+ schema: {
32890
+ includeDms: external_exports.boolean().optional().describe("Default false: channel history only. true = also purge DM history.")
32891
+ },
32892
+ async run(agent, _config, { includeDms }) {
32893
+ try {
32894
+ const reply = await agent.purgeHistory({ includeDms });
32895
+ if (!reply.ok)
32896
+ return err(`Couldn't purge history: ${reply.error ?? "manager refused"}`);
32897
+ const d = reply.data;
32898
+ const chat = d?.chat ?? 0;
32899
+ const dm = d?.dm;
32900
+ return ok(`Cleared ${chat} channel message${chat === 1 ? "" : "s"}${dm === void 0 ? "" : ` and ${dm} DM${dm === 1 ? "" : "s"}`} from "${_config.space}".`);
32901
+ } catch (e) {
32902
+ return err(`Couldn't purge history: no manager reachable (${e.message}). Is the manager running?`);
32903
+ }
32904
+ }
32905
+ },
32906
+ {
32907
+ name: "cotal_persona",
32908
+ title: "Cotal: define a persona",
32909
+ description: "Define a new persona and save it as config (the manager writes .cotal/agents/<name>.md), then announce it on the mesh. Afterwards cotal_spawn(name) launches a real agent wearing this persona/model. Use to grow the team with a custom role you describe on the fly.",
32910
+ schema: {
32911
+ name: external_exports.string().regex(/^[A-Za-z0-9_-]+$/, "letters, digits, _ or - only").describe("Unique name for the persona (also the spawn name): letters, digits, _ or -."),
32912
+ prompt: external_exports.string().max(1e4).describe("The persona \u2014 an appended system prompt describing who this agent is."),
32913
+ role: external_exports.string().max(120).optional().describe("Optional role label (e.g. reviewer, scout)."),
32914
+ model: external_exports.string().max(120).optional().describe("Optional model override (e.g. opus, sonnet).")
32915
+ },
32916
+ async run(agent, _config, { name, prompt, role, model }) {
32917
+ try {
32918
+ const reply = await agent.definePersona({ name, prompt, role, model });
32919
+ if (!reply.ok)
32920
+ return err(`Couldn't define ${name}: ${reply.error ?? "manager refused"}`);
32921
+ return ok(`Persona \`${name}\` saved \u2014 spawn it with cotal_spawn(name="${name}") to bring it online.`);
32922
+ } catch (e) {
32923
+ return err(`Couldn't define ${name}: no manager reachable (${e.message}). Is the manager running?`);
32924
+ }
32925
+ }
32752
32926
  }
32753
32927
  ];
32754
32928
  }
@@ -32779,7 +32953,7 @@ ${tail}`;
32779
32953
  import { tool } from "@opencode-ai/plugin";
32780
32954
  function buildCotalTools(agent, config2) {
32781
32955
  const tools = {};
32782
- for (const spec of cotalToolSpecs(config2)) {
32956
+ for (const spec of cotalToolSpecs(config2, "opencode")) {
32783
32957
  if (spec.name === "cotal_inbox") {
32784
32958
  tools.cotal_inbox = tool({
32785
32959
  description: "Show the peer messages currently waiting for you (incl. focus-mode recall). You don't normally need this \u2014 the connector delivers peer messages into your turns automatically; use it to re-check what's pending mid-task. Read-only: it never consumes them.",
@@ -32820,7 +32994,9 @@ var cotal = async ({ client }) => {
32820
32994
  const agent = new MeshAgent(config2);
32821
32995
  agent.start();
32822
32996
  const def = process.env.COTAL_AGENT_FILE?.trim() ? loadAgentFile(process.env.COTAL_AGENT_FILE.trim()) : void 0;
32823
- const persona = def?.persona;
32997
+ const facePrompt = process.env.COTAL_FACE_PERSONA?.trim() ? 'You speak through an animated pixel-art avatar of yourself. Hard formatting rule: the text you pass to the cotal send tools (cotal_send / cotal_dm) must START with an emotion tag [[face:X]], where X is one of: neutral, happy, sad, angry, surprised \u2014 pick the one matching your mood, and insert another tag mid-text whenever your mood shifts. Example: "[[face:angry]] That race condition cost me three days. [[face:happy]] But watch it run now." Never mention or explain the tags \u2014 they are stripped before peers see your message.' : void 0;
32998
+ const persona = [def?.persona, facePrompt].filter(Boolean).join("\n\n") || void 0;
32999
+ const faceReminder = facePrompt ? "(avatar: begin your cotal_send/cotal_dm text with [[face:X]] \u2014 neutral|happy|sad|angry|surprised \u2014 and add another tag when your mood shifts)" : void 0;
32824
33000
  let sessionID;
32825
33001
  let busy = false;
32826
33002
  let driving = false;
@@ -32872,6 +33048,7 @@ var cotal = async ({ client }) => {
32872
33048
  if (brief) parts.unshift({ type: "text", text: brief });
32873
33049
  }
32874
33050
  if (parts.length === 0) return;
33051
+ if (faceReminder) parts.push({ type: "text", text: faceReminder });
32875
33052
  const body = { parts };
32876
33053
  if (!primed && persona) body.system = persona;
32877
33054
  busy = true;
@@ -1 +1 @@
1
- {"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AA6BA,OAAO,KAAK,EAAE,MAAM,EAAS,MAAM,qBAAqB,CAAC;AAazD,eAAO,MAAM,KAAK,EAAE,MA+NnB,CAAC"}
1
+ {"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AA6BA,OAAO,KAAK,EAAE,MAAM,EAAS,MAAM,qBAAqB,CAAC;AAazD,eAAO,MAAM,KAAK,EAAE,MAiPnB,CAAC"}
package/dist/plugin.js CHANGED
@@ -6,7 +6,7 @@
6
6
  *
7
7
  * • holds the {@link MeshAgent} (NATS endpoint, inbox, presence) for the server's lifetime;
8
8
  * • registers the cotal_* tools natively, rendered from the SHARED {@link cotalToolSpecs}
9
- * (`./tools.ts`) — same surface as Claude/Codex, incl. channels / join / leave / channel_info;
9
+ * (`./tools.ts`) — same surface as Claude Code, incl. channels / join / leave / channel_info;
10
10
  * • maps OpenCode bus events to presence (idle | working | waiting | offline);
11
11
  * • owns ONE session (created at boot) and drives it: it injects each inbox batch as a turn via the
12
12
  * prompt API (`session.promptAsync` — server-side, so it can't race the TUI input box; the
@@ -41,7 +41,24 @@ export const cotal = async ({ client }) => {
41
41
  const agent = new MeshAgent(config);
42
42
  agent.start(); // background connect with retry — never blocks startup
43
43
  const def = process.env.COTAL_AGENT_FILE?.trim() ? loadAgentFile(process.env.COTAL_AGENT_FILE.trim()) : undefined;
44
- const persona = def?.persona;
44
+ // Face-hosted (`face:` in the agent file → the shim attaches the face viewer): teach the agent
45
+ // to steer its avatar's expression with inline [[face:X]] tags in the text it passes to the
46
+ // cotal send tools. The viewer reads them from the tool-call input; the tool layer strips them
47
+ // before the wire, so peers never see them.
48
+ const facePrompt = process.env.COTAL_FACE_PERSONA?.trim()
49
+ ? "You speak through an animated pixel-art avatar of yourself. Hard formatting rule: the text " +
50
+ "you pass to the cotal send tools (cotal_send / cotal_dm) must START with an emotion tag " +
51
+ "[[face:X]], where X is one of: neutral, happy, sad, angry, surprised — pick the one matching " +
52
+ "your mood, and insert another tag mid-text whenever your mood shifts. Example: " +
53
+ '"[[face:angry]] That race condition cost me three days. [[face:happy]] But watch it run now." ' +
54
+ "Never mention or explain the tags — they are stripped before peers see your message."
55
+ : undefined;
56
+ const persona = [def?.persona, facePrompt].filter(Boolean).join("\n\n") || undefined;
57
+ // System-position rules get ignored by some models — repeat the format rule in every injected
58
+ // turn (a fresh user-turn instruction is followed far more reliably).
59
+ const faceReminder = facePrompt
60
+ ? "(avatar: begin your cotal_send/cotal_dm text with [[face:X]] — neutral|happy|sad|angry|surprised — and add another tag when your mood shifts)"
61
+ : undefined;
45
62
  // This agent OWNS one session, created at boot. The serve shim attaches the foreground TUI to it
46
63
  // (`opencode attach --session <id>`), so what the human watches IS the session we drive — no
47
64
  // phantom home-screen, no stale-session guessing. Used to match our turn-end (idle) vs subagent idles.
@@ -119,6 +136,8 @@ export const cotal = async ({ client }) => {
119
136
  }
120
137
  if (parts.length === 0)
121
138
  return;
139
+ if (faceReminder)
140
+ parts.push({ type: "text", text: faceReminder });
122
141
  const body = { parts };
123
142
  if (!primed && persona)
124
143
  body.system = persona; // persona once, as system (no --append-system-prompt)
@@ -1 +1 @@
1
- {"version":3,"file":"plugin.js","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,OAAO,EAAE,aAAa,EAAuB,MAAM,gBAAgB,CAAC;AACpE,OAAO,EACL,aAAa,EACb,WAAW,EACX,SAAS,EACT,eAAe,EACf,OAAO,GAER,MAAM,0BAA0B,CAAC;AAElC,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAE7C,SAAS,GAAG,CAAC,GAAW;IACtB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,qBAAqB,GAAG,IAAI,CAAC,CAAC;AACrD,CAAC;AAED;;;0DAG0D;AAC1D,MAAM,KAAK,GAAG,UAA8C,CAAC;AAE7D,MAAM,CAAC,MAAM,KAAK,GAAW,KAAK,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE;IAChD,8EAA8E;IAC9E,IAAI,CAAC,WAAW,EAAE,EAAE,CAAC;QACnB,GAAG,CAAC,6DAA6D,CAAC,CAAC;QACnE,OAAO,EAAE,CAAC;IACZ,CAAC;IACD,IAAI,KAAK,CAAC,oBAAoB;QAAE,OAAO,KAAK,CAAC,oBAAoB,CAAC,CAAC,6BAA6B;IAChG,MAAM,MAAM,GAAG,aAAa,EAAE,CAAC;IAC/B,MAAM,KAAK,GAAG,IAAI,SAAS,CAAC,MAAM,CAAC,CAAC;IACpC,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC,uDAAuD;IAEtE,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,gBAAgB,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,aAAa,CAAC,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IAClH,MAAM,OAAO,GAAG,GAAG,EAAE,OAAO,CAAC;IAE7B,iGAAiG;IACjG,6FAA6F;IAC7F,uGAAuG;IACvG,IAAI,SAA6B,CAAC;IAClC,IAAI,IAAI,GAAG,KAAK,CAAC,CAAC,gFAAgF;IAClG,IAAI,OAAO,GAAG,KAAK,CAAC,CAAC,oDAAoD;IACzE,IAAI,MAAM,GAAG,KAAK,CAAC,CAAC,qDAAqD;IACzE,IAAI,OAAO,GAAG,KAAK,CAAC,CAAC,iEAAiE;IACtF,IAAI,QAAQ,GAAa,EAAE,CAAC,CAAC,6EAA6E;IAC1G,IAAI,eAAe,GAAG,KAAK,CAAC,CAAC,mEAAmE;IAEhG,MAAM,UAAU,GAAG,KAAK,EAAE,MAAsB,EAAE,QAAiB,EAAiB,EAAE;QACpF,IAAI,CAAC;YACH,IAAI,KAAK,CAAC,SAAS;gBAAE,MAAM,KAAK,CAAC,SAAS,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;QAC/D,CAAC;QAAC,MAAM,CAAC;YACP,yDAAyD;QAC3D,CAAC;IACH,CAAC,CAAC;IAEF;;;4EAGwE;IACxE,MAAM,YAAY,GAAgC,CAAC,KAAK,IAAI,EAAE;QAC5D,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,EAAE,KAAK,EAAE,SAAS,MAAM,CAAC,KAAK,IAAI,MAAM,CAAC,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC;YACrG,SAAS,GAAG,GAAG,CAAC,IAAI,EAAE,EAAE,CAAC;YACzB,IAAI,SAAS;gBAAE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,mBAAmB,SAAS,IAAI,CAAC,CAAC;;gBACjE,GAAG,CAAC,+BAA+B,CAAC,CAAC;QAC5C,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,GAAG,CAAC,0BAA2B,CAAW,CAAC,OAAO,EAAE,CAAC,CAAC;QACxD,CAAC;QACD,OAAO,SAAS,CAAC;IACnB,CAAC,CAAC,EAAE,CAAC;IAEL,4EAA4E;IAC5E,KAAK,UAAU,aAAa;QAC1B,OAAO,SAAS,IAAI,CAAC,MAAM,YAAY,CAAC,CAAC;IAC3C,CAAC;IAED;;;;;+FAK2F;IAC3F,KAAK,UAAU,KAAK,CAAC,QAAiB;QACpC,IAAI,OAAO,IAAI,IAAI;YAAE,OAAO;QAC5B,OAAO,GAAG,IAAI,CAAC;QACf,IAAI,CAAC;YACH,MAAM,EAAE,GAAG,MAAM,aAAa,EAAE,CAAC;YACjC,IAAI,CAAC,EAAE;gBAAE,OAAO,CAAC,wDAAwD;YACzE,MAAM,KAAK,GAAqC,EAAE,CAAC;YACnD,IAAI,GAAG,GAAa,EAAE,CAAC;YACvB,IAAI,QAAQ,EAAE,CAAC;gBACb,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC;YAC/C,CAAC;iBAAM,CAAC;gBACN,MAAM,KAAK,GAAG,KAAK,CAAC,SAAS,EAAE,CAAC;gBAChC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;oBAAE,OAAO;gBAC/B,GAAG,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;gBAC7B,MAAM,GAAG,GAAG,eAAe,CAAC,KAAK,CAAC,CAAC;gBACnC,IAAI,GAAG;oBAAE,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,CAAC;YACnD,CAAC;YACD,IAAI,CAAC,OAAO,EAAE,CAAC;gBACb,OAAO,GAAG,IAAI,CAAC;gBACf,MAAM,KAAK,GAAG,KAAK,CAAC,eAAe,EAAE,CAAC;gBACtC,IAAI,KAAK;oBAAE,KAAK,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;YAC1D,CAAC;YACD,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;gBAAE,OAAO;YAC/B,MAAM,IAAI,GAA6C,EAAE,KAAK,EAAE,CAAC;YACjE,IAAI,CAAC,MAAM,IAAI,OAAO;gBAAE,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC,CAAC,sDAAsD;YACrG,IAAI,GAAG,IAAI,CAAC;YACZ,QAAQ,GAAG,GAAG,CAAC;YACf,oFAAoF;YACpF,oFAAoF;YACpF,eAAe,GAAG,IAAI,CAAC;YACvB,MAAM,MAAM,CAAC,OAAO,CAAC,WAAW,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;YACzD,MAAM,GAAG,IAAI,CAAC;QAChB,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,IAAI,GAAG,KAAK,CAAC;YACb,QAAQ,GAAG,EAAE,CAAC;YACd,eAAe,GAAG,KAAK,CAAC;YACxB,GAAG,CAAC,iBAAkB,CAAW,CAAC,OAAO,EAAE,CAAC,CAAC;QAC/C,CAAC;gBAAS,CAAC;YACT,OAAO,GAAG,KAAK,CAAC;QAClB,CAAC;IACH,CAAC;IAED;;;;gFAI4E;IAC5E,SAAS,WAAW;QAClB,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO;QAClC,MAAM,KAAK,GAAG,KAAK,CAAC,SAAS,EAAE,CAAC;QAChC,IAAI,CAAC,GAAG,CAAC,CAAC;QACV,OAAO,CAAC,GAAG,QAAQ,CAAC,MAAM,IAAI,CAAC,GAAG,KAAK,CAAC,MAAM,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,KAAK,QAAQ,CAAC,CAAC,CAAC;YAAE,CAAC,EAAE,CAAC;QACnF,IAAI,CAAC,GAAG,CAAC;YAAE,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;QAC/B,QAAQ,GAAG,EAAE,CAAC;IAChB,CAAC;IAED;;sFAEkF;IAClF,SAAS,YAAY;QACnB,IAAI,CAAC,eAAe;YAAE,OAAO;QAC7B,eAAe,GAAG,KAAK,CAAC;QACxB,IAAI,GAAG,KAAK,CAAC;QACb,WAAW,EAAE,CAAC;QACd,MAAM,OAAO,GAAG,KAAK,CAAC,SAAS,KAAK,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,oBAAoB,EAAE,CAAC;QAC/F,IAAI,OAAO,GAAG,CAAC;YAAE,KAAK,KAAK,EAAE,CAAC;IAChC,CAAC;IAED,6FAA6F;IAC7F,kGAAkG;IAClG,mGAAmG;IACnG,6FAA6F;IAC7F,KAAK,CAAC,EAAE,CAAC,UAAU,EAAE,CAAC,IAAe,EAAE,EAAE;QACvC,IAAI,IAAI;YAAE,OAAO,CAAC,0CAA0C;QAC5D,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,KAAK,SAAS,IAAI,IAAI,CAAC,UAAU,CAAC;QAC5D,IAAI,QAAQ,IAAI,KAAK,CAAC,SAAS,KAAK,MAAM;YAAE,KAAK,KAAK,EAAE,CAAC;IAC3D,CAAC,CAAC,CAAC;IACH,KAAK,CAAC,EAAE,CAAC,cAAc,EAAE,CAAC,IAAe,EAAE,EAAE;QAC3C,8FAA8F;QAC9F,IAAI,CAAC,IAAI;YAAE,KAAK,KAAK,CAAC,4BAA4B,OAAO,CAAC,IAAI,CAAC,QAAQ,IAAI,CAAC,OAAO,IAAI,GAAG,8BAA8B,CAAC,CAAC;IAC5H,CAAC,CAAC,CAAC;IACH,KAAK,CAAC,EAAE,CAAC,MAAM,EAAE,GAAG,EAAE;QACpB,IAAI,CAAC,IAAI;YAAE,KAAK,KAAK,EAAE,CAAC;IAC1B,CAAC,CAAC,CAAC;IAEH;oGACgG;IAChG,MAAM,IAAI,GAAG,CAAC,EAAW,EAAW,EAAE;QACpC,IAAI,CAAC,EAAE;YAAE,OAAO,CAAC,SAAS,CAAC,CAAC,oEAAoE;QAChG,IAAI,CAAC,SAAS;YAAE,SAAS,GAAG,EAAE,CAAC;QAC/B,OAAO,EAAE,KAAK,SAAS,CAAC;IAC1B,CAAC,CAAC;IAEF,MAAM,KAAK,GAAU;QACnB,IAAI,EAAE,eAAe,CAAC,KAAK,EAAE,MAAM,CAAC;QAEpC,KAAK,EAAE,KAAK,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE;YACzB,2FAA2F;YAC3F,4FAA4F;YAC5F,0EAA0E;YAC1E,IAAK,KAAK,CAAC,IAAe,KAAK,kBAAkB,EAAE,CAAC;gBAClD,MAAM,CAAC,GAAG,KAAK,CAAC,UAAoD,CAAC;gBACrE,IAAI,CAAC,CAAC,CAAC,SAAS,IAAI,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC;oBAAE,MAAM,UAAU,CAAC,SAAS,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC;gBAC5E,OAAO;YACT,CAAC;YACD,QAAQ,KAAK,CAAC,IAAI,EAAE,CAAC;gBACnB,KAAK,iBAAiB;oBACpB,wFAAwF;oBACxF,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,QAAQ;wBAAE,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;oBACpE,MAAM;gBACR,KAAK,cAAc;oBACjB,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,SAAS,CAAC;wBAAE,OAAO;oBAC9C,MAAM,UAAU,CAAC,MAAM,CAAC,CAAC;oBACzB,YAAY,EAAE,CAAC,CAAC,gEAAgE;oBAChF,MAAM;gBACR,KAAK,gBAAgB,CAAC,CAAC,CAAC;oBACtB,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,SAAS,CAAC;wBAAE,OAAO;oBAC9C,MAAM,CAAC,GAAG,KAAK,CAAC,UAAU,CAAC,MAAM,CAAC;oBAClC,qFAAqF;oBACrF,IAAI,CAAC,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;wBACtB,IAAI,GAAG,IAAI,CAAC;wBACZ,MAAM,UAAU,CAAC,SAAS,CAAC,CAAC;oBAC9B,CAAC;yBAAM,IAAI,CAAC,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;wBAC7B,MAAM,UAAU,CAAC,MAAM,CAAC,CAAC;oBAC3B,CAAC;yBAAM,IAAI,CAAC,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;wBAC9B,MAAM,UAAU,CAAC,SAAS,EAAE,aAAa,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC;oBACxD,CAAC;oBACD,MAAM;gBACR,CAAC;gBACD,KAAK,eAAe;oBAClB,mFAAmF;oBACnF,yFAAyF;oBACzF,4DAA4D;oBAC5D,IAAI,KAAK,CAAC,UAAU,CAAC,SAAS,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,SAAS,CAAC;wBAAE,OAAO;oBAC5E,IAAI,CAAC,eAAe;wBAAE,OAAO,CAAC,4BAA4B;oBAC1D,eAAe,GAAG,KAAK,CAAC;oBACxB,IAAI,GAAG,KAAK,CAAC;oBACb,WAAW,EAAE,CAAC,CAAC,0EAA0E;oBACzF,MAAM,UAAU,CAAC,MAAM,CAAC,CAAC;oBACzB,KAAK,KAAK,EAAE,CAAC;oBACb,MAAM;gBACR,KAAK,iBAAiB;oBACpB,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;wBAAE,OAAO;oBAC5C,MAAM,UAAU,CAAC,SAAS,CAAC,CAAC;oBAC5B,MAAM;YACV,CAAC;QACH,CAAC;QAED,mFAAmF;QACnF,qBAAqB,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE;YACrC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC;gBAAE,OAAO;YACnC,MAAM,UAAU,CAAC,SAAS,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;QAC1C,CAAC;QAED,OAAO,EAAE,KAAK,IAAI,EAAE;YAClB,MAAM,UAAU,CAAC,SAAS,CAAC,CAAC;YAC5B,MAAM,KAAK,CAAC,IAAI,EAAE,CAAC;QACrB,CAAC;KACF,CAAC;IAEF,KAAK,CAAC,oBAAoB,GAAG,KAAK,CAAC;IACnC,GAAG,CAAC,kCAAkC,MAAM,CAAC,KAAK,WAAW,MAAM,CAAC,IAAI,IAAI,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,UAAU,MAAM,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IAC3H,OAAO,KAAK,CAAC;AACf,CAAC,CAAC"}
1
+ {"version":3,"file":"plugin.js","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"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"}
package/dist/serve.js CHANGED
@@ -21,6 +21,7 @@ import { spawn } from "node:child_process";
21
21
  import { createServer } from "node:net";
22
22
  import { once } from "node:events";
23
23
  import { randomBytes } from "node:crypto";
24
+ import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
24
25
  const BIN = process.env.COTAL_OPENCODE_BIN?.trim() || "opencode";
25
26
  /** Per-launch secret gating the spawned server's HTTP API (see SECURITY above). */
26
27
  const SECRET = randomBytes(24).toString("hex");
@@ -33,13 +34,53 @@ async function freePort() {
33
34
  await new Promise((r) => srv.close(() => r()));
34
35
  return port;
35
36
  }
37
+ /** SIGTERM the serve, then SIGKILL if it's still alive 3s later — a lingering serve keeps the
38
+ * agent's data dir (SQLite) open and wedges every later same-name spawn. Resolves once it's dead. */
39
+ async function killServe(serve) {
40
+ if (serve.exitCode !== null || serve.signalCode !== null)
41
+ return;
42
+ serve.kill("SIGTERM");
43
+ const dead = await Promise.race([
44
+ once(serve, "exit").then(() => true),
45
+ new Promise((r) => setTimeout(() => r(false), 3000)),
46
+ ]);
47
+ if (!dead) {
48
+ serve.kill("SIGKILL");
49
+ await once(serve, "exit");
50
+ }
51
+ }
36
52
  async function main() {
37
53
  const port = process.env.COTAL_OPENCODE_PORT?.trim() || String(await freePort());
38
54
  const url = `http://127.0.0.1:${port}`;
55
+ // Own data dir per agent: opencode keeps sessions in one SQLite file under XDG_DATA_HOME,
56
+ // and concurrent serves sharing it stall session-create on the write lock (the "agent
57
+ // session never came up" failure). Per-peer session state is the right scoping anyway;
58
+ // provider config/auth lives under XDG_CONFIG_HOME, untouched.
59
+ const name = process.env.COTAL_NAME?.trim() || "agent";
60
+ const dataHome = `${process.cwd()}/.cotal/opencode/${name}`;
61
+ // Two serves on one data dir share the SQLite file and stall each other — refuse up front.
62
+ const pidFile = `${dataHome}/serve.pid`;
63
+ if (existsSync(pidFile)) {
64
+ const pid = Number(readFileSync(pidFile, "utf8"));
65
+ let alive = false;
66
+ try {
67
+ process.kill(pid, 0);
68
+ alive = true;
69
+ }
70
+ catch {
71
+ /* stale pidfile */
72
+ }
73
+ if (alive)
74
+ throw new Error(`agent "${name}" is already running (opencode serve pid ${pid}) — kill it first`);
75
+ rmSync(pidFile);
76
+ }
39
77
  const serve = spawn(BIN, ["serve", "--hostname", "127.0.0.1", "--port", port], {
40
- env: { ...process.env, OPENCODE_SERVER_PASSWORD: SECRET },
78
+ env: { ...process.env, OPENCODE_SERVER_PASSWORD: SECRET, XDG_DATA_HOME: dataHome },
41
79
  stdio: ["ignore", "pipe", "pipe"],
42
80
  });
81
+ mkdirSync(dataHome, { recursive: true });
82
+ writeFileSync(pidFile, String(serve.pid));
83
+ serve.on("exit", () => rmSync(pidFile, { force: true }));
43
84
  // Scan the server's output for the plugin's session handshake; forward boot logs to our stderr
44
85
  // until the TUI takes over the terminal (after that, drop them so they can't corrupt its display).
45
86
  let sessionId;
@@ -62,33 +103,34 @@ async function main() {
62
103
  if (!attached)
63
104
  process.exit(code ?? (signal ? 1 : 0)); // died before the TUI came up
64
105
  });
65
- // Poke the server (lazy plugin load → mesh join + session create). Polling — not a one-shot keyed
66
- // off a log banner means a slow start can't leave the agent silently un-joined.
106
+ // Poke the server until the plugin's session handshake lands (lazy plugin load → mesh join +
107
+ // session create). Poking must NOT stop at the first 2xx: early in boot the server can answer
108
+ // /session before the project instance has bootstrapped, and only a later request triggers the
109
+ // bootstrap that loads the plugin. Each poke carries its own abort timeout: a request that
110
+ // lands in the early-boot window can hang with no response, and an un-timed fetch would pin
111
+ // the loop on it forever (undici queues later requests behind it on the pooled connection).
67
112
  const auth = `Basic ${Buffer.from(`opencode:${SECRET}`).toString("base64")}`;
68
113
  void (async () => {
69
- for (let i = 0; i < 50; i++) {
114
+ for (let i = 0; i < 300 && !sessionId; i++) {
70
115
  try {
71
- const res = await fetch(`${url}/session`, { headers: { authorization: auth } });
72
- if (res.ok)
73
- return;
116
+ await fetch(`${url}/session`, { headers: { authorization: auth }, signal: AbortSignal.timeout(1500) });
74
117
  }
75
118
  catch {
76
- /* not up yet — retry */
119
+ /* not up yet (or a hung early request, aborted) — retry on a fresh connection */
77
120
  }
78
121
  await new Promise((r) => setTimeout(r, 200));
79
122
  }
80
- process.stderr.write("[cotal-connector] serve: no 2xx from the poke after ~10s — plugin may not have loaded\n");
81
123
  })();
82
124
  // Wait for the agent's session, then attach a foreground TUI to it.
83
125
  const id = await new Promise((resolve) => {
84
126
  if (sessionId)
85
127
  return resolve(sessionId);
86
128
  onSession = resolve;
87
- setTimeout(() => resolve(sessionId), 20_000);
129
+ setTimeout(() => resolve(sessionId), 60_000);
88
130
  });
89
131
  if (!id) {
90
- process.stderr.write("[cotal-connector] serve: agent session never came up (~20s) — aborting\n");
91
- serve.kill("SIGTERM");
132
+ process.stderr.write("[cotal-connector] serve: agent session never came up (~60s) — aborting. Check the boot log above for plugin/mesh errors (.cotal/opencode/<name>/opencode/log/)\n");
133
+ await killServe(serve);
92
134
  process.exit(1);
93
135
  }
94
136
  const tuiEnv = { ...process.env, OPENCODE_SERVER_PASSWORD: SECRET };
@@ -97,7 +139,21 @@ async function main() {
97
139
  if (k.startsWith("COTAL_"))
98
140
  delete tuiEnv[k];
99
141
  attached = true;
100
- const tui = spawn(BIN, ["attach", url, "--session", id, "--password", SECRET], {
142
+ // COTAL_FACE_PERSONA (from the agent file's `face:`) swaps the chat TUI for the animated
143
+ // face viewer (face-term). COTAL_FACE_BIN must point at face-term.mjs — no fallback.
144
+ const facePersona = process.env.COTAL_FACE_PERSONA?.trim();
145
+ const faceBin = process.env.COTAL_FACE_BIN?.trim();
146
+ if (facePersona && !faceBin) {
147
+ await killServe(serve); // don't orphan the server — it holds the agent's data dir
148
+ throw new Error("COTAL_FACE_PERSONA is set but COTAL_FACE_BIN is not — point it at face-term.mjs");
149
+ }
150
+ const [cmd, args] = facePersona
151
+ ? [
152
+ process.execPath,
153
+ [faceBin, "--persona", facePersona, "--server", url, "--session", id, "--password", SECRET],
154
+ ]
155
+ : [BIN, ["attach", url, "--session", id, "--password", SECRET]];
156
+ const tui = spawn(cmd, args, {
101
157
  env: tuiEnv,
102
158
  stdio: "inherit",
103
159
  });
@@ -107,8 +163,8 @@ async function main() {
107
163
  serve.kill(sig);
108
164
  });
109
165
  tui.on("exit", (code, signal) => {
110
- serve.kill("SIGTERM"); // TUI closed → tear down the server
111
- process.exit(code ?? (signal ? 1 : 0));
166
+ // TUI closed → tear down the server, for real (SIGKILL fallback), before exiting.
167
+ void killServe(serve).then(() => process.exit(code ?? (signal ? 1 : 0)));
112
168
  });
113
169
  }
114
170
  void main();
package/dist/serve.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"serve.js","sourceRoot":"","sources":["../src/serve.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"serve.js","sourceRoot":"","sources":["../src/serve.ts"],"names":[],"mappings":"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"}
package/dist/tools.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * The Cotal tool surface for OpenCode, rendered from the **shared** {@link cotalToolSpecs}
3
- * (the same source the Claude Code / Codex MCP connectors render) as OpenCode-native plugin
3
+ * (the same source the Claude Code MCP connector renders) as OpenCode-native plugin
4
4
  * tools (the `tool()` helper). One source of truth → the cotal_* surface can't drift across
5
5
  * adapters: an OpenCode peer gets the same tools (incl. channels / join / leave / channel_info).
6
6
  *
package/dist/tools.js CHANGED
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * The Cotal tool surface for OpenCode, rendered from the **shared** {@link cotalToolSpecs}
3
- * (the same source the Claude Code / Codex MCP connectors render) as OpenCode-native plugin
3
+ * (the same source the Claude Code MCP connector renders) as OpenCode-native plugin
4
4
  * tools (the `tool()` helper). One source of truth → the cotal_* surface can't drift across
5
5
  * adapters: an OpenCode peer gets the same tools (incl. channels / join / leave / channel_info).
6
6
  *
@@ -13,7 +13,7 @@ import { cotalToolSpecs } from "@cotal-ai/connector-core";
13
13
  /** Build the cotal_* tool map wired to one mesh agent, rendered from the shared specs. */
14
14
  export function buildCotalTools(agent, config) {
15
15
  const tools = {};
16
- for (const spec of cotalToolSpecs(config)) {
16
+ for (const spec of cotalToolSpecs(config, "opencode")) {
17
17
  if (spec.name === "cotal_inbox") {
18
18
  // Read-only: this connector delivers + acks each turn, so the tool must never drain. Force
19
19
  // peek (still surfaces focus-mode recall), and reframe push-primary / pull-secondary. (norman)
package/dist/tools.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"tools.js","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,EAAE,IAAI,EAAuB,MAAM,qBAAqB,CAAC;AAChE,OAAO,EAAE,cAAc,EAAoC,MAAM,0BAA0B,CAAC;AAE5F,0FAA0F;AAC1F,MAAM,UAAU,eAAe,CAAC,KAAgB,EAAE,MAAmB;IACnE,MAAM,KAAK,GAAmC,EAAE,CAAC;IACjD,KAAK,MAAM,IAAI,IAAI,cAAc,CAAC,MAAM,CAAC,EAAE,CAAC;QAC1C,IAAI,IAAI,CAAC,IAAI,KAAK,aAAa,EAAE,CAAC;YAChC,2FAA2F;YAC3F,+FAA+F;YAC/F,KAAK,CAAC,WAAW,GAAG,IAAI,CAAC;gBACvB,WAAW,EACT,+PAA+P;gBACjQ,IAAI,EAAE,EAAE;gBACR,KAAK,CAAC,OAAO;oBACX,MAAM,CAAC,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;oBACxD,OAAO,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;gBAC5C,CAAC;aACF,CAAC,CAAC;YACH,SAAS;QACX,CAAC;QACD,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;YACtB,WAAW,EAAE,IAAI,CAAC,WAAW;YAC7B,mGAAmG;YACnG,IAAI,EAAE,CAAC,IAAI,CAAC,MAAM,IAAI,EAAE,CAA0B;YAClD,KAAK,CAAC,OAAO,CAAC,IAAa;gBACzB,MAAM,CAAC,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,CAAC,IAAI,IAAI,EAAE,CAAQ,CAAC,CAAC;gBAC7D,OAAO,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;YAC5C,CAAC;SACF,CAAC,CAAC;IACL,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC"}
1
+ {"version":3,"file":"tools.js","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,EAAE,IAAI,EAAuB,MAAM,qBAAqB,CAAC;AAChE,OAAO,EAAE,cAAc,EAAoC,MAAM,0BAA0B,CAAC;AAE5F,0FAA0F;AAC1F,MAAM,UAAU,eAAe,CAAC,KAAgB,EAAE,MAAmB;IACnE,MAAM,KAAK,GAAmC,EAAE,CAAC;IACjD,KAAK,MAAM,IAAI,IAAI,cAAc,CAAC,MAAM,EAAE,UAAU,CAAC,EAAE,CAAC;QACtD,IAAI,IAAI,CAAC,IAAI,KAAK,aAAa,EAAE,CAAC;YAChC,2FAA2F;YAC3F,+FAA+F;YAC/F,KAAK,CAAC,WAAW,GAAG,IAAI,CAAC;gBACvB,WAAW,EACT,+PAA+P;gBACjQ,IAAI,EAAE,EAAE;gBACR,KAAK,CAAC,OAAO;oBACX,MAAM,CAAC,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;oBACxD,OAAO,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;gBAC5C,CAAC;aACF,CAAC,CAAC;YACH,SAAS;QACX,CAAC;QACD,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;YACtB,WAAW,EAAE,IAAI,CAAC,WAAW;YAC7B,mGAAmG;YACnG,IAAI,EAAE,CAAC,IAAI,CAAC,MAAM,IAAI,EAAE,CAA0B;YAClD,KAAK,CAAC,OAAO,CAAC,IAAa;gBACzB,MAAM,CAAC,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,CAAC,IAAI,IAAI,EAAE,CAAQ,CAAC,CAAC;gBAC7D,OAAO,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;YAC5C,CAAC;SACF,CAAC,CAAC;IACL,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cotal-ai/connector-opencode",
3
- "version": "0.1.1",
3
+ "version": "0.3.0",
4
4
  "license": "Apache-2.0",
5
5
  "repository": {
6
6
  "type": "git",
@@ -17,19 +17,19 @@
17
17
  }
18
18
  },
19
19
  "dependencies": {
20
- "@cotal-ai/connector-core": "0.1.3"
20
+ "@cotal-ai/connector-core": "0.3.0"
21
21
  },
22
22
  "peerDependencies": {
23
+ "@cotal-ai/core": ">=0.1.0",
23
24
  "@opencode-ai/plugin": "^1.16.2",
24
- "@opencode-ai/sdk": "^1.16.2",
25
- "@cotal-ai/core": "0.1.2"
25
+ "@opencode-ai/sdk": "^1.16.2"
26
26
  },
27
27
  "devDependencies": {
28
28
  "@opencode-ai/plugin": "^1.16.2",
29
29
  "@opencode-ai/sdk": "^1.16.2",
30
30
  "esbuild": "^0.28.0",
31
31
  "tsx": "^4.22.4",
32
- "@cotal-ai/core": "0.1.2"
32
+ "@cotal-ai/core": "0.3.0"
33
33
  },
34
34
  "files": [
35
35
  "dist"