cotal-ai 0.96.1 → 0.97.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/daemon/register.js +4 -4
- package/dist/daemon/service.js +41 -10
- package/package.json +18 -18
- package/seeded-connectors/claude/dist/mcp.cjs +214 -211
- package/seeded-connectors/claude/package.json +1 -1
- package/seeded-connectors/codex/dist/host.js +214 -211
- package/seeded-connectors/codex/package.json +1 -1
- package/seeded-connectors/hermes/dist/launch.js +214 -211
- package/seeded-connectors/hermes/package.json +1 -1
- package/seeded-connectors/hermes/plugin/cotal/_sidecar/standalone.cjs +214 -211
- package/seeded-connectors/jcode/dist/host.js +214 -211
- package/seeded-connectors/jcode/dist/mcp.js +24 -21
- package/seeded-connectors/jcode/package.json +1 -1
- package/seeded-connectors/opencode/dist/plugin/index.js +214 -211
- package/seeded-connectors/opencode/package.json +1 -1
- package/seeded-connectors/pi/dist/index.js +5 -5
- package/seeded-connectors/pi/dist/standalone.js +214 -211
- package/seeded-connectors/pi/package.json +1 -1
- package/seeded-connectors/web/package.json +1 -1
package/dist/daemon/register.js
CHANGED
|
@@ -21,12 +21,12 @@ import { join } from "node:path";
|
|
|
21
21
|
import { contractDigest, resolveAuthProvider, ServiceAuthorityTransportError, singleDocumentClosure, VOID_SCHEMA_DIGEST } from "@cotal-ai/core";
|
|
22
22
|
import { claimIdentityRecord, findMesh, homeCotalDir, spaceSegment, userAuthStateDir, workspaceSecretStore } from "@cotal-ai/workspace";
|
|
23
23
|
import { connectCheck, DAEMON_ENDPOINT } from "./connect.js";
|
|
24
|
-
/** The daemon's
|
|
25
|
-
* It is ephemeral, untargeted and ungoverned, the
|
|
24
|
+
/** The daemon's existing void liveness contract. It reports no machine metadata or vitals.
|
|
25
|
+
* It is ephemeral, untargeted and ungoverned, the shape the service door admits. */
|
|
26
26
|
const CLUSTER = { urn: DAEMON_ENDPOINT, revision: 1, attributes: [], events: [],
|
|
27
27
|
commands: [{ name: "machine-status", class: "ephemeral", targeted: false, capability: "read", inputDigest: VOID_SCHEMA_DIGEST, outputDigest: VOID_SCHEMA_DIGEST }] };
|
|
28
28
|
const closure = singleDocumentClosure(CLUSTER);
|
|
29
|
-
const
|
|
29
|
+
export const DAEMON_REGISTRATION = { clusterDigests: [closure.closureDigest], contractArtifacts: [closure.manifest, CLUSTER] };
|
|
30
30
|
const KIND = "cotal-daemon-register-request";
|
|
31
31
|
export function daemonRegisterFile(space, home = homeCotalDir()) {
|
|
32
32
|
return join(home, "daemon", spaceSegment(space), "register-request.json");
|
|
@@ -92,7 +92,7 @@ async function sendRegister(space, home) {
|
|
|
92
92
|
const base = {
|
|
93
93
|
v: 1, kind: "service-endpoint-authority", operation: "register", space,
|
|
94
94
|
accountPublicKey: ready.accountPublicKey, endpoint: ready.endpoint, instanceId: ready.instanceId,
|
|
95
|
-
registration:
|
|
95
|
+
registration: DAEMON_REGISTRATION, expected: { state: "unregistered" },
|
|
96
96
|
};
|
|
97
97
|
const bodyDigest = contractDigest(base);
|
|
98
98
|
const record = claimIdentityRecord(daemonRegisterFile(space, home), "daemon register request", parseRecord(space), () => ({
|
package/dist/daemon/service.js
CHANGED
|
@@ -17,16 +17,18 @@
|
|
|
17
17
|
* or close). Either going down withdraws `connected` at once, as `connecting`; it is claimed again
|
|
18
18
|
* only after the broker is back and the space answers a fresh `ready`.
|
|
19
19
|
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
20
|
+
* The stock guest seam verifies each pulled credential against the registered authority's issuer
|
|
21
|
+
* and keys and this daemon's embedded closure. Each opened transport binds the existing void
|
|
22
|
+
* `machine-status` responder before ready. Its public descriptor includes the endpoint, derived
|
|
23
|
+
* owner token and command schemas; broker caller grants still control invoke access. It reports no vitals or machine metadata. No token, proof
|
|
24
|
+
* or provider text leaves this module; every message is fixed text.
|
|
23
25
|
*/
|
|
24
26
|
import { join } from "node:path";
|
|
25
27
|
import { existsSync } from "node:fs";
|
|
26
28
|
import { randomBytes } from "node:crypto";
|
|
27
|
-
import { CotalEndpoint, resolveAuthProvider, ServiceAuthorityTransportError, serviceWitnessDigest, } from "@cotal-ai/core";
|
|
29
|
+
import { CotalEndpoint, authorizeGuestServeGrant, compileContract, resolveAuthProvider, serveAuthenticityOf, serveEndpoint, ServiceAuthorityTransportError, serviceWitnessDigest, VOID_SCHEMA, } from "@cotal-ai/core";
|
|
28
30
|
import { FsSecretStore, findMesh, homeCotalDir, spaceSegment, userAuthStateDir, workspaceSecretStore } from "@cotal-ai/workspace";
|
|
29
|
-
import { daemonRegisterFile, daemonWitness } from "./register.js";
|
|
31
|
+
import { DAEMON_REGISTRATION, daemonRegisterFile, daemonWitness } from "./register.js";
|
|
30
32
|
const SENTENCE = {
|
|
31
33
|
"not-requested": "this daemon has not requested registration with this space; run `cotal daemon register --space <s>` first",
|
|
32
34
|
"not-registered": "this space is not registered on this machine; add it with `cotal meshes add`",
|
|
@@ -114,7 +116,11 @@ export function createServiceConnections(home = homeCotalDir()) {
|
|
|
114
116
|
l.endpoint = undefined;
|
|
115
117
|
l.source = undefined;
|
|
116
118
|
l.brokerUp = false;
|
|
119
|
+
l.flush = undefined;
|
|
120
|
+
const drains = [...l.serving].map((handle) => handle.stop().catch(() => { }));
|
|
117
121
|
await ep?.stop().catch(() => { });
|
|
122
|
+
await Promise.all(drains);
|
|
123
|
+
l.serving.clear();
|
|
118
124
|
await src?.close().catch(() => { });
|
|
119
125
|
})();
|
|
120
126
|
await l.closing;
|
|
@@ -138,6 +144,12 @@ export function createServiceConnections(home = homeCotalDir()) {
|
|
|
138
144
|
* one persisted ready request per witness. Sets `connected` only if the broker is still up. */
|
|
139
145
|
async function ready(l, space, witness, store, dir) {
|
|
140
146
|
const provider = resolveAuthProvider();
|
|
147
|
+
const flush = l.flush;
|
|
148
|
+
if (!flush) {
|
|
149
|
+
l.state = "unavailable";
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
await flush();
|
|
141
153
|
const requestId = await readyRequestId(store, witness);
|
|
142
154
|
if (requestId === undefined) {
|
|
143
155
|
l.state = "unavailable";
|
|
@@ -162,7 +174,7 @@ export function createServiceConnections(home = homeCotalDir()) {
|
|
|
162
174
|
return;
|
|
163
175
|
}
|
|
164
176
|
if (answer.state === "ready") {
|
|
165
|
-
l.state = l.brokerUp && l.endpoint ? "connected" : "connecting";
|
|
177
|
+
l.state = l.brokerUp && l.endpoint && l.flush === flush && l.serving.size > 0 ? "connected" : "connecting";
|
|
166
178
|
return;
|
|
167
179
|
}
|
|
168
180
|
if (answer.state === "denied" && answer.reason === "rate-limited") {
|
|
@@ -217,7 +229,7 @@ export function createServiceConnections(home = homeCotalDir()) {
|
|
|
217
229
|
return result(space);
|
|
218
230
|
if (current)
|
|
219
231
|
await teardown(current);
|
|
220
|
-
const l = current ?? { state: "connecting", brokerUp: false };
|
|
232
|
+
const l = current ?? { state: "connecting", brokerUp: false, serving: new Set() };
|
|
221
233
|
l.state = "connecting";
|
|
222
234
|
l.reason = undefined;
|
|
223
235
|
live.set(space, l);
|
|
@@ -238,7 +250,7 @@ export function createServiceConnections(home = homeCotalDir()) {
|
|
|
238
250
|
const witness = w.witness;
|
|
239
251
|
l.instanceId = witness.instanceId;
|
|
240
252
|
const provider = resolveAuthProvider();
|
|
241
|
-
if (!provider.serviceEndpointRenewal || !provider.serviceEndpointAuthority) {
|
|
253
|
+
if (!provider.serviceEndpointRenewal || !provider.serviceEndpointAuthority || !provider.serviceEndpointInfo) {
|
|
242
254
|
l.state = "unsupported";
|
|
243
255
|
return result(space);
|
|
244
256
|
}
|
|
@@ -246,8 +258,18 @@ export function createServiceConnections(home = homeCotalDir()) {
|
|
|
246
258
|
const dir = userAuthStateDir(entry.root, space, { readOnly: true });
|
|
247
259
|
const source = provider.serviceEndpointRenewal({ store, dir, witness });
|
|
248
260
|
l.source = source;
|
|
261
|
+
let grant;
|
|
262
|
+
const pull = async () => {
|
|
263
|
+
const credential = await source.credential();
|
|
264
|
+
const info = await provider.serviceEndpointInfo({ store, dir, space });
|
|
265
|
+
if (info.accountPublicKey !== witness.accountPublicKey)
|
|
266
|
+
throw new Error("the service authority account changed");
|
|
267
|
+
grant = await authorizeGuestServeGrant({ accountPublicKey: witness.accountPublicKey, result: credential,
|
|
268
|
+
registration: DAEMON_REGISTRATION, authenticity: serveAuthenticityOf(info) });
|
|
269
|
+
return credential.accessBearer;
|
|
270
|
+
};
|
|
249
271
|
try {
|
|
250
|
-
await
|
|
272
|
+
await pull();
|
|
251
273
|
}
|
|
252
274
|
catch {
|
|
253
275
|
sourceFailed(l);
|
|
@@ -264,11 +286,20 @@ export function createServiceConnections(home = homeCotalDir()) {
|
|
|
264
286
|
const endpoint = new CotalEndpoint({
|
|
265
287
|
space, servers: entry.server, sentinelCreds: source.sentinelCreds,
|
|
266
288
|
bearer: async () => { try {
|
|
267
|
-
return await
|
|
289
|
+
return await pull();
|
|
268
290
|
}
|
|
269
291
|
finally {
|
|
270
292
|
onEnd();
|
|
271
293
|
} },
|
|
294
|
+
onConnection: (nc) => {
|
|
295
|
+
if (l.endpoint !== endpoint)
|
|
296
|
+
return;
|
|
297
|
+
const contract = compileContract({ root: VOID_SCHEMA });
|
|
298
|
+
const handle = serveEndpoint(nc, space, grant, [{ command: "machine-status", contract: { input: contract, output: contract }, handler: () => null }], { public: true });
|
|
299
|
+
l.serving.add(handle);
|
|
300
|
+
l.flush = () => nc.flush();
|
|
301
|
+
void nc.closed().then(() => handle.stop()).catch(() => { }).finally(() => { l.serving.delete(handle); });
|
|
302
|
+
},
|
|
272
303
|
card: { name: "cotal-daemon", kind: "endpoint", owner: witness.principal.owner, actor: witness.principal.actor },
|
|
273
304
|
channels: [], registerPresence: false, watchPresence: false, watchChannels: false, consume: false,
|
|
274
305
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cotal-ai",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.97.0",
|
|
4
4
|
"description": "Cotal — lateral agent coordination over NATS. Run `npx cotal-ai` for the CLI.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"keywords": [
|
|
@@ -33,26 +33,26 @@
|
|
|
33
33
|
"node": ">=22"
|
|
34
34
|
},
|
|
35
35
|
"dependencies": {
|
|
36
|
-
"@cotal-ai/auth": "0.
|
|
37
|
-
"@cotal-ai/cli": "0.
|
|
38
|
-
"@cotal-ai/connector-core": "0.
|
|
39
|
-
"@cotal-ai/core": "0.
|
|
40
|
-
"@cotal-ai/delivery": "0.
|
|
41
|
-
"@cotal-ai/manager": "0.
|
|
42
|
-
"@cotal-ai/runtime": "0.
|
|
43
|
-
"@cotal-ai/seat": "0.
|
|
44
|
-
"@cotal-ai/workspace": "0.
|
|
36
|
+
"@cotal-ai/auth": "0.97.0",
|
|
37
|
+
"@cotal-ai/cli": "0.97.0",
|
|
38
|
+
"@cotal-ai/connector-core": "0.97.0",
|
|
39
|
+
"@cotal-ai/core": "0.97.0",
|
|
40
|
+
"@cotal-ai/delivery": "0.97.0",
|
|
41
|
+
"@cotal-ai/manager": "0.97.0",
|
|
42
|
+
"@cotal-ai/runtime": "0.97.0",
|
|
43
|
+
"@cotal-ai/seat": "0.97.0",
|
|
44
|
+
"@cotal-ai/workspace": "0.97.0"
|
|
45
45
|
},
|
|
46
46
|
"devDependencies": {
|
|
47
|
-
"@cotal-ai/connector-claude-code": "0.
|
|
48
|
-
"@cotal-ai/connector-codex": "0.
|
|
49
|
-
"@cotal-ai/connector-hermes": "0.
|
|
50
|
-
"@cotal-ai/connector-jcode": "0.
|
|
51
|
-
"@cotal-ai/connector-opencode": "0.
|
|
52
|
-
"@cotal-ai/linear": "0.
|
|
53
|
-
"@cotal-ai/pi": "0.
|
|
47
|
+
"@cotal-ai/connector-claude-code": "0.97.0",
|
|
48
|
+
"@cotal-ai/connector-codex": "0.97.0",
|
|
49
|
+
"@cotal-ai/connector-hermes": "0.97.0",
|
|
50
|
+
"@cotal-ai/connector-jcode": "0.97.0",
|
|
51
|
+
"@cotal-ai/connector-opencode": "0.97.0",
|
|
52
|
+
"@cotal-ai/linear": "0.97.0",
|
|
53
|
+
"@cotal-ai/pi": "0.97.0",
|
|
54
54
|
"@cotal-ai/smoke-kit": "0.0.0",
|
|
55
|
-
"@cotal-ai/web": "0.
|
|
55
|
+
"@cotal-ai/web": "0.97.0",
|
|
56
56
|
"@nats-io/jetstream": "^3.4.0",
|
|
57
57
|
"@nats-io/transport-node": "^3.4.0",
|
|
58
58
|
"typescript": "^5.9.3"
|