@staix/agent-hub 0.12.38 → 0.12.39
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/CHANGELOG.md +8 -0
- package/README.md +8 -4
- package/docs/agent-notes/adapters.md +3 -1
- package/docs/agent-notes/benchmarks.md +1 -1
- package/docs/agent-notes/daemon.md +2 -1
- package/docs/agent-notes/tests.md +1 -1
- package/docs/operations.md +24 -11
- package/docs/quickstart.md +9 -3
- package/docs/security.md +2 -2
- package/docs/specs/2026-09-19-agent-hub-design.md +11 -4
- package/docs/verification/2026-10-20-0.12.39.md +55 -0
- package/docs/verification/2026-10-20-jcode-tui-0.98.1.md +39 -0
- package/docs/verified.json +12 -12
- package/package.json +1 -1
- package/plugins/agent-hub/.claude-plugin/plugin.json +1 -1
- package/plugins/agent-hub/server.js +273 -53
- package/src/adapters/acp.ts +20 -2
- package/src/adapters/definitions/builtin-metadata.ts +4 -4
- package/src/adapters/definitions/native-cli-entry-jcode.ts +80 -11
- package/src/adapters/definitions/native-cli-entry-types.ts +1 -0
- package/src/adapters/definitions/native-cli-preview-common.ts +1 -0
- package/src/adapters/definitions/native-cli-preview-jcode.ts +7 -7
- package/src/adapters/definitions/native-daemon-policy.ts +1 -1
- package/src/adapters/jcode.ts +58 -1
- package/src/adapters/registry.ts +1 -1
- package/src/cli/main.ts +4 -4
- package/src/cli/preview.ts +2 -2
- package/src/hub/control-client.ts +1 -1
- package/src/hub/daemon.ts +13 -1
- package/src/hub/peers.ts +2 -2
- package/src/hub/start-mode.ts +1 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agent-hub",
|
|
3
|
-
"version": "0.12.
|
|
3
|
+
"version": "0.12.39",
|
|
4
4
|
"description": "Channel between Claude Code and the agent-hub daemon: peer messages from Codex, Kimi and the local worker arrive as channel events; hub_send replies.",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Young Joon Lee",
|
|
@@ -456,12 +456,12 @@ class BasePeer {
|
|
|
456
456
|
this._state = next;
|
|
457
457
|
this.onState?.(next);
|
|
458
458
|
}
|
|
459
|
-
touch() {
|
|
459
|
+
touch(ms = this.watchdogMs) {
|
|
460
460
|
this.clearWatchdog();
|
|
461
461
|
this.timer = setTimeout(() => {
|
|
462
462
|
if (this._state === "busy")
|
|
463
463
|
this.onWatchdog();
|
|
464
|
-
},
|
|
464
|
+
}, ms);
|
|
465
465
|
this.timer.unref?.();
|
|
466
466
|
}
|
|
467
467
|
onWatchdog() {
|
|
@@ -2551,13 +2551,14 @@ function jsonObject(text) {
|
|
|
2551
2551
|
return;
|
|
2552
2552
|
}
|
|
2553
2553
|
}
|
|
2554
|
-
var HANDSHAKE_MS = 30000, TOOL_INPUT_CAP = 64, RpcTimeoutError, AcpPeer;
|
|
2554
|
+
var HANDSHAKE_MS = 30000, TOOL_INPUT_CAP = 64, TOOL_CEILING_MS, RpcTimeoutError, AcpPeer;
|
|
2555
2555
|
var init_acp = __esm(() => {
|
|
2556
2556
|
init_envelope();
|
|
2557
2557
|
init_kimi_native();
|
|
2558
2558
|
init_qwen_native();
|
|
2559
2559
|
init_qwen_native();
|
|
2560
2560
|
init_child_process();
|
|
2561
|
+
TOOL_CEILING_MS = 30 * 60000;
|
|
2561
2562
|
RpcTimeoutError = class RpcTimeoutError extends Error {
|
|
2562
2563
|
};
|
|
2563
2564
|
AcpPeer = class AcpPeer extends BasePeer {
|
|
@@ -2575,6 +2576,8 @@ var init_acp = __esm(() => {
|
|
|
2575
2576
|
toolInputs = new Map;
|
|
2576
2577
|
toolText = new Map;
|
|
2577
2578
|
toolTitles = new Map;
|
|
2579
|
+
openTools = new Map;
|
|
2580
|
+
lastSignAt = 0;
|
|
2578
2581
|
primed = false;
|
|
2579
2582
|
turn = 0;
|
|
2580
2583
|
stopping = false;
|
|
@@ -2793,6 +2796,7 @@ var init_acp = __esm(() => {
|
|
|
2793
2796
|
this.deliveryAccepted = false;
|
|
2794
2797
|
this.promptActivity = false;
|
|
2795
2798
|
this.chunks = [];
|
|
2799
|
+
this.openTools.clear();
|
|
2796
2800
|
this.activityOpen = true;
|
|
2797
2801
|
this.activityPrivate = envs.some((env) => env.private === true);
|
|
2798
2802
|
try {
|
|
@@ -2894,6 +2898,21 @@ ${renderDigest(envs, false)}` }] });
|
|
|
2894
2898
|
this.clearWatchdog();
|
|
2895
2899
|
return;
|
|
2896
2900
|
}
|
|
2901
|
+
if (this.openTools.size) {
|
|
2902
|
+
const ceiling = Math.max(this.watchdogMs, this.opts.toolCeilingMs ?? TOOL_CEILING_MS);
|
|
2903
|
+
const remaining = ceiling - (Date.now() - this.lastSignAt);
|
|
2904
|
+
if (remaining > 0) {
|
|
2905
|
+
this.touch(Math.min(this.watchdogMs, remaining));
|
|
2906
|
+
return;
|
|
2907
|
+
}
|
|
2908
|
+
try {
|
|
2909
|
+
this.activityPrivate ||= this.opts.isPrivateTurn?.() === true;
|
|
2910
|
+
} catch {
|
|
2911
|
+
this.activityPrivate = true;
|
|
2912
|
+
}
|
|
2913
|
+
const tools = this.activityPrivate ? "a tool call" : [...new Set(this.openTools.values())].map((title) => JSON.stringify(activityText(title).replace(/[\p{Cc}\p{Cf}\p{Zl}\p{Zp}]/gu, " ").slice(0, 80))).join(", ");
|
|
2914
|
+
this.opts.log?.(`[${this.id}] open tool call (${tools}) silent past the ${Math.round(ceiling / 60000)} min tool ceiling; cancelling the turn`);
|
|
2915
|
+
}
|
|
2897
2916
|
this.endActivity("watchdog cancelled", true);
|
|
2898
2917
|
const cancelledTurn = this.turn;
|
|
2899
2918
|
this.cancelPermissions();
|
|
@@ -2967,8 +2986,10 @@ ${renderDigest(envs, false)}` }] });
|
|
|
2967
2986
|
} catch {
|
|
2968
2987
|
return;
|
|
2969
2988
|
}
|
|
2970
|
-
if (this.state === "busy" && !this.cancelWait)
|
|
2989
|
+
if (this.state === "busy" && !this.cancelWait) {
|
|
2990
|
+
this.lastSignAt = Date.now();
|
|
2971
2991
|
this.touch();
|
|
2992
|
+
}
|
|
2972
2993
|
if (msg.method === "session/update") {
|
|
2973
2994
|
if (msg.params?.sessionId && msg.params.sessionId !== this.sessionId)
|
|
2974
2995
|
return;
|
|
@@ -2999,7 +3020,11 @@ ${renderDigest(envs, false)}` }] });
|
|
|
2999
3020
|
if (text)
|
|
3000
3021
|
this.toolText.set(u.toolCallId, text);
|
|
3001
3022
|
if (u.status === "completed" || u.status === "failed")
|
|
3002
|
-
this.toolInputs.delete(u.toolCallId), this.toolText.delete(u.toolCallId), this.toolTitles.delete(u.toolCallId);
|
|
3023
|
+
this.toolInputs.delete(u.toolCallId), this.toolText.delete(u.toolCallId), this.toolTitles.delete(u.toolCallId), this.openTools.delete(u.toolCallId);
|
|
3024
|
+
else if (u.sessionUpdate === "tool_call" || this.openTools.has(u.toolCallId))
|
|
3025
|
+
this.openTools.set(u.toolCallId, this.toolTitles.get(u.toolCallId) ?? "tool");
|
|
3026
|
+
while (this.openTools.size > TOOL_INPUT_CAP)
|
|
3027
|
+
this.openTools.delete(this.openTools.keys().next().value);
|
|
3003
3028
|
for (const map of [this.toolInputs, this.toolText, this.toolTitles])
|
|
3004
3029
|
while (map.size > TOOL_INPUT_CAP)
|
|
3005
3030
|
map.delete(map.keys().next().value);
|
|
@@ -3104,7 +3129,7 @@ ${renderDigest(envs, false)}` }] });
|
|
|
3104
3129
|
|
|
3105
3130
|
// src/adapters/jcode.ts
|
|
3106
3131
|
import { spawn as spawn6, spawnSync as spawnSync2 } from "child_process";
|
|
3107
|
-
import { existsSync as existsSync4, lstatSync as lstatSync4, mkdtempSync as mkdtempSync3, rmSync as rmSync3 } from "fs";
|
|
3132
|
+
import { closeSync, constants, existsSync as existsSync4, fstatSync, lstatSync as lstatSync4, mkdtempSync as mkdtempSync3, openSync, readSync, rmSync as rmSync3 } from "fs";
|
|
3108
3133
|
import { tmpdir as tmpdir3 } from "os";
|
|
3109
3134
|
import { isAbsolute as isAbsolute3, join as join5 } from "path";
|
|
3110
3135
|
function jcodeCommand(command, kind, socket, cwd, model, profile) {
|
|
@@ -3124,6 +3149,72 @@ function jcodeCommand(command, kind, socket, cwd, model, profile) {
|
|
|
3124
3149
|
...kind === "serve" ? ["--temporary-server", "--owner-pid", String(process.pid), "--server-name", "agent-hub-jcode"] : ["--mcp-tools", "eager"]
|
|
3125
3150
|
];
|
|
3126
3151
|
}
|
|
3152
|
+
function jcodeTuiCommand(command, socket, sessionId, model, profile) {
|
|
3153
|
+
if (!command.length || command.some((word) => typeof word !== "string" || !word))
|
|
3154
|
+
throw new Error("jcode_cmd must name an executable argv");
|
|
3155
|
+
return [
|
|
3156
|
+
...command,
|
|
3157
|
+
"--socket",
|
|
3158
|
+
socket,
|
|
3159
|
+
"--resume",
|
|
3160
|
+
sessionId,
|
|
3161
|
+
"--no-update",
|
|
3162
|
+
"--no-selfdev",
|
|
3163
|
+
...model ? ["--model", model] : [],
|
|
3164
|
+
...profile ? ["--provider-profile", profile] : []
|
|
3165
|
+
];
|
|
3166
|
+
}
|
|
3167
|
+
function savedSession(home, id) {
|
|
3168
|
+
if (!/^[A-Za-z0-9_-]{1,128}$/.test(id))
|
|
3169
|
+
throw new Error("invalid native session identity");
|
|
3170
|
+
const directory = join5(home, "sessions"), info = lstatSync4(directory, { throwIfNoEntry: false });
|
|
3171
|
+
if (!info)
|
|
3172
|
+
return false;
|
|
3173
|
+
if (!info.isDirectory() || info.isSymbolicLink())
|
|
3174
|
+
throw new Error("unsafe native session directory");
|
|
3175
|
+
const file = join5(directory, `${id}.json`), entry = lstatSync4(file, { throwIfNoEntry: false });
|
|
3176
|
+
if (!entry)
|
|
3177
|
+
return false;
|
|
3178
|
+
if (!entry.isFile() || entry.isSymbolicLink())
|
|
3179
|
+
throw new Error("unsafe native session proof");
|
|
3180
|
+
let fd;
|
|
3181
|
+
try {
|
|
3182
|
+
fd = openSync(file, constants.O_RDONLY | constants.O_NOFOLLOW | constants.O_NONBLOCK);
|
|
3183
|
+
} catch (error) {
|
|
3184
|
+
if (error.code === "ENOENT")
|
|
3185
|
+
return false;
|
|
3186
|
+
throw error;
|
|
3187
|
+
}
|
|
3188
|
+
try {
|
|
3189
|
+
const before = fstatSync(fd);
|
|
3190
|
+
if (!before.isFile() || before.nlink !== 1 || before.size > 32 * 1024 * 1024)
|
|
3191
|
+
throw new Error("unsafe native session proof");
|
|
3192
|
+
if (!before.size)
|
|
3193
|
+
return false;
|
|
3194
|
+
const bytes = Buffer.alloc(before.size);
|
|
3195
|
+
let offset = 0;
|
|
3196
|
+
while (offset < bytes.length) {
|
|
3197
|
+
const n = readSync(fd, bytes, offset, bytes.length - offset, offset);
|
|
3198
|
+
if (!n)
|
|
3199
|
+
return false;
|
|
3200
|
+
offset += n;
|
|
3201
|
+
}
|
|
3202
|
+
const after = fstatSync(fd);
|
|
3203
|
+
if (before.size !== after.size || before.mtimeMs !== after.mtimeMs || before.ctimeMs !== after.ctimeMs)
|
|
3204
|
+
return false;
|
|
3205
|
+
let data;
|
|
3206
|
+
try {
|
|
3207
|
+
data = JSON.parse(bytes.toString("utf8"));
|
|
3208
|
+
} catch {
|
|
3209
|
+
return false;
|
|
3210
|
+
}
|
|
3211
|
+
if (!data || typeof data !== "object" || data.id !== id || !Array.isArray(data.messages))
|
|
3212
|
+
throw new Error("native saved session identity is unproven");
|
|
3213
|
+
return true;
|
|
3214
|
+
} finally {
|
|
3215
|
+
closeSync(fd);
|
|
3216
|
+
}
|
|
3217
|
+
}
|
|
3127
3218
|
function jcodeVersionSupported(version) {
|
|
3128
3219
|
const v = typeof version === "string" ? release(version) : undefined;
|
|
3129
3220
|
return !!v && compare(v, release(JCODE_MIN_VERSION)) >= 0 && compare(v, release(JCODE_BREAKING_VERSION)) < 0;
|
|
@@ -3135,6 +3226,8 @@ var init_jcode = __esm(() => {
|
|
|
3135
3226
|
JCODE_OWNED_ENV = { JCODE_DISABLE_CLAUDE_MCP: "1", JCODE_NO_TELEMETRY: "1" };
|
|
3136
3227
|
JcodePeer = class JcodePeer extends AcpPeer {
|
|
3137
3228
|
jcode;
|
|
3229
|
+
launchId = crypto.randomUUID();
|
|
3230
|
+
socketIdentity;
|
|
3138
3231
|
root;
|
|
3139
3232
|
socket;
|
|
3140
3233
|
server;
|
|
@@ -3187,6 +3280,8 @@ var init_jcode = __esm(() => {
|
|
|
3187
3280
|
if (!this.ending && this.server === server)
|
|
3188
3281
|
this.stop("Jcode owned daemon disconnected").catch(() => {});
|
|
3189
3282
|
});
|
|
3283
|
+
const identity = lstatSync4(this.socket);
|
|
3284
|
+
this.socketIdentity = { dev: identity.dev, ino: identity.ino };
|
|
3190
3285
|
await super.start();
|
|
3191
3286
|
} catch (error) {
|
|
3192
3287
|
await this.stop().catch(() => {});
|
|
@@ -3252,6 +3347,21 @@ var init_jcode = __esm(() => {
|
|
|
3252
3347
|
if (failure)
|
|
3253
3348
|
throw failure;
|
|
3254
3349
|
}
|
|
3350
|
+
tuiLaunch(expected, options = {}) {
|
|
3351
|
+
const sessionId = super.recoveryMetadata().sessionId;
|
|
3352
|
+
const socket = lstatSync4(this.socket, { throwIfNoEntry: false });
|
|
3353
|
+
if (this.ending || !this.server || this.server.exitCode !== null || this.server.signalCode !== null || this.state === "offline" || !socket?.isSocket() || socket.dev !== this.socketIdentity?.dev || socket.ino !== this.socketIdentity.ino || typeof sessionId !== "string")
|
|
3354
|
+
throw new Error("owned Jcode launch is unavailable");
|
|
3355
|
+
const binding = { launchId: this.launchId, sessionId };
|
|
3356
|
+
if (expected && (expected.launchId !== binding.launchId || expected.sessionId !== binding.sessionId))
|
|
3357
|
+
throw new Error("Jcode launch changed");
|
|
3358
|
+
if (options.sessionId !== undefined && options.sessionId !== sessionId || options.model !== undefined && options.model !== this.jcode.launchModel || options.providerProfile !== undefined && options.providerProfile !== this.jcode.providerProfile)
|
|
3359
|
+
throw new Error("Jcode launch options differ from its running session");
|
|
3360
|
+
if (!savedSession(this.jcode.home, sessionId))
|
|
3361
|
+
return { state: "waiting", binding };
|
|
3362
|
+
const [cmd, ...args] = jcodeTuiCommand(this.jcode.command, this.socket, sessionId, this.jcode.launchModel, this.jcode.providerProfile);
|
|
3363
|
+
return { state: "ready", binding, launch: { cmd, args, env: { JCODE_HOME: this.jcode.home, JCODE_SOCKET: this.socket, ...JCODE_OWNED_ENV } } };
|
|
3364
|
+
}
|
|
3255
3365
|
recoveryMetadata() {
|
|
3256
3366
|
return { ...super.recoveryMetadata(), launch: { kind: "jcode", peer: "jcode", mode: "headless", ...this.jcode.launchModel ? { model: this.jcode.launchModel } : {}, ...this.jcode.providerProfile ? { providerProfile: this.jcode.providerProfile } : {} } };
|
|
3257
3367
|
}
|
|
@@ -3299,7 +3409,7 @@ var init_recovery_store = __esm(() => {
|
|
|
3299
3409
|
});
|
|
3300
3410
|
|
|
3301
3411
|
// src/pi/session.ts
|
|
3302
|
-
import { readFileSync as readFileSync4, openSync, closeSync, fsyncSync, mkdirSync as mkdirSync3 } from "fs";
|
|
3412
|
+
import { readFileSync as readFileSync4, openSync as openSync2, closeSync as closeSync2, fsyncSync, mkdirSync as mkdirSync3 } from "fs";
|
|
3303
3413
|
import { join as join7, relative as relative2, resolve as resolve5, dirname as dirname5 } from "path";
|
|
3304
3414
|
function sessionReadFailure(error) {
|
|
3305
3415
|
if (error.code === "ENOENT")
|
|
@@ -3368,7 +3478,7 @@ var init_permission_mode = __esm(() => {
|
|
|
3368
3478
|
});
|
|
3369
3479
|
|
|
3370
3480
|
// src/hub/path-policy.ts
|
|
3371
|
-
import { accessSync, constants, lstatSync as lstatSync5, opendirSync, readlinkSync, statSync as statSync2 } from "fs";
|
|
3481
|
+
import { accessSync, constants as constants2, lstatSync as lstatSync5, opendirSync, readlinkSync, statSync as statSync2 } from "fs";
|
|
3372
3482
|
import { dirname as dirname6, isAbsolute as isAbsolute4, join as join8, relative as relative3, resolve as resolve6, sep as sep2 } from "path";
|
|
3373
3483
|
function existing(path) {
|
|
3374
3484
|
try {
|
|
@@ -3423,7 +3533,7 @@ function directAliasTarget(path) {
|
|
|
3423
3533
|
return;
|
|
3424
3534
|
}
|
|
3425
3535
|
function aliasScope(dir, lexical, actual, includeParents, budget) {
|
|
3426
|
-
accessSync(dir,
|
|
3536
|
+
accessSync(dir, constants2.R_OK);
|
|
3427
3537
|
const handle = opendirSync(dir);
|
|
3428
3538
|
let matched = false;
|
|
3429
3539
|
try {
|
|
@@ -7243,7 +7353,7 @@ var init_shipped_roles = __esm(() => {
|
|
|
7243
7353
|
|
|
7244
7354
|
// src/hub/roles.ts
|
|
7245
7355
|
import { createHash as createHash5 } from "crypto";
|
|
7246
|
-
import { constants as
|
|
7356
|
+
import { constants as constants3, closeSync as closeSync3, fstatSync as fstatSync2, lstatSync as lstatSync7, openSync as openSync3, readSync as readSync2, readdirSync as readdirSync2 } from "fs";
|
|
7247
7357
|
import { join as join12 } from "path";
|
|
7248
7358
|
function parseRole(text, stem, layer) {
|
|
7249
7359
|
if (Buffer.byteLength(text) > 8192 || text.includes("\r") || !ID.test(stem))
|
|
@@ -7291,24 +7401,24 @@ function parseRole(text, stem, layer) {
|
|
|
7291
7401
|
return { id: stem, name: header.name, group: header.group, summary: header.summary, source: header.source, base: list("base", BASES2), classes: list("classes", CLASSES2), body, review, layer, hash: createHash5("sha256").update(text).digest("hex") };
|
|
7292
7402
|
}
|
|
7293
7403
|
function projectRole(file) {
|
|
7294
|
-
const fd =
|
|
7404
|
+
const fd = openSync3(file, constants3.O_RDONLY | constants3.O_NOFOLLOW | constants3.O_NONBLOCK);
|
|
7295
7405
|
try {
|
|
7296
|
-
const before =
|
|
7406
|
+
const before = fstatSync2(fd);
|
|
7297
7407
|
if (!before.isFile() || before.nlink !== 1 || before.size > 8192)
|
|
7298
7408
|
throw new Error("role must be a bounded regular file");
|
|
7299
7409
|
const bytes = Buffer.alloc(8193);
|
|
7300
7410
|
let length = 0, n = 0;
|
|
7301
|
-
while ((n =
|
|
7411
|
+
while ((n = readSync2(fd, bytes, length, bytes.length - length, null)) > 0) {
|
|
7302
7412
|
length += n;
|
|
7303
7413
|
if (length > 8192)
|
|
7304
7414
|
throw new Error("role exceeds file cap");
|
|
7305
7415
|
}
|
|
7306
|
-
const after =
|
|
7416
|
+
const after = fstatSync2(fd);
|
|
7307
7417
|
if (before.size !== after.size || before.mtimeMs !== after.mtimeMs || length !== after.size)
|
|
7308
7418
|
throw new Error("role changed during read");
|
|
7309
7419
|
return bytes.subarray(0, length).toString("utf8");
|
|
7310
7420
|
} finally {
|
|
7311
|
-
|
|
7421
|
+
closeSync3(fd);
|
|
7312
7422
|
}
|
|
7313
7423
|
}
|
|
7314
7424
|
function loadRoleCatalog(cwd) {
|
|
@@ -8254,7 +8364,7 @@ var init_reviewer_variants = __esm(() => {
|
|
|
8254
8364
|
});
|
|
8255
8365
|
|
|
8256
8366
|
// src/adapters/agy/hooks.ts
|
|
8257
|
-
import { closeSync as
|
|
8367
|
+
import { closeSync as closeSync4, constants as constants4, fstatSync as fstatSync3, lstatSync as lstatSync8, openSync as openSync4, readSync as readSync3 } from "fs";
|
|
8258
8368
|
import { homedir as homedir4 } from "os";
|
|
8259
8369
|
import { isAbsolute as isAbsolute5, join as join13, relative as relative5 } from "path";
|
|
8260
8370
|
import { createHash as createHash6 } from "crypto";
|
|
@@ -8303,8 +8413,8 @@ function readAgyTranscript(session, transcript) {
|
|
|
8303
8413
|
if (lstatSync8(cursor).isSymbolicLink())
|
|
8304
8414
|
return empty;
|
|
8305
8415
|
}
|
|
8306
|
-
fd =
|
|
8307
|
-
const stat =
|
|
8416
|
+
fd = openSync4(transcript, constants4.O_RDONLY | constants4.O_NOFOLLOW);
|
|
8417
|
+
const stat = fstatSync3(fd);
|
|
8308
8418
|
if (!stat.isFile() || stat.nlink !== 1)
|
|
8309
8419
|
return empty;
|
|
8310
8420
|
const cap = 4 * 1024 * 1024;
|
|
@@ -8313,7 +8423,7 @@ function readAgyTranscript(session, transcript) {
|
|
|
8313
8423
|
const buffer = Buffer.alloc(stat.size - from);
|
|
8314
8424
|
let bytes = 0;
|
|
8315
8425
|
while (bytes < buffer.length) {
|
|
8316
|
-
const count =
|
|
8426
|
+
const count = readSync3(fd, buffer, bytes, buffer.length - bytes, from + bytes);
|
|
8317
8427
|
if (!count)
|
|
8318
8428
|
break;
|
|
8319
8429
|
bytes += count;
|
|
@@ -8346,7 +8456,7 @@ function readAgyTranscript(session, transcript) {
|
|
|
8346
8456
|
return empty;
|
|
8347
8457
|
} finally {
|
|
8348
8458
|
if (fd !== undefined)
|
|
8349
|
-
|
|
8459
|
+
closeSync4(fd);
|
|
8350
8460
|
}
|
|
8351
8461
|
}
|
|
8352
8462
|
var EVENTS, UUID, record3 = (value) => !!value && typeof value === "object" && !Array.isArray(value), AGY_FACTS_HOOK;
|
|
@@ -8461,7 +8571,7 @@ function bundleInStatus(status) {
|
|
|
8461
8571
|
|
|
8462
8572
|
// src/cli/agy-mcp.ts
|
|
8463
8573
|
import { randomUUID as randomUUID5 } from "crypto";
|
|
8464
|
-
import { closeSync as
|
|
8574
|
+
import { closeSync as closeSync5, fstatSync as fstatSync4, lstatSync as lstatSync9, mkdirSync as mkdirSync6, openSync as openSync5, readFileSync as readFileSync6, renameSync, rmdirSync, unlinkSync, writeFileSync as writeFileSync4 } from "fs";
|
|
8465
8575
|
import { isAbsolute as isAbsolute6, join as join14, resolve as resolve10 } from "path";
|
|
8466
8576
|
import { isDeepStrictEqual } from "util";
|
|
8467
8577
|
function object4(value) {
|
|
@@ -8712,11 +8822,11 @@ function atomicWrite(path, bytes, expected, plan) {
|
|
|
8712
8822
|
let tempIdentity;
|
|
8713
8823
|
try {
|
|
8714
8824
|
verifyPluginDirectory(plan, path);
|
|
8715
|
-
fd =
|
|
8716
|
-
const tempStat =
|
|
8825
|
+
fd = openSync5(temporary, "wx", 384);
|
|
8826
|
+
const tempStat = fstatSync4(fd);
|
|
8717
8827
|
tempIdentity = { dev: tempStat.dev, ino: tempStat.ino };
|
|
8718
8828
|
writeFileSync4(fd, bytes);
|
|
8719
|
-
|
|
8829
|
+
closeSync5(fd);
|
|
8720
8830
|
fd = undefined;
|
|
8721
8831
|
verifyPluginDirectory(plan, path);
|
|
8722
8832
|
if (!identityMatches(path, expected))
|
|
@@ -8728,7 +8838,7 @@ function atomicWrite(path, bytes, expected, plan) {
|
|
|
8728
8838
|
return { dev: stat.dev, ino: stat.ino };
|
|
8729
8839
|
} finally {
|
|
8730
8840
|
if (fd !== undefined)
|
|
8731
|
-
|
|
8841
|
+
closeSync5(fd);
|
|
8732
8842
|
try {
|
|
8733
8843
|
const current = lstatSync9(temporary, { throwIfNoEntry: false });
|
|
8734
8844
|
if (current && tempIdentity && current.dev === tempIdentity.dev && current.ino === tempIdentity.ino)
|
|
@@ -9108,22 +9218,89 @@ var init_native_cli_entry_codex = () => {};
|
|
|
9108
9218
|
|
|
9109
9219
|
// src/adapters/definitions/native-cli-entry-jcode.ts
|
|
9110
9220
|
import { resolve as resolve12 } from "path";
|
|
9221
|
+
async function waitForJcodeTui(hub, fail, signal, options, first) {
|
|
9222
|
+
let binding = first?.binding, announced = false, current = first;
|
|
9223
|
+
while (!signal.aborted) {
|
|
9224
|
+
if (!current) {
|
|
9225
|
+
const reply = await hub.request({ t: "native_tui_launch", peer: "jcode", binding, args: options });
|
|
9226
|
+
if (signal.aborted)
|
|
9227
|
+
return;
|
|
9228
|
+
if (!reply.ok || !reply.binding || !["waiting", "ready"].includes(reply.state))
|
|
9229
|
+
fail("Jcode launch changed or its native saved session is unavailable; retry from a terminal");
|
|
9230
|
+
current = reply;
|
|
9231
|
+
}
|
|
9232
|
+
if (binding && (binding.launchId !== current.binding.launchId || binding.sessionId !== current.binding.sessionId))
|
|
9233
|
+
fail("Jcode launch changed while waiting");
|
|
9234
|
+
binding = current.binding;
|
|
9235
|
+
if (current.state === "ready")
|
|
9236
|
+
return current;
|
|
9237
|
+
if (!announced) {
|
|
9238
|
+
console.log(WAITING);
|
|
9239
|
+
announced = true;
|
|
9240
|
+
}
|
|
9241
|
+
await new Promise((resolve) => {
|
|
9242
|
+
const finish = () => {
|
|
9243
|
+
clearTimeout(timer);
|
|
9244
|
+
signal.removeEventListener("abort", finish);
|
|
9245
|
+
resolve();
|
|
9246
|
+
};
|
|
9247
|
+
const timer = setTimeout(finish, 200);
|
|
9248
|
+
signal.addEventListener("abort", finish, { once: true });
|
|
9249
|
+
if (signal.aborted)
|
|
9250
|
+
finish();
|
|
9251
|
+
});
|
|
9252
|
+
current = undefined;
|
|
9253
|
+
}
|
|
9254
|
+
}
|
|
9111
9255
|
async function runJcodeEntry(ctx) {
|
|
9112
9256
|
const { args, cwd, stateDir, cliDir, unattendedEnv, connect, fail, takeFlags } = ctx;
|
|
9113
|
-
const { launcherPreview, qwenSessionId, configureJcodeMcp } = ctx.helpers;
|
|
9114
|
-
|
|
9257
|
+
const { launcherPreview, qwenSessionId, configureJcodeMcp, readControl, startModeOf } = ctx.helpers;
|
|
9258
|
+
const print = args.includes("--print-command");
|
|
9259
|
+
if (args.includes("--dry-run") || print) {
|
|
9260
|
+
if (!print || args.includes("--dry-run") || !ctx.person) {
|
|
9261
|
+
try {
|
|
9262
|
+
return console.log(JSON.stringify(launcherPreview("jcode", args, cwd, stateDir, unattendedEnv), null, 2));
|
|
9263
|
+
} catch {
|
|
9264
|
+
fail("cannot preview Jcode launch: invalid arguments or configuration (details withheld)");
|
|
9265
|
+
}
|
|
9266
|
+
}
|
|
9267
|
+
}
|
|
9268
|
+
const { one, rest } = takeFlags(args.filter((arg) => arg !== "--print-command"), ["--mode", "--model", "--provider-profile", "--session-id"], []);
|
|
9269
|
+
if (rest.length || one["--mode"] !== undefined && !["headless", "tui"].includes(one["--mode"]))
|
|
9270
|
+
fail("usage: ahub jcode [--mode tui|headless] [--model <alias>] [--provider-profile <name>] [--session-id <id>]");
|
|
9271
|
+
if (one["--session-id"] !== undefined && !qwenSessionId(one["--session-id"]))
|
|
9272
|
+
fail("invalid Jcode session identity");
|
|
9273
|
+
const control = readControl(stateDir);
|
|
9274
|
+
const mode = one["--mode"] ?? (ctx.instance ? "headless" : control?.startModes?.jcode ?? startModeOf(ctx.projectConfig().peers, "jcode"));
|
|
9275
|
+
if (print && (mode === "headless" || !control?.features?.includes("native_tui_launch"))) {
|
|
9115
9276
|
try {
|
|
9116
9277
|
return console.log(JSON.stringify(launcherPreview("jcode", args, cwd, stateDir, unattendedEnv), null, 2));
|
|
9117
9278
|
} catch {
|
|
9118
|
-
fail("cannot preview Jcode launch: invalid arguments or configuration (details withheld)");
|
|
9279
|
+
return fail("cannot preview Jcode launch: invalid arguments or configuration (details withheld)");
|
|
9119
9280
|
}
|
|
9120
9281
|
}
|
|
9121
|
-
|
|
9122
|
-
|
|
9123
|
-
|
|
9124
|
-
|
|
9125
|
-
|
|
9126
|
-
|
|
9282
|
+
if (mode === "tui" && !ctx.person)
|
|
9283
|
+
fail("Jcode's private TUI is person-only; run ahub jcode in your terminal");
|
|
9284
|
+
const hub = await connect(), abort = new AbortController;
|
|
9285
|
+
let interrupted = false;
|
|
9286
|
+
const interruptedWait = () => {
|
|
9287
|
+
if (abort.signal.aborted && !interrupted)
|
|
9288
|
+
fail("hub connection closed while waiting for Jcode; retry from a terminal");
|
|
9289
|
+
return abort.signal.aborted;
|
|
9290
|
+
};
|
|
9291
|
+
const interrupt = () => {
|
|
9292
|
+
interrupted = true;
|
|
9293
|
+
abort.abort();
|
|
9294
|
+
hub.close();
|
|
9295
|
+
process.exitCode = 130;
|
|
9296
|
+
};
|
|
9297
|
+
process.once("SIGINT", interrupt);
|
|
9298
|
+
const oldClose = hub.onClose;
|
|
9299
|
+
hub.onClose = (code, reason) => {
|
|
9300
|
+
if (!abort.signal.aborted)
|
|
9301
|
+
abort.abort();
|
|
9302
|
+
oldClose?.(code, reason);
|
|
9303
|
+
};
|
|
9127
9304
|
try {
|
|
9128
9305
|
const snapshot = (await hub.request({ t: "status" })).status;
|
|
9129
9306
|
const rostered = rosterInStatus(snapshot, "jcode");
|
|
@@ -9134,17 +9311,60 @@ async function runJcodeEntry(ctx) {
|
|
|
9134
9311
|
const warning = retainedLaunchWarning(snapshot, "jcode", ctx.definition);
|
|
9135
9312
|
if (warning)
|
|
9136
9313
|
console.error(warning);
|
|
9314
|
+
const options = { model: one["--model"], providerProfile: one["--provider-profile"], sessionId: one["--session-id"] };
|
|
9315
|
+
if (print) {
|
|
9316
|
+
if (!hub.features.includes("native_tui_launch") || mode !== "tui")
|
|
9317
|
+
return console.log(JSON.stringify(launcherPreview("jcode", args, cwd, stateDir, unattendedEnv), null, 2));
|
|
9318
|
+
const reply = await hub.request({ t: "native_tui_launch", peer: "jcode", args: options });
|
|
9319
|
+
if (!reply.ok || reply.state !== "ready")
|
|
9320
|
+
fail("Jcode's selected native session is not saved and ready; run ahub jcode to wait for its first hub turn");
|
|
9321
|
+
return console.log(JSON.stringify(reply.launch, null, 2));
|
|
9322
|
+
}
|
|
9323
|
+
if (mode === "tui") {
|
|
9324
|
+
if (!hub.features.includes("native_tui_launch"))
|
|
9325
|
+
fail("the running hub does not support Jcode TUI launch; upgrade it before retrying");
|
|
9326
|
+
if (!process.stdin.isTTY || !process.stdout.isTTY) {
|
|
9327
|
+
if (one["--mode"] || Object.values(options).some((value) => value !== undefined))
|
|
9328
|
+
fail("run ahub jcode with these options in a terminal");
|
|
9329
|
+
const reply = await hub.request({ t: "peer_start", peer: "jcode" });
|
|
9330
|
+
if (!reply.ok)
|
|
9331
|
+
fail(reply.error);
|
|
9332
|
+
console.log(reply.command ?? "Jcode terminal requested");
|
|
9333
|
+
return;
|
|
9334
|
+
}
|
|
9335
|
+
}
|
|
9137
9336
|
const written = configureJcodeMcp(cwd, stateDir, bundleInStatus(snapshot) ?? resolve12(cliDir, "../../plugins/agent-hub/server.js"));
|
|
9138
9337
|
if (written.tracked)
|
|
9139
9338
|
console.error(".jcode/mcp.json is tracked; review this local machine-path change before committing it");
|
|
9140
|
-
const reply = await hub.request({ t: "start", peer: "jcode", args: { mode
|
|
9339
|
+
const reply = await hub.request({ t: "start", peer: "jcode", args: { mode, ...options }, operationId: process.env.AGENTHUB_RECOVERY_OPERATION }, 65000);
|
|
9340
|
+
if (interruptedWait())
|
|
9341
|
+
return;
|
|
9141
9342
|
if (!reply.ok)
|
|
9142
9343
|
fail(reply.error);
|
|
9143
|
-
|
|
9344
|
+
if (mode === "headless") {
|
|
9345
|
+
console.log(reply.already ? "jcode is already attached" : "jcode attached (headless); native policy unmanaged, NO hub sandbox");
|
|
9346
|
+
return;
|
|
9347
|
+
}
|
|
9348
|
+
const ready = await waitForJcodeTui(hub, fail, abort.signal, options);
|
|
9349
|
+
if (interruptedWait() || !ready)
|
|
9350
|
+
return;
|
|
9351
|
+
const instanceId = typeof snapshot?.instanceId === "string" ? snapshot.instanceId : undefined;
|
|
9352
|
+
if (!instanceId)
|
|
9353
|
+
return fail("cannot bind Jcode's terminal to the running hub");
|
|
9354
|
+
await ctx.helpers.recordTerminalLaunch("jcode", cwd, stateDir, instanceId);
|
|
9355
|
+
const confirmed = await hub.request({ t: "native_tui_launch", peer: "jcode", binding: ready.binding, args: options });
|
|
9356
|
+
if (interruptedWait())
|
|
9357
|
+
return;
|
|
9358
|
+
if (!confirmed.ok || confirmed.state !== "ready")
|
|
9359
|
+
fail("Jcode launch changed before its terminal opened");
|
|
9360
|
+
ctx.execWithEnv(confirmed.launch.cmd, confirmed.launch.args, { ...ctx.helpers.childEnv(), ...confirmed.launch.env });
|
|
9144
9361
|
} finally {
|
|
9362
|
+
process.removeListener("SIGINT", interrupt);
|
|
9363
|
+
hub.onClose = oldClose;
|
|
9145
9364
|
hub.close();
|
|
9146
9365
|
}
|
|
9147
9366
|
}
|
|
9367
|
+
var WAITING = "jcode's TUI opens after its first hub turn; send it work, or Ctrl-C";
|
|
9148
9368
|
var init_native_cli_entry_jcode = () => {};
|
|
9149
9369
|
|
|
9150
9370
|
// src/adapters/definitions/native-cli-entry-qwen.ts
|
|
@@ -9605,23 +9825,23 @@ var init_native_cli_preview_qwen = () => {};
|
|
|
9605
9825
|
// src/adapters/definitions/native-cli-preview-jcode.ts
|
|
9606
9826
|
function previewJcode(ctx) {
|
|
9607
9827
|
const { args, config } = ctx;
|
|
9608
|
-
const { jcodeCommand, qwenSessionId } = ctx.helpers;
|
|
9828
|
+
const { jcodeCommand, jcodeTuiCommand, qwenSessionId, startModeOf } = ctx.helpers;
|
|
9609
9829
|
const state = previewState(args, ctx.baseEnvNames), { unresolved, value } = state;
|
|
9610
9830
|
let envNames = state.envNames;
|
|
9611
9831
|
let launch;
|
|
9612
|
-
const mode = value("--mode") ?? "
|
|
9613
|
-
if (mode !== "headless")
|
|
9614
|
-
throw new Error("Jcode
|
|
9832
|
+
const mode = value("--mode") ?? startModeOf(config.peers, "jcode"), model = value("--model"), profile = value("--provider-profile"), session = value("--session-id");
|
|
9833
|
+
if (mode !== "headless" && mode !== "tui")
|
|
9834
|
+
throw new Error("invalid Jcode start mode");
|
|
9615
9835
|
for (let i = 0;i < args.length; i += 2)
|
|
9616
9836
|
if (!["--model", "--mode", "--provider-profile", "--session-id"].includes(args[i]) || !args[i + 1])
|
|
9617
9837
|
throw new Error("unknown Jcode option");
|
|
9618
9838
|
if (session !== undefined && !qwenSessionId(session))
|
|
9619
9839
|
throw new Error("invalid Jcode session identity");
|
|
9620
|
-
const cmd = jcodeCommand(nativeCommand(config.jcode_cmd, ["jcode"]), "acp", UNRESOLVED, UNRESOLVED, model ? REDACTED : undefined, profile || config.jcode_provider_profile ? REDACTED : undefined);
|
|
9840
|
+
const cmd = mode === "tui" ? jcodeTuiCommand(nativeCommand(config.jcode_cmd, ["jcode"]), UNRESOLVED, UNRESOLVED, model ? REDACTED : undefined, profile || config.jcode_provider_profile ? REDACTED : undefined) : jcodeCommand(nativeCommand(config.jcode_cmd, ["jcode"]), "acp", UNRESOLVED, UNRESOLVED, model ? REDACTED : undefined, profile || config.jcode_provider_profile ? REDACTED : undefined);
|
|
9621
9841
|
launch = { cmd: cmd[0], args: cmd.slice(1) };
|
|
9622
9842
|
unresolved.push({ field: "ownedDaemon", reason: "private daemon/socket and source-pinned native identity verified at start; preview starts nothing" });
|
|
9623
9843
|
unresolved.push({ field: "hubTools", reason: "project MCP bridge required; native tool-call receipt remains unverified" });
|
|
9624
|
-
return finishPreview(ctx, launch, envNames, unresolved,
|
|
9844
|
+
return { ...finishPreview(ctx, launch, envNames, unresolved), mode };
|
|
9625
9845
|
}
|
|
9626
9846
|
var init_native_cli_preview_jcode = () => {};
|
|
9627
9847
|
|
|
@@ -9651,7 +9871,7 @@ function kimiAcpCommand(command, model) {
|
|
|
9651
9871
|
}
|
|
9652
9872
|
|
|
9653
9873
|
// src/adapters/definitions/native-daemon-policy.ts
|
|
9654
|
-
var claudeRecoveryLaunch = (instance) => ({ kind: "claude-channel", peer: instance }), kimiRecoveryLaunch = (instance) => ({ kind: "kimi-tui", peer: instance, mode: "tui" }), claudeRetainedTerminalNotice = (instance) => `Stop ${instance}'s existing work in its retained terminal; removal detaches the hub connection and does not stop that terminal's work.`, piRetainedTerminalNotice = (instance, form) => form === "tui" ? claudeRetainedTerminalNotice(instance) : undefined, codexRetainedTerminalNotice = (_instance, _form, resumeCommand) => `Check codex's existing terminal and stop any remaining work. Its app-server and proxy stay available, but Codex 0.146.0 exits its TUI on disconnect and does not reconnect automatically; after ahub roster add codex, resume the previous session with ${resumeCommand}.`, codexRosterReturnNotice = (resumeCommand) => `Codex 0.146.0 needs a manual return: resume the previous native session with ${resumeCommand}.`, jcodeStartPreflight = (request) => request.form !== undefined && request.form !== "headless"
|
|
9874
|
+
var claudeRecoveryLaunch = (instance) => ({ kind: "claude-channel", peer: instance }), kimiRecoveryLaunch = (instance) => ({ kind: "kimi-tui", peer: instance, mode: "tui" }), claudeRetainedTerminalNotice = (instance) => `Stop ${instance}'s existing work in its retained terminal; removal detaches the hub connection and does not stop that terminal's work.`, piRetainedTerminalNotice = (instance, form) => form === "tui" ? claudeRetainedTerminalNotice(instance) : undefined, codexRetainedTerminalNotice = (_instance, _form, resumeCommand) => `Check codex's existing terminal and stop any remaining work. Its app-server and proxy stay available, but Codex 0.146.0 exits its TUI on disconnect and does not reconnect automatically; after ahub roster add codex, resume the previous session with ${resumeCommand}.`, codexRosterReturnNotice = (resumeCommand) => `Codex 0.146.0 needs a manual return: resume the previous native session with ${resumeCommand}.`, jcodeStartPreflight = (request) => request.form !== undefined && request.form !== "headless" && request.form !== "tui" ? "invalid Jcode start mode" : undefined, claudeObservedVersion = (context) => context.observedVersion, codexObservedVersion = (context) => context.peer?.version ?? context.observedVersion;
|
|
9655
9875
|
|
|
9656
9876
|
// src/adapters/definitions/native-config-policy.ts
|
|
9657
9877
|
function piConfigSchema(v) {
|
|
@@ -9697,7 +9917,7 @@ var init_native_config_policy = __esm(() => {
|
|
|
9697
9917
|
});
|
|
9698
9918
|
|
|
9699
9919
|
// src/adapters/definitions/native-policy-aux.ts
|
|
9700
|
-
import { closeSync as
|
|
9920
|
+
import { closeSync as closeSync6, constants as constants5, fstatSync as fstatSync5, openSync as openSync6, readdirSync as readdirSync3, readFileSync as readFileSync9 } from "fs";
|
|
9701
9921
|
import { isAbsolute as isAbsolute7, join as join20, normalize } from "path";
|
|
9702
9922
|
function claudeCrashPlan(_meta) {
|
|
9703
9923
|
return { how: "claude: the Claude Code plugin reconnects by itself while that session is still open" };
|
|
@@ -9802,8 +10022,8 @@ function absoluteContinuityPath(value) {
|
|
|
9802
10022
|
var str3 = (value) => typeof value === "string" && value ? value : undefined, PLUGINS, CLAUDE_ONLY, text = (file) => {
|
|
9803
10023
|
let fd;
|
|
9804
10024
|
try {
|
|
9805
|
-
fd =
|
|
9806
|
-
const st =
|
|
10025
|
+
fd = openSync6(file, constants5.O_RDONLY | constants5.O_NONBLOCK);
|
|
10026
|
+
const st = fstatSync5(fd);
|
|
9807
10027
|
if (!st.isFile() || st.size > 1024 * 1024)
|
|
9808
10028
|
return;
|
|
9809
10029
|
return readFileSync9(fd, "utf8");
|
|
@@ -9811,7 +10031,7 @@ var str3 = (value) => typeof value === "string" && value ? value : undefined, PL
|
|
|
9811
10031
|
return;
|
|
9812
10032
|
} finally {
|
|
9813
10033
|
if (fd !== undefined)
|
|
9814
|
-
|
|
10034
|
+
closeSync6(fd);
|
|
9815
10035
|
}
|
|
9816
10036
|
}, json = (file) => {
|
|
9817
10037
|
try {
|
|
@@ -10009,7 +10229,7 @@ var init_native_cli_codex_launch = __esm(() => {
|
|
|
10009
10229
|
});
|
|
10010
10230
|
|
|
10011
10231
|
// src/hub/events.ts
|
|
10012
|
-
import { appendFileSync, closeSync as
|
|
10232
|
+
import { appendFileSync, closeSync as closeSync7, existsSync as existsSync7, fstatSync as fstatSync6, openSync as openSync7, readFileSync as readFileSync11, readSync as readSync4 } from "fs";
|
|
10013
10233
|
function readEvents(file, since = 0) {
|
|
10014
10234
|
if (!existsSync7(file))
|
|
10015
10235
|
return [];
|
|
@@ -10171,8 +10391,8 @@ function claudeWindows(rateLimits) {
|
|
|
10171
10391
|
}
|
|
10172
10392
|
|
|
10173
10393
|
// src/adapters/definitions/builtin-metadata.ts
|
|
10174
|
-
function compatibilityLaunch(kind, ctx) {
|
|
10175
|
-
const mode = kind === "kimi" || kind === "pi" ? ["--mode", ctx.form] : [];
|
|
10394
|
+
function compatibilityLaunch(kind, ctx, explicitMode = false) {
|
|
10395
|
+
const mode = explicitMode || kind === "kimi" || kind === "pi" ? ["--mode", ctx.form] : [];
|
|
10176
10396
|
const unattended = ctx.unattended && (kind === "claude" || kind === "codex") ? ["--unattended"] : [];
|
|
10177
10397
|
const args = [
|
|
10178
10398
|
ctx.entrypoint,
|
|
@@ -10408,7 +10628,7 @@ var init_builtin_metadata = __esm(() => {
|
|
|
10408
10628
|
optional: true,
|
|
10409
10629
|
defaultOnRoster: false,
|
|
10410
10630
|
trust: { onPrem: false, hubSandboxed: false },
|
|
10411
|
-
start: { create: createJcode, preflight: jcodeStartPreflight, daemonPort: "owned-acp", forms:
|
|
10631
|
+
start: { create: createJcode, preflight: jcodeStartPreflight, daemonPort: "owned-acp", forms: dualForms, defaultForm: "tui", ownsTerminal: terminal, explicitHeadlessMode: true, launch: (ctx) => compatibilityLaunch("jcode", ctx, true), conductorStartable: true, hubSwitches: [], ownedFlags: [] },
|
|
10412
10632
|
identity: { mcp: "project-file" },
|
|
10413
10633
|
permission: { modes: {}, unmanaged: "Jcode native policy is unmanaged; no hub mode mapping", grants: {
|
|
10414
10634
|
ask: "no verified hub mode mapping; native policy only",
|
|
@@ -10418,7 +10638,7 @@ var init_builtin_metadata = __esm(() => {
|
|
|
10418
10638
|
session: { idField: "sessionId", currentId: sessionId("sessionId"), launchKind: "jcode", ...JCODE_RECOVERY_SESSION, crashPlan: jcodeCrashPlan },
|
|
10419
10639
|
turnEnd: "adapter",
|
|
10420
10640
|
budget: { account: "jcode" },
|
|
10421
|
-
cli: { command: "jcode", authority: "person", launchConfigKeys: ["jcode_cmd", "jcode_home", "jcode_provider_profile"], startWords: () => ["jcode"] },
|
|
10641
|
+
cli: { command: "jcode", authority: "person", launchConfigKeys: ["jcode_cmd", "jcode_home", "jcode_provider_profile"], startWords: (mode) => ["jcode", "--mode", mode] },
|
|
10422
10642
|
display: JCODE_DISPLAY,
|
|
10423
10643
|
hooks: { recallPlatform: "jcode" }
|
|
10424
10644
|
}
|
|
@@ -17993,7 +18213,7 @@ var STDOUT_LIMIT = 512 * 1024;
|
|
|
17993
18213
|
// package.json
|
|
17994
18214
|
var package_default = {
|
|
17995
18215
|
name: "@staix/agent-hub",
|
|
17996
|
-
version: "0.12.
|
|
18216
|
+
version: "0.12.39",
|
|
17997
18217
|
description: "Native multi-agent hub: Claude Code, Codex, Kimi Code, Pi and local inference as peers in one project",
|
|
17998
18218
|
license: "MIT",
|
|
17999
18219
|
type: "module",
|