talentos 1.0.0 → 1.1.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/README.md +31 -0
- package/dist/agent/adapters.js +363 -0
- package/dist/agent/gateway.js +70 -0
- package/dist/agent/mcp-entry.js +11 -0
- package/dist/agent/serve.js +254 -0
- package/dist/agent/sessions.js +36 -0
- package/dist/agent-config.js +105 -0
- package/dist/agent-http.js +182 -0
- package/dist/agent-link.js +49 -0
- package/dist/agent-service.js +152 -0
- package/dist/args.js +4 -1
- package/dist/commands/agent-serve.js +45 -0
- package/dist/commands/agent.js +278 -0
- package/dist/gateway-install.js +343 -0
- package/dist/gateway-version.js +45 -0
- package/dist/index.js +24 -1
- package/package.json +2 -1
|
@@ -0,0 +1,343 @@
|
|
|
1
|
+
import { execFile } from "node:child_process";
|
|
2
|
+
import { randomUUID } from "node:crypto";
|
|
3
|
+
import { cp, link, mkdir, readdir, readFile, readlink, realpath, rename, rm, stat, symlink, } from "node:fs/promises";
|
|
4
|
+
import { dirname, join } from "node:path";
|
|
5
|
+
import { setTimeout as delay } from "node:timers/promises";
|
|
6
|
+
import { fileURLToPath } from "node:url";
|
|
7
|
+
import { promisify } from "node:util";
|
|
8
|
+
import { writePrivateFile } from "./agent-config.js";
|
|
9
|
+
import { compareGatewayVersions } from "./gateway-version.js";
|
|
10
|
+
import { homeDir } from "./install.js";
|
|
11
|
+
const exec = promisify(execFile);
|
|
12
|
+
const TRANSIENT_BIN = /(?:\/_npx\/|node_modules\/\.bin|node-gyp-bin|\/Cellar\/|\/\.nvm\/versions\/)/;
|
|
13
|
+
const NPM_ENV = new Set([
|
|
14
|
+
"HOME",
|
|
15
|
+
"USER",
|
|
16
|
+
"LOGNAME",
|
|
17
|
+
"LANG",
|
|
18
|
+
"LC_ALL",
|
|
19
|
+
"TMPDIR",
|
|
20
|
+
"TEMP",
|
|
21
|
+
"TMP",
|
|
22
|
+
"SystemRoot",
|
|
23
|
+
"HTTP_PROXY",
|
|
24
|
+
"HTTPS_PROXY",
|
|
25
|
+
"NO_PROXY",
|
|
26
|
+
"NODE_EXTRA_CA_CERTS",
|
|
27
|
+
]);
|
|
28
|
+
export function gatewayLauncherPath(home = homeDir()) {
|
|
29
|
+
return join(home, ".talentos", "bin", "talentos-gateway");
|
|
30
|
+
}
|
|
31
|
+
export function servicePathEnv(home = homeDir()) {
|
|
32
|
+
return [
|
|
33
|
+
...new Set([
|
|
34
|
+
...(process.env.PATH ?? "")
|
|
35
|
+
.split(":")
|
|
36
|
+
.filter((entry) => entry.startsWith("/") && !TRANSIENT_BIN.test(entry)),
|
|
37
|
+
join(home, ".local/bin"),
|
|
38
|
+
join(home, ".npm-global/bin"),
|
|
39
|
+
"/opt/homebrew/bin",
|
|
40
|
+
"/usr/local/bin",
|
|
41
|
+
"/usr/bin",
|
|
42
|
+
"/bin",
|
|
43
|
+
]),
|
|
44
|
+
].join(":");
|
|
45
|
+
}
|
|
46
|
+
// No user paths are interpolated into executable shell text. The Node hint is data.
|
|
47
|
+
const LAUNCHER = `#!/bin/sh
|
|
48
|
+
set -f
|
|
49
|
+
root="\${0%/*}/.."
|
|
50
|
+
agent=
|
|
51
|
+
next_agent=
|
|
52
|
+
for argument in "$@"; do
|
|
53
|
+
if [ "$next_agent" = yes ]; then agent=$argument; break; fi
|
|
54
|
+
if [ "$argument" = --agent ]; then next_agent=yes; fi
|
|
55
|
+
done
|
|
56
|
+
node_missing=
|
|
57
|
+
case "$agent" in
|
|
58
|
+
''|*[!a-zA-Z0-9_-]*) ;;
|
|
59
|
+
*) node_missing="$root/agents/$agent/.node-missing" ;;
|
|
60
|
+
esac
|
|
61
|
+
qualifies() {
|
|
62
|
+
[ -n "$1" ] && [ -x "$1" ] && "$1" -e 'process.exit(Number(process.versions.node.split(".")[0]) >= 20 ? 0 : 1)' >/dev/null 2>&1
|
|
63
|
+
}
|
|
64
|
+
start() {
|
|
65
|
+
if [ -n "$node_missing" ]; then /bin/rm -f "$node_missing"; fi
|
|
66
|
+
node=$1
|
|
67
|
+
shift
|
|
68
|
+
PATH="\${node%/*}:\${PATH:-/usr/bin:/bin}"
|
|
69
|
+
export PATH
|
|
70
|
+
exec "$node" "$root/cli/current/node_modules/talentos/dist/index.js" "$@"
|
|
71
|
+
}
|
|
72
|
+
node_hint=
|
|
73
|
+
IFS= read -r node_hint < "$root/cli/node-path" || :
|
|
74
|
+
if qualifies "\${TALENTOS_NODE:-}"; then
|
|
75
|
+
start "$TALENTOS_NODE" "$@"
|
|
76
|
+
fi
|
|
77
|
+
if qualifies "$node_hint"; then
|
|
78
|
+
start "$node_hint" "$@"
|
|
79
|
+
fi
|
|
80
|
+
old_ifs=$IFS
|
|
81
|
+
IFS=:
|
|
82
|
+
for dir in \${PATH:-}; do
|
|
83
|
+
IFS=$old_ifs
|
|
84
|
+
if qualifies "$dir/node"; then
|
|
85
|
+
start "$dir/node" "$@"
|
|
86
|
+
fi
|
|
87
|
+
IFS=:
|
|
88
|
+
done
|
|
89
|
+
IFS=$old_ifs
|
|
90
|
+
for candidate in /opt/homebrew/bin/node /usr/local/bin/node; do
|
|
91
|
+
if qualifies "$candidate"; then
|
|
92
|
+
start "$candidate" "$@"
|
|
93
|
+
fi
|
|
94
|
+
done
|
|
95
|
+
# nvm has no stable system bin; discover surviving installations at startup.
|
|
96
|
+
set +f
|
|
97
|
+
for candidate in "$root"/../.nvm/versions/node/*/bin/node; do
|
|
98
|
+
if qualifies "$candidate"; then start "$candidate" "$@"; fi
|
|
99
|
+
done
|
|
100
|
+
message='TalentOS gateway requires Node.js 20 or newer. Install Node, then run talentos agent repair.'
|
|
101
|
+
if [ -z "$node_missing" ]; then
|
|
102
|
+
echo "$message" >&2
|
|
103
|
+
elif (set -C; : > "$node_missing") 2>/dev/null; then
|
|
104
|
+
echo "$message" >> "$root/agents/$agent/gateway.log"
|
|
105
|
+
fi
|
|
106
|
+
exit 78
|
|
107
|
+
`;
|
|
108
|
+
async function manifestVersion(root) {
|
|
109
|
+
return JSON.parse(await readFile(join(root, "package.json"), "utf8")).version;
|
|
110
|
+
}
|
|
111
|
+
async function copyPackage(source, destination) {
|
|
112
|
+
await mkdir(destination, { recursive: true, mode: 0o700 });
|
|
113
|
+
for (const name of ["package.json", "dist", "node_modules"]) {
|
|
114
|
+
try {
|
|
115
|
+
await cp(join(source, name), join(destination, name), {
|
|
116
|
+
recursive: true,
|
|
117
|
+
dereference: true,
|
|
118
|
+
force: true,
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
catch (error) {
|
|
122
|
+
if (name !== "node_modules" ||
|
|
123
|
+
error.code !== "ENOENT") {
|
|
124
|
+
throw error;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
async function installed(root, version) {
|
|
130
|
+
try {
|
|
131
|
+
if ((await manifestVersion(root)) !== version ||
|
|
132
|
+
!(await readFile(join(root, "dist/index.js"))).length) {
|
|
133
|
+
return false;
|
|
134
|
+
}
|
|
135
|
+
const { dependencies = {} } = JSON.parse(await readFile(join(root, "package.json"), "utf8"));
|
|
136
|
+
// The SDK has no root entrypoint. Load the same exports the CLI uses;
|
|
137
|
+
// imports also catch missing transitive dependencies in partial installs.
|
|
138
|
+
const imports = Object.keys(dependencies).flatMap((name) => name === "@modelcontextprotocol/sdk"
|
|
139
|
+
? [
|
|
140
|
+
`${name}/client/index.js`,
|
|
141
|
+
`${name}/server/index.js`,
|
|
142
|
+
`${name}/types.js`,
|
|
143
|
+
]
|
|
144
|
+
: [name]);
|
|
145
|
+
if (imports.length) {
|
|
146
|
+
await exec(process.execPath, [
|
|
147
|
+
"--input-type=module",
|
|
148
|
+
"--eval",
|
|
149
|
+
`await Promise.all(${JSON.stringify(imports)}.map(name => import(name)))`,
|
|
150
|
+
], { cwd: root, timeout: 15_000 });
|
|
151
|
+
}
|
|
152
|
+
return true;
|
|
153
|
+
}
|
|
154
|
+
catch (error) {
|
|
155
|
+
if (error.killed) {
|
|
156
|
+
throw new Error("Gateway dependency check timed out. Keeping the current version; retry agent repair shortly.");
|
|
157
|
+
}
|
|
158
|
+
return false;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
async function installLock(root, signal) {
|
|
162
|
+
const path = join(root, ".install-lock");
|
|
163
|
+
const pending = join(root, `.lock-${randomUUID()}`);
|
|
164
|
+
const contents = `${process.pid}\n${randomUUID()}`;
|
|
165
|
+
// Publish a populated lock atomically so a second installer never sees an
|
|
166
|
+
// empty new lock and mistakes it for one left behind by a crash.
|
|
167
|
+
await writePrivateFile(pending, contents);
|
|
168
|
+
try {
|
|
169
|
+
for (let attempt = 0; attempt < 600; attempt++) {
|
|
170
|
+
signal?.throwIfAborted();
|
|
171
|
+
try {
|
|
172
|
+
await link(pending, path);
|
|
173
|
+
return async () => {
|
|
174
|
+
if ((await readFile(path, "utf8").catch(() => "")) === contents) {
|
|
175
|
+
await rm(path, { force: true });
|
|
176
|
+
}
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
catch (error) {
|
|
180
|
+
if (error.code !== "EEXIST") {
|
|
181
|
+
throw error;
|
|
182
|
+
}
|
|
183
|
+
try {
|
|
184
|
+
const lock = await readFile(path, "utf8");
|
|
185
|
+
const metadata = await stat(path);
|
|
186
|
+
const age = Date.now() - metadata.mtimeMs;
|
|
187
|
+
const pid = Number(lock.split("\n")[0]);
|
|
188
|
+
let stale = !lock.trim() || age > 5 * 60_000;
|
|
189
|
+
if (!stale && pid > 0) {
|
|
190
|
+
try {
|
|
191
|
+
process.kill(pid, 0);
|
|
192
|
+
}
|
|
193
|
+
catch (failure) {
|
|
194
|
+
stale = failure.code === "ESRCH";
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
if (stale && (await readFile(path, "utf8")) === lock) {
|
|
198
|
+
const latest = await stat(path);
|
|
199
|
+
if (latest.dev === metadata.dev && latest.ino === metadata.ino) {
|
|
200
|
+
await rm(path, { force: true });
|
|
201
|
+
continue;
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
catch (error) {
|
|
206
|
+
if (error.code !== "ENOENT") {
|
|
207
|
+
throw error;
|
|
208
|
+
}
|
|
209
|
+
continue;
|
|
210
|
+
}
|
|
211
|
+
await delay(200, undefined, { signal });
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
throw new Error("Another gateway installation is still running. Retry agent repair shortly.");
|
|
215
|
+
}
|
|
216
|
+
finally {
|
|
217
|
+
await rm(pending, { force: true });
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
export async function installSharedGateway(options = {}) {
|
|
221
|
+
const home = options.home ?? homeDir();
|
|
222
|
+
const source = options.source ?? fileURLToPath(new URL("../", import.meta.url));
|
|
223
|
+
const ownVersion = await manifestVersion(source);
|
|
224
|
+
let version = options.version ?? ownVersion;
|
|
225
|
+
if (compareGatewayVersions(version, version) === undefined) {
|
|
226
|
+
throw new Error("Unsupported gateway version.");
|
|
227
|
+
}
|
|
228
|
+
const root = join(home, ".talentos/cli");
|
|
229
|
+
await mkdir(root, { recursive: true, mode: 0o700 });
|
|
230
|
+
const release = await installLock(root, options.signal);
|
|
231
|
+
const temporary = join(root, `.install-${randomUUID()}`);
|
|
232
|
+
const pointer = join(root, `.current-${randomUUID()}`);
|
|
233
|
+
let stagedVersion;
|
|
234
|
+
try {
|
|
235
|
+
const active = await readlink(join(root, "current")).catch(() => "");
|
|
236
|
+
if ((compareGatewayVersions(active, version) ?? 0) > 0 &&
|
|
237
|
+
(await installed(join(root, active, "node_modules/talentos"), active))) {
|
|
238
|
+
version = active;
|
|
239
|
+
}
|
|
240
|
+
const destination = join(root, version);
|
|
241
|
+
const pkg = join(destination, "node_modules/talentos");
|
|
242
|
+
if (!(await installed(pkg, version))) {
|
|
243
|
+
await mkdir(temporary, { mode: 0o700 });
|
|
244
|
+
// Local builds have not been published. Copy resolved dependencies too,
|
|
245
|
+
// so pnpm's symlinks cannot strand the installed gateway in a worktree.
|
|
246
|
+
if (version === ownVersion &&
|
|
247
|
+
!source.includes("/node_modules/talentos")) {
|
|
248
|
+
await copyPackage(source, join(temporary, "node_modules/talentos"));
|
|
249
|
+
}
|
|
250
|
+
else {
|
|
251
|
+
const npmEnv = {
|
|
252
|
+
PATH: `${process.env.PATH ?? servicePathEnv()}:${dirname(process.execPath)}`,
|
|
253
|
+
};
|
|
254
|
+
for (const [key, value] of Object.entries(process.env)) {
|
|
255
|
+
if ((NPM_ENV.has(key) || key.toLowerCase().startsWith("npm_config_")) &&
|
|
256
|
+
value) {
|
|
257
|
+
npmEnv[key] = value;
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
try {
|
|
261
|
+
await exec("npm", [
|
|
262
|
+
"install",
|
|
263
|
+
"--prefix",
|
|
264
|
+
temporary,
|
|
265
|
+
"--omit=dev",
|
|
266
|
+
"--ignore-scripts",
|
|
267
|
+
"--no-audit",
|
|
268
|
+
"--no-fund",
|
|
269
|
+
`talentos@${version}`,
|
|
270
|
+
], { env: npmEnv, signal: options.signal, timeout: 90_000 });
|
|
271
|
+
}
|
|
272
|
+
catch {
|
|
273
|
+
if (version === ownVersion) {
|
|
274
|
+
await rm(temporary, { recursive: true, force: true });
|
|
275
|
+
await copyPackage(source, join(temporary, "node_modules/talentos"));
|
|
276
|
+
}
|
|
277
|
+
else {
|
|
278
|
+
throw new Error("Gateway update failed. Serving the current version; retrying when the network is available.");
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
if (!(await installed(join(temporary, "node_modules/talentos"), version))) {
|
|
283
|
+
throw new Error("Gateway package is incomplete. Restore its runtime dependencies or retry agent repair online.");
|
|
284
|
+
}
|
|
285
|
+
await rm(destination, { recursive: true, force: true });
|
|
286
|
+
await rename(temporary, destination);
|
|
287
|
+
if (version !== active) {
|
|
288
|
+
stagedVersion = destination;
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
let previous;
|
|
292
|
+
try {
|
|
293
|
+
previous = await readlink(join(root, "current"));
|
|
294
|
+
}
|
|
295
|
+
catch {
|
|
296
|
+
/* First install. */
|
|
297
|
+
}
|
|
298
|
+
await symlink(version, pointer);
|
|
299
|
+
await rename(pointer, join(root, "current"));
|
|
300
|
+
stagedVersion = undefined;
|
|
301
|
+
const launcher = gatewayLauncherPath(home);
|
|
302
|
+
await writePrivateFile(launcher, LAUNCHER, 0o700);
|
|
303
|
+
let nodePath = options.nodePath ?? process.execPath;
|
|
304
|
+
for (const stable of [
|
|
305
|
+
"/opt/homebrew/bin/node",
|
|
306
|
+
"/usr/local/bin/node",
|
|
307
|
+
"/usr/bin/node",
|
|
308
|
+
]) {
|
|
309
|
+
if ((await realpath(stable).catch(() => "")) === nodePath) {
|
|
310
|
+
nodePath = stable;
|
|
311
|
+
break;
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
// Preserve the link-time hint during updates and repairs.
|
|
315
|
+
const hint = join(root, "node-path");
|
|
316
|
+
try {
|
|
317
|
+
await readFile(hint);
|
|
318
|
+
}
|
|
319
|
+
catch {
|
|
320
|
+
await writePrivateFile(hint, `${nodePath}\n`);
|
|
321
|
+
}
|
|
322
|
+
const keep = new Set([version, previous]);
|
|
323
|
+
const oldVersions = (await readdir(root))
|
|
324
|
+
.filter((entry) => compareGatewayVersions(entry, entry) !== undefined && !keep.has(entry))
|
|
325
|
+
.sort((a, b) => compareGatewayVersions(b, a) ?? 0);
|
|
326
|
+
// A repeat repair retains the other installed version.
|
|
327
|
+
if (previous === version) {
|
|
328
|
+
oldVersions.shift();
|
|
329
|
+
}
|
|
330
|
+
for (const old of oldVersions) {
|
|
331
|
+
await rm(join(root, old), { recursive: true, force: true });
|
|
332
|
+
}
|
|
333
|
+
return launcher;
|
|
334
|
+
}
|
|
335
|
+
finally {
|
|
336
|
+
await rm(temporary, { recursive: true, force: true });
|
|
337
|
+
await rm(pointer, { force: true });
|
|
338
|
+
if (stagedVersion) {
|
|
339
|
+
await rm(stagedVersion, { recursive: true, force: true });
|
|
340
|
+
}
|
|
341
|
+
await release();
|
|
342
|
+
}
|
|
343
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
const VERSION = /^(\d+)\.(\d+)\.(\d+)(?:-([\da-zA-Z-]+(?:\.[\da-zA-Z-]+)*))?(?:\+[\da-zA-Z-]+(?:\.[\da-zA-Z-]+)*)?$/;
|
|
2
|
+
const NUMERIC_IDENTIFIER = /^\d+$/;
|
|
3
|
+
export function compareGatewayVersions(a, b) {
|
|
4
|
+
const left = VERSION.exec(a), right = VERSION.exec(b);
|
|
5
|
+
if (!(left && right)) {
|
|
6
|
+
return;
|
|
7
|
+
}
|
|
8
|
+
for (let i = 1; i <= 3; i++) {
|
|
9
|
+
const difference = Number(left[i]) - Number(right[i]);
|
|
10
|
+
if (difference) {
|
|
11
|
+
return difference;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
if (left[4] === right[4]) {
|
|
15
|
+
return 0;
|
|
16
|
+
}
|
|
17
|
+
if (!left[4]) {
|
|
18
|
+
return 1;
|
|
19
|
+
}
|
|
20
|
+
if (!right[4]) {
|
|
21
|
+
return -1;
|
|
22
|
+
}
|
|
23
|
+
const l = left[4].split("."), r = right[4].split(".");
|
|
24
|
+
for (let i = 0; i < Math.max(l.length, r.length); i++) {
|
|
25
|
+
const x = l[i], y = r[i];
|
|
26
|
+
if (x === undefined) {
|
|
27
|
+
return -1;
|
|
28
|
+
}
|
|
29
|
+
if (y === undefined) {
|
|
30
|
+
return 1;
|
|
31
|
+
}
|
|
32
|
+
if (x === y) {
|
|
33
|
+
continue;
|
|
34
|
+
}
|
|
35
|
+
const xn = NUMERIC_IDENTIFIER.test(x), yn = NUMERIC_IDENTIFIER.test(y);
|
|
36
|
+
if (xn && yn) {
|
|
37
|
+
return Number(x) - Number(y);
|
|
38
|
+
}
|
|
39
|
+
if (xn !== yn) {
|
|
40
|
+
return xn ? -1 : 1;
|
|
41
|
+
}
|
|
42
|
+
return x < y ? -1 : 1;
|
|
43
|
+
}
|
|
44
|
+
return 0;
|
|
45
|
+
}
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { readFileSync } from "node:fs";
|
|
3
|
+
import { redactAgentOutput } from "./agent-link.js";
|
|
3
4
|
import { parseArgv } from "./args.js";
|
|
4
5
|
import { emit } from "./format.js";
|
|
5
6
|
const USAGE = `talentos — your team's skills, memory and Talent, from any coding agent.
|
|
@@ -8,6 +9,7 @@ Usage: talentos <command> [options]
|
|
|
8
9
|
|
|
9
10
|
Commands:
|
|
10
11
|
init Connect this machine's agents to TalentOS
|
|
12
|
+
agent <link|repair|status|list|unlink|logs> Bring your own agent into Rooms
|
|
11
13
|
login Authorize this machine
|
|
12
14
|
logout Forget the key stored on this machine
|
|
13
15
|
whoami Show the member and org this key acts as
|
|
@@ -26,6 +28,17 @@ Options:
|
|
|
26
28
|
|
|
27
29
|
Run \`talentos <command> --help\` for command options.`;
|
|
28
30
|
const GROUP_USAGE = {
|
|
31
|
+
agent: `talentos agent link --url <setup-url-with-#token> [--yes] [--name <device>]
|
|
32
|
+
talentos agent status | list [--json] [--agent <id>]
|
|
33
|
+
talentos agent unlink [name] [--agent <id>]
|
|
34
|
+
talentos agent logs [--agent <id>]
|
|
35
|
+
talentos agent repair [--agent <id>]
|
|
36
|
+
talentos agent serve --agent <id>
|
|
37
|
+
|
|
38
|
+
The link command checks the provider's CLI login, mints the key locally, and
|
|
39
|
+
installs one user service per agent. Only the key hash is sent to redeem.
|
|
40
|
+
Config is private under ~/.talentos/agents. Never print the setup fragment.
|
|
41
|
+
Serve is supplied by the S6 gateway release; Connected requires its heartbeat.`,
|
|
29
42
|
init: `talentos init [--for claude|cursor|codex|all] [--no-pull] [--name <device>]
|
|
30
43
|
|
|
31
44
|
One command: signs you in (skipped when your stored key still works), writes the
|
|
@@ -88,6 +101,8 @@ function helpFor(group) {
|
|
|
88
101
|
}
|
|
89
102
|
async function dispatch(parsed) {
|
|
90
103
|
switch (parsed.group) {
|
|
104
|
+
case "agent":
|
|
105
|
+
return await (await import("./commands/agent.js")).runAgent(parsed);
|
|
91
106
|
case "init":
|
|
92
107
|
return await (await import("./commands/init.js")).runInit(parsed);
|
|
93
108
|
case "login":
|
|
@@ -120,6 +135,14 @@ function version() {
|
|
|
120
135
|
}
|
|
121
136
|
main(process.argv.slice(2)).catch((error) => {
|
|
122
137
|
const message = error instanceof Error ? error.message : String(error);
|
|
123
|
-
process.
|
|
138
|
+
const fragments = process.argv.flatMap((arg) => {
|
|
139
|
+
try {
|
|
140
|
+
return new URLSearchParams(new URL(arg).hash.slice(1)).getAll("token");
|
|
141
|
+
}
|
|
142
|
+
catch {
|
|
143
|
+
return [];
|
|
144
|
+
}
|
|
145
|
+
});
|
|
146
|
+
process.stderr.write(`${redactAgentOutput(message, fragments).split("\n")[0]}\n`);
|
|
124
147
|
process.exit(1);
|
|
125
148
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "talentos",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "TalentOS CLI: push and pull skills, read and write team memory, and delegate work to your Talent from any coding agent.",
|
|
6
6
|
"repository": {
|
|
@@ -25,6 +25,7 @@
|
|
|
25
25
|
"prepack": "rm -rf dist && tsc -p tsconfig.build.json"
|
|
26
26
|
},
|
|
27
27
|
"dependencies": {
|
|
28
|
+
"convex": "^1.43.0",
|
|
28
29
|
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
29
30
|
"zod": "^4.4.3"
|
|
30
31
|
},
|