@cotal-ai/workspace 0.68.0 → 0.70.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/auth-paths.d.ts +16 -19
- package/dist/auth-paths.d.ts.map +1 -1
- package/dist/auth-paths.js +126 -170
- package/dist/auth-paths.js.map +1 -1
- package/dist/bin-path.d.ts +7 -6
- package/dist/bin-path.d.ts.map +1 -1
- package/dist/bin-path.js +11 -7
- package/dist/bin-path.js.map +1 -1
- package/dist/connect.d.ts.map +1 -1
- package/dist/connect.js +11 -11
- package/dist/connect.js.map +1 -1
- package/dist/default-agent.d.ts +9 -0
- package/dist/default-agent.d.ts.map +1 -1
- package/dist/default-agent.js +8 -0
- package/dist/default-agent.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/join-target.d.ts +3 -50
- package/dist/join-target.d.ts.map +1 -1
- package/dist/join-target.js +5 -18
- package/dist/join-target.js.map +1 -1
- package/dist/local-process.d.ts +5 -1
- package/dist/local-process.d.ts.map +1 -1
- package/dist/local-process.js +14 -11
- package/dist/local-process.js.map +1 -1
- package/dist/manager-shutdown.d.ts.map +1 -1
- package/dist/manager-shutdown.js +5 -5
- package/dist/manager-shutdown.js.map +1 -1
- package/dist/mesh-registry.d.ts +11 -0
- package/dist/mesh-registry.d.ts.map +1 -1
- package/dist/mesh-registry.js +69 -37
- package/dist/mesh-registry.js.map +1 -1
- package/dist/registration-policy.d.ts +5 -0
- package/dist/registration-policy.d.ts.map +1 -1
- package/dist/registration-policy.js +12 -4
- package/dist/registration-policy.js.map +1 -1
- package/dist/secret-store-fs.d.ts +17 -2
- package/dist/secret-store-fs.d.ts.map +1 -1
- package/dist/secret-store-fs.js +85 -6
- package/dist/secret-store-fs.js.map +1 -1
- package/dist/web-session.d.ts +24 -0
- package/dist/web-session.d.ts.map +1 -0
- package/dist/web-session.js +25 -0
- package/dist/web-session.js.map +1 -0
- package/package.json +2 -2
|
@@ -118,6 +118,17 @@ export async function pinnedFetch(target, what) {
|
|
|
118
118
|
throw new Error(`✗ ${what} answered ${res.status} (a redirect to ${JSON.stringify(res.headers.get("location") ?? "")}) - a redirect can move a pinned fetch onto plaintext or onto another host, so it is refused rather than followed; publish the document at the pinned URL itself`);
|
|
119
119
|
return res;
|
|
120
120
|
}
|
|
121
|
+
/** The discovery document under an exchange base. The public exchange face serves
|
|
122
|
+
* `/.well-known/cotal-mesh` beneath its own base path, so `meshes add --from` and the policy
|
|
123
|
+
* refresh resolve the same URL from the same base. A base path may itself end in that suffix,
|
|
124
|
+
* so it is always appended. */
|
|
125
|
+
export function discoveryDocumentUrl(base) {
|
|
126
|
+
const url = new URL(base);
|
|
127
|
+
url.pathname = `${url.pathname.replace(/\/$/, "")}/.well-known/cotal-mesh`;
|
|
128
|
+
url.search = "";
|
|
129
|
+
url.hash = "";
|
|
130
|
+
return url;
|
|
131
|
+
}
|
|
121
132
|
/** How long a trusted policy refresh stays warm. Pinned to the catalog freshness window by the
|
|
122
133
|
* user-bundle smoke, so the two cannot drift. */
|
|
123
134
|
export const POLICY_FRESH_MS = 5_000;
|
|
@@ -151,14 +162,11 @@ export async function refreshRegistrationPolicy(target) {
|
|
|
151
162
|
return target.policy;
|
|
152
163
|
let base;
|
|
153
164
|
try {
|
|
154
|
-
base = new URL(entry.userAuth.endpoints.url);
|
|
165
|
+
base = discoveryDocumentUrl(new URL(entry.userAuth.endpoints.url));
|
|
155
166
|
}
|
|
156
167
|
catch {
|
|
157
168
|
throw new Error(`manual registration for "${entry.space}" has an invalid pinned exchange URL`);
|
|
158
169
|
}
|
|
159
|
-
base.pathname = `${base.pathname.replace(/\/$/, "")}/.well-known/cotal-mesh`;
|
|
160
|
-
base.search = "";
|
|
161
|
-
base.hash = "";
|
|
162
170
|
let response;
|
|
163
171
|
try {
|
|
164
172
|
response = await pinnedFetch(base.toString(), `manual registration "${entry.space}" policy refresh at ${entry.userAuth.endpoints.url}`);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"registration-policy.js","sourceRoot":"","sources":["../src/registration-policy.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"registration-policy.js","sourceRoot":"","sources":["../src/registration-policy.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,9 @@
|
|
|
1
1
|
import { type SecretStore, type SecretStoreIdentity } from "@cotal-ai/core";
|
|
2
|
+
/** Whether `path` is the id file of the store rooted at `dir`. Its own path is, and so is any other
|
|
3
|
+
* name the filesystem resolves to that file. No spelling rule can list those (a case-insensitive
|
|
4
|
+
* filesystem folds `STORE.ID` onto it, and a link reaches it under any name), so they are found by
|
|
5
|
+
* device and inode once the file exists. */
|
|
6
|
+
export declare function isStoreIdFile(dir: string, path: string): boolean;
|
|
2
7
|
/** THE local composition of the secret keyspace: a filesystem store rooted at the workspace's
|
|
3
8
|
* `.cotal/` dir, so every canonical key (`delivery.creds`, `auth/<space>/callout.json`, …)
|
|
4
9
|
* lands byte-for-byte on today's paths. Every local caller composes through here — a hand-rolled
|
|
@@ -25,14 +30,24 @@ export declare function workspaceSecretStore(root: string): FsSecretStore;
|
|
|
25
30
|
*/
|
|
26
31
|
export declare class FsSecretStore implements SecretStore {
|
|
27
32
|
private readonly root;
|
|
28
|
-
readonly
|
|
29
|
-
|
|
33
|
+
private readonly identityRoot;
|
|
34
|
+
private readonly idPath;
|
|
35
|
+
/** `identityRoot` is the root the identity names when that is not the store's own directory: the
|
|
36
|
+
* workspace store lives in `<root>/.cotal` and is named by `<root>`. */
|
|
37
|
+
constructor(root: string, identityRoot?: string);
|
|
38
|
+
/** The root is a local path, so two hosts that mount different directories at one path would
|
|
39
|
+
* name one store by it alone (#2580). The id is random and lives inside the store, so only the
|
|
40
|
+
* same directory carries it. It is written the first time a process names this store or puts a key. */
|
|
41
|
+
get identity(): SecretStoreIdentity;
|
|
42
|
+
/** The id file as lstat sees it, written only by exclusive create, so an existing one is never replaced. */
|
|
43
|
+
private idFile;
|
|
30
44
|
/** Resolve a logical key to an absolute path strictly UNDER `root`, fail-closed: reject empty,
|
|
31
45
|
* NUL, absolute keys, the root itself (`.`), and any key that normalizes outside the root
|
|
32
46
|
* (`..` traversal). Containment is checked via `path.relative`, not a `root + sep` prefix —
|
|
33
47
|
* the prefix form breaks at a filesystem-root base (`/` doubles the separator and rejects
|
|
34
48
|
* every key). A malformed key must never read or clobber a path outside the store's tree. */
|
|
35
49
|
private resolve;
|
|
50
|
+
private refuseIdFile;
|
|
36
51
|
get(key: string): Promise<string | undefined>;
|
|
37
52
|
put(key: string, value: string): Promise<void>;
|
|
38
53
|
delete(key: string): Promise<void>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"secret-store-fs.d.ts","sourceRoot":"","sources":["../src/secret-store-fs.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"secret-store-fs.d.ts","sourceRoot":"","sources":["../src/secret-store-fs.ts"],"names":[],"mappings":"AAGA,OAAO,EAAiE,KAAK,WAAW,EAAE,KAAK,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAkB3I;;;6CAG6C;AAC7C,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAOhE;AAED;;;gFAGgF;AAChF,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,aAAa,CAGhE;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,qBAAa,aAAc,YAAW,WAAW;IAC/C,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAS;IAC9B,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAS;IACtC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAEhC;6EACyE;gBAC7D,IAAI,EAAE,MAAM,EAAE,YAAY,CAAC,EAAE,MAAM;IAO/C;;4GAEwG;IACxG,IAAI,QAAQ,IAAI,mBAAmB,CAelC;IAED,4GAA4G;IAC5G,OAAO,CAAC,MAAM;IAed;;;;kGAI8F;IAC9F,OAAO,CAAC,OAAO;IAYf,OAAO,CAAC,YAAY;IAKd,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC;IAW7C,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAQ9C,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CASzC"}
|
package/dist/secret-store-fs.js
CHANGED
|
@@ -1,13 +1,41 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
2
|
+
import { closeSync, fstatSync, lstatSync, openSync, readFileSync, rmSync, statSync } from "node:fs";
|
|
2
3
|
import { join, dirname, isAbsolute, normalize, relative, resolve, sep } from "node:path";
|
|
3
|
-
import { mkSecretDir, writeSecretFileAtomic } from "@cotal-ai/core";
|
|
4
|
+
import { mkSecretDir, writeSecretFileAtomic, writeSecretFileCreateOnly } from "@cotal-ai/core";
|
|
5
|
+
/** The file in which a filesystem store records the random id its identity carries. No key may name
|
|
6
|
+
* it: the id is published to peers, so a secret stored there would be published with it. */
|
|
7
|
+
const STORE_ID_FILE = "store.id";
|
|
8
|
+
/** What `randomUUID` writes. An id file holding anything else may hold a secret, so it is never published. */
|
|
9
|
+
const STORE_ID = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/;
|
|
10
|
+
/** The id file at `p` as lstat sees it, or undefined while the name is free. A link there would make
|
|
11
|
+
* the id whatever it points at, a key included, so anything but a regular file is refused, never followed. */
|
|
12
|
+
function idFileStat(p) {
|
|
13
|
+
const st = lstatSync(p, { bigint: true, throwIfNoEntry: false });
|
|
14
|
+
if (st !== undefined && !st.isFile())
|
|
15
|
+
throw new Error(`FsSecretStore: ${p} is not a regular file, so it cannot hold the store id; rename or remove it`);
|
|
16
|
+
return st;
|
|
17
|
+
}
|
|
18
|
+
/** Whether `path` is the id file of the store rooted at `dir`. Its own path is, and so is any other
|
|
19
|
+
* name the filesystem resolves to that file. No spelling rule can list those (a case-insensitive
|
|
20
|
+
* filesystem folds `STORE.ID` onto it, and a link reaches it under any name), so they are found by
|
|
21
|
+
* device and inode once the file exists. */
|
|
22
|
+
export function isStoreIdFile(dir, path) {
|
|
23
|
+
const idFile = resolve(dir, STORE_ID_FILE);
|
|
24
|
+
if (resolve(path) === idFile)
|
|
25
|
+
return true;
|
|
26
|
+
const id = idFileStat(idFile);
|
|
27
|
+
if (id === undefined)
|
|
28
|
+
return false;
|
|
29
|
+
const file = statSync(path, { bigint: true, throwIfNoEntry: false });
|
|
30
|
+
return file !== undefined && file.dev === id.dev && file.ino === id.ino;
|
|
31
|
+
}
|
|
4
32
|
/** THE local composition of the secret keyspace: a filesystem store rooted at the workspace's
|
|
5
33
|
* `.cotal/` dir, so every canonical key (`delivery.creds`, `auth/<space>/callout.json`, …)
|
|
6
34
|
* lands byte-for-byte on today's paths. Every local caller composes through here — a hand-rolled
|
|
7
35
|
* root that drifted from `.cotal` would silently split the keyspace in two. */
|
|
8
36
|
export function workspaceSecretStore(root) {
|
|
9
37
|
const workspaceRoot = normalize(resolve(root));
|
|
10
|
-
return new FsSecretStore(join(workspaceRoot, ".cotal"),
|
|
38
|
+
return new FsSecretStore(join(workspaceRoot, ".cotal"), workspaceRoot);
|
|
11
39
|
}
|
|
12
40
|
/**
|
|
13
41
|
* The default filesystem {@link SecretStore}: the workstation adapter behind core's abstract seam.
|
|
@@ -30,12 +58,55 @@ export function workspaceSecretStore(root) {
|
|
|
30
58
|
*/
|
|
31
59
|
export class FsSecretStore {
|
|
32
60
|
root;
|
|
33
|
-
|
|
34
|
-
|
|
61
|
+
identityRoot;
|
|
62
|
+
idPath;
|
|
63
|
+
/** `identityRoot` is the root the identity names when that is not the store's own directory: the
|
|
64
|
+
* workspace store lives in `<root>/.cotal` and is named by `<root>`. */
|
|
65
|
+
constructor(root, identityRoot) {
|
|
35
66
|
if (!root)
|
|
36
67
|
throw new Error("FsSecretStore: root is required");
|
|
37
68
|
this.root = normalize(resolve(root)); // absolutize so keys are cwd-independent
|
|
38
|
-
this.
|
|
69
|
+
this.identityRoot = identityRoot ?? this.root;
|
|
70
|
+
this.idPath = join(this.root, STORE_ID_FILE);
|
|
71
|
+
}
|
|
72
|
+
/** The root is a local path, so two hosts that mount different directories at one path would
|
|
73
|
+
* name one store by it alone (#2580). The id is random and lives inside the store, so only the
|
|
74
|
+
* same directory carries it. It is written the first time a process names this store or puts a key. */
|
|
75
|
+
get identity() {
|
|
76
|
+
const vetted = this.idFile();
|
|
77
|
+
const fd = openSync(this.idPath, "r");
|
|
78
|
+
try {
|
|
79
|
+
// The name can be replaced between lstat and open, so only the file lstat vetted is read.
|
|
80
|
+
const opened = fstatSync(fd, { bigint: true });
|
|
81
|
+
if (opened.dev !== vetted.dev || opened.ino !== vetted.ino)
|
|
82
|
+
throw new Error(`FsSecretStore: ${this.idPath} was replaced while the store id was read`);
|
|
83
|
+
const id = readFileSync(fd, "utf8");
|
|
84
|
+
if (!STORE_ID.test(id))
|
|
85
|
+
throw new Error(`FsSecretStore: ${this.idPath} does not hold a store id (a lowercase UUID and nothing else); rename or remove it`);
|
|
86
|
+
return { kind: "fs", root: this.identityRoot, id };
|
|
87
|
+
}
|
|
88
|
+
finally {
|
|
89
|
+
closeSync(fd);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
/** The id file as lstat sees it, written only by exclusive create, so an existing one is never replaced. */
|
|
93
|
+
idFile() {
|
|
94
|
+
const found = idFileStat(this.idPath);
|
|
95
|
+
if (found !== undefined)
|
|
96
|
+
return found;
|
|
97
|
+
mkSecretDir(this.root);
|
|
98
|
+
try {
|
|
99
|
+
writeSecretFileCreateOnly(this.idPath, randomUUID());
|
|
100
|
+
}
|
|
101
|
+
catch (e) {
|
|
102
|
+
if (e.code !== "EEXIST")
|
|
103
|
+
throw e;
|
|
104
|
+
}
|
|
105
|
+
// EEXIST is a concurrent first use only if what holds the name passes the same lstat check.
|
|
106
|
+
const made = idFileStat(this.idPath);
|
|
107
|
+
if (made === undefined)
|
|
108
|
+
throw new Error(`FsSecretStore: ${this.idPath} was removed as it was created`);
|
|
109
|
+
return made;
|
|
39
110
|
}
|
|
40
111
|
/** Resolve a logical key to an absolute path strictly UNDER `root`, fail-closed: reject empty,
|
|
41
112
|
* NUL, absolute keys, the root itself (`.`), and any key that normalizes outside the root
|
|
@@ -53,8 +124,13 @@ export class FsSecretStore {
|
|
|
53
124
|
throw new Error(`FsSecretStore: key must name a file under the root: ${JSON.stringify(key)}`);
|
|
54
125
|
return abs;
|
|
55
126
|
}
|
|
127
|
+
refuseIdFile(key, p) {
|
|
128
|
+
if (isStoreIdFile(this.root, p))
|
|
129
|
+
throw new Error(`FsSecretStore: key ${JSON.stringify(key)} names the file that holds the store id`);
|
|
130
|
+
}
|
|
56
131
|
async get(key) {
|
|
57
132
|
const p = this.resolve(key);
|
|
133
|
+
this.refuseIdFile(key, p);
|
|
58
134
|
try {
|
|
59
135
|
return readFileSync(p, "utf8");
|
|
60
136
|
}
|
|
@@ -66,11 +142,14 @@ export class FsSecretStore {
|
|
|
66
142
|
}
|
|
67
143
|
async put(key, value) {
|
|
68
144
|
const p = this.resolve(key);
|
|
145
|
+
this.idFile(); // a name the filesystem folds onto the id file can only be told once that file exists
|
|
146
|
+
this.refuseIdFile(key, p);
|
|
69
147
|
mkSecretDir(dirname(p)); // harden the parent dir before the secret lands (0700 / private ACL)
|
|
70
148
|
writeSecretFileAtomic(p, value); // temp + rename: a concurrent get sees old or new, never torn
|
|
71
149
|
}
|
|
72
150
|
async delete(key) {
|
|
73
151
|
const p = this.resolve(key);
|
|
152
|
+
this.refuseIdFile(key, p);
|
|
74
153
|
try {
|
|
75
154
|
rmSync(p);
|
|
76
155
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"secret-store-fs.js","sourceRoot":"","sources":["../src/secret-store-fs.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"secret-store-fs.js","sourceRoot":"","sources":["../src/secret-store-fs.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/** `.cotal/web.session` — the web dashboard's record of the listener it bound, written 0600 beside its
|
|
2
|
+
* pidfile. The dashboard writes it and reads it back in its detached parent, and `cotal status` reads
|
|
3
|
+
* it from a package that cannot import the dashboard's. The name, the shape and the one reader live
|
|
4
|
+
* here so that a change reaches both packages or fails to compile in them. */
|
|
5
|
+
export declare const WEB_SESSION_FILE = "web.session";
|
|
6
|
+
/** The header that presents {@link WebSession.readiness} to the dashboard. Lower-case because Node
|
|
7
|
+
* lower-cases incoming header names, so a capitalised name would never match and would look like a
|
|
8
|
+
* working check. */
|
|
9
|
+
export declare const WEB_READINESS_HEADER = "x-cotal-readiness";
|
|
10
|
+
export interface WebSession {
|
|
11
|
+
/** The single-use link that opens one browser session. */
|
|
12
|
+
readonly launchUrl: string;
|
|
13
|
+
/** Accepted in {@link WEB_READINESS_HEADER} on `/api/meta` only, for the dashboard's whole life,
|
|
14
|
+
* so a caller can poll whether the listener is up and is this dashboard. */
|
|
15
|
+
readonly readiness: string;
|
|
16
|
+
/** The socket's bound address, not the requested one: a hostname `--host` binds what it resolved to. */
|
|
17
|
+
readonly host: string;
|
|
18
|
+
readonly port: number;
|
|
19
|
+
}
|
|
20
|
+
/** The whole record, or `undefined` while there is none to read: the dashboard writes it only once it
|
|
21
|
+
* is listening, truncates the file before writing, and removes it on exit, so an absent, empty or
|
|
22
|
+
* partial file is an ordinary moment in its life. */
|
|
23
|
+
export declare function readWebSession(path: string): WebSession | undefined;
|
|
24
|
+
//# sourceMappingURL=web-session.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"web-session.d.ts","sourceRoot":"","sources":["../src/web-session.ts"],"names":[],"mappings":"AAEA;;;+EAG+E;AAC/E,eAAO,MAAM,gBAAgB,gBAAgB,CAAC;AAE9C;;qBAEqB;AACrB,eAAO,MAAM,oBAAoB,sBAAsB,CAAC;AAExD,MAAM,WAAW,UAAU;IACzB,0DAA0D;IAC1D,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B;iFAC6E;IAC7E,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,wGAAwG;IACxG,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED;;sDAEsD;AACtD,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,UAAU,GAAG,SAAS,CAOnE"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { readFileSync } from "node:fs";
|
|
2
|
+
/** `.cotal/web.session` — the web dashboard's record of the listener it bound, written 0600 beside its
|
|
3
|
+
* pidfile. The dashboard writes it and reads it back in its detached parent, and `cotal status` reads
|
|
4
|
+
* it from a package that cannot import the dashboard's. The name, the shape and the one reader live
|
|
5
|
+
* here so that a change reaches both packages or fails to compile in them. */
|
|
6
|
+
export const WEB_SESSION_FILE = "web.session";
|
|
7
|
+
/** The header that presents {@link WebSession.readiness} to the dashboard. Lower-case because Node
|
|
8
|
+
* lower-cases incoming header names, so a capitalised name would never match and would look like a
|
|
9
|
+
* working check. */
|
|
10
|
+
export const WEB_READINESS_HEADER = "x-cotal-readiness";
|
|
11
|
+
/** The whole record, or `undefined` while there is none to read: the dashboard writes it only once it
|
|
12
|
+
* is listening, truncates the file before writing, and removes it on exit, so an absent, empty or
|
|
13
|
+
* partial file is an ordinary moment in its life. */
|
|
14
|
+
export function readWebSession(path) {
|
|
15
|
+
try {
|
|
16
|
+
const { launchUrl, readiness, host, port } = JSON.parse(readFileSync(path, "utf8"));
|
|
17
|
+
if (typeof launchUrl !== "string" || typeof readiness !== "string" || typeof host !== "string" || typeof port !== "number")
|
|
18
|
+
return undefined;
|
|
19
|
+
return { launchUrl, readiness, host, port };
|
|
20
|
+
}
|
|
21
|
+
catch {
|
|
22
|
+
return undefined;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=web-session.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"web-session.js","sourceRoot":"","sources":["../src/web-session.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAEvC;;;+EAG+E;AAC/E,MAAM,CAAC,MAAM,gBAAgB,GAAG,aAAa,CAAC;AAE9C;;qBAEqB;AACrB,MAAM,CAAC,MAAM,oBAAoB,GAAG,mBAAmB,CAAC;AAaxD;;sDAEsD;AACtD,MAAM,UAAU,cAAc,CAAC,IAAY;IACzC,IAAI,CAAC;QACH,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAA4B,CAAC;QAC/G,IAAI,OAAO,SAAS,KAAK,QAAQ,IAAI,OAAO,SAAS,KAAK,QAAQ,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,OAAO,IAAI,KAAK,QAAQ;YACxH,OAAO,SAAS,CAAC;QACnB,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;IAC9C,CAAC;IAAC,MAAM,CAAC;QAAC,OAAO,SAAS,CAAC;IAAC,CAAC;AAC/B,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cotal-ai/workspace",
|
|
3
3
|
"description": "Cotal machine-local workstation layer: the ~/.cotal mesh registry, target resolution, preflight, on-disk auth-path I/O, and the command-copy renderer — operator concerns over a local checkout, kept separate from the wire protocol in @cotal-ai/core.",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.70.0",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
}
|
|
19
19
|
},
|
|
20
20
|
"dependencies": {
|
|
21
|
-
"@cotal-ai/core": "0.
|
|
21
|
+
"@cotal-ai/core": "0.70.0"
|
|
22
22
|
},
|
|
23
23
|
"devDependencies": {
|
|
24
24
|
"@cotal-ai/smoke-kit": "0.0.0"
|