@harmonyos-arkts/opencode-acp 0.0.4 → 0.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +332 -166
- package/dist/index.cjs.map +4 -4
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -19586,6 +19586,11 @@ function createOpencodeClient(config2) {
|
|
|
19586
19586
|
// node_modules/@opencode-ai/sdk/dist/v2/server.js
|
|
19587
19587
|
var import_cross_spawn = __toESM(require_cross_spawn(), 1);
|
|
19588
19588
|
|
|
19589
|
+
// src/index.ts
|
|
19590
|
+
var http = __toESM(require("node:http"), 1);
|
|
19591
|
+
var https = __toESM(require("node:https"), 1);
|
|
19592
|
+
var import_node_stream = require("node:stream");
|
|
19593
|
+
|
|
19589
19594
|
// src/agent.ts
|
|
19590
19595
|
var import_url2 = require("url");
|
|
19591
19596
|
|
|
@@ -20279,65 +20284,6 @@ function applyStructuredPatch(source, patch, options = {}) {
|
|
|
20279
20284
|
|
|
20280
20285
|
// src/utils.ts
|
|
20281
20286
|
var import_url = require("url");
|
|
20282
|
-
function toToolKind(toolName) {
|
|
20283
|
-
const tool = toolName.toLowerCase();
|
|
20284
|
-
switch (tool) {
|
|
20285
|
-
case "bash":
|
|
20286
|
-
return "execute";
|
|
20287
|
-
case "webfetch":
|
|
20288
|
-
return "fetch";
|
|
20289
|
-
case "edit":
|
|
20290
|
-
case "patch":
|
|
20291
|
-
case "write":
|
|
20292
|
-
return "edit";
|
|
20293
|
-
case "grep":
|
|
20294
|
-
case "glob":
|
|
20295
|
-
case "context7_resolve_library_id":
|
|
20296
|
-
case "context7_get_library_docs":
|
|
20297
|
-
return "search";
|
|
20298
|
-
case "list":
|
|
20299
|
-
case "read":
|
|
20300
|
-
return "read";
|
|
20301
|
-
default:
|
|
20302
|
-
return "other";
|
|
20303
|
-
}
|
|
20304
|
-
}
|
|
20305
|
-
function toLocations(toolName, input) {
|
|
20306
|
-
const tool = toolName.toLowerCase();
|
|
20307
|
-
switch (tool) {
|
|
20308
|
-
case "read":
|
|
20309
|
-
case "edit":
|
|
20310
|
-
case "write":
|
|
20311
|
-
return input["filePath"] ? [{ path: input["filePath"] }] : [];
|
|
20312
|
-
case "glob":
|
|
20313
|
-
case "grep":
|
|
20314
|
-
return input["path"] ? [{ path: input["path"] }] : [];
|
|
20315
|
-
case "list":
|
|
20316
|
-
return input["path"] ? [{ path: input["path"] }] : [];
|
|
20317
|
-
default:
|
|
20318
|
-
return [];
|
|
20319
|
-
}
|
|
20320
|
-
}
|
|
20321
|
-
function parseUri(uri) {
|
|
20322
|
-
try {
|
|
20323
|
-
if (uri.startsWith("file://")) {
|
|
20324
|
-
const path = uri.slice(7);
|
|
20325
|
-
const name = path.split("/").pop() || path;
|
|
20326
|
-
return { type: "file", url: uri, filename: name, mime: "text/plain" };
|
|
20327
|
-
}
|
|
20328
|
-
if (uri.startsWith("zed://")) {
|
|
20329
|
-
const url2 = new URL(uri);
|
|
20330
|
-
const path = url2.searchParams.get("path");
|
|
20331
|
-
if (path) {
|
|
20332
|
-
const name = path.split("/").pop() || path;
|
|
20333
|
-
return { type: "file", url: (0, import_url.pathToFileURL)(path).href, filename: name, mime: "text/plain" };
|
|
20334
|
-
}
|
|
20335
|
-
}
|
|
20336
|
-
return { type: "text", text: uri };
|
|
20337
|
-
} catch {
|
|
20338
|
-
return { type: "text", text: uri };
|
|
20339
|
-
}
|
|
20340
|
-
}
|
|
20341
20287
|
|
|
20342
20288
|
// src/logger.ts
|
|
20343
20289
|
var import_fs = require("fs");
|
|
@@ -20403,13 +20349,18 @@ function sysLog(action, data) {
|
|
|
20403
20349
|
write("system", action, data);
|
|
20404
20350
|
}
|
|
20405
20351
|
function sanitize(obj, depth = 0) {
|
|
20406
|
-
if (!obj
|
|
20352
|
+
if (!obj) return obj;
|
|
20353
|
+
if (depth > 5) return { __truncated__: true, __depth__: depth };
|
|
20407
20354
|
const result = {};
|
|
20408
20355
|
for (const [key, val] of Object.entries(obj)) {
|
|
20409
20356
|
if (typeof val === "string" && val.length > 2e3) {
|
|
20410
20357
|
result[key] = val.slice(0, 2e3) + `... [${val.length} chars total]`;
|
|
20411
20358
|
} else if (val && typeof val === "object" && !Array.isArray(val)) {
|
|
20412
20359
|
result[key] = sanitize(val, depth + 1);
|
|
20360
|
+
} else if (val && Array.isArray(val)) {
|
|
20361
|
+
result[key] = val.map(
|
|
20362
|
+
(item) => typeof item === "string" && item.length > 2e3 ? item.slice(0, 2e3) + `... [${item.length} chars total]` : item && typeof item === "object" ? sanitize(item, depth + 1) : item
|
|
20363
|
+
);
|
|
20413
20364
|
} else {
|
|
20414
20365
|
result[key] = val;
|
|
20415
20366
|
}
|
|
@@ -20417,8 +20368,78 @@ function sanitize(obj, depth = 0) {
|
|
|
20417
20368
|
return result;
|
|
20418
20369
|
}
|
|
20419
20370
|
|
|
20371
|
+
// src/utils.ts
|
|
20372
|
+
function toToolKind(toolName) {
|
|
20373
|
+
const tool = toolName.toLowerCase();
|
|
20374
|
+
switch (tool) {
|
|
20375
|
+
case "bash":
|
|
20376
|
+
return "execute";
|
|
20377
|
+
case "webfetch":
|
|
20378
|
+
return "fetch";
|
|
20379
|
+
case "edit":
|
|
20380
|
+
case "patch":
|
|
20381
|
+
case "write":
|
|
20382
|
+
return "edit";
|
|
20383
|
+
case "grep":
|
|
20384
|
+
case "glob":
|
|
20385
|
+
case "context7_resolve_library_id":
|
|
20386
|
+
case "context7_get_library_docs":
|
|
20387
|
+
return "search";
|
|
20388
|
+
case "list":
|
|
20389
|
+
case "read":
|
|
20390
|
+
return "read";
|
|
20391
|
+
default:
|
|
20392
|
+
return "other";
|
|
20393
|
+
}
|
|
20394
|
+
}
|
|
20395
|
+
function toLocations(toolName, input) {
|
|
20396
|
+
const tool = toolName.toLowerCase();
|
|
20397
|
+
switch (tool) {
|
|
20398
|
+
case "read":
|
|
20399
|
+
case "edit":
|
|
20400
|
+
case "write":
|
|
20401
|
+
return input["filePath"] ? [{ path: input["filePath"] }] : [];
|
|
20402
|
+
case "glob":
|
|
20403
|
+
case "grep":
|
|
20404
|
+
return input["path"] ? [{ path: input["path"] }] : [];
|
|
20405
|
+
case "list":
|
|
20406
|
+
return input["path"] ? [{ path: input["path"] }] : [];
|
|
20407
|
+
default:
|
|
20408
|
+
return [];
|
|
20409
|
+
}
|
|
20410
|
+
}
|
|
20411
|
+
function parseUri(uri) {
|
|
20412
|
+
try {
|
|
20413
|
+
if (uri.startsWith("file://")) {
|
|
20414
|
+
const path = uri.slice(7);
|
|
20415
|
+
const name = path.split("/").pop() || path;
|
|
20416
|
+
return { type: "file", url: uri, filename: name, mime: "text/plain" };
|
|
20417
|
+
}
|
|
20418
|
+
if (uri.startsWith("zed://")) {
|
|
20419
|
+
const url2 = new URL(uri);
|
|
20420
|
+
const path = url2.searchParams.get("path");
|
|
20421
|
+
if (path) {
|
|
20422
|
+
const name = path.split("/").pop() || path;
|
|
20423
|
+
return { type: "file", url: (0, import_url.pathToFileURL)(path).href, filename: name, mime: "text/plain" };
|
|
20424
|
+
}
|
|
20425
|
+
}
|
|
20426
|
+
return { type: "text", text: uri };
|
|
20427
|
+
} catch {
|
|
20428
|
+
return { type: "text", text: uri };
|
|
20429
|
+
}
|
|
20430
|
+
}
|
|
20431
|
+
async function sendToClient(connection, params) {
|
|
20432
|
+
const updateType = params.update.sessionUpdate;
|
|
20433
|
+
const update = params.update;
|
|
20434
|
+
acpOut(`sessionUpdate.${updateType}`, {
|
|
20435
|
+
sessionId: params.sessionId.slice(0, 12),
|
|
20436
|
+
...updateType === "agent_message_chunk" || updateType === "agent_thought_chunk" ? { messageId: update.messageId?.slice(0, 12), delta: update.content?.text?.slice(0, 200) } : updateType === "tool_call" || updateType === "tool_call_update" ? { toolCallId: update.toolCallId, tool: update.title, kind: update.kind, status: update.status } : updateType === "session_info_update" ? { title: update.title, _meta: update._meta } : updateType === "usage_update" ? { used: update.used, size: update.size, cost: update.cost, _meta: update._meta } : {}
|
|
20437
|
+
});
|
|
20438
|
+
return connection.sessionUpdate(params);
|
|
20439
|
+
}
|
|
20440
|
+
|
|
20420
20441
|
// src/event-handler.ts
|
|
20421
|
-
var QUESTION_TIMEOUT_MS =
|
|
20442
|
+
var QUESTION_TIMEOUT_MS = 3e5;
|
|
20422
20443
|
var permissionOptions = [
|
|
20423
20444
|
{ optionId: "once", kind: "allow_once", name: "Allow once" },
|
|
20424
20445
|
{ optionId: "always", kind: "allow_always", name: "Always allow" },
|
|
@@ -20438,28 +20459,10 @@ var EventHandler = class {
|
|
|
20438
20459
|
partMetaIndex = /* @__PURE__ */ new Map();
|
|
20439
20460
|
/** Track tool call counts per child session to detect completion. */
|
|
20440
20461
|
childToolCounts = /* @__PURE__ */ new Map();
|
|
20441
|
-
/** Cumulative
|
|
20442
|
-
|
|
20443
|
-
/**
|
|
20444
|
-
|
|
20445
|
-
* Every call here corresponds to a real message sent over the wire.
|
|
20446
|
-
*/
|
|
20447
|
-
async sendToClient(params) {
|
|
20448
|
-
const updateType = params.update.sessionUpdate;
|
|
20449
|
-
const update = params.update;
|
|
20450
|
-
acpOut(`sessionUpdate.${updateType}`, {
|
|
20451
|
-
sessionId: params.sessionId.slice(0, 12),
|
|
20452
|
-
...updateType === "agent_message_chunk" || updateType === "agent_thought_chunk" ? { messageId: update.messageId?.slice(0, 12), delta: update.content?.text?.slice(0, 200) } : updateType === "tool_call" || updateType === "tool_call_update" ? { toolCallId: update.toolCallId, tool: update.title, kind: update.kind, status: update.status } : updateType === "session_info_update" ? { title: update.title, _meta: update._meta } : updateType === "usage_update" ? { used: update.used, size: update.size, cost: update.cost, _meta: update._meta } : {}
|
|
20453
|
-
});
|
|
20454
|
-
return this.connection.sessionUpdate(params);
|
|
20455
|
-
}
|
|
20456
|
-
getDiffStats(sessionId) {
|
|
20457
|
-
return this.diffStats.get(sessionId);
|
|
20458
|
-
}
|
|
20459
|
-
setDiffStats(sessionId, stats) {
|
|
20460
|
-
if (this.diffStats.has(sessionId)) return;
|
|
20461
|
-
this.diffStats.set(sessionId, stats);
|
|
20462
|
-
}
|
|
20462
|
+
/** Cumulative file diff stats per session, aggregated from session.diff SSE events. */
|
|
20463
|
+
fileDiffStats = /* @__PURE__ */ new Map();
|
|
20464
|
+
/** AI code change stats per session, keyed by sessionId → filePath → { additions, deletions }. */
|
|
20465
|
+
aiCodeChangeStats = /* @__PURE__ */ new Map();
|
|
20463
20466
|
constructor(deps) {
|
|
20464
20467
|
this.connection = deps.connection;
|
|
20465
20468
|
this.sdk = deps.sdk;
|
|
@@ -20602,15 +20605,26 @@ var EventHandler = class {
|
|
|
20602
20605
|
}
|
|
20603
20606
|
case "question.asked": {
|
|
20604
20607
|
const q = event.properties;
|
|
20605
|
-
|
|
20606
|
-
|
|
20608
|
+
ocEvent("question.asked", event);
|
|
20609
|
+
let resolved = this.resolveSession(q.sessionID);
|
|
20610
|
+
if (!resolved) {
|
|
20611
|
+
console.warn(`[event-handler] question.asked: session ${q.sessionID} not in manager, attempting auto-register`);
|
|
20612
|
+
try {
|
|
20613
|
+
const sessionResp = await this.sdk.session.get({ sessionID: q.sessionID, directory: "" });
|
|
20614
|
+
const fetchedSession = sessionResp.data;
|
|
20615
|
+
if (fetchedSession?.parentID) {
|
|
20616
|
+
this.sessionManager.registerDiscovered(fetchedSession.id, fetchedSession.parentID, fetchedSession.title);
|
|
20617
|
+
resolved = this.resolveSession(q.sessionID);
|
|
20618
|
+
} else if (fetchedSession) {
|
|
20619
|
+
console.warn(`[event-handler] question.asked: top-level session ${q.sessionID} not registered; was agent.newSession called?`);
|
|
20620
|
+
}
|
|
20621
|
+
} catch (err) {
|
|
20622
|
+
console.error(`[event-handler] question.asked: failed to fetch session ${q.sessionID}:`, err);
|
|
20623
|
+
}
|
|
20624
|
+
if (!resolved) return;
|
|
20625
|
+
}
|
|
20607
20626
|
const directory = resolved.cwd;
|
|
20608
20627
|
const sessionId = resolved.sessionId;
|
|
20609
|
-
ocEvent("question.asked", {
|
|
20610
|
-
id: q.id,
|
|
20611
|
-
sessionID: q.sessionID,
|
|
20612
|
-
questions: q.questions.length
|
|
20613
|
-
});
|
|
20614
20628
|
const prev = this.questionQueues.get(q.sessionID) ?? Promise.resolve();
|
|
20615
20629
|
const next = prev.then(async () => {
|
|
20616
20630
|
const extResult = await Promise.race([
|
|
@@ -20630,7 +20644,7 @@ var EventHandler = class {
|
|
|
20630
20644
|
if (!extResult || !extResult.answers) {
|
|
20631
20645
|
await this.sdk.question.reject({ requestID: q.id, directory }).catch(() => {
|
|
20632
20646
|
});
|
|
20633
|
-
|
|
20647
|
+
sysLog("question.rejected", { requestID: q.id });
|
|
20634
20648
|
return;
|
|
20635
20649
|
}
|
|
20636
20650
|
const answers = extResult.answers;
|
|
@@ -20638,7 +20652,7 @@ var EventHandler = class {
|
|
|
20638
20652
|
console.error("[event-handler] invalid answers shape from client:", JSON.stringify(answers));
|
|
20639
20653
|
await this.sdk.question.reject({ requestID: q.id, directory }).catch(() => {
|
|
20640
20654
|
});
|
|
20641
|
-
|
|
20655
|
+
sysLog("question.rejected", {
|
|
20642
20656
|
requestID: q.id,
|
|
20643
20657
|
reason: "invalid_answers"
|
|
20644
20658
|
});
|
|
@@ -20649,7 +20663,7 @@ var EventHandler = class {
|
|
|
20649
20663
|
directory,
|
|
20650
20664
|
answers
|
|
20651
20665
|
});
|
|
20652
|
-
|
|
20666
|
+
sysLog("question.reply", { requestID: q.id, answers });
|
|
20653
20667
|
}).catch((err) => {
|
|
20654
20668
|
console.error("[event-handler] question handling error:", err);
|
|
20655
20669
|
}).finally(() => {
|
|
@@ -20673,7 +20687,7 @@ var EventHandler = class {
|
|
|
20673
20687
|
await this.handleToolPart(resolved.sessionId, part);
|
|
20674
20688
|
}
|
|
20675
20689
|
if (part.type === "text" && typeof part.text === "string" && part.ignored === true) {
|
|
20676
|
-
await this.
|
|
20690
|
+
await sendToClient(this.connection, {
|
|
20677
20691
|
sessionId: resolved.sessionId,
|
|
20678
20692
|
update: {
|
|
20679
20693
|
sessionUpdate: "agent_message_chunk",
|
|
@@ -20694,7 +20708,7 @@ var EventHandler = class {
|
|
|
20694
20708
|
const partMeta = this.partMetaIndex.get(props.partID);
|
|
20695
20709
|
if (!partMeta) return;
|
|
20696
20710
|
if (partMeta.type === "text" && props.field === "text" && partMeta.ignored !== true) {
|
|
20697
|
-
await this.
|
|
20711
|
+
await sendToClient(this.connection, {
|
|
20698
20712
|
sessionId,
|
|
20699
20713
|
update: {
|
|
20700
20714
|
sessionUpdate: "agent_message_chunk",
|
|
@@ -20706,7 +20720,7 @@ var EventHandler = class {
|
|
|
20706
20720
|
return;
|
|
20707
20721
|
}
|
|
20708
20722
|
if (partMeta.type === "reasoning" && props.field === "text") {
|
|
20709
|
-
await this.
|
|
20723
|
+
await sendToClient(this.connection, {
|
|
20710
20724
|
sessionId,
|
|
20711
20725
|
update: {
|
|
20712
20726
|
sessionUpdate: "agent_thought_chunk",
|
|
@@ -20731,7 +20745,7 @@ var EventHandler = class {
|
|
|
20731
20745
|
additions += d.additions;
|
|
20732
20746
|
deletions += d.deletions;
|
|
20733
20747
|
}
|
|
20734
|
-
this.
|
|
20748
|
+
this.fileDiffStats.set(resolved.sessionId, { additions, deletions, files: diff.length });
|
|
20735
20749
|
return;
|
|
20736
20750
|
}
|
|
20737
20751
|
default: {
|
|
@@ -20747,7 +20761,7 @@ var EventHandler = class {
|
|
|
20747
20761
|
* and _meta containing structured metadata about the subagent.
|
|
20748
20762
|
*/
|
|
20749
20763
|
async announceChildSession(childSessionId, parentSessionId, title, meta3) {
|
|
20750
|
-
await this.
|
|
20764
|
+
await sendToClient(this.connection, {
|
|
20751
20765
|
sessionId: childSessionId,
|
|
20752
20766
|
update: {
|
|
20753
20767
|
sessionUpdate: "session_info_update",
|
|
@@ -20780,7 +20794,7 @@ var EventHandler = class {
|
|
|
20780
20794
|
});
|
|
20781
20795
|
}
|
|
20782
20796
|
}
|
|
20783
|
-
await this.
|
|
20797
|
+
await sendToClient(this.connection, {
|
|
20784
20798
|
sessionId,
|
|
20785
20799
|
update: {
|
|
20786
20800
|
sessionUpdate: "tool_call",
|
|
@@ -20812,7 +20826,7 @@ var EventHandler = class {
|
|
|
20812
20826
|
content: { type: "text", text: output }
|
|
20813
20827
|
});
|
|
20814
20828
|
}
|
|
20815
|
-
await this.
|
|
20829
|
+
await sendToClient(this.connection, {
|
|
20816
20830
|
sessionId,
|
|
20817
20831
|
update: {
|
|
20818
20832
|
sessionUpdate: "tool_call_update",
|
|
@@ -20865,12 +20879,13 @@ var EventHandler = class {
|
|
|
20865
20879
|
const oldText = typeof input["oldString"] === "string" ? input["oldString"] : "";
|
|
20866
20880
|
const newText = typeof input["newString"] === "string" ? input["newString"] : typeof input["content"] === "string" ? input["content"] : "";
|
|
20867
20881
|
content.push({ type: "diff", path: filePath, oldText, newText });
|
|
20882
|
+
this.accumulateAICodeChangeStats(sessionId, part);
|
|
20868
20883
|
}
|
|
20869
20884
|
if (part.tool === "todowrite") {
|
|
20870
20885
|
try {
|
|
20871
20886
|
const todos = JSON.parse(part.state.output);
|
|
20872
20887
|
if (Array.isArray(todos)) {
|
|
20873
|
-
await this.
|
|
20888
|
+
await sendToClient(this.connection, {
|
|
20874
20889
|
sessionId,
|
|
20875
20890
|
update: {
|
|
20876
20891
|
sessionUpdate: "plan",
|
|
@@ -20886,7 +20901,7 @@ var EventHandler = class {
|
|
|
20886
20901
|
} catch {
|
|
20887
20902
|
}
|
|
20888
20903
|
}
|
|
20889
|
-
await this.
|
|
20904
|
+
await sendToClient(this.connection, {
|
|
20890
20905
|
sessionId,
|
|
20891
20906
|
update: {
|
|
20892
20907
|
sessionUpdate: "tool_call_update",
|
|
@@ -20908,7 +20923,7 @@ var EventHandler = class {
|
|
|
20908
20923
|
case "error": {
|
|
20909
20924
|
this.toolStarts.delete(part.callID);
|
|
20910
20925
|
this.bashSnapshots.delete(part.callID);
|
|
20911
|
-
await this.
|
|
20926
|
+
await sendToClient(this.connection, {
|
|
20912
20927
|
sessionId,
|
|
20913
20928
|
update: {
|
|
20914
20929
|
sessionUpdate: "tool_call_update",
|
|
@@ -20943,8 +20958,7 @@ var EventHandler = class {
|
|
|
20943
20958
|
const agentMatch = title.match(/@(\w+)\s+subagent/);
|
|
20944
20959
|
const agentType = agentMatch?.[1];
|
|
20945
20960
|
const description = title.replace(/\s*\(@\w+\s+subagent\)\s*$/, "");
|
|
20946
|
-
|
|
20947
|
-
await this.sendToClient({
|
|
20961
|
+
await sendToClient(this.connection, {
|
|
20948
20962
|
sessionId: childSessionId,
|
|
20949
20963
|
update: {
|
|
20950
20964
|
sessionUpdate: "session_info_update",
|
|
@@ -20956,8 +20970,7 @@ var EventHandler = class {
|
|
|
20956
20970
|
toolCallCount,
|
|
20957
20971
|
durationMs,
|
|
20958
20972
|
...agentType && { agentType },
|
|
20959
|
-
...description && { description }
|
|
20960
|
-
...childDiffStats && { codeChange: childDiffStats }
|
|
20973
|
+
...description && { description }
|
|
20961
20974
|
}
|
|
20962
20975
|
}
|
|
20963
20976
|
});
|
|
@@ -20969,6 +20982,44 @@ var EventHandler = class {
|
|
|
20969
20982
|
if (typeof output !== "string") return;
|
|
20970
20983
|
return output;
|
|
20971
20984
|
}
|
|
20985
|
+
// ─── Statistics Accessors ────────────────────────────────────────
|
|
20986
|
+
getFileDiffStats(sessionId) {
|
|
20987
|
+
return this.fileDiffStats.get(sessionId);
|
|
20988
|
+
}
|
|
20989
|
+
setFileDiffStats(sessionId, stats) {
|
|
20990
|
+
if (this.fileDiffStats.has(sessionId)) return;
|
|
20991
|
+
this.fileDiffStats.set(sessionId, stats);
|
|
20992
|
+
}
|
|
20993
|
+
/**
|
|
20994
|
+
* Accumulate AI code change stats from a completed tool part's metadata.
|
|
20995
|
+
* The harmony-code plugin injects `metadata.aiCodeChange` for edit/write tools.
|
|
20996
|
+
*/
|
|
20997
|
+
accumulateAICodeChangeStats(sessionId, part) {
|
|
20998
|
+
if (part.state.status !== "completed") return;
|
|
20999
|
+
const meta3 = part.state.metadata ?? {};
|
|
21000
|
+
const aiCodeChange = meta3["aiCodeChange"];
|
|
21001
|
+
if (!aiCodeChange || aiCodeChange.additions === 0 && aiCodeChange.deletions === 0) return;
|
|
21002
|
+
const fileMap = this.aiCodeChangeStats.get(sessionId) ?? /* @__PURE__ */ new Map();
|
|
21003
|
+
const existing = fileMap.get(aiCodeChange.file) ?? { additions: 0, deletions: 0 };
|
|
21004
|
+
fileMap.set(aiCodeChange.file, {
|
|
21005
|
+
additions: existing.additions + aiCodeChange.additions,
|
|
21006
|
+
deletions: existing.deletions + aiCodeChange.deletions
|
|
21007
|
+
});
|
|
21008
|
+
if (!this.aiCodeChangeStats.has(sessionId)) {
|
|
21009
|
+
this.aiCodeChangeStats.set(sessionId, fileMap);
|
|
21010
|
+
}
|
|
21011
|
+
}
|
|
21012
|
+
getAICodeChangeStats(sessionId) {
|
|
21013
|
+
const fileMap = this.aiCodeChangeStats.get(sessionId);
|
|
21014
|
+
if (!fileMap || fileMap.size === 0) return void 0;
|
|
21015
|
+
let additions = 0;
|
|
21016
|
+
let deletions = 0;
|
|
21017
|
+
for (const stats of fileMap.values()) {
|
|
21018
|
+
additions += stats.additions;
|
|
21019
|
+
deletions += stats.deletions;
|
|
21020
|
+
}
|
|
21021
|
+
return { additions, deletions, files: fileMap.size };
|
|
21022
|
+
}
|
|
20972
21023
|
};
|
|
20973
21024
|
function simpleHash(str) {
|
|
20974
21025
|
let hash2 = 0;
|
|
@@ -21072,31 +21123,6 @@ var Agent = class {
|
|
|
21072
21123
|
eventHandler;
|
|
21073
21124
|
authProvider;
|
|
21074
21125
|
mcpManager;
|
|
21075
|
-
/**
|
|
21076
|
-
* Wrapper around connection.sessionUpdate that logs what's sent to the ACP client.
|
|
21077
|
-
*/
|
|
21078
|
-
async sendToClient(params) {
|
|
21079
|
-
const updateType = params.update.sessionUpdate;
|
|
21080
|
-
const update = params.update;
|
|
21081
|
-
acpOut(`sessionUpdate.${updateType}`, {
|
|
21082
|
-
sessionId: params.sessionId.slice(0, 12),
|
|
21083
|
-
...updateType === "agent_message_chunk" || updateType === "agent_thought_chunk" ? {
|
|
21084
|
-
messageId: update.messageId?.slice(0, 12),
|
|
21085
|
-
delta: update.content?.text?.slice(0, 200)
|
|
21086
|
-
} : updateType === "tool_call" || updateType === "tool_call_update" ? {
|
|
21087
|
-
toolCallId: update.toolCallId,
|
|
21088
|
-
tool: update.title,
|
|
21089
|
-
kind: update.kind,
|
|
21090
|
-
status: update.status
|
|
21091
|
-
} : updateType === "usage_update" ? {
|
|
21092
|
-
used: update.used,
|
|
21093
|
-
size: update.size,
|
|
21094
|
-
cost: update.cost,
|
|
21095
|
-
_meta: update._meta
|
|
21096
|
-
} : {}
|
|
21097
|
-
});
|
|
21098
|
-
return this.connection.sessionUpdate(params);
|
|
21099
|
-
}
|
|
21100
21126
|
constructor(config2) {
|
|
21101
21127
|
this.config = config2;
|
|
21102
21128
|
this.sdk = config2.sdk;
|
|
@@ -21317,13 +21343,14 @@ var Agent = class {
|
|
|
21317
21343
|
}
|
|
21318
21344
|
}
|
|
21319
21345
|
async loadSession(params) {
|
|
21346
|
+
acpIn("loadSession", { sessionId: params.sessionId, cwd: params.cwd });
|
|
21320
21347
|
try {
|
|
21321
21348
|
const directory = params.cwd;
|
|
21322
21349
|
const sessionId = params.sessionId;
|
|
21323
21350
|
const model = await this.defaultModel(directory);
|
|
21324
21351
|
const { session } = await this.sessionManager.load(sessionId, params.cwd, params.mcpServers, model);
|
|
21325
21352
|
if (session.summary) {
|
|
21326
|
-
this.eventHandler.
|
|
21353
|
+
this.eventHandler.setFileDiffStats(sessionId, {
|
|
21327
21354
|
additions: session.summary.additions,
|
|
21328
21355
|
deletions: session.summary.deletions,
|
|
21329
21356
|
files: session.summary.files
|
|
@@ -21364,6 +21391,7 @@ var Agent = class {
|
|
|
21364
21391
|
}
|
|
21365
21392
|
}
|
|
21366
21393
|
async listSessions(params) {
|
|
21394
|
+
acpIn("listSessions", { cwd: params.cwd, cursor: params.cursor });
|
|
21367
21395
|
const limit = 100;
|
|
21368
21396
|
const cursor = params.cursor ? Number(params.cursor) : void 0;
|
|
21369
21397
|
const sessions = await this.sdk.session.list({ directory: params.cwd ?? void 0, roots: true }).then((x) => x.data ?? []);
|
|
@@ -21380,9 +21408,11 @@ var Agent = class {
|
|
|
21380
21408
|
const next = filtered.length > limit && last ? String(last.time.updated) : void 0;
|
|
21381
21409
|
const response = { sessions: entries };
|
|
21382
21410
|
if (next) response.nextCursor = next;
|
|
21411
|
+
acpOut("listSessions.response", { count: entries.length, hasNext: !!next });
|
|
21383
21412
|
return response;
|
|
21384
21413
|
}
|
|
21385
21414
|
async unstable_forkSession(params) {
|
|
21415
|
+
acpIn("forkSession", { sessionId: params.sessionId, cwd: params.cwd });
|
|
21386
21416
|
try {
|
|
21387
21417
|
const directory = params.cwd;
|
|
21388
21418
|
const mcpServers = params.mcpServers ?? [];
|
|
@@ -21408,6 +21438,7 @@ var Agent = class {
|
|
|
21408
21438
|
}
|
|
21409
21439
|
}
|
|
21410
21440
|
async unstable_resumeSession(params) {
|
|
21441
|
+
acpIn("resumeSession", { sessionId: params.sessionId, cwd: params.cwd });
|
|
21411
21442
|
try {
|
|
21412
21443
|
const directory = params.cwd;
|
|
21413
21444
|
const sessionId = params.sessionId;
|
|
@@ -21415,7 +21446,7 @@ var Agent = class {
|
|
|
21415
21446
|
const model = await this.defaultModel(directory);
|
|
21416
21447
|
const { session } = await this.sessionManager.load(sessionId, directory, mcpServers, model);
|
|
21417
21448
|
if (session.summary) {
|
|
21418
|
-
this.eventHandler.
|
|
21449
|
+
this.eventHandler.setFileDiffStats(sessionId, {
|
|
21419
21450
|
additions: session.summary.additions,
|
|
21420
21451
|
deletions: session.summary.deletions,
|
|
21421
21452
|
files: session.summary.files
|
|
@@ -21460,6 +21491,16 @@ var Agent = class {
|
|
|
21460
21491
|
agent,
|
|
21461
21492
|
directory
|
|
21462
21493
|
});
|
|
21494
|
+
const rawErr = response2.error;
|
|
21495
|
+
ocCall("session.prompt.raw", {
|
|
21496
|
+
hasData: !!response2.data,
|
|
21497
|
+
hasError: !!rawErr,
|
|
21498
|
+
errorName: rawErr?.name,
|
|
21499
|
+
errorMessage: rawErr?.message,
|
|
21500
|
+
errorCode: rawErr?.code ?? rawErr?.cause?.code,
|
|
21501
|
+
errorCauseName: rawErr?.cause?.name,
|
|
21502
|
+
errorCauseMessage: rawErr?.cause?.message
|
|
21503
|
+
});
|
|
21463
21504
|
const msg2 = response2.data?.info;
|
|
21464
21505
|
ocCall("session.prompt.response", {
|
|
21465
21506
|
messageId: msg2?.id,
|
|
@@ -21546,6 +21587,7 @@ var Agent = class {
|
|
|
21546
21587
|
}
|
|
21547
21588
|
// ─── Configuration ────────────────────────────────────────────────
|
|
21548
21589
|
async setSessionMode(params) {
|
|
21590
|
+
acpIn("setSessionMode", { sessionId: params.sessionId, modeId: params.modeId });
|
|
21549
21591
|
const session = this.sessionManager.get(params.sessionId);
|
|
21550
21592
|
const agents = await this.sdk.app.agents({ directory: session.cwd }).then((x) => x.data ?? []).catch(() => []);
|
|
21551
21593
|
const availableModes = agents.filter((a) => a.mode !== "subagent" && !a.hidden);
|
|
@@ -21555,6 +21597,7 @@ var Agent = class {
|
|
|
21555
21597
|
this.sessionManager.setMode(params.sessionId, params.modeId);
|
|
21556
21598
|
}
|
|
21557
21599
|
async unstable_setSessionModel(params) {
|
|
21600
|
+
acpIn("setSessionModel", { sessionId: params.sessionId, modelId: params.modelId });
|
|
21558
21601
|
const session = this.sessionManager.get(params.sessionId);
|
|
21559
21602
|
const providers = await this.sdk.config.providers({ directory: session.cwd }).then((x) => x.data?.providers ?? []).catch(() => []);
|
|
21560
21603
|
const selection = parseModelSelection(params.modelId, providers);
|
|
@@ -21568,6 +21611,7 @@ var Agent = class {
|
|
|
21568
21611
|
};
|
|
21569
21612
|
}
|
|
21570
21613
|
async setSessionConfigOption(params) {
|
|
21614
|
+
acpIn("setSessionConfigOption", { sessionId: params.sessionId, configId: params.configId, value: params.value });
|
|
21571
21615
|
const session = this.sessionManager.get(params.sessionId);
|
|
21572
21616
|
const providers = await this.sdk.config.providers({ directory: session.cwd }).then((x) => x.data?.providers ?? []).catch(() => []);
|
|
21573
21617
|
const sortedProviders = [...providers].sort(
|
|
@@ -21653,7 +21697,7 @@ var Agent = class {
|
|
|
21653
21697
|
if (!childMessages?.length) return;
|
|
21654
21698
|
const title = `Subagent (${childSessionId.slice(0, 8)})`;
|
|
21655
21699
|
this.sessionManager.registerDiscovered(childSessionId, parentSessionId, title);
|
|
21656
|
-
await this.
|
|
21700
|
+
await sendToClient(this.connection, {
|
|
21657
21701
|
sessionId: childSessionId,
|
|
21658
21702
|
update: {
|
|
21659
21703
|
sessionUpdate: "session_info_update",
|
|
@@ -21770,7 +21814,7 @@ var Agent = class {
|
|
|
21770
21814
|
availableCommands.push({ name: "compact", description: "compact the session" });
|
|
21771
21815
|
}
|
|
21772
21816
|
setTimeout(() => {
|
|
21773
|
-
this.
|
|
21817
|
+
sendToClient(this.connection, {
|
|
21774
21818
|
sessionId: params.sessionId,
|
|
21775
21819
|
update: {
|
|
21776
21820
|
sessionUpdate: "available_commands_update",
|
|
@@ -21823,7 +21867,7 @@ var Agent = class {
|
|
|
21823
21867
|
await this.replayToolPart(sessionId, part);
|
|
21824
21868
|
} else if (part.type === "text" && part.text) {
|
|
21825
21869
|
const audience = part.synthetic ? ["assistant"] : part.ignored ? ["user"] : void 0;
|
|
21826
|
-
await this.
|
|
21870
|
+
await sendToClient(this.connection, {
|
|
21827
21871
|
sessionId,
|
|
21828
21872
|
update: {
|
|
21829
21873
|
sessionUpdate: messageChunk,
|
|
@@ -21841,7 +21885,7 @@ var Agent = class {
|
|
|
21841
21885
|
const filename = part.filename ?? "file";
|
|
21842
21886
|
const mime = part.mime || "application/octet-stream";
|
|
21843
21887
|
if (url2.startsWith("file://")) {
|
|
21844
|
-
await this.
|
|
21888
|
+
await sendToClient(this.connection, {
|
|
21845
21889
|
sessionId,
|
|
21846
21890
|
update: {
|
|
21847
21891
|
sessionUpdate: messageChunk,
|
|
@@ -21856,7 +21900,7 @@ var Agent = class {
|
|
|
21856
21900
|
const base64Data = base64Match?.[2] ?? "";
|
|
21857
21901
|
const effectiveMime = dataMime || mime;
|
|
21858
21902
|
if (effectiveMime.startsWith("image/")) {
|
|
21859
|
-
await this.
|
|
21903
|
+
await sendToClient(this.connection, {
|
|
21860
21904
|
sessionId,
|
|
21861
21905
|
update: {
|
|
21862
21906
|
sessionUpdate: messageChunk,
|
|
@@ -21878,7 +21922,7 @@ var Agent = class {
|
|
|
21878
21922
|
mimeType: effectiveMime,
|
|
21879
21923
|
text: Buffer.from(base64Data, "base64").toString("utf-8")
|
|
21880
21924
|
} : { uri: fileUri, mimeType: effectiveMime, blob: base64Data };
|
|
21881
|
-
await this.
|
|
21925
|
+
await sendToClient(this.connection, {
|
|
21882
21926
|
sessionId,
|
|
21883
21927
|
update: {
|
|
21884
21928
|
sessionUpdate: messageChunk,
|
|
@@ -21890,7 +21934,7 @@ var Agent = class {
|
|
|
21890
21934
|
}
|
|
21891
21935
|
}
|
|
21892
21936
|
} else if (part.type === "reasoning" && part.text) {
|
|
21893
|
-
await this.
|
|
21937
|
+
await sendToClient(this.connection, {
|
|
21894
21938
|
sessionId,
|
|
21895
21939
|
update: {
|
|
21896
21940
|
sessionUpdate: "agent_thought_chunk",
|
|
@@ -21903,7 +21947,7 @@ var Agent = class {
|
|
|
21903
21947
|
}
|
|
21904
21948
|
}
|
|
21905
21949
|
async replayToolPart(sessionId, part) {
|
|
21906
|
-
await this.
|
|
21950
|
+
await sendToClient(this.connection, {
|
|
21907
21951
|
sessionId,
|
|
21908
21952
|
update: {
|
|
21909
21953
|
sessionUpdate: "tool_call",
|
|
@@ -21928,12 +21972,13 @@ var Agent = class {
|
|
|
21928
21972
|
oldText: typeof input["oldString"] === "string" ? input["oldString"] : "",
|
|
21929
21973
|
newText: typeof input["newString"] === "string" ? input["newString"] : typeof input["content"] === "string" ? input["content"] : ""
|
|
21930
21974
|
});
|
|
21975
|
+
this.eventHandler.accumulateAICodeChangeStats(sessionId, part);
|
|
21931
21976
|
}
|
|
21932
21977
|
if (part.tool === "todowrite") {
|
|
21933
21978
|
try {
|
|
21934
21979
|
const todos = JSON.parse(part.state.output);
|
|
21935
21980
|
if (Array.isArray(todos)) {
|
|
21936
|
-
await this.
|
|
21981
|
+
await sendToClient(this.connection, {
|
|
21937
21982
|
sessionId,
|
|
21938
21983
|
update: {
|
|
21939
21984
|
sessionUpdate: "plan",
|
|
@@ -21949,7 +21994,7 @@ var Agent = class {
|
|
|
21949
21994
|
} catch {
|
|
21950
21995
|
}
|
|
21951
21996
|
}
|
|
21952
|
-
await this.
|
|
21997
|
+
await sendToClient(this.connection, {
|
|
21953
21998
|
sessionId,
|
|
21954
21999
|
update: {
|
|
21955
22000
|
sessionUpdate: "tool_call_update",
|
|
@@ -21966,7 +22011,7 @@ var Agent = class {
|
|
|
21966
22011
|
break;
|
|
21967
22012
|
}
|
|
21968
22013
|
case "error":
|
|
21969
|
-
await this.
|
|
22014
|
+
await sendToClient(this.connection, {
|
|
21970
22015
|
sessionId,
|
|
21971
22016
|
update: {
|
|
21972
22017
|
sessionUpdate: "tool_call_update",
|
|
@@ -22002,19 +22047,6 @@ var Agent = class {
|
|
|
22002
22047
|
childCost += childMessages.filter((m) => m.info.role === "assistant").reduce((sum, m) => sum + (m.info.cost ?? 0), 0);
|
|
22003
22048
|
}
|
|
22004
22049
|
}
|
|
22005
|
-
const stats = this.eventHandler.getDiffStats(sessionId);
|
|
22006
|
-
let childStats;
|
|
22007
|
-
for (const childId of children) {
|
|
22008
|
-
const cs = this.eventHandler.getDiffStats(childId);
|
|
22009
|
-
if (cs) {
|
|
22010
|
-
childStats = childStats ? {
|
|
22011
|
-
additions: childStats.additions + cs.additions,
|
|
22012
|
-
deletions: childStats.deletions + cs.deletions,
|
|
22013
|
-
files: childStats.files + cs.files
|
|
22014
|
-
} : { ...cs };
|
|
22015
|
-
}
|
|
22016
|
-
}
|
|
22017
|
-
const totalStats = stats ?? childStats;
|
|
22018
22050
|
const providers = await this.sdk.config.providers({ directory }).then((x) => x.data?.providers ?? []).catch(() => []);
|
|
22019
22051
|
const provider = providers.find((p) => p.id === msg.providerID);
|
|
22020
22052
|
const model = provider?.models[msg.modelID];
|
|
@@ -22025,13 +22057,9 @@ var Agent = class {
|
|
|
22025
22057
|
_meta.childCost = childCost;
|
|
22026
22058
|
_meta.childSessionCount = children.length;
|
|
22027
22059
|
}
|
|
22028
|
-
|
|
22029
|
-
|
|
22030
|
-
|
|
22031
|
-
if (childStats) {
|
|
22032
|
-
_meta.childCodeChange = childStats;
|
|
22033
|
-
}
|
|
22034
|
-
await this.sendToClient({
|
|
22060
|
+
this.aggregateFileDiffStats(sessionId, children, _meta);
|
|
22061
|
+
this.aggregateAICodeChangeStats(sessionId, children, _meta);
|
|
22062
|
+
await sendToClient(this.connection, {
|
|
22035
22063
|
sessionId,
|
|
22036
22064
|
update: {
|
|
22037
22065
|
sessionUpdate: "usage_update",
|
|
@@ -22043,6 +22071,56 @@ var Agent = class {
|
|
|
22043
22071
|
}).catch(() => {
|
|
22044
22072
|
});
|
|
22045
22073
|
}
|
|
22074
|
+
/**
|
|
22075
|
+
* Aggregate file diff stats (git-based) for parent + child sessions into _meta.
|
|
22076
|
+
* 主 session 的 session.diff 已包含子任务的变更数据,直接使用,不累加子 session。
|
|
22077
|
+
*/
|
|
22078
|
+
aggregateFileDiffStats(sessionId, children, _meta) {
|
|
22079
|
+
const stats = this.eventHandler.getFileDiffStats(sessionId);
|
|
22080
|
+
let childFileDiffStats;
|
|
22081
|
+
for (const childId of children) {
|
|
22082
|
+
const cs = this.eventHandler.getFileDiffStats(childId);
|
|
22083
|
+
if (cs) {
|
|
22084
|
+
childFileDiffStats = childFileDiffStats ? {
|
|
22085
|
+
additions: childFileDiffStats.additions + cs.additions,
|
|
22086
|
+
deletions: childFileDiffStats.deletions + cs.deletions,
|
|
22087
|
+
files: childFileDiffStats.files + cs.files
|
|
22088
|
+
} : { ...cs };
|
|
22089
|
+
}
|
|
22090
|
+
}
|
|
22091
|
+
const totalFileDiffStats = stats ?? childFileDiffStats;
|
|
22092
|
+
if (totalFileDiffStats) {
|
|
22093
|
+
_meta.fileDiffStats = totalFileDiffStats;
|
|
22094
|
+
}
|
|
22095
|
+
if (childFileDiffStats) {
|
|
22096
|
+
_meta.childFileDiffStats = childFileDiffStats;
|
|
22097
|
+
}
|
|
22098
|
+
}
|
|
22099
|
+
/**
|
|
22100
|
+
* Aggregate AI code change stats (tool-based) for parent + child sessions into _meta.
|
|
22101
|
+
*/
|
|
22102
|
+
aggregateAICodeChangeStats(sessionId, children, _meta) {
|
|
22103
|
+
const parentStats = this.eventHandler.getAICodeChangeStats(sessionId);
|
|
22104
|
+
let childAICodeChangeStats;
|
|
22105
|
+
for (const childId of children) {
|
|
22106
|
+
const cs = this.eventHandler.getAICodeChangeStats(childId);
|
|
22107
|
+
if (cs) {
|
|
22108
|
+
childAICodeChangeStats = childAICodeChangeStats ? {
|
|
22109
|
+
additions: childAICodeChangeStats.additions + cs.additions,
|
|
22110
|
+
deletions: childAICodeChangeStats.deletions + cs.deletions,
|
|
22111
|
+
files: childAICodeChangeStats.files + cs.files
|
|
22112
|
+
} : { ...cs };
|
|
22113
|
+
}
|
|
22114
|
+
}
|
|
22115
|
+
const totalAICodeChangeStats = parentStats ? childAICodeChangeStats ? {
|
|
22116
|
+
additions: parentStats.additions + childAICodeChangeStats.additions,
|
|
22117
|
+
deletions: parentStats.deletions + childAICodeChangeStats.deletions,
|
|
22118
|
+
files: parentStats.files + childAICodeChangeStats.files
|
|
22119
|
+
} : parentStats : childAICodeChangeStats;
|
|
22120
|
+
if (totalAICodeChangeStats) {
|
|
22121
|
+
_meta.aiCodeChange = totalAICodeChangeStats;
|
|
22122
|
+
}
|
|
22123
|
+
}
|
|
22046
22124
|
convertPromptParts(parts) {
|
|
22047
22125
|
const result = [];
|
|
22048
22126
|
for (const part of parts) {
|
|
@@ -22168,6 +22246,91 @@ function parseModelSelection(modelId, providers) {
|
|
|
22168
22246
|
}
|
|
22169
22247
|
|
|
22170
22248
|
// src/index.ts
|
|
22249
|
+
var nativeFetch = (input, init) => {
|
|
22250
|
+
return new Promise((resolve, reject) => {
|
|
22251
|
+
let url2;
|
|
22252
|
+
let requestMethod;
|
|
22253
|
+
let requestHeaders;
|
|
22254
|
+
let requestBody = null;
|
|
22255
|
+
if (typeof input === "string") {
|
|
22256
|
+
url2 = new URL(input);
|
|
22257
|
+
} else if (input instanceof URL) {
|
|
22258
|
+
url2 = input;
|
|
22259
|
+
} else {
|
|
22260
|
+
url2 = new URL(input.url);
|
|
22261
|
+
requestMethod = input.method;
|
|
22262
|
+
requestHeaders = input.headers;
|
|
22263
|
+
requestBody = input.body;
|
|
22264
|
+
}
|
|
22265
|
+
const method = (init?.method ?? requestMethod ?? "GET").toUpperCase();
|
|
22266
|
+
const mergedHeaders = new Headers(init?.headers ?? requestHeaders ?? void 0);
|
|
22267
|
+
const headerObj = {};
|
|
22268
|
+
mergedHeaders.forEach((value, key) => {
|
|
22269
|
+
headerObj[key] = value;
|
|
22270
|
+
});
|
|
22271
|
+
const body = init?.body !== void 0 ? init.body : requestBody;
|
|
22272
|
+
const signal = init?.signal;
|
|
22273
|
+
if (signal?.aborted) {
|
|
22274
|
+
return reject(
|
|
22275
|
+
signal.reason instanceof Error ? signal.reason : new DOMException("The operation was aborted.", "AbortError")
|
|
22276
|
+
);
|
|
22277
|
+
}
|
|
22278
|
+
const mod = url2.protocol === "https:" ? https : http;
|
|
22279
|
+
const req = mod.request(
|
|
22280
|
+
url2,
|
|
22281
|
+
{
|
|
22282
|
+
method,
|
|
22283
|
+
headers: headerObj
|
|
22284
|
+
// Note: do NOT set `timeout` here. Leaving it unset means
|
|
22285
|
+
// node:http will not apply any inactivity-based abort.
|
|
22286
|
+
},
|
|
22287
|
+
(res) => {
|
|
22288
|
+
const respHeaders = new Headers();
|
|
22289
|
+
for (const [k, v] of Object.entries(res.headers)) {
|
|
22290
|
+
if (v == null) continue;
|
|
22291
|
+
if (Array.isArray(v)) {
|
|
22292
|
+
for (const item of v) respHeaders.append(k, item);
|
|
22293
|
+
} else {
|
|
22294
|
+
respHeaders.set(k, String(v));
|
|
22295
|
+
}
|
|
22296
|
+
}
|
|
22297
|
+
const webStream = import_node_stream.Readable.toWeb(res);
|
|
22298
|
+
resolve(
|
|
22299
|
+
new Response(webStream, {
|
|
22300
|
+
status: res.statusCode ?? 200,
|
|
22301
|
+
statusText: res.statusMessage ?? "",
|
|
22302
|
+
headers: respHeaders
|
|
22303
|
+
})
|
|
22304
|
+
);
|
|
22305
|
+
}
|
|
22306
|
+
);
|
|
22307
|
+
req.on("error", reject);
|
|
22308
|
+
if (signal) {
|
|
22309
|
+
signal.addEventListener(
|
|
22310
|
+
"abort",
|
|
22311
|
+
() => {
|
|
22312
|
+
req.destroy(
|
|
22313
|
+
signal.reason instanceof Error ? signal.reason : new DOMException("The operation was aborted.", "AbortError")
|
|
22314
|
+
);
|
|
22315
|
+
},
|
|
22316
|
+
{ once: true }
|
|
22317
|
+
);
|
|
22318
|
+
}
|
|
22319
|
+
if (body == null) {
|
|
22320
|
+
req.end();
|
|
22321
|
+
} else if (typeof body === "string") {
|
|
22322
|
+
req.end(body);
|
|
22323
|
+
} else if (body instanceof Uint8Array || Buffer.isBuffer(body)) {
|
|
22324
|
+
req.end(body);
|
|
22325
|
+
} else if (body instanceof URLSearchParams) {
|
|
22326
|
+
req.end(body.toString());
|
|
22327
|
+
} else if (typeof body.pipeTo === "function") {
|
|
22328
|
+
import_node_stream.Readable.fromWeb(body).pipe(req);
|
|
22329
|
+
} else {
|
|
22330
|
+
req.end(String(body));
|
|
22331
|
+
}
|
|
22332
|
+
});
|
|
22333
|
+
};
|
|
22171
22334
|
function parseArgs(args) {
|
|
22172
22335
|
let server = "http://localhost:4096";
|
|
22173
22336
|
let cwd = process.cwd();
|
|
@@ -22207,7 +22370,10 @@ async function main() {
|
|
|
22207
22370
|
initLogger();
|
|
22208
22371
|
if (log) setLogEnabled(true);
|
|
22209
22372
|
sysLog("starting", { server, cwd });
|
|
22210
|
-
const sdk = createOpencodeClient({
|
|
22373
|
+
const sdk = createOpencodeClient({
|
|
22374
|
+
baseUrl: server,
|
|
22375
|
+
fetch: nativeFetch
|
|
22376
|
+
});
|
|
22211
22377
|
try {
|
|
22212
22378
|
await sdk.global.health();
|
|
22213
22379
|
sysLog("server_connected");
|