@cotal-ai/connector-opencode 0.55.0 → 0.56.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.
- package/dist/extension.d.ts.map +1 -1
- package/dist/index.js +41 -20
- package/dist/opencode-line.d.ts +5 -0
- package/dist/opencode-line.d.ts.map +1 -0
- package/dist/opencode2-types.d.ts +75 -0
- package/dist/opencode2-types.d.ts.map +1 -0
- package/dist/{plugin.bundle.js → plugin/index.js} +456 -63
- package/dist/plugin.d.ts +23 -0
- package/dist/plugin.d.ts.map +1 -1
- package/dist/plugin.entry.d.ts +7 -5
- package/dist/plugin.entry.d.ts.map +1 -1
- package/dist/plugin2.d.ts +12 -0
- package/dist/plugin2.d.ts.map +1 -0
- package/dist/serve.js +18 -5
- package/dist/tools.d.ts +9 -0
- package/dist/tools.d.ts.map +1 -1
- package/package.json +6 -5
package/dist/plugin.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { MeshAgent } from "@cotal-ai/connector-core";
|
|
1
2
|
import type { Plugin } from "@opencode-ai/plugin";
|
|
2
3
|
/** The machine-stable half of the retirement line. The suite asserts on THIS, never on the sentence
|
|
3
4
|
* around it: a guard keyed on human prose dies the first time someone rewords a log message, and it
|
|
@@ -13,6 +14,28 @@ export declare const WAL_REAPED = "opencode-wal-reaped";
|
|
|
13
14
|
* This is the token the reaping cell grades, because the lifetime is the claim and the deletion is
|
|
14
15
|
* only the easy half of it. */
|
|
15
16
|
export declare const WAL_KEPT = "opencode-wal-kept";
|
|
17
|
+
/** The shared shape of a pre-join model refusal: `"<model>: <detail>. Refusing before join"`.
|
|
18
|
+
* Exported so the 2.x adapter's own check (a different route, `/api/model`) produces the same
|
|
19
|
+
* sentence shape as `verifyServerModel` below without duplicating it. */
|
|
20
|
+
export declare function modelRefusalSentence(selectedModel: string, detail: string): string;
|
|
16
21
|
export declare function verifyServerModel(serverUrl: string, serverAuth: string, selectedModel: string): Promise<void>;
|
|
22
|
+
/**
|
|
23
|
+
* Races `work` against a `ms` timeout so a stuck settle is abandoned out loud rather than waited on
|
|
24
|
+
* forever (see the note at its call sites in `quiesce`). Exported: the 2.x adapter's own teardown
|
|
25
|
+
* uses the same bounded-settle shape rather than a second copy of it.
|
|
26
|
+
*/
|
|
27
|
+
declare function settleWithin(work: Promise<unknown> | undefined, ms: number, what: string): Promise<boolean>;
|
|
28
|
+
export { settleWithin };
|
|
29
|
+
/**
|
|
30
|
+
* The buffered-inbox + pending-run-turn composition that goes out ahead of a native prompt. Shared
|
|
31
|
+
* by the 1.x text-part mutator (`injectIntoPrompt` below) and the 2.x `session.hook("prompt")`
|
|
32
|
+
* mutator, so the two callers cannot drift on what "inject" means. Returns `undefined` when there is
|
|
33
|
+
* nothing to prepend.
|
|
34
|
+
*/
|
|
35
|
+
export declare function computeInjection(agent: MeshAgent): {
|
|
36
|
+
prefix: string;
|
|
37
|
+
surfacedIds: string[];
|
|
38
|
+
turnIds: string[];
|
|
39
|
+
} | undefined;
|
|
17
40
|
export declare const cotal: Plugin;
|
|
18
41
|
//# sourceMappingURL=plugin.d.ts.map
|
package/dist/plugin.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAuCA,OAAO,EAGL,SAAS,EAoBV,MAAM,0BAA0B,CAAC;AAMlC,OAAO,KAAK,EAAE,MAAM,EAAyB,MAAM,qBAAqB,CAAC;AAgBzE;;;0EAG0E;AAC1E,eAAO,MAAM,eAAe,6BAA6B,CAAC;AAC1D,gGAAgG;AAChG,eAAO,MAAM,gBAAgB,8BAA8B,CAAC;AAC5D;iEACiE;AACjE,eAAO,MAAM,UAAU,wBAAwB,CAAC;AAChD;;gCAEgC;AAChC,eAAO,MAAM,QAAQ,sBAAsB,CAAC;AAC5C;;0EAE0E;AAC1E,wBAAgB,oBAAoB,CAAC,aAAa,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAElF;AACD,wBAAsB,iBAAiB,CAAC,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAYnH;AA8BD;;;;GAIG;AACH,iBAAe,YAAY,CAAC,IAAI,EAAE,OAAO,CAAC,OAAO,CAAC,GAAG,SAAS,EAAE,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAqB1G;AACD,OAAO,EAAE,YAAY,EAAE,CAAC;AAExB;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,SAAS,GAAG;IAClD,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB,GAAG,SAAS,CAQZ;AAED,eAAO,MAAM,KAAK,EAAE,MAixCnB,CAAC"}
|
package/dist/plugin.entry.d.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
import { setupCotal } from "./plugin2.js";
|
|
2
|
+
declare const _default: {
|
|
3
|
+
id: string;
|
|
4
|
+
server: import("@opencode-ai/plugin").Plugin;
|
|
5
|
+
setup: typeof setupCotal;
|
|
6
|
+
};
|
|
7
|
+
export default _default;
|
|
6
8
|
//# sourceMappingURL=plugin.entry.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin.entry.d.ts","sourceRoot":"","sources":["../src/plugin.entry.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"plugin.entry.d.ts","sourceRoot":"","sources":["../src/plugin.entry.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;;;;;;AAC1C,wBAAiE"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { OpenCode2Context } from "./opencode2-types.js";
|
|
2
|
+
/** 2.x model check: `GET /api/model` lists the configured model directly (no `/provider.all`
|
|
3
|
+
* nesting to walk, unlike 1.x's `verifyServerModel`). Same refusal sentence shape, different
|
|
4
|
+
* route and body — measured in fx105/measurements.md (routes). The server answers `/api/model`
|
|
5
|
+
* with an empty listing for up to about a second after the location boot its first `/api/config`
|
|
6
|
+
* triggers (fx105/brief-g.md measurement), so an empty listing is polled every 200 ms until the
|
|
7
|
+
* provider appears rather than refused on the first read. The wait is bounded: a server that
|
|
8
|
+
* never lists anything within the deadline is a real refusal, not a hang. */
|
|
9
|
+
export declare const MODEL_LIST_SETTLE_MS = 10000;
|
|
10
|
+
/** The 2.x `setup(context)` entry point. */
|
|
11
|
+
export declare function setupCotal(ctx: OpenCode2Context): Promise<(() => Promise<void>) | void>;
|
|
12
|
+
//# sourceMappingURL=plugin2.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin2.d.ts","sourceRoot":"","sources":["../src/plugin2.ts"],"names":[],"mappings":"AA2BA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAiB7D;;;;;;8EAM8E;AAC9E,eAAO,MAAM,oBAAoB,QAAS,CAAC;AAoC3C,4CAA4C;AAC5C,wBAAsB,UAAU,CAAC,GAAG,EAAE,gBAAgB,GAAG,OAAO,CAAC,CAAC,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,CAmR7F"}
|
package/dist/serve.js
CHANGED
|
@@ -5,6 +5,18 @@ import { once } from "node:events";
|
|
|
5
5
|
import { randomBytes } from "node:crypto";
|
|
6
6
|
import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
|
7
7
|
import { delimiter, join } from "node:path";
|
|
8
|
+
|
|
9
|
+
// src/opencode-line.ts
|
|
10
|
+
function opencodeLine(raw, bin) {
|
|
11
|
+
const m = raw.match(/(?:^|v)(\d+)\.\d+/);
|
|
12
|
+
const major = m ? Number(m[1]) : NaN;
|
|
13
|
+
if (major === 1 || major === 2) return major;
|
|
14
|
+
throw new Error(
|
|
15
|
+
`opencode connector: unsupported OpenCode version "${raw}" from ${bin}; this connector supports the 1.x (opencode-ai) and 2.x (@opencode/cli) lines`
|
|
16
|
+
);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// src/serve.ts
|
|
8
20
|
function resolveOpencodeBin() {
|
|
9
21
|
const override = process.env.COTAL_OPENCODE_BIN?.trim() || process.env.COTAL_OPENCODE_RESOLVED_BIN?.trim();
|
|
10
22
|
if (override) return override;
|
|
@@ -84,11 +96,14 @@ async function main() {
|
|
|
84
96
|
throw new Error(`agent "${name}" is already running (opencode serve pid ${pid}) \u2014 kill it first`);
|
|
85
97
|
rmSync(pidFile);
|
|
86
98
|
}
|
|
99
|
+
const versionRaw = execFileSync(BIN, ["--version"], { encoding: "utf8" }).trim();
|
|
100
|
+
const line = opencodeLine(versionRaw, BIN);
|
|
87
101
|
mkdirSync(agentHome, { recursive: true });
|
|
88
102
|
const serve = spawn(BIN, ["serve", "--hostname", "127.0.0.1", "--port", port], {
|
|
89
103
|
env: {
|
|
90
104
|
...process.env,
|
|
91
105
|
COTAL_OPENCODE_SERVER_URL: url,
|
|
106
|
+
COTAL_OPENCODE_LINE: String(line),
|
|
92
107
|
OPENCODE_SERVER_USERNAME: USERNAME,
|
|
93
108
|
OPENCODE_SERVER_PASSWORD: SECRET,
|
|
94
109
|
OPENCODE_DB: dbPath
|
|
@@ -116,10 +131,11 @@ async function main() {
|
|
|
116
131
|
if (!attached) process.exit(code ?? (signal ? 1 : 0));
|
|
117
132
|
});
|
|
118
133
|
const auth = `Basic ${Buffer.from(`${USERNAME}:${SECRET}`).toString("base64")}`;
|
|
134
|
+
const pokePath = line === 2 ? "/api/config" : "/session";
|
|
119
135
|
void (async () => {
|
|
120
136
|
for (let i = 0; i < 300 && !sessionId; i++) {
|
|
121
137
|
try {
|
|
122
|
-
await fetch(`${url}
|
|
138
|
+
await fetch(`${url}${pokePath}`, { headers: { authorization: auth }, signal: AbortSignal.timeout(1500) });
|
|
123
139
|
} catch {
|
|
124
140
|
}
|
|
125
141
|
await new Promise((r) => setTimeout(r, 200));
|
|
@@ -154,10 +170,7 @@ async function main() {
|
|
|
154
170
|
delete tuiEnv.OPENCODE_CONFIG_CONTENT;
|
|
155
171
|
for (const k of Object.keys(tuiEnv)) if (k.startsWith("COTAL_")) delete tuiEnv[k];
|
|
156
172
|
attached = true;
|
|
157
|
-
const tui = spawn(BIN, ["attach", url, "--session", id, "--password", SECRET], {
|
|
158
|
-
env: tuiEnv,
|
|
159
|
-
stdio: "inherit"
|
|
160
|
-
});
|
|
173
|
+
const tui = line === 2 ? spawn(BIN, ["--server", url, "--session", id], { env: tuiEnv, stdio: "inherit" }) : spawn(BIN, ["attach", url, "--session", id, "--password", SECRET], { env: tuiEnv, stdio: "inherit" });
|
|
161
174
|
for (const sig of ["SIGINT", "SIGTERM"])
|
|
162
175
|
process.on(sig, () => {
|
|
163
176
|
tui.kill(sig);
|
package/dist/tools.d.ts
CHANGED
|
@@ -15,6 +15,15 @@
|
|
|
15
15
|
*/
|
|
16
16
|
import type { ToolDefinition } from "@opencode-ai/plugin";
|
|
17
17
|
import { type MeshAgent, type AgentConfig } from "@cotal-ai/connector-core";
|
|
18
|
+
import type { OpenCode2ToolEditor } from "./opencode2-types.js";
|
|
18
19
|
/** Build the cotal_* tool map wired to one mesh agent, rendered from the shared specs. */
|
|
19
20
|
export declare function buildCotalTools(agent: MeshAgent, config: AgentConfig): Record<string, ToolDefinition>;
|
|
21
|
+
/** Build the cotal_* tool list for OpenCode 2.x's `ctx.tool.transform(ed => ed.add(...))`, from
|
|
22
|
+
* the SAME shared specs {@link buildCotalTools} renders for 1.x. 2.x's `Tool.Info.input` accepts
|
|
23
|
+
* a zod 4 object directly (a StandardSchema — measured, `fx105/measurements.md`), so the closed
|
|
24
|
+
* schema goes across unmodified; there is no 1.x-style raw-shape flattening needed here. The
|
|
25
|
+
* closed-object refusal at dispatch is the same guard as {@link buildCotalTools} keeps: this host
|
|
26
|
+
* also hands `execute` the caller's object UNVALIDATED, so a stray `owner`/`actor` is refused by
|
|
27
|
+
* name here too, never silently reaching `run`. */
|
|
28
|
+
export declare function buildCotalTools2(agent: MeshAgent, config: AgentConfig): Parameters<OpenCode2ToolEditor["add"]>[0][];
|
|
20
29
|
//# sourceMappingURL=tools.d.ts.map
|
package/dist/tools.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,EAAgD,KAAK,SAAS,EAAE,KAAK,WAAW,EAAE,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,EAAgD,KAAK,SAAS,EAAE,KAAK,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAC1H,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAEhE,0FAA0F;AAC1F,wBAAgB,eAAe,CAAC,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,WAAW,GAAG,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CA2CrG;AAED;;;;;;oDAMoD;AACpD,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,WAAW,GAAG,UAAU,CAAC,mBAAmB,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAmCnH"}
|
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.
|
|
4
|
+
"version": "0.56.0",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
@@ -21,11 +21,12 @@
|
|
|
21
21
|
"@cotal-ai/core": ">=0.1.0"
|
|
22
22
|
},
|
|
23
23
|
"devDependencies": {
|
|
24
|
+
"@nats-io/transport-node": "^3.4.0",
|
|
24
25
|
"@opencode-ai/plugin": "^1.16.2",
|
|
25
26
|
"esbuild": "^0.28.0",
|
|
26
27
|
"tsx": "^4.22.4",
|
|
27
|
-
"@cotal-ai/connector-core": "0.
|
|
28
|
-
"@cotal-ai/core": "0.
|
|
28
|
+
"@cotal-ai/connector-core": "0.56.0",
|
|
29
|
+
"@cotal-ai/core": "0.56.0",
|
|
29
30
|
"@cotal-ai/smoke-kit": "0.0.0"
|
|
30
31
|
},
|
|
31
32
|
"files": [
|
|
@@ -36,8 +37,8 @@
|
|
|
36
37
|
},
|
|
37
38
|
"scripts": {
|
|
38
39
|
"test": "tsx smoke/tool-input-closed.smoke.ts",
|
|
39
|
-
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
40
|
+
"typecheck": "tsc -p tsconfig.json --noEmit && tsc -p tsconfig.smoke.json",
|
|
40
41
|
"build": "node -e \"require('node:fs').rmSync('dist',{recursive:true,force:true})\" && tsc -p tsconfig.json --emitDeclarationOnly && pnpm run bundle",
|
|
41
|
-
"bundle": "esbuild src/index.ts --bundle --platform=node --format=esm --target=node20 --outfile=dist/index.js --external:@cotal-ai/core && esbuild src/plugin.entry.ts --bundle --platform=node --format=esm --target=node20 --outfile=dist/plugin.
|
|
42
|
+
"bundle": "esbuild src/index.ts --bundle --platform=node --format=esm --target=node20 --outfile=dist/index.js --external:@cotal-ai/core && esbuild src/plugin.entry.ts --bundle --platform=node --format=esm --target=node20 --outfile=dist/plugin/index.js && esbuild src/serve.ts --bundle --platform=node --format=esm --target=node20 --outfile=dist/serve.js"
|
|
42
43
|
}
|
|
43
44
|
}
|