lody 0.59.1 → 0.60.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chunks/{index-Dv4vvpJo.js → index-Dr2JkTB2.js} +30 -16
- package/dist/index.js +1638 -299
- package/package.json +3 -2
package/dist/index.js
CHANGED
|
@@ -20,6 +20,7 @@ import require$$0$7, { errorMonitor, EventEmitter as EventEmitter$1 } from "node
|
|
|
20
20
|
import * as diagch from "diagnostics_channel";
|
|
21
21
|
import diagch__default from "diagnostics_channel";
|
|
22
22
|
import * as net from "node:net";
|
|
23
|
+
import net__default from "node:net";
|
|
23
24
|
import require$$1$4 from "async_hooks";
|
|
24
25
|
import require$$1$5, { execFile, spawn as spawn$1, execFileSync } from "node:child_process";
|
|
25
26
|
import fs$3, { readdir, readFile, createReadStream, existsSync, readFileSync as readFileSync$1, createWriteStream, rmSync, readdirSync, promises as promises$1 } from "node:fs";
|
|
@@ -47,7 +48,7 @@ import require$$1$6 from "string_decoder";
|
|
|
47
48
|
import * as http$2 from "http";
|
|
48
49
|
import http__default from "http";
|
|
49
50
|
import require$$1$7 from "https";
|
|
50
|
-
import { randomFillSync, randomUUID, createHash, randomBytes as randomBytes$1 } from "node:crypto";
|
|
51
|
+
import crypto$1, { randomFillSync, randomUUID, createHash, randomBytes as randomBytes$1 } from "node:crypto";
|
|
51
52
|
import require$$0$a from "net";
|
|
52
53
|
import require$$4$3 from "tls";
|
|
53
54
|
import { i as imports, _ as __wbg_set_wasm$1, r as rawWasm, L as LoroDoc, E as EphemeralStoreWasm, U as UndoManager, c as callPendingEvents$3, a as LoroTree, b as LoroText, d as LoroMovableList, e as LoroList, f as LoroMap, g as __vite__initWasm, V as VersionVector, h as decodeImportBlobMeta, __tla as __tla_0 } from "./chunks/loro_wasm_bg-BV-n7JyC.js";
|
|
@@ -12304,7 +12305,7 @@ ${JSON.stringify(itemHeaders)}
|
|
|
12304
12305
|
function createTransport(options, makeRequest, buffer2 = makePromiseBuffer(options.bufferSize || DEFAULT_TRANSPORT_BUFFER_SIZE)) {
|
|
12305
12306
|
let rateLimits = {};
|
|
12306
12307
|
const flush2 = (timeout2) => buffer2.drain(timeout2);
|
|
12307
|
-
function
|
|
12308
|
+
function send2(envelope) {
|
|
12308
12309
|
const filteredEnvelopeItems = [];
|
|
12309
12310
|
forEachEnvelopeItem(envelope, (item, type2) => {
|
|
12310
12311
|
const dataCategory = envelopeItemTypeToDataCategory(type2);
|
|
@@ -12353,7 +12354,7 @@ ${JSON.stringify(itemHeaders)}
|
|
|
12353
12354
|
});
|
|
12354
12355
|
}
|
|
12355
12356
|
return {
|
|
12356
|
-
send,
|
|
12357
|
+
send: send2,
|
|
12357
12358
|
flush: flush2
|
|
12358
12359
|
};
|
|
12359
12360
|
}
|
|
@@ -25954,7 +25955,7 @@ Event: ${getEventDescription(event)}`);
|
|
|
25954
25955
|
const instrumentation2 = this;
|
|
25955
25956
|
this._diag.debug("Patching fastify reply.send function");
|
|
25956
25957
|
return function patchSend(original) {
|
|
25957
|
-
return function
|
|
25958
|
+
return function send2(...args2) {
|
|
25958
25959
|
const maybeError = args2[0];
|
|
25959
25960
|
if (!instrumentation2.isEnabled()) {
|
|
25960
25961
|
return original.apply(this, args2);
|
|
@@ -27283,7 +27284,7 @@ Event: ${getEventDescription(event)}`);
|
|
|
27283
27284
|
const transactionPromise = original.apply(this, args2);
|
|
27284
27285
|
transactionPromise.then((transaction2) => {
|
|
27285
27286
|
const originalSend = transaction2.send;
|
|
27286
|
-
transaction2.send = function
|
|
27287
|
+
transaction2.send = function send2(...args3) {
|
|
27287
27288
|
return api_1.context.with(api_1.trace.setSpan(api_1.context.active(), transactionSpan), () => {
|
|
27288
27289
|
const patched = instrumentation2._getSendPatch()(originalSend);
|
|
27289
27290
|
return patched.apply(this, args3).catch((err2) => {
|
|
@@ -27369,7 +27370,7 @@ Event: ${getEventDescription(event)}`);
|
|
|
27369
27370
|
_getSendPatch() {
|
|
27370
27371
|
const instrumentation2 = this;
|
|
27371
27372
|
return (original) => {
|
|
27372
|
-
return function
|
|
27373
|
+
return function send2(...args2) {
|
|
27373
27374
|
const record2 = args2[0];
|
|
27374
27375
|
const spans = record2.messages.map((message) => {
|
|
27375
27376
|
return instrumentation2._startProducerSpan(record2.topic, message);
|
|
@@ -36827,7 +36828,7 @@ Mongoose Error Code: ${error2.code}` : ""}`
|
|
|
36827
36828
|
return client;
|
|
36828
36829
|
}
|
|
36829
36830
|
const name$1 = "lody";
|
|
36830
|
-
const version$4 = "0.
|
|
36831
|
+
const version$4 = "0.60.1";
|
|
36831
36832
|
const description$1 = "Lody Agent CLI tool for managing remote command execution";
|
|
36832
36833
|
const type$2 = "module";
|
|
36833
36834
|
const main$4 = "dist/index.js";
|
|
@@ -36942,6 +36943,7 @@ Mongoose Error Code: ${error2.code}` : ""}`
|
|
|
36942
36943
|
const dependencies$1 = {
|
|
36943
36944
|
"better-sqlite3": "catalog:",
|
|
36944
36945
|
"loro-crdt": "1.13.1",
|
|
36946
|
+
"node-pty": "1.1.0",
|
|
36945
36947
|
"shell-env": "^4.0.3",
|
|
36946
36948
|
"typescript": "^5.9.3"
|
|
36947
36949
|
};
|
|
@@ -37137,6 +37139,30 @@ Task description:
|
|
|
37137
37139
|
"image/webp",
|
|
37138
37140
|
"image/gif"
|
|
37139
37141
|
];
|
|
37142
|
+
const IMAGE_MIME_TYPE_BY_EXTENSION = {
|
|
37143
|
+
png: "image/png",
|
|
37144
|
+
apng: "image/apng",
|
|
37145
|
+
jpg: "image/jpeg",
|
|
37146
|
+
jpeg: "image/jpeg",
|
|
37147
|
+
jfif: "image/jpeg",
|
|
37148
|
+
gif: "image/gif",
|
|
37149
|
+
webp: "image/webp",
|
|
37150
|
+
svg: "image/svg+xml",
|
|
37151
|
+
bmp: "image/bmp",
|
|
37152
|
+
ico: "image/x-icon",
|
|
37153
|
+
cur: "image/x-icon",
|
|
37154
|
+
avif: "image/avif"
|
|
37155
|
+
};
|
|
37156
|
+
function getImageMimeTypeForPath(pathOrName) {
|
|
37157
|
+
const lastDot = pathOrName.lastIndexOf(".");
|
|
37158
|
+
if (lastDot < 0 || lastDot === pathOrName.length - 1) return void 0;
|
|
37159
|
+
const extension2 = pathOrName.slice(lastDot + 1).trim().toLowerCase();
|
|
37160
|
+
return IMAGE_MIME_TYPE_BY_EXTENSION[extension2];
|
|
37161
|
+
}
|
|
37162
|
+
function isBinaryImagePath(pathOrName) {
|
|
37163
|
+
const mimeType = getImageMimeTypeForPath(pathOrName);
|
|
37164
|
+
return mimeType !== void 0 && mimeType !== "image/svg+xml";
|
|
37165
|
+
}
|
|
37140
37166
|
const WORKSPACE_API_PATH_PREFIX = "/api/workspaces";
|
|
37141
37167
|
const SESSION_IMAGE_UPLOAD_API_PATH = "/session-images/upload";
|
|
37142
37168
|
const trimTrailingSlash = (url) => {
|
|
@@ -47263,7 +47289,11 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
47263
47289
|
const LocalProjectFileReadResultSchema = object$1({
|
|
47264
47290
|
path: string$1(),
|
|
47265
47291
|
content: string$1(),
|
|
47266
|
-
truncated: boolean()
|
|
47292
|
+
truncated: boolean(),
|
|
47293
|
+
encoding: _enum$1([
|
|
47294
|
+
"utf8",
|
|
47295
|
+
"base64"
|
|
47296
|
+
]).optional()
|
|
47267
47297
|
}).strict();
|
|
47268
47298
|
const LocalProjectDirectoryListResultSchema = object$1({
|
|
47269
47299
|
entries: array$2(object$1({
|
|
@@ -47777,6 +47807,8 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
47777
47807
|
"acp_not_ready",
|
|
47778
47808
|
"agent_disconnected",
|
|
47779
47809
|
"turn_pre_prompt_failed",
|
|
47810
|
+
"message_delivery_failed",
|
|
47811
|
+
"machine_access_denied",
|
|
47780
47812
|
"acp_auth_required",
|
|
47781
47813
|
"acp_internal_error",
|
|
47782
47814
|
"acp_upstream_api_error",
|
|
@@ -48123,7 +48155,35 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
48123
48155
|
};
|
|
48124
48156
|
}
|
|
48125
48157
|
}
|
|
48126
|
-
const
|
|
48158
|
+
const HARDCODED_REGISTRY_ACP_AGENTS = [
|
|
48159
|
+
{
|
|
48160
|
+
id: "claude-p",
|
|
48161
|
+
name: "Interactive Claude",
|
|
48162
|
+
version: "0.1.5",
|
|
48163
|
+
description: "Interactive Claude Code ACP runtime",
|
|
48164
|
+
distribution: {
|
|
48165
|
+
npx: {
|
|
48166
|
+
package: "acp-extension-claude-pty@0.1.5",
|
|
48167
|
+
registry: "https://registry.npmjs.org/",
|
|
48168
|
+
platformPackages: {
|
|
48169
|
+
darwin: {
|
|
48170
|
+
arm64: "acp-extension-claude-pty-darwin-arm64@0.1.5",
|
|
48171
|
+
x64: "acp-extension-claude-pty-darwin-x64@0.1.5"
|
|
48172
|
+
},
|
|
48173
|
+
linux: {
|
|
48174
|
+
arm64: "acp-extension-claude-pty-linux-arm64@0.1.5",
|
|
48175
|
+
x64: "acp-extension-claude-pty-linux-x64@0.1.5"
|
|
48176
|
+
},
|
|
48177
|
+
win32: {
|
|
48178
|
+
arm64: "acp-extension-claude-pty-win32-arm64@0.1.5",
|
|
48179
|
+
x64: "acp-extension-claude-pty-win32-x64@0.1.5"
|
|
48180
|
+
}
|
|
48181
|
+
}
|
|
48182
|
+
}
|
|
48183
|
+
}
|
|
48184
|
+
}
|
|
48185
|
+
];
|
|
48186
|
+
const REMOTE_REGISTRY_ACP_AGENTS = [
|
|
48127
48187
|
{
|
|
48128
48188
|
id: "agoragentic-acp",
|
|
48129
48189
|
name: "Agoragentic",
|
|
@@ -48946,6 +49006,10 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
48946
49006
|
}
|
|
48947
49007
|
}
|
|
48948
49008
|
];
|
|
49009
|
+
const REGISTRY_ACP_AGENTS = [
|
|
49010
|
+
...HARDCODED_REGISTRY_ACP_AGENTS,
|
|
49011
|
+
...REMOTE_REGISTRY_ACP_AGENTS
|
|
49012
|
+
];
|
|
48949
49013
|
const CodexShellCommandArraySchema = array$2(string$1()).min(1);
|
|
48950
49014
|
const CodexToolRawInputSchema = object$1({
|
|
48951
49015
|
command: union$7([
|
|
@@ -55617,6 +55681,7 @@ ${tailedOutput}` : null;
|
|
|
55617
55681
|
if (brandId === "minimax") return "MM";
|
|
55618
55682
|
if (session.cliType === "builtin" && session.agentType === "codex") return "CX";
|
|
55619
55683
|
if (session.cliType === "builtin" && session.agentType === "claude") return "CC";
|
|
55684
|
+
if (session.cliType === "registry" && session.agentType === "claude-p") return "IC";
|
|
55620
55685
|
const source = normalizeText(agentConfig?.name) || normalizeText(session.agentType) || normalizeText(session.cliType) || "ACP";
|
|
55621
55686
|
const letters = source.replace(/[^a-zA-Z0-9]+/g, " ").split(" ").filter(Boolean).map((part) => part[0]).join("").slice(0, 2).toUpperCase();
|
|
55622
55687
|
return letters || "ACP";
|
|
@@ -55631,6 +55696,7 @@ ${tailedOutput}` : null;
|
|
|
55631
55696
|
if (brandId === "minimax") return "minimax";
|
|
55632
55697
|
if (session.cliType === "builtin" && session.agentType === "codex") return "codex";
|
|
55633
55698
|
if (session.cliType === "builtin" && session.agentType === "claude") return "claude";
|
|
55699
|
+
if (session.cliType === "registry" && session.agentType === "claude-p") return "claude";
|
|
55634
55700
|
return "agent";
|
|
55635
55701
|
}
|
|
55636
55702
|
function buildLiveActivityConversationItems({ sessions, agentConfigs = [], currentUserId, defaultTitle, statusLabels, formatUpdatedAt, maxItems = DEFAULT_MAX_ITEMS }) {
|
|
@@ -55731,6 +55797,102 @@ ${tailedOutput}` : null;
|
|
|
55731
55797
|
return normalizeBaseUrl$1(convexUrl);
|
|
55732
55798
|
}
|
|
55733
55799
|
}
|
|
55800
|
+
const TerminalDimensionsSchema = object$1({
|
|
55801
|
+
cols: number$3().int().positive(),
|
|
55802
|
+
rows: number$3().int().positive()
|
|
55803
|
+
});
|
|
55804
|
+
const TerminalSnapshotSchema = object$1({
|
|
55805
|
+
terminalId: string$1().min(1),
|
|
55806
|
+
title: string$1(),
|
|
55807
|
+
cwd: string$1().optional()
|
|
55808
|
+
});
|
|
55809
|
+
const TERMINAL_MAX_PER_SESSION = 8;
|
|
55810
|
+
const RequestIdSchema$1 = string$1().min(1).optional();
|
|
55811
|
+
const TerminalClientMessageSchema = discriminatedUnion("type", [
|
|
55812
|
+
object$1({
|
|
55813
|
+
type: literal$1("list"),
|
|
55814
|
+
requestId: RequestIdSchema$1,
|
|
55815
|
+
sessionId: string$1().min(1)
|
|
55816
|
+
}),
|
|
55817
|
+
object$1({
|
|
55818
|
+
type: literal$1("open"),
|
|
55819
|
+
requestId: RequestIdSchema$1,
|
|
55820
|
+
sessionId: string$1().min(1),
|
|
55821
|
+
cols: TerminalDimensionsSchema.shape.cols,
|
|
55822
|
+
rows: TerminalDimensionsSchema.shape.rows
|
|
55823
|
+
}),
|
|
55824
|
+
object$1({
|
|
55825
|
+
type: literal$1("attach"),
|
|
55826
|
+
requestId: RequestIdSchema$1,
|
|
55827
|
+
terminalId: string$1().min(1),
|
|
55828
|
+
cols: TerminalDimensionsSchema.shape.cols,
|
|
55829
|
+
rows: TerminalDimensionsSchema.shape.rows
|
|
55830
|
+
}),
|
|
55831
|
+
object$1({
|
|
55832
|
+
type: literal$1("input"),
|
|
55833
|
+
requestId: RequestIdSchema$1,
|
|
55834
|
+
terminalId: string$1().min(1),
|
|
55835
|
+
data: string$1()
|
|
55836
|
+
}),
|
|
55837
|
+
object$1({
|
|
55838
|
+
type: literal$1("resize"),
|
|
55839
|
+
requestId: RequestIdSchema$1,
|
|
55840
|
+
terminalId: string$1().min(1),
|
|
55841
|
+
cols: TerminalDimensionsSchema.shape.cols,
|
|
55842
|
+
rows: TerminalDimensionsSchema.shape.rows
|
|
55843
|
+
}),
|
|
55844
|
+
object$1({
|
|
55845
|
+
type: literal$1("close"),
|
|
55846
|
+
requestId: RequestIdSchema$1,
|
|
55847
|
+
terminalId: string$1().min(1)
|
|
55848
|
+
}),
|
|
55849
|
+
object$1({
|
|
55850
|
+
type: literal$1("close_session"),
|
|
55851
|
+
requestId: RequestIdSchema$1,
|
|
55852
|
+
sessionId: string$1().min(1)
|
|
55853
|
+
})
|
|
55854
|
+
]);
|
|
55855
|
+
discriminatedUnion("type", [
|
|
55856
|
+
object$1({
|
|
55857
|
+
type: literal$1("terminals"),
|
|
55858
|
+
requestId: RequestIdSchema$1,
|
|
55859
|
+
sessionId: string$1().min(1),
|
|
55860
|
+
terminals: array$2(TerminalSnapshotSchema)
|
|
55861
|
+
}),
|
|
55862
|
+
object$1({
|
|
55863
|
+
type: literal$1("opened"),
|
|
55864
|
+
requestId: RequestIdSchema$1,
|
|
55865
|
+
terminalId: string$1().min(1),
|
|
55866
|
+
cwd: string$1().optional()
|
|
55867
|
+
}),
|
|
55868
|
+
object$1({
|
|
55869
|
+
type: literal$1("data"),
|
|
55870
|
+
requestId: RequestIdSchema$1,
|
|
55871
|
+
terminalId: string$1().min(1),
|
|
55872
|
+
data: string$1(),
|
|
55873
|
+
replay: boolean().optional()
|
|
55874
|
+
}),
|
|
55875
|
+
object$1({
|
|
55876
|
+
type: literal$1("title"),
|
|
55877
|
+
requestId: RequestIdSchema$1,
|
|
55878
|
+
terminalId: string$1().min(1),
|
|
55879
|
+
title: string$1()
|
|
55880
|
+
}),
|
|
55881
|
+
object$1({
|
|
55882
|
+
type: literal$1("exit"),
|
|
55883
|
+
requestId: RequestIdSchema$1,
|
|
55884
|
+
terminalId: string$1().min(1),
|
|
55885
|
+
exitCode: number$3().int(),
|
|
55886
|
+
signal: string$1().optional()
|
|
55887
|
+
}),
|
|
55888
|
+
object$1({
|
|
55889
|
+
type: literal$1("error"),
|
|
55890
|
+
requestId: RequestIdSchema$1,
|
|
55891
|
+
terminalId: string$1().min(1).optional(),
|
|
55892
|
+
code: string$1().min(1),
|
|
55893
|
+
message: string$1()
|
|
55894
|
+
})
|
|
55895
|
+
]);
|
|
55734
55896
|
const LOCAL_PROBE_PORT$1 = 17789;
|
|
55735
55897
|
const LOCAL_SESSION_CONTROL_PORT = 17790;
|
|
55736
55898
|
const IMAGE_UPLOAD_PATH = "/image-upload";
|
|
@@ -84135,17 +84297,17 @@ ${fromBody}`;
|
|
|
84135
84297
|
return this.client.subscribeToConnectionState(cb);
|
|
84136
84298
|
}
|
|
84137
84299
|
}
|
|
84138
|
-
const require$
|
|
84300
|
+
const require$2 = createRequire(resolve$1("."));
|
|
84139
84301
|
var __create = Object.create;
|
|
84140
84302
|
var __defProp = Object.defineProperty;
|
|
84141
84303
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
84142
84304
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
84143
84305
|
var __getProtoOf = Object.getPrototypeOf;
|
|
84144
84306
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
84145
|
-
var __require = ((x) => typeof require$
|
|
84146
|
-
get: (a, b) => (typeof require$
|
|
84307
|
+
var __require = ((x) => typeof require$2 !== "undefined" ? require$2 : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
84308
|
+
get: (a, b) => (typeof require$2 !== "undefined" ? require$2 : a)[b]
|
|
84147
84309
|
}) : x)(function(x) {
|
|
84148
|
-
if (typeof require$
|
|
84310
|
+
if (typeof require$2 !== "undefined") return require$2.apply(this, arguments);
|
|
84149
84311
|
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
84150
84312
|
});
|
|
84151
84313
|
var __commonJS = (cb, mod2) => function __require2() {
|
|
@@ -110943,6 +111105,18 @@ ${this.stack.split("\n").slice(1).join("\n")}` : this.toString();
|
|
|
110943
111105
|
}
|
|
110944
111106
|
}
|
|
110945
111107
|
};
|
|
111108
|
+
const DEFAULT_RECONNECT_BASE_DELAY_MS = 1e3;
|
|
111109
|
+
const DEFAULT_RECONNECT_MAX_DELAY_MS = 3e4;
|
|
111110
|
+
const RECONNECT_JITTER_FRACTION = 0.2;
|
|
111111
|
+
const computeLoroReconnectDelayMs = (attempt, options = {}) => {
|
|
111112
|
+
const safeAttempt = Number.isFinite(attempt) ? Math.max(0, Math.floor(attempt)) : 0;
|
|
111113
|
+
const baseDelayMs = Math.max(0, options.baseDelayMs ?? DEFAULT_RECONNECT_BASE_DELAY_MS);
|
|
111114
|
+
const maxDelayMs = Math.max(baseDelayMs, options.maxDelayMs ?? DEFAULT_RECONNECT_MAX_DELAY_MS);
|
|
111115
|
+
const exponentialDelay = Math.min(maxDelayMs, baseDelayMs * 2 ** safeAttempt);
|
|
111116
|
+
const random2 = options.random ?? Math.random;
|
|
111117
|
+
const jitter = exponentialDelay * RECONNECT_JITTER_FRACTION * (Math.min(1, Math.max(0, random2())) * 2 - 1);
|
|
111118
|
+
return Math.min(maxDelayMs, Math.max(0, Math.round(exponentialDelay + jitter)));
|
|
111119
|
+
};
|
|
110946
111120
|
const isRecoverableMetaRoomStatus = (status) => status === "disconnected" || status === "error";
|
|
110947
111121
|
class LoroConnectionRecoveryController {
|
|
110948
111122
|
recoveryEvents = runSync(unbounded());
|
|
@@ -110962,6 +111136,7 @@ ${this.stack.split("\n").slice(1).join("\n")}` : this.toString();
|
|
|
110962
111136
|
activeOperation = null;
|
|
110963
111137
|
metaRoomReadyPending = 0;
|
|
110964
111138
|
metaRoomReadySequence = 0;
|
|
111139
|
+
reconnectAttempt = 0;
|
|
110965
111140
|
initialMetaSyncCompleted;
|
|
110966
111141
|
isCleanedUp = false;
|
|
110967
111142
|
constructor(options) {
|
|
@@ -110992,6 +111167,10 @@ ${this.stack.split("\n").slice(1).join("\n")}` : this.toString();
|
|
|
110992
111167
|
}
|
|
110993
111168
|
setTransportStatus(status) {
|
|
110994
111169
|
this.transportStatus = status;
|
|
111170
|
+
if (this.isStreamsHealthy()) {
|
|
111171
|
+
this.resetReconnectBackoff("transport-connected");
|
|
111172
|
+
return;
|
|
111173
|
+
}
|
|
110995
111174
|
if (status === "disconnected") {
|
|
110996
111175
|
this.scheduleReconnect("transport-disconnected");
|
|
110997
111176
|
}
|
|
@@ -111123,6 +111302,7 @@ ${this.stack.split("\n").slice(1).join("\n")}` : this.toString();
|
|
|
111123
111302
|
this.markReconnectCompletionActive(event.completion);
|
|
111124
111303
|
try {
|
|
111125
111304
|
await this.runReconnect(event.reason, event.options);
|
|
111305
|
+
this.updateBackoffAfterReconnect(event.reason, event.options);
|
|
111126
111306
|
this.resolveReconnectCompletion(event.completion);
|
|
111127
111307
|
} catch (error2) {
|
|
111128
111308
|
this.rejectReconnectCompletion(event.completion, error2);
|
|
@@ -111219,6 +111399,9 @@ ${this.stack.split("\n").slice(1).join("\n")}` : this.toString();
|
|
|
111219
111399
|
this.metaRoomReadyPending = Math.max(0, this.metaRoomReadyPending - 1);
|
|
111220
111400
|
}
|
|
111221
111401
|
}
|
|
111402
|
+
if (this.isStreamsHealthy()) {
|
|
111403
|
+
this.resetReconnectBackoff("meta-room-joined");
|
|
111404
|
+
}
|
|
111222
111405
|
}
|
|
111223
111406
|
startAutoReconnectWatchdog() {
|
|
111224
111407
|
const intervalMs = readTimeoutEnv("LODY_LORO_AUTO_RECONNECT_INTERVAL_MS", 3e4);
|
|
@@ -111241,8 +111424,13 @@ ${this.stack.split("\n").slice(1).join("\n")}` : this.toString();
|
|
|
111241
111424
|
if (this.isCleanedUp || this.isStreamsHealthy() || this.reconnectTimer) {
|
|
111242
111425
|
return;
|
|
111243
111426
|
}
|
|
111244
|
-
const
|
|
111245
|
-
|
|
111427
|
+
const baseDelayMs = readTimeoutEnv("LODY_LORO_AUTO_RECONNECT_DELAY_MS", DEFAULT_RECONNECT_BASE_DELAY_MS);
|
|
111428
|
+
const maxDelayMs = readTimeoutEnv("LODY_LORO_AUTO_RECONNECT_MAX_DELAY_MS", DEFAULT_RECONNECT_MAX_DELAY_MS);
|
|
111429
|
+
const delayMs = computeLoroReconnectDelayMs(this.reconnectAttempt, {
|
|
111430
|
+
baseDelayMs,
|
|
111431
|
+
maxDelayMs
|
|
111432
|
+
});
|
|
111433
|
+
this.logger.debug(`[${this.workspaceId}] Scheduling Loro streams reconnect in ${delayMs}ms (attempt=${this.reconnectAttempt + 1}, reason=${reason}, transport=${this.transportStatus}, metaRoom=${this.metaRoomStatus ?? "unknown"})`);
|
|
111246
111434
|
this.reconnectTimer = setTimeout(() => {
|
|
111247
111435
|
this.reconnectTimer = null;
|
|
111248
111436
|
this.offer({
|
|
@@ -111258,6 +111446,28 @@ ${this.stack.split("\n").slice(1).join("\n")}` : this.toString();
|
|
|
111258
111446
|
isStreamsHealthy() {
|
|
111259
111447
|
return this.transportStatus === "connected" && this.metaRoomStatus === "joined";
|
|
111260
111448
|
}
|
|
111449
|
+
resetReconnectBackoff(reason) {
|
|
111450
|
+
if (this.reconnectAttempt === 0) {
|
|
111451
|
+
return;
|
|
111452
|
+
}
|
|
111453
|
+
this.logger.debug(`[${this.workspaceId}] Resetting Loro streams reconnect backoff (reason=${reason}, attempts=${this.reconnectAttempt})`);
|
|
111454
|
+
this.reconnectAttempt = 0;
|
|
111455
|
+
}
|
|
111456
|
+
updateBackoffAfterReconnect(reason, options) {
|
|
111457
|
+
if (this.isCleanedUp) {
|
|
111458
|
+
return;
|
|
111459
|
+
}
|
|
111460
|
+
if (this.isStreamsHealthy()) {
|
|
111461
|
+
this.resetReconnectBackoff(`reconnect:${reason}`);
|
|
111462
|
+
return;
|
|
111463
|
+
}
|
|
111464
|
+
if (options.force) {
|
|
111465
|
+
this.reconnectAttempt = 0;
|
|
111466
|
+
return;
|
|
111467
|
+
}
|
|
111468
|
+
this.reconnectAttempt += 1;
|
|
111469
|
+
this.scheduleReconnect(`retry-after-${reason}`);
|
|
111470
|
+
}
|
|
111261
111471
|
async runReconnect(reason, options) {
|
|
111262
111472
|
if (this.isCleanedUp) {
|
|
111263
111473
|
return;
|
|
@@ -111275,7 +111485,7 @@ ${this.stack.split("\n").slice(1).join("\n")}` : this.toString();
|
|
|
111275
111485
|
}
|
|
111276
111486
|
await this.ensureMetaRoomJoined(reason);
|
|
111277
111487
|
await withTimeout$3(this.repo.reconnect({
|
|
111278
|
-
resetBackoff: true,
|
|
111488
|
+
resetBackoff: options.force === true,
|
|
111279
111489
|
timeout: timeoutMs
|
|
111280
111490
|
}), timeoutMs, `Timeout waiting for Loro streams reconnect (workspace=${this.workspaceId})`);
|
|
111281
111491
|
if (shouldLog) {
|
|
@@ -111314,6 +111524,7 @@ ${this.stack.split("\n").slice(1).join("\n")}` : this.toString();
|
|
|
111314
111524
|
}
|
|
111315
111525
|
this.initialMetaSyncCompleted = true;
|
|
111316
111526
|
this.onMetaRoomReady();
|
|
111527
|
+
this.resetReconnectBackoff(`meta-room-ready:${reason}`);
|
|
111317
111528
|
this.logger.debug(`[${this.workspaceId}] Loro meta room ready in ${Date.now() - startedAt}ms (reason=${reason})`);
|
|
111318
111529
|
this.emitMetaRoomSynced(reason);
|
|
111319
111530
|
} catch (error2) {
|
|
@@ -112784,16 +112995,6 @@ ${this.stack.split("\n").slice(1).join("\n")}` : this.toString();
|
|
|
112784
112995
|
const key2 = getAcpCapabilityCacheKey(cliType, agentType);
|
|
112785
112996
|
return meta?.acpCapabilities?.[key2];
|
|
112786
112997
|
}
|
|
112787
|
-
async sendMachineHeartbeat() {
|
|
112788
|
-
if (!this.machine) {
|
|
112789
|
-
return;
|
|
112790
|
-
}
|
|
112791
|
-
const startedAt = Date.now();
|
|
112792
|
-
this.logger.debug(`[${this.workspaceId}] Machine heartbeat writing presence and meta`);
|
|
112793
|
-
this.presenceRuntime?.writeMachineHeartbeat();
|
|
112794
|
-
await withSlowOperationWarning(this.machine.sendHeartbeat(), this.logger, "machine.sendHeartbeat repo.upsertDocMeta(lastSeen)", this.workspaceId);
|
|
112795
|
-
this.logger.debug(`[${this.workspaceId}] Machine heartbeat meta write completed (duration=${Date.now() - startedAt}ms)`);
|
|
112796
|
-
}
|
|
112797
112998
|
async restoreMachineDocument(machineId) {
|
|
112798
112999
|
const machineRoomId = getMachineRoomId(machineId);
|
|
112799
113000
|
await this.repo.restoreDoc(machineRoomId);
|
|
@@ -113337,9 +113538,6 @@ ${this.stack.split("\n").slice(1).join("\n")}` : this.toString();
|
|
|
113337
113538
|
const current2 = await this.repo.getDocMeta(this.roomId);
|
|
113338
113539
|
if (isLoroRepoDocDeleted(current2)) return;
|
|
113339
113540
|
const currentMeta = current2?.meta;
|
|
113340
|
-
await this.repo.upsertDocMeta(this.roomId, {
|
|
113341
|
-
lastRunningSeen: getServerNow()
|
|
113342
|
-
});
|
|
113343
113541
|
this.presenceRuntime?.setSessionPresence({
|
|
113344
113542
|
sessionId: this.sessionId,
|
|
113345
113543
|
machineId: currentMeta?.machineId,
|
|
@@ -113760,11 +113958,6 @@ ${this.stack.split("\n").slice(1).join("\n")}` : this.toString();
|
|
|
113760
113958
|
}
|
|
113761
113959
|
});
|
|
113762
113960
|
}
|
|
113763
|
-
async sendHeartbeat() {
|
|
113764
|
-
await this.repo.upsertDocMeta(this.roomId, {
|
|
113765
|
-
lastSeen: getServerNow()
|
|
113766
|
-
});
|
|
113767
|
-
}
|
|
113768
113961
|
}
|
|
113769
113962
|
const DEFAULT_GATEWAY_BASE_URL = "https://streams-api-proxy.loro.dev";
|
|
113770
113963
|
const JSON_RPC_VERSION$1 = "2.0";
|
|
@@ -127702,6 +127895,9 @@ ${error2.message}` : execaMessage;
|
|
|
127702
127895
|
function resolveCodexPlatformPackage(platform2 = process.platform, arch = process.arch) {
|
|
127703
127896
|
return CODEX_PLATFORM_PACKAGES[platform2]?.[arch];
|
|
127704
127897
|
}
|
|
127898
|
+
function resolveRegistryNpxPackage(distribution, platform2 = process.platform, arch = process.arch) {
|
|
127899
|
+
return distribution.platformPackages?.[platform2]?.[arch] ?? distribution.package;
|
|
127900
|
+
}
|
|
127705
127901
|
const DEFAULT_ACP_PATH_RELATIVE_DIRS = [
|
|
127706
127902
|
".local/bin",
|
|
127707
127903
|
"bin",
|
|
@@ -127711,10 +127907,6 @@ ${error2.message}` : execaMessage;
|
|
|
127711
127907
|
agent.id,
|
|
127712
127908
|
agent
|
|
127713
127909
|
]));
|
|
127714
|
-
const builtinTypeSet = /* @__PURE__ */ new Set([
|
|
127715
|
-
"claude",
|
|
127716
|
-
"codex"
|
|
127717
|
-
]);
|
|
127718
127910
|
const moduleRequire = createRequire$1(import.meta.url);
|
|
127719
127911
|
function isRecord$2(value) {
|
|
127720
127912
|
return typeof value === "object" && value !== null;
|
|
@@ -127739,7 +127931,7 @@ ${error2.message}` : execaMessage;
|
|
|
127739
127931
|
}
|
|
127740
127932
|
}
|
|
127741
127933
|
function resolveBuiltinACPSetting(agentType) {
|
|
127742
|
-
if (!
|
|
127934
|
+
if (!isBuiltinAgentType(agentType)) {
|
|
127743
127935
|
throw new Error(`Unsupported builtin ACP type: ${agentType}`);
|
|
127744
127936
|
}
|
|
127745
127937
|
const builtinType = agentType;
|
|
@@ -127759,8 +127951,8 @@ ${error2.message}` : execaMessage;
|
|
|
127759
127951
|
};
|
|
127760
127952
|
}
|
|
127761
127953
|
}
|
|
127762
|
-
const
|
|
127763
|
-
const packageName =
|
|
127954
|
+
const platformPackage = builtinType === "codex" ? resolveCodexPlatformPackage() : void 0;
|
|
127955
|
+
const packageName = platformPackage ?? setting.packageName;
|
|
127764
127956
|
const packageSpec = `${packageName}@${setting.version}`;
|
|
127765
127957
|
const args2 = [
|
|
127766
127958
|
...builtinType === "codex" ? [
|
|
@@ -127787,7 +127979,7 @@ ${error2.message}` : execaMessage;
|
|
|
127787
127979
|
return input2.customAcp ? `custom:${serializeCustomAcpLaunchSpec(input2.customAcp)}` : `custom:${input2.agentType}:unknown`;
|
|
127788
127980
|
}
|
|
127789
127981
|
if (input2.cliType === "builtin") {
|
|
127790
|
-
if (
|
|
127982
|
+
if (isBuiltinAgentType(input2.agentType)) {
|
|
127791
127983
|
const setting = BuiltinACPSetting[input2.agentType];
|
|
127792
127984
|
return `${setting.packageName}@${setting.version}`;
|
|
127793
127985
|
}
|
|
@@ -127821,11 +128013,16 @@ ${error2.message}` : execaMessage;
|
|
|
127821
128013
|
};
|
|
127822
128014
|
}
|
|
127823
128015
|
if (agent.distribution.npx?.package) {
|
|
128016
|
+
const npxDistribution = agent.distribution.npx;
|
|
128017
|
+
const packageSpec = resolveRegistryNpxPackage(npxDistribution);
|
|
127824
128018
|
const args2 = [
|
|
128019
|
+
...npxDistribution.registry ? [
|
|
128020
|
+
`--registry=${npxDistribution.registry}`
|
|
128021
|
+
] : [],
|
|
127825
128022
|
NPX_CACHE_MODE_ARG,
|
|
127826
128023
|
"-y",
|
|
127827
|
-
|
|
127828
|
-
...
|
|
128024
|
+
packageSpec,
|
|
128025
|
+
...npxDistribution.args ?? []
|
|
127829
128026
|
];
|
|
127830
128027
|
return {
|
|
127831
128028
|
status: {
|
|
@@ -127835,7 +128032,7 @@ ${error2.message}` : execaMessage;
|
|
|
127835
128032
|
exec: {
|
|
127836
128033
|
command: "npx",
|
|
127837
128034
|
args: args2,
|
|
127838
|
-
env:
|
|
128035
|
+
env: npxDistribution.env
|
|
127839
128036
|
}
|
|
127840
128037
|
};
|
|
127841
128038
|
}
|
|
@@ -131541,6 +131738,9 @@ ${exitStatus.output}` : `Worktree ${options.phase} failed at command "${stepComm
|
|
|
131541
131738
|
}
|
|
131542
131739
|
return out;
|
|
131543
131740
|
}
|
|
131741
|
+
function shouldScrubClaudeAuthEnv(cliType, agentType) {
|
|
131742
|
+
return cliType === "builtin" && agentType === "claude" || cliType === "registry" && agentType === "claude-p";
|
|
131743
|
+
}
|
|
131544
131744
|
function isSelectGroup(item) {
|
|
131545
131745
|
return typeof item === "object" && item !== null && "group" in item;
|
|
131546
131746
|
}
|
|
@@ -131596,7 +131796,7 @@ ${exitStatus.output}` : `Worktree ${options.phase} failed at command "${stepComm
|
|
|
131596
131796
|
...process.env,
|
|
131597
131797
|
...env2
|
|
131598
131798
|
} : process.env;
|
|
131599
|
-
const probeEnv = cliType
|
|
131799
|
+
const probeEnv = shouldScrubClaudeAuthEnv(cliType, agentType) && env2 ? scrubInheritedClaudeAuthEnv(mergedProbeEnv, env2) : mergedProbeEnv;
|
|
131600
131800
|
let capturedCommands;
|
|
131601
131801
|
let commandsResolve;
|
|
131602
131802
|
const commandsPromise = new Promise((resolve2) => {
|
|
@@ -132035,23 +132235,12 @@ The postId is ${normalizedFeedbackPostId}. Use the feedback-progress-reporter sk
|
|
|
132035
132235
|
"diff",
|
|
132036
132236
|
"--numstat",
|
|
132037
132237
|
"--no-renames",
|
|
132038
|
-
mergeBase
|
|
132238
|
+
mergeBase,
|
|
132239
|
+
"HEAD"
|
|
132039
132240
|
]);
|
|
132040
132241
|
const baseDiff = parseGitNumstat(baseNumstat);
|
|
132041
|
-
const trackedBasePaths = new Set(baseDiff.map((diff2) => diff2.filePath));
|
|
132042
|
-
const untrackedPaths = (await listUntrackedFiles(runGit)).filter((filePath) => !trackedBasePaths.has(filePath));
|
|
132043
|
-
const untrackedFileDiff = await buildUntrackedFileDiffs(untrackedPaths, options?.countWorkingTreeFileLines);
|
|
132044
|
-
const baseDiffWithUntracked = [
|
|
132045
|
-
...baseDiff,
|
|
132046
|
-
...untrackedFileDiff
|
|
132047
|
-
];
|
|
132048
|
-
const untrackedFileDiffByPath = new Map(untrackedFileDiff.map((diff2) => [
|
|
132049
|
-
diff2.filePath,
|
|
132050
|
-
diff2
|
|
132051
|
-
]));
|
|
132052
132242
|
const baseDiffStats = {
|
|
132053
|
-
allChange: sumLineChange(
|
|
132054
|
-
files: baseDiffWithUntracked
|
|
132243
|
+
allChange: sumLineChange(baseDiff)
|
|
132055
132244
|
};
|
|
132056
132245
|
let commitFileDiff;
|
|
132057
132246
|
if (options?.baseCommitHash) {
|
|
@@ -132075,6 +132264,12 @@ The postId is ${normalizedFeedbackPostId}. Use the feedback-progress-reporter sk
|
|
|
132075
132264
|
});
|
|
132076
132265
|
}
|
|
132077
132266
|
const commitFileDiffPaths = new Set(commitFileDiff.map((diff2) => diff2.filePath));
|
|
132267
|
+
const untrackedPaths = await listUntrackedFiles(runGit);
|
|
132268
|
+
const untrackedFileDiff = await buildUntrackedFileDiffs(untrackedPaths, options?.countWorkingTreeFileLines);
|
|
132269
|
+
const untrackedFileDiffByPath = new Map(untrackedFileDiff.map((diff2) => [
|
|
132270
|
+
diff2.filePath,
|
|
132271
|
+
diff2
|
|
132272
|
+
]));
|
|
132078
132273
|
let turnUntrackedPaths = untrackedPaths.filter((filePath) => !commitFileDiffPaths.has(filePath));
|
|
132079
132274
|
if (turnStartWorkingTreeDiff && turnUntrackedPaths.length > 0) {
|
|
132080
132275
|
const currentHashes = await hashObjectPaths(runGit, turnUntrackedPaths);
|
|
@@ -133030,9 +133225,13 @@ $mem | ConvertTo-Json -Compress
|
|
|
133030
133225
|
this.deps.logger.warn(`[${sessionId}] Code Collab host skipped: session has no workspace directory`);
|
|
133031
133226
|
return _void;
|
|
133032
133227
|
}
|
|
133033
|
-
|
|
133228
|
+
const hostSessionId = session.getParentSessionId();
|
|
133229
|
+
this.deps.logger.debug(`[${sessionId}] Code Collab host start requested by agent turn workspaceRoot=${workspaceRoot}${hostSessionId === void 0 ? "" : ` host=${hostSessionId}`}`);
|
|
133034
133230
|
return this.tryPromise(() => startCodeCollabHost({
|
|
133035
133231
|
sessionId,
|
|
133232
|
+
...hostSessionId === void 0 ? {} : {
|
|
133233
|
+
hostSessionId
|
|
133234
|
+
},
|
|
133036
133235
|
workspaceRoot,
|
|
133037
133236
|
project
|
|
133038
133237
|
}));
|
|
@@ -133181,7 +133380,13 @@ $mem | ConvertTo-Json -Compress
|
|
|
133181
133380
|
turnId: options.turnId,
|
|
133182
133381
|
session: runtime?.session ?? options.session ?? null,
|
|
133183
133382
|
baseCommitHash: runtime?.baseCommitHash ?? null,
|
|
133184
|
-
fileDiff: markerResult?.fileDiff
|
|
133383
|
+
fileDiff: markerResult?.fileDiff,
|
|
133384
|
+
...markerResult?.allChangesFileDiff === void 0 ? {} : {
|
|
133385
|
+
allChangesFileDiff: markerResult.allChangesFileDiff
|
|
133386
|
+
},
|
|
133387
|
+
...runtime?.project === void 0 ? {} : {
|
|
133388
|
+
project: runtime.project
|
|
133389
|
+
}
|
|
133185
133390
|
})));
|
|
133186
133391
|
}).pipe(ensuring(sync(() => {
|
|
133187
133392
|
self2.clearTurnCancellation(options.sessionId, options.turnId);
|
|
@@ -133268,7 +133473,13 @@ $mem | ConvertTo-Json -Compress
|
|
|
133268
133473
|
turnId: options.runtime.turnId,
|
|
133269
133474
|
session: options.runtime.session ?? null,
|
|
133270
133475
|
baseCommitHash: options.runtime.baseCommitHash ?? null,
|
|
133271
|
-
fileDiff: failedMarkerResult?.fileDiff
|
|
133476
|
+
fileDiff: failedMarkerResult?.fileDiff,
|
|
133477
|
+
...failedMarkerResult?.allChangesFileDiff === void 0 ? {} : {
|
|
133478
|
+
allChangesFileDiff: failedMarkerResult.allChangesFileDiff
|
|
133479
|
+
},
|
|
133480
|
+
...options.runtime.project === void 0 ? {} : {
|
|
133481
|
+
project: options.runtime.project
|
|
133482
|
+
}
|
|
133272
133483
|
});
|
|
133273
133484
|
} catch (persistError) {
|
|
133274
133485
|
this.deps.logger.warn(`[${options.sessionId}] Failed to persist Code Collab fileDiff for failed turn: ${formatErrorMessage$1(persistError)}`);
|
|
@@ -133283,7 +133494,10 @@ $mem | ConvertTo-Json -Compress
|
|
|
133283
133494
|
sessionId: options.sessionId,
|
|
133284
133495
|
sessionDoc: options.sessionDoc,
|
|
133285
133496
|
turnId: options.turnId,
|
|
133286
|
-
fileDiff: markerResult?.fileDiff
|
|
133497
|
+
fileDiff: markerResult?.fileDiff,
|
|
133498
|
+
...markerResult?.allChangesFileDiff === void 0 ? {} : {
|
|
133499
|
+
allChangesFileDiff: markerResult.allChangesFileDiff
|
|
133500
|
+
}
|
|
133287
133501
|
});
|
|
133288
133502
|
await this.handleTurnError(options.sessionId, options.sessionDoc);
|
|
133289
133503
|
} catch (error2) {
|
|
@@ -133414,40 +133628,68 @@ $mem | ConvertTo-Json -Compress
|
|
|
133414
133628
|
if (await stopIfTurnCancelled("ACP finalization")) {
|
|
133415
133629
|
return;
|
|
133416
133630
|
}
|
|
133417
|
-
|
|
133418
|
-
|
|
133631
|
+
const githubProject = resolveProjectGitHubRepo(project);
|
|
133632
|
+
let branchName = null;
|
|
133633
|
+
let preferredStatsBaseBranch = project?.branch;
|
|
133634
|
+
if (githubProject) {
|
|
133635
|
+
branchName = await this.deps.turnFinalization.syncSessionBranchName(sessionId, session);
|
|
133419
133636
|
if (await stopIfTurnCancelled("branch synchronization")) {
|
|
133420
133637
|
return;
|
|
133421
133638
|
}
|
|
133422
|
-
await this.deps.turnFinalization.updateSessionDiffStats(sessionId, session, {
|
|
133423
|
-
turnId,
|
|
133424
|
-
baseCommitHash: baseCommitHash ?? void 0,
|
|
133425
|
-
turnStartWorkingTreeDiff,
|
|
133426
|
-
preferredBaseBranch: project?.branch
|
|
133427
|
-
});
|
|
133428
|
-
if (await stopIfTurnCancelled("diff recording")) {
|
|
133429
|
-
return;
|
|
133430
|
-
}
|
|
133431
133639
|
try {
|
|
133432
|
-
await this.deps.turnFinalization.detectAndAssociatePR({
|
|
133640
|
+
const detectedPr = await this.deps.turnFinalization.detectAndAssociatePR({
|
|
133433
133641
|
sessionId,
|
|
133434
133642
|
session,
|
|
133435
133643
|
sessionDoc,
|
|
133436
133644
|
project,
|
|
133437
133645
|
branchName
|
|
133438
133646
|
});
|
|
133647
|
+
preferredStatsBaseBranch = detectedPr?.baseBranch ?? preferredStatsBaseBranch;
|
|
133439
133648
|
} catch (error2) {
|
|
133440
133649
|
this.deps.logger.debug(`[${sessionId}] PR detection failed: ${formatErrorMessage$1(error2)}`);
|
|
133441
133650
|
}
|
|
133442
133651
|
if (await stopIfTurnCancelled("PR detection")) {
|
|
133443
133652
|
return;
|
|
133444
133653
|
}
|
|
133654
|
+
await this.deps.turnFinalization.updateSessionDiffStats(sessionId, session, {
|
|
133655
|
+
turnId,
|
|
133656
|
+
baseCommitHash: baseCommitHash ?? void 0,
|
|
133657
|
+
turnStartWorkingTreeDiff,
|
|
133658
|
+
preferredBaseBranch: preferredStatsBaseBranch
|
|
133659
|
+
});
|
|
133660
|
+
if (await stopIfTurnCancelled("diff recording")) {
|
|
133661
|
+
return;
|
|
133662
|
+
}
|
|
133663
|
+
}
|
|
133664
|
+
const codeCollabTurnMarkerResult = await runPromise(this.recordCodeCollabTurnMarkerEffect(sessionId, turnId, "turn:end", project, {
|
|
133665
|
+
baseCommitHash,
|
|
133666
|
+
turnStartWorkingTreeDiff
|
|
133667
|
+
}));
|
|
133668
|
+
await this.persistCodeCollabFileDiffForTurn({
|
|
133669
|
+
sessionId,
|
|
133670
|
+
sessionDoc,
|
|
133671
|
+
turnId,
|
|
133672
|
+
session,
|
|
133673
|
+
baseCommitHash,
|
|
133674
|
+
fileDiff: codeCollabTurnMarkerResult?.fileDiff,
|
|
133675
|
+
...codeCollabTurnMarkerResult?.allChangesFileDiff === void 0 ? {} : {
|
|
133676
|
+
allChangesFileDiff: codeCollabTurnMarkerResult.allChangesFileDiff
|
|
133677
|
+
},
|
|
133678
|
+
...project === void 0 ? {} : {
|
|
133679
|
+
project
|
|
133680
|
+
}
|
|
133681
|
+
});
|
|
133682
|
+
if (await stopIfTurnCancelled("Code Collab diff recording")) {
|
|
133683
|
+
return;
|
|
133684
|
+
}
|
|
133685
|
+
if (githubProject) {
|
|
133445
133686
|
try {
|
|
133446
133687
|
await this.deps.turnFinalization.autoCommitAndPushForPR({
|
|
133447
133688
|
sessionId,
|
|
133448
133689
|
session,
|
|
133449
133690
|
sessionDoc,
|
|
133450
133691
|
project,
|
|
133692
|
+
preferredBaseBranch: preferredStatsBaseBranch,
|
|
133451
133693
|
userId,
|
|
133452
133694
|
isTurnCancelled,
|
|
133453
133695
|
abortSignal: ctx.abortSignal,
|
|
@@ -133466,18 +133708,6 @@ $mem | ConvertTo-Json -Compress
|
|
|
133466
133708
|
this.captureStatusChanged(sessionId, "idle", void 0, "turn_completed");
|
|
133467
133709
|
await this.captureTurnCompleted(sessionId, sessionDoc, turnId);
|
|
133468
133710
|
this.deps.logger.info(`Session chat completed: ${sessionId}`);
|
|
133469
|
-
const codeCollabTurnMarkerResult = await runPromise(this.recordCodeCollabTurnMarkerEffect(sessionId, turnId, "turn:end", project, {
|
|
133470
|
-
baseCommitHash,
|
|
133471
|
-
turnStartWorkingTreeDiff
|
|
133472
|
-
}));
|
|
133473
|
-
await this.persistCodeCollabFileDiffForTurn({
|
|
133474
|
-
sessionId,
|
|
133475
|
-
sessionDoc,
|
|
133476
|
-
turnId,
|
|
133477
|
-
session,
|
|
133478
|
-
baseCommitHash,
|
|
133479
|
-
fileDiff: codeCollabTurnMarkerResult?.fileDiff
|
|
133480
|
-
});
|
|
133481
133711
|
try {
|
|
133482
133712
|
await sessionDoc.setLastMessageAt();
|
|
133483
133713
|
} catch (error2) {
|
|
@@ -133505,18 +133735,14 @@ $mem | ConvertTo-Json -Compress
|
|
|
133505
133735
|
}
|
|
133506
133736
|
const currentMeta = current2?.meta;
|
|
133507
133737
|
const currentDiffStats = currentMeta?.diffStats ?? (targetSessionId === sessionId ? meta?.diffStats : void 0);
|
|
133508
|
-
const currentFiles = currentDiffStats?.files ?? [];
|
|
133509
133738
|
const currentAllChange = currentDiffStats?.allChange;
|
|
133510
|
-
const hasExistingStats =
|
|
133739
|
+
const hasExistingStats = (currentAllChange?.add ?? 0) !== 0 || (currentAllChange?.del ?? 0) !== 0;
|
|
133511
133740
|
if (hasExistingStats) {
|
|
133512
133741
|
return;
|
|
133513
133742
|
}
|
|
133514
133743
|
await this.deps.workspaceDocument.repo.upsertDocMeta(targetRoomId, {
|
|
133515
133744
|
diffStats: {
|
|
133516
|
-
allChange: sumLineChange(fileDiff)
|
|
133517
|
-
files: [
|
|
133518
|
-
...fileDiff
|
|
133519
|
-
]
|
|
133745
|
+
allChange: sumLineChange(fileDiff)
|
|
133520
133746
|
}
|
|
133521
133747
|
});
|
|
133522
133748
|
} catch (error2) {
|
|
@@ -133551,14 +133777,38 @@ $mem | ConvertTo-Json -Compress
|
|
|
133551
133777
|
}
|
|
133552
133778
|
async persistCodeCollabFileDiffForTurn(options) {
|
|
133553
133779
|
const fileDiff = options.fileDiff ?? [];
|
|
133554
|
-
|
|
133780
|
+
let normalizedCodeCollabFileDiff = [];
|
|
133781
|
+
if (fileDiff.length > 0) {
|
|
133782
|
+
normalizedCodeCollabFileDiff = options.session === void 0 || options.session === null ? [
|
|
133783
|
+
...fileDiff
|
|
133784
|
+
] : await this.normalizeCodeCollabFileDiffLineStats(options.session, options.baseCommitHash ?? null, fileDiff);
|
|
133785
|
+
options.sessionDoc.setLatestAssistantHistoryFileDiff(normalizedCodeCollabFileDiff, options.turnId);
|
|
133786
|
+
}
|
|
133787
|
+
if (options.allChangesFileDiff !== void 0 && !resolveProjectGitHubRepo(options.project)) {
|
|
133788
|
+
await this.upsertDiffStatsFromCodeCollabAllChanges(options.sessionId, options.sessionDoc, options.allChangesFileDiff);
|
|
133555
133789
|
return;
|
|
133556
133790
|
}
|
|
133557
|
-
|
|
133558
|
-
|
|
133559
|
-
|
|
133560
|
-
|
|
133561
|
-
|
|
133791
|
+
if (normalizedCodeCollabFileDiff.length > 0) {
|
|
133792
|
+
await this.upsertMissingDiffStatsFromCodeCollabFileDiff(options.sessionId, options.sessionDoc, normalizedCodeCollabFileDiff);
|
|
133793
|
+
}
|
|
133794
|
+
}
|
|
133795
|
+
async upsertDiffStatsFromCodeCollabAllChanges(sessionId, sessionDoc, allChangesFileDiff) {
|
|
133796
|
+
try {
|
|
133797
|
+
const meta = await sessionDoc.getMetaState();
|
|
133798
|
+
const targetSessionId = meta?.parentSessionId ?? sessionId;
|
|
133799
|
+
const targetRoomId = getSessionRoomId(targetSessionId);
|
|
133800
|
+
const current2 = await this.deps.workspaceDocument.repo.getDocMeta(targetRoomId);
|
|
133801
|
+
if (isLoroRepoDocDeleted(current2)) {
|
|
133802
|
+
return;
|
|
133803
|
+
}
|
|
133804
|
+
await this.deps.workspaceDocument.repo.upsertDocMeta(targetRoomId, {
|
|
133805
|
+
diffStats: {
|
|
133806
|
+
allChange: sumLineChange(allChangesFileDiff)
|
|
133807
|
+
}
|
|
133808
|
+
});
|
|
133809
|
+
} catch (error2) {
|
|
133810
|
+
this.deps.logger.debug(`[${sessionId}] Failed to persist session diffStats from Code Collab All Changes: ${formatErrorMessage$1(error2)}`);
|
|
133811
|
+
}
|
|
133562
133812
|
}
|
|
133563
133813
|
async isFileMissingAtGitBase(session, options) {
|
|
133564
133814
|
if (!options.baseCommitHash) {
|
|
@@ -133750,7 +134000,8 @@ $mem | ConvertTo-Json -Compress
|
|
|
133750
134000
|
await this.setUserTurnStatus(sessionDoc, userTurnId, "processing");
|
|
133751
134001
|
await this.upsertSessionMeta(sessionId, {
|
|
133752
134002
|
latestUserMsgId: userTurnId,
|
|
133753
|
-
processingUserMsgId: userTurnId
|
|
134003
|
+
processingUserMsgId: userTurnId,
|
|
134004
|
+
lastMissingHistoryUserMsgId: void 0
|
|
133754
134005
|
});
|
|
133755
134006
|
}
|
|
133756
134007
|
async clearDispatchProcessing(sessionId) {
|
|
@@ -133814,7 +134065,8 @@ $mem | ConvertTo-Json -Compress
|
|
|
133814
134065
|
await this.upsertSessionMeta(sessionId, {
|
|
133815
134066
|
latestUserMsgId: this.resolveLatestUserMsgIdForTerminalTurn(existingMeta, userTurnId),
|
|
133816
134067
|
lastHandledUserMsgId: userTurnId,
|
|
133817
|
-
processingUserMsgId: void 0
|
|
134068
|
+
processingUserMsgId: void 0,
|
|
134069
|
+
lastMissingHistoryUserMsgId: void 0
|
|
133818
134070
|
});
|
|
133819
134071
|
}
|
|
133820
134072
|
async markTurnFailed(sessionId, sessionDoc, userTurnId) {
|
|
@@ -133823,7 +134075,8 @@ $mem | ConvertTo-Json -Compress
|
|
|
133823
134075
|
await this.upsertSessionMeta(sessionId, {
|
|
133824
134076
|
latestUserMsgId: this.resolveLatestUserMsgIdForTerminalTurn(existingMeta, userTurnId),
|
|
133825
134077
|
lastHandledUserMsgId: userTurnId,
|
|
133826
|
-
processingUserMsgId: void 0
|
|
134078
|
+
processingUserMsgId: void 0,
|
|
134079
|
+
lastMissingHistoryUserMsgId: void 0
|
|
133827
134080
|
});
|
|
133828
134081
|
}
|
|
133829
134082
|
resolveGitHubProjectBranch(meta, preferredBranch) {
|
|
@@ -135099,6 +135352,9 @@ $mem | ConvertTo-Json -Compress
|
|
|
135099
135352
|
if (meta.lastGoalCommand?.id && meta.lastGoalCommand.id !== this.goalCommandSeenId.get(meta.id)) {
|
|
135100
135353
|
return true;
|
|
135101
135354
|
}
|
|
135355
|
+
if (meta.lastMissingHistoryUserMsgId && !meta.latestUserMsgId) {
|
|
135356
|
+
return false;
|
|
135357
|
+
}
|
|
135102
135358
|
if (!meta.lastHandledUserMsgId) {
|
|
135103
135359
|
return true;
|
|
135104
135360
|
}
|
|
@@ -135126,7 +135382,7 @@ $mem | ConvertTo-Json -Compress
|
|
|
135126
135382
|
const nextUserTurn = await this.findOrAwaitDispatchableTurn(sessionId, sessionDoc, meta);
|
|
135127
135383
|
if (!nextUserTurn) {
|
|
135128
135384
|
if (this.hasPendingUserTurnSignal(meta)) {
|
|
135129
|
-
await this.markMissingUserTurnRecovery(sessionId, meta);
|
|
135385
|
+
await this.markMissingUserTurnRecovery(sessionId, sessionDoc, meta);
|
|
135130
135386
|
} else {
|
|
135131
135387
|
await this.markMessageQueueSignalChecked(sessionDoc, meta);
|
|
135132
135388
|
}
|
|
@@ -135258,7 +135514,8 @@ $mem | ConvertTo-Json -Compress
|
|
|
135258
135514
|
await this.deps.workspaceDocument.repo.upsertDocMeta?.(getSessionRoomId(sessionId), {
|
|
135259
135515
|
latestUserMsgId: userTurnId,
|
|
135260
135516
|
lastHandledUserMsgId: userTurnId,
|
|
135261
|
-
processingUserMsgId: void 0
|
|
135517
|
+
processingUserMsgId: void 0,
|
|
135518
|
+
lastMissingHistoryUserMsgId: void 0
|
|
135262
135519
|
});
|
|
135263
135520
|
await sessionDoc.setStatus(SessionStatusFactory.idle());
|
|
135264
135521
|
await this.deps.recordChatFailure?.(sessionDoc, "machine_access_denied", message);
|
|
@@ -135579,7 +135836,7 @@ $mem | ConvertTo-Json -Compress
|
|
|
135579
135836
|
}
|
|
135580
135837
|
});
|
|
135581
135838
|
}
|
|
135582
|
-
async markMissingUserTurnRecovery(sessionId, previousMeta) {
|
|
135839
|
+
async markMissingUserTurnRecovery(sessionId, sessionDoc, previousMeta) {
|
|
135583
135840
|
const roomId = getSessionRoomId(sessionId);
|
|
135584
135841
|
let meta = previousMeta;
|
|
135585
135842
|
try {
|
|
@@ -135596,13 +135853,20 @@ $mem | ConvertTo-Json -Compress
|
|
|
135596
135853
|
const pendingUserMsgId = meta.processingUserMsgId ?? meta.latestUserMsgId ?? meta.lastHandledUserMsgId;
|
|
135597
135854
|
const recoveryPatch = {
|
|
135598
135855
|
status: SessionStatusFactory.idle(),
|
|
135856
|
+
latestUserMsgId: void 0,
|
|
135599
135857
|
processingUserMsgId: void 0
|
|
135600
135858
|
};
|
|
135601
135859
|
if (pendingUserMsgId) {
|
|
135602
|
-
recoveryPatch.
|
|
135603
|
-
recoveryPatch.latestUserMsgId = pendingUserMsgId;
|
|
135860
|
+
recoveryPatch.lastMissingHistoryUserMsgId = pendingUserMsgId;
|
|
135604
135861
|
}
|
|
135605
135862
|
await this.deps.workspaceDocument.repo.upsertDocMeta?.(roomId, recoveryPatch);
|
|
135863
|
+
if (this.deps.recordChatFailure) {
|
|
135864
|
+
try {
|
|
135865
|
+
await this.deps.recordChatFailure(sessionDoc, "message_delivery_failed", "The user message could not be delivered because its history payload did not sync to this machine. Please resend it after sync recovers.");
|
|
135866
|
+
} catch (error2) {
|
|
135867
|
+
this.deps.logger.debug(`[${sessionId}] Failed to record missing-history delivery failure: ${formatErrorMessage$1(error2)}`);
|
|
135868
|
+
}
|
|
135869
|
+
}
|
|
135606
135870
|
const watched = this.watchedSessions.get(sessionId);
|
|
135607
135871
|
watched?.unsubscribe();
|
|
135608
135872
|
this.watchedSessions.delete(sessionId);
|
|
@@ -135729,7 +135993,8 @@ $mem | ConvertTo-Json -Compress
|
|
|
135729
135993
|
"CLOSED",
|
|
135730
135994
|
"MERGED"
|
|
135731
135995
|
]),
|
|
135732
|
-
headRefName: string$1()
|
|
135996
|
+
headRefName: string$1(),
|
|
135997
|
+
baseRefName: string$1()
|
|
135733
135998
|
});
|
|
135734
135999
|
const GhPrListSchema = array$2(GhPrListItemSchema);
|
|
135735
136000
|
async function detectPullRequestForBranch(options) {
|
|
@@ -135746,7 +136011,7 @@ $mem | ConvertTo-Json -Compress
|
|
|
135746
136011
|
"--head",
|
|
135747
136012
|
branchName,
|
|
135748
136013
|
"--json",
|
|
135749
|
-
"number,url,state,headRefName",
|
|
136014
|
+
"number,url,state,headRefName,baseRefName",
|
|
135750
136015
|
"--limit",
|
|
135751
136016
|
"5"
|
|
135752
136017
|
], workdir, false);
|
|
@@ -135772,6 +136037,7 @@ $mem | ConvertTo-Json -Compress
|
|
|
135772
136037
|
prNumber: pr.number,
|
|
135773
136038
|
prUrl: pr.url,
|
|
135774
136039
|
branch: branchName,
|
|
136040
|
+
baseBranch: pr.baseRefName,
|
|
135775
136041
|
status
|
|
135776
136042
|
};
|
|
135777
136043
|
} catch (error2) {
|
|
@@ -135838,8 +136104,7 @@ $mem | ConvertTo-Json -Compress
|
|
|
135838
136104
|
allChange: {
|
|
135839
136105
|
add: 0,
|
|
135840
136106
|
del: 0
|
|
135841
|
-
}
|
|
135842
|
-
files: []
|
|
136107
|
+
}
|
|
135843
136108
|
};
|
|
135844
136109
|
try {
|
|
135845
136110
|
const preferredBaseBranch = resolveBaseBranchPreference({
|
|
@@ -135889,11 +136154,7 @@ $mem | ConvertTo-Json -Compress
|
|
|
135889
136154
|
const { sessionId, session, sessionDoc, project, branchName } = ctx;
|
|
135890
136155
|
const githubRepo = resolveProjectGitHubRepo(project);
|
|
135891
136156
|
if (!githubRepo) {
|
|
135892
|
-
return;
|
|
135893
|
-
}
|
|
135894
|
-
const workspace = await this.resolveWorkspaceSessionContext(sessionId, sessionDoc);
|
|
135895
|
-
if (workspace.pullRequests.some((pr) => pr.status === "open")) {
|
|
135896
|
-
return;
|
|
136157
|
+
return null;
|
|
135897
136158
|
}
|
|
135898
136159
|
const workdir = session.getWorkdir();
|
|
135899
136160
|
const detected = await detectPullRequestForBranch({
|
|
@@ -135903,8 +136164,15 @@ $mem | ConvertTo-Json -Compress
|
|
|
135903
136164
|
branchName: branchName ?? void 0,
|
|
135904
136165
|
logger: this.deps.logger
|
|
135905
136166
|
});
|
|
135906
|
-
if (!detected
|
|
135907
|
-
return;
|
|
136167
|
+
if (!detected) {
|
|
136168
|
+
return null;
|
|
136169
|
+
}
|
|
136170
|
+
const workspace = await this.resolveWorkspaceSessionContext(sessionId, sessionDoc);
|
|
136171
|
+
if (workspace.pullRequests.some((pr) => pr.status === "open")) {
|
|
136172
|
+
return detected;
|
|
136173
|
+
}
|
|
136174
|
+
if (!this.deps.authBaseUrl) {
|
|
136175
|
+
return detected;
|
|
135908
136176
|
}
|
|
135909
136177
|
try {
|
|
135910
136178
|
const actionUrl = new URL("/api/action", this.deps.authBaseUrl).toString();
|
|
@@ -135931,12 +136199,12 @@ $mem | ConvertTo-Json -Compress
|
|
|
135931
136199
|
if (!res.ok) {
|
|
135932
136200
|
const text = await res.text().catch(() => "");
|
|
135933
136201
|
this.deps.logger.debug(`[${sessionId}] PR association backend call failed (${res.status}): ${text || "no body"}`);
|
|
135934
|
-
return;
|
|
136202
|
+
return detected;
|
|
135935
136203
|
}
|
|
135936
136204
|
this.deps.logger.debug(`[${sessionId}] Associated PR #${detected.prNumber} with session`);
|
|
135937
136205
|
} catch (error2) {
|
|
135938
136206
|
this.deps.logger.debug(`[${sessionId}] PR association backend call failed: ${formatErrorMessage$1(error2)}`);
|
|
135939
|
-
return;
|
|
136207
|
+
return detected;
|
|
135940
136208
|
}
|
|
135941
136209
|
const reportedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
135942
136210
|
try {
|
|
@@ -135951,6 +136219,7 @@ $mem | ConvertTo-Json -Compress
|
|
|
135951
136219
|
} catch (error2) {
|
|
135952
136220
|
this.deps.logger.debug(`[${sessionId}] Failed to write PR to local doc: ${formatErrorMessage$1(error2)}`);
|
|
135953
136221
|
}
|
|
136222
|
+
return detected;
|
|
135954
136223
|
}
|
|
135955
136224
|
async autoCommitAndPushForPR(ctx) {
|
|
135956
136225
|
const { sessionId, session, sessionDoc, project } = ctx;
|
|
@@ -135969,6 +136238,7 @@ $mem | ConvertTo-Json -Compress
|
|
|
135969
136238
|
if (workspace.pullRequests.length === 0) {
|
|
135970
136239
|
return;
|
|
135971
136240
|
}
|
|
136241
|
+
const preferredBaseBranch = ctx.preferredBaseBranch ?? project?.branch;
|
|
135972
136242
|
const workdir = session.getWorkdir();
|
|
135973
136243
|
const runGit = (args2) => session.exec("git", args2, workdir, false);
|
|
135974
136244
|
for (let attempt = 0; attempt < 2; attempt++) {
|
|
@@ -136006,7 +136276,7 @@ $mem | ConvertTo-Json -Compress
|
|
|
136006
136276
|
turnId: result.turnId,
|
|
136007
136277
|
baseCommitHash: result.baseCommitHash ?? void 0,
|
|
136008
136278
|
turnStartWorkingTreeDiff: result.turnStartWorkingTreeDiff,
|
|
136009
|
-
preferredBaseBranch
|
|
136279
|
+
preferredBaseBranch
|
|
136010
136280
|
});
|
|
136011
136281
|
} catch (error2) {
|
|
136012
136282
|
if (shouldStop("commit prompt failure")) {
|
|
@@ -136051,7 +136321,7 @@ $mem | ConvertTo-Json -Compress
|
|
|
136051
136321
|
turnId: result.turnId,
|
|
136052
136322
|
baseCommitHash: result.baseCommitHash ?? void 0,
|
|
136053
136323
|
turnStartWorkingTreeDiff: result.turnStartWorkingTreeDiff,
|
|
136054
|
-
preferredBaseBranch
|
|
136324
|
+
preferredBaseBranch
|
|
136055
136325
|
});
|
|
136056
136326
|
} catch (error2) {
|
|
136057
136327
|
if (shouldStop("push prompt failure")) {
|
|
@@ -141278,7 +141548,6 @@ $mem | ConvertTo-Json -Compress
|
|
|
141278
141548
|
return parseFileId(key2).fileId;
|
|
141279
141549
|
}
|
|
141280
141550
|
function normalizeCurrentChangeValue(value) {
|
|
141281
|
-
if (value === true) return true;
|
|
141282
141551
|
if (!value || typeof value !== "object" || Array.isArray(value)) return void 0;
|
|
141283
141552
|
const record2 = value;
|
|
141284
141553
|
const a = parseOptionalLineCount(record2.a);
|
|
@@ -141308,7 +141577,7 @@ $mem | ConvertTo-Json -Compress
|
|
|
141308
141577
|
n: true
|
|
141309
141578
|
} : {}
|
|
141310
141579
|
};
|
|
141311
|
-
return Object.keys(normalized).length === 0 ?
|
|
141580
|
+
return Object.keys(normalized).length === 0 ? void 0 : normalized;
|
|
141312
141581
|
}
|
|
141313
141582
|
function parseOptionalOpId(value) {
|
|
141314
141583
|
if (typeof value !== "string" || !/^\d+:\d+$/u.test(value)) return void 0;
|
|
@@ -142402,7 +142671,8 @@ $mem | ConvertTo-Json -Compress
|
|
|
142402
142671
|
"diff",
|
|
142403
142672
|
"--numstat",
|
|
142404
142673
|
"--no-renames",
|
|
142405
|
-
stats.mergeBase
|
|
142674
|
+
stats.mergeBase,
|
|
142675
|
+
"HEAD"
|
|
142406
142676
|
]));
|
|
142407
142677
|
const tracked = await Promise.all(trackedFileDiffs.map(async (fileDiff) => {
|
|
142408
142678
|
const baseText = await readGitTextAtMergeBase(runGit, stats.mergeBase, fileDiff.filePath);
|
|
@@ -142447,17 +142717,7 @@ $mem | ConvertTo-Json -Compress
|
|
|
142447
142717
|
}
|
|
142448
142718
|
};
|
|
142449
142719
|
}));
|
|
142450
|
-
|
|
142451
|
-
const untracked = (await listUntrackedFiles(runGit)).filter((filePath) => !trackedPaths.has(filePath)).map((filePath) => ({
|
|
142452
|
-
path: filePath,
|
|
142453
|
-
base: {
|
|
142454
|
-
status: "missing"
|
|
142455
|
-
}
|
|
142456
|
-
}));
|
|
142457
|
-
return [
|
|
142458
|
-
...tracked,
|
|
142459
|
-
...untracked
|
|
142460
|
-
];
|
|
142720
|
+
return tracked;
|
|
142461
142721
|
}
|
|
142462
142722
|
class TurnFileChangeTracker {
|
|
142463
142723
|
#base = /* @__PURE__ */ new Map();
|
|
@@ -143607,7 +143867,7 @@ $mem | ConvertTo-Json -Compress
|
|
|
143607
143867
|
await m.__tla;
|
|
143608
143868
|
return m;
|
|
143609
143869
|
}),
|
|
143610
|
-
import("./chunks/index-
|
|
143870
|
+
import("./chunks/index-Dr2JkTB2.js").then(async (m) => {
|
|
143611
143871
|
await m.__tla;
|
|
143612
143872
|
return m;
|
|
143613
143873
|
})
|
|
@@ -143634,6 +143894,7 @@ $mem | ConvertTo-Json -Compress
|
|
|
143634
143894
|
host: input2.host
|
|
143635
143895
|
}),
|
|
143636
143896
|
computeHostTurnChanges: async (input2) => await codeCollab.computeHostTurnChanges(input2),
|
|
143897
|
+
computeHostTurnFileDiff: async (input2) => await codeCollab.computeHostTurnFileDiff(input2),
|
|
143637
143898
|
publishHostCurrentChanges: async (input2) => await codeCollab.publishHostCurrentChanges(input2)
|
|
143638
143899
|
};
|
|
143639
143900
|
}
|
|
@@ -144376,16 +144637,41 @@ parentPort.on('message', (message) => {
|
|
|
144376
144637
|
lastActivityAtMs = /* @__PURE__ */ new Map();
|
|
144377
144638
|
idleTimers = /* @__PURE__ */ new Map();
|
|
144378
144639
|
pendingWorkCounts = /* @__PURE__ */ new Map();
|
|
144640
|
+
pendingWorkWaiters = /* @__PURE__ */ new Map();
|
|
144379
144641
|
hostStreamsTokenCache = /* @__PURE__ */ new Map();
|
|
144380
144642
|
hostStreamsTokenInFlight = /* @__PURE__ */ new Map();
|
|
144381
144643
|
bootstrapSecretCache = /* @__PURE__ */ new Map();
|
|
144382
144644
|
disabledLogged = false;
|
|
144645
|
+
hostSessionAliases = /* @__PURE__ */ new Map();
|
|
144646
|
+
publishCurrentChangesTails = /* @__PURE__ */ new Map();
|
|
144383
144647
|
codeCollabTurnTrackers = /* @__PURE__ */ new Map();
|
|
144384
144648
|
activeCodeCollabTurnTrackers = /* @__PURE__ */ new Map();
|
|
144385
144649
|
turnHistoryLineStatsWorkerPool;
|
|
144386
144650
|
initialTextSnapshotWorkerPool;
|
|
144387
144651
|
textUpdateWorkerPool;
|
|
144388
144652
|
textFrontierCheckoutWorkerPool;
|
|
144653
|
+
resolveHostSessionId(sessionId) {
|
|
144654
|
+
return this.hostSessionAliases.get(sessionId) ?? sessionId;
|
|
144655
|
+
}
|
|
144656
|
+
registerHostSessionAlias(sessionId, hostSessionId) {
|
|
144657
|
+
if (hostSessionId === void 0 || hostSessionId === sessionId) {
|
|
144658
|
+
return this.resolveHostSessionId(sessionId);
|
|
144659
|
+
}
|
|
144660
|
+
if (this.hostSessionAliases.get(sessionId) !== hostSessionId) {
|
|
144661
|
+
this.hostSessionAliases.set(sessionId, hostSessionId);
|
|
144662
|
+
this.hostStates.delete(sessionId);
|
|
144663
|
+
}
|
|
144664
|
+
return hostSessionId;
|
|
144665
|
+
}
|
|
144666
|
+
sessionIdsOnHost(hostSessionId) {
|
|
144667
|
+
const ids2 = [
|
|
144668
|
+
hostSessionId
|
|
144669
|
+
];
|
|
144670
|
+
for (const [sessionId, host] of this.hostSessionAliases) {
|
|
144671
|
+
if (host === hostSessionId) ids2.push(sessionId);
|
|
144672
|
+
}
|
|
144673
|
+
return ids2;
|
|
144674
|
+
}
|
|
144389
144675
|
recordAgentFileWrite(sessionId, filePath, oldContent, newContent) {
|
|
144390
144676
|
if (!this.config.cliConfig.enabled) return;
|
|
144391
144677
|
const normalizedFilePath = this.normalizeSessionWritePath(sessionId, filePath);
|
|
@@ -144468,10 +144754,11 @@ parentPort.on('message', (message) => {
|
|
|
144468
144754
|
}
|
|
144469
144755
|
}
|
|
144470
144756
|
sessionTracker(sessionId) {
|
|
144471
|
-
|
|
144757
|
+
const hostSessionId = this.resolveHostSessionId(sessionId);
|
|
144758
|
+
let tracker = this.codeCollabTurnTrackers.get(hostSessionId);
|
|
144472
144759
|
if (tracker === void 0) {
|
|
144473
144760
|
tracker = new TurnFileChangeTracker();
|
|
144474
|
-
this.codeCollabTurnTrackers.set(
|
|
144761
|
+
this.codeCollabTurnTrackers.set(hostSessionId, tracker);
|
|
144475
144762
|
}
|
|
144476
144763
|
return tracker;
|
|
144477
144764
|
}
|
|
@@ -144521,10 +144808,15 @@ parentPort.on('message', (message) => {
|
|
|
144521
144808
|
if (!record2 || record2.type !== "file_changed") return;
|
|
144522
144809
|
const filePath = normalizeWatchedTurnPath(record2.path);
|
|
144523
144810
|
if (filePath === void 0) return;
|
|
144524
|
-
const
|
|
144525
|
-
|
|
144526
|
-
const
|
|
144527
|
-
|
|
144811
|
+
const hostSessionId = this.resolveHostSessionId(sessionId);
|
|
144812
|
+
let oldText;
|
|
144813
|
+
for (const candidateSessionId of this.sessionIdsOnHost(hostSessionId)) {
|
|
144814
|
+
const activeTurn = this.activeCodeCollabTurnTrackers.get(candidateSessionId);
|
|
144815
|
+
if (activeTurn === void 0) continue;
|
|
144816
|
+
const bases = this.turnSnapshotTextBases.get(turnSnapshotKey(candidateSessionId, activeTurn.turnId));
|
|
144817
|
+
oldText = bases?.get(filePath);
|
|
144818
|
+
if (oldText !== void 0) break;
|
|
144819
|
+
}
|
|
144528
144820
|
if (oldText === void 0) return;
|
|
144529
144821
|
const normalized = this.normalizeSessionWritePath(sessionId, filePath);
|
|
144530
144822
|
if (normalized === void 0) return;
|
|
@@ -144543,6 +144835,15 @@ parentPort.on('message', (message) => {
|
|
|
144543
144835
|
reason: this.config.cliConfig.reason
|
|
144544
144836
|
};
|
|
144545
144837
|
}
|
|
144838
|
+
if (input2.hostSessionId !== void 0 && input2.hostSessionId !== input2.sessionId) {
|
|
144839
|
+
this.registerHostSessionAlias(input2.sessionId, input2.hostSessionId);
|
|
144840
|
+
this.logCodeCollabDebug(`[${input2.sessionId}] Code Collab host start aliased to parent host=${input2.hostSessionId}`);
|
|
144841
|
+
const { hostSessionId, sessionId: _childSessionId, ...rest } = input2;
|
|
144842
|
+
return await this.startForSession({
|
|
144843
|
+
...rest,
|
|
144844
|
+
sessionId: hostSessionId
|
|
144845
|
+
});
|
|
144846
|
+
}
|
|
144546
144847
|
const existing = this.activeHosts.get(input2.sessionId);
|
|
144547
144848
|
if (existing) {
|
|
144548
144849
|
this.touchActivity(input2.sessionId);
|
|
@@ -144568,6 +144869,22 @@ parentPort.on('message', (message) => {
|
|
|
144568
144869
|
return await start2;
|
|
144569
144870
|
}
|
|
144570
144871
|
stopSession(sessionId, reason = "session stopped") {
|
|
144872
|
+
const aliasedHostSessionId = this.hostSessionAliases.get(sessionId);
|
|
144873
|
+
if (aliasedHostSessionId !== void 0 && aliasedHostSessionId !== sessionId) {
|
|
144874
|
+
this.hostSessionAliases.delete(sessionId);
|
|
144875
|
+
this.activeCodeCollabTurnTrackers.delete(sessionId);
|
|
144876
|
+
this.clearTurnSnapshotsForSession(sessionId);
|
|
144877
|
+
this.hostStates.delete(sessionId);
|
|
144878
|
+
this.logCodeCollabDebug(`[${sessionId}] Code Collab child session detached from host=${aliasedHostSessionId} (${reason})`);
|
|
144879
|
+
return;
|
|
144880
|
+
}
|
|
144881
|
+
for (const childSessionId of this.sessionIdsOnHost(sessionId)) {
|
|
144882
|
+
if (childSessionId === sessionId) continue;
|
|
144883
|
+
this.hostSessionAliases.delete(childSessionId);
|
|
144884
|
+
this.activeCodeCollabTurnTrackers.delete(childSessionId);
|
|
144885
|
+
this.clearTurnSnapshotsForSession(childSessionId);
|
|
144886
|
+
this.hostStates.delete(childSessionId);
|
|
144887
|
+
}
|
|
144571
144888
|
this.clearIdleTimer(sessionId);
|
|
144572
144889
|
if (this.startInFlight.has(sessionId)) {
|
|
144573
144890
|
this.stopRequestedWhileStarting.set(sessionId, reason);
|
|
@@ -144591,7 +144908,7 @@ parentPort.on('message', (message) => {
|
|
|
144591
144908
|
this.activeCodeCollabTurnTrackers.delete(sessionId);
|
|
144592
144909
|
this.clearTurnSnapshotsForSession(sessionId);
|
|
144593
144910
|
this.lastActivityAtMs.delete(sessionId);
|
|
144594
|
-
this.
|
|
144911
|
+
this.clearPendingWork(sessionId);
|
|
144595
144912
|
this.disposeTurnHistoryLineStatsWorkerPoolIfIdle();
|
|
144596
144913
|
try {
|
|
144597
144914
|
host.running.stop();
|
|
@@ -144636,7 +144953,7 @@ parentPort.on('message', (message) => {
|
|
|
144636
144953
|
];
|
|
144637
144954
|
}
|
|
144638
144955
|
getSessionState(sessionId) {
|
|
144639
|
-
const state2 = this.hostStates.get(sessionId);
|
|
144956
|
+
const state2 = this.hostStates.get(sessionId) ?? this.hostStates.get(this.resolveHostSessionId(sessionId));
|
|
144640
144957
|
if (state2) {
|
|
144641
144958
|
return state2;
|
|
144642
144959
|
}
|
|
@@ -144651,6 +144968,17 @@ parentPort.on('message', (message) => {
|
|
|
144651
144968
|
status: "idle"
|
|
144652
144969
|
};
|
|
144653
144970
|
}
|
|
144971
|
+
async waitForPendingWork(sessionId) {
|
|
144972
|
+
const hostSessionId = this.resolveHostSessionId(sessionId);
|
|
144973
|
+
if ((this.pendingWorkCounts.get(hostSessionId) ?? 0) === 0) {
|
|
144974
|
+
return;
|
|
144975
|
+
}
|
|
144976
|
+
await new Promise((resolve2) => {
|
|
144977
|
+
const waiters = this.pendingWorkWaiters.get(hostSessionId) ?? /* @__PURE__ */ new Set();
|
|
144978
|
+
waiters.add(resolve2);
|
|
144979
|
+
this.pendingWorkWaiters.set(hostSessionId, waiters);
|
|
144980
|
+
});
|
|
144981
|
+
}
|
|
144654
144982
|
prefetchWorkspaceHostStreamsToken() {
|
|
144655
144983
|
const cliConfig = this.config.cliConfig;
|
|
144656
144984
|
if (!cliConfig.enabled) {
|
|
@@ -144677,7 +145005,7 @@ parentPort.on('message', (message) => {
|
|
|
144677
145005
|
this.logDisabledOnce();
|
|
144678
145006
|
throw new Error(`Code Collab host disabled: ${this.config.cliConfig.message}`);
|
|
144679
145007
|
}
|
|
144680
|
-
const host = this.activeHosts.get(input2.sessionId);
|
|
145008
|
+
const host = this.activeHosts.get(this.resolveHostSessionId(input2.sessionId));
|
|
144681
145009
|
if (!host?.running) {
|
|
144682
145010
|
throw new Error("Code Collab host runtime is not online for this session.");
|
|
144683
145011
|
}
|
|
@@ -144714,9 +145042,10 @@ parentPort.on('message', (message) => {
|
|
|
144714
145042
|
reason: this.config.cliConfig.reason
|
|
144715
145043
|
};
|
|
144716
145044
|
}
|
|
144717
|
-
const
|
|
145045
|
+
const hostSessionId = this.registerHostSessionAlias(input2.sessionId, input2.hostSessionId);
|
|
145046
|
+
const host = this.activeHosts.get(hostSessionId);
|
|
144718
145047
|
if (host?.running.runtime === void 0) {
|
|
144719
|
-
this.logCodeCollabDebug(`[${input2.sessionId}] Code Collab turn marker skipped: no active host phase=${input2.phase} turn=${input2.turnId}`);
|
|
145048
|
+
this.logCodeCollabDebug(`[${input2.sessionId}] Code Collab turn marker skipped: no active host host=${hostSessionId} phase=${input2.phase} turn=${input2.turnId}`);
|
|
144720
145049
|
return {
|
|
144721
145050
|
status: "no-host"
|
|
144722
145051
|
};
|
|
@@ -144726,7 +145055,7 @@ parentPort.on('message', (message) => {
|
|
|
144726
145055
|
const runtime = await (this.config.runtimeLoader ?? loadLodyCodeCollabRuntime)();
|
|
144727
145056
|
const backend = this.createBackend();
|
|
144728
145057
|
const getHostToken = async () => await runPromise(backend.getStreamsToken({
|
|
144729
|
-
sessionId:
|
|
145058
|
+
sessionId: hostSessionId,
|
|
144730
145059
|
requestedRole: "host"
|
|
144731
145060
|
}));
|
|
144732
145061
|
const auth = async () => {
|
|
@@ -144749,6 +145078,7 @@ parentPort.on('message', (message) => {
|
|
|
144749
145078
|
if (computeHostTurnChanges === void 0) {
|
|
144750
145079
|
throw new Error(`[${input2.sessionId}] Code Collab runtime is missing computeHostTurnChanges; turn-history fallback has been removed`);
|
|
144751
145080
|
}
|
|
145081
|
+
const computeHostTurnFileDiff = runtime.computeHostTurnFileDiff;
|
|
144752
145082
|
if (input2.phase === "turn:start") {
|
|
144753
145083
|
const snapshot = await runtime.snapshotHostTurnHistoryFiles({
|
|
144754
145084
|
host: host.running
|
|
@@ -144779,27 +145109,52 @@ parentPort.on('message', (message) => {
|
|
|
144779
145109
|
}
|
|
144780
145110
|
}
|
|
144781
145111
|
const capture2 = await this.buildTurnCapture(input2.phase, input2.turnId, input2.sessionId, input2.capture, input2.baseCommitHash, input2.turnStartWorkingTreeDiff);
|
|
145112
|
+
const isTerminalMarker = isTerminalLodyCodeCollabTurnMarkerPhase(input2.phase);
|
|
144782
145113
|
let changedFilesResult;
|
|
145114
|
+
let currentChangesPublishDeferred = false;
|
|
144783
145115
|
try {
|
|
144784
|
-
|
|
144785
|
-
|
|
144786
|
-
|
|
144787
|
-
|
|
144788
|
-
|
|
144789
|
-
|
|
144790
|
-
|
|
144791
|
-
|
|
144792
|
-
|
|
145116
|
+
if (isTerminalMarker && computeHostTurnFileDiff !== void 0) {
|
|
145117
|
+
changedFilesResult = await this.computeTurnFileDiffForSessionHistory({
|
|
145118
|
+
computeHostTurnFileDiff,
|
|
145119
|
+
host: host.running,
|
|
145120
|
+
input: input2,
|
|
145121
|
+
baseFiles,
|
|
145122
|
+
capture: capture2,
|
|
145123
|
+
auth,
|
|
145124
|
+
blobAuth
|
|
145125
|
+
});
|
|
145126
|
+
currentChangesPublishDeferred = true;
|
|
145127
|
+
this.publishCodeCollabCurrentChangesInBackground({
|
|
145128
|
+
runtime,
|
|
145129
|
+
computeHostTurnChanges,
|
|
145130
|
+
host: host.running,
|
|
145131
|
+
input: input2,
|
|
145132
|
+
baseFiles,
|
|
145133
|
+
capture: capture2,
|
|
145134
|
+
auth,
|
|
145135
|
+
blobAuth
|
|
145136
|
+
});
|
|
145137
|
+
} else {
|
|
145138
|
+
changedFilesResult = await this.computeTurnChangesForSessionHistory({
|
|
145139
|
+
computeHostTurnChanges,
|
|
145140
|
+
host: host.running,
|
|
145141
|
+
input: input2,
|
|
145142
|
+
baseFiles,
|
|
145143
|
+
capture: capture2,
|
|
145144
|
+
auth,
|
|
145145
|
+
blobAuth
|
|
145146
|
+
});
|
|
145147
|
+
}
|
|
144793
145148
|
} finally {
|
|
144794
145149
|
if (snapshotKeyToClear !== void 0) {
|
|
144795
145150
|
this.turnSnapshots.delete(snapshotKeyToClear);
|
|
144796
145151
|
this.turnSnapshotTextBases.delete(snapshotKeyToClear);
|
|
144797
145152
|
}
|
|
144798
|
-
if (
|
|
145153
|
+
if (isTerminalMarker) {
|
|
144799
145154
|
this.clearActiveTurnTracker(input2.sessionId, input2.turnId);
|
|
144800
145155
|
}
|
|
144801
145156
|
}
|
|
144802
|
-
if (
|
|
145157
|
+
if (isTerminalMarker) {
|
|
144803
145158
|
if (changedFilesResult.status === "recorded") {
|
|
144804
145159
|
this.config.logger.debug(`[${input2.sessionId}] Code Collab changedFiles recorded turn=${input2.turnId}`);
|
|
144805
145160
|
} else if (changedFilesResult.status === "failed") {
|
|
@@ -144809,21 +145164,24 @@ parentPort.on('message', (message) => {
|
|
|
144809
145164
|
this.logCodeCollabDebug(`[${input2.sessionId}] Code Collab turn marker recorded phase=${input2.phase} turn=${input2.turnId}`);
|
|
144810
145165
|
const turnChangedFiles = changedFilesResult.status === "recorded" ? changedFilesResult.result?.turnChangedFiles : void 0;
|
|
144811
145166
|
const allChangedFiles = changedFilesResult.status === "recorded" ? changedFilesResult.result?.changedFiles : void 0;
|
|
144812
|
-
if (
|
|
144813
|
-
await
|
|
145167
|
+
if (isTerminalMarker && runtime.publishHostCurrentChanges !== void 0 && !currentChangesPublishDeferred) {
|
|
145168
|
+
await this.publishCodeCollabCurrentChanges({
|
|
145169
|
+
sessionId: input2.sessionId,
|
|
145170
|
+
runtime,
|
|
144814
145171
|
host: host.running,
|
|
144815
|
-
|
|
144816
|
-
auth
|
|
144817
|
-
...this.config.fetch === void 0 ? {} : {
|
|
144818
|
-
fetch: this.config.fetch
|
|
144819
|
-
}
|
|
145172
|
+
allChangedFiles,
|
|
145173
|
+
auth
|
|
144820
145174
|
});
|
|
144821
145175
|
}
|
|
144822
145176
|
const fileDiff = turnChangedFiles === void 0 ? void 0 : fileDiffsFromChangedFiles(turnChangedFiles);
|
|
145177
|
+
const allChangesFileDiff = allChangedFiles === void 0 ? void 0 : fileDiffsFromChangedFiles(allChangedFiles);
|
|
144823
145178
|
return {
|
|
144824
145179
|
status: "recorded",
|
|
144825
145180
|
...fileDiff === void 0 ? {} : {
|
|
144826
145181
|
fileDiff
|
|
145182
|
+
},
|
|
145183
|
+
...allChangesFileDiff === void 0 ? {} : {
|
|
145184
|
+
allChangesFileDiff
|
|
144827
145185
|
}
|
|
144828
145186
|
};
|
|
144829
145187
|
} catch (error2) {
|
|
@@ -144878,6 +145236,109 @@ parentPort.on('message', (message) => {
|
|
|
144878
145236
|
};
|
|
144879
145237
|
}
|
|
144880
145238
|
}
|
|
145239
|
+
async computeTurnFileDiffForSessionHistory(input2) {
|
|
145240
|
+
if (!isTerminalLodyCodeCollabTurnMarkerPhase(input2.input.phase)) {
|
|
145241
|
+
return {
|
|
145242
|
+
status: "not_applicable"
|
|
145243
|
+
};
|
|
145244
|
+
}
|
|
145245
|
+
const capturedTurnBases = input2.capture?.capturedTurnBases ?? [];
|
|
145246
|
+
if (capturedTurnBases.length === 0) {
|
|
145247
|
+
return {
|
|
145248
|
+
status: "recorded",
|
|
145249
|
+
result: {
|
|
145250
|
+
turnChangedFiles: /* @__PURE__ */ new Map()
|
|
145251
|
+
}
|
|
145252
|
+
};
|
|
145253
|
+
}
|
|
145254
|
+
try {
|
|
145255
|
+
const result = await input2.computeHostTurnFileDiff({
|
|
145256
|
+
host: input2.host,
|
|
145257
|
+
turnId: input2.input.turnId,
|
|
145258
|
+
...input2.baseFiles === void 0 ? {} : {
|
|
145259
|
+
baseFiles: input2.baseFiles
|
|
145260
|
+
},
|
|
145261
|
+
capturedTurnBases,
|
|
145262
|
+
auth: input2.auth,
|
|
145263
|
+
blobAuth: input2.blobAuth,
|
|
145264
|
+
...this.config.fetch === void 0 ? {} : {
|
|
145265
|
+
fetch: this.config.fetch
|
|
145266
|
+
}
|
|
145267
|
+
});
|
|
145268
|
+
return {
|
|
145269
|
+
status: "recorded",
|
|
145270
|
+
result
|
|
145271
|
+
};
|
|
145272
|
+
} catch (error2) {
|
|
145273
|
+
return {
|
|
145274
|
+
status: "failed",
|
|
145275
|
+
error: formatErrorMessage$1(error2)
|
|
145276
|
+
};
|
|
145277
|
+
}
|
|
145278
|
+
}
|
|
145279
|
+
async publishCodeCollabCurrentChanges(input2) {
|
|
145280
|
+
const publishHostCurrentChanges = input2.runtime.publishHostCurrentChanges;
|
|
145281
|
+
if (publishHostCurrentChanges === void 0) {
|
|
145282
|
+
return;
|
|
145283
|
+
}
|
|
145284
|
+
const hostSessionId = this.resolveHostSessionId(input2.sessionId);
|
|
145285
|
+
const tail2 = this.publishCurrentChangesTails.get(hostSessionId) ?? Promise.resolve();
|
|
145286
|
+
const publish2 = tail2.catch(() => void 0).then(async () => {
|
|
145287
|
+
await publishHostCurrentChanges({
|
|
145288
|
+
host: input2.host,
|
|
145289
|
+
currentChanges: input2.allChangedFiles === void 0 ? {} : currentChangesFromChangedFiles(input2.allChangedFiles),
|
|
145290
|
+
auth: input2.auth,
|
|
145291
|
+
...this.config.fetch === void 0 ? {} : {
|
|
145292
|
+
fetch: this.config.fetch
|
|
145293
|
+
}
|
|
145294
|
+
});
|
|
145295
|
+
});
|
|
145296
|
+
const tracked = publish2.catch(() => void 0).then(() => {
|
|
145297
|
+
if (this.publishCurrentChangesTails.get(hostSessionId) === tracked) {
|
|
145298
|
+
this.publishCurrentChangesTails.delete(hostSessionId);
|
|
145299
|
+
}
|
|
145300
|
+
});
|
|
145301
|
+
this.publishCurrentChangesTails.set(hostSessionId, tracked);
|
|
145302
|
+
await publish2;
|
|
145303
|
+
}
|
|
145304
|
+
publishCodeCollabCurrentChangesInBackground(input2) {
|
|
145305
|
+
if (!isTerminalLodyCodeCollabTurnMarkerPhase(input2.input.phase) || input2.runtime.publishHostCurrentChanges === void 0) {
|
|
145306
|
+
return;
|
|
145307
|
+
}
|
|
145308
|
+
this.beginPendingWork(input2.input.sessionId);
|
|
145309
|
+
const allChangesCapture = input2.capture === void 0 ? void 0 : {
|
|
145310
|
+
capturedBases: input2.capture.capturedBases
|
|
145311
|
+
};
|
|
145312
|
+
void (async () => {
|
|
145313
|
+
try {
|
|
145314
|
+
const changedFilesResult = await this.computeTurnChangesForSessionHistory({
|
|
145315
|
+
computeHostTurnChanges: input2.computeHostTurnChanges,
|
|
145316
|
+
host: input2.host,
|
|
145317
|
+
input: input2.input,
|
|
145318
|
+
baseFiles: input2.baseFiles,
|
|
145319
|
+
capture: allChangesCapture,
|
|
145320
|
+
auth: input2.auth,
|
|
145321
|
+
blobAuth: input2.blobAuth
|
|
145322
|
+
});
|
|
145323
|
+
if (changedFilesResult.status === "failed") {
|
|
145324
|
+
this.config.logger.warn(`[${input2.input.sessionId}] Failed to record Code Collab current changes turn=${input2.input.turnId}: ${changedFilesResult.error ?? "unknown error"}`);
|
|
145325
|
+
return;
|
|
145326
|
+
}
|
|
145327
|
+
const allChangedFiles = changedFilesResult.status === "recorded" ? changedFilesResult.result?.changedFiles : void 0;
|
|
145328
|
+
await this.publishCodeCollabCurrentChanges({
|
|
145329
|
+
sessionId: input2.input.sessionId,
|
|
145330
|
+
runtime: input2.runtime,
|
|
145331
|
+
host: input2.host,
|
|
145332
|
+
allChangedFiles,
|
|
145333
|
+
auth: input2.auth
|
|
145334
|
+
});
|
|
145335
|
+
} catch (error2) {
|
|
145336
|
+
this.config.logger.warn(`[${input2.input.sessionId}] Failed to publish Code Collab current changes turn=${input2.input.turnId}: ${formatErrorMessage$1(error2)}`);
|
|
145337
|
+
} finally {
|
|
145338
|
+
this.endPendingWork(input2.input.sessionId);
|
|
145339
|
+
}
|
|
145340
|
+
})();
|
|
145341
|
+
}
|
|
144881
145342
|
async buildTurnCapture(phase, turnId, sessionId, captureConfig, baseCommitHash, turnStartWorkingTreeDiff) {
|
|
144882
145343
|
if (!isTerminalLodyCodeCollabTurnMarkerPhase(phase)) return void 0;
|
|
144883
145344
|
const mode2 = captureConfig?.mode ?? "acp-tracked";
|
|
@@ -144903,7 +145364,7 @@ parentPort.on('message', (message) => {
|
|
|
144903
145364
|
}
|
|
144904
145365
|
}
|
|
144905
145366
|
} else {
|
|
144906
|
-
const tracker = this.codeCollabTurnTrackers.get(sessionId);
|
|
145367
|
+
const tracker = this.codeCollabTurnTrackers.get(this.resolveHostSessionId(sessionId));
|
|
144907
145368
|
capturedBases = tracker ? tracker.entries().map(([filePath, base]) => ({
|
|
144908
145369
|
path: filePath,
|
|
144909
145370
|
base: capturedBaseContentFromTracker(base)
|
|
@@ -145173,7 +145634,7 @@ parentPort.on('message', (message) => {
|
|
|
145173
145634
|
this.activeHosts.delete(sessionId);
|
|
145174
145635
|
this.clearIdleTimer(sessionId);
|
|
145175
145636
|
this.lastActivityAtMs.delete(sessionId);
|
|
145176
|
-
this.
|
|
145637
|
+
this.clearPendingWork(sessionId);
|
|
145177
145638
|
this.disposeTurnHistoryLineStatsWorkerPoolIfIdle();
|
|
145178
145639
|
this.setSessionState(sessionId, {
|
|
145179
145640
|
status: "stopped",
|
|
@@ -145187,7 +145648,7 @@ parentPort.on('message', (message) => {
|
|
|
145187
145648
|
this.activeHosts.delete(sessionId);
|
|
145188
145649
|
this.clearIdleTimer(sessionId);
|
|
145189
145650
|
this.lastActivityAtMs.delete(sessionId);
|
|
145190
|
-
this.
|
|
145651
|
+
this.clearPendingWork(sessionId);
|
|
145191
145652
|
this.disposeTurnHistoryLineStatsWorkerPoolIfIdle();
|
|
145192
145653
|
this.setSessionState(sessionId, {
|
|
145193
145654
|
status: "degraded",
|
|
@@ -145199,24 +145660,43 @@ parentPort.on('message', (message) => {
|
|
|
145199
145660
|
});
|
|
145200
145661
|
}
|
|
145201
145662
|
beginPendingWork(sessionId) {
|
|
145202
|
-
|
|
145203
|
-
this.
|
|
145663
|
+
const hostSessionId = this.resolveHostSessionId(sessionId);
|
|
145664
|
+
this.pendingWorkCounts.set(hostSessionId, (this.pendingWorkCounts.get(hostSessionId) ?? 0) + 1);
|
|
145665
|
+
this.touchActivity(hostSessionId);
|
|
145204
145666
|
}
|
|
145205
145667
|
endPendingWork(sessionId) {
|
|
145206
|
-
const
|
|
145668
|
+
const hostSessionId = this.resolveHostSessionId(sessionId);
|
|
145669
|
+
const next2 = Math.max(0, (this.pendingWorkCounts.get(hostSessionId) ?? 0) - 1);
|
|
145207
145670
|
if (next2 === 0) {
|
|
145208
|
-
this.pendingWorkCounts.delete(
|
|
145671
|
+
this.pendingWorkCounts.delete(hostSessionId);
|
|
145672
|
+
this.resolvePendingWorkWaiters(hostSessionId);
|
|
145209
145673
|
} else {
|
|
145210
|
-
this.pendingWorkCounts.set(
|
|
145674
|
+
this.pendingWorkCounts.set(hostSessionId, next2);
|
|
145675
|
+
}
|
|
145676
|
+
this.touchActivity(hostSessionId);
|
|
145677
|
+
}
|
|
145678
|
+
clearPendingWork(sessionId) {
|
|
145679
|
+
const hostSessionId = this.resolveHostSessionId(sessionId);
|
|
145680
|
+
this.pendingWorkCounts.delete(hostSessionId);
|
|
145681
|
+
this.resolvePendingWorkWaiters(hostSessionId);
|
|
145682
|
+
}
|
|
145683
|
+
resolvePendingWorkWaiters(sessionId) {
|
|
145684
|
+
const waiters = this.pendingWorkWaiters.get(sessionId);
|
|
145685
|
+
if (waiters === void 0) {
|
|
145686
|
+
return;
|
|
145687
|
+
}
|
|
145688
|
+
this.pendingWorkWaiters.delete(sessionId);
|
|
145689
|
+
for (const resolve2 of waiters) {
|
|
145690
|
+
resolve2();
|
|
145211
145691
|
}
|
|
145212
|
-
this.touchActivity(sessionId);
|
|
145213
145692
|
}
|
|
145214
145693
|
touchActivity(sessionId, now2 = Date.now()) {
|
|
145215
|
-
|
|
145694
|
+
const hostSessionId = this.resolveHostSessionId(sessionId);
|
|
145695
|
+
if (!this.activeHosts.has(hostSessionId)) {
|
|
145216
145696
|
return;
|
|
145217
145697
|
}
|
|
145218
|
-
this.lastActivityAtMs.set(
|
|
145219
|
-
this.scheduleIdleCheck(
|
|
145698
|
+
this.lastActivityAtMs.set(hostSessionId, now2);
|
|
145699
|
+
this.scheduleIdleCheck(hostSessionId, now2);
|
|
145220
145700
|
}
|
|
145221
145701
|
scheduleIdleCheck(sessionId, now2 = Date.now()) {
|
|
145222
145702
|
this.clearIdleTimer(sessionId);
|
|
@@ -145865,22 +146345,28 @@ parentPort.on('message', (message) => {
|
|
|
145865
146345
|
function currentChangesFromChangedFiles(changedFiles) {
|
|
145866
146346
|
const projected = projectChangedFiles(changedFiles);
|
|
145867
146347
|
if (projected.length === 0) return {};
|
|
145868
|
-
|
|
146348
|
+
const entries = [];
|
|
146349
|
+
for (const { record: record2, filePath } of projected) {
|
|
146350
|
+
const change = currentChangeFromChangedFileRecord(record2);
|
|
146351
|
+
if (change === void 0) continue;
|
|
145869
146352
|
const currentPath = record2.current.path;
|
|
145870
146353
|
const basePath = record2.base.path;
|
|
145871
146354
|
const path2 = currentPath ?? basePath ?? filePath;
|
|
145872
146355
|
const key2 = record2.current.state === "present" ? record2.fileId : `path:${path2}`;
|
|
145873
|
-
|
|
146356
|
+
entries.push([
|
|
145874
146357
|
key2,
|
|
145875
|
-
|
|
145876
|
-
];
|
|
145877
|
-
}
|
|
146358
|
+
change
|
|
146359
|
+
]);
|
|
146360
|
+
}
|
|
146361
|
+
if (entries.length === 0) return {};
|
|
146362
|
+
return Object.fromEntries(entries.sort(([left2], [right2]) => left2.localeCompare(right2)));
|
|
145878
146363
|
}
|
|
145879
146364
|
function fileDiffsFromChangedFiles(changedFiles) {
|
|
145880
146365
|
const projected = projectChangedFiles(changedFiles);
|
|
145881
146366
|
if (projected.length === 0) return void 0;
|
|
145882
|
-
|
|
146367
|
+
const fileDiffs = projected.flatMap(({ record: record2, filePath, add: add2, del }) => {
|
|
145883
146368
|
const cc = codeCollabFileDiffCheckpointFromRecord(record2);
|
|
146369
|
+
if (cc === void 0 && currentChangeFromChangedFileRecord(record2) === void 0) return [];
|
|
145884
146370
|
return {
|
|
145885
146371
|
filePath,
|
|
145886
146372
|
add: add2,
|
|
@@ -145890,6 +146376,7 @@ parentPort.on('message', (message) => {
|
|
|
145890
146376
|
}
|
|
145891
146377
|
};
|
|
145892
146378
|
});
|
|
146379
|
+
return fileDiffs.length === 0 ? void 0 : fileDiffs;
|
|
145893
146380
|
}
|
|
145894
146381
|
function projectChangedFiles(changedFiles) {
|
|
145895
146382
|
const statsByFileId = new Map(projectTurnHistoryFileDiffStats(changedFiles).map((diffStat) => [
|
|
@@ -145925,15 +146412,15 @@ parentPort.on('message', (message) => {
|
|
|
145925
146412
|
} : {}
|
|
145926
146413
|
};
|
|
145927
146414
|
if (record2.lineStats?.kind !== "counted") {
|
|
145928
|
-
const
|
|
146415
|
+
const value2 = {
|
|
145929
146416
|
...record2.current.state === "deleted" ? {
|
|
145930
146417
|
r: true
|
|
145931
146418
|
} : {},
|
|
145932
146419
|
...checkpoint
|
|
145933
146420
|
};
|
|
145934
|
-
return Object.keys(
|
|
146421
|
+
return Object.keys(value2).length === 0 ? void 0 : value2;
|
|
145935
146422
|
}
|
|
145936
|
-
|
|
146423
|
+
const value = {
|
|
145937
146424
|
...record2.lineStats.add === 0 ? {} : {
|
|
145938
146425
|
a: record2.lineStats.add
|
|
145939
146426
|
},
|
|
@@ -145945,6 +146432,7 @@ parentPort.on('message', (message) => {
|
|
|
145945
146432
|
} : {},
|
|
145946
146433
|
...checkpoint
|
|
145947
146434
|
};
|
|
146435
|
+
return Object.keys(value).length === 0 ? void 0 : value;
|
|
145948
146436
|
}
|
|
145949
146437
|
function changedFileRecords(changedFiles) {
|
|
145950
146438
|
if (Array.isArray(changedFiles)) {
|
|
@@ -146089,7 +146577,7 @@ parentPort.on('message', (message) => {
|
|
|
146089
146577
|
const DEFAULT_LOCAL_PROJECT_BROWSE_DIR_LIMIT = 500;
|
|
146090
146578
|
const HARD_LOCAL_PROJECT_BROWSE_DIR_LIMIT = 5e3;
|
|
146091
146579
|
const DEFAULT_LOCAL_PROJECT_READ_MAX_BYTES = 64 * 1024;
|
|
146092
|
-
const HARD_LOCAL_PROJECT_READ_MAX_BYTES = 1024 * 1024;
|
|
146580
|
+
const HARD_LOCAL_PROJECT_READ_MAX_BYTES = 5 * 1024 * 1024;
|
|
146093
146581
|
const GIT_COMMAND_MAX_BUFFER_BYTES = 64 * 1024 * 1024;
|
|
146094
146582
|
const LOCAL_PROJECT_GIT_COMMAND_TIMEOUT_MS = 5e3;
|
|
146095
146583
|
const LOCAL_PROJECT_WALK_YIELD_EVERY_ENTRIES = 1e3;
|
|
@@ -146152,7 +146640,7 @@ parentPort.on('message', (message) => {
|
|
|
146152
146640
|
}
|
|
146153
146641
|
return absolutePath;
|
|
146154
146642
|
}
|
|
146155
|
-
function readLocalFileAtRoot(rootPath, relativePath, maxBytes) {
|
|
146643
|
+
function readLocalFileAtRoot(rootPath, relativePath, maxBytes, allowBinary = false) {
|
|
146156
146644
|
const requestedRelativePath = normalizeProjectRelativePath(relativePath.trim());
|
|
146157
146645
|
const safePath = resolveSafeProjectFilePath(rootPath, requestedRelativePath);
|
|
146158
146646
|
if (!safePath) return null;
|
|
@@ -146189,8 +146677,17 @@ parentPort.on('message', (message) => {
|
|
|
146189
146677
|
const bytesRead = fs$3.readSync(fd, buffer2, 0, maxBytes + 1, 0);
|
|
146190
146678
|
const truncated = bytesRead > maxBytes;
|
|
146191
146679
|
const safeBytes = truncated ? maxBytes : bytesRead;
|
|
146680
|
+
const resolvedRelativePath = toProjectRelativePath(rootRealPath, targetRealPath);
|
|
146681
|
+
if (allowBinary && isBinaryImagePath(resolvedRelativePath)) {
|
|
146682
|
+
return {
|
|
146683
|
+
path: resolvedRelativePath,
|
|
146684
|
+
content: buffer2.subarray(0, safeBytes).toString("base64"),
|
|
146685
|
+
truncated,
|
|
146686
|
+
encoding: "base64"
|
|
146687
|
+
};
|
|
146688
|
+
}
|
|
146192
146689
|
return {
|
|
146193
|
-
path:
|
|
146690
|
+
path: resolvedRelativePath,
|
|
146194
146691
|
content: buffer2.subarray(0, safeBytes).toString("utf8"),
|
|
146195
146692
|
truncated
|
|
146196
146693
|
};
|
|
@@ -146740,7 +147237,7 @@ parentPort.on('message', (message) => {
|
|
|
146740
147237
|
}
|
|
146741
147238
|
readProjectFile(rootPath, relativePath, options) {
|
|
146742
147239
|
const maxBytes = clampInteger(options?.maxBytes, 1, HARD_LOCAL_PROJECT_READ_MAX_BYTES, DEFAULT_LOCAL_PROJECT_READ_MAX_BYTES);
|
|
146743
|
-
return readLocalFileAtRoot(rootPath, relativePath, maxBytes);
|
|
147240
|
+
return readLocalFileAtRoot(rootPath, relativePath, maxBytes, true);
|
|
146744
147241
|
}
|
|
146745
147242
|
async checkoutProjectBranch(rootPath, branchName) {
|
|
146746
147243
|
try {
|
|
@@ -150001,6 +150498,7 @@ ${escapeHtmlScriptContent(VISUAL_ANNOTATION_INSPECTOR_BROWSER_SCRIPT)}
|
|
|
150001
150498
|
this.cliVersion = config2.cliVersion;
|
|
150002
150499
|
this.machineId = config2.machineId;
|
|
150003
150500
|
this.supportRegistryAgentTypes = config2.supportRegistryAgentTypes ?? [];
|
|
150501
|
+
this.closeSessionTerminals = config2.closeSessionTerminals;
|
|
150004
150502
|
this.onFatalAuthFailure = config2.onFatalAuthFailure;
|
|
150005
150503
|
this.notificationService = createNotificationService(this.token, this.logger);
|
|
150006
150504
|
this.usageTrackingService = createUsageTrackingService(this.token, this.logger);
|
|
@@ -150056,9 +150554,12 @@ ${escapeHtmlScriptContent(VISUAL_ANNOTATION_INSPECTOR_BROWSER_SCRIPT)}
|
|
|
150056
150554
|
touchSession: (sessionId) => this.touchSession(sessionId),
|
|
150057
150555
|
startMachineSessionHeartbeat: (sessionId) => this.startMachineSessionHeartbeat(sessionId),
|
|
150058
150556
|
stopMachineSessionHeartbeat: (sessionId) => this.stopMachineSessionHeartbeat(sessionId),
|
|
150059
|
-
startCodeCollabHost: async ({ sessionId, workspaceRoot, project }) => {
|
|
150557
|
+
startCodeCollabHost: async ({ sessionId, hostSessionId, workspaceRoot, project }) => {
|
|
150060
150558
|
const result = await this.codeCollabHostManager.startForSession({
|
|
150061
150559
|
sessionId,
|
|
150560
|
+
...hostSessionId === void 0 ? {} : {
|
|
150561
|
+
hostSessionId
|
|
150562
|
+
},
|
|
150062
150563
|
workspaceRoot,
|
|
150063
150564
|
project
|
|
150064
150565
|
});
|
|
@@ -150079,18 +150580,34 @@ ${escapeHtmlScriptContent(VISUAL_ANNOTATION_INSPECTOR_BROWSER_SCRIPT)}
|
|
|
150079
150580
|
}
|
|
150080
150581
|
},
|
|
150081
150582
|
recordCodeCollabTurnMarker: async ({ sessionId, turnId, phase, project, baseCommitHash, turnStartWorkingTreeDiff }) => {
|
|
150583
|
+
const hostSessionId = await this.resolveCodeCollabHostSessionId(sessionId);
|
|
150082
150584
|
const result = await this.codeCollabHostManager.recordTurnMarker({
|
|
150083
150585
|
sessionId,
|
|
150586
|
+
...hostSessionId === void 0 ? {} : {
|
|
150587
|
+
hostSessionId
|
|
150588
|
+
},
|
|
150084
150589
|
turnId,
|
|
150085
150590
|
phase,
|
|
150086
150591
|
baseCommitHash,
|
|
150087
150592
|
turnStartWorkingTreeDiff,
|
|
150088
150593
|
capture: await this.resolveCodeCollabCaptureConfig(sessionId, project)
|
|
150089
150594
|
});
|
|
150090
|
-
|
|
150091
|
-
|
|
150092
|
-
|
|
150093
|
-
|
|
150595
|
+
if (result.status !== "recorded") {
|
|
150596
|
+
return void 0;
|
|
150597
|
+
}
|
|
150598
|
+
const fileDiff = result.fileDiff;
|
|
150599
|
+
const allChangesFileDiff = result.allChangesFileDiff;
|
|
150600
|
+
if ((!fileDiff || fileDiff.length === 0) && allChangesFileDiff === void 0) {
|
|
150601
|
+
return void 0;
|
|
150602
|
+
}
|
|
150603
|
+
return {
|
|
150604
|
+
...fileDiff && fileDiff.length > 0 ? {
|
|
150605
|
+
fileDiff
|
|
150606
|
+
} : {},
|
|
150607
|
+
...allChangesFileDiff === void 0 ? {} : {
|
|
150608
|
+
allChangesFileDiff
|
|
150609
|
+
}
|
|
150610
|
+
};
|
|
150094
150611
|
},
|
|
150095
150612
|
beginACPReplaySuppression: (sessionId) => this.beginACPReplaySuppression(sessionId),
|
|
150096
150613
|
endACPReplaySuppression: (sessionId) => this.endACPReplaySuppression(sessionId),
|
|
@@ -150289,6 +150806,7 @@ ${escapeHtmlScriptContent(VISUAL_ANNOTATION_INSPECTOR_BROWSER_SCRIPT)}
|
|
|
150289
150806
|
machineName;
|
|
150290
150807
|
cliVersion;
|
|
150291
150808
|
supportRegistryAgentTypes;
|
|
150809
|
+
closeSessionTerminals;
|
|
150292
150810
|
onFatalAuthFailure;
|
|
150293
150811
|
store = new SessionTransientStore();
|
|
150294
150812
|
titleGenerationInFlight = /* @__PURE__ */ new Set();
|
|
@@ -150304,10 +150822,6 @@ ${escapeHtmlScriptContent(VISUAL_ANNOTATION_INSPECTOR_BROWSER_SCRIPT)}
|
|
|
150304
150822
|
static CODEX_PROPOSED_PLAN_UPDATE_BATCH_WINDOW_MS = 100;
|
|
150305
150823
|
static CONTEXT_WINDOW_USAGE_THROTTLE_MS = 400;
|
|
150306
150824
|
permissionRequestStartTimes = /* @__PURE__ */ new Map();
|
|
150307
|
-
machineHeartbeatTimer = null;
|
|
150308
|
-
machineHeartbeatInFlightStartedAt = null;
|
|
150309
|
-
machineHeartbeatSeq = 0;
|
|
150310
|
-
static MACHINE_HEARTBEAT_INTERVAL_MS = 2e4;
|
|
150311
150825
|
static MACHINE_ACCESS_REGISTRATION_CACHE_TTL_MS = 20 * 6e4;
|
|
150312
150826
|
machineAccessRegistrationInFlight = null;
|
|
150313
150827
|
machineAccessRegistrationExpiresAtMs = 0;
|
|
@@ -150342,39 +150856,6 @@ ${escapeHtmlScriptContent(VISUAL_ANNOTATION_INSPECTOR_BROWSER_SCRIPT)}
|
|
|
150342
150856
|
touchSession(sessionId) {
|
|
150343
150857
|
this.store.get(sessionId).lastActivityMs = Date.now();
|
|
150344
150858
|
}
|
|
150345
|
-
startMachineHeartbeat() {
|
|
150346
|
-
this.stopMachineHeartbeat();
|
|
150347
|
-
this.logger.debug(`Machine heartbeat started (${Math.round(MessageHandler.MACHINE_HEARTBEAT_INTERVAL_MS / 1e3)}s interval)`);
|
|
150348
|
-
this.sendMachineHeartbeatWithDiagnostics("initial");
|
|
150349
|
-
this.machineHeartbeatTimer = setInterval(() => {
|
|
150350
|
-
this.sendMachineHeartbeatWithDiagnostics("periodic");
|
|
150351
|
-
}, MessageHandler.MACHINE_HEARTBEAT_INTERVAL_MS);
|
|
150352
|
-
this.machineHeartbeatTimer.unref?.();
|
|
150353
|
-
}
|
|
150354
|
-
sendMachineHeartbeatWithDiagnostics(reason) {
|
|
150355
|
-
const now2 = Date.now();
|
|
150356
|
-
if (this.machineHeartbeatInFlightStartedAt !== null) {
|
|
150357
|
-
this.logger.warn(`Machine heartbeat skipped (reason=${reason}); previous heartbeat still pending for ${now2 - this.machineHeartbeatInFlightStartedAt}ms`);
|
|
150358
|
-
return;
|
|
150359
|
-
}
|
|
150360
|
-
const seq2 = ++this.machineHeartbeatSeq;
|
|
150361
|
-
this.machineHeartbeatInFlightStartedAt = now2;
|
|
150362
|
-
this.logger.debug(`Machine heartbeat tick started (reason=${reason} seq=${seq2})`);
|
|
150363
|
-
void withSlowOperationWarning(this.workspaceDocument.sendMachineHeartbeat(), this.logger, `workspaceDocument.sendMachineHeartbeat(reason=${reason}, seq=${seq2})`, this.machineId).then(() => {
|
|
150364
|
-
this.logger.debug(`Machine heartbeat sent (reason=${reason} seq=${seq2} duration=${Date.now() - now2}ms)`);
|
|
150365
|
-
}).catch((error2) => {
|
|
150366
|
-
this.logger.debug(`Machine heartbeat failed (reason=${reason} seq=${seq2} duration=${Date.now() - now2}ms): ${formatErrorMessage$1(error2)}`);
|
|
150367
|
-
}).finally(() => {
|
|
150368
|
-
this.machineHeartbeatInFlightStartedAt = null;
|
|
150369
|
-
});
|
|
150370
|
-
}
|
|
150371
|
-
stopMachineHeartbeat() {
|
|
150372
|
-
if (this.machineHeartbeatTimer) {
|
|
150373
|
-
clearInterval(this.machineHeartbeatTimer);
|
|
150374
|
-
this.machineHeartbeatTimer = null;
|
|
150375
|
-
}
|
|
150376
|
-
this.machineHeartbeatInFlightStartedAt = null;
|
|
150377
|
-
}
|
|
150378
150859
|
preferredBaseBranch = (process.env.LODY_BASE_BRANCH || "main").trim() || "main";
|
|
150379
150860
|
resolveGitHubProjectBranch(meta, preferredBranch) {
|
|
150380
150861
|
return resolveBaseBranchPreference({
|
|
@@ -150384,6 +150865,21 @@ ${escapeHtmlScriptContent(VISUAL_ANNOTATION_INSPECTOR_BROWSER_SCRIPT)}
|
|
|
150384
150865
|
fallbackBranch: this.preferredBaseBranch
|
|
150385
150866
|
});
|
|
150386
150867
|
}
|
|
150868
|
+
async resolveCodeCollabHostSessionId(sessionId) {
|
|
150869
|
+
const activeParent = this.sessionManager.getSession(sessionId)?.getParentSessionId();
|
|
150870
|
+
if (activeParent !== void 0 && activeParent !== sessionId) {
|
|
150871
|
+
return activeParent;
|
|
150872
|
+
}
|
|
150873
|
+
try {
|
|
150874
|
+
const sessionDoc = await this.workspaceDocument.getOrCreateSessionDoc(sessionId);
|
|
150875
|
+
const meta = await sessionDoc.getMetaState();
|
|
150876
|
+
const parentSessionId = meta?.parentSessionId;
|
|
150877
|
+
return parentSessionId !== void 0 && parentSessionId !== sessionId ? parentSessionId : void 0;
|
|
150878
|
+
} catch (error2) {
|
|
150879
|
+
this.logger.debug(`[${sessionId}] Code Collab host session resolve failed: ${formatErrorMessage$1(error2)}`);
|
|
150880
|
+
return void 0;
|
|
150881
|
+
}
|
|
150882
|
+
}
|
|
150387
150883
|
async resolveCodeCollabCaptureConfig(sessionId, projectHint) {
|
|
150388
150884
|
try {
|
|
150389
150885
|
const sessionDoc = await this.workspaceDocument.getOrCreateSessionDoc(sessionId);
|
|
@@ -151374,7 +151870,7 @@ ${escapeHtmlScriptContent(VISUAL_ANNOTATION_INSPECTOR_BROWSER_SCRIPT)}
|
|
|
151374
151870
|
if (!meta) continue;
|
|
151375
151871
|
if (meta.machineId !== this.machineId) continue;
|
|
151376
151872
|
if (meta.status?.type === "idle") continue;
|
|
151377
|
-
if (
|
|
151873
|
+
if (this.store.has(sessionId) && this.store.get(sessionId).heartbeat !== null) continue;
|
|
151378
151874
|
await sessionDoc.setStatus(SessionStatusFactory.idle());
|
|
151379
151875
|
resetCount += 1;
|
|
151380
151876
|
} catch (error2) {
|
|
@@ -151534,6 +152030,7 @@ ${escapeHtmlScriptContent(VISUAL_ANNOTATION_INSPECTOR_BROWSER_SCRIPT)}
|
|
|
151534
152030
|
this.logger.debug(`[${sessionId}] Archiving session resources`);
|
|
151535
152031
|
this.stopMachineSessionHeartbeat(sessionId);
|
|
151536
152032
|
this.codeCollabHostManager.stopSession(sessionId, "session archived");
|
|
152033
|
+
this.closeSessionTerminals?.(sessionId);
|
|
151537
152034
|
this.logger.debug(`[${sessionId}] Heartbeat stopped`);
|
|
151538
152035
|
await this.finalizeACPState(sessionId);
|
|
151539
152036
|
this.logger.debug(`[${sessionId}] ACP state finalized`);
|
|
@@ -151655,6 +152152,7 @@ ${escapeHtmlScriptContent(VISUAL_ANNOTATION_INSPECTOR_BROWSER_SCRIPT)}
|
|
|
151655
152152
|
this.logger.debug(`[${parentSessionId}] Terminating ${childSessionIds.length} active child session(s) before workspace cleanup`);
|
|
151656
152153
|
await Promise.all(childSessionIds.map(async (childSessionId) => {
|
|
151657
152154
|
this.stopMachineSessionHeartbeat(childSessionId);
|
|
152155
|
+
this.closeSessionTerminals?.(childSessionId);
|
|
151658
152156
|
await this.finalizeACPState(childSessionId);
|
|
151659
152157
|
await this.previewService.closeSessionPreviewForCleanup(childSessionId, reason);
|
|
151660
152158
|
await this.sessionManager.terminateSession(childSessionId, true);
|
|
@@ -151797,6 +152295,7 @@ ${escapeHtmlScriptContent(VISUAL_ANNOTATION_INSPECTOR_BROWSER_SCRIPT)}
|
|
|
151797
152295
|
await this.terminateActiveChildSessions(sessionId, "Parent session deleted");
|
|
151798
152296
|
this.stopMachineSessionHeartbeat(sessionId);
|
|
151799
152297
|
this.codeCollabHostManager.stopSession(sessionId, "session deleted");
|
|
152298
|
+
this.closeSessionTerminals?.(sessionId);
|
|
151800
152299
|
await this.finalizeACPState(sessionId);
|
|
151801
152300
|
await this.previewService.closeSessionPreviewForCleanup(sessionId, "Session deleted");
|
|
151802
152301
|
this.logger.debug(`[${sessionId}] Preview tunnel closed for deletion`);
|
|
@@ -152260,7 +152759,6 @@ ${escapeHtmlScriptContent(VISUAL_ANNOTATION_INSPECTOR_BROWSER_SCRIPT)}
|
|
|
152260
152759
|
raceLimits: machineMeta?.raceLimits ?? {}
|
|
152261
152760
|
});
|
|
152262
152761
|
await this.registerMachineAccess();
|
|
152263
|
-
this.startMachineHeartbeat();
|
|
152264
152762
|
this.logger.debug(`Machine registered with name: ${registeredName}`);
|
|
152265
152763
|
} catch (error2) {
|
|
152266
152764
|
this.logger.error(`Failed to register machine: ${formatErrorMessage$1(error2)}`);
|
|
@@ -152310,12 +152808,16 @@ ${escapeHtmlScriptContent(VISUAL_ANNOTATION_INSPECTOR_BROWSER_SCRIPT)}
|
|
|
152310
152808
|
}
|
|
152311
152809
|
return null;
|
|
152312
152810
|
};
|
|
152811
|
+
const hostSessionIdField = (parentSessionId) => parentSessionId === void 0 || parentSessionId === sessionId ? {} : {
|
|
152812
|
+
hostSessionId: parentSessionId
|
|
152813
|
+
};
|
|
152313
152814
|
const activeSession = this.sessionManager.getSession(sessionId);
|
|
152314
152815
|
if (activeSession) {
|
|
152315
152816
|
return {
|
|
152316
152817
|
ok: true,
|
|
152317
152818
|
workspaceRoot: activeSession.getHostWorkdir() ?? activeSession.getWorkdir(),
|
|
152318
|
-
source: "active-session"
|
|
152819
|
+
source: "active-session",
|
|
152820
|
+
...hostSessionIdField(activeSession.getParentSessionId())
|
|
152319
152821
|
};
|
|
152320
152822
|
}
|
|
152321
152823
|
const pendingSession = this.sessionManager.getPendingSession(sessionId);
|
|
@@ -152336,7 +152838,8 @@ ${escapeHtmlScriptContent(VISUAL_ANNOTATION_INSPECTOR_BROWSER_SCRIPT)}
|
|
|
152336
152838
|
return {
|
|
152337
152839
|
ok: true,
|
|
152338
152840
|
workspaceRoot: session.getHostWorkdir() ?? session.getWorkdir(),
|
|
152339
|
-
source: "pending-session"
|
|
152841
|
+
source: "pending-session",
|
|
152842
|
+
...hostSessionIdField(session.getParentSessionId())
|
|
152340
152843
|
};
|
|
152341
152844
|
}
|
|
152342
152845
|
const metaRecord = await this.workspaceDocument.repo.getDocMeta(getSessionRoomId(sessionId));
|
|
@@ -152356,6 +152859,7 @@ ${escapeHtmlScriptContent(VISUAL_ANNOTATION_INSPECTOR_BROWSER_SCRIPT)}
|
|
|
152356
152859
|
};
|
|
152357
152860
|
}
|
|
152358
152861
|
const project = meta.project;
|
|
152862
|
+
const hostSessionId = meta.parentSessionId ?? sessionId;
|
|
152359
152863
|
if (project?.kind === "local") {
|
|
152360
152864
|
const workspaceRoot = await resolveWorkspaceLocalProjectRootPath(this.workspaceDocument.repo, this.machineId, project.localProjectId);
|
|
152361
152865
|
if (!workspaceRoot) {
|
|
@@ -152368,17 +152872,18 @@ ${escapeHtmlScriptContent(VISUAL_ANNOTATION_INSPECTOR_BROWSER_SCRIPT)}
|
|
|
152368
152872
|
return {
|
|
152369
152873
|
ok: true,
|
|
152370
152874
|
workspaceRoot,
|
|
152371
|
-
source: `local-project:${project.localProjectId}
|
|
152875
|
+
source: `local-project:${project.localProjectId}`,
|
|
152876
|
+
...hostSessionIdField(hostSessionId)
|
|
152372
152877
|
};
|
|
152373
152878
|
}
|
|
152374
|
-
const hostSessionId = meta.parentSessionId ?? sessionId;
|
|
152375
152879
|
if (meta.parentSessionId) {
|
|
152376
152880
|
const parentSession = this.sessionManager.getSession(meta.parentSessionId);
|
|
152377
152881
|
if (parentSession) {
|
|
152378
152882
|
return {
|
|
152379
152883
|
ok: true,
|
|
152380
152884
|
workspaceRoot: parentSession.getHostWorkdir() ?? parentSession.getWorkdir(),
|
|
152381
|
-
source: `active-parent-session:${meta.parentSessionId}
|
|
152885
|
+
source: `active-parent-session:${meta.parentSessionId}`,
|
|
152886
|
+
...hostSessionIdField(hostSessionId)
|
|
152382
152887
|
};
|
|
152383
152888
|
}
|
|
152384
152889
|
const pendingParentSession = this.sessionManager.getPendingSession(meta.parentSessionId);
|
|
@@ -152399,7 +152904,8 @@ ${escapeHtmlScriptContent(VISUAL_ANNOTATION_INSPECTOR_BROWSER_SCRIPT)}
|
|
|
152399
152904
|
return {
|
|
152400
152905
|
ok: true,
|
|
152401
152906
|
workspaceRoot: session.getHostWorkdir() ?? session.getWorkdir(),
|
|
152402
|
-
source: `pending-parent-session:${meta.parentSessionId}
|
|
152907
|
+
source: `pending-parent-session:${meta.parentSessionId}`,
|
|
152908
|
+
...hostSessionIdField(hostSessionId)
|
|
152403
152909
|
};
|
|
152404
152910
|
}
|
|
152405
152911
|
}
|
|
@@ -152414,7 +152920,8 @@ ${escapeHtmlScriptContent(VISUAL_ANNOTATION_INSPECTOR_BROWSER_SCRIPT)}
|
|
|
152414
152920
|
return {
|
|
152415
152921
|
ok: true,
|
|
152416
152922
|
workspaceRoot: worktreeManager.getWorktreeHostPath(hostSessionId),
|
|
152417
|
-
source: `github-worktree-existing:${hostSessionId}
|
|
152923
|
+
source: `github-worktree-existing:${hostSessionId}`,
|
|
152924
|
+
...hostSessionIdField(hostSessionId)
|
|
152418
152925
|
};
|
|
152419
152926
|
}
|
|
152420
152927
|
this.logCodeCollabDebug(`[${sessionId}] Code Collab host-start waiting for session workspace hostSessionId=${hostSessionId} repo=${repoFullName}`);
|
|
@@ -152425,13 +152932,17 @@ ${escapeHtmlScriptContent(VISUAL_ANNOTATION_INSPECTOR_BROWSER_SCRIPT)}
|
|
|
152425
152932
|
timeoutMs: CODE_COLLAB_HOST_SESSION_WAIT_TIMEOUT_MS
|
|
152426
152933
|
});
|
|
152427
152934
|
if (waited) {
|
|
152428
|
-
return waited
|
|
152935
|
+
return waited.ok ? {
|
|
152936
|
+
...waited,
|
|
152937
|
+
...hostSessionIdField(hostSessionId)
|
|
152938
|
+
} : waited;
|
|
152429
152939
|
}
|
|
152430
152940
|
if (worktreeManager.hasWorktree(hostSessionId)) {
|
|
152431
152941
|
return {
|
|
152432
152942
|
ok: true,
|
|
152433
152943
|
workspaceRoot: worktreeManager.getWorktreeHostPath(hostSessionId),
|
|
152434
|
-
source: `github-worktree-existing-after-wait:${hostSessionId}
|
|
152944
|
+
source: `github-worktree-existing-after-wait:${hostSessionId}`,
|
|
152945
|
+
...hostSessionIdField(hostSessionId)
|
|
152435
152946
|
};
|
|
152436
152947
|
}
|
|
152437
152948
|
return {
|
|
@@ -152510,7 +153021,10 @@ ${escapeHtmlScriptContent(VISUAL_ANNOTATION_INSPECTOR_BROWSER_SCRIPT)}
|
|
|
152510
153021
|
this.logCodeCollabDebug(`[${sessionId}] Code Collab host-start resolved workspaceRoot=${resolved.workspaceRoot} source=${resolved.source}`);
|
|
152511
153022
|
const result = await this.codeCollabHostManager.startForSession({
|
|
152512
153023
|
sessionId,
|
|
152513
|
-
workspaceRoot: resolved.workspaceRoot
|
|
153024
|
+
workspaceRoot: resolved.workspaceRoot,
|
|
153025
|
+
...resolved.hostSessionId === void 0 ? {} : {
|
|
153026
|
+
hostSessionId: resolved.hostSessionId
|
|
153027
|
+
}
|
|
152514
153028
|
});
|
|
152515
153029
|
this.logCodeCollabDebug(`[${sessionId}] Code Collab host-start result status=${result.status}`);
|
|
152516
153030
|
switch (result.status) {
|
|
@@ -153650,7 +154164,6 @@ ${escapeHtmlScriptContent(VISUAL_ANNOTATION_INSPECTOR_BROWSER_SCRIPT)}
|
|
|
153650
154164
|
}
|
|
153651
154165
|
async cleanup() {
|
|
153652
154166
|
this.logger.debug("Cleaning up message handler resources");
|
|
153653
|
-
this.stopMachineHeartbeat();
|
|
153654
154167
|
this.cancelPendingPermissionRequests();
|
|
153655
154168
|
this.machineRpcServer?.stop();
|
|
153656
154169
|
this.codeCollabHostManager.stopAll("message handler cleanup");
|
|
@@ -153877,10 +154390,14 @@ ${escapeHtmlScriptContent(VISUAL_ANNOTATION_INSPECTOR_BROWSER_SCRIPT)}
|
|
|
153877
154390
|
if (await this.hasActiveGoal(sessionId)) {
|
|
153878
154391
|
return false;
|
|
153879
154392
|
}
|
|
153880
|
-
|
|
153881
|
-
if (meta && isSessionActiveWithHeartbeat(meta.status, meta.lastRunningSeen)) {
|
|
154393
|
+
if (this.store.has(sessionId) && this.store.get(sessionId).heartbeat !== null) {
|
|
153882
154394
|
return false;
|
|
153883
154395
|
}
|
|
154396
|
+
for (const childSessionId of this.sessionManager.getActiveChildSessionIds(sessionId)) {
|
|
154397
|
+
if (!await this.isCodeCollabHostSessionIdle(childSessionId)) {
|
|
154398
|
+
return false;
|
|
154399
|
+
}
|
|
154400
|
+
}
|
|
153884
154401
|
return true;
|
|
153885
154402
|
}
|
|
153886
154403
|
async hasActiveGoal(sessionId) {
|
|
@@ -154532,6 +155049,7 @@ ${escapeHtmlScriptContent(VISUAL_ANNOTATION_INSPECTOR_BROWSER_SCRIPT)}
|
|
|
154532
155049
|
messageProcessor;
|
|
154533
155050
|
gcManager = null;
|
|
154534
155051
|
initialized = false;
|
|
155052
|
+
sessionTerminatedHandlers = /* @__PURE__ */ new Set();
|
|
154535
155053
|
async initialize() {
|
|
154536
155054
|
if (this.initialized) {
|
|
154537
155055
|
return {
|
|
@@ -154542,6 +155060,11 @@ ${escapeHtmlScriptContent(VISUAL_ANNOTATION_INSPECTOR_BROWSER_SCRIPT)}
|
|
|
154542
155060
|
this.options.logger.debug("Initializing machine runtime");
|
|
154543
155061
|
this.sessionManager = this.options.sessionManagerFactory();
|
|
154544
155062
|
await this.sessionManager.initialize();
|
|
155063
|
+
this.sessionManager.on("terminated", (event) => {
|
|
155064
|
+
for (const handler of this.sessionTerminatedHandlers) {
|
|
155065
|
+
handler(event.sessionId);
|
|
155066
|
+
}
|
|
155067
|
+
});
|
|
154545
155068
|
this.options.logger.debug("Session manager initialized");
|
|
154546
155069
|
this.handler = new MessageHandler(this.sessionManager, this.options.workspaceDocument, this.options.logger, this.options.handlerConfig);
|
|
154547
155070
|
this.initializeGCManager();
|
|
@@ -154563,6 +155086,21 @@ ${escapeHtmlScriptContent(VISUAL_ANNOTATION_INSPECTOR_BROWSER_SCRIPT)}
|
|
|
154563
155086
|
getSessionManager() {
|
|
154564
155087
|
return this.sessionManager;
|
|
154565
155088
|
}
|
|
155089
|
+
async resolveSessionWorkdir(sessionId) {
|
|
155090
|
+
const sessionManager = this.requireSessionManager();
|
|
155091
|
+
const pendingSession = sessionManager.getPendingSession(sessionId);
|
|
155092
|
+
if (pendingSession) {
|
|
155093
|
+
const session = await pendingSession;
|
|
155094
|
+
return session.getWorkdir();
|
|
155095
|
+
}
|
|
155096
|
+
return sessionManager.getSession(sessionId)?.getWorkdir() ?? null;
|
|
155097
|
+
}
|
|
155098
|
+
onSessionTerminated(handler) {
|
|
155099
|
+
this.sessionTerminatedHandlers.add(handler);
|
|
155100
|
+
return () => {
|
|
155101
|
+
this.sessionTerminatedHandlers.delete(handler);
|
|
155102
|
+
};
|
|
155103
|
+
}
|
|
154566
155104
|
getActiveSessionCount() {
|
|
154567
155105
|
return this.handler?.getActiveTurnCount() ?? 0;
|
|
154568
155106
|
}
|
|
@@ -161449,7 +161987,7 @@ export PATH=${toSingleQuotedShellString(ghShimBinDir)}:"$PATH"
|
|
|
161449
161987
|
LODY_WORKSPACE_SESSION_ID: workspaceSessionId
|
|
161450
161988
|
};
|
|
161451
161989
|
const withLoginShell = mergeLoginShellEnv(merged, getCachedLoginShellEnvSync());
|
|
161452
|
-
const agentEnv = this.config.agentCliType
|
|
161990
|
+
const agentEnv = shouldScrubClaudeAuthEnv(this.config.agentCliType, this.config.agentType) ? scrubInheritedClaudeAuthEnv(withLoginShell, {
|
|
161453
161991
|
...configEnv,
|
|
161454
161992
|
...extraEnv
|
|
161455
161993
|
}) : withLoginShell;
|
|
@@ -162348,6 +162886,7 @@ export PATH=${toSingleQuotedShellString(ghShimBinDir)}:"$PATH"
|
|
|
162348
162886
|
machineName: this.machineName,
|
|
162349
162887
|
cliVersion: pkg.version,
|
|
162350
162888
|
supportRegistryAgentTypes: this.supportRegistryAgentTypes,
|
|
162889
|
+
closeSessionTerminals: options.closeSessionTerminals,
|
|
162351
162890
|
onFatalAuthFailure: options.onFatalAuthFailure
|
|
162352
162891
|
},
|
|
162353
162892
|
logger: this.logger
|
|
@@ -162444,6 +162983,12 @@ export PATH=${toSingleQuotedShellString(ghShimBinDir)}:"$PATH"
|
|
|
162444
162983
|
getActiveSessionCount() {
|
|
162445
162984
|
return this.runtime.getActiveSessionCount();
|
|
162446
162985
|
}
|
|
162986
|
+
async resolveSessionWorkdir(sessionId) {
|
|
162987
|
+
return await this.runtime.resolveSessionWorkdir(sessionId);
|
|
162988
|
+
}
|
|
162989
|
+
onSessionTerminated(handler) {
|
|
162990
|
+
return this.runtime.onSessionTerminated(handler);
|
|
162991
|
+
}
|
|
162447
162992
|
getConnectedRoomCount() {
|
|
162448
162993
|
return this.documentManager.getConnectedRoomCount();
|
|
162449
162994
|
}
|
|
@@ -163166,6 +163711,679 @@ export PATH=${toSingleQuotedShellString(ghShimBinDir)}:"$PATH"
|
|
|
163166
163711
|
server.close(() => resolve2());
|
|
163167
163712
|
});
|
|
163168
163713
|
}
|
|
163714
|
+
const LOCAL_TERMINAL_SOCKET_BASENAME = "lody-terminal";
|
|
163715
|
+
function getUserSocketSuffix() {
|
|
163716
|
+
if (typeof process.getuid === "function") {
|
|
163717
|
+
return String(process.getuid());
|
|
163718
|
+
}
|
|
163719
|
+
const userInfo2 = os__default$1.userInfo();
|
|
163720
|
+
return crypto$1.createHash("sha256").update(`${userInfo2.uid}:${userInfo2.username}:${os__default$1.homedir()}`).digest("hex").slice(0, 16);
|
|
163721
|
+
}
|
|
163722
|
+
function getLocalTerminalSocketPath() {
|
|
163723
|
+
const userId = getUserSocketSuffix();
|
|
163724
|
+
if (process.platform === "win32") {
|
|
163725
|
+
return `\\\\.\\pipe\\${LOCAL_TERMINAL_SOCKET_BASENAME}-${userId}`;
|
|
163726
|
+
}
|
|
163727
|
+
return path__default$1.join(os__default$1.tmpdir(), `${LOCAL_TERMINAL_SOCKET_BASENAME}-${userId}.sock`);
|
|
163728
|
+
}
|
|
163729
|
+
const MAX_BUFFER_BYTES = 1024 * 1024;
|
|
163730
|
+
let terminalServer = null;
|
|
163731
|
+
let activeSocketPath = null;
|
|
163732
|
+
let terminalServerStart = null;
|
|
163733
|
+
function encodeEvent(event) {
|
|
163734
|
+
return `${JSON.stringify(event)}
|
|
163735
|
+
`;
|
|
163736
|
+
}
|
|
163737
|
+
function send(socket, event) {
|
|
163738
|
+
if (socket.destroyed) return;
|
|
163739
|
+
socket.write(encodeEvent(event));
|
|
163740
|
+
}
|
|
163741
|
+
function getEventTerminalId(event) {
|
|
163742
|
+
return "terminalId" in event && typeof event.terminalId === "string" ? event.terminalId : null;
|
|
163743
|
+
}
|
|
163744
|
+
function createTerminalSocketState() {
|
|
163745
|
+
return {
|
|
163746
|
+
subscribedTerminalIds: /* @__PURE__ */ new Set(),
|
|
163747
|
+
replayingTerminalIds: /* @__PURE__ */ new Set(),
|
|
163748
|
+
replayBuffers: /* @__PURE__ */ new Map()
|
|
163749
|
+
};
|
|
163750
|
+
}
|
|
163751
|
+
function publishTerminalEvent(socket, state2, event) {
|
|
163752
|
+
const terminalId = getEventTerminalId(event);
|
|
163753
|
+
if (!terminalId) {
|
|
163754
|
+
send(socket, event);
|
|
163755
|
+
return;
|
|
163756
|
+
}
|
|
163757
|
+
if (!state2.subscribedTerminalIds.has(terminalId)) {
|
|
163758
|
+
return;
|
|
163759
|
+
}
|
|
163760
|
+
if (state2.replayingTerminalIds.has(terminalId)) {
|
|
163761
|
+
const buffer2 = state2.replayBuffers.get(terminalId) ?? [];
|
|
163762
|
+
buffer2.push(event);
|
|
163763
|
+
state2.replayBuffers.set(terminalId, buffer2);
|
|
163764
|
+
return;
|
|
163765
|
+
}
|
|
163766
|
+
send(socket, event);
|
|
163767
|
+
if (event.type === "exit") {
|
|
163768
|
+
state2.subscribedTerminalIds.delete(terminalId);
|
|
163769
|
+
}
|
|
163770
|
+
}
|
|
163771
|
+
function startTerminalReplay(state2, terminalId) {
|
|
163772
|
+
state2.subscribedTerminalIds.add(terminalId);
|
|
163773
|
+
state2.replayingTerminalIds.add(terminalId);
|
|
163774
|
+
state2.replayBuffers.set(terminalId, []);
|
|
163775
|
+
}
|
|
163776
|
+
function finishTerminalReplay(socket, state2, terminalId) {
|
|
163777
|
+
state2.replayingTerminalIds.delete(terminalId);
|
|
163778
|
+
const bufferedEvents = state2.replayBuffers.get(terminalId) ?? [];
|
|
163779
|
+
state2.replayBuffers.delete(terminalId);
|
|
163780
|
+
for (const event of bufferedEvents) {
|
|
163781
|
+
send(socket, event);
|
|
163782
|
+
if (event.type === "exit") {
|
|
163783
|
+
state2.subscribedTerminalIds.delete(terminalId);
|
|
163784
|
+
}
|
|
163785
|
+
}
|
|
163786
|
+
}
|
|
163787
|
+
function cancelTerminalReplay(state2, terminalId) {
|
|
163788
|
+
state2.replayingTerminalIds.delete(terminalId);
|
|
163789
|
+
state2.replayBuffers.delete(terminalId);
|
|
163790
|
+
state2.subscribedTerminalIds.delete(terminalId);
|
|
163791
|
+
}
|
|
163792
|
+
function classifyTerminalError(error2) {
|
|
163793
|
+
const message = formatErrorMessage$1(error2);
|
|
163794
|
+
if (message.startsWith("session_not_found:")) {
|
|
163795
|
+
return {
|
|
163796
|
+
code: "session_not_found",
|
|
163797
|
+
message
|
|
163798
|
+
};
|
|
163799
|
+
}
|
|
163800
|
+
if (message.startsWith("session_archived:")) {
|
|
163801
|
+
return {
|
|
163802
|
+
code: "session_archived",
|
|
163803
|
+
message
|
|
163804
|
+
};
|
|
163805
|
+
}
|
|
163806
|
+
if (message.startsWith("session_deleted:")) {
|
|
163807
|
+
return {
|
|
163808
|
+
code: "session_deleted",
|
|
163809
|
+
message
|
|
163810
|
+
};
|
|
163811
|
+
}
|
|
163812
|
+
if (message.startsWith("session_machine_mismatch:")) {
|
|
163813
|
+
return {
|
|
163814
|
+
code: "session_machine_mismatch",
|
|
163815
|
+
message
|
|
163816
|
+
};
|
|
163817
|
+
}
|
|
163818
|
+
if (message.startsWith("session_parent_cycle:")) {
|
|
163819
|
+
return {
|
|
163820
|
+
code: "session_parent_cycle",
|
|
163821
|
+
message
|
|
163822
|
+
};
|
|
163823
|
+
}
|
|
163824
|
+
if (message.startsWith("session_ambiguous:")) {
|
|
163825
|
+
return {
|
|
163826
|
+
code: "session_ambiguous",
|
|
163827
|
+
message
|
|
163828
|
+
};
|
|
163829
|
+
}
|
|
163830
|
+
if (message.startsWith("terminal_not_found:")) {
|
|
163831
|
+
return {
|
|
163832
|
+
code: "terminal_not_found",
|
|
163833
|
+
message
|
|
163834
|
+
};
|
|
163835
|
+
}
|
|
163836
|
+
if (message.startsWith("terminal_limit_exceeded:")) {
|
|
163837
|
+
return {
|
|
163838
|
+
code: "terminal_limit_exceeded",
|
|
163839
|
+
message
|
|
163840
|
+
};
|
|
163841
|
+
}
|
|
163842
|
+
if (message.includes("workdir") || message.includes("directory") || message.includes("ENOENT")) {
|
|
163843
|
+
return {
|
|
163844
|
+
code: "workdir_unavailable",
|
|
163845
|
+
message
|
|
163846
|
+
};
|
|
163847
|
+
}
|
|
163848
|
+
return {
|
|
163849
|
+
code: "terminal_error",
|
|
163850
|
+
message
|
|
163851
|
+
};
|
|
163852
|
+
}
|
|
163853
|
+
async function removeStaleUnixSocket(socketPath) {
|
|
163854
|
+
if (process.platform === "win32" || !fs$3.existsSync(socketPath)) {
|
|
163855
|
+
return;
|
|
163856
|
+
}
|
|
163857
|
+
await new Promise((resolve2, reject) => {
|
|
163858
|
+
const socket = net__default.createConnection(socketPath);
|
|
163859
|
+
socket.once("connect", () => {
|
|
163860
|
+
socket.destroy();
|
|
163861
|
+
reject(new Error(`local_terminal_socket_in_use:${socketPath}`));
|
|
163862
|
+
});
|
|
163863
|
+
socket.once("error", (error2) => {
|
|
163864
|
+
socket.destroy();
|
|
163865
|
+
if (error2.code === "ECONNREFUSED" || error2.code === "ENOENT") {
|
|
163866
|
+
fs$3.unlinkSync(socketPath);
|
|
163867
|
+
resolve2();
|
|
163868
|
+
return;
|
|
163869
|
+
}
|
|
163870
|
+
reject(error2);
|
|
163871
|
+
});
|
|
163872
|
+
});
|
|
163873
|
+
}
|
|
163874
|
+
async function handleMessage(config2, socket, state2, message) {
|
|
163875
|
+
try {
|
|
163876
|
+
switch (message.type) {
|
|
163877
|
+
case "list": {
|
|
163878
|
+
send(socket, {
|
|
163879
|
+
type: "terminals",
|
|
163880
|
+
requestId: message.requestId,
|
|
163881
|
+
sessionId: message.sessionId,
|
|
163882
|
+
terminals: config2.terminalPtyService.list(message.sessionId)
|
|
163883
|
+
});
|
|
163884
|
+
return;
|
|
163885
|
+
}
|
|
163886
|
+
case "open": {
|
|
163887
|
+
const result = await config2.terminalPtyService.open(message);
|
|
163888
|
+
send(socket, {
|
|
163889
|
+
type: "opened",
|
|
163890
|
+
requestId: message.requestId,
|
|
163891
|
+
terminalId: result.terminalId,
|
|
163892
|
+
...result.cwd ? {
|
|
163893
|
+
cwd: result.cwd
|
|
163894
|
+
} : {}
|
|
163895
|
+
});
|
|
163896
|
+
return;
|
|
163897
|
+
}
|
|
163898
|
+
case "attach": {
|
|
163899
|
+
startTerminalReplay(state2, message.terminalId);
|
|
163900
|
+
try {
|
|
163901
|
+
const replay = config2.terminalPtyService.attach(message.terminalId, message.cols, message.rows);
|
|
163902
|
+
send(socket, {
|
|
163903
|
+
terminalId: message.terminalId,
|
|
163904
|
+
type: "title",
|
|
163905
|
+
title: replay.title
|
|
163906
|
+
});
|
|
163907
|
+
if (replay.scrollback) {
|
|
163908
|
+
send(socket, {
|
|
163909
|
+
type: "data",
|
|
163910
|
+
terminalId: message.terminalId,
|
|
163911
|
+
data: replay.scrollback,
|
|
163912
|
+
replay: true
|
|
163913
|
+
});
|
|
163914
|
+
}
|
|
163915
|
+
finishTerminalReplay(socket, state2, message.terminalId);
|
|
163916
|
+
} catch (error2) {
|
|
163917
|
+
cancelTerminalReplay(state2, message.terminalId);
|
|
163918
|
+
throw error2;
|
|
163919
|
+
}
|
|
163920
|
+
return;
|
|
163921
|
+
}
|
|
163922
|
+
case "input": {
|
|
163923
|
+
config2.terminalPtyService.input(message.terminalId, message.data);
|
|
163924
|
+
return;
|
|
163925
|
+
}
|
|
163926
|
+
case "resize": {
|
|
163927
|
+
config2.terminalPtyService.resize(message.terminalId, message.cols, message.rows);
|
|
163928
|
+
return;
|
|
163929
|
+
}
|
|
163930
|
+
case "close": {
|
|
163931
|
+
config2.terminalPtyService.close(message.terminalId);
|
|
163932
|
+
return;
|
|
163933
|
+
}
|
|
163934
|
+
case "close_session": {
|
|
163935
|
+
config2.terminalPtyService.closeSession(message.sessionId);
|
|
163936
|
+
return;
|
|
163937
|
+
}
|
|
163938
|
+
default: {
|
|
163939
|
+
throw new Error(`unsupported_terminal_message:${JSON.stringify(message)}`);
|
|
163940
|
+
}
|
|
163941
|
+
}
|
|
163942
|
+
} catch (error2) {
|
|
163943
|
+
const terminalError = classifyTerminalError(error2);
|
|
163944
|
+
send(socket, {
|
|
163945
|
+
type: "error",
|
|
163946
|
+
requestId: message.requestId,
|
|
163947
|
+
..."terminalId" in message ? {
|
|
163948
|
+
terminalId: message.terminalId
|
|
163949
|
+
} : {},
|
|
163950
|
+
code: terminalError.code,
|
|
163951
|
+
message: terminalError.message
|
|
163952
|
+
});
|
|
163953
|
+
}
|
|
163954
|
+
}
|
|
163955
|
+
async function startLocalTerminalServer(config2) {
|
|
163956
|
+
if (terminalServer) {
|
|
163957
|
+
return;
|
|
163958
|
+
}
|
|
163959
|
+
if (terminalServerStart) {
|
|
163960
|
+
return await terminalServerStart;
|
|
163961
|
+
}
|
|
163962
|
+
terminalServerStart = startLocalTerminalServerInner(config2).finally(() => {
|
|
163963
|
+
terminalServerStart = null;
|
|
163964
|
+
});
|
|
163965
|
+
return await terminalServerStart;
|
|
163966
|
+
}
|
|
163967
|
+
async function startLocalTerminalServerInner(config2) {
|
|
163968
|
+
const socketPath = getLocalTerminalSocketPath();
|
|
163969
|
+
await removeStaleUnixSocket(socketPath);
|
|
163970
|
+
const server = net__default.createServer((socket) => {
|
|
163971
|
+
let buffer2 = "";
|
|
163972
|
+
const state2 = createTerminalSocketState();
|
|
163973
|
+
const unsubscribe2 = config2.terminalPtyService.onEvent((event) => {
|
|
163974
|
+
publishTerminalEvent(socket, state2, event);
|
|
163975
|
+
});
|
|
163976
|
+
socket.on("data", (chunk) => {
|
|
163977
|
+
buffer2 += chunk.toString("utf8");
|
|
163978
|
+
if (buffer2.length > MAX_BUFFER_BYTES) {
|
|
163979
|
+
send(socket, {
|
|
163980
|
+
type: "error",
|
|
163981
|
+
code: "payload_too_large",
|
|
163982
|
+
message: "Terminal socket payload exceeded buffer limit"
|
|
163983
|
+
});
|
|
163984
|
+
socket.destroy();
|
|
163985
|
+
return;
|
|
163986
|
+
}
|
|
163987
|
+
let newlineIndex = buffer2.indexOf("\n");
|
|
163988
|
+
while (newlineIndex >= 0) {
|
|
163989
|
+
const line3 = buffer2.slice(0, newlineIndex).trim();
|
|
163990
|
+
buffer2 = buffer2.slice(newlineIndex + 1);
|
|
163991
|
+
if (line3) {
|
|
163992
|
+
let raw2;
|
|
163993
|
+
try {
|
|
163994
|
+
raw2 = JSON.parse(line3);
|
|
163995
|
+
} catch (error2) {
|
|
163996
|
+
send(socket, {
|
|
163997
|
+
type: "error",
|
|
163998
|
+
code: "invalid_json",
|
|
163999
|
+
message: formatErrorMessage$1(error2)
|
|
164000
|
+
});
|
|
164001
|
+
newlineIndex = buffer2.indexOf("\n");
|
|
164002
|
+
continue;
|
|
164003
|
+
}
|
|
164004
|
+
const parsed = TerminalClientMessageSchema.safeParse(raw2);
|
|
164005
|
+
if (!parsed.success) {
|
|
164006
|
+
send(socket, {
|
|
164007
|
+
type: "error",
|
|
164008
|
+
code: "invalid_request",
|
|
164009
|
+
message: parsed.error.message
|
|
164010
|
+
});
|
|
164011
|
+
newlineIndex = buffer2.indexOf("\n");
|
|
164012
|
+
continue;
|
|
164013
|
+
}
|
|
164014
|
+
void handleMessage(config2, socket, state2, parsed.data);
|
|
164015
|
+
}
|
|
164016
|
+
newlineIndex = buffer2.indexOf("\n");
|
|
164017
|
+
}
|
|
164018
|
+
});
|
|
164019
|
+
socket.on("close", unsubscribe2);
|
|
164020
|
+
socket.on("error", (error2) => {
|
|
164021
|
+
config2.logger.debug(`[terminal] socket error: ${error2.message}`);
|
|
164022
|
+
});
|
|
164023
|
+
});
|
|
164024
|
+
await new Promise((resolve2, reject) => {
|
|
164025
|
+
server.once("error", reject);
|
|
164026
|
+
server.listen(socketPath, () => {
|
|
164027
|
+
server.off("error", reject);
|
|
164028
|
+
terminalServer = server;
|
|
164029
|
+
activeSocketPath = socketPath;
|
|
164030
|
+
if (process.platform !== "win32") {
|
|
164031
|
+
fs$3.chmodSync(socketPath, 384);
|
|
164032
|
+
}
|
|
164033
|
+
config2.logger.debug(`[terminal] local terminal socket listening at ${socketPath}`);
|
|
164034
|
+
resolve2();
|
|
164035
|
+
});
|
|
164036
|
+
});
|
|
164037
|
+
server.on("error", (error2) => {
|
|
164038
|
+
config2.logger.warn(`[terminal] local terminal server error: ${error2.message}`);
|
|
164039
|
+
if (terminalServer === server) {
|
|
164040
|
+
terminalServer = null;
|
|
164041
|
+
activeSocketPath = null;
|
|
164042
|
+
}
|
|
164043
|
+
try {
|
|
164044
|
+
server.close();
|
|
164045
|
+
} catch {
|
|
164046
|
+
}
|
|
164047
|
+
if (process.platform !== "win32" && fs$3.existsSync(socketPath)) {
|
|
164048
|
+
fs$3.unlinkSync(socketPath);
|
|
164049
|
+
}
|
|
164050
|
+
});
|
|
164051
|
+
}
|
|
164052
|
+
async function stopLocalTerminalServer() {
|
|
164053
|
+
if (!terminalServer) {
|
|
164054
|
+
return;
|
|
164055
|
+
}
|
|
164056
|
+
const server = terminalServer;
|
|
164057
|
+
const socketPath = activeSocketPath;
|
|
164058
|
+
terminalServer = null;
|
|
164059
|
+
activeSocketPath = null;
|
|
164060
|
+
await new Promise((resolve2) => {
|
|
164061
|
+
server.close(() => resolve2());
|
|
164062
|
+
});
|
|
164063
|
+
if (socketPath && process.platform !== "win32" && fs$3.existsSync(socketPath)) {
|
|
164064
|
+
fs$3.unlinkSync(socketPath);
|
|
164065
|
+
}
|
|
164066
|
+
}
|
|
164067
|
+
const SCROLLBACK_MAX_CHARS = 512 * 1024;
|
|
164068
|
+
const ESC = String.fromCharCode(27);
|
|
164069
|
+
const BEL = String.fromCharCode(7);
|
|
164070
|
+
const OSC_TITLE_REGEX = new RegExp(`${ESC}\\](?:0|2);([^${BEL}${ESC}]*)(?:${BEL}|${ESC}\\\\)`, "g");
|
|
164071
|
+
const TERMINAL_ENV_BLOCKLIST = /* @__PURE__ */ new Set([
|
|
164072
|
+
"LODY_CLI_TOKEN",
|
|
164073
|
+
"LODY_ELECTRON_SESSION_TOKEN",
|
|
164074
|
+
"LODY_GIT_CRED_BROKER_TOKEN",
|
|
164075
|
+
LODY_GIT_CRED_CONTEXT_TOKEN_ENV,
|
|
164076
|
+
LODY_MANAGED_GH_TOKEN_SHA256_ENV
|
|
164077
|
+
]);
|
|
164078
|
+
const require$1 = createRequire$1(import.meta.url);
|
|
164079
|
+
const pty = require$1("node-pty");
|
|
164080
|
+
function basenameForTitle(cwd) {
|
|
164081
|
+
const name2 = path__default$1.basename(cwd);
|
|
164082
|
+
return name2 || cwd;
|
|
164083
|
+
}
|
|
164084
|
+
function resolveShellCommand() {
|
|
164085
|
+
if (process.platform === "win32") {
|
|
164086
|
+
return {
|
|
164087
|
+
file: process.env.ComSpec || "powershell.exe",
|
|
164088
|
+
args: []
|
|
164089
|
+
};
|
|
164090
|
+
}
|
|
164091
|
+
return {
|
|
164092
|
+
file: process.env.SHELL || "/bin/sh",
|
|
164093
|
+
args: [
|
|
164094
|
+
"-l"
|
|
164095
|
+
]
|
|
164096
|
+
};
|
|
164097
|
+
}
|
|
164098
|
+
function buildTerminalEnv(sessionId) {
|
|
164099
|
+
const base = {
|
|
164100
|
+
...process.env,
|
|
164101
|
+
TERM: "xterm-256color",
|
|
164102
|
+
COLORTERM: process.env.COLORTERM ?? "truecolor",
|
|
164103
|
+
FORCE_COLOR: "1",
|
|
164104
|
+
LODY_SESSION_ID: sessionId,
|
|
164105
|
+
LODY_WORKSPACE_SESSION_ID: sessionId
|
|
164106
|
+
};
|
|
164107
|
+
const merged = withDefaultAcpPathEntries(mergeLoginShellEnv(base, getCachedLoginShellEnvSync()));
|
|
164108
|
+
clearManagedGhTokenEnv(merged);
|
|
164109
|
+
for (const key2 of TERMINAL_ENV_BLOCKLIST) {
|
|
164110
|
+
delete merged[key2];
|
|
164111
|
+
}
|
|
164112
|
+
return merged;
|
|
164113
|
+
}
|
|
164114
|
+
function normalizeExitSignal(signal) {
|
|
164115
|
+
if (typeof signal === "undefined") return void 0;
|
|
164116
|
+
return String(signal);
|
|
164117
|
+
}
|
|
164118
|
+
function appendScrollback(current2, data) {
|
|
164119
|
+
const next2 = current2 + data;
|
|
164120
|
+
if (next2.length <= SCROLLBACK_MAX_CHARS) return next2;
|
|
164121
|
+
return next2.slice(next2.length - SCROLLBACK_MAX_CHARS);
|
|
164122
|
+
}
|
|
164123
|
+
function extractLatestTitle(record2, data) {
|
|
164124
|
+
record2.titleParseBuffer = (record2.titleParseBuffer + data).slice(-4096);
|
|
164125
|
+
let latest2 = null;
|
|
164126
|
+
for (const match5 of record2.titleParseBuffer.matchAll(OSC_TITLE_REGEX)) {
|
|
164127
|
+
const title2 = match5[1]?.trim();
|
|
164128
|
+
if (title2) {
|
|
164129
|
+
latest2 = title2;
|
|
164130
|
+
}
|
|
164131
|
+
}
|
|
164132
|
+
return latest2;
|
|
164133
|
+
}
|
|
164134
|
+
class TerminalPtyServiceImpl {
|
|
164135
|
+
logger;
|
|
164136
|
+
resolveSessionWorkdir;
|
|
164137
|
+
records = /* @__PURE__ */ new Map();
|
|
164138
|
+
sessionIndex = /* @__PURE__ */ new Map();
|
|
164139
|
+
pendingSessionOpens = /* @__PURE__ */ new Map();
|
|
164140
|
+
handlers = /* @__PURE__ */ new Set();
|
|
164141
|
+
constructor(options) {
|
|
164142
|
+
this.logger = options.logger;
|
|
164143
|
+
this.resolveSessionWorkdir = options.resolveSessionWorkdir;
|
|
164144
|
+
}
|
|
164145
|
+
list(sessionId) {
|
|
164146
|
+
const ids2 = this.sessionIndex.get(sessionId);
|
|
164147
|
+
if (!ids2) return [];
|
|
164148
|
+
return [
|
|
164149
|
+
...ids2
|
|
164150
|
+
].flatMap((terminalId) => {
|
|
164151
|
+
const record2 = this.records.get(terminalId);
|
|
164152
|
+
if (!record2) return [];
|
|
164153
|
+
return [
|
|
164154
|
+
{
|
|
164155
|
+
terminalId: record2.terminalId,
|
|
164156
|
+
title: record2.title,
|
|
164157
|
+
cwd: record2.cwd
|
|
164158
|
+
}
|
|
164159
|
+
];
|
|
164160
|
+
});
|
|
164161
|
+
}
|
|
164162
|
+
async open(params) {
|
|
164163
|
+
const sessionId = params.sessionId;
|
|
164164
|
+
this.reserveSessionOpen(params.sessionId);
|
|
164165
|
+
try {
|
|
164166
|
+
const cwd = await this.resolveSessionWorkdir(sessionId);
|
|
164167
|
+
const terminalId = randomUUID();
|
|
164168
|
+
const shell = resolveShellCommand();
|
|
164169
|
+
const terminal2 = pty.spawn(shell.file, shell.args, {
|
|
164170
|
+
name: "xterm-256color",
|
|
164171
|
+
cols: params.cols,
|
|
164172
|
+
rows: params.rows,
|
|
164173
|
+
cwd,
|
|
164174
|
+
env: buildTerminalEnv(params.sessionId)
|
|
164175
|
+
});
|
|
164176
|
+
const record2 = {
|
|
164177
|
+
sessionId: params.sessionId,
|
|
164178
|
+
terminalId,
|
|
164179
|
+
cwd,
|
|
164180
|
+
title: basenameForTitle(cwd),
|
|
164181
|
+
pty: terminal2,
|
|
164182
|
+
scrollback: "",
|
|
164183
|
+
titleParseBuffer: ""
|
|
164184
|
+
};
|
|
164185
|
+
this.records.set(terminalId, record2);
|
|
164186
|
+
const sessionTerminals = this.sessionIndex.get(params.sessionId) ?? /* @__PURE__ */ new Set();
|
|
164187
|
+
sessionTerminals.add(terminalId);
|
|
164188
|
+
this.sessionIndex.set(params.sessionId, sessionTerminals);
|
|
164189
|
+
terminal2.onData((data) => {
|
|
164190
|
+
record2.scrollback = appendScrollback(record2.scrollback, data);
|
|
164191
|
+
this.emit({
|
|
164192
|
+
type: "data",
|
|
164193
|
+
terminalId,
|
|
164194
|
+
data
|
|
164195
|
+
});
|
|
164196
|
+
const title2 = extractLatestTitle(record2, data);
|
|
164197
|
+
if (title2 && title2 !== record2.title) {
|
|
164198
|
+
record2.title = title2;
|
|
164199
|
+
this.emit({
|
|
164200
|
+
type: "title",
|
|
164201
|
+
terminalId,
|
|
164202
|
+
title: title2
|
|
164203
|
+
});
|
|
164204
|
+
}
|
|
164205
|
+
});
|
|
164206
|
+
terminal2.onExit(({ exitCode, signal }) => {
|
|
164207
|
+
this.removeRecord(terminalId);
|
|
164208
|
+
this.emit({
|
|
164209
|
+
type: "exit",
|
|
164210
|
+
terminalId,
|
|
164211
|
+
exitCode,
|
|
164212
|
+
...typeof signal === "undefined" ? {} : {
|
|
164213
|
+
signal: normalizeExitSignal(signal)
|
|
164214
|
+
}
|
|
164215
|
+
});
|
|
164216
|
+
});
|
|
164217
|
+
this.emit({
|
|
164218
|
+
type: "title",
|
|
164219
|
+
terminalId,
|
|
164220
|
+
title: record2.title
|
|
164221
|
+
});
|
|
164222
|
+
this.logger.debug(`[terminal] opened terminalId=${terminalId} sessionId=${params.sessionId} cwd=${cwd}`);
|
|
164223
|
+
return {
|
|
164224
|
+
terminalId,
|
|
164225
|
+
cwd
|
|
164226
|
+
};
|
|
164227
|
+
} finally {
|
|
164228
|
+
this.releaseSessionOpen(params.sessionId);
|
|
164229
|
+
}
|
|
164230
|
+
}
|
|
164231
|
+
attach(terminalId, cols, rows) {
|
|
164232
|
+
const record2 = this.requireRecord(terminalId);
|
|
164233
|
+
record2.pty.resize(cols, rows);
|
|
164234
|
+
return {
|
|
164235
|
+
title: record2.title,
|
|
164236
|
+
scrollback: record2.scrollback
|
|
164237
|
+
};
|
|
164238
|
+
}
|
|
164239
|
+
input(terminalId, data) {
|
|
164240
|
+
this.requireRecord(terminalId).pty.write(data);
|
|
164241
|
+
}
|
|
164242
|
+
resize(terminalId, cols, rows) {
|
|
164243
|
+
this.requireRecord(terminalId).pty.resize(cols, rows);
|
|
164244
|
+
}
|
|
164245
|
+
close(terminalId) {
|
|
164246
|
+
const record2 = this.requireRecord(terminalId);
|
|
164247
|
+
record2.pty.kill();
|
|
164248
|
+
}
|
|
164249
|
+
closeSession(sessionId) {
|
|
164250
|
+
const ids2 = [
|
|
164251
|
+
...this.sessionIndex.get(sessionId) ?? []
|
|
164252
|
+
];
|
|
164253
|
+
for (const terminalId of ids2) {
|
|
164254
|
+
this.closeIfPresent(terminalId);
|
|
164255
|
+
}
|
|
164256
|
+
}
|
|
164257
|
+
closeAll() {
|
|
164258
|
+
const ids2 = [
|
|
164259
|
+
...this.records.keys()
|
|
164260
|
+
];
|
|
164261
|
+
for (const terminalId of ids2) {
|
|
164262
|
+
this.closeIfPresent(terminalId);
|
|
164263
|
+
}
|
|
164264
|
+
}
|
|
164265
|
+
onEvent(handler) {
|
|
164266
|
+
this.handlers.add(handler);
|
|
164267
|
+
return () => {
|
|
164268
|
+
this.handlers.delete(handler);
|
|
164269
|
+
};
|
|
164270
|
+
}
|
|
164271
|
+
requireRecord(terminalId) {
|
|
164272
|
+
const record2 = this.records.get(terminalId);
|
|
164273
|
+
if (!record2) {
|
|
164274
|
+
throw new Error(`terminal_not_found:${terminalId}`);
|
|
164275
|
+
}
|
|
164276
|
+
return record2;
|
|
164277
|
+
}
|
|
164278
|
+
closeIfPresent(terminalId) {
|
|
164279
|
+
const record2 = this.records.get(terminalId);
|
|
164280
|
+
if (!record2) return;
|
|
164281
|
+
try {
|
|
164282
|
+
record2.pty.kill();
|
|
164283
|
+
} catch (error2) {
|
|
164284
|
+
this.logger.debug(`[terminal] failed to close terminalId=${terminalId}: ${formatErrorMessage$1(error2)}`);
|
|
164285
|
+
this.removeRecord(terminalId);
|
|
164286
|
+
}
|
|
164287
|
+
}
|
|
164288
|
+
removeRecord(terminalId) {
|
|
164289
|
+
const record2 = this.records.get(terminalId);
|
|
164290
|
+
if (!record2) return;
|
|
164291
|
+
this.records.delete(terminalId);
|
|
164292
|
+
const sessionTerminals = this.sessionIndex.get(record2.sessionId);
|
|
164293
|
+
sessionTerminals?.delete(terminalId);
|
|
164294
|
+
if (sessionTerminals && sessionTerminals.size === 0) {
|
|
164295
|
+
this.sessionIndex.delete(record2.sessionId);
|
|
164296
|
+
}
|
|
164297
|
+
}
|
|
164298
|
+
reserveSessionOpen(sessionId) {
|
|
164299
|
+
const currentCount = (this.sessionIndex.get(sessionId)?.size ?? 0) + (this.pendingSessionOpens.get(sessionId) ?? 0);
|
|
164300
|
+
if (currentCount >= TERMINAL_MAX_PER_SESSION) {
|
|
164301
|
+
throw new Error(`terminal_limit_exceeded:${sessionId}:${TERMINAL_MAX_PER_SESSION}`);
|
|
164302
|
+
}
|
|
164303
|
+
this.pendingSessionOpens.set(sessionId, (this.pendingSessionOpens.get(sessionId) ?? 0) + 1);
|
|
164304
|
+
}
|
|
164305
|
+
releaseSessionOpen(sessionId) {
|
|
164306
|
+
const current2 = this.pendingSessionOpens.get(sessionId) ?? 0;
|
|
164307
|
+
if (current2 <= 1) {
|
|
164308
|
+
this.pendingSessionOpens.delete(sessionId);
|
|
164309
|
+
return;
|
|
164310
|
+
}
|
|
164311
|
+
this.pendingSessionOpens.set(sessionId, current2 - 1);
|
|
164312
|
+
}
|
|
164313
|
+
emit(event) {
|
|
164314
|
+
for (const handler of this.handlers) {
|
|
164315
|
+
handler(event);
|
|
164316
|
+
}
|
|
164317
|
+
}
|
|
164318
|
+
}
|
|
164319
|
+
function makeTerminalPtyService(options) {
|
|
164320
|
+
return new TerminalPtyServiceImpl(options);
|
|
164321
|
+
}
|
|
164322
|
+
function defaultIsDirectory(filePath) {
|
|
164323
|
+
try {
|
|
164324
|
+
return fs$3.statSync(filePath).isDirectory();
|
|
164325
|
+
} catch {
|
|
164326
|
+
return false;
|
|
164327
|
+
}
|
|
164328
|
+
}
|
|
164329
|
+
function requireExistingDirectory(filePath, isDirectory2) {
|
|
164330
|
+
if (!isDirectory2(filePath)) {
|
|
164331
|
+
throw new Error(`workdir_unavailable:path_not_found:${filePath}`);
|
|
164332
|
+
}
|
|
164333
|
+
return filePath;
|
|
164334
|
+
}
|
|
164335
|
+
function resolveDefaultChatWorkdir(sessionId, homeDir, isDirectory2) {
|
|
164336
|
+
const workdir = path__default$1.join(homeDir, ".lody", "chats", sessionId);
|
|
164337
|
+
fs$3.mkdirSync(workdir, {
|
|
164338
|
+
recursive: true
|
|
164339
|
+
});
|
|
164340
|
+
return requireExistingDirectory(workdir, isDirectory2);
|
|
164341
|
+
}
|
|
164342
|
+
async function resolveTerminalWorkdirForSession(sessionId, options, seen) {
|
|
164343
|
+
if (seen.has(sessionId)) {
|
|
164344
|
+
throw new Error(`session_parent_cycle:${sessionId}`);
|
|
164345
|
+
}
|
|
164346
|
+
seen.add(sessionId);
|
|
164347
|
+
const lookup2 = await options.lookupSessionMeta(sessionId);
|
|
164348
|
+
if (lookup2.type === "missing") {
|
|
164349
|
+
throw new Error(`session_not_found:${sessionId}`);
|
|
164350
|
+
}
|
|
164351
|
+
if (lookup2.type === "deleted") {
|
|
164352
|
+
throw new Error(`session_deleted:${sessionId}`);
|
|
164353
|
+
}
|
|
164354
|
+
const meta = lookup2.meta;
|
|
164355
|
+
if (meta.isArchived) {
|
|
164356
|
+
throw new Error(`session_archived:${sessionId}`);
|
|
164357
|
+
}
|
|
164358
|
+
if (meta.machineId !== options.machineId) {
|
|
164359
|
+
throw new Error(`session_machine_mismatch:${sessionId}:${meta.machineId}`);
|
|
164360
|
+
}
|
|
164361
|
+
if (meta.parentSessionId) {
|
|
164362
|
+
return await resolveTerminalWorkdirForSession(meta.parentSessionId, options, seen);
|
|
164363
|
+
}
|
|
164364
|
+
const isDirectory2 = options.isDirectory ?? defaultIsDirectory;
|
|
164365
|
+
const homeDir = options.homeDir ?? os__default$1.homedir();
|
|
164366
|
+
const project = meta.project;
|
|
164367
|
+
if (project?.kind === "local") {
|
|
164368
|
+
const rootPath = await options.resolveLocalProjectRootPath(project.localProjectId);
|
|
164369
|
+
if (!rootPath) {
|
|
164370
|
+
throw new Error(`workdir_unavailable:local_project_not_found:${project.localProjectId}`);
|
|
164371
|
+
}
|
|
164372
|
+
if (meta.isWorktree || project.useWorktree === true) {
|
|
164373
|
+
const repoId = deriveRepoIdFromLocalProjectPath(rootPath);
|
|
164374
|
+
return requireExistingDirectory(getWorktreeHostPath(repoId, sessionId, homeDir), isDirectory2);
|
|
164375
|
+
}
|
|
164376
|
+
return requireExistingDirectory(rootPath, isDirectory2);
|
|
164377
|
+
}
|
|
164378
|
+
if (meta.repoFullName) {
|
|
164379
|
+
const repoId = deriveRepoIdFromGitHubRepo$1(meta.repoFullName);
|
|
164380
|
+
return requireExistingDirectory(getWorktreeHostPath(repoId, sessionId, homeDir), isDirectory2);
|
|
164381
|
+
}
|
|
164382
|
+
return resolveDefaultChatWorkdir(sessionId, homeDir, isDirectory2);
|
|
164383
|
+
}
|
|
164384
|
+
async function resolveTerminalWorkdirFromMetadata(options) {
|
|
164385
|
+
return await resolveTerminalWorkdirForSession(options.sessionId, options, /* @__PURE__ */ new Set());
|
|
164386
|
+
}
|
|
163169
164387
|
const FLEET_RUNTIME_STATE_INTERVAL_MS = 2e3;
|
|
163170
164388
|
class LodyFleet {
|
|
163171
164389
|
logger;
|
|
@@ -163177,6 +164395,7 @@ export PATH=${toSingleQuotedShellString(ghShimBinDir)}:"$PATH"
|
|
|
163177
164395
|
machineName;
|
|
163178
164396
|
localProjectControlService;
|
|
163179
164397
|
runtimeStateReporter;
|
|
164398
|
+
terminalPtyService;
|
|
163180
164399
|
onFatalAuthFailure;
|
|
163181
164400
|
runtimes = /* @__PURE__ */ new Map();
|
|
163182
164401
|
startInFlight = /* @__PURE__ */ new Map();
|
|
@@ -163202,6 +164421,10 @@ export PATH=${toSingleQuotedShellString(ghShimBinDir)}:"$PATH"
|
|
|
163202
164421
|
this.runtimeStateReporter = options.runtimeStateReporter;
|
|
163203
164422
|
this.onFatalAuthFailure = options.onFatalAuthFailure;
|
|
163204
164423
|
this.localProjectControlService = new LocalProjectControlService(this.logger);
|
|
164424
|
+
this.terminalPtyService = makeTerminalPtyService({
|
|
164425
|
+
logger: this.logger,
|
|
164426
|
+
resolveSessionWorkdir: async (sessionId) => await this.resolveTerminalSessionWorkdir(sessionId)
|
|
164427
|
+
});
|
|
163205
164428
|
}
|
|
163206
164429
|
async start() {
|
|
163207
164430
|
if (!LODY_AUTH_URL) {
|
|
@@ -163250,6 +164473,10 @@ export PATH=${toSingleQuotedShellString(ghShimBinDir)}:"$PATH"
|
|
|
163250
164473
|
dispatchSession: async (message) => await this.dispatchLocalSessionControl(message),
|
|
163251
164474
|
dispatchProject: async (message) => await this.dispatchLocalProjectControl(message)
|
|
163252
164475
|
});
|
|
164476
|
+
await startLocalTerminalServer({
|
|
164477
|
+
logger: this.logger,
|
|
164478
|
+
terminalPtyService: this.terminalPtyService
|
|
164479
|
+
});
|
|
163253
164480
|
this.convex = new ConvexClient(LODY_AUTH_URL);
|
|
163254
164481
|
await new Promise((resolve2, reject) => {
|
|
163255
164482
|
let initialResolved = false;
|
|
@@ -163336,7 +164563,9 @@ export PATH=${toSingleQuotedShellString(ghShimBinDir)}:"$PATH"
|
|
|
163336
164563
|
for (const runtime of runtimes) {
|
|
163337
164564
|
try {
|
|
163338
164565
|
await runtime.lody.cleanup();
|
|
164566
|
+
runtime.unsubscribeTerminalCleanup();
|
|
163339
164567
|
} catch (error2) {
|
|
164568
|
+
runtime.unsubscribeTerminalCleanup();
|
|
163340
164569
|
this.logger.debug(`[fleet] Failed to cleanup workspace runtime ${runtime.workspace.id}: ${formatErrorMessage$1(error2)}`);
|
|
163341
164570
|
}
|
|
163342
164571
|
}
|
|
@@ -163346,6 +164575,10 @@ export PATH=${toSingleQuotedShellString(ghShimBinDir)}:"$PATH"
|
|
|
163346
164575
|
await stopLocalSessionControl().catch((error2) => {
|
|
163347
164576
|
this.logger.debug(`[fleet] Failed to stop local session control: ${formatErrorMessage$1(error2)}`);
|
|
163348
164577
|
});
|
|
164578
|
+
await stopLocalTerminalServer().catch((error2) => {
|
|
164579
|
+
this.logger.debug(`[fleet] Failed to stop local terminal server: ${formatErrorMessage$1(error2)}`);
|
|
164580
|
+
});
|
|
164581
|
+
this.terminalPtyService.closeAll();
|
|
163349
164582
|
}
|
|
163350
164583
|
async applyWorkspaceList(next2) {
|
|
163351
164584
|
if (this.stopped) return;
|
|
@@ -163404,6 +164637,7 @@ export PATH=${toSingleQuotedShellString(ghShimBinDir)}:"$PATH"
|
|
|
163404
164637
|
userId: this.userId,
|
|
163405
164638
|
machineId: this.machineId,
|
|
163406
164639
|
machineName: this.machineName,
|
|
164640
|
+
closeSessionTerminals: (sessionId) => this.terminalPtyService.closeSession(sessionId),
|
|
163407
164641
|
onFatalAuthFailure: this.onFatalAuthFailure
|
|
163408
164642
|
});
|
|
163409
164643
|
if (!this.desiredWorkspaces.has(workspace.id) || this.stopped) {
|
|
@@ -163420,9 +164654,13 @@ export PATH=${toSingleQuotedShellString(ghShimBinDir)}:"$PATH"
|
|
|
163420
164654
|
await lody.cleanup();
|
|
163421
164655
|
return;
|
|
163422
164656
|
}
|
|
164657
|
+
const unsubscribeTerminalCleanup = lody.onSessionTerminated((sessionId) => {
|
|
164658
|
+
this.terminalPtyService.closeSession(sessionId);
|
|
164659
|
+
});
|
|
163423
164660
|
this.runtimes.set(workspace.id, {
|
|
163424
164661
|
workspace,
|
|
163425
|
-
lody
|
|
164662
|
+
lody,
|
|
164663
|
+
unsubscribeTerminalCleanup
|
|
163426
164664
|
});
|
|
163427
164665
|
this.logger.debug(`[fleet] Connected workspace: ${workspaceLabel} (${workspace.id})`);
|
|
163428
164666
|
this.runtimeStateReporter.clearIssue(`workspace_start_failed:${workspace.id}`);
|
|
@@ -163480,7 +164718,9 @@ export PATH=${toSingleQuotedShellString(ghShimBinDir)}:"$PATH"
|
|
|
163480
164718
|
this.runtimes.delete(workspaceId);
|
|
163481
164719
|
try {
|
|
163482
164720
|
await state2.lody.cleanup();
|
|
164721
|
+
state2.unsubscribeTerminalCleanup();
|
|
163483
164722
|
} catch (error2) {
|
|
164723
|
+
state2.unsubscribeTerminalCleanup();
|
|
163484
164724
|
this.logger.debug(`[fleet] Failed to cleanup workspace runtime ${workspaceId}: ${formatErrorMessage$1(error2)}`);
|
|
163485
164725
|
}
|
|
163486
164726
|
this.refreshRuntimeState();
|
|
@@ -163618,6 +164858,93 @@ export PATH=${toSingleQuotedShellString(ghShimBinDir)}:"$PATH"
|
|
|
163618
164858
|
}
|
|
163619
164859
|
return await runtime.lody.dispatchLocalControl(message);
|
|
163620
164860
|
}
|
|
164861
|
+
async lookupTerminalSessionMeta(runtime, sessionId) {
|
|
164862
|
+
const record2 = await runtime.lody.documentManager.repo.getDocMeta(getSessionRoomId(sessionId));
|
|
164863
|
+
if (!record2?.meta) {
|
|
164864
|
+
return {
|
|
164865
|
+
type: "missing"
|
|
164866
|
+
};
|
|
164867
|
+
}
|
|
164868
|
+
if (isLoroRepoDocDeleted(record2)) {
|
|
164869
|
+
return {
|
|
164870
|
+
type: "deleted"
|
|
164871
|
+
};
|
|
164872
|
+
}
|
|
164873
|
+
return {
|
|
164874
|
+
type: "found",
|
|
164875
|
+
meta: record2.meta
|
|
164876
|
+
};
|
|
164877
|
+
}
|
|
164878
|
+
async assertTerminalSessionAllowed(sessionId) {
|
|
164879
|
+
for (const runtime of this.runtimes.values()) {
|
|
164880
|
+
const lookup2 = await this.lookupTerminalSessionMeta(runtime, sessionId);
|
|
164881
|
+
if (lookup2.type === "missing") {
|
|
164882
|
+
continue;
|
|
164883
|
+
}
|
|
164884
|
+
if (lookup2.type === "deleted") {
|
|
164885
|
+
throw new Error(`session_deleted:${sessionId}`);
|
|
164886
|
+
}
|
|
164887
|
+
if (lookup2.meta.isArchived) {
|
|
164888
|
+
throw new Error(`session_archived:${sessionId}`);
|
|
164889
|
+
}
|
|
164890
|
+
if (lookup2.meta.machineId !== this.machineId) {
|
|
164891
|
+
throw new Error(`session_machine_mismatch:${sessionId}:${lookup2.meta.machineId}`);
|
|
164892
|
+
}
|
|
164893
|
+
return;
|
|
164894
|
+
}
|
|
164895
|
+
}
|
|
164896
|
+
async resolveActiveTerminalSessionWorkdir(sessionId) {
|
|
164897
|
+
const matches = [];
|
|
164898
|
+
for (const runtime of this.runtimes.values()) {
|
|
164899
|
+
const workdir = await runtime.lody.resolveSessionWorkdir(sessionId);
|
|
164900
|
+
if (workdir) {
|
|
164901
|
+
matches.push(workdir);
|
|
164902
|
+
}
|
|
164903
|
+
}
|
|
164904
|
+
if (matches.length > 1) {
|
|
164905
|
+
throw new Error(`session_ambiguous:${sessionId}`);
|
|
164906
|
+
}
|
|
164907
|
+
return matches[0] ?? null;
|
|
164908
|
+
}
|
|
164909
|
+
async resolveTerminalSessionWorkdirFromMetadata(sessionId) {
|
|
164910
|
+
const matches = [];
|
|
164911
|
+
const errors2 = [];
|
|
164912
|
+
for (const runtime of this.runtimes.values()) {
|
|
164913
|
+
try {
|
|
164914
|
+
const workdir = await resolveTerminalWorkdirFromMetadata({
|
|
164915
|
+
sessionId,
|
|
164916
|
+
machineId: this.machineId,
|
|
164917
|
+
lookupSessionMeta: async (targetSessionId) => await this.lookupTerminalSessionMeta(runtime, targetSessionId),
|
|
164918
|
+
resolveLocalProjectRootPath: async (localProjectId) => await resolveWorkspaceLocalProjectRootPath(runtime.lody.documentManager.repo, this.machineId, localProjectId)
|
|
164919
|
+
});
|
|
164920
|
+
matches.push(workdir);
|
|
164921
|
+
} catch (error2) {
|
|
164922
|
+
const message = formatErrorMessage$1(error2);
|
|
164923
|
+
if (message.startsWith("session_not_found:")) {
|
|
164924
|
+
continue;
|
|
164925
|
+
}
|
|
164926
|
+
errors2.push(error2 instanceof Error ? error2 : new Error(message));
|
|
164927
|
+
}
|
|
164928
|
+
}
|
|
164929
|
+
if (matches.length > 1) {
|
|
164930
|
+
throw new Error(`session_ambiguous:${sessionId}`);
|
|
164931
|
+
}
|
|
164932
|
+
if (matches.length === 1) {
|
|
164933
|
+
return matches[0];
|
|
164934
|
+
}
|
|
164935
|
+
if (errors2[0]) {
|
|
164936
|
+
throw errors2[0];
|
|
164937
|
+
}
|
|
164938
|
+
throw new Error(`session_not_found:${sessionId}`);
|
|
164939
|
+
}
|
|
164940
|
+
async resolveTerminalSessionWorkdir(sessionId) {
|
|
164941
|
+
await this.assertTerminalSessionAllowed(sessionId);
|
|
164942
|
+
const activeWorkdir = await this.resolveActiveTerminalSessionWorkdir(sessionId);
|
|
164943
|
+
if (activeWorkdir) {
|
|
164944
|
+
return activeWorkdir;
|
|
164945
|
+
}
|
|
164946
|
+
return await this.resolveTerminalSessionWorkdirFromMetadata(sessionId);
|
|
164947
|
+
}
|
|
163621
164948
|
toProjectControlError(type2, error2, message, data) {
|
|
163622
164949
|
return {
|
|
163623
164950
|
ok: false,
|
|
@@ -168165,9 +169492,9 @@ Received ${signal}, shutting down gracefully...` : "\nShutting down gracefully..
|
|
|
168165
169492
|
(function(module2) {
|
|
168166
169493
|
const ansiEscapes2 = module2.exports;
|
|
168167
169494
|
module2.exports.default = ansiEscapes2;
|
|
168168
|
-
const
|
|
169495
|
+
const ESC2 = "\x1B[";
|
|
168169
169496
|
const OSC = "\x1B]";
|
|
168170
|
-
const
|
|
169497
|
+
const BEL2 = "\x07";
|
|
168171
169498
|
const SEP = ";";
|
|
168172
169499
|
const isTerminalApp = process.env.TERM_PROGRAM === "Apple_Terminal";
|
|
168173
169500
|
ansiEscapes2.cursorTo = (x, y) => {
|
|
@@ -168175,9 +169502,9 @@ Received ${signal}, shutting down gracefully...` : "\nShutting down gracefully..
|
|
|
168175
169502
|
throw new TypeError("The `x` argument is required");
|
|
168176
169503
|
}
|
|
168177
169504
|
if (typeof y !== "number") {
|
|
168178
|
-
return
|
|
169505
|
+
return ESC2 + (x + 1) + "G";
|
|
168179
169506
|
}
|
|
168180
|
-
return
|
|
169507
|
+
return ESC2 + (y + 1) + ";" + (x + 1) + "H";
|
|
168181
169508
|
};
|
|
168182
169509
|
ansiEscapes2.cursorMove = (x, y) => {
|
|
168183
169510
|
if (typeof x !== "number") {
|
|
@@ -168185,29 +169512,29 @@ Received ${signal}, shutting down gracefully...` : "\nShutting down gracefully..
|
|
|
168185
169512
|
}
|
|
168186
169513
|
let ret = "";
|
|
168187
169514
|
if (x < 0) {
|
|
168188
|
-
ret +=
|
|
169515
|
+
ret += ESC2 + -x + "D";
|
|
168189
169516
|
} else if (x > 0) {
|
|
168190
|
-
ret +=
|
|
169517
|
+
ret += ESC2 + x + "C";
|
|
168191
169518
|
}
|
|
168192
169519
|
if (y < 0) {
|
|
168193
|
-
ret +=
|
|
169520
|
+
ret += ESC2 + -y + "A";
|
|
168194
169521
|
} else if (y > 0) {
|
|
168195
|
-
ret +=
|
|
169522
|
+
ret += ESC2 + y + "B";
|
|
168196
169523
|
}
|
|
168197
169524
|
return ret;
|
|
168198
169525
|
};
|
|
168199
|
-
ansiEscapes2.cursorUp = (count2 = 1) =>
|
|
168200
|
-
ansiEscapes2.cursorDown = (count2 = 1) =>
|
|
168201
|
-
ansiEscapes2.cursorForward = (count2 = 1) =>
|
|
168202
|
-
ansiEscapes2.cursorBackward = (count2 = 1) =>
|
|
168203
|
-
ansiEscapes2.cursorLeft =
|
|
168204
|
-
ansiEscapes2.cursorSavePosition = isTerminalApp ? "\x1B7" :
|
|
168205
|
-
ansiEscapes2.cursorRestorePosition = isTerminalApp ? "\x1B8" :
|
|
168206
|
-
ansiEscapes2.cursorGetPosition =
|
|
168207
|
-
ansiEscapes2.cursorNextLine =
|
|
168208
|
-
ansiEscapes2.cursorPrevLine =
|
|
168209
|
-
ansiEscapes2.cursorHide =
|
|
168210
|
-
ansiEscapes2.cursorShow =
|
|
169526
|
+
ansiEscapes2.cursorUp = (count2 = 1) => ESC2 + count2 + "A";
|
|
169527
|
+
ansiEscapes2.cursorDown = (count2 = 1) => ESC2 + count2 + "B";
|
|
169528
|
+
ansiEscapes2.cursorForward = (count2 = 1) => ESC2 + count2 + "C";
|
|
169529
|
+
ansiEscapes2.cursorBackward = (count2 = 1) => ESC2 + count2 + "D";
|
|
169530
|
+
ansiEscapes2.cursorLeft = ESC2 + "G";
|
|
169531
|
+
ansiEscapes2.cursorSavePosition = isTerminalApp ? "\x1B7" : ESC2 + "s";
|
|
169532
|
+
ansiEscapes2.cursorRestorePosition = isTerminalApp ? "\x1B8" : ESC2 + "u";
|
|
169533
|
+
ansiEscapes2.cursorGetPosition = ESC2 + "6n";
|
|
169534
|
+
ansiEscapes2.cursorNextLine = ESC2 + "E";
|
|
169535
|
+
ansiEscapes2.cursorPrevLine = ESC2 + "F";
|
|
169536
|
+
ansiEscapes2.cursorHide = ESC2 + "?25l";
|
|
169537
|
+
ansiEscapes2.cursorShow = ESC2 + "?25h";
|
|
168211
169538
|
ansiEscapes2.eraseLines = (count2) => {
|
|
168212
169539
|
let clear = "";
|
|
168213
169540
|
for (let i2 = 0; i2 < count2; i2++) {
|
|
@@ -168218,17 +169545,17 @@ Received ${signal}, shutting down gracefully...` : "\nShutting down gracefully..
|
|
|
168218
169545
|
}
|
|
168219
169546
|
return clear;
|
|
168220
169547
|
};
|
|
168221
|
-
ansiEscapes2.eraseEndLine =
|
|
168222
|
-
ansiEscapes2.eraseStartLine =
|
|
168223
|
-
ansiEscapes2.eraseLine =
|
|
168224
|
-
ansiEscapes2.eraseDown =
|
|
168225
|
-
ansiEscapes2.eraseUp =
|
|
168226
|
-
ansiEscapes2.eraseScreen =
|
|
168227
|
-
ansiEscapes2.scrollUp =
|
|
168228
|
-
ansiEscapes2.scrollDown =
|
|
169548
|
+
ansiEscapes2.eraseEndLine = ESC2 + "K";
|
|
169549
|
+
ansiEscapes2.eraseStartLine = ESC2 + "1K";
|
|
169550
|
+
ansiEscapes2.eraseLine = ESC2 + "2K";
|
|
169551
|
+
ansiEscapes2.eraseDown = ESC2 + "J";
|
|
169552
|
+
ansiEscapes2.eraseUp = ESC2 + "1J";
|
|
169553
|
+
ansiEscapes2.eraseScreen = ESC2 + "2J";
|
|
169554
|
+
ansiEscapes2.scrollUp = ESC2 + "S";
|
|
169555
|
+
ansiEscapes2.scrollDown = ESC2 + "T";
|
|
168229
169556
|
ansiEscapes2.clearScreen = "\x1Bc";
|
|
168230
|
-
ansiEscapes2.clearTerminal = process.platform === "win32" ? `${ansiEscapes2.eraseScreen}${
|
|
168231
|
-
ansiEscapes2.beep =
|
|
169557
|
+
ansiEscapes2.clearTerminal = process.platform === "win32" ? `${ansiEscapes2.eraseScreen}${ESC2}0f` : `${ansiEscapes2.eraseScreen}${ESC2}3J${ESC2}H`;
|
|
169558
|
+
ansiEscapes2.beep = BEL2;
|
|
168232
169559
|
ansiEscapes2.link = (text, url) => {
|
|
168233
169560
|
return [
|
|
168234
169561
|
OSC,
|
|
@@ -168236,13 +169563,13 @@ Received ${signal}, shutting down gracefully...` : "\nShutting down gracefully..
|
|
|
168236
169563
|
SEP,
|
|
168237
169564
|
SEP,
|
|
168238
169565
|
url,
|
|
168239
|
-
|
|
169566
|
+
BEL2,
|
|
168240
169567
|
text,
|
|
168241
169568
|
OSC,
|
|
168242
169569
|
"8",
|
|
168243
169570
|
SEP,
|
|
168244
169571
|
SEP,
|
|
168245
|
-
|
|
169572
|
+
BEL2
|
|
168246
169573
|
].join("");
|
|
168247
169574
|
};
|
|
168248
169575
|
ansiEscapes2.image = (buffer2, options = {}) => {
|
|
@@ -168256,10 +169583,10 @@ Received ${signal}, shutting down gracefully...` : "\nShutting down gracefully..
|
|
|
168256
169583
|
if (options.preserveAspectRatio === false) {
|
|
168257
169584
|
ret += ";preserveAspectRatio=0";
|
|
168258
169585
|
}
|
|
168259
|
-
return ret + ":" + buffer2.toString("base64") +
|
|
169586
|
+
return ret + ":" + buffer2.toString("base64") + BEL2;
|
|
168260
169587
|
};
|
|
168261
169588
|
ansiEscapes2.iTerm = {
|
|
168262
|
-
setCwd: (cwd = process.cwd()) => `${OSC}50;CurrentDir=${cwd}${
|
|
169589
|
+
setCwd: (cwd = process.cwd()) => `${OSC}50;CurrentDir=${cwd}${BEL2}`,
|
|
168263
169590
|
annotation: (message, options = {}) => {
|
|
168264
169591
|
let ret = `${OSC}1337;`;
|
|
168265
169592
|
const hasX = typeof options.x !== "undefined";
|
|
@@ -168282,7 +169609,7 @@ Received ${signal}, shutting down gracefully...` : "\nShutting down gracefully..
|
|
|
168282
169609
|
} else {
|
|
168283
169610
|
ret += message;
|
|
168284
169611
|
}
|
|
168285
|
-
return ret +
|
|
169612
|
+
return ret + BEL2;
|
|
168286
169613
|
}
|
|
168287
169614
|
};
|
|
168288
169615
|
})(ansiEscapes$1);
|
|
@@ -188151,7 +189478,7 @@ ${page}${helpTipBottom}${choiceDescription}${ansiEscapes.cursorHide}`;
|
|
|
188151
189478
|
throttled === null || throttled === void 0 ? void 0 : throttled.unsubscribe();
|
|
188152
189479
|
throttled = null;
|
|
188153
189480
|
if (trailing) {
|
|
188154
|
-
|
|
189481
|
+
send2();
|
|
188155
189482
|
isComplete && subscriber.complete();
|
|
188156
189483
|
}
|
|
188157
189484
|
};
|
|
@@ -188162,7 +189489,7 @@ ${page}${helpTipBottom}${choiceDescription}${ansiEscapes.cursorHide}`;
|
|
|
188162
189489
|
var startThrottle = function(value) {
|
|
188163
189490
|
return throttled = innerFrom_1.innerFrom(durationSelector(value)).subscribe(OperatorSubscriber_1.createOperatorSubscriber(subscriber, endThrottling, cleanupThrottling));
|
|
188164
189491
|
};
|
|
188165
|
-
var
|
|
189492
|
+
var send2 = function() {
|
|
188166
189493
|
if (hasValue) {
|
|
188167
189494
|
hasValue = false;
|
|
188168
189495
|
var value = sendValue;
|
|
@@ -188174,7 +189501,7 @@ ${page}${helpTipBottom}${choiceDescription}${ansiEscapes.cursorHide}`;
|
|
|
188174
189501
|
source.subscribe(OperatorSubscriber_1.createOperatorSubscriber(subscriber, function(value) {
|
|
188175
189502
|
hasValue = true;
|
|
188176
189503
|
sendValue = value;
|
|
188177
|
-
!(throttled && !throttled.closed) && (leading ?
|
|
189504
|
+
!(throttled && !throttled.closed) && (leading ? send2() : startThrottle(value));
|
|
188178
189505
|
}, function() {
|
|
188179
189506
|
isComplete = true;
|
|
188180
189507
|
!(trailing && hasValue && throttled && !throttled.closed) && subscriber.complete();
|
|
@@ -191068,7 +192395,7 @@ ${page}${helpTipBottom}${choiceDescription}${ansiEscapes.cursorHide}`;
|
|
|
191068
192395
|
}
|
|
191069
192396
|
function hyperlink(url, text) {
|
|
191070
192397
|
const OSC = "\x1B]";
|
|
191071
|
-
const
|
|
192398
|
+
const BEL2 = "\x07";
|
|
191072
192399
|
const SEP = ";";
|
|
191073
192400
|
return [
|
|
191074
192401
|
OSC,
|
|
@@ -191076,13 +192403,13 @@ ${page}${helpTipBottom}${choiceDescription}${ansiEscapes.cursorHide}`;
|
|
|
191076
192403
|
SEP,
|
|
191077
192404
|
SEP,
|
|
191078
192405
|
url || text,
|
|
191079
|
-
|
|
192406
|
+
BEL2,
|
|
191080
192407
|
text,
|
|
191081
192408
|
OSC,
|
|
191082
192409
|
"8",
|
|
191083
192410
|
SEP,
|
|
191084
192411
|
SEP,
|
|
191085
|
-
|
|
192412
|
+
BEL2
|
|
191086
192413
|
].join("");
|
|
191087
192414
|
}
|
|
191088
192415
|
utils$1 = {
|
|
@@ -193234,7 +194561,7 @@ ${page}${helpTipBottom}${choiceDescription}${ansiEscapes.cursorHide}`;
|
|
|
193234
194561
|
}
|
|
193235
194562
|
function inferAgentConfigCliType(agentType) {
|
|
193236
194563
|
const normalized = normalizeCliValue(agentType)?.toLowerCase();
|
|
193237
|
-
return normalized
|
|
194564
|
+
return normalized && isBuiltinAgentType(normalized) ? "builtin" : "registry";
|
|
193238
194565
|
}
|
|
193239
194566
|
function parseEnvAssignments(entries) {
|
|
193240
194567
|
const parsed = {};
|
|
@@ -194247,7 +195574,7 @@ ${entry.text}`).join("\n\n");
|
|
|
194247
195574
|
}
|
|
194248
195575
|
throw new Error(`Multiple agent configs are available; pass --agent-config. Candidates: ${formatAgentConfigCandidates(configs)}`);
|
|
194249
195576
|
}
|
|
194250
|
-
async function resolveLocalProjectRefOrThrow(manager, machineId, selector, requestedBranch) {
|
|
195577
|
+
async function resolveLocalProjectRefOrThrow(manager, machineId, selector, requestedBranch, useWorktree) {
|
|
194251
195578
|
const machineRoomId = getMachineRoomId(machineId);
|
|
194252
195579
|
const raw2 = await manager.repo.getDocMeta(machineRoomId);
|
|
194253
195580
|
const machineMeta = raw2?.meta;
|
|
@@ -194267,18 +195594,26 @@ ${entry.text}`).join("\n\n");
|
|
|
194267
195594
|
throw new Error(`Local project selector is ambiguous: ${normalizedSelector}. Use a project id instead.`);
|
|
194268
195595
|
}
|
|
194269
195596
|
const project = matches[0];
|
|
194270
|
-
const branch = await resolveLocalProjectBranchForCreate(project, requestedBranch
|
|
195597
|
+
const branch = await resolveLocalProjectBranchForCreate(project, requestedBranch, {
|
|
195598
|
+
requireGit: useWorktree === true
|
|
195599
|
+
});
|
|
194271
195600
|
return {
|
|
194272
195601
|
kind: "local",
|
|
194273
195602
|
localProjectId: project.id,
|
|
194274
195603
|
...branch ? {
|
|
194275
195604
|
branch
|
|
195605
|
+
} : {},
|
|
195606
|
+
...useWorktree === true ? {
|
|
195607
|
+
useWorktree: true
|
|
194276
195608
|
} : {}
|
|
194277
195609
|
};
|
|
194278
195610
|
}
|
|
194279
|
-
async function resolveLocalProjectBranchForCreate(project, requestedBranch) {
|
|
195611
|
+
async function resolveLocalProjectBranchForCreate(project, requestedBranch, options = {}) {
|
|
194280
195612
|
const gitState = await getLocalProjectGitStateAtRootPath(project.rootPath);
|
|
194281
195613
|
if (!gitState.git) {
|
|
195614
|
+
if (options.requireGit === true) {
|
|
195615
|
+
throw new Error("Cannot use --worktree with a local project that is not a git repository.");
|
|
195616
|
+
}
|
|
194282
195617
|
if (requestedBranch) {
|
|
194283
195618
|
throw new Error("Cannot use --branch with a local project that is not a git repository.");
|
|
194284
195619
|
}
|
|
@@ -194634,6 +195969,10 @@ ${entry.text}`).join("\n\n");
|
|
|
194634
195969
|
if (normalizedRepo && normalizedLocalProject) {
|
|
194635
195970
|
throw new Error("Pass either --repo or --local-project, not both.");
|
|
194636
195971
|
}
|
|
195972
|
+
const useLocalProjectWorktree = options.worktree === true;
|
|
195973
|
+
if (useLocalProjectWorktree && !normalizedLocalProject) {
|
|
195974
|
+
throw new Error("Pass --worktree together with --local-project.");
|
|
195975
|
+
}
|
|
194637
195976
|
const requestedBranch = normalizeCliValue(options.branch);
|
|
194638
195977
|
const envOverrides = parseEnvAssignments(options.env);
|
|
194639
195978
|
let project;
|
|
@@ -194648,7 +195987,7 @@ ${entry.text}`).join("\n\n");
|
|
|
194648
195987
|
branch
|
|
194649
195988
|
};
|
|
194650
195989
|
} else if (normalizedLocalProject) {
|
|
194651
|
-
project = await resolveLocalProjectRefOrThrow(manager, auth.machineId, normalizedLocalProject, requestedBranch);
|
|
195990
|
+
project = await resolveLocalProjectRefOrThrow(manager, auth.machineId, normalizedLocalProject, requestedBranch, useLocalProjectWorktree);
|
|
194652
195991
|
}
|
|
194653
195992
|
const sessionId = v4();
|
|
194654
195993
|
const sessionRoomId = getSessionRoomId(sessionId);
|
|
@@ -194850,7 +196189,7 @@ ${entry.text}`).join("\n\n");
|
|
|
194850
196189
|
process.exit(code2);
|
|
194851
196190
|
}
|
|
194852
196191
|
}
|
|
194853
|
-
const sessionCreateCommand = new Command("create").description("Create a new session on the current machine").option("--workspace <idOrSlug>", "Target workspace id or slug").option("--agent-config <idOrName>", "Agent config id or name").option("--title <title>", "Session title").option("--repo <owner/repo>", "GitHub repository to attach").option("--local-project <id|name|path>", "Local project id, name, or root path").option("--branch <name>", "Git branch to use for GitHub repos or local git projects").option("--mode <modeId>", "ACP mode override").option("--model <modelId>", "ACP model override").option("--env <keyValue>", "Extra environment variable in KEY=VALUE form; repeatable", collectListOption, []).option("--prompt <text>", "Prompt text").option("--prompt-file <path>", "Read prompt text from file, or - for stdin").option("--json", "Print JSON output").option("--jsonl", "Print JSON Lines output").option("--timeout <seconds>", "Wait timeout in seconds for structured output", parsePositiveIntOption).option("--debug", "Enable debug output").argument("[prompt]", "Prompt text").action(async (promptArg, options) => {
|
|
196192
|
+
const sessionCreateCommand = new Command("create").description("Create a new session on the current machine").option("--workspace <idOrSlug>", "Target workspace id or slug").option("--agent-config <idOrName>", "Agent config id or name").option("--title <title>", "Session title").option("--repo <owner/repo>", "GitHub repository to attach").option("--local-project <id|name|path>", "Local project id, name, or root path").option("--worktree", "Create an isolated git worktree for --local-project").option("--branch <name>", "Git branch to use for GitHub repos or local git projects").option("--mode <modeId>", "ACP mode override").option("--model <modelId>", "ACP model override").option("--env <keyValue>", "Extra environment variable in KEY=VALUE form; repeatable", collectListOption, []).option("--prompt <text>", "Prompt text").option("--prompt-file <path>", "Read prompt text from file, or - for stdin").option("--json", "Print JSON output").option("--jsonl", "Print JSON Lines output").option("--timeout <seconds>", "Wait timeout in seconds for structured output", parsePositiveIntOption).option("--debug", "Enable debug output").argument("[prompt]", "Prompt text").action(async (promptArg, options) => {
|
|
194854
196193
|
await runSessionCommand(options, async () => {
|
|
194855
196194
|
const outputMode = resolveStructuredOutputMode(options);
|
|
194856
196195
|
const createStartMs = Date.now();
|