@cotal-ai/pi 0.28.0 → 0.28.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +1 -1
- package/dist/standalone.js +375 -364
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -15963,7 +15963,7 @@ import { isConcreteChannel as isConcreteChannel3, channelInAllow as channelInAll
|
|
|
15963
15963
|
|
|
15964
15964
|
// ../connector-core/dist/docs-bundle.generated.js
|
|
15965
15965
|
var DOCS_BUNDLE = {
|
|
15966
|
-
"version": "0.28.
|
|
15966
|
+
"version": "0.28.1",
|
|
15967
15967
|
"generatedFrom": "docs/*.md + SPEC.md + spec/cotal-lang.md + spec/cotal.schema.json",
|
|
15968
15968
|
"pages": [
|
|
15969
15969
|
{
|
package/dist/standalone.js
CHANGED
|
@@ -13615,11 +13615,11 @@ var require_connect = __commonJS({
|
|
|
13615
13615
|
"../../node_modules/.pnpm/@nats-io+transport-node@3.4.0/node_modules/@nats-io/transport-node/lib/connect.js"(exports) {
|
|
13616
13616
|
"use strict";
|
|
13617
13617
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13618
|
-
exports.connect =
|
|
13618
|
+
exports.connect = connect7;
|
|
13619
13619
|
var node_transport_1 = require_node_transport();
|
|
13620
13620
|
var nats_base_client_1 = require_nats_base_client();
|
|
13621
13621
|
var nats_base_client_2 = require_nats_base_client();
|
|
13622
|
-
function
|
|
13622
|
+
function connect7(opts = {}) {
|
|
13623
13623
|
if ((0, nats_base_client_2.hasWsProtocol)(opts)) {
|
|
13624
13624
|
return Promise.reject(nats_base_client_2.errors.InvalidArgumentError.format(`servers`, `node client doesn't support websockets, use the 'wsconnect' function instead`));
|
|
13625
13625
|
}
|
|
@@ -35856,49 +35856,33 @@ var SYS_LIMITS = { ...BASE_LIMITS, mem_storage: 0, disk_storage: 0 };
|
|
|
35856
35856
|
var import_nkeys4 = __toESM(require_mod2(), 1);
|
|
35857
35857
|
|
|
35858
35858
|
// ../../packages/core/dist/channels.js
|
|
35859
|
-
var
|
|
35860
|
-
var
|
|
35861
|
-
|
|
35862
|
-
|
|
35863
|
-
|
|
35864
|
-
|
|
35865
|
-
|
|
35866
|
-
|
|
35867
|
-
|
|
35868
|
-
|
|
35869
|
-
|
|
35870
|
-
|
|
35871
|
-
|
|
35872
|
-
|
|
35873
|
-
|
|
35874
|
-
|
|
35875
|
-
|
|
35876
|
-
function effectiveDeliveryClass(cfg, defaults) {
|
|
35877
|
-
return cfg?.deliveryClass ?? defaults?.deliveryClass ?? "durable";
|
|
35878
|
-
}
|
|
35879
|
-
async function openChannelRegistry(nc, space, opts = {}) {
|
|
35880
|
-
const kvm = new import_kv4.Kvm(nc);
|
|
35881
|
-
return opts.create ? kvm.create(channelBucket(space)) : kvm.open(channelBucket(space));
|
|
35882
|
-
}
|
|
35883
|
-
async function readChannelConfig(kv, channel) {
|
|
35884
|
-
return decode2(kv, channel);
|
|
35885
|
-
}
|
|
35886
|
-
async function readChannelDefaults(kv) {
|
|
35887
|
-
return decode2(kv, CHANNEL_DEFAULTS_KEY);
|
|
35888
|
-
}
|
|
35889
|
-
async function decode2(kv, key) {
|
|
35890
|
-
const e = await kv.get(key);
|
|
35891
|
-
if (!e || e.operation === "DEL" || e.operation === "PURGE")
|
|
35892
|
-
return void 0;
|
|
35893
|
-
try {
|
|
35894
|
-
return e.json();
|
|
35895
|
-
} catch {
|
|
35896
|
-
return void 0;
|
|
35897
|
-
}
|
|
35859
|
+
var import_kv7 = __toESM(require_mod6(), 1);
|
|
35860
|
+
var import_transport_node15 = __toESM(require_transport_node(), 1);
|
|
35861
|
+
|
|
35862
|
+
// ../../packages/core/dist/endpoint.js
|
|
35863
|
+
var import_transport_node14 = __toESM(require_transport_node(), 1);
|
|
35864
|
+
var import_nats_core = __toESM(require_mod3(), 1);
|
|
35865
|
+
import { EventEmitter } from "node:events";
|
|
35866
|
+
import { randomUUID } from "node:crypto";
|
|
35867
|
+
import { createConnection } from "node:net";
|
|
35868
|
+
|
|
35869
|
+
// ../../packages/core/dist/artifact.js
|
|
35870
|
+
var ARTIFACT_PART_KIND = "artifact";
|
|
35871
|
+
function isArtifactPart(value) {
|
|
35872
|
+
if (!value || typeof value !== "object")
|
|
35873
|
+
return false;
|
|
35874
|
+
const p = value;
|
|
35875
|
+
return p.kind === ARTIFACT_PART_KIND && typeof p.name === "string" && p.name.length > 0 && typeof p.mediaType === "string" && p.mediaType.length > 0 && typeof p.digest === "string" && isContractDigest(p.digest) && typeof p.size === "number" && Number.isSafeInteger(p.size) && p.size >= 0;
|
|
35898
35876
|
}
|
|
35899
35877
|
|
|
35878
|
+
// ../../packages/core/dist/endpoint.js
|
|
35879
|
+
var import_jetstream13 = __toESM(require_mod4(), 1);
|
|
35880
|
+
var import_jetstream14 = __toESM(require_mod4(), 1);
|
|
35881
|
+
var import_kv6 = __toESM(require_mod6(), 1);
|
|
35882
|
+
var import_internal2 = __toESM(require_internal_mod3(), 1);
|
|
35883
|
+
|
|
35900
35884
|
// ../../packages/core/dist/members.js
|
|
35901
|
-
var
|
|
35885
|
+
var import_kv4 = __toESM(require_mod6(), 1);
|
|
35902
35886
|
var StaleMembershipWrite = class extends Error {
|
|
35903
35887
|
constructor(channel, owner, attempted, current) {
|
|
35904
35888
|
super(`stale membership write for ${channel}/${owner}: generation ${attempted} < current ${current}`);
|
|
@@ -35906,7 +35890,7 @@ var StaleMembershipWrite = class extends Error {
|
|
|
35906
35890
|
}
|
|
35907
35891
|
};
|
|
35908
35892
|
async function openMembersRegistry(nc, space, opts = {}) {
|
|
35909
|
-
const kvm = new
|
|
35893
|
+
const kvm = new import_kv4.Kvm(nc);
|
|
35910
35894
|
return opts.create ? kvm.create(membersBucket(space)) : kvm.open(membersBucket(space));
|
|
35911
35895
|
}
|
|
35912
35896
|
async function readMember(kv, channel, owner, lifecycleUid) {
|
|
@@ -36006,312 +35990,14 @@ function durableEligible(rec, seq) {
|
|
|
36006
35990
|
return true;
|
|
36007
35991
|
}
|
|
36008
35992
|
|
|
36009
|
-
// ../../packages/core/dist/membership-feed.js
|
|
36010
|
-
var import_transport_node14 = __toESM(require_transport_node(), 1);
|
|
36011
|
-
var import_kv6 = __toESM(require_mod6(), 1);
|
|
36012
|
-
|
|
36013
|
-
// ../../packages/core/dist/evict.js
|
|
36014
|
-
var import_transport_node15 = __toESM(require_transport_node(), 1);
|
|
36015
|
-
|
|
36016
35993
|
// ../../packages/core/dist/lease.js
|
|
36017
|
-
var
|
|
36018
|
-
var
|
|
35994
|
+
var import_kv5 = __toESM(require_mod6(), 1);
|
|
35995
|
+
var import_transport_node13 = __toESM(require_transport_node(), 1);
|
|
36019
35996
|
async function openDeliveryRegistry(nc, space) {
|
|
36020
|
-
return new
|
|
36021
|
-
}
|
|
36022
|
-
|
|
36023
|
-
// ../../packages/core/dist/agent-file.js
|
|
36024
|
-
import { mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
36025
|
-
var import_yaml = __toESM(require_dist(), 1);
|
|
36026
|
-
function parseFrontmatter(src, path) {
|
|
36027
|
-
let doc;
|
|
36028
|
-
try {
|
|
36029
|
-
doc = (0, import_yaml.parse)(src);
|
|
36030
|
-
} catch (e) {
|
|
36031
|
-
throw new Error(`agent file ${path}: invalid YAML frontmatter; ${e.message}`);
|
|
36032
|
-
}
|
|
36033
|
-
if (doc === null || doc === void 0)
|
|
36034
|
-
return {};
|
|
36035
|
-
if (typeof doc !== "object" || Array.isArray(doc))
|
|
36036
|
-
throw new Error(`agent file ${path}: frontmatter must be a YAML mapping (key: value pairs)`);
|
|
36037
|
-
return doc;
|
|
36038
|
-
}
|
|
36039
|
-
function loadAgentFile(path) {
|
|
36040
|
-
const src = readFileSync(path, "utf8");
|
|
36041
|
-
const m = /^---\n([\s\S]*?)\n---\n?([\s\S]*)$/.exec(src);
|
|
36042
|
-
if (!m)
|
|
36043
|
-
throw new Error(`agent file ${path}: missing "---" frontmatter block`);
|
|
36044
|
-
const fm = parseFrontmatter(m[1], path);
|
|
36045
|
-
const persona = m[2].trim();
|
|
36046
|
-
const str2 = (k) => {
|
|
36047
|
-
const v = fm[k];
|
|
36048
|
-
if (v === void 0 || v === null)
|
|
36049
|
-
return void 0;
|
|
36050
|
-
if (typeof v === "object")
|
|
36051
|
-
throw new Error(`agent file ${path}: "${k}" must be a scalar`);
|
|
36052
|
-
return String(v);
|
|
36053
|
-
};
|
|
36054
|
-
const list = (k) => {
|
|
36055
|
-
const v = fm[k];
|
|
36056
|
-
if (v === void 0 || v === null)
|
|
36057
|
-
return void 0;
|
|
36058
|
-
return (Array.isArray(v) ? v : [v]).map((x) => {
|
|
36059
|
-
if (x === null || typeof x === "object")
|
|
36060
|
-
throw new Error(`agent file ${path}: "${k}" list items must be scalars`);
|
|
36061
|
-
return String(x);
|
|
36062
|
-
});
|
|
36063
|
-
};
|
|
36064
|
-
const name = str2("name");
|
|
36065
|
-
if (!name)
|
|
36066
|
-
throw new Error(`agent file ${path}: "name" is required`);
|
|
36067
|
-
assertValidName(name);
|
|
36068
|
-
const kind = str2("kind");
|
|
36069
|
-
if (kind && kind !== "agent" && kind !== "endpoint")
|
|
36070
|
-
throw new Error(`agent file ${path}: "kind" must be "agent" or "endpoint"`);
|
|
36071
|
-
for (const old of ["channels", "publish"])
|
|
36072
|
-
if (old in fm)
|
|
36073
|
-
throw new Error(`agent file ${path}: "${old}" was renamed - use "subscribe"/"allowSubscribe" (read) and "allowPublish" (post)`);
|
|
36074
|
-
const subscribe = list("subscribe");
|
|
36075
|
-
const allowSubscribe = list("allowSubscribe");
|
|
36076
|
-
const allowPublish = list("allowPublish");
|
|
36077
|
-
const quiet = list("quiet");
|
|
36078
|
-
const muted = list("muted");
|
|
36079
|
-
for (const ch of [...subscribe ?? [], ...allowSubscribe ?? [], ...allowPublish ?? []])
|
|
36080
|
-
try {
|
|
36081
|
-
assertValidChannel(ch);
|
|
36082
|
-
} catch (e) {
|
|
36083
|
-
throw new Error(`agent file ${path}: ${e.message}`);
|
|
36084
|
-
}
|
|
36085
|
-
const effSubscribe = subscribe ?? [];
|
|
36086
|
-
const effAllow = allowSubscribe?.length ? allowSubscribe : effSubscribe;
|
|
36087
|
-
for (const ch of effSubscribe)
|
|
36088
|
-
if (!channelInAllow(effAllow, ch))
|
|
36089
|
-
throw new Error(`agent file ${path}: subscribe channel "${ch}" is not within allowSubscribe [${effAllow.join(", ")}]`);
|
|
36090
|
-
const both = (quiet ?? []).filter((c) => (muted ?? []).includes(c));
|
|
36091
|
-
if (both.length)
|
|
36092
|
-
throw new Error(`agent file ${path}: channel(s) [${both.join(", ")}] are in both quiet and muted - pick one`);
|
|
36093
|
-
for (const [field, chans] of [["quiet", quiet], ["muted", muted]])
|
|
36094
|
-
for (const ch of chans ?? []) {
|
|
36095
|
-
try {
|
|
36096
|
-
assertValidChannel(ch);
|
|
36097
|
-
} catch (e) {
|
|
36098
|
-
throw new Error(`agent file ${path}: ${e.message}`);
|
|
36099
|
-
}
|
|
36100
|
-
if (!isConcreteChannel(ch))
|
|
36101
|
-
throw new Error(`agent file ${path}: ${field} channel "${ch}" must be a concrete channel (no wildcard)`);
|
|
36102
|
-
if (!channelInAllow(effAllow, ch))
|
|
36103
|
-
throw new Error(`agent file ${path}: ${field} channel "${ch}" is not within your read ACL / allowSubscribe [${effAllow.join(", ")}]`);
|
|
36104
|
-
}
|
|
36105
|
-
const launchOptionsRaw = fm["launchOptions"];
|
|
36106
|
-
let launchOptions;
|
|
36107
|
-
if (launchOptionsRaw !== void 0 && launchOptionsRaw !== null) {
|
|
36108
|
-
if (typeof launchOptionsRaw !== "object" || Array.isArray(launchOptionsRaw))
|
|
36109
|
-
throw new Error(`agent file ${path}: "launchOptions" must be a mapping of key: value pairs`);
|
|
36110
|
-
launchOptions = launchOptionsRaw;
|
|
36111
|
-
}
|
|
36112
|
-
const known = /* @__PURE__ */ new Set(["name", "role", "kind", "description", "tags", "subscribe", "allowSubscribe", "allowPublish", "quiet", "muted", "model", "variant", "launchOptions", "capabilities", "owner"]);
|
|
36113
|
-
const meta3 = {};
|
|
36114
|
-
for (const [k, v] of Object.entries(fm))
|
|
36115
|
-
if (!known.has(k) && v !== null && typeof v !== "object")
|
|
36116
|
-
meta3[k] = String(v);
|
|
36117
|
-
return {
|
|
36118
|
-
name,
|
|
36119
|
-
role: str2("role"),
|
|
36120
|
-
kind,
|
|
36121
|
-
description: str2("description"),
|
|
36122
|
-
tags: list("tags"),
|
|
36123
|
-
subscribe,
|
|
36124
|
-
allowSubscribe,
|
|
36125
|
-
allowPublish,
|
|
36126
|
-
quiet,
|
|
36127
|
-
muted,
|
|
36128
|
-
model: str2("model"),
|
|
36129
|
-
variant: str2("variant"),
|
|
36130
|
-
launchOptions,
|
|
36131
|
-
capabilities: list("capabilities"),
|
|
36132
|
-
owner: str2("owner"),
|
|
36133
|
-
meta: Object.keys(meta3).length ? meta3 : void 0,
|
|
36134
|
-
persona: persona || void 0
|
|
36135
|
-
};
|
|
36136
|
-
}
|
|
36137
|
-
|
|
36138
|
-
// ../../packages/core/dist/secret-fs.js
|
|
36139
|
-
import { chmodSync, mkdirSync as mkdirSync2, renameSync, unlinkSync, writeFileSync as writeFileSync2 } from "node:fs";
|
|
36140
|
-
import { execFileSync } from "node:child_process";
|
|
36141
|
-
import { join } from "node:path";
|
|
36142
|
-
var isWin = process.platform === "win32";
|
|
36143
|
-
function sys32(exe) {
|
|
36144
|
-
const root = process.env.SystemRoot || process.env.windir || "C:\\Windows";
|
|
36145
|
-
return join(root, "System32", exe);
|
|
36146
|
-
}
|
|
36147
|
-
var cachedSid;
|
|
36148
|
-
function ownerSid() {
|
|
36149
|
-
if (cachedSid)
|
|
36150
|
-
return cachedSid;
|
|
36151
|
-
const out = execFileSync(sys32("whoami.exe"), ["/user", "/fo", "csv", "/nh"], { encoding: "utf8" });
|
|
36152
|
-
const sid = out.trim().split(",").pop()?.replace(/^"|"$/g, "").trim();
|
|
36153
|
-
if (!sid || !/^S-1-/.test(sid))
|
|
36154
|
-
throw new Error(`could not determine the current user's SID from \`whoami\` (got: ${out.trim()})`);
|
|
36155
|
-
cachedSid = sid;
|
|
36156
|
-
return sid;
|
|
36157
|
-
}
|
|
36158
|
-
var BROAD_SIDS = ["S-1-1-0", "S-1-5-11", "S-1-5-32-545"];
|
|
36159
|
-
function hardenPrivate(path, kind) {
|
|
36160
|
-
if (!isWin) {
|
|
36161
|
-
chmodSync(path, kind === "dir" ? 448 : 384);
|
|
36162
|
-
return;
|
|
36163
|
-
}
|
|
36164
|
-
const perm = kind === "dir" ? "(OI)(CI)(F)" : "(F)";
|
|
36165
|
-
const removeBroad = BROAD_SIDS.flatMap((sid) => ["/remove:g", `*${sid}`]);
|
|
36166
|
-
const grant = (sid) => ["/grant:r", `*${sid}:${perm}`];
|
|
36167
|
-
try {
|
|
36168
|
-
execFileSync(sys32("icacls.exe"), [
|
|
36169
|
-
path,
|
|
36170
|
-
"/inheritance:r",
|
|
36171
|
-
...removeBroad,
|
|
36172
|
-
...grant(ownerSid()),
|
|
36173
|
-
...grant("S-1-5-18"),
|
|
36174
|
-
...grant("S-1-5-32-544")
|
|
36175
|
-
], { stdio: ["ignore", "ignore", "pipe"] });
|
|
36176
|
-
} catch (e) {
|
|
36177
|
-
throw new Error(`failed to harden ${kind} "${path}" to private via icacls: ${e.message.trim()}. Cotal will not leave a secret with a permissive ACL - ensure the path is on an NTFS volume and %SystemRoot%\\System32\\icacls.exe is available.`);
|
|
36178
|
-
}
|
|
36179
|
-
}
|
|
36180
|
-
function writeSecretFile(path, data) {
|
|
36181
|
-
writeFileSync2(path, data, { mode: 384 });
|
|
36182
|
-
if (!isWin)
|
|
36183
|
-
return;
|
|
36184
|
-
try {
|
|
36185
|
-
hardenPrivate(path, "file");
|
|
36186
|
-
} catch (e) {
|
|
36187
|
-
try {
|
|
36188
|
-
unlinkSync(path);
|
|
36189
|
-
} catch {
|
|
36190
|
-
}
|
|
36191
|
-
throw e;
|
|
36192
|
-
}
|
|
36193
|
-
}
|
|
36194
|
-
function writeSecretFileAtomic(path, data) {
|
|
36195
|
-
const tmp = `${path}.${process.pid}.${Date.now()}.tmp`;
|
|
36196
|
-
try {
|
|
36197
|
-
writeSecretFile(tmp, data);
|
|
36198
|
-
renameSync(tmp, path);
|
|
36199
|
-
} catch (e) {
|
|
36200
|
-
try {
|
|
36201
|
-
unlinkSync(tmp);
|
|
36202
|
-
} catch {
|
|
36203
|
-
}
|
|
36204
|
-
throw e;
|
|
36205
|
-
}
|
|
36206
|
-
}
|
|
36207
|
-
function mkSecretDir(path) {
|
|
36208
|
-
mkdirSync2(path, { recursive: true, mode: 448 });
|
|
36209
|
-
hardenPrivate(path, "dir");
|
|
36210
|
-
}
|
|
36211
|
-
|
|
36212
|
-
// ../../packages/core/dist/launch-material.js
|
|
36213
|
-
import { mkdtempSync, readFileSync as readFileSync2, realpathSync, rmSync, rmdirSync, statSync } from "node:fs";
|
|
36214
|
-
import { tmpdir } from "node:os";
|
|
36215
|
-
import { basename, dirname, join as join2, resolve } from "node:path";
|
|
36216
|
-
var DIR_PREFIX = "cotal-launch-";
|
|
36217
|
-
var MATERIAL_FILE = "material.json";
|
|
36218
|
-
var LAUNCH_MATERIAL_ENV = "COTAL_LAUNCH_MATERIAL";
|
|
36219
|
-
function readLaunchMaterial(path) {
|
|
36220
|
-
let raw;
|
|
36221
|
-
try {
|
|
36222
|
-
if (process.platform !== "win32") {
|
|
36223
|
-
const mode = statSync(path).mode & 511;
|
|
36224
|
-
if (mode & 63)
|
|
36225
|
-
throw new Error(`is readable beyond its owner (mode ${mode.toString(8)}) - refusing to read connection material out of a file other local users can open`);
|
|
36226
|
-
}
|
|
36227
|
-
raw = readFileSync2(path, "utf8");
|
|
36228
|
-
} catch (e) {
|
|
36229
|
-
throw new Error(`launch material: cannot read ${path} (${e instanceof Error ? e.message : String(e)})`);
|
|
36230
|
-
}
|
|
36231
|
-
let parsed;
|
|
36232
|
-
try {
|
|
36233
|
-
parsed = JSON.parse(raw);
|
|
36234
|
-
} catch {
|
|
36235
|
-
throw new Error(`launch material: ${path} is not valid JSON`);
|
|
36236
|
-
}
|
|
36237
|
-
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed))
|
|
36238
|
-
throw new Error(`launch material: ${path} must contain a JSON object`);
|
|
36239
|
-
return validate(parsed, path);
|
|
36240
|
-
}
|
|
36241
|
-
function validate(raw, path) {
|
|
36242
|
-
const material = {};
|
|
36243
|
-
const str2 = (key) => {
|
|
36244
|
-
const v = raw[key];
|
|
36245
|
-
if (v === void 0)
|
|
36246
|
-
return;
|
|
36247
|
-
if (typeof v !== "string" || !v.trim())
|
|
36248
|
-
throw new Error(`launch material: ${path} has a ${key} that is not a non-empty string`);
|
|
36249
|
-
material[key] = v;
|
|
36250
|
-
};
|
|
36251
|
-
str2("servers");
|
|
36252
|
-
str2("creds");
|
|
36253
|
-
str2("token");
|
|
36254
|
-
str2("controlToken");
|
|
36255
|
-
if (raw.userAuth !== void 0) {
|
|
36256
|
-
const u = raw.userAuth;
|
|
36257
|
-
if (typeof u !== "object" || u === null || Array.isArray(u))
|
|
36258
|
-
throw new Error(`launch material: ${path} has a userAuth that is not an object`);
|
|
36259
|
-
const { owner, actor, sentinelCredsPath, bearerCmd } = u;
|
|
36260
|
-
const named = { owner, actor, sentinelCredsPath };
|
|
36261
|
-
for (const [k, v] of Object.entries(named))
|
|
36262
|
-
if (typeof v !== "string" || !v.trim())
|
|
36263
|
-
throw new Error(`launch material: ${path} has a userAuth.${k} that is not a non-empty string`);
|
|
36264
|
-
if (!Array.isArray(bearerCmd) || bearerCmd.length === 0 || !bearerCmd.every((a) => typeof a === "string" && a))
|
|
36265
|
-
throw new Error(`launch material: ${path} has a userAuth.bearerCmd that is not a non-empty array of strings`);
|
|
36266
|
-
material.userAuth = {
|
|
36267
|
-
owner,
|
|
36268
|
-
actor,
|
|
36269
|
-
sentinelCredsPath,
|
|
36270
|
-
bearerCmd
|
|
36271
|
-
};
|
|
36272
|
-
}
|
|
36273
|
-
if (Object.keys(material).length === 0)
|
|
36274
|
-
throw new Error(`launch material: ${path} carries nothing this reader recognises. A launch that references material and supplies none is a broken launcher, not an open-mode launch, so it is refused rather than defaulted.`);
|
|
36275
|
-
return material;
|
|
36276
|
-
}
|
|
36277
|
-
function discardLaunchMaterial(path) {
|
|
36278
|
-
const file2 = resolve(path);
|
|
36279
|
-
try {
|
|
36280
|
-
rmSync(file2, { force: true });
|
|
36281
|
-
} catch {
|
|
36282
|
-
}
|
|
36283
|
-
const dir = dirname(file2);
|
|
36284
|
-
if (basename(file2) !== MATERIAL_FILE || !basename(dir).startsWith(DIR_PREFIX))
|
|
36285
|
-
return;
|
|
36286
|
-
try {
|
|
36287
|
-
if (realpathSync(dirname(dir)) !== realpathSync(tmpdir()))
|
|
36288
|
-
return;
|
|
36289
|
-
rmdirSync(dir);
|
|
36290
|
-
} catch {
|
|
36291
|
-
}
|
|
36292
|
-
}
|
|
36293
|
-
|
|
36294
|
-
// ../../packages/core/dist/endpoint.js
|
|
36295
|
-
var import_transport_node17 = __toESM(require_transport_node(), 1);
|
|
36296
|
-
var import_nats_core = __toESM(require_mod3(), 1);
|
|
36297
|
-
import { EventEmitter } from "node:events";
|
|
36298
|
-
import { randomUUID } from "node:crypto";
|
|
36299
|
-
import { createConnection } from "node:net";
|
|
36300
|
-
|
|
36301
|
-
// ../../packages/core/dist/artifact.js
|
|
36302
|
-
var ARTIFACT_PART_KIND = "artifact";
|
|
36303
|
-
function isArtifactPart(value) {
|
|
36304
|
-
if (!value || typeof value !== "object")
|
|
36305
|
-
return false;
|
|
36306
|
-
const p = value;
|
|
36307
|
-
return p.kind === ARTIFACT_PART_KIND && typeof p.name === "string" && p.name.length > 0 && typeof p.mediaType === "string" && p.mediaType.length > 0 && typeof p.digest === "string" && isContractDigest(p.digest) && typeof p.size === "number" && Number.isSafeInteger(p.size) && p.size >= 0;
|
|
35997
|
+
return new import_kv5.Kvm(nc).open(deliveryBucket(space));
|
|
36308
35998
|
}
|
|
36309
35999
|
|
|
36310
36000
|
// ../../packages/core/dist/endpoint.js
|
|
36311
|
-
var import_jetstream13 = __toESM(require_mod4(), 1);
|
|
36312
|
-
var import_jetstream14 = __toESM(require_mod4(), 1);
|
|
36313
|
-
var import_kv8 = __toESM(require_mod6(), 1);
|
|
36314
|
-
var import_internal2 = __toESM(require_internal_mod3(), 1);
|
|
36315
36001
|
var DEFAULT_SERVER = "nats://127.0.0.1:4222";
|
|
36316
36002
|
var PLANE3_FRAME_HEADER = "Cotal-Delivery-Frame";
|
|
36317
36003
|
var READER_MAX_REDELIVERIES = 10;
|
|
@@ -36825,7 +36511,7 @@ var CotalEndpoint = class _CotalEndpoint extends EventEmitter {
|
|
|
36825
36511
|
this.watchStatus();
|
|
36826
36512
|
this.js = (0, import_jetstream13.jetstream)(this.nc);
|
|
36827
36513
|
if (this.doWatch || this.doRegister) {
|
|
36828
|
-
const kvm = new
|
|
36514
|
+
const kvm = new import_kv6.Kvm(this.nc);
|
|
36829
36515
|
this.kv = this.authed ? await kvm.open(presenceBucket(this.space)) : await kvm.create(presenceBucket(this.space), { ttl: this.ttlMs });
|
|
36830
36516
|
}
|
|
36831
36517
|
if (this.doWatch) {
|
|
@@ -37207,7 +36893,7 @@ var CotalEndpoint = class _CotalEndpoint extends EventEmitter {
|
|
|
37207
36893
|
throw new Error(`expectedLastSubjectSeq must be a non-negative safe integer, got ${JSON.stringify(opts.expectedLastSubjectSeq)}`);
|
|
37208
36894
|
if (!Array.isArray(opts.parts) || opts.parts.length === 0)
|
|
37209
36895
|
throw new Error("encodedSize requires at least one part");
|
|
37210
|
-
const mh = (0,
|
|
36896
|
+
const mh = (0, import_transport_node14.headers)();
|
|
37211
36897
|
mh.set("Nats-Msg-Id", opts.id);
|
|
37212
36898
|
mh.set("Nats-Expected-Last-Subject-Sequence", `${opts.expectedLastSubjectSeq}`);
|
|
37213
36899
|
const headerBytes = mh.encode().length;
|
|
@@ -37713,7 +37399,7 @@ var CotalEndpoint = class _CotalEndpoint extends EventEmitter {
|
|
|
37713
37399
|
async membershipFeedRegistry() {
|
|
37714
37400
|
if (!this.nc)
|
|
37715
37401
|
throw new Error("endpoint not started");
|
|
37716
|
-
this.membershipFeedKv ??= await new
|
|
37402
|
+
this.membershipFeedKv ??= await new import_kv6.Kvm(this.nc).open(membershipBucket(this.space));
|
|
37717
37403
|
return this.membershipFeedKv;
|
|
37718
37404
|
}
|
|
37719
37405
|
/**
|
|
@@ -38079,7 +37765,7 @@ var CotalEndpoint = class _CotalEndpoint extends EventEmitter {
|
|
|
38079
37765
|
for await (const s of this.nc.status()) {
|
|
38080
37766
|
if (s.type !== "error")
|
|
38081
37767
|
continue;
|
|
38082
|
-
if (s.error instanceof
|
|
37768
|
+
if (s.error instanceof import_transport_node14.PermissionViolationError && this.confirmingChatSubs.has(s.error.subject))
|
|
38083
37769
|
continue;
|
|
38084
37770
|
this.emit("error", describeStatusError(s.error));
|
|
38085
37771
|
}
|
|
@@ -38302,7 +37988,7 @@ var CotalEndpoint = class _CotalEndpoint extends EventEmitter {
|
|
|
38302
37988
|
throw new Error("endpoint not started");
|
|
38303
37989
|
if (this.managerLeaseKv)
|
|
38304
37990
|
return this.managerLeaseKv;
|
|
38305
|
-
const kvm = new
|
|
37991
|
+
const kvm = new import_kv6.Kvm((0, import_jetstream13.jetstream)(this.nc, { timeout: MANAGER_LEASE_ATTEMPT_MS }));
|
|
38306
37992
|
if (this.authed) {
|
|
38307
37993
|
this.managerLeaseKv = await kvm.open(managerBucket(this.space));
|
|
38308
37994
|
} else {
|
|
@@ -38532,7 +38218,7 @@ var CotalEndpoint = class _CotalEndpoint extends EventEmitter {
|
|
|
38532
38218
|
filter_subject: subject,
|
|
38533
38219
|
ack_policy: import_jetstream13.AckPolicy.None,
|
|
38534
38220
|
mem_storage: true,
|
|
38535
|
-
inactive_threshold: (0,
|
|
38221
|
+
inactive_threshold: (0, import_transport_node14.nanos)(3e4),
|
|
38536
38222
|
deliver_policy: import_jetstream13.DeliverPolicy.StartSequence,
|
|
38537
38223
|
opt_start_seq: fromSeqExcl + 1
|
|
38538
38224
|
});
|
|
@@ -38994,7 +38680,7 @@ var CotalEndpoint = class _CotalEndpoint extends EventEmitter {
|
|
|
38994
38680
|
channel: entry.channel,
|
|
38995
38681
|
msg: authenticatedChannelMessage(entry.msg, entry.channel)
|
|
38996
38682
|
};
|
|
38997
|
-
const frameHeaders = (0,
|
|
38683
|
+
const frameHeaders = (0, import_transport_node14.headers)();
|
|
38998
38684
|
frameHeaders.set(PLANE3_FRAME_HEADER, "1");
|
|
38999
38685
|
await this.js.publish(dlvSubject(this.space, pr.owner, pr.actor, pr.lifecycleUid), JSON.stringify(frame), {
|
|
39000
38686
|
msgID: `${entry.msg.id}:${owner}:${pr.lifecycleUid}:${entry.generation}`,
|
|
@@ -39124,7 +38810,7 @@ var CotalEndpoint = class _CotalEndpoint extends EventEmitter {
|
|
|
39124
38810
|
* distinct from a responder that errored. nats.js surfaces it as NoRespondersError, or a RequestError
|
|
39125
38811
|
* whose `isNoResponders()` is true. */
|
|
39126
38812
|
isNoResponders(e) {
|
|
39127
|
-
return e instanceof
|
|
38813
|
+
return e instanceof import_transport_node14.NoRespondersError || e instanceof import_transport_node14.RequestError && e.isNoResponders();
|
|
39128
38814
|
}
|
|
39129
38815
|
/** Agent-side: this session's CURRENT durable memberships (channel + join generation) from the
|
|
39130
38816
|
* manager — the agent holds no read on the privileged members KV. `undefined` ⇒ NO control responder
|
|
@@ -39467,7 +39153,7 @@ var CotalEndpoint = class _CotalEndpoint extends EventEmitter {
|
|
|
39467
39153
|
filter_subject: subject,
|
|
39468
39154
|
ack_policy: import_jetstream13.AckPolicy.None,
|
|
39469
39155
|
mem_storage: true,
|
|
39470
|
-
inactive_threshold: (0,
|
|
39156
|
+
inactive_threshold: (0, import_transport_node14.nanos)(3e4),
|
|
39471
39157
|
..."time" in start ? { deliver_policy: import_jetstream13.DeliverPolicy.StartTime, opt_start_time: start.time.toISOString() } : { deliver_policy: import_jetstream13.DeliverPolicy.StartSequence, opt_start_seq: start.seq }
|
|
39472
39158
|
});
|
|
39473
39159
|
try {
|
|
@@ -39828,7 +39514,7 @@ function authOpts(a) {
|
|
|
39828
39514
|
if (!a.sentinelCreds)
|
|
39829
39515
|
throw new Error("user-mode bearer requires sentinelCreds");
|
|
39830
39516
|
return {
|
|
39831
|
-
authenticator: [(0,
|
|
39517
|
+
authenticator: [(0, import_transport_node14.credsAuthenticator)(new TextEncoder().encode(a.sentinelCreds)), (0, import_transport_node14.tokenAuthenticator)(a.bearer)],
|
|
39832
39518
|
tls
|
|
39833
39519
|
};
|
|
39834
39520
|
}
|
|
@@ -39836,7 +39522,7 @@ function authOpts(a) {
|
|
|
39836
39522
|
if (a.token || a.user || a.pass)
|
|
39837
39523
|
throw new Error("creds are mutually exclusive with token/user/pass auth");
|
|
39838
39524
|
const creds = a.creds;
|
|
39839
|
-
const authenticator = typeof creds === "function" ? (nonce3) => (0,
|
|
39525
|
+
const authenticator = typeof creds === "function" ? (nonce3) => (0, import_transport_node14.credsAuthenticator)(new TextEncoder().encode(creds()))(nonce3) : (0, import_transport_node14.credsAuthenticator)(new TextEncoder().encode(creds));
|
|
39840
39526
|
return { authenticator, tls };
|
|
39841
39527
|
}
|
|
39842
39528
|
return { token: a.token, user: a.user, pass: a.pass, tls };
|
|
@@ -39871,25 +39557,32 @@ function decodeBearerPrincipal(bearer) {
|
|
|
39871
39557
|
return { owner, actor };
|
|
39872
39558
|
}
|
|
39873
39559
|
function describeStatusError(err2) {
|
|
39874
|
-
if (err2 instanceof
|
|
39560
|
+
if (err2 instanceof import_transport_node14.PermissionViolationError) {
|
|
39875
39561
|
return new Error(`NATS permission denied: cannot ${err2.operation} "${err2.subject}" - check this endpoint's ACLs (a denied peer looks "absent" rather than blocked)`, { cause: err2 });
|
|
39876
39562
|
}
|
|
39877
39563
|
return err2;
|
|
39878
39564
|
}
|
|
39879
39565
|
function isPermissionDenied(e) {
|
|
39880
|
-
if (e instanceof
|
|
39566
|
+
if (e instanceof import_transport_node14.PermissionViolationError)
|
|
39881
39567
|
return true;
|
|
39882
|
-
if (e?.cause instanceof
|
|
39568
|
+
if (e?.cause instanceof import_transport_node14.PermissionViolationError)
|
|
39883
39569
|
return true;
|
|
39884
39570
|
return /permissions?\s+violation/i.test(String(e?.message ?? ""));
|
|
39885
39571
|
}
|
|
39886
39572
|
function isPublishPermissionDenied(e) {
|
|
39887
|
-
const typed = e instanceof
|
|
39573
|
+
const typed = e instanceof import_transport_node14.PermissionViolationError ? e : e?.cause instanceof import_transport_node14.PermissionViolationError ? e.cause : void 0;
|
|
39888
39574
|
return typed?.operation === "publish";
|
|
39889
39575
|
}
|
|
39576
|
+
function wsServers(servers) {
|
|
39577
|
+
return /^wss?:\/\//i.test((servers.split(",")[0] ?? "").trim());
|
|
39578
|
+
}
|
|
39890
39579
|
function dialerFor(servers) {
|
|
39891
|
-
|
|
39892
|
-
|
|
39580
|
+
if (!wsServers(servers))
|
|
39581
|
+
return import_transport_node14.connect;
|
|
39582
|
+
return ((opts) => {
|
|
39583
|
+
const { tls: _tls, ...rest } = opts ?? {};
|
|
39584
|
+
return (0, import_nats_core.wsconnect)(rest);
|
|
39585
|
+
});
|
|
39893
39586
|
}
|
|
39894
39587
|
function hostPort(server) {
|
|
39895
39588
|
const raw = (server.split(",")[0] ?? "").trim();
|
|
@@ -39954,13 +39647,331 @@ function classifyProbeFailure(e, opts) {
|
|
|
39954
39647
|
} catch {
|
|
39955
39648
|
}
|
|
39956
39649
|
}
|
|
39957
|
-
if (e instanceof
|
|
39650
|
+
if (e instanceof import_transport_node14.UserAuthenticationExpiredError)
|
|
39958
39651
|
return { ok: false, reason: "stale-auth" };
|
|
39959
|
-
if (e instanceof
|
|
39652
|
+
if (e instanceof import_transport_node14.AuthorizationError)
|
|
39960
39653
|
return { ok: false, reason: "auth-required" };
|
|
39961
39654
|
return { ok: false, reason: "unreachable" };
|
|
39962
39655
|
}
|
|
39963
39656
|
|
|
39657
|
+
// ../../packages/core/dist/channels.js
|
|
39658
|
+
function parseDuration(s) {
|
|
39659
|
+
const m = /^(\d+)(s|m|h|d)$/.exec(s.trim());
|
|
39660
|
+
if (!m)
|
|
39661
|
+
throw new Error(`invalid duration "${s}" - expected <number><s|m|h|d>, e.g. "24h"`);
|
|
39662
|
+
const n = Number(m[1]);
|
|
39663
|
+
const unit = { s: 1e3, m: 6e4, h: 36e5, d: 864e5 }[m[2]];
|
|
39664
|
+
return n * unit;
|
|
39665
|
+
}
|
|
39666
|
+
function effectiveReplay(cfg, defaults) {
|
|
39667
|
+
return cfg?.replay ?? defaults?.replay ?? true;
|
|
39668
|
+
}
|
|
39669
|
+
function effectiveReplayWindowMs(cfg, defaults) {
|
|
39670
|
+
const w = cfg?.replayWindow ?? defaults?.replayWindow;
|
|
39671
|
+
return w === void 0 ? void 0 : parseDuration(w);
|
|
39672
|
+
}
|
|
39673
|
+
function effectiveDeliveryClass(cfg, defaults) {
|
|
39674
|
+
return cfg?.deliveryClass ?? defaults?.deliveryClass ?? "durable";
|
|
39675
|
+
}
|
|
39676
|
+
async function openChannelRegistry(nc, space, opts = {}) {
|
|
39677
|
+
const kvm = new import_kv7.Kvm(nc);
|
|
39678
|
+
return opts.create ? kvm.create(channelBucket(space)) : kvm.open(channelBucket(space));
|
|
39679
|
+
}
|
|
39680
|
+
async function readChannelConfig(kv, channel) {
|
|
39681
|
+
return decode2(kv, channel);
|
|
39682
|
+
}
|
|
39683
|
+
async function readChannelDefaults(kv) {
|
|
39684
|
+
return decode2(kv, CHANNEL_DEFAULTS_KEY);
|
|
39685
|
+
}
|
|
39686
|
+
async function decode2(kv, key) {
|
|
39687
|
+
const e = await kv.get(key);
|
|
39688
|
+
if (!e || e.operation === "DEL" || e.operation === "PURGE")
|
|
39689
|
+
return void 0;
|
|
39690
|
+
try {
|
|
39691
|
+
return e.json();
|
|
39692
|
+
} catch {
|
|
39693
|
+
return void 0;
|
|
39694
|
+
}
|
|
39695
|
+
}
|
|
39696
|
+
|
|
39697
|
+
// ../../packages/core/dist/membership-feed.js
|
|
39698
|
+
var import_transport_node16 = __toESM(require_transport_node(), 1);
|
|
39699
|
+
var import_kv8 = __toESM(require_mod6(), 1);
|
|
39700
|
+
|
|
39701
|
+
// ../../packages/core/dist/evict.js
|
|
39702
|
+
var import_transport_node17 = __toESM(require_transport_node(), 1);
|
|
39703
|
+
|
|
39704
|
+
// ../../packages/core/dist/agent-file.js
|
|
39705
|
+
import { mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
39706
|
+
var import_yaml = __toESM(require_dist(), 1);
|
|
39707
|
+
function parseFrontmatter(src, path) {
|
|
39708
|
+
let doc;
|
|
39709
|
+
try {
|
|
39710
|
+
doc = (0, import_yaml.parse)(src);
|
|
39711
|
+
} catch (e) {
|
|
39712
|
+
throw new Error(`agent file ${path}: invalid YAML frontmatter; ${e.message}`);
|
|
39713
|
+
}
|
|
39714
|
+
if (doc === null || doc === void 0)
|
|
39715
|
+
return {};
|
|
39716
|
+
if (typeof doc !== "object" || Array.isArray(doc))
|
|
39717
|
+
throw new Error(`agent file ${path}: frontmatter must be a YAML mapping (key: value pairs)`);
|
|
39718
|
+
return doc;
|
|
39719
|
+
}
|
|
39720
|
+
function loadAgentFile(path) {
|
|
39721
|
+
const src = readFileSync(path, "utf8");
|
|
39722
|
+
const m = /^---\n([\s\S]*?)\n---\n?([\s\S]*)$/.exec(src);
|
|
39723
|
+
if (!m)
|
|
39724
|
+
throw new Error(`agent file ${path}: missing "---" frontmatter block`);
|
|
39725
|
+
const fm = parseFrontmatter(m[1], path);
|
|
39726
|
+
const persona = m[2].trim();
|
|
39727
|
+
const str2 = (k) => {
|
|
39728
|
+
const v = fm[k];
|
|
39729
|
+
if (v === void 0 || v === null)
|
|
39730
|
+
return void 0;
|
|
39731
|
+
if (typeof v === "object")
|
|
39732
|
+
throw new Error(`agent file ${path}: "${k}" must be a scalar`);
|
|
39733
|
+
return String(v);
|
|
39734
|
+
};
|
|
39735
|
+
const list = (k) => {
|
|
39736
|
+
const v = fm[k];
|
|
39737
|
+
if (v === void 0 || v === null)
|
|
39738
|
+
return void 0;
|
|
39739
|
+
return (Array.isArray(v) ? v : [v]).map((x) => {
|
|
39740
|
+
if (x === null || typeof x === "object")
|
|
39741
|
+
throw new Error(`agent file ${path}: "${k}" list items must be scalars`);
|
|
39742
|
+
return String(x);
|
|
39743
|
+
});
|
|
39744
|
+
};
|
|
39745
|
+
const name = str2("name");
|
|
39746
|
+
if (!name)
|
|
39747
|
+
throw new Error(`agent file ${path}: "name" is required`);
|
|
39748
|
+
assertValidName(name);
|
|
39749
|
+
const kind = str2("kind");
|
|
39750
|
+
if (kind && kind !== "agent" && kind !== "endpoint")
|
|
39751
|
+
throw new Error(`agent file ${path}: "kind" must be "agent" or "endpoint"`);
|
|
39752
|
+
for (const old of ["channels", "publish"])
|
|
39753
|
+
if (old in fm)
|
|
39754
|
+
throw new Error(`agent file ${path}: "${old}" was renamed - use "subscribe"/"allowSubscribe" (read) and "allowPublish" (post)`);
|
|
39755
|
+
const subscribe = list("subscribe");
|
|
39756
|
+
const allowSubscribe = list("allowSubscribe");
|
|
39757
|
+
const allowPublish = list("allowPublish");
|
|
39758
|
+
const quiet = list("quiet");
|
|
39759
|
+
const muted = list("muted");
|
|
39760
|
+
for (const ch of [...subscribe ?? [], ...allowSubscribe ?? [], ...allowPublish ?? []])
|
|
39761
|
+
try {
|
|
39762
|
+
assertValidChannel(ch);
|
|
39763
|
+
} catch (e) {
|
|
39764
|
+
throw new Error(`agent file ${path}: ${e.message}`);
|
|
39765
|
+
}
|
|
39766
|
+
const effSubscribe = subscribe ?? [];
|
|
39767
|
+
const effAllow = allowSubscribe?.length ? allowSubscribe : effSubscribe;
|
|
39768
|
+
for (const ch of effSubscribe)
|
|
39769
|
+
if (!channelInAllow(effAllow, ch))
|
|
39770
|
+
throw new Error(`agent file ${path}: subscribe channel "${ch}" is not within allowSubscribe [${effAllow.join(", ")}]`);
|
|
39771
|
+
const both = (quiet ?? []).filter((c) => (muted ?? []).includes(c));
|
|
39772
|
+
if (both.length)
|
|
39773
|
+
throw new Error(`agent file ${path}: channel(s) [${both.join(", ")}] are in both quiet and muted - pick one`);
|
|
39774
|
+
for (const [field, chans] of [["quiet", quiet], ["muted", muted]])
|
|
39775
|
+
for (const ch of chans ?? []) {
|
|
39776
|
+
try {
|
|
39777
|
+
assertValidChannel(ch);
|
|
39778
|
+
} catch (e) {
|
|
39779
|
+
throw new Error(`agent file ${path}: ${e.message}`);
|
|
39780
|
+
}
|
|
39781
|
+
if (!isConcreteChannel(ch))
|
|
39782
|
+
throw new Error(`agent file ${path}: ${field} channel "${ch}" must be a concrete channel (no wildcard)`);
|
|
39783
|
+
if (!channelInAllow(effAllow, ch))
|
|
39784
|
+
throw new Error(`agent file ${path}: ${field} channel "${ch}" is not within your read ACL / allowSubscribe [${effAllow.join(", ")}]`);
|
|
39785
|
+
}
|
|
39786
|
+
const launchOptionsRaw = fm["launchOptions"];
|
|
39787
|
+
let launchOptions;
|
|
39788
|
+
if (launchOptionsRaw !== void 0 && launchOptionsRaw !== null) {
|
|
39789
|
+
if (typeof launchOptionsRaw !== "object" || Array.isArray(launchOptionsRaw))
|
|
39790
|
+
throw new Error(`agent file ${path}: "launchOptions" must be a mapping of key: value pairs`);
|
|
39791
|
+
launchOptions = launchOptionsRaw;
|
|
39792
|
+
}
|
|
39793
|
+
const known = /* @__PURE__ */ new Set(["name", "role", "kind", "description", "tags", "subscribe", "allowSubscribe", "allowPublish", "quiet", "muted", "model", "variant", "launchOptions", "capabilities", "owner"]);
|
|
39794
|
+
const meta3 = {};
|
|
39795
|
+
for (const [k, v] of Object.entries(fm))
|
|
39796
|
+
if (!known.has(k) && v !== null && typeof v !== "object")
|
|
39797
|
+
meta3[k] = String(v);
|
|
39798
|
+
return {
|
|
39799
|
+
name,
|
|
39800
|
+
role: str2("role"),
|
|
39801
|
+
kind,
|
|
39802
|
+
description: str2("description"),
|
|
39803
|
+
tags: list("tags"),
|
|
39804
|
+
subscribe,
|
|
39805
|
+
allowSubscribe,
|
|
39806
|
+
allowPublish,
|
|
39807
|
+
quiet,
|
|
39808
|
+
muted,
|
|
39809
|
+
model: str2("model"),
|
|
39810
|
+
variant: str2("variant"),
|
|
39811
|
+
launchOptions,
|
|
39812
|
+
capabilities: list("capabilities"),
|
|
39813
|
+
owner: str2("owner"),
|
|
39814
|
+
meta: Object.keys(meta3).length ? meta3 : void 0,
|
|
39815
|
+
persona: persona || void 0
|
|
39816
|
+
};
|
|
39817
|
+
}
|
|
39818
|
+
|
|
39819
|
+
// ../../packages/core/dist/secret-fs.js
|
|
39820
|
+
import { chmodSync, mkdirSync as mkdirSync2, renameSync, unlinkSync, writeFileSync as writeFileSync2 } from "node:fs";
|
|
39821
|
+
import { execFileSync } from "node:child_process";
|
|
39822
|
+
import { join } from "node:path";
|
|
39823
|
+
var isWin = process.platform === "win32";
|
|
39824
|
+
function sys32(exe) {
|
|
39825
|
+
const root = process.env.SystemRoot || process.env.windir || "C:\\Windows";
|
|
39826
|
+
return join(root, "System32", exe);
|
|
39827
|
+
}
|
|
39828
|
+
var cachedSid;
|
|
39829
|
+
function ownerSid() {
|
|
39830
|
+
if (cachedSid)
|
|
39831
|
+
return cachedSid;
|
|
39832
|
+
const out = execFileSync(sys32("whoami.exe"), ["/user", "/fo", "csv", "/nh"], { encoding: "utf8" });
|
|
39833
|
+
const sid = out.trim().split(",").pop()?.replace(/^"|"$/g, "").trim();
|
|
39834
|
+
if (!sid || !/^S-1-/.test(sid))
|
|
39835
|
+
throw new Error(`could not determine the current user's SID from \`whoami\` (got: ${out.trim()})`);
|
|
39836
|
+
cachedSid = sid;
|
|
39837
|
+
return sid;
|
|
39838
|
+
}
|
|
39839
|
+
var BROAD_SIDS = ["S-1-1-0", "S-1-5-11", "S-1-5-32-545"];
|
|
39840
|
+
function hardenPrivate(path, kind) {
|
|
39841
|
+
if (!isWin) {
|
|
39842
|
+
chmodSync(path, kind === "dir" ? 448 : 384);
|
|
39843
|
+
return;
|
|
39844
|
+
}
|
|
39845
|
+
const perm = kind === "dir" ? "(OI)(CI)(F)" : "(F)";
|
|
39846
|
+
const removeBroad = BROAD_SIDS.flatMap((sid) => ["/remove:g", `*${sid}`]);
|
|
39847
|
+
const grant = (sid) => ["/grant:r", `*${sid}:${perm}`];
|
|
39848
|
+
try {
|
|
39849
|
+
execFileSync(sys32("icacls.exe"), [
|
|
39850
|
+
path,
|
|
39851
|
+
"/inheritance:r",
|
|
39852
|
+
...removeBroad,
|
|
39853
|
+
...grant(ownerSid()),
|
|
39854
|
+
...grant("S-1-5-18"),
|
|
39855
|
+
...grant("S-1-5-32-544")
|
|
39856
|
+
], { stdio: ["ignore", "ignore", "pipe"] });
|
|
39857
|
+
} catch (e) {
|
|
39858
|
+
throw new Error(`failed to harden ${kind} "${path}" to private via icacls: ${e.message.trim()}. Cotal will not leave a secret with a permissive ACL - ensure the path is on an NTFS volume and %SystemRoot%\\System32\\icacls.exe is available.`);
|
|
39859
|
+
}
|
|
39860
|
+
}
|
|
39861
|
+
function writeSecretFile(path, data) {
|
|
39862
|
+
writeFileSync2(path, data, { mode: 384 });
|
|
39863
|
+
if (!isWin)
|
|
39864
|
+
return;
|
|
39865
|
+
try {
|
|
39866
|
+
hardenPrivate(path, "file");
|
|
39867
|
+
} catch (e) {
|
|
39868
|
+
try {
|
|
39869
|
+
unlinkSync(path);
|
|
39870
|
+
} catch {
|
|
39871
|
+
}
|
|
39872
|
+
throw e;
|
|
39873
|
+
}
|
|
39874
|
+
}
|
|
39875
|
+
function writeSecretFileAtomic(path, data) {
|
|
39876
|
+
const tmp = `${path}.${process.pid}.${Date.now()}.tmp`;
|
|
39877
|
+
try {
|
|
39878
|
+
writeSecretFile(tmp, data);
|
|
39879
|
+
renameSync(tmp, path);
|
|
39880
|
+
} catch (e) {
|
|
39881
|
+
try {
|
|
39882
|
+
unlinkSync(tmp);
|
|
39883
|
+
} catch {
|
|
39884
|
+
}
|
|
39885
|
+
throw e;
|
|
39886
|
+
}
|
|
39887
|
+
}
|
|
39888
|
+
function mkSecretDir(path) {
|
|
39889
|
+
mkdirSync2(path, { recursive: true, mode: 448 });
|
|
39890
|
+
hardenPrivate(path, "dir");
|
|
39891
|
+
}
|
|
39892
|
+
|
|
39893
|
+
// ../../packages/core/dist/launch-material.js
|
|
39894
|
+
import { mkdtempSync, readFileSync as readFileSync2, realpathSync, rmSync, rmdirSync, statSync } from "node:fs";
|
|
39895
|
+
import { tmpdir } from "node:os";
|
|
39896
|
+
import { basename, dirname, join as join2, resolve } from "node:path";
|
|
39897
|
+
var DIR_PREFIX = "cotal-launch-";
|
|
39898
|
+
var MATERIAL_FILE = "material.json";
|
|
39899
|
+
var LAUNCH_MATERIAL_ENV = "COTAL_LAUNCH_MATERIAL";
|
|
39900
|
+
function readLaunchMaterial(path) {
|
|
39901
|
+
let raw;
|
|
39902
|
+
try {
|
|
39903
|
+
if (process.platform !== "win32") {
|
|
39904
|
+
const mode = statSync(path).mode & 511;
|
|
39905
|
+
if (mode & 63)
|
|
39906
|
+
throw new Error(`is readable beyond its owner (mode ${mode.toString(8)}) - refusing to read connection material out of a file other local users can open`);
|
|
39907
|
+
}
|
|
39908
|
+
raw = readFileSync2(path, "utf8");
|
|
39909
|
+
} catch (e) {
|
|
39910
|
+
throw new Error(`launch material: cannot read ${path} (${e instanceof Error ? e.message : String(e)})`);
|
|
39911
|
+
}
|
|
39912
|
+
let parsed;
|
|
39913
|
+
try {
|
|
39914
|
+
parsed = JSON.parse(raw);
|
|
39915
|
+
} catch {
|
|
39916
|
+
throw new Error(`launch material: ${path} is not valid JSON`);
|
|
39917
|
+
}
|
|
39918
|
+
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed))
|
|
39919
|
+
throw new Error(`launch material: ${path} must contain a JSON object`);
|
|
39920
|
+
return validate(parsed, path);
|
|
39921
|
+
}
|
|
39922
|
+
function validate(raw, path) {
|
|
39923
|
+
const material = {};
|
|
39924
|
+
const str2 = (key) => {
|
|
39925
|
+
const v = raw[key];
|
|
39926
|
+
if (v === void 0)
|
|
39927
|
+
return;
|
|
39928
|
+
if (typeof v !== "string" || !v.trim())
|
|
39929
|
+
throw new Error(`launch material: ${path} has a ${key} that is not a non-empty string`);
|
|
39930
|
+
material[key] = v;
|
|
39931
|
+
};
|
|
39932
|
+
str2("servers");
|
|
39933
|
+
str2("creds");
|
|
39934
|
+
str2("token");
|
|
39935
|
+
str2("controlToken");
|
|
39936
|
+
if (raw.userAuth !== void 0) {
|
|
39937
|
+
const u = raw.userAuth;
|
|
39938
|
+
if (typeof u !== "object" || u === null || Array.isArray(u))
|
|
39939
|
+
throw new Error(`launch material: ${path} has a userAuth that is not an object`);
|
|
39940
|
+
const { owner, actor, sentinelCredsPath, bearerCmd } = u;
|
|
39941
|
+
const named = { owner, actor, sentinelCredsPath };
|
|
39942
|
+
for (const [k, v] of Object.entries(named))
|
|
39943
|
+
if (typeof v !== "string" || !v.trim())
|
|
39944
|
+
throw new Error(`launch material: ${path} has a userAuth.${k} that is not a non-empty string`);
|
|
39945
|
+
if (!Array.isArray(bearerCmd) || bearerCmd.length === 0 || !bearerCmd.every((a) => typeof a === "string" && a))
|
|
39946
|
+
throw new Error(`launch material: ${path} has a userAuth.bearerCmd that is not a non-empty array of strings`);
|
|
39947
|
+
material.userAuth = {
|
|
39948
|
+
owner,
|
|
39949
|
+
actor,
|
|
39950
|
+
sentinelCredsPath,
|
|
39951
|
+
bearerCmd
|
|
39952
|
+
};
|
|
39953
|
+
}
|
|
39954
|
+
if (Object.keys(material).length === 0)
|
|
39955
|
+
throw new Error(`launch material: ${path} carries nothing this reader recognises. A launch that references material and supplies none is a broken launcher, not an open-mode launch, so it is refused rather than defaulted.`);
|
|
39956
|
+
return material;
|
|
39957
|
+
}
|
|
39958
|
+
function discardLaunchMaterial(path) {
|
|
39959
|
+
const file2 = resolve(path);
|
|
39960
|
+
try {
|
|
39961
|
+
rmSync(file2, { force: true });
|
|
39962
|
+
} catch {
|
|
39963
|
+
}
|
|
39964
|
+
const dir = dirname(file2);
|
|
39965
|
+
if (basename(file2) !== MATERIAL_FILE || !basename(dir).startsWith(DIR_PREFIX))
|
|
39966
|
+
return;
|
|
39967
|
+
try {
|
|
39968
|
+
if (realpathSync(dirname(dir)) !== realpathSync(tmpdir()))
|
|
39969
|
+
return;
|
|
39970
|
+
rmdirSync(dir);
|
|
39971
|
+
} catch {
|
|
39972
|
+
}
|
|
39973
|
+
}
|
|
39974
|
+
|
|
39964
39975
|
// ../../packages/core/dist/spaces.js
|
|
39965
39976
|
var import_transport_node18 = __toESM(require_transport_node(), 1);
|
|
39966
39977
|
var import_jetstream15 = __toESM(require_mod4(), 1);
|
|
@@ -55867,7 +55878,7 @@ config(en_default());
|
|
|
55867
55878
|
|
|
55868
55879
|
// ../connector-core/dist/docs-bundle.generated.js
|
|
55869
55880
|
var DOCS_BUNDLE = {
|
|
55870
|
-
"version": "0.28.
|
|
55881
|
+
"version": "0.28.1",
|
|
55871
55882
|
"generatedFrom": "docs/*.md + SPEC.md + spec/cotal-lang.md + spec/cotal.schema.json",
|
|
55872
55883
|
"pages": [
|
|
55873
55884
|
{
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cotal-ai/pi",
|
|
3
|
-
"version": "0.28.
|
|
3
|
+
"version": "0.28.1",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -34,8 +34,8 @@
|
|
|
34
34
|
"esbuild": "^0.28.0",
|
|
35
35
|
"typebox": "^1.1.0",
|
|
36
36
|
"zod": "^4.4.3",
|
|
37
|
-
"@cotal-ai/
|
|
38
|
-
"@cotal-ai/core": "0.28.
|
|
37
|
+
"@cotal-ai/core": "0.28.1",
|
|
38
|
+
"@cotal-ai/connector-core": "0.28.1"
|
|
39
39
|
},
|
|
40
40
|
"files": [
|
|
41
41
|
"dist"
|