toyon 0.17.0 → 0.18.0
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/CHANGELOG.md +36 -0
- package/dist/cli.js +1 -1
- package/dist/daemon.js +612 -384
- package/dist/shell/assets/{Editor-BMBnZV2V.js → Editor-CU91PIeX.js} +131 -131
- package/dist/shell/assets/{XTerm-xxm4nCyN.js → XTerm-y7vQoOEu.js} +1 -1
- package/dist/shell/assets/{cssMode-DRRmIKjD.js → cssMode-B7sFzM6K.js} +1 -1
- package/dist/shell/assets/{freemarker2-BWXbPnFF.js → freemarker2-ChTLQoDC.js} +1 -1
- package/dist/shell/assets/{grammar-BlgE3B1J.js → grammar-xXcxTc3V.js} +1 -1
- package/dist/shell/assets/{handlebars-swdzvdWB.js → handlebars-DPJSozQx.js} +1 -1
- package/dist/shell/assets/{html-GPVhANjL.js → html-Cog2rLcD.js} +1 -1
- package/dist/shell/assets/{htmlMode-BTtuR8kD.js → htmlMode-Xm5_ujKb.js} +1 -1
- package/dist/shell/assets/index-BpW1Kufz.css +1 -0
- package/dist/shell/assets/index-CdY8WF4P.js +270 -0
- package/dist/shell/assets/{javascript-CFXn2iKE.js → javascript-Dcv6lw7b.js} +1 -1
- package/dist/shell/assets/{jsonMode-wmrRCrSu.js → jsonMode-D5_V0TW5.js} +1 -1
- package/dist/shell/assets/{liquid-Bz7Svg4V.js → liquid-C_zXIF5F.js} +1 -1
- package/dist/shell/assets/{lspLanguageFeatures-BDP4BowE.js → lspLanguageFeatures-CkiTdLmp.js} +1 -1
- package/dist/shell/assets/{mdx-CzERTPdi.js → mdx-gvbILQkr.js} +1 -1
- package/dist/shell/assets/{python-3OsSAVmo.js → python-CZTrOkh_.js} +1 -1
- package/dist/shell/assets/{razor-BKY4SJuy.js → razor-DowlBj1i.js} +1 -1
- package/dist/shell/assets/{tsMode-BESW693Z.js → tsMode-BNl2cV_K.js} +1 -1
- package/dist/shell/assets/{xml-SaTEQQ9V.js → xml-DIiuHFHw.js} +1 -1
- package/dist/shell/assets/{yaml-gHi84-nk.js → yaml-CBnMyn4j.js} +1 -1
- package/dist/shell/icon-192.png +0 -0
- package/dist/shell/icon-512.png +0 -0
- package/dist/shell/icon-maskable-512.png +0 -0
- package/dist/shell/index.html +94 -13
- package/dist/shell/manifest.json +19 -1
- package/package.json +1 -1
- package/dist/shell/assets/index-9aG0ri4Y.css +0 -1
- package/dist/shell/assets/index-miqqiN7Z.js +0 -269
package/dist/daemon.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
// @bun
|
|
2
2
|
// ../daemon/src/index.ts
|
|
3
|
-
import { rmSync as rmSync9, writeFileSync as
|
|
3
|
+
import { rmSync as rmSync9, writeFileSync as writeFileSync14 } from "fs";
|
|
4
4
|
import { homedir as homedir15 } from "os";
|
|
5
|
-
import { dirname as
|
|
5
|
+
import { dirname as dirname14, join as join33 } from "path";
|
|
6
6
|
import { fileURLToPath } from "url";
|
|
7
7
|
|
|
8
8
|
// ../shared/src/protocol/events.ts
|
|
@@ -71,6 +71,7 @@ function applyLog(lines, proc, line, retract = 0) {
|
|
|
71
71
|
return out;
|
|
72
72
|
return [...out, { proc, line }];
|
|
73
73
|
}
|
|
74
|
+
var isBusy = (status) => status === "working" || status === "waiting";
|
|
74
75
|
var KEEP_AWAKE_MODES = ["use", "always", "off"];
|
|
75
76
|
|
|
76
77
|
// ../shared/src/worktree-caps.ts
|
|
@@ -6601,7 +6602,7 @@ ${text.slice(text.length - (CONTEXT_CHARS - HEAD_CHARS))}`;
|
|
|
6601
6602
|
}
|
|
6602
6603
|
|
|
6603
6604
|
// ../shared/src/protocol/limits.ts
|
|
6604
|
-
var PROTOCOL_VERSION =
|
|
6605
|
+
var PROTOCOL_VERSION = 119;
|
|
6605
6606
|
var PAGE_ERROR_MAX_CHARS = 2000;
|
|
6606
6607
|
var PAGE_TITLE_MAX_CHARS = 1000;
|
|
6607
6608
|
var FILE_MAX_CHARS = 5000000;
|
|
@@ -7039,7 +7040,13 @@ var clientMsgSchema = discriminatedUnion("t", [
|
|
|
7039
7040
|
attachments,
|
|
7040
7041
|
boxId
|
|
7041
7042
|
}),
|
|
7042
|
-
object({
|
|
7043
|
+
object({
|
|
7044
|
+
t: literal("agent-decide"),
|
|
7045
|
+
worktreeId: id,
|
|
7046
|
+
askId: string2().max(64),
|
|
7047
|
+
choiceId: string2().max(200),
|
|
7048
|
+
note: string2().max(1e4).optional()
|
|
7049
|
+
}),
|
|
7043
7050
|
object({
|
|
7044
7051
|
t: literal("handoff-answer"),
|
|
7045
7052
|
worktreeId: id,
|
|
@@ -8519,7 +8526,7 @@ async function turnRemoteOff(ts, daemonPort, file, was) {
|
|
|
8519
8526
|
// ../daemon/package.json
|
|
8520
8527
|
var package_default = {
|
|
8521
8528
|
name: "@toyon/daemon",
|
|
8522
|
-
version: "0.
|
|
8529
|
+
version: "0.18.0",
|
|
8523
8530
|
private: true,
|
|
8524
8531
|
type: "module",
|
|
8525
8532
|
main: "src/index.ts",
|
|
@@ -13765,7 +13772,8 @@ function sameLimits(a, b) {
|
|
|
13765
13772
|
if (!a || !b)
|
|
13766
13773
|
return a === b;
|
|
13767
13774
|
const win = (x) => x ? `${x.used}@${x.resetsAt}` : "";
|
|
13768
|
-
|
|
13775
|
+
const keys = ["five_hour", "seven_day", "seven_day_overage_included"];
|
|
13776
|
+
return a.status === b.status && a.binding === b.binding && keys.every((k) => win(a.windows[k]) === win(b.windows[k]));
|
|
13769
13777
|
}
|
|
13770
13778
|
function same(a, b) {
|
|
13771
13779
|
if (!a || !b)
|
|
@@ -15091,6 +15099,91 @@ function loadAgentRegistry(agentsFile, agentsDir, sandbox, managed = MANAGED_DEF
|
|
|
15091
15099
|
// ../daemon/src/agent/acp/session.ts
|
|
15092
15100
|
import { randomUUID } from "crypto";
|
|
15093
15101
|
|
|
15102
|
+
// ../daemon/src/agent/awsAuth.ts
|
|
15103
|
+
import { existsSync as existsSync10, mkdirSync as mkdirSync7, readFileSync as readFileSync9, renameSync as renameSync2, writeFileSync as writeFileSync6 } from "fs";
|
|
15104
|
+
import { dirname as dirname4, join as join8 } from "path";
|
|
15105
|
+
var AWS_EXPIRED_RE = /could not load aws credentials|aws sso login|aws authentication failed|expiredtoken|security token included in the request is (expired|invalid)|sso (session|token)[^.]*expired|token is expired|awsauthrefresh/i;
|
|
15106
|
+
var AWS_LOGIN_METHOD = "aws-login";
|
|
15107
|
+
var AWS_REFRESH_METHOD = "aws-refresh";
|
|
15108
|
+
function readAwsAuth(configDir, cwd, env = process.env) {
|
|
15109
|
+
const files = [
|
|
15110
|
+
join8(cwd, ".claude", "settings.local.json"),
|
|
15111
|
+
join8(cwd, ".claude", "settings.json"),
|
|
15112
|
+
join8(configDir, "settings.json")
|
|
15113
|
+
];
|
|
15114
|
+
let profile;
|
|
15115
|
+
let refresh;
|
|
15116
|
+
for (const file of files) {
|
|
15117
|
+
const s = readSettings(file);
|
|
15118
|
+
if (!s)
|
|
15119
|
+
continue;
|
|
15120
|
+
const e = s.env;
|
|
15121
|
+
profile ??= str2(e?.AWS_PROFILE);
|
|
15122
|
+
refresh ??= str2(s.awsAuthRefresh);
|
|
15123
|
+
}
|
|
15124
|
+
profile ??= str2(env.AWS_PROFILE);
|
|
15125
|
+
return { ...profile ? { profile } : {}, ...refresh ? { refresh } : {} };
|
|
15126
|
+
}
|
|
15127
|
+
function awsLoginCommand(profile) {
|
|
15128
|
+
return profile ? `aws sso login --profile ${shellWord(profile)}` : "aws sso login";
|
|
15129
|
+
}
|
|
15130
|
+
function awsMethods(auth, settable) {
|
|
15131
|
+
const login = {
|
|
15132
|
+
id: AWS_LOGIN_METHOD,
|
|
15133
|
+
name: "log in to AWS",
|
|
15134
|
+
description: `runs ${awsLoginCommand(auth.profile)} in the terminal pane`,
|
|
15135
|
+
kind: "terminal"
|
|
15136
|
+
};
|
|
15137
|
+
if (auth.refresh || !settable)
|
|
15138
|
+
return [login];
|
|
15139
|
+
return [
|
|
15140
|
+
{
|
|
15141
|
+
id: AWS_REFRESH_METHOD,
|
|
15142
|
+
name: "refresh automatically",
|
|
15143
|
+
description: "sets awsAuthRefresh in your Claude settings, so Claude runs the login itself when the session expires",
|
|
15144
|
+
kind: "agent"
|
|
15145
|
+
},
|
|
15146
|
+
login
|
|
15147
|
+
];
|
|
15148
|
+
}
|
|
15149
|
+
function setAwsAuthRefresh(configDir, command) {
|
|
15150
|
+
const file = join8(configDir, "settings.json");
|
|
15151
|
+
let settings = {};
|
|
15152
|
+
if (existsSync10(file)) {
|
|
15153
|
+
try {
|
|
15154
|
+
const v = JSON.parse(readFileSync9(file, "utf8"));
|
|
15155
|
+
if (!v || typeof v !== "object" || Array.isArray(v))
|
|
15156
|
+
throw new Error("not an object");
|
|
15157
|
+
settings = v;
|
|
15158
|
+
} catch (e) {
|
|
15159
|
+
throw new UserError(`${file} is not valid JSON (${e instanceof Error ? e.message : String(e)}); fix it, then try again`);
|
|
15160
|
+
}
|
|
15161
|
+
}
|
|
15162
|
+
const rest = Object.fromEntries(Object.entries(settings).filter(([k]) => k !== "awsAuthRefresh"));
|
|
15163
|
+
const next = { awsAuthRefresh: command, ...rest };
|
|
15164
|
+
mkdirSync7(dirname4(file), { recursive: true });
|
|
15165
|
+
const tmp = `${file}.${process.pid}.tmp`;
|
|
15166
|
+
writeFileSync6(tmp, `${JSON.stringify(next, null, 2)}
|
|
15167
|
+
`);
|
|
15168
|
+
renameSync2(tmp, file);
|
|
15169
|
+
return file;
|
|
15170
|
+
}
|
|
15171
|
+
function readSettings(file) {
|
|
15172
|
+
if (!existsSync10(file))
|
|
15173
|
+
return null;
|
|
15174
|
+
try {
|
|
15175
|
+
const v = JSON.parse(readFileSync9(file, "utf8"));
|
|
15176
|
+
return v && typeof v === "object" && !Array.isArray(v) ? v : null;
|
|
15177
|
+
} catch (e) {
|
|
15178
|
+
log.warn("aws-auth", `${file} is not valid JSON`, e);
|
|
15179
|
+
return null;
|
|
15180
|
+
}
|
|
15181
|
+
}
|
|
15182
|
+
var str2 = (v) => typeof v === "string" && v.trim() ? v.trim() : undefined;
|
|
15183
|
+
function shellWord(s) {
|
|
15184
|
+
return /^[\w.@-]+$/.test(s) ? s : `'${s.replace(/'/g, "'\\''")}'`;
|
|
15185
|
+
}
|
|
15186
|
+
|
|
15094
15187
|
// ../daemon/src/agent/modes.ts
|
|
15095
15188
|
var READ_ONLY_MODE_IDS = ["plan", "read-only"];
|
|
15096
15189
|
function agentModeFor(spec, mode, available) {
|
|
@@ -15117,19 +15210,19 @@ function orderPlanOptions(options) {
|
|
|
15117
15210
|
}
|
|
15118
15211
|
|
|
15119
15212
|
// ../daemon/src/agent/origins.ts
|
|
15120
|
-
import { existsSync as
|
|
15213
|
+
import { existsSync as existsSync11, readdirSync as readdirSync4, readFileSync as readFileSync10, statSync as statSync3 } from "fs";
|
|
15121
15214
|
import { homedir as homedir4 } from "os";
|
|
15122
|
-
import { basename as basename3, join as
|
|
15215
|
+
import { basename as basename3, join as join9 } from "path";
|
|
15123
15216
|
function commandFolders(spec, cwd, home = homedir4()) {
|
|
15124
15217
|
if (spec.id === "claude") {
|
|
15125
15218
|
return [
|
|
15126
|
-
{ origin: "project", skills:
|
|
15127
|
-
{ origin: "user", skills:
|
|
15128
|
-
...pluginPaths(spec.meta).map((p) => ({ origin: "plugin", skills:
|
|
15219
|
+
{ origin: "project", skills: join9(cwd, ".claude", "skills"), commands: join9(cwd, ".claude", "commands") },
|
|
15220
|
+
{ origin: "user", skills: join9(home, ".claude", "skills"), commands: join9(home, ".claude", "commands") },
|
|
15221
|
+
...pluginPaths(spec.meta).map((p) => ({ origin: "plugin", skills: join9(p, "skills"), commands: join9(p, "commands") }))
|
|
15129
15222
|
];
|
|
15130
15223
|
}
|
|
15131
15224
|
if (spec.id === "codex")
|
|
15132
|
-
return [{ origin: "user", commands:
|
|
15225
|
+
return [{ origin: "user", commands: join9(home, ".codex", "prompts") }];
|
|
15133
15226
|
return [];
|
|
15134
15227
|
}
|
|
15135
15228
|
function readCommandOrigins(folders) {
|
|
@@ -15169,15 +15262,15 @@ function pluginPaths(meta) {
|
|
|
15169
15262
|
}
|
|
15170
15263
|
function skillNames(dir) {
|
|
15171
15264
|
return entries2(dir).flatMap((e) => {
|
|
15172
|
-
const file =
|
|
15173
|
-
if (!
|
|
15265
|
+
const file = join9(dir, e, "SKILL.md");
|
|
15266
|
+
if (!existsSync11(file))
|
|
15174
15267
|
return [];
|
|
15175
15268
|
return [frontMatterName(file) ?? e];
|
|
15176
15269
|
});
|
|
15177
15270
|
}
|
|
15178
15271
|
function commandNames(dir) {
|
|
15179
15272
|
return entries2(dir).flatMap((e) => {
|
|
15180
|
-
const path =
|
|
15273
|
+
const path = join9(dir, e);
|
|
15181
15274
|
if (e.endsWith(".md"))
|
|
15182
15275
|
return [basename3(e, ".md")];
|
|
15183
15276
|
return isDir(path) ? commandNames(path) : [];
|
|
@@ -15185,7 +15278,7 @@ function commandNames(dir) {
|
|
|
15185
15278
|
}
|
|
15186
15279
|
function frontMatterName(file) {
|
|
15187
15280
|
try {
|
|
15188
|
-
const text =
|
|
15281
|
+
const text = readFileSync10(file, "utf8");
|
|
15189
15282
|
if (!text.startsWith("---"))
|
|
15190
15283
|
return null;
|
|
15191
15284
|
const end = text.indexOf(`
|
|
@@ -15199,7 +15292,7 @@ function frontMatterName(file) {
|
|
|
15199
15292
|
}
|
|
15200
15293
|
}
|
|
15201
15294
|
function entries2(dir) {
|
|
15202
|
-
if (!
|
|
15295
|
+
if (!existsSync11(dir))
|
|
15203
15296
|
return [];
|
|
15204
15297
|
try {
|
|
15205
15298
|
return readdirSync4(dir).filter((e) => !e.startsWith("."));
|
|
@@ -15249,10 +15342,10 @@ function unformatOutput(output) {
|
|
|
15249
15342
|
import { isAbsolute as isAbsolute3, resolve as resolve4 } from "path";
|
|
15250
15343
|
|
|
15251
15344
|
// ../daemon/src/agent/acp/background.ts
|
|
15252
|
-
import { existsSync as
|
|
15345
|
+
import { existsSync as existsSync12, statSync as statSync4 } from "fs";
|
|
15253
15346
|
import { open as open2 } from "fs/promises";
|
|
15254
15347
|
import { homedir as homedir5 } from "os";
|
|
15255
|
-
import { basename as basename4, dirname as
|
|
15348
|
+
import { basename as basename4, dirname as dirname5, join as join10 } from "path";
|
|
15256
15349
|
var STARTED = /Command running in background with ID: (\S+)\. Output is being written to: (\S+)\./;
|
|
15257
15350
|
function backgroundStart(input, output) {
|
|
15258
15351
|
const flag = input && typeof input === "object" ? input.run_in_background : undefined;
|
|
@@ -15265,15 +15358,15 @@ function spawnDetached(output) {
|
|
|
15265
15358
|
return output.includes("Async agent launched successfully");
|
|
15266
15359
|
}
|
|
15267
15360
|
function claudeConfigDir() {
|
|
15268
|
-
return process.env.CLAUDE_CONFIG_DIR ||
|
|
15361
|
+
return process.env.CLAUDE_CONFIG_DIR || join10(homedir5(), ".claude");
|
|
15269
15362
|
}
|
|
15270
15363
|
function sessionLogFor(file, configDir = claudeConfigDir()) {
|
|
15271
|
-
const tasks =
|
|
15364
|
+
const tasks = dirname5(file);
|
|
15272
15365
|
if (basename4(tasks) !== "tasks")
|
|
15273
15366
|
return null;
|
|
15274
|
-
const session =
|
|
15275
|
-
const path =
|
|
15276
|
-
return
|
|
15367
|
+
const session = dirname5(tasks);
|
|
15368
|
+
const path = join10(configDir, "projects", basename4(dirname5(session)), `${basename4(session)}.jsonl`);
|
|
15369
|
+
return existsSync12(path) ? path : null;
|
|
15277
15370
|
}
|
|
15278
15371
|
function taskEnd(text, toolId) {
|
|
15279
15372
|
const at = text.indexOf(`<tool-use-id>${toolId}</tool-use-id>`);
|
|
@@ -16187,11 +16280,11 @@ ${a.text}
|
|
|
16187
16280
|
}
|
|
16188
16281
|
|
|
16189
16282
|
// ../daemon/src/agent/transcript.ts
|
|
16190
|
-
import { existsSync as
|
|
16283
|
+
import { existsSync as existsSync13, readFileSync as readFileSync11 } from "fs";
|
|
16191
16284
|
import { appendFile } from "fs/promises";
|
|
16192
|
-
import { join as
|
|
16285
|
+
import { join as join11 } from "path";
|
|
16193
16286
|
function transcriptPathFor(transcriptsDir, worktreeId) {
|
|
16194
|
-
return
|
|
16287
|
+
return join11(transcriptsDir, `${worktreeId}.jsonl`);
|
|
16195
16288
|
}
|
|
16196
16289
|
function coalesce(entries) {
|
|
16197
16290
|
const out = [];
|
|
@@ -16214,6 +16307,24 @@ function coalesce(entries) {
|
|
|
16214
16307
|
}
|
|
16215
16308
|
return out;
|
|
16216
16309
|
}
|
|
16310
|
+
var NOT_THE_TURNS = new Set(["usage", "session-info", "user-message", "fix-asked"]);
|
|
16311
|
+
function sealOpenTurn(entries) {
|
|
16312
|
+
let reason = null;
|
|
16313
|
+
let ts = 0;
|
|
16314
|
+
for (let i = entries.length - 1;i >= 0; i--) {
|
|
16315
|
+
const e = entries[i].event;
|
|
16316
|
+
if ("ts" in e && typeof e.ts === "number")
|
|
16317
|
+
ts = Math.max(ts, e.ts);
|
|
16318
|
+
if (e.type === "turn-end")
|
|
16319
|
+
return null;
|
|
16320
|
+
if (e.type === "turn-start")
|
|
16321
|
+
return { type: "turn-end", stopReason: reason ?? "lost", ts };
|
|
16322
|
+
if (NOT_THE_TURNS.has(e.type))
|
|
16323
|
+
continue;
|
|
16324
|
+
reason ??= e.type === "agent-auth-required" ? "auth" : e.type === "agent-error" ? "failed" : "lost";
|
|
16325
|
+
}
|
|
16326
|
+
return null;
|
|
16327
|
+
}
|
|
16217
16328
|
function parseTranscript(text, tag) {
|
|
16218
16329
|
const out = [];
|
|
16219
16330
|
let torn = 0;
|
|
@@ -16245,7 +16356,7 @@ class Transcript {
|
|
|
16245
16356
|
this.seq = (this.entries.at(-1)?.seq ?? -1) + 1;
|
|
16246
16357
|
}
|
|
16247
16358
|
read() {
|
|
16248
|
-
return
|
|
16359
|
+
return existsSync13(this.path) ? parseTranscript(readFileSync11(this.path, "utf8"), this.tag) : [];
|
|
16249
16360
|
}
|
|
16250
16361
|
append(event) {
|
|
16251
16362
|
const entry = { seq: this.seq++, event };
|
|
@@ -16458,6 +16569,9 @@ function toContent(form, answers) {
|
|
|
16458
16569
|
// ../daemon/src/agent/acp/ratelimit.ts
|
|
16459
16570
|
var RATE_LIMIT_META = "_claude/rateLimit";
|
|
16460
16571
|
var STATUSES = new Set(["allowed", "allowed_warning", "rejected"]);
|
|
16572
|
+
var WINDOW_KEYS = ["five_hour", "seven_day", "seven_day_overage_included"];
|
|
16573
|
+
var isWindowKey = (v) => WINDOW_KEYS.includes(v);
|
|
16574
|
+
var hasWindow = (windows) => WINDOW_KEYS.some((key) => windows[key]);
|
|
16461
16575
|
var num = (v) => typeof v === "number" && Number.isFinite(v) ? v : undefined;
|
|
16462
16576
|
function window(v) {
|
|
16463
16577
|
const w = v;
|
|
@@ -16479,18 +16593,17 @@ function parseRateLimit(meta, now) {
|
|
|
16479
16593
|
const binding = typeof info.rateLimitType === "string" ? info.rateLimitType : undefined;
|
|
16480
16594
|
const unified = info.unifiedWindows ?? undefined;
|
|
16481
16595
|
const windows = {};
|
|
16482
|
-
const
|
|
16483
|
-
|
|
16484
|
-
|
|
16485
|
-
|
|
16486
|
-
|
|
16487
|
-
|
|
16488
|
-
if (!fiveHour && !sevenDay && (binding === "five_hour" || binding === "seven_day")) {
|
|
16596
|
+
for (const key of WINDOW_KEYS) {
|
|
16597
|
+
const w = window(unified?.[key]);
|
|
16598
|
+
if (w)
|
|
16599
|
+
windows[key] = w;
|
|
16600
|
+
}
|
|
16601
|
+
if (!hasWindow(windows) && isWindowKey(binding)) {
|
|
16489
16602
|
const top = window({ utilization: info.utilization, resetsAt: info.resetsAt });
|
|
16490
16603
|
if (top)
|
|
16491
16604
|
windows[binding] = top;
|
|
16492
16605
|
}
|
|
16493
|
-
if (!windows
|
|
16606
|
+
if (!hasWindow(windows))
|
|
16494
16607
|
return null;
|
|
16495
16608
|
return { status, ...binding ? { binding } : {}, windows, at: now };
|
|
16496
16609
|
}
|
|
@@ -16525,9 +16638,10 @@ class AcpSession {
|
|
|
16525
16638
|
status = "idle";
|
|
16526
16639
|
queue = [];
|
|
16527
16640
|
steered = [];
|
|
16641
|
+
steerMark;
|
|
16642
|
+
streamingId;
|
|
16528
16643
|
refused = null;
|
|
16529
|
-
|
|
16530
|
-
interrupted = false;
|
|
16644
|
+
turn = null;
|
|
16531
16645
|
stopped = false;
|
|
16532
16646
|
holds = 0;
|
|
16533
16647
|
get held() {
|
|
@@ -16557,6 +16671,7 @@ class AcpSession {
|
|
|
16557
16671
|
...d.claudeConfigDir !== undefined ? { configDir: d.claudeConfigDir } : {}
|
|
16558
16672
|
});
|
|
16559
16673
|
this.seq = nextNumbers(this.log.entries.map(({ event }) => event.type === "user-message" ? event.attachments : undefined));
|
|
16674
|
+
const seal = sealOpenTurn(this.log.entries);
|
|
16560
16675
|
const open = new Set;
|
|
16561
16676
|
for (const { event } of this.log.entries) {
|
|
16562
16677
|
if (event.type === "agent-question" || event.type === "agent-permission")
|
|
@@ -16597,6 +16712,10 @@ class AcpSession {
|
|
|
16597
16712
|
ts: Date.now()
|
|
16598
16713
|
});
|
|
16599
16714
|
}
|
|
16715
|
+
if (seal) {
|
|
16716
|
+
log.info(d.worktreeId, `sealed a turn left open: ${seal.stopReason}`);
|
|
16717
|
+
this.emit(seal);
|
|
16718
|
+
}
|
|
16600
16719
|
if (this.openHandoffs.size > 0)
|
|
16601
16720
|
this.syncStatus();
|
|
16602
16721
|
}
|
|
@@ -16707,6 +16826,19 @@ class AcpSession {
|
|
|
16707
16826
|
this.status = s;
|
|
16708
16827
|
this.d.onStatus(s);
|
|
16709
16828
|
}
|
|
16829
|
+
get running() {
|
|
16830
|
+
return this.turn !== null;
|
|
16831
|
+
}
|
|
16832
|
+
get stopping() {
|
|
16833
|
+
return this.turn?.stopping ?? false;
|
|
16834
|
+
}
|
|
16835
|
+
setStopping(on) {
|
|
16836
|
+
const turn = this.turn;
|
|
16837
|
+
if (!turn || turn.stopping === on)
|
|
16838
|
+
return;
|
|
16839
|
+
turn.stopping = on;
|
|
16840
|
+
this.d.onStopping?.();
|
|
16841
|
+
}
|
|
16710
16842
|
send(text, opts = {}) {
|
|
16711
16843
|
if (this.stopped)
|
|
16712
16844
|
return log.warn(this.d.worktreeId, "send after close dropped");
|
|
@@ -16716,6 +16848,11 @@ class AcpSession {
|
|
|
16716
16848
|
this.post(text, opts);
|
|
16717
16849
|
}
|
|
16718
16850
|
post(text, opts = {}) {
|
|
16851
|
+
const steer = this.deliver(text, opts);
|
|
16852
|
+
if (steer)
|
|
16853
|
+
fireAndForget(this.d.worktreeId, steer, "agent steer");
|
|
16854
|
+
}
|
|
16855
|
+
deliver(text, opts = {}) {
|
|
16719
16856
|
const { context, attachments, asked } = opts;
|
|
16720
16857
|
const item = {
|
|
16721
16858
|
text,
|
|
@@ -16728,10 +16865,11 @@ class AcpSession {
|
|
|
16728
16865
|
item.recorded = { attachments: [] };
|
|
16729
16866
|
}
|
|
16730
16867
|
this.d.attachments.uploads.hold(uploadIds(attachments));
|
|
16731
|
-
if ((this.running || this.own) && !this.
|
|
16732
|
-
return
|
|
16868
|
+
if ((this.running || this.own) && !this.turn?.stopping && !this.held && this.live?.conn.steering) {
|
|
16869
|
+
return this.steer(item);
|
|
16733
16870
|
}
|
|
16734
16871
|
this.enqueue(item);
|
|
16872
|
+
return;
|
|
16735
16873
|
}
|
|
16736
16874
|
enqueue(item) {
|
|
16737
16875
|
this.queue.push(item);
|
|
@@ -16754,9 +16892,10 @@ class AcpSession {
|
|
|
16754
16892
|
async steer(item) {
|
|
16755
16893
|
item.recorded ??= await this.record(item);
|
|
16756
16894
|
const live = this.live;
|
|
16757
|
-
if (!live || !(this.running || this.own) || this.
|
|
16895
|
+
if (!live || !(this.running || this.own) || this.turn?.stopping)
|
|
16758
16896
|
return this.enqueue(item);
|
|
16759
16897
|
this.steered.push(item);
|
|
16898
|
+
this.steerMark = this.streamingId;
|
|
16760
16899
|
let outcome;
|
|
16761
16900
|
try {
|
|
16762
16901
|
outcome = steerOutcome(await live.conn.ctx.request(STEER_METHOD, {
|
|
@@ -16787,6 +16926,13 @@ class AcpSession {
|
|
|
16787
16926
|
if (this.live === live)
|
|
16788
16927
|
preempted(live.tools);
|
|
16789
16928
|
}
|
|
16929
|
+
answered() {
|
|
16930
|
+
this.steered = [];
|
|
16931
|
+
if (!this.turn?.stopping || !this.queue.some((q) => q.handedBack))
|
|
16932
|
+
return;
|
|
16933
|
+
this.queue = this.queue.filter((q) => !q.handedBack);
|
|
16934
|
+
this.queueChanged();
|
|
16935
|
+
}
|
|
16790
16936
|
unsteer(item) {
|
|
16791
16937
|
const at = this.steered.indexOf(item);
|
|
16792
16938
|
if (at >= 0)
|
|
@@ -16803,8 +16949,10 @@ class AcpSession {
|
|
|
16803
16949
|
}
|
|
16804
16950
|
return;
|
|
16805
16951
|
}
|
|
16806
|
-
this.
|
|
16952
|
+
this.setStopping(true);
|
|
16807
16953
|
if (this.steered.length > 0) {
|
|
16954
|
+
for (const item of this.steered)
|
|
16955
|
+
item.handedBack = true;
|
|
16808
16956
|
this.queue.unshift(...this.steered);
|
|
16809
16957
|
this.steered = [];
|
|
16810
16958
|
this.queueChanged();
|
|
@@ -16829,7 +16977,7 @@ class AcpSession {
|
|
|
16829
16977
|
}
|
|
16830
16978
|
async drain() {
|
|
16831
16979
|
this.endOwn("end_turn");
|
|
16832
|
-
this.
|
|
16980
|
+
this.turn = { open: false, stopping: false };
|
|
16833
16981
|
this.clearReaper();
|
|
16834
16982
|
this.setStatus("working");
|
|
16835
16983
|
let item = null;
|
|
@@ -16837,44 +16985,69 @@ class AcpSession {
|
|
|
16837
16985
|
while (this.queue.length > 0 && !this.held) {
|
|
16838
16986
|
item = this.queue.shift();
|
|
16839
16987
|
this.queueChanged();
|
|
16988
|
+
const turn = { open: false, stopping: false };
|
|
16989
|
+
this.turn = turn;
|
|
16840
16990
|
try {
|
|
16841
16991
|
await this.runTurn(item);
|
|
16842
16992
|
} catch (e) {
|
|
16843
|
-
if (!
|
|
16993
|
+
if (!turn.stopping)
|
|
16844
16994
|
throw e;
|
|
16845
|
-
|
|
16995
|
+
if (turn.open)
|
|
16996
|
+
this.endTurn("interrupted");
|
|
16997
|
+
else
|
|
16998
|
+
this.emit({ type: "agent-error", message: this.describe(e), ts: Date.now() });
|
|
16846
16999
|
}
|
|
16847
|
-
this.interrupted = false;
|
|
16848
17000
|
this.steered = [];
|
|
17001
|
+
for (const q of this.queue)
|
|
17002
|
+
q.handedBack = false;
|
|
17003
|
+
this.setStopping(false);
|
|
16849
17004
|
}
|
|
16850
17005
|
this.setStatus(this.openHandoffs.size > 0 ? "waiting" : "idle");
|
|
16851
17006
|
} catch (e) {
|
|
16852
|
-
|
|
17007
|
+
const aws = this.conn && AWS_EXPIRED_RE.test(this.describe(e)) ? this.awsAuth() : null;
|
|
17008
|
+
if (this.conn && (aws || isAuthRequired(e) || this.rejectedCredential(e))) {
|
|
16853
17009
|
const rejected = !isAuthRequired(e);
|
|
16854
|
-
if (rejected)
|
|
17010
|
+
if (rejected && !aws)
|
|
16855
17011
|
this.emit({ type: "agent-error", message: this.describe(e), ts: Date.now() });
|
|
16856
17012
|
this.refused = item;
|
|
16857
17013
|
this.emit({
|
|
16858
17014
|
type: "agent-auth-required",
|
|
16859
17015
|
agent: this.conn.spec.id,
|
|
16860
17016
|
agentName: this.conn.spec.name,
|
|
16861
|
-
...
|
|
17017
|
+
...aws ? {
|
|
17018
|
+
methods: awsMethods(aws, this.conn.spec.id === "claude"),
|
|
17019
|
+
provider: "aws",
|
|
17020
|
+
detail: this.describe(e),
|
|
17021
|
+
...aws.refresh ? { refresh: aws.refresh } : {}
|
|
17022
|
+
} : this.offeredMethods(this.conn),
|
|
16862
17023
|
...rejected ? { rejected: true } : {},
|
|
16863
17024
|
ts: Date.now()
|
|
16864
17025
|
});
|
|
17026
|
+
this.endTurn("auth");
|
|
16865
17027
|
this.setStatus("error");
|
|
16866
17028
|
} else {
|
|
16867
17029
|
this.emit({ type: "agent-error", message: this.describe(e), ts: Date.now() });
|
|
17030
|
+
this.endTurn("failed");
|
|
16868
17031
|
this.setStatus("error");
|
|
16869
17032
|
fireAndForget(this.d.worktreeId, this.dropConn("error"), "drop agent after error");
|
|
16870
17033
|
}
|
|
16871
17034
|
} finally {
|
|
16872
|
-
this.interrupted = false;
|
|
16873
17035
|
this.steered = [];
|
|
16874
|
-
this.
|
|
17036
|
+
for (const q of this.queue)
|
|
17037
|
+
q.handedBack = false;
|
|
17038
|
+
this.setStopping(false);
|
|
17039
|
+
this.turn = null;
|
|
16875
17040
|
this.maybeArmReaper();
|
|
16876
17041
|
}
|
|
16877
17042
|
}
|
|
17043
|
+
endTurn(stopReason) {
|
|
17044
|
+
const turn = this.turn;
|
|
17045
|
+
if (!turn?.open)
|
|
17046
|
+
return;
|
|
17047
|
+
turn.open = false;
|
|
17048
|
+
this.emit({ type: "turn-end", stopReason, ts: Date.now() });
|
|
17049
|
+
this.setStopping(false);
|
|
17050
|
+
}
|
|
16878
17051
|
async ask(system, prompt, opts = {}) {
|
|
16879
17052
|
if (this.stopped)
|
|
16880
17053
|
return null;
|
|
@@ -16905,6 +17078,8 @@ class AcpSession {
|
|
|
16905
17078
|
}
|
|
16906
17079
|
async authenticate(methodId, apiKey) {
|
|
16907
17080
|
const conn = await this.ensureConn("login");
|
|
17081
|
+
if (methodId === AWS_LOGIN_METHOD || methodId === AWS_REFRESH_METHOD)
|
|
17082
|
+
return this.authenticateAws(methodId);
|
|
16908
17083
|
const method = conn.authMethods.find((m) => m.id === methodId);
|
|
16909
17084
|
if (!method)
|
|
16910
17085
|
throw new UserError(`${conn.spec.name} offers no login method "${methodId}"`);
|
|
@@ -16936,6 +17111,23 @@ class AcpSession {
|
|
|
16936
17111
|
this.loggedIn();
|
|
16937
17112
|
return { kind: "done" };
|
|
16938
17113
|
}
|
|
17114
|
+
async authenticateAws(methodId) {
|
|
17115
|
+
const command = awsLoginCommand(this.awsAuth().profile);
|
|
17116
|
+
if (methodId === AWS_LOGIN_METHOD) {
|
|
17117
|
+
return { kind: "terminal", run: { command: process.env.SHELL || "sh", args: ["-lc", command], env: {} } };
|
|
17118
|
+
}
|
|
17119
|
+
const file = setAwsAuthRefresh(this.claudeConfigDir(), command);
|
|
17120
|
+
log.info(this.d.worktreeId, `awsAuthRefresh set to "${command}" in ${file}`);
|
|
17121
|
+
await this.dropConn("settings changed");
|
|
17122
|
+
this.loggedIn();
|
|
17123
|
+
return { kind: "done" };
|
|
17124
|
+
}
|
|
17125
|
+
awsAuth() {
|
|
17126
|
+
return readAwsAuth(this.claudeConfigDir(), this.d.cwd);
|
|
17127
|
+
}
|
|
17128
|
+
claudeConfigDir() {
|
|
17129
|
+
return this.d.claudeConfigDir ?? claudeConfigDir();
|
|
17130
|
+
}
|
|
16939
17131
|
loggedIn() {
|
|
16940
17132
|
this.emit({ type: "agent-auth-ok", ts: Date.now() });
|
|
16941
17133
|
this.retry();
|
|
@@ -17000,12 +17192,13 @@ class AcpSession {
|
|
|
17000
17192
|
log.warn(this.d.worktreeId, "before-turn hook failed", e);
|
|
17001
17193
|
}
|
|
17002
17194
|
this.emit({ type: "turn-start", ts: Date.now() });
|
|
17195
|
+
this.turn.open = true;
|
|
17003
17196
|
const live = await this.ensureLive("a turn");
|
|
17004
17197
|
await this.applyMode(live);
|
|
17005
17198
|
await this.applyOption(live, "model");
|
|
17006
17199
|
await this.applyOption(live, "thought_level");
|
|
17007
|
-
if (this.
|
|
17008
|
-
this.
|
|
17200
|
+
if (this.turn?.stopping) {
|
|
17201
|
+
this.endTurn("interrupted");
|
|
17009
17202
|
return;
|
|
17010
17203
|
}
|
|
17011
17204
|
const carried = this.carried(live, item.recorded.attachments);
|
|
@@ -17015,7 +17208,7 @@ class AcpSession {
|
|
|
17015
17208
|
sessionId: live.sessionId,
|
|
17016
17209
|
prompt: buildPrompt(item.text, this.contextFor(item), prefix, carried)
|
|
17017
17210
|
});
|
|
17018
|
-
this.
|
|
17211
|
+
this.endTurn(mapStopReason(res.stopReason));
|
|
17019
17212
|
}
|
|
17020
17213
|
contextFor(item) {
|
|
17021
17214
|
return ambientBlock([
|
|
@@ -17285,8 +17478,15 @@ class AcpSession {
|
|
|
17285
17478
|
if (!this.running)
|
|
17286
17479
|
this.trackOwn(events);
|
|
17287
17480
|
for (const ev of events) {
|
|
17288
|
-
if (ev.type === "
|
|
17289
|
-
this.
|
|
17481
|
+
if (ev.type === "tool-start")
|
|
17482
|
+
this.answered();
|
|
17483
|
+
else if (ev.type === "text-delta") {
|
|
17484
|
+
if (ev.messageId === undefined)
|
|
17485
|
+
this.steered = [];
|
|
17486
|
+
else if (ev.messageId !== this.steerMark)
|
|
17487
|
+
this.answered();
|
|
17488
|
+
this.streamingId = ev.messageId;
|
|
17489
|
+
}
|
|
17290
17490
|
this.emit(ev.type === "session-info" ? { ...ev, sessionId: live.sessionId } : ev);
|
|
17291
17491
|
}
|
|
17292
17492
|
}
|
|
@@ -17357,18 +17557,23 @@ class AcpSession {
|
|
|
17357
17557
|
const choice = picked ? choices.find((c) => c.id === picked) : undefined;
|
|
17358
17558
|
if (!choice)
|
|
17359
17559
|
return { outcome: { outcome: "cancelled" } };
|
|
17560
|
+
const res = { outcome: { outcome: "selected", optionId: choice.id } };
|
|
17360
17561
|
if (plan && (choice.kind === "allow_once" || choice.kind === "allow_always")) {
|
|
17361
17562
|
this.d.setMode?.(modeAfterPlan(choice.name));
|
|
17362
17563
|
if (planPath)
|
|
17363
|
-
|
|
17564
|
+
return this.sayPlanEdited(detail, planPath).then(() => res);
|
|
17364
17565
|
}
|
|
17365
|
-
return
|
|
17566
|
+
return res;
|
|
17366
17567
|
});
|
|
17367
17568
|
}
|
|
17368
17569
|
async sayPlanEdited(proposed, path) {
|
|
17369
|
-
|
|
17370
|
-
|
|
17371
|
-
|
|
17570
|
+
try {
|
|
17571
|
+
if (!await this.d.planEdited?.(path, proposed))
|
|
17572
|
+
return;
|
|
17573
|
+
await this.deliver(`I edited the plan before approving it. Build what is in ${path}, not the plan you proposed.`);
|
|
17574
|
+
} catch (e) {
|
|
17575
|
+
log.warn(this.d.worktreeId, "the edited plan was not sent", e);
|
|
17576
|
+
}
|
|
17372
17577
|
}
|
|
17373
17578
|
onElicit(params, signal) {
|
|
17374
17579
|
const live = this.live;
|
|
@@ -17399,13 +17604,14 @@ class AcpSession {
|
|
|
17399
17604
|
openAsk(card, respond, signal, headers) {
|
|
17400
17605
|
const id = randomUUID();
|
|
17401
17606
|
return new Promise((resolve) => {
|
|
17402
|
-
const settle = (outcome, reply) => {
|
|
17607
|
+
const settle = (outcome, reply, before) => {
|
|
17403
17608
|
if (!this.asks.delete(id))
|
|
17404
17609
|
return;
|
|
17405
17610
|
signal?.removeEventListener("abort", onAbort);
|
|
17406
17611
|
this.emit({ type: "agent-ask-end", id, outcome, ...recorded(reply), ts: Date.now() });
|
|
17407
17612
|
this.syncStatus();
|
|
17408
|
-
|
|
17613
|
+
const res = respond(outcome, reply);
|
|
17614
|
+
resolve(before ? before().then(() => res) : res);
|
|
17409
17615
|
};
|
|
17410
17616
|
const onAbort = () => settle("cancelled");
|
|
17411
17617
|
signal?.addEventListener("abort", onAbort, { once: true });
|
|
@@ -17419,12 +17625,21 @@ class AcpSession {
|
|
|
17419
17625
|
if (!ask)
|
|
17420
17626
|
return log.debug(this.d.worktreeId, `answer for an ask that already closed (${askId})`);
|
|
17421
17627
|
const skipped = reply.kind === "answers" && !reply.answers;
|
|
17422
|
-
|
|
17423
|
-
|
|
17424
|
-
return;
|
|
17628
|
+
const note = reply.kind === "choice" ? reply.note?.trim() : undefined;
|
|
17629
|
+
const attachments = skipped ? [] : followUp?.attachments ?? [];
|
|
17425
17630
|
const headers = ask.headers ?? [];
|
|
17426
17631
|
const text = headers.length === 1 ? `with my answer to "${headers[0]}"` : "with my answers";
|
|
17427
|
-
|
|
17632
|
+
const before = note || attachments.length ? async () => {
|
|
17633
|
+
try {
|
|
17634
|
+
if (note)
|
|
17635
|
+
await this.deliver(note);
|
|
17636
|
+
if (attachments.length)
|
|
17637
|
+
await this.deliver(text, { attachments });
|
|
17638
|
+
} catch (e) {
|
|
17639
|
+
log.warn(this.d.worktreeId, "what followed the answer did not go", e);
|
|
17640
|
+
}
|
|
17641
|
+
} : undefined;
|
|
17642
|
+
ask.settle(skipped ? "skipped" : "answered", reply, before);
|
|
17428
17643
|
}
|
|
17429
17644
|
cancelAsks(outcome = "cancelled") {
|
|
17430
17645
|
for (const ask of [...this.asks.values()])
|
|
@@ -18803,6 +19018,7 @@ function defaultAgent(wt, d, preview, onProcess) {
|
|
|
18803
19018
|
setSessionId: (id) => d.state.setSession(wt.id, id),
|
|
18804
19019
|
onEvent: (event, seq) => d.hub.emit("agent", wt.id, seq, event),
|
|
18805
19020
|
onStatus: (status) => d.hub.emit("agentStatus", wt.id, status),
|
|
19021
|
+
onStopping: () => d.hub.emit("agentStopping", wt.id),
|
|
18806
19022
|
beforeTurn: async () => d.turnStarting?.(wt.id),
|
|
18807
19023
|
onAuth: (agentId, o) => d.readiness?.observe(agentId, o),
|
|
18808
19024
|
onLimits: (agentId, limits) => d.readiness?.observeLimits(agentId, limits),
|
|
@@ -19648,8 +19864,8 @@ class RuntimeRegistry {
|
|
|
19648
19864
|
|
|
19649
19865
|
// ../daemon/src/worktrees/naming.ts
|
|
19650
19866
|
import { randomBytes as randomBytes3 } from "crypto";
|
|
19651
|
-
import { existsSync as
|
|
19652
|
-
import { join as
|
|
19867
|
+
import { existsSync as existsSync14 } from "fs";
|
|
19868
|
+
import { join as join12 } from "path";
|
|
19653
19869
|
function shortId() {
|
|
19654
19870
|
return randomBytes3(5).toString("hex");
|
|
19655
19871
|
}
|
|
@@ -19657,7 +19873,7 @@ function freeSlot(parent) {
|
|
|
19657
19873
|
for (;; ) {
|
|
19658
19874
|
const id = shortId();
|
|
19659
19875
|
const dir = `wt-${id.slice(0, 4)}`;
|
|
19660
|
-
if (!
|
|
19876
|
+
if (!existsSync14(join12(parent, dir)))
|
|
19661
19877
|
return { id, dir };
|
|
19662
19878
|
}
|
|
19663
19879
|
}
|
|
@@ -19685,6 +19901,7 @@ function variantLens(index) {
|
|
|
19685
19901
|
}
|
|
19686
19902
|
|
|
19687
19903
|
// ../daemon/src/agent/recap.ts
|
|
19904
|
+
var DAEMON_STOPS = new Set(["interrupted", "failed", "auth", "lost"]);
|
|
19688
19905
|
var REPLY_KEEP = 2000;
|
|
19689
19906
|
var CLIP = 160;
|
|
19690
19907
|
function clip(text, max = CLIP) {
|
|
@@ -19807,7 +20024,7 @@ function openAskOf(entries) {
|
|
|
19807
20024
|
}
|
|
19808
20025
|
function factsOf(turns, end, ask) {
|
|
19809
20026
|
const last = turns.at(-1);
|
|
19810
|
-
const cut = last?.stop && last.stop !== "end_turn" && last.stop
|
|
20027
|
+
const cut = last?.stop && last.stop !== "end_turn" && !DAEMON_STOPS.has(last.stop) ? last.stop : undefined;
|
|
19811
20028
|
return {
|
|
19812
20029
|
turns: Math.max(1, turns.length),
|
|
19813
20030
|
edits: turns.reduce((n, t) => n + t.edits, 0),
|
|
@@ -20114,8 +20331,8 @@ function makePlanner(agents) {
|
|
|
20114
20331
|
}
|
|
20115
20332
|
|
|
20116
20333
|
// ../daemon/src/agent/transcriptForward.ts
|
|
20117
|
-
import { existsSync as
|
|
20118
|
-
import { join as
|
|
20334
|
+
import { existsSync as existsSync15, readdirSync as readdirSync5, readFileSync as readFileSync12, renameSync as renameSync3, writeFileSync as writeFileSync7 } from "fs";
|
|
20335
|
+
import { join as join13 } from "path";
|
|
20119
20336
|
var FORWARD_STEP = "1";
|
|
20120
20337
|
var MARK = '"page';
|
|
20121
20338
|
function forwardLine(line) {
|
|
@@ -20157,22 +20374,22 @@ function forwardTranscripts(dirs, stamp) {
|
|
|
20157
20374
|
let files = 0;
|
|
20158
20375
|
let rows = 0;
|
|
20159
20376
|
for (const path of dirs.flatMap(transcriptsUnder)) {
|
|
20160
|
-
const { text, changed } = forwardText(
|
|
20377
|
+
const { text, changed } = forwardText(readFileSync12(path, "utf8"));
|
|
20161
20378
|
if (!changed)
|
|
20162
20379
|
continue;
|
|
20163
20380
|
const tmp = `${path}.tmp`;
|
|
20164
|
-
|
|
20165
|
-
|
|
20381
|
+
writeFileSync7(tmp, text);
|
|
20382
|
+
renameSync3(tmp, path);
|
|
20166
20383
|
files++;
|
|
20167
20384
|
rows += changed;
|
|
20168
20385
|
}
|
|
20169
|
-
|
|
20386
|
+
writeFileSync7(stamp, FORWARD_STEP);
|
|
20170
20387
|
if (files)
|
|
20171
20388
|
log.info("transcripts", `moved ${rows} row(s) in ${files} transcript(s) past the preview-threw row`);
|
|
20172
20389
|
}
|
|
20173
20390
|
function readStamp(stamp) {
|
|
20174
20391
|
try {
|
|
20175
|
-
return
|
|
20392
|
+
return readFileSync12(stamp, "utf8").trim();
|
|
20176
20393
|
} catch {
|
|
20177
20394
|
return null;
|
|
20178
20395
|
}
|
|
@@ -20181,10 +20398,10 @@ function transcriptsUnder(dir) {
|
|
|
20181
20398
|
const found = [];
|
|
20182
20399
|
for (const entry of readdirSync5(dir, { withFileTypes: true })) {
|
|
20183
20400
|
if (entry.isFile() && entry.name.endsWith(".jsonl"))
|
|
20184
|
-
found.push(
|
|
20401
|
+
found.push(join13(dir, entry.name));
|
|
20185
20402
|
else if (entry.isDirectory()) {
|
|
20186
|
-
const inner =
|
|
20187
|
-
if (
|
|
20403
|
+
const inner = join13(dir, entry.name, "transcript.jsonl");
|
|
20404
|
+
if (existsSync15(inner))
|
|
20188
20405
|
found.push(inner);
|
|
20189
20406
|
}
|
|
20190
20407
|
}
|
|
@@ -20192,23 +20409,23 @@ function transcriptsUnder(dir) {
|
|
|
20192
20409
|
}
|
|
20193
20410
|
|
|
20194
20411
|
// ../daemon/src/core/assets.ts
|
|
20195
|
-
import { existsSync as
|
|
20196
|
-
import { join as
|
|
20412
|
+
import { existsSync as existsSync16, readdirSync as readdirSync6, rmSync as rmSync3, statSync as statSync5 } from "fs";
|
|
20413
|
+
import { join as join14, resolve as resolve5 } from "path";
|
|
20197
20414
|
function locateAssets(here, env = process.env) {
|
|
20198
|
-
const packaged =
|
|
20415
|
+
const packaged = existsSync16(join14(here, "shell", "index.html"));
|
|
20199
20416
|
return {
|
|
20200
|
-
shellDist: env.TOYON_SHELL_DIST ?? (packaged ?
|
|
20201
|
-
bridgeJs: env.TOYON_BRIDGE_JS ?? (packaged ?
|
|
20202
|
-
helperStub: packaged ?
|
|
20203
|
-
cliEntry: packaged ?
|
|
20417
|
+
shellDist: env.TOYON_SHELL_DIST ?? (packaged ? join14(here, "shell") : join14(here, "../../shell/dist")),
|
|
20418
|
+
bridgeJs: env.TOYON_BRIDGE_JS ?? (packaged ? join14(here, "bridge.js") : join14(here, "../../bridge/dist/bridge.js")),
|
|
20419
|
+
helperStub: packaged ? join14(here, "helper-stub") : join14(here, "../dist/helper-stub"),
|
|
20420
|
+
cliEntry: packaged ? join14(here, "cli.js") : join14(here, "../../cli/src/cli.ts"),
|
|
20204
20421
|
sourceRoot: packaged ? null : resolve5(here, "../../.."),
|
|
20205
|
-
packageJson: packaged ?
|
|
20206
|
-
changelog: packaged ?
|
|
20422
|
+
packageJson: packaged ? join14(here, "..", "package.json") : null,
|
|
20423
|
+
changelog: packaged ? join14(here, "CHANGELOG.md") : resolve5(here, "../../../CHANGELOG.md")
|
|
20207
20424
|
};
|
|
20208
20425
|
}
|
|
20209
20426
|
var KEEP_MS = 3 * 24 * 60 * 60 * 1000;
|
|
20210
20427
|
function pruneAssets(shellDist) {
|
|
20211
|
-
const dir =
|
|
20428
|
+
const dir = join14(shellDist, "assets");
|
|
20212
20429
|
let names;
|
|
20213
20430
|
try {
|
|
20214
20431
|
names = readdirSync6(dir);
|
|
@@ -20217,7 +20434,7 @@ function pruneAssets(shellDist) {
|
|
|
20217
20434
|
}
|
|
20218
20435
|
const found = [];
|
|
20219
20436
|
for (const name of names) {
|
|
20220
|
-
const path =
|
|
20437
|
+
const path = join14(dir, name);
|
|
20221
20438
|
try {
|
|
20222
20439
|
found.push({ path, mtime: statSync5(path).mtimeMs });
|
|
20223
20440
|
} catch {}
|
|
@@ -20662,7 +20879,7 @@ class KeepAwake {
|
|
|
20662
20879
|
}
|
|
20663
20880
|
|
|
20664
20881
|
// ../daemon/src/core/dialog.ts
|
|
20665
|
-
import { existsSync as
|
|
20882
|
+
import { existsSync as existsSync17 } from "fs";
|
|
20666
20883
|
import { homedir as homedir6 } from "os";
|
|
20667
20884
|
var PROMPTS = {
|
|
20668
20885
|
location: { prompt: "Choose where the new project goes", pick: "folder" },
|
|
@@ -20681,7 +20898,7 @@ function folderDialog() {
|
|
|
20681
20898
|
let cancelled = false;
|
|
20682
20899
|
const ask = async (start, purpose) => {
|
|
20683
20900
|
const typed = start === "~" || start.startsWith("~/") ? `${homedir6()}${start.slice(1)}` : start;
|
|
20684
|
-
const from = typed.startsWith("/") &&
|
|
20901
|
+
const from = typed.startsWith("/") && existsSync17(typed) ? typed : homedir6();
|
|
20685
20902
|
cancelled = false;
|
|
20686
20903
|
const { prompt, pick } = PROMPTS[purpose];
|
|
20687
20904
|
const p = Bun.spawn(["osascript", ...script(pick).flatMap((line) => ["-e", line]), prompt, from], {
|
|
@@ -20759,9 +20976,9 @@ class GrantCodes {
|
|
|
20759
20976
|
|
|
20760
20977
|
// ../daemon/src/core/helper.ts
|
|
20761
20978
|
import { createHash as createHash3 } from "crypto";
|
|
20762
|
-
import { existsSync as
|
|
20979
|
+
import { existsSync as existsSync18 } from "fs";
|
|
20763
20980
|
import { chmod, copyFile as copyFile3, mkdir as mkdir2, readFile as readFile2, rm, writeFile as writeFile2 } from "fs/promises";
|
|
20764
|
-
import { basename as basename5, dirname as
|
|
20981
|
+
import { basename as basename5, dirname as dirname6, join as join15 } from "path";
|
|
20765
20982
|
var EXECUTABLE = "Toyon";
|
|
20766
20983
|
function helperWanted(where) {
|
|
20767
20984
|
return where.platform === "darwin" && !where.cloud && where.port === DAEMON_DEFAULT_PORT && where.home === undefined;
|
|
@@ -20828,7 +21045,7 @@ class Helper {
|
|
|
20828
21045
|
run;
|
|
20829
21046
|
constructor(spec, run2) {
|
|
20830
21047
|
this.spec = spec;
|
|
20831
|
-
this.run = run2 ?? (async (cmd) => (await run(cmd[0], cmd.slice(1),
|
|
21048
|
+
this.run = run2 ?? (async (cmd) => (await run(cmd[0], cmd.slice(1), dirname6(spec.dir))).ok);
|
|
20832
21049
|
}
|
|
20833
21050
|
startLink() {
|
|
20834
21051
|
return this.ready ? START_LINK : null;
|
|
@@ -20840,23 +21057,23 @@ class Helper {
|
|
|
20840
21057
|
}
|
|
20841
21058
|
async write() {
|
|
20842
21059
|
const { spec } = this;
|
|
20843
|
-
if (!
|
|
21060
|
+
if (!existsSync18(spec.stub))
|
|
20844
21061
|
return "skipped";
|
|
20845
21062
|
const stubHash = createHash3("sha256").update(await readFile2(spec.stub)).digest("hex").slice(0, 16);
|
|
20846
21063
|
const { plist, script } = helperFiles(spec, stubHash);
|
|
20847
|
-
const contents =
|
|
20848
|
-
const resources =
|
|
20849
|
-
const stub =
|
|
20850
|
-
const scriptFile =
|
|
20851
|
-
if (
|
|
21064
|
+
const contents = join15(spec.dir, "Contents");
|
|
21065
|
+
const resources = join15(contents, "Resources");
|
|
21066
|
+
const stub = join15(contents, "MacOS", EXECUTABLE);
|
|
21067
|
+
const scriptFile = join15(resources, "launch.sh");
|
|
21068
|
+
if (existsSync18(stub) && existsSync18(scriptFile) && await readFile2(scriptFile, "utf8") === script)
|
|
20852
21069
|
return "kept";
|
|
20853
|
-
await mkdir2(
|
|
21070
|
+
await mkdir2(join15(contents, "MacOS"), { recursive: true });
|
|
20854
21071
|
await mkdir2(resources, { recursive: true });
|
|
20855
|
-
await writeFile2(
|
|
21072
|
+
await writeFile2(join15(contents, "Info.plist"), plist);
|
|
20856
21073
|
await writeFile2(scriptFile, script, { mode: 493 });
|
|
20857
21074
|
await copyFile3(spec.stub, stub);
|
|
20858
21075
|
await chmod(stub, 493);
|
|
20859
|
-
if (!
|
|
21076
|
+
if (!existsSync18(join15(resources, "AppIcon.icns")))
|
|
20860
21077
|
await this.drawIcon(resources);
|
|
20861
21078
|
await this.run(["xattr", "-cr", spec.dir]);
|
|
20862
21079
|
if (!await this.run(["codesign", "--force", "--deep", "-s", "-", spec.dir])) {
|
|
@@ -20867,16 +21084,16 @@ class Helper {
|
|
|
20867
21084
|
}
|
|
20868
21085
|
async drawIcon(resources) {
|
|
20869
21086
|
const svg = this.spec.icon;
|
|
20870
|
-
const tmp =
|
|
20871
|
-
const set =
|
|
21087
|
+
const tmp = join15(resources, "iconset.tmp");
|
|
21088
|
+
const set = join15(tmp, "AppIcon.iconset");
|
|
20872
21089
|
await mkdir2(set, { recursive: true });
|
|
20873
21090
|
await this.run(["qlmanage", "-t", "-s", "1024", "-o", tmp, svg]);
|
|
20874
|
-
const big =
|
|
20875
|
-
if (
|
|
21091
|
+
const big = join15(tmp, `${basename5(svg)}.png`);
|
|
21092
|
+
if (existsSync18(big)) {
|
|
20876
21093
|
for (const size of [16, 32, 64, 128, 256, 512, 1024]) {
|
|
20877
|
-
await this.run(["sips", "-z", String(size), String(size), big, "--out",
|
|
21094
|
+
await this.run(["sips", "-z", String(size), String(size), big, "--out", join15(set, `icon_${size}x${size}.png`)]);
|
|
20878
21095
|
}
|
|
20879
|
-
await this.run(["iconutil", "-c", "icns", set, "-o",
|
|
21096
|
+
await this.run(["iconutil", "-c", "icns", set, "-o", join15(resources, "AppIcon.icns")]);
|
|
20880
21097
|
}
|
|
20881
21098
|
await rm(tmp, { recursive: true, force: true });
|
|
20882
21099
|
}
|
|
@@ -21100,7 +21317,7 @@ class Origins {
|
|
|
21100
21317
|
}
|
|
21101
21318
|
|
|
21102
21319
|
// ../daemon/src/core/remoteSwitch.ts
|
|
21103
|
-
import { writeFileSync as
|
|
21320
|
+
import { writeFileSync as writeFileSync8 } from "fs";
|
|
21104
21321
|
class RemoteSwitch {
|
|
21105
21322
|
d;
|
|
21106
21323
|
constructor(d) {
|
|
@@ -21133,7 +21350,7 @@ class RemoteSwitch {
|
|
|
21133
21350
|
const accepted = acceptRemote(view, this.d.policy);
|
|
21134
21351
|
if (typeof accepted === "string")
|
|
21135
21352
|
throw new UserError(accepted);
|
|
21136
|
-
|
|
21353
|
+
writeFileSync8(this.d.file, `${JSON.stringify(accepted, null, 2)}
|
|
21137
21354
|
`);
|
|
21138
21355
|
return this.live(accepted);
|
|
21139
21356
|
}
|
|
@@ -21156,12 +21373,12 @@ import { spawn as spawn4 } from "child_process";
|
|
|
21156
21373
|
import { homedir as homedir7 } from "os";
|
|
21157
21374
|
|
|
21158
21375
|
// ../shared/src/logfile.ts
|
|
21159
|
-
import { chmodSync, existsSync as
|
|
21376
|
+
import { chmodSync, existsSync as existsSync19, openSync, renameSync as renameSync4, statSync as statSync6 } from "fs";
|
|
21160
21377
|
var LOG_ROTATE_BYTES = 10 * 1024 * 1024;
|
|
21161
21378
|
var previousLog = (path) => `${path}.1`;
|
|
21162
21379
|
function openLog(path, maxBytes = LOG_ROTATE_BYTES) {
|
|
21163
|
-
if (
|
|
21164
|
-
|
|
21380
|
+
if (existsSync19(path) && statSync6(path).size > maxBytes)
|
|
21381
|
+
renameSync4(path, previousLog(path));
|
|
21165
21382
|
const fd = openSync(path, "a", 384);
|
|
21166
21383
|
chmodSync(path, 384);
|
|
21167
21384
|
return fd;
|
|
@@ -21328,7 +21545,7 @@ class SelfWatch {
|
|
|
21328
21545
|
|
|
21329
21546
|
// ../daemon/src/core/state.ts
|
|
21330
21547
|
import { randomBytes as randomBytes6 } from "crypto";
|
|
21331
|
-
import { existsSync as
|
|
21548
|
+
import { existsSync as existsSync20, readFileSync as readFileSync13, renameSync as renameSync5, writeFileSync as writeFileSync9 } from "fs";
|
|
21332
21549
|
var TRUSTED_MAX = 16;
|
|
21333
21550
|
var DAEMON_GROUPS = "daemon";
|
|
21334
21551
|
var GROUPS_SAVE_MS = 250;
|
|
@@ -21337,11 +21554,11 @@ var empty = { repos: [], worktrees: [], sessions: {} };
|
|
|
21337
21554
|
function loadState(paths) {
|
|
21338
21555
|
ensureDirs(paths);
|
|
21339
21556
|
const STATE_FILE = paths.stateFile;
|
|
21340
|
-
if (!
|
|
21557
|
+
if (!existsSync20(STATE_FILE))
|
|
21341
21558
|
return structuredClone(empty);
|
|
21342
21559
|
let raw;
|
|
21343
21560
|
try {
|
|
21344
|
-
raw =
|
|
21561
|
+
raw = readFileSync13(STATE_FILE, "utf8");
|
|
21345
21562
|
} catch (e) {
|
|
21346
21563
|
log.error("state", `cannot read ${STATE_FILE}; starting empty`, e);
|
|
21347
21564
|
return structuredClone(empty);
|
|
@@ -21352,7 +21569,7 @@ function loadState(paths) {
|
|
|
21352
21569
|
} catch (e) {
|
|
21353
21570
|
const backup = `${STATE_FILE}.corrupt-${Date.now()}`;
|
|
21354
21571
|
try {
|
|
21355
|
-
|
|
21572
|
+
writeFileSync9(backup, raw);
|
|
21356
21573
|
} catch (be) {
|
|
21357
21574
|
log.warn("state", "could not write the corrupt-state backup", be);
|
|
21358
21575
|
}
|
|
@@ -21383,16 +21600,16 @@ function loadState(paths) {
|
|
|
21383
21600
|
}
|
|
21384
21601
|
function saveState(paths, state) {
|
|
21385
21602
|
const tmp = `${paths.stateFile}.tmp`;
|
|
21386
|
-
|
|
21387
|
-
|
|
21603
|
+
writeFileSync9(tmp, JSON.stringify(state, null, 2));
|
|
21604
|
+
renameSync5(tmp, paths.stateFile);
|
|
21388
21605
|
}
|
|
21389
21606
|
function loadOrCreateToken(paths) {
|
|
21390
21607
|
ensureDirs(paths);
|
|
21391
21608
|
const TOKEN_FILE = paths.tokenFile;
|
|
21392
|
-
if (
|
|
21393
|
-
return
|
|
21609
|
+
if (existsSync20(TOKEN_FILE))
|
|
21610
|
+
return readFileSync13(TOKEN_FILE, "utf8").trim();
|
|
21394
21611
|
const token = randomBytes6(32).toString("hex");
|
|
21395
|
-
|
|
21612
|
+
writeFileSync9(TOKEN_FILE, token, { mode: 384 });
|
|
21396
21613
|
return token;
|
|
21397
21614
|
}
|
|
21398
21615
|
|
|
@@ -21855,7 +22072,7 @@ class Tailnet {
|
|
|
21855
22072
|
}
|
|
21856
22073
|
|
|
21857
22074
|
// ../daemon/src/design/service.ts
|
|
21858
|
-
import { join as
|
|
22075
|
+
import { join as join16 } from "path";
|
|
21859
22076
|
|
|
21860
22077
|
// ../daemon/src/design/scan.ts
|
|
21861
22078
|
var COLOR = /^(#|rgba?\(|hsla?\(|oklch\(|oklab\(|lab\(|lch\(|color\(|color-mix\(|light-dark\()/i;
|
|
@@ -22305,7 +22522,7 @@ class DesignService {
|
|
|
22305
22522
|
async function readAll(root, paths) {
|
|
22306
22523
|
const out = [];
|
|
22307
22524
|
for (const path of paths) {
|
|
22308
|
-
const file = Bun.file(
|
|
22525
|
+
const file = Bun.file(join16(root, path));
|
|
22309
22526
|
if (file.size === 0 || file.size > MAX_FILE_BYTES)
|
|
22310
22527
|
continue;
|
|
22311
22528
|
try {
|
|
@@ -22420,14 +22637,14 @@ function typicalUse(classes) {
|
|
|
22420
22637
|
var normal = (s) => s.replace(/[-_]/g, "").toLowerCase();
|
|
22421
22638
|
async function loadProjectTypescript(root) {
|
|
22422
22639
|
try {
|
|
22423
|
-
return await import(
|
|
22640
|
+
return await import(join16(root, "node_modules", "typescript", "lib", "typescript.js"));
|
|
22424
22641
|
} catch {
|
|
22425
22642
|
return null;
|
|
22426
22643
|
}
|
|
22427
22644
|
}
|
|
22428
22645
|
|
|
22429
22646
|
// ../daemon/src/drafts/store.ts
|
|
22430
|
-
import { existsSync as
|
|
22647
|
+
import { existsSync as existsSync21, readFileSync as readFileSync14, renameSync as renameSync6, writeFileSync as writeFileSync10 } from "fs";
|
|
22431
22648
|
var SAVE_DELAY_MS = 1000;
|
|
22432
22649
|
|
|
22433
22650
|
class DraftStore {
|
|
@@ -22564,10 +22781,10 @@ class DraftStore {
|
|
|
22564
22781
|
}
|
|
22565
22782
|
}
|
|
22566
22783
|
function readRecord(file) {
|
|
22567
|
-
if (!
|
|
22784
|
+
if (!existsSync21(file))
|
|
22568
22785
|
return [];
|
|
22569
22786
|
try {
|
|
22570
|
-
const raw = JSON.parse(
|
|
22787
|
+
const raw = JSON.parse(readFileSync14(file, "utf8"));
|
|
22571
22788
|
return raw && typeof raw === "object" ? Object.entries(raw) : [];
|
|
22572
22789
|
} catch (e) {
|
|
22573
22790
|
log.warn("drafts", `skipped an unreadable ${file}`, e);
|
|
@@ -22577,8 +22794,8 @@ function readRecord(file) {
|
|
|
22577
22794
|
function writeAtomic(file, value) {
|
|
22578
22795
|
const tmp = `${file}.tmp`;
|
|
22579
22796
|
try {
|
|
22580
|
-
|
|
22581
|
-
|
|
22797
|
+
writeFileSync10(tmp, JSON.stringify(value));
|
|
22798
|
+
renameSync6(tmp, file);
|
|
22582
22799
|
} catch (e) {
|
|
22583
22800
|
log.error("drafts", `could not write ${file}`, e);
|
|
22584
22801
|
}
|
|
@@ -22824,13 +23041,13 @@ import { stat as stat3 } from "fs/promises";
|
|
|
22824
23041
|
import { basename as basename6, resolve as resolve7 } from "path";
|
|
22825
23042
|
|
|
22826
23043
|
// ../daemon/src/repos/browse.ts
|
|
22827
|
-
import { existsSync as
|
|
23044
|
+
import { existsSync as existsSync22, statSync as statSync7 } from "fs";
|
|
22828
23045
|
import { readdir } from "fs/promises";
|
|
22829
23046
|
import { homedir as homedir8 } from "os";
|
|
22830
|
-
import { dirname as
|
|
23047
|
+
import { dirname as dirname7, join as join17 } from "path";
|
|
22831
23048
|
var MAX_ENTRIES = 40;
|
|
22832
23049
|
function expandTilde(raw) {
|
|
22833
|
-
return raw === "~" || raw.startsWith("~/") ?
|
|
23050
|
+
return raw === "~" || raw.startsWith("~/") ? join17(homedir8(), raw.slice(1)) : raw;
|
|
22834
23051
|
}
|
|
22835
23052
|
function collapseTilde(abs) {
|
|
22836
23053
|
const home = homedir8();
|
|
@@ -22841,7 +23058,7 @@ function holdsNothing(names) {
|
|
|
22841
23058
|
}
|
|
22842
23059
|
async function describeFolder(abs) {
|
|
22843
23060
|
const path = collapseTilde(abs);
|
|
22844
|
-
if (
|
|
23061
|
+
if (existsSync22(join17(abs, ".git")))
|
|
22845
23062
|
return { path, kind: "project" };
|
|
22846
23063
|
try {
|
|
22847
23064
|
return { path, kind: holdsNothing(await readdir(abs)) ? "empty" : "folder" };
|
|
@@ -22859,11 +23076,11 @@ function describe2(typed, parent) {
|
|
|
22859
23076
|
isFile = st.isFile();
|
|
22860
23077
|
} catch {}
|
|
22861
23078
|
return {
|
|
22862
|
-
exists:
|
|
23079
|
+
exists: existsSync22(typed),
|
|
22863
23080
|
isDir,
|
|
22864
|
-
isRepo: isDir &&
|
|
23081
|
+
isRepo: isDir && existsSync22(join17(typed, ".git")),
|
|
22865
23082
|
isFile,
|
|
22866
|
-
parentExists:
|
|
23083
|
+
parentExists: existsSync22(parent)
|
|
22867
23084
|
};
|
|
22868
23085
|
}
|
|
22869
23086
|
async function browsePath(raw) {
|
|
@@ -22871,7 +23088,7 @@ async function browsePath(raw) {
|
|
|
22871
23088
|
if (!typed.startsWith("/"))
|
|
22872
23089
|
return { entries: [], target: NOWHERE };
|
|
22873
23090
|
const listing = typed.endsWith("/");
|
|
22874
|
-
const dir = listing ? typed :
|
|
23091
|
+
const dir = listing ? typed : dirname7(typed);
|
|
22875
23092
|
const prefix = listing ? "" : typed.slice(dir.length).replace(/^\//, "").toLowerCase();
|
|
22876
23093
|
const target = describe2(listing ? typed.replace(/\/+$/, "") : typed, dir);
|
|
22877
23094
|
let found;
|
|
@@ -22879,7 +23096,7 @@ async function browsePath(raw) {
|
|
|
22879
23096
|
const listed = await readdir(dir, { withFileTypes: true });
|
|
22880
23097
|
found = listed.map((e) => ({
|
|
22881
23098
|
name: e.name,
|
|
22882
|
-
isFile: e.isSymbolicLink() ? isFileAt(
|
|
23099
|
+
isFile: e.isSymbolicLink() ? isFileAt(join17(dir, e.name)) : e.isFile() ? true : e.isDirectory() ? false : null
|
|
22883
23100
|
})).filter((e) => e.isFile !== null);
|
|
22884
23101
|
} catch {
|
|
22885
23102
|
return { entries: [], target };
|
|
@@ -22890,8 +23107,8 @@ async function browsePath(raw) {
|
|
|
22890
23107
|
continue;
|
|
22891
23108
|
if (!name.toLowerCase().startsWith(prefix))
|
|
22892
23109
|
continue;
|
|
22893
|
-
const abs =
|
|
22894
|
-
entries.push({ path: collapseTilde(abs), name, isRepo: !isFile &&
|
|
23110
|
+
const abs = join17(dir, name);
|
|
23111
|
+
entries.push({ path: collapseTilde(abs), name, isRepo: !isFile && existsSync22(join17(abs, ".git")), isFile });
|
|
22895
23112
|
}
|
|
22896
23113
|
const rank = (e) => e.isRepo ? 0 : e.isFile ? 2 : 1;
|
|
22897
23114
|
entries.sort((a, b) => rank(a) - rank(b) || a.name.localeCompare(b.name));
|
|
@@ -23014,7 +23231,7 @@ function withFetchLock(repoPath, fn) {
|
|
|
23014
23231
|
var fileLockKey = (absPath) => `file:${absPath}`;
|
|
23015
23232
|
|
|
23016
23233
|
// ../daemon/src/git/status.ts
|
|
23017
|
-
import { join as
|
|
23234
|
+
import { join as join18 } from "path";
|
|
23018
23235
|
async function treeFingerprint(worktreePath) {
|
|
23019
23236
|
const [head, diff, untracked] = await Promise.all([
|
|
23020
23237
|
git(worktreePath, "rev-parse", "HEAD"),
|
|
@@ -23024,7 +23241,7 @@ async function treeFingerprint(worktreePath) {
|
|
|
23024
23241
|
const others = await Promise.all(untracked.out.split(`
|
|
23025
23242
|
`).filter(Boolean).map(async (p) => {
|
|
23026
23243
|
try {
|
|
23027
|
-
const f = Bun.file(
|
|
23244
|
+
const f = Bun.file(join18(worktreePath, p));
|
|
23028
23245
|
const body = f.size > 2000000 ? String(f.size) : Bun.hash(await f.arrayBuffer()).toString(36);
|
|
23029
23246
|
return `${p}:${body}`;
|
|
23030
23247
|
} catch {
|
|
@@ -23109,7 +23326,7 @@ async function numstat(worktreePath, ...range) {
|
|
|
23109
23326
|
}
|
|
23110
23327
|
async function untrackedLines(worktreePath, file, budget) {
|
|
23111
23328
|
try {
|
|
23112
|
-
const f = Bun.file(
|
|
23329
|
+
const f = Bun.file(join18(worktreePath, file));
|
|
23113
23330
|
if (f.size > 2000000 || f.size > budget.left)
|
|
23114
23331
|
return {};
|
|
23115
23332
|
budget.left -= f.size;
|
|
@@ -23822,7 +24039,7 @@ class OpenService {
|
|
|
23822
24039
|
async grant(path, size, mtimeMs) {
|
|
23823
24040
|
const name = basename6(path);
|
|
23824
24041
|
if (this.d.refused.some((r) => within2(path, canonical(resolve7(r))))) {
|
|
23825
|
-
throw new UserError(`${name} is
|
|
24042
|
+
throw new UserError(`${name} is Toyon's own state, which the daemon keeps itself`);
|
|
23826
24043
|
}
|
|
23827
24044
|
const id = shortId();
|
|
23828
24045
|
if (size > FILE_MAX_CHARS) {
|
|
@@ -24215,9 +24432,9 @@ class AfterLand {
|
|
|
24215
24432
|
}
|
|
24216
24433
|
|
|
24217
24434
|
// ../daemon/src/repos/registry.ts
|
|
24218
|
-
import { existsSync as
|
|
24435
|
+
import { existsSync as existsSync26, mkdirSync as mkdirSync8, rmSync as rmSync4, writeFileSync as writeFileSync11 } from "fs";
|
|
24219
24436
|
import { homedir as homedir10 } from "os";
|
|
24220
|
-
import { basename as basename8, dirname as
|
|
24437
|
+
import { basename as basename8, dirname as dirname9, join as join22 } from "path";
|
|
24221
24438
|
|
|
24222
24439
|
// ../daemon/src/git/base.ts
|
|
24223
24440
|
async function resolveBase(repoPath, defaultBranch, route) {
|
|
@@ -24228,8 +24445,8 @@ async function resolveBase(repoPath, defaultBranch, route) {
|
|
|
24228
24445
|
}
|
|
24229
24446
|
|
|
24230
24447
|
// ../daemon/src/repos/config.ts
|
|
24231
|
-
import { closeSync, existsSync as
|
|
24232
|
-
import { join as
|
|
24448
|
+
import { closeSync, existsSync as existsSync23, openSync as openSync2, readdirSync as readdirSync7, readFileSync as readFileSync15, readSync, statSync as statSync8 } from "fs";
|
|
24449
|
+
import { join as join19 } from "path";
|
|
24233
24450
|
|
|
24234
24451
|
// ../../node_modules/.bun/jsonc-parser@3.3.1/node_modules/jsonc-parser/lib/esm/impl/scanner.js
|
|
24235
24452
|
function createScanner(text, ignoreTrivia = false) {
|
|
@@ -25593,7 +25810,7 @@ function applyEdits(text, edits) {
|
|
|
25593
25810
|
|
|
25594
25811
|
// ../daemon/src/repos/config.ts
|
|
25595
25812
|
var PLACES = [CONFIG_FILES.folder, CONFIG_FILES.root];
|
|
25596
|
-
var present = (repoPath, place) => [place.shared, place.local].filter((rel) =>
|
|
25813
|
+
var present = (repoPath, place) => [place.shared, place.local].filter((rel) => existsSync23(join19(repoPath, rel)));
|
|
25597
25814
|
var isObject2 = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
|
|
25598
25815
|
function parseSettings(text) {
|
|
25599
25816
|
const errors = [];
|
|
@@ -25618,7 +25835,7 @@ function readConfigFile(repoPath) {
|
|
|
25618
25835
|
for (const rel of files) {
|
|
25619
25836
|
let raw;
|
|
25620
25837
|
try {
|
|
25621
|
-
raw = parseSettings(
|
|
25838
|
+
raw = parseSettings(readFileSync15(join19(repoPath, rel), "utf8"));
|
|
25622
25839
|
} catch (e) {
|
|
25623
25840
|
return { ok: false, reason: `${rel} is not valid JSON: ${e instanceof Error ? e.message : String(e)}` };
|
|
25624
25841
|
}
|
|
@@ -25677,12 +25894,12 @@ function configTarget(repoPath, made) {
|
|
|
25677
25894
|
}
|
|
25678
25895
|
function configBody(repoPath, rel, config) {
|
|
25679
25896
|
const place = PLACES.find((p) => p.local === rel);
|
|
25680
|
-
const abs = place &&
|
|
25681
|
-
if (!abs || !
|
|
25897
|
+
const abs = place && join19(repoPath, place.shared);
|
|
25898
|
+
if (!abs || !existsSync23(abs))
|
|
25682
25899
|
return config;
|
|
25683
25900
|
let shared;
|
|
25684
25901
|
try {
|
|
25685
|
-
shared = parseSettings(
|
|
25902
|
+
shared = parseSettings(readFileSync15(abs, "utf8"));
|
|
25686
25903
|
} catch {
|
|
25687
25904
|
return config;
|
|
25688
25905
|
}
|
|
@@ -25695,7 +25912,7 @@ function configText(repoPath, rel, config) {
|
|
|
25695
25912
|
let text;
|
|
25696
25913
|
let was;
|
|
25697
25914
|
try {
|
|
25698
|
-
text =
|
|
25915
|
+
text = readFileSync15(join19(repoPath, rel), "utf8");
|
|
25699
25916
|
was = parseSettings(text);
|
|
25700
25917
|
} catch {
|
|
25701
25918
|
return fresh;
|
|
@@ -25725,9 +25942,9 @@ function detectConfig(repoPath) {
|
|
|
25725
25942
|
return { config: explicit.config, needsSetup: false };
|
|
25726
25943
|
if (explicit)
|
|
25727
25944
|
log.warn("config", `${repoPath}: ${explicit.reason}; detecting instead`);
|
|
25728
|
-
const pkgPath =
|
|
25729
|
-
if (
|
|
25730
|
-
const pkg = JSON.parse(
|
|
25945
|
+
const pkgPath = join19(repoPath, "package.json");
|
|
25946
|
+
if (existsSync23(pkgPath)) {
|
|
25947
|
+
const pkg = JSON.parse(readFileSync15(pkgPath, "utf8"));
|
|
25731
25948
|
const scripts = pkg.scripts ?? {};
|
|
25732
25949
|
const runner = detectRunner(repoPath, pkg.packageManager);
|
|
25733
25950
|
const pages = detectPages(repoPath, scripts, runner);
|
|
@@ -25748,7 +25965,7 @@ function detectConfig(repoPath) {
|
|
|
25748
25965
|
};
|
|
25749
25966
|
}
|
|
25750
25967
|
}
|
|
25751
|
-
if (
|
|
25968
|
+
if (existsSync23(join19(repoPath, "start.sh"))) {
|
|
25752
25969
|
return { config: { run: { app: "./start.sh" } }, needsSetup: true, from: "start.sh" };
|
|
25753
25970
|
}
|
|
25754
25971
|
const assumed = assumeNothingToRun(repoPath);
|
|
@@ -25791,7 +26008,7 @@ function assumeNothingToRun(repoPath) {
|
|
|
25791
26008
|
return marker && !servesPage(repoPath) ? marker : undefined;
|
|
25792
26009
|
}
|
|
25793
26010
|
function markerIn(repoPath) {
|
|
25794
|
-
const named = NO_PAGE_MARKERS.find((f) =>
|
|
26011
|
+
const named = NO_PAGE_MARKERS.find((f) => existsSync23(join19(repoPath, f)));
|
|
25795
26012
|
if (named)
|
|
25796
26013
|
return named;
|
|
25797
26014
|
let entries;
|
|
@@ -25803,12 +26020,12 @@ function markerIn(repoPath) {
|
|
|
25803
26020
|
return entries.find((f) => NO_PAGE_EXTENSIONS.some((ext) => f.endsWith(ext)));
|
|
25804
26021
|
}
|
|
25805
26022
|
function servesPage(repoPath) {
|
|
25806
|
-
if (WEB_FILES.some((f) =>
|
|
26023
|
+
if (WEB_FILES.some((f) => existsSync23(join19(repoPath, f))))
|
|
25807
26024
|
return true;
|
|
25808
|
-
if (/^web:/m.test(head(
|
|
26025
|
+
if (/^web:/m.test(head(join19(repoPath, "Procfile"))))
|
|
25809
26026
|
return true;
|
|
25810
26027
|
for (const [files, names] of WEB_DEPENDENCIES) {
|
|
25811
|
-
const text = files.map((f) => head(
|
|
26028
|
+
const text = files.map((f) => head(join19(repoPath, f))).join(`
|
|
25812
26029
|
`);
|
|
25813
26030
|
if (text.trim() && names.some((n) => mentions(text, n)))
|
|
25814
26031
|
return true;
|
|
@@ -25825,7 +26042,7 @@ function frontEndBeside(repoPath) {
|
|
|
25825
26042
|
return dirs.some((d) => {
|
|
25826
26043
|
if (!d.isDirectory() || d.name.startsWith(".") || NOT_A_PACKAGE.has(d.name))
|
|
25827
26044
|
return false;
|
|
25828
|
-
const pkg = head(
|
|
26045
|
+
const pkg = head(join19(repoPath, d.name, "package.json"));
|
|
25829
26046
|
if (!pkg)
|
|
25830
26047
|
return false;
|
|
25831
26048
|
try {
|
|
@@ -25840,7 +26057,7 @@ function mentions(text, name) {
|
|
|
25840
26057
|
return new RegExp(`(?<![\\w-])${escaped}(?![\\w-])`, "i").test(text);
|
|
25841
26058
|
}
|
|
25842
26059
|
function head(path) {
|
|
25843
|
-
if (!
|
|
26060
|
+
if (!existsSync23(path))
|
|
25844
26061
|
return "";
|
|
25845
26062
|
try {
|
|
25846
26063
|
const fd = openSync2(path, "r");
|
|
@@ -25881,11 +26098,11 @@ function isLocalDatabase(url) {
|
|
|
25881
26098
|
}
|
|
25882
26099
|
function detectServices(repoPath) {
|
|
25883
26100
|
const out = {};
|
|
25884
|
-
const compose = COMPOSE_FILES.find((f) =>
|
|
26101
|
+
const compose = COMPOSE_FILES.find((f) => existsSync23(join19(repoPath, f)));
|
|
25885
26102
|
if (compose)
|
|
25886
26103
|
out.compose = compose;
|
|
25887
26104
|
for (const file of ENV_FILES) {
|
|
25888
|
-
const text = head(
|
|
26105
|
+
const text = head(join19(repoPath, file));
|
|
25889
26106
|
if (!text)
|
|
25890
26107
|
continue;
|
|
25891
26108
|
for (const name of DB_URL_NAMES) {
|
|
@@ -25909,7 +26126,7 @@ function inferPaths(cmd, repoPath, depth = 1) {
|
|
|
25909
26126
|
return;
|
|
25910
26127
|
let dir = false;
|
|
25911
26128
|
try {
|
|
25912
|
-
dir = statSync8(
|
|
26129
|
+
dir = statSync8(join19(repoPath, clean)).isDirectory();
|
|
25913
26130
|
} catch {
|
|
25914
26131
|
return;
|
|
25915
26132
|
}
|
|
@@ -25920,25 +26137,25 @@ function inferPaths(cmd, repoPath, depth = 1) {
|
|
|
25920
26137
|
const t = tokens[i];
|
|
25921
26138
|
if (t === "cd") {
|
|
25922
26139
|
const dir = tokens[i + 1];
|
|
25923
|
-
if (dir && !dir.startsWith("-") &&
|
|
26140
|
+
if (dir && !dir.startsWith("-") && existsSync23(join19(repoPath, dir)))
|
|
25924
26141
|
add(dir);
|
|
25925
26142
|
continue;
|
|
25926
26143
|
}
|
|
25927
26144
|
if (t.startsWith("-") || t.startsWith("$"))
|
|
25928
26145
|
continue;
|
|
25929
26146
|
const mod = /^([A-Za-z_]\w*)(?:\.\w+)*:\w+$/.exec(t);
|
|
25930
|
-
if (mod?.[1] &&
|
|
26147
|
+
if (mod?.[1] && existsSync23(join19(repoPath, mod[1]))) {
|
|
25931
26148
|
add(mod[1]);
|
|
25932
26149
|
continue;
|
|
25933
26150
|
}
|
|
25934
26151
|
const rel = t.replace(/^\.\//, "");
|
|
25935
26152
|
if (rel.startsWith("/") || rel.startsWith("..") || rel.includes("="))
|
|
25936
26153
|
continue;
|
|
25937
|
-
if (!
|
|
26154
|
+
if (!existsSync23(join19(repoPath, rel)))
|
|
25938
26155
|
continue;
|
|
25939
26156
|
add(rel);
|
|
25940
26157
|
if (depth > 0 && rel.endsWith(".sh")) {
|
|
25941
|
-
for (const p of inferPaths(head(
|
|
26158
|
+
for (const p of inferPaths(head(join19(repoPath, rel)), repoPath, depth - 1))
|
|
25942
26159
|
out.add(p);
|
|
25943
26160
|
}
|
|
25944
26161
|
}
|
|
@@ -25961,31 +26178,31 @@ function procCommand(runner, script, body) {
|
|
|
25961
26178
|
return `${base}${runner === "npm" ? " --" : ""} ${flag}`;
|
|
25962
26179
|
}
|
|
25963
26180
|
function detectPages(repoPath, scripts, runner) {
|
|
25964
|
-
if (!scripts.build || !
|
|
26181
|
+
if (!scripts.build || !existsSync23(join19(repoPath, "functions")))
|
|
25965
26182
|
return null;
|
|
25966
|
-
const cfg = ["wrangler.jsonc", "wrangler.json", "wrangler.toml"].map((f) =>
|
|
26183
|
+
const cfg = ["wrangler.jsonc", "wrangler.json", "wrangler.toml"].map((f) => join19(repoPath, f)).find((f) => existsSync23(f));
|
|
25967
26184
|
if (!cfg)
|
|
25968
26185
|
return null;
|
|
25969
|
-
const out =
|
|
26186
|
+
const out = readFileSync15(cfg, "utf8").match(/pages_build_output_dir"?\s*[:=]\s*"([^"]+)"/)?.[1];
|
|
25970
26187
|
if (!out)
|
|
25971
26188
|
return null;
|
|
25972
26189
|
return { web: `${runner} run build && npx wrangler pages dev ${out} --ip 127.0.0.1 --port $PORT` };
|
|
25973
26190
|
}
|
|
25974
26191
|
function detectRunner(repoPath, packageManager) {
|
|
25975
|
-
if (
|
|
26192
|
+
if (existsSync23(join19(repoPath, "bun.lock")) || existsSync23(join19(repoPath, "bun.lockb")))
|
|
25976
26193
|
return "bun";
|
|
25977
|
-
if (
|
|
26194
|
+
if (existsSync23(join19(repoPath, "pnpm-lock.yaml")))
|
|
25978
26195
|
return "pnpm";
|
|
25979
|
-
if (
|
|
26196
|
+
if (existsSync23(join19(repoPath, "yarn.lock")) || typeof packageManager === "string" && packageManager.startsWith("yarn"))
|
|
25980
26197
|
return "yarn";
|
|
25981
26198
|
return "npm";
|
|
25982
26199
|
}
|
|
25983
26200
|
|
|
25984
26201
|
// ../daemon/src/repos/create.ts
|
|
25985
|
-
import { existsSync as
|
|
26202
|
+
import { existsSync as existsSync24, realpathSync as realpathSync2, statSync as statSync9 } from "fs";
|
|
25986
26203
|
import { appendFile as appendFile2, mkdir as mkdir3, rm as rm2 } from "fs/promises";
|
|
25987
26204
|
import { homedir as homedir9 } from "os";
|
|
25988
|
-
import { dirname as
|
|
26205
|
+
import { dirname as dirname8, join as join20, resolve as resolve8 } from "path";
|
|
25989
26206
|
function isInside(dir, parent) {
|
|
25990
26207
|
const p = parent.replace(/\/+$/, "");
|
|
25991
26208
|
return dir === p || dir.startsWith(`${p}/`);
|
|
@@ -25996,35 +26213,35 @@ function planProject(opts, home = homedir9()) {
|
|
|
25996
26213
|
throw new UserError(nameError);
|
|
25997
26214
|
const first = firstProjectsFolder(opts.parent, home);
|
|
25998
26215
|
const parent = first ?? resolveParent(opts.parent);
|
|
25999
|
-
const dir =
|
|
26000
|
-
if (
|
|
26216
|
+
const dir = join20(parent, opts.name.trim());
|
|
26217
|
+
if (existsSync24(dir))
|
|
26001
26218
|
throw new UserError(`${dir} already exists`);
|
|
26002
26219
|
return { parent, dir, makeParent: first !== null };
|
|
26003
26220
|
}
|
|
26004
26221
|
function firstProjectsFolder(raw, home) {
|
|
26005
26222
|
const typed = expandTilde(raw.trim()).replace(/\/+$/, "");
|
|
26006
|
-
if (typed !==
|
|
26223
|
+
if (typed !== join20(home, PROJECTS_FOLDER) || existsSync24(typed) || !existsSync24(home))
|
|
26007
26224
|
return null;
|
|
26008
|
-
return
|
|
26225
|
+
return join20(realpathSync2(home), PROJECTS_FOLDER);
|
|
26009
26226
|
}
|
|
26010
26227
|
function planInPlace(opts) {
|
|
26011
26228
|
const name = opts.name.trim();
|
|
26012
26229
|
if (!name || name === "." || name === ".." || name.includes("/")) {
|
|
26013
26230
|
throw new UserError(`${opts.name} is not a folder name`);
|
|
26014
26231
|
}
|
|
26015
|
-
const typed =
|
|
26016
|
-
if (!
|
|
26232
|
+
const typed = join20(resolveParent(opts.parent), name);
|
|
26233
|
+
if (!existsSync24(typed) || !statSync9(typed).isDirectory())
|
|
26017
26234
|
throw new UserError(`${typed} is not a folder`);
|
|
26018
26235
|
const dir = realpathSync2(typed);
|
|
26019
|
-
if (
|
|
26236
|
+
if (existsSync24(join20(dir, ".git")))
|
|
26020
26237
|
throw new UserError(`${dir} is already a project; open it instead`);
|
|
26021
|
-
return { parent:
|
|
26238
|
+
return { parent: dirname8(dir), dir, makeParent: false };
|
|
26022
26239
|
}
|
|
26023
26240
|
function resolveParent(raw) {
|
|
26024
26241
|
const typed = expandTilde(raw.trim());
|
|
26025
26242
|
if (!typed.startsWith("/"))
|
|
26026
26243
|
throw new UserError(`${raw} is not a folder path`);
|
|
26027
|
-
if (!
|
|
26244
|
+
if (!existsSync24(typed))
|
|
26028
26245
|
throw new UserError(`${raw} does not exist; make it first`);
|
|
26029
26246
|
if (!statSync9(typed).isDirectory())
|
|
26030
26247
|
throw new UserError(`${raw} is not a folder`);
|
|
@@ -26065,7 +26282,7 @@ async function initWithFirstCommit(dir) {
|
|
|
26065
26282
|
if (!exclude.ok)
|
|
26066
26283
|
throw new UserError(`git rev-parse failed: ${exclude.err}`);
|
|
26067
26284
|
const excludePath = resolve8(dir, exclude.out);
|
|
26068
|
-
await mkdir3(
|
|
26285
|
+
await mkdir3(dirname8(excludePath), { recursive: true });
|
|
26069
26286
|
await appendFile2(excludePath, `
|
|
26070
26287
|
${LOCAL_EXCLUDES.join(`
|
|
26071
26288
|
`)}
|
|
@@ -26105,13 +26322,13 @@ async function undoCreate(dir) {
|
|
|
26105
26322
|
}
|
|
26106
26323
|
async function undoInit(dir) {
|
|
26107
26324
|
try {
|
|
26108
|
-
await rm2(
|
|
26325
|
+
await rm2(join20(dir, ".git"), { recursive: true, force: true });
|
|
26109
26326
|
} catch (e) {
|
|
26110
26327
|
log.warn(dir, "could not take back a half-made .git", e);
|
|
26111
26328
|
}
|
|
26112
26329
|
}
|
|
26113
26330
|
async function unmakeProject(dir, made) {
|
|
26114
|
-
const target = made === "folder" ? dir :
|
|
26331
|
+
const target = made === "folder" ? dir : join20(dir, ".git");
|
|
26115
26332
|
try {
|
|
26116
26333
|
await rm2(target, { recursive: true, force: true });
|
|
26117
26334
|
} catch (e) {
|
|
@@ -26141,8 +26358,8 @@ async function ok(p, what) {
|
|
|
26141
26358
|
}
|
|
26142
26359
|
|
|
26143
26360
|
// ../daemon/src/repos/watcher.ts
|
|
26144
|
-
import { existsSync as
|
|
26145
|
-
import { basename as basename7, join as
|
|
26361
|
+
import { existsSync as existsSync25, watch } from "fs";
|
|
26362
|
+
import { basename as basename7, join as join21 } from "path";
|
|
26146
26363
|
function watchDefaultBranch(repoPath, branch, onMove) {
|
|
26147
26364
|
const last = { local: null, upstream: null };
|
|
26148
26365
|
const read = async () => {
|
|
@@ -26195,29 +26412,29 @@ function watchDefaultBranch(repoPath, branch, onMove) {
|
|
|
26195
26412
|
]);
|
|
26196
26413
|
if (stopped)
|
|
26197
26414
|
return;
|
|
26198
|
-
const gitDir = common.ok && common.out ? common.out :
|
|
26415
|
+
const gitDir = common.ok && common.out ? common.out : join21(repoPath, ".git");
|
|
26199
26416
|
tryWatch(gitDir);
|
|
26200
|
-
tryWatch(
|
|
26417
|
+
tryWatch(join21(gitDir, "refs", "heads"));
|
|
26201
26418
|
if (!remote.ok || !remote.out)
|
|
26202
26419
|
return;
|
|
26203
|
-
const remotes =
|
|
26204
|
-
const mine =
|
|
26420
|
+
const remotes = join21(gitDir, "refs", "remotes");
|
|
26421
|
+
const mine = join21(remotes, remote.out);
|
|
26205
26422
|
let inner = null;
|
|
26206
26423
|
let mid = null;
|
|
26207
26424
|
const armInner = () => {
|
|
26208
26425
|
inner?.close();
|
|
26209
|
-
inner =
|
|
26426
|
+
inner = existsSync25(mine) ? tryWatch(mine) : null;
|
|
26210
26427
|
};
|
|
26211
26428
|
const armMid = () => {
|
|
26212
26429
|
mid?.close();
|
|
26213
|
-
mid =
|
|
26430
|
+
mid = existsSync25(remotes) ? tryWatch(remotes, (_event, filename) => {
|
|
26214
26431
|
if (!filename || filename === remote.out)
|
|
26215
26432
|
armInner();
|
|
26216
26433
|
schedule();
|
|
26217
26434
|
}) : null;
|
|
26218
26435
|
armInner();
|
|
26219
26436
|
};
|
|
26220
|
-
tryWatch(
|
|
26437
|
+
tryWatch(join21(gitDir, "refs"), (_event, filename) => {
|
|
26221
26438
|
if (!filename || filename === "remotes")
|
|
26222
26439
|
armMid();
|
|
26223
26440
|
schedule();
|
|
@@ -26246,7 +26463,7 @@ function watchWorktreeDir(repoPath, onChange) {
|
|
|
26246
26463
|
}, 300);
|
|
26247
26464
|
};
|
|
26248
26465
|
const arm = (commonDir) => {
|
|
26249
|
-
const dir =
|
|
26466
|
+
const dir = join21(commonDir, "worktrees");
|
|
26250
26467
|
const armInner = () => {
|
|
26251
26468
|
inner?.close();
|
|
26252
26469
|
inner = null;
|
|
@@ -26289,7 +26506,7 @@ function watchWorktreeDir(repoPath, onChange) {
|
|
|
26289
26506
|
function watchConfigFile(repoPath, onChange) {
|
|
26290
26507
|
const atRoot = new Set([CONFIG_FILES.root.shared, CONFIG_FILES.root.local, CONFIG_DIR]);
|
|
26291
26508
|
const inDir = new Set([CONFIG_FILES.folder.shared, CONFIG_FILES.folder.local].map((rel) => basename7(rel)));
|
|
26292
|
-
const dir =
|
|
26509
|
+
const dir = join21(repoPath, CONFIG_DIR);
|
|
26293
26510
|
let timer = null;
|
|
26294
26511
|
let outer = null;
|
|
26295
26512
|
let inner = null;
|
|
@@ -26304,7 +26521,7 @@ function watchConfigFile(repoPath, onChange) {
|
|
|
26304
26521
|
const armInner = () => {
|
|
26305
26522
|
inner?.close();
|
|
26306
26523
|
inner = null;
|
|
26307
|
-
if (!
|
|
26524
|
+
if (!existsSync25(dir))
|
|
26308
26525
|
return;
|
|
26309
26526
|
try {
|
|
26310
26527
|
inner = watch(dir, (_event, filename) => {
|
|
@@ -26358,7 +26575,7 @@ class RepoRegistry {
|
|
|
26358
26575
|
}
|
|
26359
26576
|
async boot() {
|
|
26360
26577
|
const { state } = this.d;
|
|
26361
|
-
const gone = state.worktrees.filter((wt) => !
|
|
26578
|
+
const gone = state.worktrees.filter((wt) => !existsSync26(wt.path) || !state.repos.some((r) => r.id === wt.repoId));
|
|
26362
26579
|
for (const wt of gone)
|
|
26363
26580
|
await this.d.worktrees.forgetGone(wt);
|
|
26364
26581
|
for (const repo of state.repos) {
|
|
@@ -26426,7 +26643,7 @@ class RepoRegistry {
|
|
|
26426
26643
|
return `${repo.name} is set up now`;
|
|
26427
26644
|
if (main.promptedAt || main.lastTurn)
|
|
26428
26645
|
return `${repo.name} has a chat now`;
|
|
26429
|
-
if (
|
|
26646
|
+
if (existsSync26(join22(repo.path, ".claude")))
|
|
26430
26647
|
return `an agent has already run in ${repo.name}`;
|
|
26431
26648
|
if ((await statusFiles(repo.path)).length > 0 || !await treeEmpty(repo.path)) {
|
|
26432
26649
|
return `${repo.name} has files in it now`;
|
|
@@ -26507,7 +26724,7 @@ class RepoRegistry {
|
|
|
26507
26724
|
}
|
|
26508
26725
|
async register(rawPath, made) {
|
|
26509
26726
|
const path = expandTilde(rawPath);
|
|
26510
|
-
if (!
|
|
26727
|
+
if (!existsSync26(path))
|
|
26511
26728
|
throw new UserError(`${path} does not exist`);
|
|
26512
26729
|
if (!await isGitRepo(path))
|
|
26513
26730
|
throw new UserError(`${path} is not a git repository`);
|
|
@@ -26581,10 +26798,10 @@ class RepoRegistry {
|
|
|
26581
26798
|
throw new UserError(current.reason);
|
|
26582
26799
|
const was = configTarget(repo.path, !!repo.made);
|
|
26583
26800
|
const rel = configSibling(was, kind);
|
|
26584
|
-
const moved = rel !== was &&
|
|
26801
|
+
const moved = rel !== was && existsSync26(join22(repo.path, was));
|
|
26585
26802
|
if (moved && !(kind === "local" && await isTracked(repo.path, was))) {
|
|
26586
26803
|
try {
|
|
26587
|
-
rmSync4(
|
|
26804
|
+
rmSync4(join22(repo.path, was));
|
|
26588
26805
|
} catch (e) {
|
|
26589
26806
|
log.warn(repoId, `could not remove ${was}`, e);
|
|
26590
26807
|
}
|
|
@@ -26593,10 +26810,10 @@ class RepoRegistry {
|
|
|
26593
26810
|
}
|
|
26594
26811
|
if (isLocalConfigFile(rel))
|
|
26595
26812
|
await excludeFromGit(repo.path, rel);
|
|
26596
|
-
const file =
|
|
26813
|
+
const file = join22(repo.path, rel);
|
|
26597
26814
|
try {
|
|
26598
|
-
|
|
26599
|
-
|
|
26815
|
+
mkdirSync8(dirname9(file), { recursive: true });
|
|
26816
|
+
writeFileSync11(file, configText(repo.path, rel, config));
|
|
26600
26817
|
} catch (e) {
|
|
26601
26818
|
log.warn(repoId, `could not write ${rel}`, e);
|
|
26602
26819
|
}
|
|
@@ -26697,7 +26914,7 @@ class RepoRegistry {
|
|
|
26697
26914
|
}
|
|
26698
26915
|
placeConfig(repo) {
|
|
26699
26916
|
const rel = configTarget(repo.path, !!repo.made);
|
|
26700
|
-
if (isLocalConfigFile(rel) &&
|
|
26917
|
+
if (isLocalConfigFile(rel) && existsSync26(join22(repo.path, rel))) {
|
|
26701
26918
|
fireAndForget(repo.id, excludeFromGit(repo.path, rel), "exclude local settings");
|
|
26702
26919
|
}
|
|
26703
26920
|
if (repo.configFile === rel)
|
|
@@ -26789,7 +27006,7 @@ class RepoRegistry {
|
|
|
26789
27006
|
}
|
|
26790
27007
|
|
|
26791
27008
|
// ../daemon/src/routes/service.ts
|
|
26792
|
-
import { join as
|
|
27009
|
+
import { join as join23 } from "path";
|
|
26793
27010
|
|
|
26794
27011
|
// ../daemon/src/routes/fileRouters.ts
|
|
26795
27012
|
var SKIP = /(^|\/)(node_modules|dist|build|out|coverage|\.next|\.nuxt|\.output|\.svelte-kit|\.vercel|\.netlify)\//;
|
|
@@ -28002,7 +28219,7 @@ class RouteService {
|
|
|
28002
28219
|
return mergeRoutes(fileRoutes(paths, roots), code);
|
|
28003
28220
|
}
|
|
28004
28221
|
async cachedRead(root, path, had, kept, decode) {
|
|
28005
|
-
const abs =
|
|
28222
|
+
const abs = join23(root, path);
|
|
28006
28223
|
const stat = await this.fs.stat(abs);
|
|
28007
28224
|
if (!stat)
|
|
28008
28225
|
return null;
|
|
@@ -28027,7 +28244,7 @@ class RouteService {
|
|
|
28027
28244
|
}
|
|
28028
28245
|
}
|
|
28029
28246
|
async hash(root, file) {
|
|
28030
|
-
const abs =
|
|
28247
|
+
const abs = join23(root, file);
|
|
28031
28248
|
const stat = await this.fs.stat(abs);
|
|
28032
28249
|
if (!stat)
|
|
28033
28250
|
return null;
|
|
@@ -28289,7 +28506,7 @@ function isAlive(pid) {
|
|
|
28289
28506
|
}
|
|
28290
28507
|
|
|
28291
28508
|
// ../daemon/src/runtime/bridge-script.ts
|
|
28292
|
-
import { existsSync as
|
|
28509
|
+
import { existsSync as existsSync27, readFileSync as readFileSync16, statSync as statSync10 } from "fs";
|
|
28293
28510
|
var LEARNED_MAX = 8;
|
|
28294
28511
|
|
|
28295
28512
|
class BridgeScript {
|
|
@@ -28319,7 +28536,7 @@ class BridgeScript {
|
|
|
28319
28536
|
this.cache = null;
|
|
28320
28537
|
}
|
|
28321
28538
|
get() {
|
|
28322
|
-
if (!
|
|
28539
|
+
if (!existsSync27(this.path))
|
|
28323
28540
|
return "// toyon bridge not built";
|
|
28324
28541
|
const s = statSync10(this.path);
|
|
28325
28542
|
const stamp = `${s.mtimeMs}:${s.size}`;
|
|
@@ -28328,7 +28545,7 @@ class BridgeScript {
|
|
|
28328
28545
|
this.stamp = stamp;
|
|
28329
28546
|
const origins = [...this.origins, ...this.learned];
|
|
28330
28547
|
this.cache = `window.__toyonShellOrigins=${JSON.stringify(origins)};
|
|
28331
|
-
${
|
|
28548
|
+
${readFileSync16(this.path, "utf8")}`;
|
|
28332
28549
|
return this.cache;
|
|
28333
28550
|
}
|
|
28334
28551
|
}
|
|
@@ -28397,50 +28614,50 @@ import { homedir as homedir12, hostname as hostname2 } from "os";
|
|
|
28397
28614
|
import { randomBytes as randomBytes7 } from "crypto";
|
|
28398
28615
|
|
|
28399
28616
|
// ../daemon/src/agent/config.ts
|
|
28400
|
-
import { existsSync as
|
|
28617
|
+
import { existsSync as existsSync28, readFileSync as readFileSync17 } from "fs";
|
|
28401
28618
|
import { homedir as homedir11 } from "os";
|
|
28402
|
-
import { join as
|
|
28619
|
+
import { join as join24 } from "path";
|
|
28403
28620
|
function agentConfigFiles(spec, repoPath, home = homedir11()) {
|
|
28404
28621
|
const file = (id, label, path) => ({
|
|
28405
28622
|
id,
|
|
28406
28623
|
label,
|
|
28407
28624
|
path,
|
|
28408
|
-
exists:
|
|
28625
|
+
exists: existsSync28(path)
|
|
28409
28626
|
});
|
|
28410
28627
|
if (spec.id === "claude") {
|
|
28411
28628
|
return [
|
|
28412
|
-
file("user-config", "user config (MCP servers, projects)",
|
|
28413
|
-
file("user-settings", "user settings (permissions, hooks)",
|
|
28414
|
-
...repoPath ? [file("project-mcp", "project MCP servers",
|
|
28415
|
-
...repoPath ? [file("project-settings", "project settings",
|
|
28629
|
+
file("user-config", "user config (MCP servers, projects)", join24(home, ".claude.json")),
|
|
28630
|
+
file("user-settings", "user settings (permissions, hooks)", join24(home, ".claude", "settings.json")),
|
|
28631
|
+
...repoPath ? [file("project-mcp", "project MCP servers", join24(repoPath, ".mcp.json"))] : [],
|
|
28632
|
+
...repoPath ? [file("project-settings", "project settings", join24(repoPath, ".claude", "settings.json"))] : []
|
|
28416
28633
|
];
|
|
28417
28634
|
}
|
|
28418
28635
|
if (spec.id === "codex")
|
|
28419
|
-
return [file("user-config", "config",
|
|
28636
|
+
return [file("user-config", "config", join24(home, ".codex", "config.toml"))];
|
|
28420
28637
|
return [];
|
|
28421
28638
|
}
|
|
28422
28639
|
function describeAgentConfig(spec, repoPath, home = homedir11()) {
|
|
28423
28640
|
const files = agentConfigFiles(spec, repoPath, home);
|
|
28424
28641
|
const servers = [];
|
|
28425
28642
|
if (spec.id === "claude") {
|
|
28426
|
-
const user = readJson(
|
|
28643
|
+
const user = readJson(join24(home, ".claude.json"));
|
|
28427
28644
|
servers.push(...serversOf(user?.mcpServers, "user"));
|
|
28428
28645
|
if (repoPath) {
|
|
28429
28646
|
const projects = user?.projects;
|
|
28430
28647
|
const mine = projects?.[repoPath];
|
|
28431
28648
|
servers.push(...serversOf(mine?.mcpServers, "local"));
|
|
28432
|
-
servers.push(...serversOf(readJson(
|
|
28649
|
+
servers.push(...serversOf(readJson(join24(repoPath, ".mcp.json"))?.mcpServers, "project"));
|
|
28433
28650
|
}
|
|
28434
28651
|
} else if (spec.id === "codex") {
|
|
28435
|
-
servers.push(...codexServers(
|
|
28652
|
+
servers.push(...codexServers(join24(home, ".codex", "config.toml")));
|
|
28436
28653
|
}
|
|
28437
28654
|
return { agent: spec.id, files, servers };
|
|
28438
28655
|
}
|
|
28439
28656
|
function readJson(path) {
|
|
28440
|
-
if (!
|
|
28657
|
+
if (!existsSync28(path))
|
|
28441
28658
|
return null;
|
|
28442
28659
|
try {
|
|
28443
|
-
const v = JSON.parse(
|
|
28660
|
+
const v = JSON.parse(readFileSync17(path, "utf8"));
|
|
28444
28661
|
return v && typeof v === "object" && !Array.isArray(v) ? v : null;
|
|
28445
28662
|
} catch (e) {
|
|
28446
28663
|
log.warn("agent-config", `${path} is not valid JSON`, e);
|
|
@@ -28458,11 +28675,11 @@ function serversOf(raw, scope) {
|
|
|
28458
28675
|
});
|
|
28459
28676
|
}
|
|
28460
28677
|
function codexServers(path) {
|
|
28461
|
-
if (!
|
|
28678
|
+
if (!existsSync28(path))
|
|
28462
28679
|
return [];
|
|
28463
28680
|
const out = [];
|
|
28464
28681
|
let current = null;
|
|
28465
|
-
for (const raw of
|
|
28682
|
+
for (const raw of readFileSync17(path, "utf8").split(`
|
|
28466
28683
|
`)) {
|
|
28467
28684
|
const line = raw.trim();
|
|
28468
28685
|
const header = /^\[mcp_servers\.("?)([^\]"]+)\1\]$/.exec(line);
|
|
@@ -29381,6 +29598,7 @@ var handlers = {
|
|
|
29381
29598
|
},
|
|
29382
29599
|
continue(msg, _ctx, s) {
|
|
29383
29600
|
s.fix.goOn(msg.worktreeId);
|
|
29601
|
+
s.worktrees.markPrompted(msg.worktreeId);
|
|
29384
29602
|
},
|
|
29385
29603
|
async "write-file"(msg, ctx, s) {
|
|
29386
29604
|
const head = { t: "file-written", worktreeId: msg.worktreeId, path: msg.path, seq: msg.seq };
|
|
@@ -29497,7 +29715,7 @@ var handlers = {
|
|
|
29497
29715
|
},
|
|
29498
29716
|
"agent-decide"(msg, _ctx, s) {
|
|
29499
29717
|
requireRun(s, msg.worktreeId);
|
|
29500
|
-
s.runtime.agentFor(msg.worktreeId)?.answer(msg.askId, { kind: "choice", choiceId: msg.choiceId });
|
|
29718
|
+
s.runtime.agentFor(msg.worktreeId)?.answer(msg.askId, { kind: "choice", choiceId: msg.choiceId, ...msg.note ? { note: msg.note } : {} });
|
|
29501
29719
|
s.worktrees.markPrompted(msg.worktreeId);
|
|
29502
29720
|
},
|
|
29503
29721
|
async "handoff-answer"(msg, _ctx, s) {
|
|
@@ -29650,9 +29868,9 @@ async function dispatch(msg, ctx, s) {
|
|
|
29650
29868
|
}
|
|
29651
29869
|
|
|
29652
29870
|
// ../daemon/src/server/http.ts
|
|
29653
|
-
import { existsSync as
|
|
29871
|
+
import { existsSync as existsSync29 } from "fs";
|
|
29654
29872
|
import { hostname } from "os";
|
|
29655
|
-
import { join as
|
|
29873
|
+
import { join as join25 } from "path";
|
|
29656
29874
|
|
|
29657
29875
|
// ../daemon/src/server/cors.ts
|
|
29658
29876
|
var ALLOW_HEADERS = "authorization, content-type";
|
|
@@ -29955,7 +30173,7 @@ function createFetch(opts) {
|
|
|
29955
30173
|
return new Response("unauthorized", { status: 401 });
|
|
29956
30174
|
const id = url.pathname.slice("/uploads/".length);
|
|
29957
30175
|
const path = opts.attachments.uploads.path(id);
|
|
29958
|
-
if (!path || !
|
|
30176
|
+
if (!path || !existsSync29(path))
|
|
29959
30177
|
return new Response("not found", { status: 404 });
|
|
29960
30178
|
return new Response(Bun.file(path), {
|
|
29961
30179
|
headers: { "cache-control": IMMUTABLE, ...attachedHeaders(opts.attachments.uploads.imageType(id)) }
|
|
@@ -29968,7 +30186,7 @@ function createFetch(opts) {
|
|
|
29968
30186
|
const places = worktreeId && file && !extra ? [opts.attachments.fileFor(worktreeId, file), opts.archivedAttachment(worktreeId, file)] : [];
|
|
29969
30187
|
if (worktreeId && file)
|
|
29970
30188
|
await opts.attachments.whenWritten(worktreeId, file);
|
|
29971
|
-
const path = places.find((p) => !!p &&
|
|
30189
|
+
const path = places.find((p) => !!p && existsSync29(p));
|
|
29972
30190
|
if (!path)
|
|
29973
30191
|
return new Response("not found", { status: 404 });
|
|
29974
30192
|
if (url.searchParams.has("where")) {
|
|
@@ -30006,12 +30224,12 @@ function createFetch(opts) {
|
|
|
30006
30224
|
});
|
|
30007
30225
|
}
|
|
30008
30226
|
const rel = url.pathname === "/" ? "/index.html" : url.pathname;
|
|
30009
|
-
const file =
|
|
30227
|
+
const file = join25(opts.shellDist, rel.replaceAll("..", ""));
|
|
30010
30228
|
const hashed = rel.startsWith("/assets/");
|
|
30011
|
-
if (
|
|
30229
|
+
if (existsSync29(file) && Bun.file(file).size > 0) {
|
|
30012
30230
|
if (rel === "/manifest.json") {
|
|
30013
|
-
const
|
|
30014
|
-
const manifest = { ...await Bun.file(file).json(), theme_color:
|
|
30231
|
+
const ground = opts.manifestGround();
|
|
30232
|
+
const manifest = { ...await Bun.file(file).json(), theme_color: ground, background_color: ground };
|
|
30015
30233
|
return Response.json(manifest, {
|
|
30016
30234
|
headers: { "content-type": "application/manifest+json", "cache-control": NO_STORE2 }
|
|
30017
30235
|
});
|
|
@@ -30027,8 +30245,8 @@ function createFetch(opts) {
|
|
|
30027
30245
|
}
|
|
30028
30246
|
if (hashed)
|
|
30029
30247
|
return new Response("not found", { status: 404 });
|
|
30030
|
-
const index =
|
|
30031
|
-
if (
|
|
30248
|
+
const index = join25(opts.shellDist, "index.html");
|
|
30249
|
+
if (existsSync29(index))
|
|
30032
30250
|
return new Response(Bun.file(index), { headers: { "cache-control": NO_STORE2 } });
|
|
30033
30251
|
return new Response("Toyon daemon running; shell not built (run: bun run build)", { status: 200 });
|
|
30034
30252
|
}
|
|
@@ -30203,6 +30421,7 @@ function startServer(opts) {
|
|
|
30203
30421
|
};
|
|
30204
30422
|
s.hub.on("worktreesChanged", worktreesChanged);
|
|
30205
30423
|
s.hub.on("agentStatus", worktreesChanged);
|
|
30424
|
+
s.hub.on("agentStopping", worktreesChanged);
|
|
30206
30425
|
s.hub.on("reposChanged", () => broadcast({ t: "repos", repos: s.state.repos }));
|
|
30207
30426
|
s.hub.on("pendingChanged", () => broadcast({ t: "pending-repos", pending: s.repos.pending }));
|
|
30208
30427
|
s.hub.on("proc", (worktreeId, proc) => broadcast({ t: "proc", worktreeId, proc }));
|
|
@@ -30349,10 +30568,7 @@ function startServer(opts) {
|
|
|
30349
30568
|
managed: { source: opts.managed.source, hash: opts.managed.hash },
|
|
30350
30569
|
preview: (id) => s.runtime.get(id)?.proxy?.handler ?? null,
|
|
30351
30570
|
bootstrap: helloFrame,
|
|
30352
|
-
|
|
30353
|
-
const { surface0, surface1 } = s.themes.current().colors;
|
|
30354
|
-
return { bar: surface0, ground: surface1 };
|
|
30355
|
-
},
|
|
30571
|
+
manifestGround: () => s.themes.current().colors.surface1,
|
|
30356
30572
|
open: (path) => s.opens.open(path),
|
|
30357
30573
|
restart: (now) => s.restarter.request({ now }),
|
|
30358
30574
|
restartWait: () => ({ waiting: s.restarter.waitingOn(), asking: s.restarter.asking() }),
|
|
@@ -30477,16 +30693,16 @@ function startServer(opts) {
|
|
|
30477
30693
|
}
|
|
30478
30694
|
|
|
30479
30695
|
// ../daemon/src/themes/store.ts
|
|
30480
|
-
import { existsSync as
|
|
30696
|
+
import { existsSync as existsSync30, readdirSync as readdirSync8, readFileSync as readFileSync18, statSync as statSync11, writeFileSync as writeFileSync12 } from "fs";
|
|
30481
30697
|
import { homedir as homedir13 } from "os";
|
|
30482
|
-
import { basename as basename9, dirname as
|
|
30698
|
+
import { basename as basename9, dirname as dirname10, join as join26, resolve as resolve9 } from "path";
|
|
30483
30699
|
var home = homedir13();
|
|
30484
30700
|
var defaultExtensionDirs = [
|
|
30485
|
-
|
|
30486
|
-
|
|
30487
|
-
|
|
30488
|
-
|
|
30489
|
-
|
|
30701
|
+
join26(home, ".vscode", "extensions"),
|
|
30702
|
+
join26(home, ".vscode-insiders", "extensions"),
|
|
30703
|
+
join26(home, ".vscode-oss", "extensions"),
|
|
30704
|
+
join26(home, ".cursor", "extensions"),
|
|
30705
|
+
join26(home, ".windsurf", "extensions"),
|
|
30490
30706
|
"/Applications/Visual Studio Code.app/Contents/Resources/app/extensions",
|
|
30491
30707
|
"/Applications/Visual Studio Code - Insiders.app/Contents/Resources/app/extensions",
|
|
30492
30708
|
"/Applications/Cursor.app/Contents/Resources/app/extensions",
|
|
@@ -30570,14 +30786,14 @@ class ThemeStore {
|
|
|
30570
30786
|
name: json?.name ?? base,
|
|
30571
30787
|
source: "file"
|
|
30572
30788
|
});
|
|
30573
|
-
|
|
30789
|
+
writeFileSync12(join26(this.themesDir, `${base}.json`), `${JSON.stringify(theme, null, 2)}
|
|
30574
30790
|
`);
|
|
30575
30791
|
this.load();
|
|
30576
30792
|
return theme;
|
|
30577
30793
|
}
|
|
30578
30794
|
}
|
|
30579
30795
|
function readJsonc(file) {
|
|
30580
|
-
return parse6(
|
|
30796
|
+
return parse6(readFileSync18(file, "utf8"), [], { allowTrailingComma: true });
|
|
30581
30797
|
}
|
|
30582
30798
|
function readVscodeTheme(file, depth = 0) {
|
|
30583
30799
|
const json = readJsonc(file);
|
|
@@ -30585,7 +30801,7 @@ function readVscodeTheme(file, depth = 0) {
|
|
|
30585
30801
|
throw new ThemeImportError(`${file}: not a JSON object`);
|
|
30586
30802
|
const t = json;
|
|
30587
30803
|
if (typeof t.include === "string" && depth < 5) {
|
|
30588
|
-
const parent = readVscodeTheme(resolve9(
|
|
30804
|
+
const parent = readVscodeTheme(resolve9(dirname10(file), t.include), depth + 1);
|
|
30589
30805
|
return {
|
|
30590
30806
|
...parent,
|
|
30591
30807
|
...t,
|
|
@@ -30599,13 +30815,13 @@ function readVscodeTheme(file, depth = 0) {
|
|
|
30599
30815
|
return t;
|
|
30600
30816
|
}
|
|
30601
30817
|
function loadDir(dir) {
|
|
30602
|
-
if (!
|
|
30818
|
+
if (!existsSync30(dir))
|
|
30603
30819
|
return [];
|
|
30604
30820
|
const out = [];
|
|
30605
30821
|
for (const f of readdirSync8(dir)) {
|
|
30606
30822
|
if (!/\.jsonc?$/i.test(f))
|
|
30607
30823
|
continue;
|
|
30608
|
-
const file =
|
|
30824
|
+
const file = join26(dir, f);
|
|
30609
30825
|
const id = `file:${slug(f.replace(/\.(json|jsonc)$/i, ""))}`;
|
|
30610
30826
|
try {
|
|
30611
30827
|
const json = readJsonc(file);
|
|
@@ -30621,7 +30837,7 @@ function loadDir(dir) {
|
|
|
30621
30837
|
return out;
|
|
30622
30838
|
}
|
|
30623
30839
|
function discover(dir) {
|
|
30624
|
-
if (!
|
|
30840
|
+
if (!existsSync30(dir))
|
|
30625
30841
|
return [];
|
|
30626
30842
|
const out = [];
|
|
30627
30843
|
let entries;
|
|
@@ -30631,21 +30847,21 @@ function discover(dir) {
|
|
|
30631
30847
|
return out;
|
|
30632
30848
|
}
|
|
30633
30849
|
for (const name of entries) {
|
|
30634
|
-
const extDir =
|
|
30635
|
-
const pkgFile =
|
|
30850
|
+
const extDir = join26(dir, name);
|
|
30851
|
+
const pkgFile = join26(extDir, "package.json");
|
|
30636
30852
|
try {
|
|
30637
|
-
if (!statSync11(extDir).isDirectory() || !
|
|
30853
|
+
if (!statSync11(extDir).isDirectory() || !existsSync30(pkgFile))
|
|
30638
30854
|
continue;
|
|
30639
|
-
const pkg = JSON.parse(
|
|
30855
|
+
const pkg = JSON.parse(readFileSync18(pkgFile, "utf8"));
|
|
30640
30856
|
const themes = pkg.contributes?.themes;
|
|
30641
30857
|
if (!Array.isArray(themes))
|
|
30642
30858
|
continue;
|
|
30643
30859
|
const ext = `${pkg.publisher ?? "local"}.${pkg.name ?? name}`;
|
|
30644
30860
|
let nls = {};
|
|
30645
|
-
const nlsFile =
|
|
30646
|
-
if (
|
|
30861
|
+
const nlsFile = join26(extDir, "package.nls.json");
|
|
30862
|
+
if (existsSync30(nlsFile)) {
|
|
30647
30863
|
try {
|
|
30648
|
-
nls = JSON.parse(
|
|
30864
|
+
nls = JSON.parse(readFileSync18(nlsFile, "utf8"));
|
|
30649
30865
|
} catch {}
|
|
30650
30866
|
}
|
|
30651
30867
|
for (const c of themes) {
|
|
@@ -31057,16 +31273,16 @@ class BackendShare {
|
|
|
31057
31273
|
|
|
31058
31274
|
// ../daemon/src/worktrees/cache.ts
|
|
31059
31275
|
import { createHash as createHash4 } from "crypto";
|
|
31060
|
-
import { existsSync as
|
|
31276
|
+
import { existsSync as existsSync31, readFileSync as readFileSync19 } from "fs";
|
|
31061
31277
|
import { mkdir as mkdir5, readdir as readdir2, rename, rm as rm4, stat as stat4, utimes, writeFile as writeFile3 } from "fs/promises";
|
|
31062
|
-
import { join as
|
|
31278
|
+
import { join as join27 } from "path";
|
|
31063
31279
|
|
|
31064
31280
|
// ../daemon/src/core/clone.ts
|
|
31065
31281
|
import { mkdir as mkdir4, rm as rm3 } from "fs/promises";
|
|
31066
|
-
import { dirname as
|
|
31282
|
+
import { dirname as dirname11 } from "path";
|
|
31067
31283
|
async function cloneTree(src, dst) {
|
|
31068
31284
|
const started = Date.now();
|
|
31069
|
-
await mkdir4(
|
|
31285
|
+
await mkdir4(dirname11(dst), { recursive: true });
|
|
31070
31286
|
const attempts = [
|
|
31071
31287
|
["clonefile", ["-Rc", src, dst]],
|
|
31072
31288
|
["reflink", ["-R", "--reflink=auto", src, dst]],
|
|
@@ -31074,7 +31290,7 @@ async function cloneTree(src, dst) {
|
|
|
31074
31290
|
];
|
|
31075
31291
|
let error = "";
|
|
31076
31292
|
for (const [how, args] of attempts) {
|
|
31077
|
-
const r = await run("cp", args,
|
|
31293
|
+
const r = await run("cp", args, dirname11(dst));
|
|
31078
31294
|
if (r.ok)
|
|
31079
31295
|
return { ok: true, how, ms: Date.now() - started };
|
|
31080
31296
|
error = r.err.split(`
|
|
@@ -31090,7 +31306,7 @@ var STALE_MS = 30 * 24 * 3600000;
|
|
|
31090
31306
|
var TMP = ".tmp-";
|
|
31091
31307
|
var MANIFEST = "manifest.json";
|
|
31092
31308
|
function defaultTools(dir) {
|
|
31093
|
-
const has = (...files) => files.some((f) =>
|
|
31309
|
+
const has = (...files) => files.some((f) => existsSync31(join27(dir, f)));
|
|
31094
31310
|
const out = [];
|
|
31095
31311
|
if (has("bun.lock", "bun.lockb"))
|
|
31096
31312
|
out.push("bun --version");
|
|
@@ -31103,7 +31319,7 @@ function defaultTools(dir) {
|
|
|
31103
31319
|
return out;
|
|
31104
31320
|
}
|
|
31105
31321
|
function withSidecars(root, rel) {
|
|
31106
|
-
return [rel, ...SIDECARS.map((s) => rel + s)].filter((n) =>
|
|
31322
|
+
return [rel, ...SIDECARS.map((s) => rel + s)].filter((n) => existsSync31(join27(root, n)));
|
|
31107
31323
|
}
|
|
31108
31324
|
var entryName = (base, at) => `${base.slice(0, 12)}-${at.toString(36)}`;
|
|
31109
31325
|
async function listEntries(familyDir) {
|
|
@@ -31118,8 +31334,8 @@ async function listEntries(familyDir) {
|
|
|
31118
31334
|
const m = /^([0-9a-f]{12})-([0-9a-z]+)$/.exec(name);
|
|
31119
31335
|
if (!m?.[1] || !m[2])
|
|
31120
31336
|
continue;
|
|
31121
|
-
const dir =
|
|
31122
|
-
if (!
|
|
31337
|
+
const dir = join27(familyDir, name);
|
|
31338
|
+
if (!existsSync31(join27(dir, MANIFEST)))
|
|
31123
31339
|
continue;
|
|
31124
31340
|
out.push({ dir, base: m[1], at: Number.parseInt(m[2], 36) });
|
|
31125
31341
|
}
|
|
@@ -31149,7 +31365,7 @@ class ArtifactCache {
|
|
|
31149
31365
|
try {
|
|
31150
31366
|
const family = await this.family(wt, repo, policy);
|
|
31151
31367
|
const base = await this.baseCommit(wt, repo);
|
|
31152
|
-
const entries = await listEntries(
|
|
31368
|
+
const entries = await listEntries(join27(this.d.paths.cacheDir, repo.id, family.key));
|
|
31153
31369
|
const entry = entries.find((e) => e.base === base.slice(0, 12)) ?? entries[0];
|
|
31154
31370
|
if (!entry) {
|
|
31155
31371
|
say(`cache: nothing kept for these lockfiles and tools on ${family.platform}`);
|
|
@@ -31157,14 +31373,14 @@ class ArtifactCache {
|
|
|
31157
31373
|
}
|
|
31158
31374
|
const restored = [];
|
|
31159
31375
|
for (const rel of policy.paths) {
|
|
31160
|
-
if (
|
|
31376
|
+
if (existsSync31(join27(wt.path, rel)))
|
|
31161
31377
|
continue;
|
|
31162
31378
|
const names = withSidecars(entry.dir, rel);
|
|
31163
31379
|
if (names.length === 0)
|
|
31164
31380
|
continue;
|
|
31165
31381
|
let whole = true;
|
|
31166
31382
|
for (const name of names) {
|
|
31167
|
-
const r = await (this.d.clone ?? cloneTree)(
|
|
31383
|
+
const r = await (this.d.clone ?? cloneTree)(join27(entry.dir, name), join27(wt.path, name));
|
|
31168
31384
|
if (r.ok)
|
|
31169
31385
|
continue;
|
|
31170
31386
|
say(`cache: could not restore ${name}: ${r.error}`);
|
|
@@ -31198,12 +31414,12 @@ class ArtifactCache {
|
|
|
31198
31414
|
let tmp;
|
|
31199
31415
|
let slot;
|
|
31200
31416
|
try {
|
|
31201
|
-
const present = policy.paths.filter((rel) =>
|
|
31417
|
+
const present = policy.paths.filter((rel) => existsSync31(join27(wt.path, rel)));
|
|
31202
31418
|
if (present.length === 0)
|
|
31203
31419
|
return;
|
|
31204
31420
|
const family = await this.family(wt, repo, policy);
|
|
31205
31421
|
const base = await this.baseCommit(wt, repo);
|
|
31206
|
-
const familyDir =
|
|
31422
|
+
const familyDir = join27(this.d.paths.cacheDir, repo.id, family.key);
|
|
31207
31423
|
const key = `${familyDir}/${base.slice(0, 12)}`;
|
|
31208
31424
|
const kept = (await listEntries(familyDir)).find((e) => e.base === base.slice(0, 12));
|
|
31209
31425
|
if (kept || this.making.has(key)) {
|
|
@@ -31214,21 +31430,21 @@ class ArtifactCache {
|
|
|
31214
31430
|
this.making.add(key);
|
|
31215
31431
|
const at = Date.now();
|
|
31216
31432
|
const name = entryName(base, at);
|
|
31217
|
-
tmp =
|
|
31433
|
+
tmp = join27(familyDir, `${TMP}${name}`);
|
|
31218
31434
|
await mkdir5(tmp, { recursive: true });
|
|
31219
31435
|
let how = "clonefile";
|
|
31220
31436
|
for (const rel of present) {
|
|
31221
31437
|
for (const n of withSidecars(wt.path, rel)) {
|
|
31222
|
-
const r = await (this.d.clone ?? cloneTree)(
|
|
31438
|
+
const r = await (this.d.clone ?? cloneTree)(join27(wt.path, n), join27(tmp, n));
|
|
31223
31439
|
if (!r.ok)
|
|
31224
31440
|
throw new Error(`could not keep ${n}: ${r.error}`);
|
|
31225
31441
|
how = r.how;
|
|
31226
31442
|
}
|
|
31227
31443
|
}
|
|
31228
31444
|
const manifest = { at, base, platform: family.platform, tools: family.tools, paths: present };
|
|
31229
|
-
await writeFile3(
|
|
31445
|
+
await writeFile3(join27(tmp, MANIFEST), `${JSON.stringify(manifest, null, 2)}
|
|
31230
31446
|
`);
|
|
31231
|
-
await rename(tmp,
|
|
31447
|
+
await rename(tmp, join27(familyDir, name));
|
|
31232
31448
|
tmp = undefined;
|
|
31233
31449
|
log.info(worktreeId, `cache: kept ${list(present)} for ${base.slice(0, 7)} via ${how} in ${Date.now() - started}ms`);
|
|
31234
31450
|
await this.prune(familyDir);
|
|
@@ -31256,7 +31472,7 @@ class ArtifactCache {
|
|
|
31256
31472
|
return;
|
|
31257
31473
|
}
|
|
31258
31474
|
for (const repoId of repoIds) {
|
|
31259
|
-
const repoDir =
|
|
31475
|
+
const repoDir = join27(root, repoId);
|
|
31260
31476
|
if (!this.d.state.repo(repoId)) {
|
|
31261
31477
|
await rm4(repoDir, { recursive: true, force: true });
|
|
31262
31478
|
continue;
|
|
@@ -31268,7 +31484,7 @@ class ArtifactCache {
|
|
|
31268
31484
|
continue;
|
|
31269
31485
|
}
|
|
31270
31486
|
for (const family of families) {
|
|
31271
|
-
const familyDir =
|
|
31487
|
+
const familyDir = join27(repoDir, family);
|
|
31272
31488
|
let names;
|
|
31273
31489
|
try {
|
|
31274
31490
|
names = await readdir2(familyDir);
|
|
@@ -31277,7 +31493,7 @@ class ArtifactCache {
|
|
|
31277
31493
|
}
|
|
31278
31494
|
for (const n of names)
|
|
31279
31495
|
if (n.startsWith(TMP))
|
|
31280
|
-
await rm4(
|
|
31496
|
+
await rm4(join27(familyDir, n), { recursive: true, force: true });
|
|
31281
31497
|
const entries = await listEntries(familyDir);
|
|
31282
31498
|
let newest = 0;
|
|
31283
31499
|
for (const e of entries) {
|
|
@@ -31297,7 +31513,7 @@ class ArtifactCache {
|
|
|
31297
31513
|
for (const f of policy.key) {
|
|
31298
31514
|
h.update(`\x00${f}\x00`);
|
|
31299
31515
|
try {
|
|
31300
|
-
h.update(
|
|
31516
|
+
h.update(readFileSync19(join27(wt.path, f)));
|
|
31301
31517
|
} catch {
|
|
31302
31518
|
h.update("(absent)");
|
|
31303
31519
|
}
|
|
@@ -31502,6 +31718,8 @@ function lastStop(entries) {
|
|
|
31502
31718
|
const e = entries[i].event;
|
|
31503
31719
|
if (e.type === "usage" || e.type === "session-info")
|
|
31504
31720
|
continue;
|
|
31721
|
+
if (e.type === "turn-end" && (e.stopReason === "failed" || e.stopReason === "auth" || e.stopReason === "lost"))
|
|
31722
|
+
continue;
|
|
31505
31723
|
if (e.type === "turn-end" && e.stopReason === "interrupted")
|
|
31506
31724
|
return { kind: "stopped" };
|
|
31507
31725
|
if (e.type === "agent-error")
|
|
@@ -31854,7 +32072,7 @@ class LandingService {
|
|
|
31854
32072
|
this.judging.delete(worktreeId);
|
|
31855
32073
|
}
|
|
31856
32074
|
note(worktreeId, status) {
|
|
31857
|
-
if (status
|
|
32075
|
+
if (isBusy(status))
|
|
31858
32076
|
this.busy.add(worktreeId);
|
|
31859
32077
|
else
|
|
31860
32078
|
this.busy.delete(worktreeId);
|
|
@@ -32537,9 +32755,9 @@ function rankRefs({ refs, merged, prs, query, defaultBranch, rowIdForPath }) {
|
|
|
32537
32755
|
}
|
|
32538
32756
|
|
|
32539
32757
|
// ../daemon/src/worktrees/service.ts
|
|
32540
|
-
import { cpSync, existsSync as
|
|
32758
|
+
import { cpSync, existsSync as existsSync36, readFileSync as readFileSync21, rmSync as rmSync8 } from "fs";
|
|
32541
32759
|
import { rm as rm5 } from "fs/promises";
|
|
32542
|
-
import { dirname as
|
|
32760
|
+
import { dirname as dirname13, join as join32 } from "path";
|
|
32543
32761
|
|
|
32544
32762
|
// ../daemon/src/git/archive.ts
|
|
32545
32763
|
import { rmSync as rmSync5 } from "fs";
|
|
@@ -32663,7 +32881,7 @@ async function dropLandRefs(repoPath, worktreeId) {
|
|
|
32663
32881
|
}
|
|
32664
32882
|
|
|
32665
32883
|
// ../daemon/src/git/land.ts
|
|
32666
|
-
import { existsSync as
|
|
32884
|
+
import { existsSync as existsSync32 } from "fs";
|
|
32667
32885
|
var STEP_TIMEOUT_MS = RUN_CEILING_MS;
|
|
32668
32886
|
function rowOf(r) {
|
|
32669
32887
|
return r.shown && r.toolId && r.command ? { toolId: r.toolId, command: r.command, text: r.text } : undefined;
|
|
@@ -32797,7 +33015,7 @@ async function midway(worktreePath) {
|
|
|
32797
33015
|
if (!r.ok)
|
|
32798
33016
|
return null;
|
|
32799
33017
|
const at = r.out.split(`
|
|
32800
|
-
`).findIndex((file) => file &&
|
|
33018
|
+
`).findIndex((file) => file && existsSync32(file));
|
|
32801
33019
|
return MIDWAY[at]?.[1] ?? null;
|
|
32802
33020
|
}
|
|
32803
33021
|
async function takeMainIn(worktreePath, defaultBr, own, w = UNWATCHED, carry = false) {
|
|
@@ -33147,8 +33365,8 @@ function compareUrl(remoteUrl, base, branch) {
|
|
|
33147
33365
|
}
|
|
33148
33366
|
|
|
33149
33367
|
// ../daemon/src/git/turn.ts
|
|
33150
|
-
import { copyFileSync, existsSync as
|
|
33151
|
-
import { join as
|
|
33368
|
+
import { copyFileSync, existsSync as existsSync33, rmSync as rmSync6 } from "fs";
|
|
33369
|
+
import { join as join28 } from "path";
|
|
33152
33370
|
var turnRef = (worktreeId, which) => `refs/toyon/turns/${worktreeId}/${which}`;
|
|
33153
33371
|
var SNAPSHOT_SUBJECT2 = "toyon: tree at a send";
|
|
33154
33372
|
var queue = new Map;
|
|
@@ -33166,14 +33384,14 @@ async function treeNow(wtPath, head, dirty) {
|
|
|
33166
33384
|
const dir = await git(wtPath, "rev-parse", "--absolute-git-dir");
|
|
33167
33385
|
if (!dir.ok || !dir.out)
|
|
33168
33386
|
return null;
|
|
33169
|
-
index =
|
|
33387
|
+
index = join28(dir.out, "toyon-turn-index");
|
|
33170
33388
|
}
|
|
33171
33389
|
const env = { GIT_INDEX_FILE: index };
|
|
33172
33390
|
const writeTree = async () => {
|
|
33173
33391
|
const tree = await run(GIT, ["write-tree"], wtPath, env);
|
|
33174
33392
|
return tree.ok && tree.out ? tree.out : null;
|
|
33175
33393
|
};
|
|
33176
|
-
if (!
|
|
33394
|
+
if (!existsSync33(index))
|
|
33177
33395
|
was = undefined;
|
|
33178
33396
|
const paths = dirty && !dirty.some((f) => /[RC]/.test(f.xy)) ? dirty.map((f) => f.path) : null;
|
|
33179
33397
|
if (was && paths && was.head === head) {
|
|
@@ -33188,9 +33406,9 @@ async function treeNow(wtPath, head, dirty) {
|
|
|
33188
33406
|
}
|
|
33189
33407
|
}
|
|
33190
33408
|
synced.delete(wtPath);
|
|
33191
|
-
if (!
|
|
33192
|
-
const own =
|
|
33193
|
-
if (
|
|
33409
|
+
if (!existsSync33(index)) {
|
|
33410
|
+
const own = join28(index, "..", "index");
|
|
33411
|
+
if (existsSync33(own))
|
|
33194
33412
|
copyFileSync(own, index);
|
|
33195
33413
|
else if (!(await run(GIT, ["read-tree", "HEAD"], wtPath, env)).ok)
|
|
33196
33414
|
return null;
|
|
@@ -33271,20 +33489,20 @@ async function dropTurnRefs(repoPath, worktreeId) {
|
|
|
33271
33489
|
}
|
|
33272
33490
|
|
|
33273
33491
|
// ../daemon/src/worktrees/archive.ts
|
|
33274
|
-
import { existsSync as
|
|
33275
|
-
import { basename as basename11, dirname as
|
|
33492
|
+
import { existsSync as existsSync34, mkdirSync as mkdirSync9, readdirSync as readdirSync9, readFileSync as readFileSync20, renameSync as renameSync7, rmSync as rmSync7, writeFileSync as writeFileSync13 } from "fs";
|
|
33493
|
+
import { basename as basename11, dirname as dirname12, join as join29 } from "path";
|
|
33276
33494
|
class WorktreeArchive {
|
|
33277
33495
|
dir;
|
|
33278
33496
|
records = new Map;
|
|
33279
33497
|
constructor(dir) {
|
|
33280
33498
|
this.dir = dir;
|
|
33281
|
-
|
|
33499
|
+
mkdirSync9(dir, { recursive: true });
|
|
33282
33500
|
for (const id of readdirSync9(dir)) {
|
|
33283
33501
|
const file = this.filesOf(id).record;
|
|
33284
|
-
if (!
|
|
33502
|
+
if (!existsSync34(file))
|
|
33285
33503
|
continue;
|
|
33286
33504
|
try {
|
|
33287
|
-
this.records.set(id, JSON.parse(
|
|
33505
|
+
this.records.set(id, JSON.parse(readFileSync20(file, "utf8")));
|
|
33288
33506
|
} catch (e) {
|
|
33289
33507
|
log.warn("archive", `skipped an unreadable record: ${file}`, e);
|
|
33290
33508
|
}
|
|
@@ -33295,11 +33513,11 @@ class WorktreeArchive {
|
|
|
33295
33513
|
}
|
|
33296
33514
|
put(rec, from) {
|
|
33297
33515
|
const at = this.filesOf(rec.worktree.id);
|
|
33298
|
-
|
|
33516
|
+
mkdirSync9(at.dir, { recursive: true });
|
|
33299
33517
|
move(from.transcript, at.transcript);
|
|
33300
33518
|
move(from.attachments, at.attachments);
|
|
33301
33519
|
move(from.plans, at.plans);
|
|
33302
|
-
|
|
33520
|
+
writeFileSync13(at.record, JSON.stringify(rec, null, 2));
|
|
33303
33521
|
this.records.set(rec.worktree.id, rec);
|
|
33304
33522
|
return { transcript: at.transcript, attachments: at.attachments, plans: at.plans };
|
|
33305
33523
|
}
|
|
@@ -33328,7 +33546,7 @@ class WorktreeArchive {
|
|
|
33328
33546
|
const rec = this.records.get(id);
|
|
33329
33547
|
if (!rec)
|
|
33330
33548
|
return;
|
|
33331
|
-
|
|
33549
|
+
writeFileSync13(this.filesOf(id).record, JSON.stringify(rec, null, 2));
|
|
33332
33550
|
}
|
|
33333
33551
|
chatFiles(id) {
|
|
33334
33552
|
if (!this.records.has(id))
|
|
@@ -33339,24 +33557,24 @@ class WorktreeArchive {
|
|
|
33339
33557
|
planFile(id, rel) {
|
|
33340
33558
|
if (!this.records.has(id) || !isPlanPath(rel))
|
|
33341
33559
|
return null;
|
|
33342
|
-
const file =
|
|
33343
|
-
if (!
|
|
33560
|
+
const file = join29(this.filesOf(id).plans, basename11(rel));
|
|
33561
|
+
if (!existsSync34(file))
|
|
33344
33562
|
return null;
|
|
33345
33563
|
try {
|
|
33346
|
-
return
|
|
33564
|
+
return readFileSync20(file, "utf8");
|
|
33347
33565
|
} catch (e) {
|
|
33348
33566
|
log.warn(id, `could not read its archived plan ${rel}`, e);
|
|
33349
33567
|
return null;
|
|
33350
33568
|
}
|
|
33351
33569
|
}
|
|
33352
33570
|
filesOf(id) {
|
|
33353
|
-
const dir =
|
|
33571
|
+
const dir = join29(this.dir, id);
|
|
33354
33572
|
return {
|
|
33355
33573
|
dir,
|
|
33356
|
-
record:
|
|
33357
|
-
transcript:
|
|
33358
|
-
attachments:
|
|
33359
|
-
plans:
|
|
33574
|
+
record: join29(dir, "record.json"),
|
|
33575
|
+
transcript: join29(dir, "transcript.jsonl"),
|
|
33576
|
+
attachments: join29(dir, "attachments"),
|
|
33577
|
+
plans: join29(dir, "plans")
|
|
33360
33578
|
};
|
|
33361
33579
|
}
|
|
33362
33580
|
}
|
|
@@ -33381,9 +33599,9 @@ function summarize(r, repoId, transcript) {
|
|
|
33381
33599
|
};
|
|
33382
33600
|
}
|
|
33383
33601
|
function lastUsage(transcript) {
|
|
33384
|
-
if (!
|
|
33602
|
+
if (!existsSync34(transcript))
|
|
33385
33603
|
return null;
|
|
33386
|
-
const lines =
|
|
33604
|
+
const lines = readFileSync20(transcript, "utf8").split(`
|
|
33387
33605
|
`);
|
|
33388
33606
|
for (let i = lines.length - 1;i >= 0; i--) {
|
|
33389
33607
|
if (!lines[i]?.includes('"usage"'))
|
|
@@ -33397,9 +33615,9 @@ function lastUsage(transcript) {
|
|
|
33397
33615
|
return null;
|
|
33398
33616
|
}
|
|
33399
33617
|
function firstPrompt(transcript) {
|
|
33400
|
-
if (!
|
|
33618
|
+
if (!existsSync34(transcript))
|
|
33401
33619
|
return;
|
|
33402
|
-
for (const line of
|
|
33620
|
+
for (const line of readFileSync20(transcript, "utf8").split(`
|
|
33403
33621
|
`)) {
|
|
33404
33622
|
if (!line.includes('"user-message"'))
|
|
33405
33623
|
continue;
|
|
@@ -33412,11 +33630,11 @@ function firstPrompt(transcript) {
|
|
|
33412
33630
|
return;
|
|
33413
33631
|
}
|
|
33414
33632
|
function move(from, to) {
|
|
33415
|
-
if (!
|
|
33633
|
+
if (!existsSync34(from))
|
|
33416
33634
|
return;
|
|
33417
|
-
|
|
33635
|
+
mkdirSync9(dirname12(to), { recursive: true });
|
|
33418
33636
|
rmSync7(to, { recursive: true, force: true });
|
|
33419
|
-
|
|
33637
|
+
renameSync7(from, to);
|
|
33420
33638
|
}
|
|
33421
33639
|
|
|
33422
33640
|
// ../daemon/src/worktrees/archivedGit.ts
|
|
@@ -33494,8 +33712,8 @@ async function fillLandMarks(jobs, read, width = 8) {
|
|
|
33494
33712
|
}
|
|
33495
33713
|
|
|
33496
33714
|
// ../daemon/src/worktrees/spare.ts
|
|
33497
|
-
import { existsSync as
|
|
33498
|
-
import { basename as basename12, join as
|
|
33715
|
+
import { existsSync as existsSync35 } from "fs";
|
|
33716
|
+
import { basename as basename12, join as join30 } from "path";
|
|
33499
33717
|
class SparePool {
|
|
33500
33718
|
d;
|
|
33501
33719
|
inflight = new Map;
|
|
@@ -33518,7 +33736,7 @@ class SparePool {
|
|
|
33518
33736
|
if (!text.trim())
|
|
33519
33737
|
return;
|
|
33520
33738
|
const wt = this.d.state.worktree(boxId);
|
|
33521
|
-
if (wt?.kind !== "spare" || !
|
|
33739
|
+
if (wt?.kind !== "spare" || !existsSync35(wt.path))
|
|
33522
33740
|
return;
|
|
33523
33741
|
const agent = this.d.runtime.ensureAgent(wt).agent;
|
|
33524
33742
|
if (agent.runningAgent === null)
|
|
@@ -33563,11 +33781,11 @@ class SparePool {
|
|
|
33563
33781
|
return this.record(repoId, repo).then((wt) => this.warmUp(wt, repo, {}));
|
|
33564
33782
|
}
|
|
33565
33783
|
async record(repoId, repo) {
|
|
33566
|
-
const { id, dir } = freeSlot(
|
|
33784
|
+
const { id, dir } = freeSlot(join30(this.d.paths.worktreesDir, repo.name));
|
|
33567
33785
|
const wt = {
|
|
33568
33786
|
id,
|
|
33569
33787
|
repoId,
|
|
33570
|
-
path:
|
|
33788
|
+
path: join30(this.d.paths.worktreesDir, repo.name, dir),
|
|
33571
33789
|
branch: repo.defaultBranch,
|
|
33572
33790
|
kind: "spare",
|
|
33573
33791
|
phase: "reserved",
|
|
@@ -33582,7 +33800,7 @@ class SparePool {
|
|
|
33582
33800
|
const repoId = repo.id;
|
|
33583
33801
|
let cut = () => {};
|
|
33584
33802
|
const added = (async () => {
|
|
33585
|
-
if (
|
|
33803
|
+
if (existsSync35(wt.path))
|
|
33586
33804
|
return;
|
|
33587
33805
|
const run = this.d.runs.begin(wt.id, "setup", {
|
|
33588
33806
|
timeoutMs: timeoutFor(repo.config, "setup"),
|
|
@@ -33643,7 +33861,7 @@ class SparePool {
|
|
|
33643
33861
|
}
|
|
33644
33862
|
log.warn(wt.repoId, "spare warm-up failed; rolling back", e);
|
|
33645
33863
|
this.d.carryDraft?.(wt.id, wt.repoId);
|
|
33646
|
-
if (
|
|
33864
|
+
if (existsSync35(wt.path)) {
|
|
33647
33865
|
await this.d.discard(wt.id).catch((re) => log.warn(wt.repoId, "spare rollback failed", re));
|
|
33648
33866
|
return;
|
|
33649
33867
|
}
|
|
@@ -33715,7 +33933,7 @@ class SparePool {
|
|
|
33715
33933
|
try {
|
|
33716
33934
|
await running?.added;
|
|
33717
33935
|
running?.cut();
|
|
33718
|
-
if (!
|
|
33936
|
+
if (!existsSync35(wt.path))
|
|
33719
33937
|
throw new Error("the worktree's directory is gone");
|
|
33720
33938
|
await this.refreshing.get(repoId);
|
|
33721
33939
|
await prepare(wt);
|
|
@@ -33743,7 +33961,7 @@ class SparePool {
|
|
|
33743
33961
|
for (const k of Object.keys(stamps))
|
|
33744
33962
|
delete wt[k];
|
|
33745
33963
|
delete wt.promptedAt;
|
|
33746
|
-
if (!
|
|
33964
|
+
if (!existsSync35(wt.path)) {
|
|
33747
33965
|
await this.rollBack(wt, e);
|
|
33748
33966
|
return;
|
|
33749
33967
|
}
|
|
@@ -33757,7 +33975,7 @@ class SparePool {
|
|
|
33757
33975
|
// ../daemon/src/worktrees/treeState.ts
|
|
33758
33976
|
import { watch as watch2 } from "fs";
|
|
33759
33977
|
import { stat as stat5 } from "fs/promises";
|
|
33760
|
-
import { join as
|
|
33978
|
+
import { join as join31 } from "path";
|
|
33761
33979
|
var EDIT_DELAY_MS = 150;
|
|
33762
33980
|
var SHELL_QUIET_MS2 = 1500;
|
|
33763
33981
|
var WATCH_DELAY_MS = 300;
|
|
@@ -34140,7 +34358,7 @@ class TreeState {
|
|
|
34140
34358
|
xy: f.xy,
|
|
34141
34359
|
...entries.folded.has(f.path) ? { add: f.add, del: f.del } : {}
|
|
34142
34360
|
}));
|
|
34143
|
-
const stats = await Promise.all(files.slice(0, SIGNATURE_STATS).map((f) => stat5(
|
|
34361
|
+
const stats = await Promise.all(files.slice(0, SIGNATURE_STATS).map((f) => stat5(join31(r.path, f.path)).then((s) => `${s.mtimeMs}:${s.size}`, () => "-")));
|
|
34144
34362
|
const t0 = performance.now();
|
|
34145
34363
|
const counts = { ...ab, ...unpushed === null ? {} : { unpushed } };
|
|
34146
34364
|
const signature = String(Bun.hash([
|
|
@@ -34449,7 +34667,7 @@ class TurnService {
|
|
|
34449
34667
|
}
|
|
34450
34668
|
}
|
|
34451
34669
|
function stopOf(prev, next) {
|
|
34452
|
-
const busy = prev
|
|
34670
|
+
const busy = isBusy(prev);
|
|
34453
34671
|
if (next === "waiting" && prev !== "waiting")
|
|
34454
34672
|
return "asking";
|
|
34455
34673
|
if (next === "idle" && busy)
|
|
@@ -34666,8 +34884,8 @@ class WorktreeService {
|
|
|
34666
34884
|
if (!await isGitRepo(repo.path)) {
|
|
34667
34885
|
throw new UserError(`git no longer reads ${repo.name} as a checkout, so there is nothing to start a worktree from. If \`git config core.bare\` says true there, \`git config --unset core.bare\` puts it back.`);
|
|
34668
34886
|
}
|
|
34669
|
-
const { id, dir } = freeSlot(
|
|
34670
|
-
const wtPath =
|
|
34887
|
+
const { id, dir } = freeSlot(join32(this.d.paths.worktreesDir, repo.name));
|
|
34888
|
+
const wtPath = join32(this.d.paths.worktreesDir, repo.name, dir);
|
|
34671
34889
|
const branch = `toyon/${dir}`;
|
|
34672
34890
|
await withRepoLock(repo.path, () => gitOrThrow(repo.path, "worktree", "add", "--no-track", "-b", branch, wtPath, baseOf(repo)));
|
|
34673
34891
|
const wt = {
|
|
@@ -34741,7 +34959,7 @@ class WorktreeService {
|
|
|
34741
34959
|
};
|
|
34742
34960
|
const carried = await git(repo.path, "ls-tree", "-r", "--name-only", `${sha}^3`);
|
|
34743
34961
|
const restored = (carried.ok ? carried.out.split(`
|
|
34744
|
-
`).filter(Boolean) : []).filter((p) => !
|
|
34962
|
+
`).filter(Boolean) : []).filter((p) => !existsSync36(join32(wt.path, p)));
|
|
34745
34963
|
const applied = await git(wt.path, "stash", "apply", sha);
|
|
34746
34964
|
if (applied.ok) {
|
|
34747
34965
|
const ref = await entry();
|
|
@@ -34778,9 +34996,9 @@ class WorktreeService {
|
|
|
34778
34996
|
const branch = kind === "pr" ? `pr/${number}` : ref;
|
|
34779
34997
|
const title = kind === "pr" ? `pr-${number}` : cleanTitle2(ref) || "branch";
|
|
34780
34998
|
let slug = branchSlug(title) || "branch";
|
|
34781
|
-
if (
|
|
34999
|
+
if (existsSync36(join32(this.d.paths.worktreesDir, repo.name, slug)))
|
|
34782
35000
|
slug = `${slug}-${shortId().slice(0, 4)}`;
|
|
34783
|
-
const wtPath =
|
|
35001
|
+
const wtPath = join32(this.d.paths.worktreesDir, repo.name, slug);
|
|
34784
35002
|
await withRepoLock(repo.path, async () => {
|
|
34785
35003
|
const out = (await listWorktrees(repo.path)).find((w) => w.branch === branch);
|
|
34786
35004
|
if (out)
|
|
@@ -35047,7 +35265,7 @@ class WorktreeService {
|
|
|
35047
35265
|
}
|
|
35048
35266
|
async teardown(wt, repo) {
|
|
35049
35267
|
const cmds = repo.config.teardown ?? [];
|
|
35050
|
-
if (cmds.length === 0 || !
|
|
35268
|
+
if (cmds.length === 0 || !existsSync36(wt.path))
|
|
35051
35269
|
return;
|
|
35052
35270
|
for (const cmd of cmds) {
|
|
35053
35271
|
const code = await runSetup(cmd, wt.path, (line) => this.d.hub.emit("log", wt.id, "setup", line), worktreeEnv(wt, repo), { timeoutMs: timeoutFor(repo.config, "setup") });
|
|
@@ -35056,7 +35274,7 @@ class WorktreeService {
|
|
|
35056
35274
|
}
|
|
35057
35275
|
}
|
|
35058
35276
|
async keep(repo, wt) {
|
|
35059
|
-
const index =
|
|
35277
|
+
const index = join32(this.d.paths.archiveDir, `${wt.id}.index`);
|
|
35060
35278
|
const kept = await keepState(repo.path, wt.path, archiveRef(wt.id), index) ?? await this.keepUnlinked(repo, wt);
|
|
35061
35279
|
if (!kept)
|
|
35062
35280
|
log.warn(wt.id, "could not keep its git state");
|
|
@@ -35088,16 +35306,16 @@ class WorktreeService {
|
|
|
35088
35306
|
throw new Error(`git worktree remove --force ${wt.path} failed (${r.exit}): ${r.err}`);
|
|
35089
35307
|
if (await deleteTree(wt.path))
|
|
35090
35308
|
return;
|
|
35091
|
-
await run("chmod", ["-R", "u+w", wt.path],
|
|
35309
|
+
await run("chmod", ["-R", "u+w", wt.path], dirname13(wt.path));
|
|
35092
35310
|
if (!await deleteTree(wt.path))
|
|
35093
35311
|
log.warn(wt.id, `its directory could not be deleted and stays at ${wt.path}`);
|
|
35094
35312
|
}
|
|
35095
35313
|
plansScratch(worktreeId) {
|
|
35096
|
-
return
|
|
35314
|
+
return join32(this.d.paths.archiveDir, `${worktreeId}.plans`);
|
|
35097
35315
|
}
|
|
35098
35316
|
keepPlans(wt) {
|
|
35099
|
-
const from =
|
|
35100
|
-
if (!
|
|
35317
|
+
const from = join32(wt.path, PLANS_DIR);
|
|
35318
|
+
if (!existsSync36(from))
|
|
35101
35319
|
return;
|
|
35102
35320
|
try {
|
|
35103
35321
|
cpSync(from, this.plansScratch(wt.id), { recursive: true });
|
|
@@ -35233,11 +35451,15 @@ class WorktreeService {
|
|
|
35233
35451
|
}
|
|
35234
35452
|
archivedTranscript(archiveId) {
|
|
35235
35453
|
const files = this.archive.chatFiles(archiveId);
|
|
35236
|
-
|
|
35454
|
+
if (!files)
|
|
35455
|
+
return null;
|
|
35456
|
+
const { entries } = new Transcript(files.transcript, archiveId);
|
|
35457
|
+
const seal = sealOpenTurn(entries);
|
|
35458
|
+
return seal ? [...entries, { seq: (entries.at(-1)?.seq ?? -1) + 1, event: seal }] : entries;
|
|
35237
35459
|
}
|
|
35238
35460
|
archivedAttachment(archiveId, file) {
|
|
35239
35461
|
const files = this.archive.chatFiles(archiveId);
|
|
35240
|
-
return files && isAttachmentFile(file) ?
|
|
35462
|
+
return files && isAttachmentFile(file) ? join32(files.attachments, file) : null;
|
|
35241
35463
|
}
|
|
35242
35464
|
archivedGit(archiveId) {
|
|
35243
35465
|
const rec = this.archive.get(archiveId);
|
|
@@ -35293,7 +35515,7 @@ class WorktreeService {
|
|
|
35293
35515
|
throw new UserError(`${old.title} was archived without its commits, so there is nothing to restore`);
|
|
35294
35516
|
if (rec.auto)
|
|
35295
35517
|
log.info(old.id, `restoring a worktree that archived itself (${rec.auto})`);
|
|
35296
|
-
const path =
|
|
35518
|
+
const path = existsSync36(old.path) ? join32(dirname13(old.path), freeSlot(dirname13(old.path)).dir) : old.path;
|
|
35297
35519
|
const { variant: _variant, ...rest } = old;
|
|
35298
35520
|
const wt = {
|
|
35299
35521
|
...rest,
|
|
@@ -35332,7 +35554,7 @@ class WorktreeService {
|
|
|
35332
35554
|
run.finish(0);
|
|
35333
35555
|
this.arriving.delete(wt.id);
|
|
35334
35556
|
wt.branch = branch;
|
|
35335
|
-
move(chat.plans,
|
|
35557
|
+
move(chat.plans, join32(path, PLANS_DIR));
|
|
35336
35558
|
const dropped = await git(repo.path, "update-ref", "-d", archiveRef(old.id));
|
|
35337
35559
|
if (!dropped.ok)
|
|
35338
35560
|
log.warn(old.id, `could not drop its archive ref: ${dropped.err}`);
|
|
@@ -35408,12 +35630,12 @@ class WorktreeService {
|
|
|
35408
35630
|
return;
|
|
35409
35631
|
const repo = this.repoOf(rec);
|
|
35410
35632
|
const repoPath = repo?.path ?? rec.repoPath;
|
|
35411
|
-
if (rec.kept &&
|
|
35633
|
+
if (rec.kept && existsSync36(repoPath)) {
|
|
35412
35634
|
const r = await git(repoPath, "update-ref", "-d", archiveRef(archiveId));
|
|
35413
35635
|
if (!r.ok)
|
|
35414
35636
|
log.warn(archiveId, `could not drop its archive ref: ${r.err}`);
|
|
35415
35637
|
}
|
|
35416
|
-
if (rec.worktree.lands?.length &&
|
|
35638
|
+
if (rec.worktree.lands?.length && existsSync36(repoPath))
|
|
35417
35639
|
await dropLandRefs(repoPath, archiveId);
|
|
35418
35640
|
this.archive.delete(archiveId);
|
|
35419
35641
|
this.d.drafts?.drop(archiveId);
|
|
@@ -35474,8 +35696,7 @@ class WorktreeService {
|
|
|
35474
35696
|
throw new UserError(`${w.title} cannot be grafted`);
|
|
35475
35697
|
if (w.repoId !== target.repoId)
|
|
35476
35698
|
throw new UserError("worktrees must belong to one repo");
|
|
35477
|
-
|
|
35478
|
-
if (status === "working" || status === "waiting")
|
|
35699
|
+
if (isBusy(this.d.runtime.agentFor(w.id)?.status))
|
|
35479
35700
|
throw new UserError(`${w.title}'s agent is mid-turn; stop it first`);
|
|
35480
35701
|
}
|
|
35481
35702
|
for (const w of all) {
|
|
@@ -35521,10 +35742,10 @@ class WorktreeService {
|
|
|
35521
35742
|
}
|
|
35522
35743
|
}
|
|
35523
35744
|
async mirrorBaseIgnore(repo) {
|
|
35524
|
-
const src =
|
|
35525
|
-
const tracked =
|
|
35526
|
-
const mirror =
|
|
35527
|
-
const lines = mirror ?
|
|
35745
|
+
const src = join32(repo.path, ".gitignore");
|
|
35746
|
+
const tracked = existsSync36(src) && (await git(repo.path, "ls-files", "--", ".gitignore")).out !== "";
|
|
35747
|
+
const mirror = existsSync36(src) && !tracked;
|
|
35748
|
+
const lines = mirror ? readFileSync21(src, "utf8").split(`
|
|
35528
35749
|
`).filter((l) => l.trim() !== "") : [];
|
|
35529
35750
|
await excludeBlock(repo.path, BASE_IGNORE, lines);
|
|
35530
35751
|
}
|
|
@@ -35536,9 +35757,9 @@ class WorktreeService {
|
|
|
35536
35757
|
await this.d.cache.restore(wt, repo, (line) => this.d.hub.emit("log", wt.id, "setup", line));
|
|
35537
35758
|
run.finish(0);
|
|
35538
35759
|
}
|
|
35539
|
-
const srcNm =
|
|
35540
|
-
const dstNm =
|
|
35541
|
-
if (
|
|
35760
|
+
const srcNm = join32(depsSource, "node_modules");
|
|
35761
|
+
const dstNm = join32(wt.path, "node_modules");
|
|
35762
|
+
if (existsSync36(srcNm) && !existsSync36(dstNm)) {
|
|
35542
35763
|
const run = this.runs.begin(wt.id, "setup", { timeoutMs: ceiling, stage: "copying dependencies" });
|
|
35543
35764
|
const r = await cloneTree(srcNm, dstNm);
|
|
35544
35765
|
run.finish(0);
|
|
@@ -35548,10 +35769,10 @@ class WorktreeService {
|
|
|
35548
35769
|
log.warn(wt.id, "could not copy node_modules from the base checkout", r.error);
|
|
35549
35770
|
}
|
|
35550
35771
|
for (const f of LOCAL_CONFIG_FILES) {
|
|
35551
|
-
const src =
|
|
35552
|
-
if (!
|
|
35772
|
+
const src = join32(depsSource, f);
|
|
35773
|
+
if (!existsSync36(src) || existsSync36(join32(wt.path, f)))
|
|
35553
35774
|
continue;
|
|
35554
|
-
const r = await run("cp", [src,
|
|
35775
|
+
const r = await run("cp", [src, join32(wt.path, f)], wt.path);
|
|
35555
35776
|
if (r.ok)
|
|
35556
35777
|
this.d.hub.emit("log", wt.id, "setup", `copied ${f}`);
|
|
35557
35778
|
else
|
|
@@ -35771,8 +35992,7 @@ ${wt.landing.body}` : s;
|
|
|
35771
35992
|
});
|
|
35772
35993
|
}
|
|
35773
35994
|
async movedMidTurn(wt) {
|
|
35774
|
-
|
|
35775
|
-
if (status !== "working" && status !== "waiting")
|
|
35995
|
+
if (!isBusy(this.d.runtime.agentFor(wt.id)?.status))
|
|
35776
35996
|
return null;
|
|
35777
35997
|
const l = wt.landing;
|
|
35778
35998
|
if (!l || l.fingerprint === await this.fingerprint(wt.path))
|
|
@@ -35821,8 +36041,7 @@ ${wt.landing.body}` : s;
|
|
|
35821
36041
|
this.ops.delete(id);
|
|
35822
36042
|
release?.();
|
|
35823
36043
|
this.d.hub.emit("worktreesChanged");
|
|
35824
|
-
|
|
35825
|
-
if (status !== "working" && status !== "waiting")
|
|
36044
|
+
if (!isBusy(this.d.runtime.agentFor(id)?.status))
|
|
35826
36045
|
this.syncAfterTurn(id);
|
|
35827
36046
|
}
|
|
35828
36047
|
}
|
|
@@ -36112,8 +36331,8 @@ ${wt.landing.body}` : wt.landing.subject : undefined);
|
|
|
36112
36331
|
const repo = this.d.state.requireRepo(r.repoId);
|
|
36113
36332
|
const own = r.wt ? hasOwnBranch(r.wt) : false;
|
|
36114
36333
|
const carry = !!r.wt;
|
|
36115
|
-
const
|
|
36116
|
-
if (carry &&
|
|
36334
|
+
const busy = isBusy(this.d.runtime.agentFor(worktreeId)?.status);
|
|
36335
|
+
if (carry && busy && (await statusFiles(r.path)).length > 0) {
|
|
36117
36336
|
this.syncQueued.add(worktreeId);
|
|
36118
36337
|
this.d.hub.emit("worktreesChanged");
|
|
36119
36338
|
return { result: { ok: true, message: `${r.name} syncs from ${r.base} once the turn ends` }, base: r.base };
|
|
@@ -36501,6 +36720,7 @@ ${wt.landing.body}` : wt.landing.subject : undefined);
|
|
|
36501
36720
|
procs: rt?.procs?.states() ?? [],
|
|
36502
36721
|
borrowed: rt?.borrowed.size ? [...rt.borrowed] : undefined,
|
|
36503
36722
|
agent: rt?.agent.status ?? "idle",
|
|
36723
|
+
stopping: rt?.agent.stopping || undefined,
|
|
36504
36724
|
login: !!rt?.login,
|
|
36505
36725
|
ahead,
|
|
36506
36726
|
behind,
|
|
@@ -36625,7 +36845,7 @@ class ArchiveSweep {
|
|
|
36625
36845
|
process.on("unhandledRejection", (e) => log.error("daemon", "unhandled rejection", e));
|
|
36626
36846
|
process.on("uncaughtException", (e) => log.error("daemon", "uncaught exception", e));
|
|
36627
36847
|
log.info("daemon", `toyon ${package_default.version} on bun ${Bun.version}, pid ${process.pid}, ${process.argv[1]}`);
|
|
36628
|
-
var here =
|
|
36848
|
+
var here = dirname14(fileURLToPath(import.meta.url));
|
|
36629
36849
|
var {
|
|
36630
36850
|
shellDist: SHELL_DIST,
|
|
36631
36851
|
bridgeJs: BRIDGE_JS,
|
|
@@ -36641,17 +36861,17 @@ if (pruned > 0)
|
|
|
36641
36861
|
var managed = await loadManaged();
|
|
36642
36862
|
var paths = makePaths();
|
|
36643
36863
|
ensureDirs(paths);
|
|
36644
|
-
forwardTranscripts([paths.transcriptsDir, paths.archiveDir],
|
|
36864
|
+
forwardTranscripts([paths.transcriptsDir, paths.archiveDir], join33(paths.home, "transcripts-forwarded"));
|
|
36645
36865
|
var token = loadOrCreateToken(paths);
|
|
36646
36866
|
var port = Number(process.env.TOYON_PORT ?? DAEMON_DEFAULT_PORT);
|
|
36647
|
-
var helperApp =
|
|
36867
|
+
var helperApp = join33(paths.home, DAEMON_FILES.helper);
|
|
36648
36868
|
var helper = helperWanted({ platform: process.platform, cloud: cloud.enabled, port, home: process.env.TOYON_HOME }) ? new Helper({
|
|
36649
36869
|
dir: helperApp,
|
|
36650
36870
|
stub: HELPER_STUB,
|
|
36651
36871
|
bun: process.execPath,
|
|
36652
36872
|
cli: CLI_ENTRY,
|
|
36653
|
-
log:
|
|
36654
|
-
icon:
|
|
36873
|
+
log: join33(paths.home, DAEMON_FILES.launcherLog),
|
|
36874
|
+
icon: join33(SHELL_DIST, "icon.svg"),
|
|
36655
36875
|
version: package_default.version
|
|
36656
36876
|
}) : null;
|
|
36657
36877
|
if (helper) {
|
|
@@ -36799,7 +37019,15 @@ var opens = new OpenService({
|
|
|
36799
37019
|
hub,
|
|
36800
37020
|
register: (path) => repos.register(path),
|
|
36801
37021
|
found: () => worktrees.discovered(),
|
|
36802
|
-
refused: [
|
|
37022
|
+
refused: [
|
|
37023
|
+
paths.stateFile,
|
|
37024
|
+
paths.draftsFile,
|
|
37025
|
+
paths.draftAttachmentsFile,
|
|
37026
|
+
paths.remoteFile,
|
|
37027
|
+
paths.pidFile,
|
|
37028
|
+
paths.tokenFile,
|
|
37029
|
+
paths.gitCredentialsFile
|
|
37030
|
+
]
|
|
36803
37031
|
});
|
|
36804
37032
|
var idle = new IdlePolicy({
|
|
36805
37033
|
runtime,
|
|
@@ -36945,7 +37173,7 @@ hub.on("remoteChanged", () => {
|
|
|
36945
37173
|
fireAndForget("remote", tailnet.refresh(), "ask Tailscale");
|
|
36946
37174
|
});
|
|
36947
37175
|
fireAndForget("remote", tailnet.start(), "ask Tailscale");
|
|
36948
|
-
|
|
37176
|
+
writeFileSync14(paths.pidFile, `${process.pid}
|
|
36949
37177
|
`);
|
|
36950
37178
|
var stopLagSampler = startLagSampler();
|
|
36951
37179
|
fireAndForget("daemon", run("sh", ["-c", "ulimit -n"], homedir15()).then((r) => {
|