adhdev 0.9.55 → 0.9.57
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/cli/index.js +391 -61
- package/dist/cli/index.js.map +1 -1
- package/dist/index.js +295 -25
- package/dist/index.js.map +1 -1
- package/package.json +2 -1
package/dist/cli/index.js
CHANGED
|
@@ -14705,6 +14705,12 @@ var init_provider_cli_adapter = __esm({
|
|
|
14705
14705
|
accumulatedRawBuffer = "";
|
|
14706
14706
|
/** Current visible terminal screen snapshot */
|
|
14707
14707
|
terminalScreen = new TerminalScreen(24, 80);
|
|
14708
|
+
static MAX_RESPONSE_BUFFER = 8e3;
|
|
14709
|
+
static MAX_RECENT_OUTPUT_BUFFER = 1e3;
|
|
14710
|
+
responseBufferDroppedChars = 0;
|
|
14711
|
+
recentOutputDroppedChars = 0;
|
|
14712
|
+
accumulatedBufferDroppedChars = 0;
|
|
14713
|
+
accumulatedRawBufferDroppedChars = 0;
|
|
14708
14714
|
/** Max accumulated buffer size. Sized to comfortably hold a single long
|
|
14709
14715
|
* Hermes turn (tool calls + reasoning + final bubble) without the
|
|
14710
14716
|
* rolling window pushing the turn's ╭─ opening line out of view. */
|
|
@@ -14722,6 +14728,23 @@ var init_provider_cli_adapter = __esm({
|
|
|
14722
14728
|
providerResolutionMeta;
|
|
14723
14729
|
static FINISH_RETRY_DELAY_MS = 300;
|
|
14724
14730
|
static MAX_FINISH_RETRIES = 2;
|
|
14731
|
+
getBufferState() {
|
|
14732
|
+
const build = (droppedChars, maxChars) => droppedChars > 0 ? { truncated: true, droppedChars, maxChars } : void 0;
|
|
14733
|
+
const responseBuffer = build(this.responseBufferDroppedChars, _ProviderCliAdapter.MAX_RESPONSE_BUFFER);
|
|
14734
|
+
const recentOutputBuffer = build(this.recentOutputDroppedChars, _ProviderCliAdapter.MAX_RECENT_OUTPUT_BUFFER);
|
|
14735
|
+
const accumulatedBuffer = build(this.accumulatedBufferDroppedChars, _ProviderCliAdapter.MAX_ACCUMULATED_BUFFER);
|
|
14736
|
+
const accumulatedRawBuffer = build(this.accumulatedRawBufferDroppedChars, _ProviderCliAdapter.MAX_ACCUMULATED_BUFFER);
|
|
14737
|
+
if (!responseBuffer && !recentOutputBuffer && !accumulatedBuffer && !accumulatedRawBuffer) return void 0;
|
|
14738
|
+
return {
|
|
14739
|
+
...responseBuffer ? { responseBuffer } : {},
|
|
14740
|
+
...recentOutputBuffer ? { recentOutputBuffer } : {},
|
|
14741
|
+
...accumulatedBuffer ? { accumulatedBuffer } : {},
|
|
14742
|
+
...accumulatedRawBuffer ? { accumulatedRawBuffer } : {}
|
|
14743
|
+
};
|
|
14744
|
+
}
|
|
14745
|
+
recordBoundedAppendDrop(previousLength, appendedLength, nextLength) {
|
|
14746
|
+
return Math.max(0, previousLength + appendedLength - nextLength);
|
|
14747
|
+
}
|
|
14725
14748
|
buildCommittedMessagesActivitySignature() {
|
|
14726
14749
|
const last = this.committedMessages[this.committedMessages.length - 1];
|
|
14727
14750
|
return [
|
|
@@ -15087,7 +15110,9 @@ var init_provider_cli_adapter = __esm({
|
|
|
15087
15110
|
this.scheduleStartupSettleCheck();
|
|
15088
15111
|
}
|
|
15089
15112
|
if (this.isWaitingForResponse && cleanData) {
|
|
15090
|
-
|
|
15113
|
+
const previousResponseLen = this.responseBuffer.length;
|
|
15114
|
+
this.responseBuffer = appendBoundedText(this.responseBuffer, cleanData, _ProviderCliAdapter.MAX_RESPONSE_BUFFER);
|
|
15115
|
+
this.responseBufferDroppedChars += this.recordBoundedAppendDrop(previousResponseLen, cleanData.length, this.responseBuffer.length);
|
|
15091
15116
|
}
|
|
15092
15117
|
if (cleanData.trim()) {
|
|
15093
15118
|
if (this.serverConn) {
|
|
@@ -15096,14 +15121,19 @@ var init_provider_cli_adapter = __esm({
|
|
|
15096
15121
|
this.logBuffer.push({ message: cleanData.trim(), level: "info" });
|
|
15097
15122
|
}
|
|
15098
15123
|
}
|
|
15124
|
+
const prevRecentLen = this.recentOutputBuffer.length;
|
|
15099
15125
|
const prevAccumulatedLen = this.accumulatedBuffer.length;
|
|
15100
15126
|
const prevAccumulatedRawLen = this.accumulatedRawBuffer.length;
|
|
15101
|
-
this.recentOutputBuffer = appendBoundedText(this.recentOutputBuffer, cleanData,
|
|
15127
|
+
this.recentOutputBuffer = appendBoundedText(this.recentOutputBuffer, cleanData, _ProviderCliAdapter.MAX_RECENT_OUTPUT_BUFFER);
|
|
15102
15128
|
this.accumulatedBuffer = appendBoundedText(this.accumulatedBuffer, cleanData, _ProviderCliAdapter.MAX_ACCUMULATED_BUFFER);
|
|
15103
15129
|
this.accumulatedRawBuffer = appendBoundedText(this.accumulatedRawBuffer, rawData, _ProviderCliAdapter.MAX_ACCUMULATED_BUFFER);
|
|
15130
|
+
const droppedRecent = this.recordBoundedAppendDrop(prevRecentLen, cleanData.length, this.recentOutputBuffer.length);
|
|
15131
|
+
const droppedClean = this.recordBoundedAppendDrop(prevAccumulatedLen, cleanData.length, this.accumulatedBuffer.length);
|
|
15132
|
+
const droppedRaw = this.recordBoundedAppendDrop(prevAccumulatedRawLen, rawData.length, this.accumulatedRawBuffer.length);
|
|
15133
|
+
this.recentOutputDroppedChars += droppedRecent;
|
|
15134
|
+
this.accumulatedBufferDroppedChars += droppedClean;
|
|
15135
|
+
this.accumulatedRawBufferDroppedChars += droppedRaw;
|
|
15104
15136
|
if (this.currentTurnScope) {
|
|
15105
|
-
const droppedClean = prevAccumulatedLen + cleanData.length - this.accumulatedBuffer.length;
|
|
15106
|
-
const droppedRaw = prevAccumulatedRawLen + rawData.length - this.accumulatedRawBuffer.length;
|
|
15107
15137
|
if (droppedClean > 0) {
|
|
15108
15138
|
this.currentTurnScope.bufferStart = Math.max(0, this.currentTurnScope.bufferStart - droppedClean);
|
|
15109
15139
|
}
|
|
@@ -15933,13 +15963,15 @@ var init_provider_cli_adapter = __esm({
|
|
|
15933
15963
|
effectiveModal = parsedModal;
|
|
15934
15964
|
}
|
|
15935
15965
|
}
|
|
15966
|
+
const bufferState = this.getBufferState();
|
|
15936
15967
|
return {
|
|
15937
15968
|
status: effectiveStatus,
|
|
15938
15969
|
messages: [...this.committedMessages],
|
|
15939
15970
|
workingDir: this.workingDir,
|
|
15940
15971
|
activeModal: effectiveModal,
|
|
15941
15972
|
errorMessage: this.parseErrorMessage || void 0,
|
|
15942
|
-
errorReason: this.parseErrorMessage ? "parse_error" : void 0
|
|
15973
|
+
errorReason: this.parseErrorMessage ? "parse_error" : void 0,
|
|
15974
|
+
...bufferState ? { bufferState } : {}
|
|
15943
15975
|
};
|
|
15944
15976
|
}
|
|
15945
15977
|
seedCommittedMessages(messages) {
|
|
@@ -16121,10 +16153,12 @@ var init_provider_cli_adapter = __esm({
|
|
|
16121
16153
|
messages: hydratedMessages,
|
|
16122
16154
|
activeModal: parsed.activeModal ?? this.activeModal,
|
|
16123
16155
|
providerSessionId: typeof parsed.providerSessionId === "string" ? parsed.providerSessionId : void 0,
|
|
16156
|
+
...this.getBufferState() ? { bufferState: this.getBufferState() } : {},
|
|
16124
16157
|
...this.providerOwnsTranscript() ? { transcriptAuthority: "provider", coverage: this.shouldUseFullProviderTranscriptContext() ? "full" : "tail" } : {}
|
|
16125
16158
|
};
|
|
16126
16159
|
} else {
|
|
16127
16160
|
const messages = [...this.committedMessages];
|
|
16161
|
+
const bufferState = this.getBufferState();
|
|
16128
16162
|
result = {
|
|
16129
16163
|
id: "cli_session",
|
|
16130
16164
|
status: this.currentStatus,
|
|
@@ -16135,7 +16169,8 @@ var init_provider_cli_adapter = __esm({
|
|
|
16135
16169
|
index: typeof message.index === "number" ? message.index : index,
|
|
16136
16170
|
receivedAt: typeof message.receivedAt === "number" ? message.receivedAt : message.timestamp
|
|
16137
16171
|
})),
|
|
16138
|
-
activeModal: this.activeModal
|
|
16172
|
+
activeModal: this.activeModal,
|
|
16173
|
+
...bufferState ? { bufferState } : {}
|
|
16139
16174
|
};
|
|
16140
16175
|
}
|
|
16141
16176
|
const hasVisibleAssistantMessage = Array.isArray(result?.messages) && result.messages.some((message) => message?.role === "assistant" && typeof message?.content === "string" && message.content.trim());
|
|
@@ -35856,7 +35891,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
35856
35891
|
resolvedDir,
|
|
35857
35892
|
resolvedCliArgs,
|
|
35858
35893
|
resolvedProvider,
|
|
35859
|
-
|
|
35894
|
+
this.providerLoader.getSettings(normalizedType),
|
|
35860
35895
|
false,
|
|
35861
35896
|
{
|
|
35862
35897
|
providerSessionId: sessionBinding.providerSessionId,
|
|
@@ -38006,9 +38041,9 @@ function validateProviderDefinition(raw) {
|
|
|
38006
38041
|
const typedProvider = provider;
|
|
38007
38042
|
const controls = Array.isArray(provider.controls) ? provider.controls : [];
|
|
38008
38043
|
if (category === "cli" || category === "acp") {
|
|
38009
|
-
const
|
|
38010
|
-
const command =
|
|
38011
|
-
if (!
|
|
38044
|
+
const spawn7 = provider.spawn;
|
|
38045
|
+
const command = spawn7 && typeof spawn7 === "object" ? spawn7.command : void 0;
|
|
38046
|
+
if (!spawn7 || typeof spawn7 !== "object") {
|
|
38012
38047
|
errors.push(`${String(category).toUpperCase()}/CLI providers must have spawn config`);
|
|
38013
38048
|
} else if (typeof command !== "string" || !command.trim()) {
|
|
38014
38049
|
errors.push("spawn.command is required");
|
|
@@ -46232,8 +46267,8 @@ async function handleAutoImplement(ctx, type, req, res) {
|
|
|
46232
46267
|
fs14.writeFileSync(promptFile, prompt2, "utf-8");
|
|
46233
46268
|
ctx.log(`Auto-implement prompt written to ${promptFile} (${prompt2.length} chars)`);
|
|
46234
46269
|
const agentProvider = ctx.providerLoader.resolve(agent) || ctx.providerLoader.getMeta(agent);
|
|
46235
|
-
const
|
|
46236
|
-
if (!
|
|
46270
|
+
const spawn7 = agentProvider?.spawn;
|
|
46271
|
+
if (!spawn7?.command) {
|
|
46237
46272
|
try {
|
|
46238
46273
|
fs14.unlinkSync(promptFile);
|
|
46239
46274
|
} catch {
|
|
@@ -46243,22 +46278,22 @@ async function handleAutoImplement(ctx, type, req, res) {
|
|
|
46243
46278
|
}
|
|
46244
46279
|
const agentCategory = agentProvider?.category;
|
|
46245
46280
|
if (agentCategory === "acp") {
|
|
46246
|
-
sendAutoImplSSE(ctx, { event: "progress", data: { function: "_init", status: "spawning", message: `Spawning ACP agent: ${
|
|
46281
|
+
sendAutoImplSSE(ctx, { event: "progress", data: { function: "_init", status: "spawning", message: `Spawning ACP agent: ${spawn7.command} ${(spawn7.args || []).join(" ")}` } });
|
|
46247
46282
|
ctx.autoImplStatus.running = true;
|
|
46248
46283
|
ctx.autoImplStatus.type = type;
|
|
46249
46284
|
const { ClientSideConnection: ClientSideConnection2, ndJsonStream: ndJsonStream2, PROTOCOL_VERSION: PROTOCOL_VERSION2 } = await Promise.resolve().then(() => (init_acp(), acp_exports));
|
|
46250
46285
|
const { Readable: Readable3, Writable: Writable3 } = await import("stream");
|
|
46251
46286
|
const { spawn: spawnFn2 } = await import("child_process");
|
|
46252
|
-
const acpArgs = [...
|
|
46287
|
+
const acpArgs = [...spawn7.args || []];
|
|
46253
46288
|
if (model) {
|
|
46254
46289
|
acpArgs.push("--model", model);
|
|
46255
46290
|
ctx.log(`Auto-implement ACP using model: ${model}`);
|
|
46256
46291
|
}
|
|
46257
|
-
const child2 = spawnFn2(
|
|
46292
|
+
const child2 = spawnFn2(spawn7.command, acpArgs, {
|
|
46258
46293
|
cwd: providerDir,
|
|
46259
46294
|
stdio: ["pipe", "pipe", "pipe"],
|
|
46260
|
-
shell:
|
|
46261
|
-
env: { ...process.env, ...
|
|
46295
|
+
shell: spawn7.shell ?? false,
|
|
46296
|
+
env: { ...process.env, ...spawn7.env || {} }
|
|
46262
46297
|
});
|
|
46263
46298
|
ctx.autoImplProcess = child2;
|
|
46264
46299
|
child2.stderr?.on("data", (d) => {
|
|
@@ -46368,7 +46403,7 @@ async function handleAutoImplement(ctx, type, req, res) {
|
|
|
46368
46403
|
ctx.json(res, 202, {
|
|
46369
46404
|
started: true,
|
|
46370
46405
|
type,
|
|
46371
|
-
agent:
|
|
46406
|
+
agent: spawn7.command,
|
|
46372
46407
|
functions,
|
|
46373
46408
|
providerDir,
|
|
46374
46409
|
message: "ACP Auto-implement started. Connect to SSE for progress.",
|
|
@@ -46376,10 +46411,10 @@ async function handleAutoImplement(ctx, type, req, res) {
|
|
|
46376
46411
|
});
|
|
46377
46412
|
return;
|
|
46378
46413
|
}
|
|
46379
|
-
const command =
|
|
46380
|
-
const autoImpl =
|
|
46414
|
+
const command = spawn7.command;
|
|
46415
|
+
const autoImpl = spawn7.autoImpl;
|
|
46381
46416
|
const interactiveFlags = ["--yolo", "--interactive", "-i"];
|
|
46382
|
-
const baseArgs = [...
|
|
46417
|
+
const baseArgs = [...spawn7.args || []].filter((a) => !interactiveFlags.includes(a));
|
|
46383
46418
|
let shellCmd;
|
|
46384
46419
|
const isWin = os24.platform() === "win32";
|
|
46385
46420
|
const escapeArg = (a) => isWin ? `"${a.replace(/"/g, '""')}"` : `'${a.replace(/'/g, "'\\''")}'`;
|
|
@@ -46426,7 +46461,7 @@ async function handleAutoImplement(ctx, type, req, res) {
|
|
|
46426
46461
|
cols: 120,
|
|
46427
46462
|
rows: 40,
|
|
46428
46463
|
cwd: providerDir,
|
|
46429
|
-
env: { ...process.env, ...
|
|
46464
|
+
env: { ...process.env, ...spawn7.env || {} }
|
|
46430
46465
|
});
|
|
46431
46466
|
isPty = true;
|
|
46432
46467
|
} catch (err) {
|
|
@@ -46438,7 +46473,7 @@ async function handleAutoImplement(ctx, type, req, res) {
|
|
|
46438
46473
|
stdio: ["pipe", "pipe", "pipe"],
|
|
46439
46474
|
env: {
|
|
46440
46475
|
...process.env,
|
|
46441
|
-
...
|
|
46476
|
+
...spawn7.env || {}
|
|
46442
46477
|
}
|
|
46443
46478
|
});
|
|
46444
46479
|
child.on("error", (err2) => {
|
|
@@ -47610,16 +47645,16 @@ var init_dev_server = __esm({
|
|
|
47610
47645
|
this.json(res, 404, { error: `Provider not found: ${type}` });
|
|
47611
47646
|
return;
|
|
47612
47647
|
}
|
|
47613
|
-
const
|
|
47614
|
-
if (!
|
|
47648
|
+
const spawn7 = provider.spawn;
|
|
47649
|
+
if (!spawn7) {
|
|
47615
47650
|
this.json(res, 400, { error: `Provider ${type} has no spawn config` });
|
|
47616
47651
|
return;
|
|
47617
47652
|
}
|
|
47618
47653
|
const { spawn: spawnFn } = await import("child_process");
|
|
47619
47654
|
const start = Date.now();
|
|
47620
47655
|
try {
|
|
47621
|
-
const child = spawnFn(
|
|
47622
|
-
shell:
|
|
47656
|
+
const child = spawnFn(spawn7.command, [...spawn7.args || []], {
|
|
47657
|
+
shell: spawn7.shell ?? false,
|
|
47623
47658
|
timeout: 5e3,
|
|
47624
47659
|
stdio: ["pipe", "pipe", "pipe"]
|
|
47625
47660
|
});
|
|
@@ -47651,7 +47686,7 @@ var init_dev_server = __esm({
|
|
|
47651
47686
|
const elapsed = Date.now() - start;
|
|
47652
47687
|
this.json(res, 200, {
|
|
47653
47688
|
success: true,
|
|
47654
|
-
command: `${
|
|
47689
|
+
command: `${spawn7.command} ${(spawn7.args || []).join(" ")}`,
|
|
47655
47690
|
elapsed,
|
|
47656
47691
|
stdout: stdout.trim(),
|
|
47657
47692
|
stderr: stderr.trim(),
|
|
@@ -47661,7 +47696,7 @@ var init_dev_server = __esm({
|
|
|
47661
47696
|
const elapsed = Date.now() - start;
|
|
47662
47697
|
this.json(res, 200, {
|
|
47663
47698
|
success: false,
|
|
47664
|
-
command: `${
|
|
47699
|
+
command: `${spawn7.command} ${(spawn7.args || []).join(" ")}`,
|
|
47665
47700
|
elapsed,
|
|
47666
47701
|
error: e.message
|
|
47667
47702
|
});
|
|
@@ -48124,20 +48159,20 @@ var init_dev_server = __esm({
|
|
|
48124
48159
|
this.json(res, 404, { error: `Provider not found: ${type}` });
|
|
48125
48160
|
return;
|
|
48126
48161
|
}
|
|
48127
|
-
const
|
|
48128
|
-
if (!
|
|
48162
|
+
const spawn7 = provider.spawn;
|
|
48163
|
+
if (!spawn7) {
|
|
48129
48164
|
this.json(res, 400, { error: `Provider ${type} has no spawn config` });
|
|
48130
48165
|
return;
|
|
48131
48166
|
}
|
|
48132
48167
|
const { spawn: spawnFn } = await import("child_process");
|
|
48133
48168
|
const start = Date.now();
|
|
48134
48169
|
try {
|
|
48135
|
-
const args = [...
|
|
48136
|
-
const child = spawnFn(
|
|
48137
|
-
shell:
|
|
48170
|
+
const args = [...spawn7.args || [], message];
|
|
48171
|
+
const child = spawnFn(spawn7.command, args, {
|
|
48172
|
+
shell: spawn7.shell ?? false,
|
|
48138
48173
|
timeout,
|
|
48139
48174
|
stdio: ["pipe", "pipe", "pipe"],
|
|
48140
|
-
env: { ...process.env, ...
|
|
48175
|
+
env: { ...process.env, ...spawn7.env || {} }
|
|
48141
48176
|
});
|
|
48142
48177
|
let stdout = "";
|
|
48143
48178
|
let stderr = "";
|
|
@@ -80944,6 +80979,58 @@ var init_server_connection = __esm({
|
|
|
80944
80979
|
onStateChange(callback) {
|
|
80945
80980
|
this.stateChangeCallbacks.push(callback);
|
|
80946
80981
|
}
|
|
80982
|
+
/**
|
|
80983
|
+
* Send a command to another daemon owned by the same user, via server relay.
|
|
80984
|
+
* The server validates ownership before forwarding to the target daemon.
|
|
80985
|
+
*
|
|
80986
|
+
* Returns the command result or throws on timeout / auth failure.
|
|
80987
|
+
*/
|
|
80988
|
+
sendMeshCommand(targetDaemonId, command, args = {}, timeoutMs = 3e4) {
|
|
80989
|
+
return new Promise((resolve21, reject) => {
|
|
80990
|
+
const requestId = `mesh_${Date.now()}_${Math.random().toString(36).substring(2, 8)}`;
|
|
80991
|
+
const timer = setTimeout(() => {
|
|
80992
|
+
this.off("daemon_mesh_result", handler);
|
|
80993
|
+
reject(new Error(`Mesh command timed out after ${timeoutMs}ms`));
|
|
80994
|
+
}, timeoutMs);
|
|
80995
|
+
const handler = (msg) => {
|
|
80996
|
+
if (msg.payload?.requestId !== requestId) return;
|
|
80997
|
+
this.off("daemon_mesh_result", handler);
|
|
80998
|
+
clearTimeout(timer);
|
|
80999
|
+
if (msg.payload?.success === false) {
|
|
81000
|
+
reject(new Error(msg.payload?.error ?? "Mesh command failed"));
|
|
81001
|
+
} else {
|
|
81002
|
+
resolve21(msg.payload?.result);
|
|
81003
|
+
}
|
|
81004
|
+
};
|
|
81005
|
+
this.on("daemon_mesh_result", handler);
|
|
81006
|
+
const sent = this.ws?.readyState === 1 && (() => {
|
|
81007
|
+
try {
|
|
81008
|
+
this.ws.send(JSON.stringify({
|
|
81009
|
+
type: "daemon_mesh_command",
|
|
81010
|
+
requestId,
|
|
81011
|
+
targetDaemonId,
|
|
81012
|
+
command,
|
|
81013
|
+
args,
|
|
81014
|
+
timestamp: Date.now()
|
|
81015
|
+
}));
|
|
81016
|
+
return true;
|
|
81017
|
+
} catch {
|
|
81018
|
+
return false;
|
|
81019
|
+
}
|
|
81020
|
+
})();
|
|
81021
|
+
if (!sent) {
|
|
81022
|
+
clearTimeout(timer);
|
|
81023
|
+
this.off("daemon_mesh_result", handler);
|
|
81024
|
+
reject(new Error("Not connected to server"));
|
|
81025
|
+
}
|
|
81026
|
+
});
|
|
81027
|
+
}
|
|
81028
|
+
off(type, handler) {
|
|
81029
|
+
const handlers = this.messageHandlers.get(type);
|
|
81030
|
+
if (!handlers) return;
|
|
81031
|
+
const idx = handlers.indexOf(handler);
|
|
81032
|
+
if (idx !== -1) handlers.splice(idx, 1);
|
|
81033
|
+
}
|
|
80947
81034
|
getState() {
|
|
80948
81035
|
return this.state;
|
|
80949
81036
|
}
|
|
@@ -81253,7 +81340,7 @@ function sendToPeer(peer, data) {
|
|
|
81253
81340
|
return false;
|
|
81254
81341
|
}
|
|
81255
81342
|
const json2 = JSON.stringify(data);
|
|
81256
|
-
if (messageType === "command_result" && json2
|
|
81343
|
+
if (messageType === "command_result" && Buffer.byteLength(json2, "utf8") > MAX_INLINE_JSON_MESSAGE_CHARS) {
|
|
81257
81344
|
return sendChunkedCommandResult(peer, peerId, requestId, json2);
|
|
81258
81345
|
}
|
|
81259
81346
|
try {
|
|
@@ -81266,21 +81353,51 @@ function sendToPeer(peer, data) {
|
|
|
81266
81353
|
return false;
|
|
81267
81354
|
}
|
|
81268
81355
|
}
|
|
81356
|
+
function buildCommandResultChunkEnvelope(requestId, chunkId, index, total, data) {
|
|
81357
|
+
return JSON.stringify({
|
|
81358
|
+
type: "command_result_chunk",
|
|
81359
|
+
id: requestId,
|
|
81360
|
+
chunkId,
|
|
81361
|
+
index,
|
|
81362
|
+
total,
|
|
81363
|
+
data
|
|
81364
|
+
});
|
|
81365
|
+
}
|
|
81366
|
+
function splitJsonIntoCommandResultChunks(json2, requestId, chunkId) {
|
|
81367
|
+
const chunks = [];
|
|
81368
|
+
let offset = 0;
|
|
81369
|
+
while (offset < json2.length) {
|
|
81370
|
+
let end = Math.min(json2.length, offset + JSON_CHUNK_PAYLOAD_CHARS);
|
|
81371
|
+
while (end > offset) {
|
|
81372
|
+
const candidate = json2.slice(offset, end);
|
|
81373
|
+
const envelope = buildCommandResultChunkEnvelope(requestId, chunkId, chunks.length, MAX_JSON_CHUNKS, candidate);
|
|
81374
|
+
if (Buffer.byteLength(envelope, "utf8") <= MAX_INLINE_JSON_MESSAGE_BYTES) break;
|
|
81375
|
+
end = offset + Math.max(1, Math.floor((end - offset) * 0.8));
|
|
81376
|
+
}
|
|
81377
|
+
chunks.push(json2.slice(offset, end));
|
|
81378
|
+
if (chunks.length > MAX_JSON_CHUNKS) return [];
|
|
81379
|
+
offset = end;
|
|
81380
|
+
}
|
|
81381
|
+
return chunks;
|
|
81382
|
+
}
|
|
81269
81383
|
function sendChunkedCommandResult(peer, peerId, requestId, json2) {
|
|
81270
81384
|
const chunkId = requestId || `command_result_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
|
|
81271
|
-
const
|
|
81385
|
+
const chunks = splitJsonIntoCommandResultChunks(json2, requestId, chunkId);
|
|
81386
|
+
const total = chunks.length;
|
|
81387
|
+
if (total === 0 || total > MAX_JSON_CHUNKS) {
|
|
81388
|
+
log(`command_result send failed: peer=${peerId} id=${requestId || "-"} reason=too_many_chunks chunks=${total || "unknown"}`);
|
|
81389
|
+
return false;
|
|
81390
|
+
}
|
|
81272
81391
|
logDebug(`command_result chunked: peer=${peerId} id=${requestId || "-"} chars=${json2.length} chunks=${total}`);
|
|
81273
81392
|
for (let index = 0; index < total; index += 1) {
|
|
81274
|
-
const chunk =
|
|
81393
|
+
const chunk = chunks[index] || "";
|
|
81275
81394
|
try {
|
|
81276
|
-
|
|
81277
|
-
|
|
81278
|
-
|
|
81279
|
-
|
|
81280
|
-
|
|
81281
|
-
|
|
81282
|
-
data: chunk
|
|
81283
|
-
}));
|
|
81395
|
+
const envelope = buildCommandResultChunkEnvelope(requestId, chunkId, index, total, chunk);
|
|
81396
|
+
if (Buffer.byteLength(envelope, "utf8") > MAX_INLINE_JSON_MESSAGE_BYTES) {
|
|
81397
|
+
log(`command_result send failed: peer=${peerId} id=${requestId || "-"} chunk=${index + 1}/${total} reason=chunk_too_large`);
|
|
81398
|
+
return false;
|
|
81399
|
+
}
|
|
81400
|
+
peer.dataChannel?.sendMessage(envelope);
|
|
81284
81401
|
} catch (error48) {
|
|
81285
81402
|
log(`command_result send failed: peer=${peerId} id=${requestId || "-"} chunk=${index + 1}/${total} error=${error48?.message || error48}`);
|
|
81286
81403
|
return false;
|
|
@@ -81288,10 +81405,58 @@ function sendChunkedCommandResult(peer, peerId, requestId, json2) {
|
|
|
81288
81405
|
}
|
|
81289
81406
|
return true;
|
|
81290
81407
|
}
|
|
81408
|
+
function parseChunkedJsonMessage(peerId, parsed) {
|
|
81409
|
+
const chunkType = typeof parsed?.type === "string" ? parsed.type : "";
|
|
81410
|
+
if (!chunkType.endsWith("_chunk")) return parsed;
|
|
81411
|
+
const chunkId = typeof parsed?.chunkId === "string" ? parsed.chunkId : "";
|
|
81412
|
+
const id = typeof parsed?.id === "string" ? parsed.id : "";
|
|
81413
|
+
const index = Number(parsed?.index);
|
|
81414
|
+
const total = Number(parsed?.total);
|
|
81415
|
+
const data = typeof parsed?.data === "string" ? parsed.data : "";
|
|
81416
|
+
if (!chunkId || !Number.isInteger(index) || !Number.isInteger(total) || index < 0 || total <= 0 || total > MAX_JSON_CHUNKS || index >= total || !data) {
|
|
81417
|
+
log(`chunked JSON ignored: peer=${peerId} type=${chunkType || "unknown"} reason=malformed`);
|
|
81418
|
+
return null;
|
|
81419
|
+
}
|
|
81420
|
+
const now = Date.now();
|
|
81421
|
+
incomingJsonChunks.forEach((entry2, key2) => {
|
|
81422
|
+
if (now - entry2.createdAt > JSON_CHUNK_TTL_MS) incomingJsonChunks.delete(key2);
|
|
81423
|
+
});
|
|
81424
|
+
const key = `${peerId}:${chunkId}`;
|
|
81425
|
+
let entry = incomingJsonChunks.get(key);
|
|
81426
|
+
if (!entry || entry.total !== total || entry.type !== chunkType) {
|
|
81427
|
+
entry = { total, chunks: new Array(total).fill(""), received: 0, createdAt: now, type: chunkType, id };
|
|
81428
|
+
incomingJsonChunks.set(key, entry);
|
|
81429
|
+
}
|
|
81430
|
+
if (!entry.chunks[index]) {
|
|
81431
|
+
entry.chunks[index] = data;
|
|
81432
|
+
entry.received += 1;
|
|
81433
|
+
}
|
|
81434
|
+
if (entry.received < entry.total) return null;
|
|
81435
|
+
incomingJsonChunks.delete(key);
|
|
81436
|
+
try {
|
|
81437
|
+
return JSON.parse(entry.chunks.join(""));
|
|
81438
|
+
} catch (error48) {
|
|
81439
|
+
log(`chunked JSON parse failed: peer=${peerId} type=${chunkType} id=${entry.id || "-"} error=${error48?.message || error48}`);
|
|
81440
|
+
return CHUNK_PARSE_FAILED;
|
|
81441
|
+
}
|
|
81442
|
+
}
|
|
81291
81443
|
function routeDataChannelMessage(peerId, msg, peers, handlers) {
|
|
81292
81444
|
const text = typeof msg === "string" ? msg : msg.toString("utf-8");
|
|
81293
81445
|
try {
|
|
81294
|
-
|
|
81446
|
+
let parsed = JSON.parse(text);
|
|
81447
|
+
const chunked = parseChunkedJsonMessage(peerId, parsed);
|
|
81448
|
+
if (chunked === null) return;
|
|
81449
|
+
if (chunked === CHUNK_PARSE_FAILED) {
|
|
81450
|
+
const peer = peers.get(peerId);
|
|
81451
|
+
const id = typeof parsed?.id === "string" ? parsed.id : "";
|
|
81452
|
+
if (parsed?.type === "command_chunk") {
|
|
81453
|
+
sendToPeer(peer, { type: "command_result", id, success: false, error: "Failed to reassemble chunked command" });
|
|
81454
|
+
} else if (id) {
|
|
81455
|
+
sendToPeer(peer, { id, type: "response", success: false, error: "Failed to reassemble chunked request" });
|
|
81456
|
+
}
|
|
81457
|
+
return;
|
|
81458
|
+
}
|
|
81459
|
+
parsed = chunked;
|
|
81295
81460
|
if (parsed.type !== "command" && parsed.type !== "pty_input" && parsed.type !== "pty_resize" && parsed.type !== "ping" && parsed.type !== "pong") {
|
|
81296
81461
|
logDebug(`Files message from peer ${peerId}: type=${parsed.type}`);
|
|
81297
81462
|
}
|
|
@@ -81587,7 +81752,7 @@ async function handleFileRequest(peerId, req, peers, handlers) {
|
|
|
81587
81752
|
}
|
|
81588
81753
|
sendToPeer(peer, response);
|
|
81589
81754
|
}
|
|
81590
|
-
var MAX_INLINE_JSON_MESSAGE_CHARS, JSON_CHUNK_PAYLOAD_CHARS;
|
|
81755
|
+
var MAX_INLINE_JSON_MESSAGE_CHARS, MAX_INLINE_JSON_MESSAGE_BYTES, JSON_CHUNK_PAYLOAD_CHARS, JSON_CHUNK_TTL_MS, MAX_JSON_CHUNKS, CHUNK_PARSE_FAILED, incomingJsonChunks;
|
|
81591
81756
|
var init_data_channel_router = __esm({
|
|
81592
81757
|
"src/daemon-p2p/data-channel-router.ts"() {
|
|
81593
81758
|
"use strict";
|
|
@@ -81595,18 +81760,23 @@ var init_data_channel_router = __esm({
|
|
|
81595
81760
|
init_permission();
|
|
81596
81761
|
init_log();
|
|
81597
81762
|
MAX_INLINE_JSON_MESSAGE_CHARS = 6e4;
|
|
81598
|
-
|
|
81763
|
+
MAX_INLINE_JSON_MESSAGE_BYTES = 6e4;
|
|
81764
|
+
JSON_CHUNK_PAYLOAD_CHARS = 16e3;
|
|
81765
|
+
JSON_CHUNK_TTL_MS = 6e4;
|
|
81766
|
+
MAX_JSON_CHUNKS = 1024;
|
|
81767
|
+
CHUNK_PARSE_FAILED = /* @__PURE__ */ Symbol("chunk_parse_failed");
|
|
81768
|
+
incomingJsonChunks = /* @__PURE__ */ new Map();
|
|
81599
81769
|
}
|
|
81600
81770
|
});
|
|
81601
81771
|
|
|
81602
81772
|
// src/daemon-p2p/screenshot-sender.ts
|
|
81603
|
-
var CHUNK_SIZE,
|
|
81773
|
+
var CHUNK_SIZE, MAX_INLINE_JSON_MESSAGE_BYTES2, JSON_CHUNK_PAYLOAD_CHARS2, ScreenshotSender;
|
|
81604
81774
|
var init_screenshot_sender = __esm({
|
|
81605
81775
|
"src/daemon-p2p/screenshot-sender.ts"() {
|
|
81606
81776
|
"use strict";
|
|
81607
81777
|
init_log();
|
|
81608
81778
|
CHUNK_SIZE = 6e4;
|
|
81609
|
-
|
|
81779
|
+
MAX_INLINE_JSON_MESSAGE_BYTES2 = 6e4;
|
|
81610
81780
|
JSON_CHUNK_PAYLOAD_CHARS2 = 16e3;
|
|
81611
81781
|
ScreenshotSender = class {
|
|
81612
81782
|
_ssDebugDone = false;
|
|
@@ -81650,7 +81820,7 @@ var init_screenshot_sender = __esm({
|
|
|
81650
81820
|
type: "topic_update",
|
|
81651
81821
|
update
|
|
81652
81822
|
});
|
|
81653
|
-
if (Buffer.byteLength(json2, "utf8") >
|
|
81823
|
+
if (Buffer.byteLength(json2, "utf8") > MAX_INLINE_JSON_MESSAGE_BYTES2) {
|
|
81654
81824
|
return this.sendChunkedTopicUpdate(peer, update, json2);
|
|
81655
81825
|
}
|
|
81656
81826
|
try {
|
|
@@ -81689,6 +81859,10 @@ var init_screenshot_sender = __esm({
|
|
|
81689
81859
|
let sentAny = false;
|
|
81690
81860
|
for (const peer of peers.values()) {
|
|
81691
81861
|
if (peer.state !== "connected" || !peer.dataChannel?.isOpen()) continue;
|
|
81862
|
+
if (Buffer.byteLength(msg, "utf8") > MAX_INLINE_JSON_MESSAGE_BYTES2) {
|
|
81863
|
+
if (this.sendChunkedSessionOutput(peer, sessionId, msg)) sentAny = true;
|
|
81864
|
+
continue;
|
|
81865
|
+
}
|
|
81692
81866
|
try {
|
|
81693
81867
|
peer.dataChannel.sendMessage(msg);
|
|
81694
81868
|
sentAny = true;
|
|
@@ -81697,6 +81871,27 @@ var init_screenshot_sender = __esm({
|
|
|
81697
81871
|
}
|
|
81698
81872
|
return sentAny;
|
|
81699
81873
|
}
|
|
81874
|
+
sendChunkedSessionOutput(peer, sessionId, json2) {
|
|
81875
|
+
const chunkId = `session_output:${sessionId}:${Date.now()}:${Math.random().toString(36).slice(2, 8)}`;
|
|
81876
|
+
const total = Math.ceil(json2.length / JSON_CHUNK_PAYLOAD_CHARS2);
|
|
81877
|
+
logDebug(`session_output chunked: peer=${peer.peerId || "unknown"} sessionId=${sessionId || "-"} chars=${json2.length} chunks=${total}`);
|
|
81878
|
+
for (let index = 0; index < total; index += 1) {
|
|
81879
|
+
const chunk = json2.slice(index * JSON_CHUNK_PAYLOAD_CHARS2, (index + 1) * JSON_CHUNK_PAYLOAD_CHARS2);
|
|
81880
|
+
try {
|
|
81881
|
+
peer.dataChannel?.sendMessage(JSON.stringify({
|
|
81882
|
+
type: "session_output_chunk",
|
|
81883
|
+
sessionId,
|
|
81884
|
+
chunkId,
|
|
81885
|
+
index,
|
|
81886
|
+
total,
|
|
81887
|
+
data: chunk
|
|
81888
|
+
}));
|
|
81889
|
+
} catch {
|
|
81890
|
+
return false;
|
|
81891
|
+
}
|
|
81892
|
+
}
|
|
81893
|
+
return true;
|
|
81894
|
+
}
|
|
81700
81895
|
sendScreenshot(peers, base64Data, targetSessionId) {
|
|
81701
81896
|
const buffer = Buffer.from(base64Data, "base64");
|
|
81702
81897
|
return this.sendScreenshotBuffer(peers, buffer, targetSessionId);
|
|
@@ -89792,6 +89987,64 @@ var init_session_host_controller = __esm({
|
|
|
89792
89987
|
}
|
|
89793
89988
|
});
|
|
89794
89989
|
|
|
89990
|
+
// src/daemon-mesh-manager.ts
|
|
89991
|
+
var daemon_mesh_manager_exports = {};
|
|
89992
|
+
__export(daemon_mesh_manager_exports, {
|
|
89993
|
+
DaemonMeshManager: () => DaemonMeshManager
|
|
89994
|
+
});
|
|
89995
|
+
function interpolateArgs(args, context) {
|
|
89996
|
+
const result = {};
|
|
89997
|
+
for (const [k, v] of Object.entries(args)) {
|
|
89998
|
+
result[k] = typeof v === "string" ? interpolateString(v, context) : v;
|
|
89999
|
+
}
|
|
90000
|
+
return result;
|
|
90001
|
+
}
|
|
90002
|
+
function interpolateString(template, ctx) {
|
|
90003
|
+
return template.replace(/\{\{(\w+)\}\}/g, (_2, key) => {
|
|
90004
|
+
const val = ctx[key];
|
|
90005
|
+
return val !== void 0 ? String(val) : `{{${key}}}`;
|
|
90006
|
+
});
|
|
90007
|
+
}
|
|
90008
|
+
var DaemonMeshManager;
|
|
90009
|
+
var init_daemon_mesh_manager = __esm({
|
|
90010
|
+
"src/daemon-mesh-manager.ts"() {
|
|
90011
|
+
"use strict";
|
|
90012
|
+
init_src();
|
|
90013
|
+
DaemonMeshManager = class {
|
|
90014
|
+
rules = [];
|
|
90015
|
+
serverConn;
|
|
90016
|
+
constructor(serverConn) {
|
|
90017
|
+
this.serverConn = serverConn;
|
|
90018
|
+
}
|
|
90019
|
+
setRules(rules) {
|
|
90020
|
+
this.rules = rules;
|
|
90021
|
+
LOG.info("Mesh", `[Mesh] ${rules.length} rule(s) loaded`);
|
|
90022
|
+
}
|
|
90023
|
+
async emit(event) {
|
|
90024
|
+
const matching = this.rules.filter((r) => r.trigger === event.trigger);
|
|
90025
|
+
if (matching.length === 0) return;
|
|
90026
|
+
await Promise.allSettled(
|
|
90027
|
+
matching.map((rule) => this.executeRule(rule, event.context ?? {}))
|
|
90028
|
+
);
|
|
90029
|
+
}
|
|
90030
|
+
async executeRule(rule, context) {
|
|
90031
|
+
const args = interpolateArgs(rule.args ?? {}, context);
|
|
90032
|
+
try {
|
|
90033
|
+
LOG.info("Mesh", `[Mesh] Relaying '${rule.command}' \u2192 ${rule.targetDaemonId.slice(0, 12)}\u2026`);
|
|
90034
|
+
await this.serverConn.sendMeshCommand(rule.targetDaemonId, rule.command, args);
|
|
90035
|
+
LOG.info("Mesh", `[Mesh] Relay '${rule.command}' complete`);
|
|
90036
|
+
} catch (err) {
|
|
90037
|
+
LOG.warn("Mesh", `[Mesh] Relay '${rule.command}' failed: ${err?.message ?? err}`);
|
|
90038
|
+
}
|
|
90039
|
+
}
|
|
90040
|
+
/** Convenience: send a one-off mesh command without a rule. */
|
|
90041
|
+
async sendCommand(targetDaemonId, command, args = {}) {
|
|
90042
|
+
return this.serverConn.sendMeshCommand(targetDaemonId, command, args);
|
|
90043
|
+
}
|
|
90044
|
+
};
|
|
90045
|
+
}
|
|
90046
|
+
});
|
|
90047
|
+
|
|
89795
90048
|
// src/adhdev-daemon.ts
|
|
89796
90049
|
var adhdev_daemon_exports = {};
|
|
89797
90050
|
__export(adhdev_daemon_exports, {
|
|
@@ -90036,13 +90289,14 @@ var init_adhdev_daemon = __esm({
|
|
|
90036
90289
|
init_version();
|
|
90037
90290
|
init_src();
|
|
90038
90291
|
init_runtime_defaults();
|
|
90039
|
-
pkgVersion = resolvePackageVersion({ injectedVersion: "0.9.
|
|
90292
|
+
pkgVersion = resolvePackageVersion({ injectedVersion: "0.9.57" });
|
|
90040
90293
|
AdhdevDaemon = class _AdhdevDaemon {
|
|
90041
90294
|
localHttpServer = null;
|
|
90042
90295
|
localWss = null;
|
|
90043
90296
|
localClients = /* @__PURE__ */ new Set();
|
|
90044
90297
|
serverConn = null;
|
|
90045
90298
|
p2p = null;
|
|
90299
|
+
meshManager = null;
|
|
90046
90300
|
screenshotController = null;
|
|
90047
90301
|
statusReporter = null;
|
|
90048
90302
|
topicSubscriptionTimer = null;
|
|
@@ -90626,6 +90880,12 @@ ${err?.stack || ""}`);
|
|
|
90626
90880
|
}
|
|
90627
90881
|
});
|
|
90628
90882
|
this.p2p = new DaemonP2PSender(this.serverConn);
|
|
90883
|
+
const { DaemonMeshManager: DaemonMeshManager2 } = await Promise.resolve().then(() => (init_daemon_mesh_manager(), daemon_mesh_manager_exports));
|
|
90884
|
+
this.meshManager = new DaemonMeshManager2(this.serverConn);
|
|
90885
|
+
const meshRules = config2.meshRules;
|
|
90886
|
+
if (Array.isArray(meshRules) && meshRules.length > 0) {
|
|
90887
|
+
this.meshManager.setRules(meshRules);
|
|
90888
|
+
}
|
|
90629
90889
|
if (this.p2p.isAvailable) {
|
|
90630
90890
|
console.log(source_default.green(" \u{1F517} P2P available (node-datachannel)"));
|
|
90631
90891
|
this.p2p.onInput(async (event) => {
|
|
@@ -90964,6 +91224,16 @@ ${err?.stack || ""}`);
|
|
|
90964
91224
|
if (cmdType.startsWith("git_")) {
|
|
90965
91225
|
void this.flushP2PWorkspaceGitSubscriptions();
|
|
90966
91226
|
}
|
|
91227
|
+
if (cmdType === "git_checkpoint" && routed.success && this.meshManager) {
|
|
91228
|
+
void this.meshManager.emit({
|
|
91229
|
+
trigger: "git_checkpoint_complete",
|
|
91230
|
+
context: {
|
|
91231
|
+
workspace: String(normalizedData.workspace ?? ""),
|
|
91232
|
+
checkpoint_message: routed.checkpoint?.message ?? String(normalizedData.message ?? ""),
|
|
91233
|
+
commit: routed.checkpoint?.commit ?? ""
|
|
91234
|
+
}
|
|
91235
|
+
});
|
|
91236
|
+
}
|
|
90967
91237
|
return { ...routed, interactionId };
|
|
90968
91238
|
} catch (e) {
|
|
90969
91239
|
logCommand({ ts: (/* @__PURE__ */ new Date()).toISOString(), cmd: cmdType, source: "p2p", interactionId, success: false, error: e.message, durationMs: Date.now() - cmdStart });
|
|
@@ -93674,9 +93944,9 @@ async function requestSessionHostDirect(request) {
|
|
|
93674
93944
|
}
|
|
93675
93945
|
}
|
|
93676
93946
|
async function runRuntimeLaunchSpec(spec) {
|
|
93677
|
-
const { spawn:
|
|
93947
|
+
const { spawn: spawn7 } = await import("child_process");
|
|
93678
93948
|
return await new Promise((resolve21, reject) => {
|
|
93679
|
-
const child =
|
|
93949
|
+
const child = spawn7(spec.command, spec.args, {
|
|
93680
93950
|
stdio: "inherit",
|
|
93681
93951
|
env: spec.env,
|
|
93682
93952
|
shell: process.platform === "win32" && spec.command !== process.execPath
|
|
@@ -93945,7 +94215,7 @@ async function handleTraceCommand(options) {
|
|
|
93945
94215
|
async function runDaemonUpgrade(options, pkgVersion3) {
|
|
93946
94216
|
const { isDaemonRunning: isDaemonRunning2, stopDaemon: stopDaemon2 } = await Promise.resolve().then(() => (init_adhdev_daemon(), adhdev_daemon_exports));
|
|
93947
94217
|
const { stopManagedSessionHostProcess: stopManagedSessionHostProcess2 } = await Promise.resolve().then(() => (init_session_host(), session_host_exports));
|
|
93948
|
-
const { execSync: execSync8, spawn:
|
|
94218
|
+
const { execSync: execSync8, spawn: spawn7 } = await import("child_process");
|
|
93949
94219
|
const fsMod = await import("fs");
|
|
93950
94220
|
const pathMod = await import("path");
|
|
93951
94221
|
console.log(source_default.bold("\n \u{1F504} ADHDev Upgrade\n"));
|
|
@@ -94029,7 +94299,7 @@ async function runDaemonUpgrade(options, pkgVersion3) {
|
|
|
94029
94299
|
await new Promise((r) => setTimeout(r, 2e3));
|
|
94030
94300
|
stopManagedSessionHostProcess2();
|
|
94031
94301
|
await new Promise((r) => setTimeout(r, 500));
|
|
94032
|
-
const child =
|
|
94302
|
+
const child = spawn7(process.execPath, [process.argv[1], "daemon", "-p", DEFAULT_DAEMON_PORT_TEXT], {
|
|
94033
94303
|
detached: true,
|
|
94034
94304
|
stdio: "ignore",
|
|
94035
94305
|
windowsHide: true,
|
|
@@ -94076,7 +94346,7 @@ function registerDaemonCommands(program2, pkgVersion3) {
|
|
|
94076
94346
|
}
|
|
94077
94347
|
});
|
|
94078
94348
|
program2.command("standalone").description("\u{1F5A5}\uFE0F Start ADHDev Standalone Server (Local Dashboard & Embedded Daemon)").option("-p, --port <port>", "Local HTTP/WS server port", "3847").option("--host <host>", "Bind to specific host (use 0.0.0.0 for LAN access)").option("--no-open", "Prevent opening browser automatically").option("--token <token>", "Require token authentication").option("--dev", "Enable Dev Mode").action(async (options) => {
|
|
94079
|
-
const { spawn:
|
|
94349
|
+
const { spawn: spawn7, execSync: execSync8 } = await import("child_process");
|
|
94080
94350
|
const { DEFAULT_STANDALONE_SESSION_HOST_APP_NAME: DEFAULT_STANDALONE_SESSION_HOST_APP_NAME2, resolveSessionHostAppNameResolution: resolveSessionHostAppNameResolution2 } = await Promise.resolve().then(() => (init_src(), src_exports));
|
|
94081
94351
|
console.log(source_default.cyan("\n Starting ADHDev Standalone Server..."));
|
|
94082
94352
|
const args = [];
|
|
@@ -94105,7 +94375,7 @@ function registerDaemonCommands(program2, pkgVersion3) {
|
|
|
94105
94375
|
}
|
|
94106
94376
|
console.log(source_default.gray(` Session host namespace: ${sessionHostName}${sessionHostResolution.source === "default" ? " (default isolated standalone namespace)" : sessionHostResolution.source === "explicit" ? " (from ADHDEV_SESSION_HOST_NAME)" : " (auto-corrected for standalone isolation)"}`));
|
|
94107
94377
|
const spawnArgs = bin === "npx" ? npxArgs : args;
|
|
94108
|
-
const child =
|
|
94378
|
+
const child = spawn7(bin, spawnArgs, {
|
|
94109
94379
|
stdio: "inherit",
|
|
94110
94380
|
shell: process.platform === "win32",
|
|
94111
94381
|
env: standaloneEnv
|
|
@@ -94579,7 +94849,7 @@ function registerDaemonCommands(program2, pkgVersion3) {
|
|
|
94579
94849
|
hideCommand(program2.command("daemon:restart").description("Restart ADHDev Daemon (stop \u2192 start)").option("-p, --port <port>", "Local WS server port", DEFAULT_DAEMON_PORT_TEXT).option("--server <url>", "Override server URL").option("--dev", "Enable Dev Mode").action(async (options) => {
|
|
94580
94850
|
const { stopDaemon: stopDaemon2, isDaemonRunning: isDaemonRunning2 } = await Promise.resolve().then(() => (init_adhdev_daemon(), adhdev_daemon_exports));
|
|
94581
94851
|
const { stopManagedSessionHostProcess: stopManagedSessionHostProcess2 } = await Promise.resolve().then(() => (init_session_host(), session_host_exports));
|
|
94582
|
-
const { spawn:
|
|
94852
|
+
const { spawn: spawn7 } = await import("child_process");
|
|
94583
94853
|
if (isDaemonRunning2({ port: parseInt(options.port, 10) || DEFAULT_DAEMON_PORT })) {
|
|
94584
94854
|
console.log(source_default.yellow("\n Stopping existing daemon..."));
|
|
94585
94855
|
stopDaemon2({ port: parseInt(options.port, 10) || DEFAULT_DAEMON_PORT });
|
|
@@ -94591,7 +94861,7 @@ function registerDaemonCommands(program2, pkgVersion3) {
|
|
|
94591
94861
|
const args = ["daemon", "-p", options.port || DEFAULT_DAEMON_PORT_TEXT];
|
|
94592
94862
|
if (options.server) args.push("--server", options.server);
|
|
94593
94863
|
if (options.dev) args.push("--dev");
|
|
94594
|
-
const child =
|
|
94864
|
+
const child = spawn7(process.execPath, [process.argv[1], ...args], {
|
|
94595
94865
|
detached: true,
|
|
94596
94866
|
stdio: "ignore",
|
|
94597
94867
|
windowsHide: true,
|
|
@@ -96595,6 +96865,64 @@ function registerCdpCommands(program2) {
|
|
|
96595
96865
|
});
|
|
96596
96866
|
}
|
|
96597
96867
|
|
|
96868
|
+
// src/cli/mcp-commands.ts
|
|
96869
|
+
var import_node_child_process3 = require("child_process");
|
|
96870
|
+
var import_node_module3 = require("module");
|
|
96871
|
+
init_source();
|
|
96872
|
+
function registerMcpCommands(program2) {
|
|
96873
|
+
program2.command("mcp").description("Start an MCP server to expose IDE agents as tools (for Claude Desktop, etc.)").option("--api-key <key>", "ADHDev cloud API key (switches to cloud mode)").option("--port <n>", "Standalone daemon port (default: 3847)", "3847").option("--password <pass>", "Standalone daemon password (if set)").option("--base-url <url>", "Override cloud API base URL").addHelpText("after", `
|
|
96874
|
+
Examples:
|
|
96875
|
+
adhdev mcp Local mode (requires: adhdev standalone)
|
|
96876
|
+
adhdev mcp --api-key adk_xxx Cloud mode (no local daemon needed)
|
|
96877
|
+
|
|
96878
|
+
Claude Desktop config (~/.claude_desktop_config.json):
|
|
96879
|
+
{
|
|
96880
|
+
"mcpServers": {
|
|
96881
|
+
"adhdev": {
|
|
96882
|
+
"command": "adhdev",
|
|
96883
|
+
"args": ["mcp"]
|
|
96884
|
+
}
|
|
96885
|
+
}
|
|
96886
|
+
}
|
|
96887
|
+
|
|
96888
|
+
Tools available (local): list_sessions, read_chat, send_chat, approve, screenshot, git_status
|
|
96889
|
+
Tools available (cloud): list_sessions, read_chat, send_chat, approve
|
|
96890
|
+
`).action(async (opts) => {
|
|
96891
|
+
const mcpBin = resolveMcpBin();
|
|
96892
|
+
if (!mcpBin) {
|
|
96893
|
+
console.error(source_default.red("\u2717 @adhdev/mcp-server not found. Run: npm install -g @adhdev/mcp-server"));
|
|
96894
|
+
process.exit(1);
|
|
96895
|
+
}
|
|
96896
|
+
const args = [];
|
|
96897
|
+
if (opts.apiKey) args.push("--api-key", opts.apiKey);
|
|
96898
|
+
if (opts.port && opts.port !== "3847") args.push("--port", opts.port);
|
|
96899
|
+
if (opts.password) args.push("--password", opts.password);
|
|
96900
|
+
if (opts.baseUrl) args.push("--base-url", opts.baseUrl);
|
|
96901
|
+
const env3 = { ...process.env };
|
|
96902
|
+
if (opts.apiKey) env3.ADHDEV_API_KEY = opts.apiKey;
|
|
96903
|
+
if (opts.password) env3.ADHDEV_PASSWORD = opts.password;
|
|
96904
|
+
const child = (0, import_node_child_process3.spawn)(process.execPath, [mcpBin, ...args], {
|
|
96905
|
+
stdio: "inherit",
|
|
96906
|
+
env: env3
|
|
96907
|
+
});
|
|
96908
|
+
child.on("error", (err) => {
|
|
96909
|
+
console.error(source_default.red(`\u2717 MCP server error: ${err.message}`));
|
|
96910
|
+
process.exit(1);
|
|
96911
|
+
});
|
|
96912
|
+
child.on("exit", (code) => {
|
|
96913
|
+
process.exit(code ?? 0);
|
|
96914
|
+
});
|
|
96915
|
+
});
|
|
96916
|
+
}
|
|
96917
|
+
function resolveMcpBin() {
|
|
96918
|
+
try {
|
|
96919
|
+
const req = (0, import_node_module3.createRequire)(__filename);
|
|
96920
|
+
return req.resolve("@adhdev/mcp-server");
|
|
96921
|
+
} catch {
|
|
96922
|
+
return null;
|
|
96923
|
+
}
|
|
96924
|
+
}
|
|
96925
|
+
|
|
96598
96926
|
// src/cli/index.ts
|
|
96599
96927
|
init_version();
|
|
96600
96928
|
var pkgVersion2 = resolvePackageVersion();
|
|
@@ -96614,6 +96942,7 @@ registerDoctorCommands(program, pkgVersion2);
|
|
|
96614
96942
|
registerProviderCommands(program);
|
|
96615
96943
|
registerCdpCommands(program);
|
|
96616
96944
|
registerServiceCommands(program);
|
|
96945
|
+
registerMcpCommands(program);
|
|
96617
96946
|
void (async () => {
|
|
96618
96947
|
const helperMode = await maybeRunDaemonUpgradeHelperFromEnv();
|
|
96619
96948
|
if (helperMode) {
|
|
@@ -96640,6 +96969,7 @@ void (async () => {
|
|
|
96640
96969
|
console.log(source_default.gray(" Advanced tools:"));
|
|
96641
96970
|
console.log(source_default.gray(" adhdev trace --category session_host \u2014 Inspect structured daemon trace"));
|
|
96642
96971
|
console.log(source_default.gray(" adhdev service \u2014 Manage OS background auto-start service"));
|
|
96972
|
+
console.log(source_default.gray(" adhdev mcp \u2014 Start MCP server (expose agents to Claude Desktop, etc.)"));
|
|
96643
96973
|
console.log(source_default.gray(" adhdev provider ... \u2014 Provider development commands"));
|
|
96644
96974
|
console.log(source_default.gray(" adhdev cdp ... \u2014 CDP debugging tools"));
|
|
96645
96975
|
console.log();
|