@pi-unipi/unipi 3.0.0 → 3.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +20 -1
- package/README.md +10 -134
- package/package.json +23 -23
- package/packages/app-bridge/package.json +2 -2
- package/packages/ask-user/package.json +2 -2
- package/packages/autocomplete/package.json +1 -1
- package/packages/background-tasks/package.json +2 -2
- package/packages/btw/package.json +2 -2
- package/packages/compactor/package.json +3 -3
- package/packages/core/README.md +4 -1
- package/packages/core/index.ts +1 -0
- package/packages/core/package.json +1 -1
- package/packages/core/src/settings/snapshot.ts +247 -0
- package/packages/dream/package.json +2 -2
- package/packages/footer/package.json +3 -3
- package/packages/fusion/package.json +4 -4
- package/packages/info-screen/package.json +2 -2
- package/packages/input-shortcuts/package.json +2 -2
- package/packages/kanboard/package.json +7 -7
- package/packages/long-horizon/README.md +1 -3
- package/packages/long-horizon/index.ts +131 -27
- package/packages/long-horizon/package.json +2 -2
- package/packages/long-horizon/src/owner.ts +33 -1
- package/packages/long-horizon/src/session-state.ts +366 -0
- package/packages/long-horizon/src/tools/graph.ts +10 -6
- package/packages/mcp/package.json +2 -2
- package/packages/memory/package.json +3 -3
- package/packages/notify/package.json +2 -2
- package/packages/skill-registry/package.json +2 -2
- package/packages/subagents/package.json +3 -3
- package/packages/subagents/src/index.ts +29 -5
- package/packages/unipi/bundled.js +950 -464
- package/packages/unipi/index.ts +18 -1
- package/packages/updater/package.json +2 -2
- package/packages/utility/package.json +2 -2
- package/packages/watchdog/package.json +3 -3
- package/packages/web-api/package.json +2 -2
- package/packages/workflow/package.json +2 -2
|
@@ -4250,8 +4250,183 @@ var init_schema = __esm({
|
|
|
4250
4250
|
}
|
|
4251
4251
|
});
|
|
4252
4252
|
|
|
4253
|
+
// packages/core/src/settings/snapshot.ts
|
|
4254
|
+
import { mkdirSync as mkdirSync8, readFileSync as readFileSync5, renameSync as renameSync3, writeFileSync as writeFileSync7 } from "node:fs";
|
|
4255
|
+
import { dirname as dirname4 } from "node:path";
|
|
4256
|
+
import { fileURLToPath } from "node:url";
|
|
4257
|
+
function coreVersion() {
|
|
4258
|
+
try {
|
|
4259
|
+
const pkg = new URL("../../package.json", import.meta.url);
|
|
4260
|
+
const parsed = JSON.parse(readFileSync5(fileURLToPath(pkg), "utf8"));
|
|
4261
|
+
return typeof parsed.version === "string" ? parsed.version : void 0;
|
|
4262
|
+
} catch {
|
|
4263
|
+
return void 0;
|
|
4264
|
+
}
|
|
4265
|
+
}
|
|
4266
|
+
function snapshotField(field) {
|
|
4267
|
+
const base = {
|
|
4268
|
+
key: field.key,
|
|
4269
|
+
label: field.label,
|
|
4270
|
+
...field.description !== void 0 ? { description: field.description } : {},
|
|
4271
|
+
...field.scopes !== void 0 ? { scopes: [...field.scopes] } : {},
|
|
4272
|
+
// validate stays in pi; the flag keeps the fact visible in the catalog.
|
|
4273
|
+
validated: "validate" in field && typeof field.validate === "function"
|
|
4274
|
+
};
|
|
4275
|
+
try {
|
|
4276
|
+
switch (field.type) {
|
|
4277
|
+
case "boolean":
|
|
4278
|
+
return { ...base, type: "boolean" };
|
|
4279
|
+
case "enum":
|
|
4280
|
+
return {
|
|
4281
|
+
...base,
|
|
4282
|
+
type: "enum",
|
|
4283
|
+
options: field.options.map(enumOption),
|
|
4284
|
+
...field.plainOptions !== void 0 ? { plainOptions: field.plainOptions } : {},
|
|
4285
|
+
...field.allowCustom !== void 0 ? { allowCustom: field.allowCustom } : {},
|
|
4286
|
+
...field.hint !== void 0 ? { hint: field.hint } : {},
|
|
4287
|
+
...field.scope !== void 0 ? { scope: field.scope } : {},
|
|
4288
|
+
...field.clearable !== void 0 ? { clearable: field.clearable } : {}
|
|
4289
|
+
};
|
|
4290
|
+
case "string":
|
|
4291
|
+
case "secret":
|
|
4292
|
+
return {
|
|
4293
|
+
...base,
|
|
4294
|
+
type: field.type,
|
|
4295
|
+
...field.emptyLabel !== void 0 ? { emptyLabel: field.emptyLabel } : {},
|
|
4296
|
+
...field.hint !== void 0 ? { hint: field.hint } : {}
|
|
4297
|
+
};
|
|
4298
|
+
case "number":
|
|
4299
|
+
return {
|
|
4300
|
+
...base,
|
|
4301
|
+
type: "number",
|
|
4302
|
+
...field.min !== void 0 ? { min: field.min } : {},
|
|
4303
|
+
...field.max !== void 0 ? { max: field.max } : {},
|
|
4304
|
+
...field.unit !== void 0 ? { unit: field.unit } : {},
|
|
4305
|
+
...field.zeroLabel !== void 0 ? { zeroLabel: field.zeroLabel } : {},
|
|
4306
|
+
...field.hint !== void 0 ? { hint: field.hint } : {}
|
|
4307
|
+
};
|
|
4308
|
+
case "model":
|
|
4309
|
+
return {
|
|
4310
|
+
...base,
|
|
4311
|
+
type: "model",
|
|
4312
|
+
...field.provider !== void 0 ? { provider: field.provider } : {},
|
|
4313
|
+
...field.capability !== void 0 ? { capability: field.capability } : {},
|
|
4314
|
+
...field.emptyLabel !== void 0 ? { emptyLabel: field.emptyLabel } : {},
|
|
4315
|
+
...field.presets !== void 0 ? { presets: [...field.presets] } : {},
|
|
4316
|
+
...field.presetsByProvider !== void 0 ? { presetsByProvider: Object.fromEntries(Object.entries(field.presetsByProvider).map(([k, v]) => [k, [...v]])) } : {},
|
|
4317
|
+
...field.emptyOption !== void 0 ? { emptyOption: field.emptyOption } : {},
|
|
4318
|
+
...field.providerKey !== void 0 ? { providerKey: field.providerKey } : {},
|
|
4319
|
+
// The filter is a function; only the fact that the catalog is filtered survives.
|
|
4320
|
+
...field.filter !== void 0 ? { filtered: true } : {}
|
|
4321
|
+
};
|
|
4322
|
+
case "multiselect":
|
|
4323
|
+
return {
|
|
4324
|
+
...base,
|
|
4325
|
+
type: "multiselect",
|
|
4326
|
+
options: field.options.map(enumOption),
|
|
4327
|
+
...field.plainOptions !== void 0 ? { plainOptions: field.plainOptions } : {},
|
|
4328
|
+
...field.emptyLabel !== void 0 ? { emptyLabel: field.emptyLabel } : {}
|
|
4329
|
+
};
|
|
4330
|
+
case "order":
|
|
4331
|
+
return { ...base, type: "order", items: field.items().map((i) => ({ value: i.value, label: i.label })) };
|
|
4332
|
+
case "page":
|
|
4333
|
+
return { ...base, type: "page", sections: snapshotSections(typeof field.sections === "function" ? field.sections() : field.sections) };
|
|
4334
|
+
case "action":
|
|
4335
|
+
return { ...base, type: "action", command: field.command };
|
|
4336
|
+
default:
|
|
4337
|
+
return void 0;
|
|
4338
|
+
}
|
|
4339
|
+
} catch {
|
|
4340
|
+
return void 0;
|
|
4341
|
+
}
|
|
4342
|
+
}
|
|
4343
|
+
function snapshotSection(section3) {
|
|
4344
|
+
try {
|
|
4345
|
+
const fields = [];
|
|
4346
|
+
for (const field of section3.fields) {
|
|
4347
|
+
const snap = snapshotField(field);
|
|
4348
|
+
if (snap) fields.push(snap);
|
|
4349
|
+
}
|
|
4350
|
+
return {
|
|
4351
|
+
title: section3.title,
|
|
4352
|
+
...section3.description !== void 0 ? { description: section3.description } : {},
|
|
4353
|
+
...section3.advanced !== void 0 ? { advanced: section3.advanced } : {},
|
|
4354
|
+
fields
|
|
4355
|
+
};
|
|
4356
|
+
} catch {
|
|
4357
|
+
return void 0;
|
|
4358
|
+
}
|
|
4359
|
+
}
|
|
4360
|
+
function snapshotSections(sections) {
|
|
4361
|
+
const out = [];
|
|
4362
|
+
for (const section3 of sections) {
|
|
4363
|
+
const snap = snapshotSection(section3);
|
|
4364
|
+
if (snap) out.push(snap);
|
|
4365
|
+
}
|
|
4366
|
+
return out;
|
|
4367
|
+
}
|
|
4368
|
+
function snapshotNamespace(definition) {
|
|
4369
|
+
return {
|
|
4370
|
+
namespace: definition.namespace,
|
|
4371
|
+
label: definition.label,
|
|
4372
|
+
defaults: definition.defaults,
|
|
4373
|
+
projectOverrides: definition.projectOverrides !== false,
|
|
4374
|
+
mirrored: typeof definition.onSet === "function",
|
|
4375
|
+
sections: snapshotSections(definition.schema ?? [])
|
|
4376
|
+
};
|
|
4377
|
+
}
|
|
4378
|
+
function buildSettingsSnapshot() {
|
|
4379
|
+
const version = coreVersion();
|
|
4380
|
+
return {
|
|
4381
|
+
version: 1,
|
|
4382
|
+
writtenAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
4383
|
+
...version !== void 0 ? { unipiVersion: version } : {},
|
|
4384
|
+
namespaces: listSettingsDefinitions().map(snapshotNamespace)
|
|
4385
|
+
};
|
|
4386
|
+
}
|
|
4387
|
+
function writeSettingsSnapshot() {
|
|
4388
|
+
try {
|
|
4389
|
+
const snapshot2 = buildSettingsSnapshot();
|
|
4390
|
+
const file = joinPath(unipiConfigRoot(), SNAPSHOT_FILE);
|
|
4391
|
+
mkdirSync8(dirname4(file), { recursive: true });
|
|
4392
|
+
const previous = readPrevious(file);
|
|
4393
|
+
if (previous && sameExceptWrittenAt(previous, snapshot2)) return;
|
|
4394
|
+
const tmp = `${file}.tmp`;
|
|
4395
|
+
writeFileSync7(tmp, `${JSON.stringify(snapshot2, null, 2)}
|
|
4396
|
+
`);
|
|
4397
|
+
renameSync3(tmp, file);
|
|
4398
|
+
} catch {
|
|
4399
|
+
}
|
|
4400
|
+
}
|
|
4401
|
+
function joinPath(root, file) {
|
|
4402
|
+
return root.endsWith("/") ? `${root}${file}` : `${root}/${file}`;
|
|
4403
|
+
}
|
|
4404
|
+
function readPrevious(file) {
|
|
4405
|
+
try {
|
|
4406
|
+
const parsed = JSON.parse(readFileSync5(file, "utf8"));
|
|
4407
|
+
return parsed && typeof parsed === "object" ? parsed : void 0;
|
|
4408
|
+
} catch {
|
|
4409
|
+
return void 0;
|
|
4410
|
+
}
|
|
4411
|
+
}
|
|
4412
|
+
function sameExceptWrittenAt(a, b) {
|
|
4413
|
+
const { writtenAt: _a, ...restA } = a;
|
|
4414
|
+
const { writtenAt: _b, ...restB } = b;
|
|
4415
|
+
return JSON.stringify(restA) === JSON.stringify(restB);
|
|
4416
|
+
}
|
|
4417
|
+
var SNAPSHOT_FILE;
|
|
4418
|
+
var init_snapshot = __esm({
|
|
4419
|
+
"packages/core/src/settings/snapshot.ts"() {
|
|
4420
|
+
"use strict";
|
|
4421
|
+
init_engine();
|
|
4422
|
+
init_paths2();
|
|
4423
|
+
init_schema();
|
|
4424
|
+
SNAPSHOT_FILE = "settings-schema.json";
|
|
4425
|
+
}
|
|
4426
|
+
});
|
|
4427
|
+
|
|
4253
4428
|
// packages/core/src/settings/catalog.ts
|
|
4254
|
-
import { readFileSync as
|
|
4429
|
+
import { readFileSync as readFileSync6 } from "node:fs";
|
|
4255
4430
|
import { homedir as homedir6 } from "node:os";
|
|
4256
4431
|
import { join as join9 } from "node:path";
|
|
4257
4432
|
function defaultModelCatalogPath() {
|
|
@@ -4276,7 +4451,7 @@ function loadModelCatalog(path31 = defaultModelCatalogPath()) {
|
|
|
4276
4451
|
}
|
|
4277
4452
|
function loadModelCatalogEntries(path31 = defaultModelCatalogPath()) {
|
|
4278
4453
|
const isDefault = path31 === defaultModelCatalogPath();
|
|
4279
|
-
const fromFile = parseModelCatalogEntries(() =>
|
|
4454
|
+
const fromFile = parseModelCatalogEntries(() => readFileSync6(path31, "utf8"));
|
|
4280
4455
|
if (!isDefault) return fromFile;
|
|
4281
4456
|
const cached2 = readModelCache().map((m) => ({
|
|
4282
4457
|
id: modelRef(m),
|
|
@@ -5405,7 +5580,7 @@ var init_open = __esm({
|
|
|
5405
5580
|
});
|
|
5406
5581
|
|
|
5407
5582
|
// packages/core/src/attach/detect.ts
|
|
5408
|
-
import { existsSync as existsSync6, readFileSync as
|
|
5583
|
+
import { existsSync as existsSync6, readFileSync as readFileSync7, statSync as statSync4 } from "node:fs";
|
|
5409
5584
|
import { homedir as homedir7 } from "node:os";
|
|
5410
5585
|
import { basename, extname } from "node:path";
|
|
5411
5586
|
function tokenFor(a) {
|
|
@@ -5474,7 +5649,7 @@ function tokenize(text, existing, size = (p) => statSync4(p).size, exists) {
|
|
|
5474
5649
|
function stillReferenced(text, attachments) {
|
|
5475
5650
|
return attachments.filter((a) => text.includes(tokenFor(a)));
|
|
5476
5651
|
}
|
|
5477
|
-
function expandForSubmit(text, attachments, read = (p) =>
|
|
5652
|
+
function expandForSubmit(text, attachments, read = (p) => readFileSync7(p)) {
|
|
5478
5653
|
const used = stillReferenced(text, attachments).sort((a, b) => text.indexOf(tokenFor(a)) - text.indexOf(tokenFor(b)));
|
|
5479
5654
|
const images = [];
|
|
5480
5655
|
let out = text;
|
|
@@ -5753,7 +5928,7 @@ var init_move = __esm({
|
|
|
5753
5928
|
});
|
|
5754
5929
|
|
|
5755
5930
|
// packages/core/src/hints/store.ts
|
|
5756
|
-
import { readFileSync as
|
|
5931
|
+
import { readFileSync as readFileSync8, writeFileSync as writeFileSync8, unlinkSync as unlinkSync2 } from "node:fs";
|
|
5757
5932
|
function emptyStore() {
|
|
5758
5933
|
return {
|
|
5759
5934
|
counts: {},
|
|
@@ -5764,7 +5939,7 @@ function emptyStore() {
|
|
|
5764
5939
|
function loadHintStore() {
|
|
5765
5940
|
if (cache2) return cache2;
|
|
5766
5941
|
try {
|
|
5767
|
-
const raw =
|
|
5942
|
+
const raw = readFileSync8(statePath("hints", "hints.json", "global"), "utf-8");
|
|
5768
5943
|
const parsed = JSON.parse(raw);
|
|
5769
5944
|
if (typeof parsed === "object" && parsed !== null) {
|
|
5770
5945
|
cache2 = {
|
|
@@ -5783,7 +5958,7 @@ function loadHintStore() {
|
|
|
5783
5958
|
function saveStore() {
|
|
5784
5959
|
if (!cache2) return;
|
|
5785
5960
|
try {
|
|
5786
|
-
|
|
5961
|
+
writeFileSync8(statePath("hints", "hints.json", "global"), JSON.stringify(cache2, null, 2));
|
|
5787
5962
|
} catch {
|
|
5788
5963
|
}
|
|
5789
5964
|
}
|
|
@@ -5818,7 +5993,7 @@ function resetHintHistory() {
|
|
|
5818
5993
|
store.counts = {};
|
|
5819
5994
|
store.learned = [];
|
|
5820
5995
|
try {
|
|
5821
|
-
|
|
5996
|
+
writeFileSync8(statePath("hints", "hints.json", "global"), JSON.stringify(store, null, 2));
|
|
5822
5997
|
} catch {
|
|
5823
5998
|
}
|
|
5824
5999
|
}
|
|
@@ -6948,7 +7123,7 @@ var init_lines = __esm({
|
|
|
6948
7123
|
});
|
|
6949
7124
|
|
|
6950
7125
|
// packages/core/src/hints/index.ts
|
|
6951
|
-
import { fileURLToPath } from "node:url";
|
|
7126
|
+
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
6952
7127
|
import {
|
|
6953
7128
|
encodeKitty,
|
|
6954
7129
|
deleteKittyImage,
|
|
@@ -7255,7 +7430,7 @@ function installHints(pi) {
|
|
|
7255
7430
|
try {
|
|
7256
7431
|
const v = getInstalledPackageVersion(cwd, "@pi-unipi/unipi");
|
|
7257
7432
|
if (v !== "0.0.0") return v;
|
|
7258
|
-
const thisDir =
|
|
7433
|
+
const thisDir = fileURLToPath2(new URL(".", import.meta.url));
|
|
7259
7434
|
return getInstalledPackageVersion(thisDir, "@pi-unipi/unipi");
|
|
7260
7435
|
} catch {
|
|
7261
7436
|
return "0.0.0";
|
|
@@ -7972,6 +8147,7 @@ __export(core_exports, {
|
|
|
7972
8147
|
boundModelOutput: () => boundModelOutput,
|
|
7973
8148
|
boxInnerWidth: () => boxInnerWidth,
|
|
7974
8149
|
brailleArea: () => brailleArea,
|
|
8150
|
+
buildSettingsSnapshot: () => buildSettingsSnapshot,
|
|
7975
8151
|
bus: () => bus,
|
|
7976
8152
|
callCommandRunner: () => callCommandRunner,
|
|
7977
8153
|
centerTo: () => centerTo,
|
|
@@ -8259,7 +8435,8 @@ __export(core_exports, {
|
|
|
8259
8435
|
workspaceRoot: () => workspaceRoot,
|
|
8260
8436
|
writeFile: () => writeFile,
|
|
8261
8437
|
writeJson: () => writeJson,
|
|
8262
|
-
writeModelCache: () => writeModelCache
|
|
8438
|
+
writeModelCache: () => writeModelCache,
|
|
8439
|
+
writeSettingsSnapshot: () => writeSettingsSnapshot
|
|
8263
8440
|
});
|
|
8264
8441
|
var init_core = __esm({
|
|
8265
8442
|
"packages/core/index.ts"() {
|
|
@@ -8298,6 +8475,7 @@ var init_core = __esm({
|
|
|
8298
8475
|
init_paths2();
|
|
8299
8476
|
init_engine();
|
|
8300
8477
|
init_schema();
|
|
8478
|
+
init_snapshot();
|
|
8301
8479
|
init_hub();
|
|
8302
8480
|
init_open();
|
|
8303
8481
|
init_detect();
|
|
@@ -8994,7 +9172,7 @@ var init_schema2 = __esm({
|
|
|
8994
9172
|
|
|
8995
9173
|
// packages/compactor/src/config/manager.ts
|
|
8996
9174
|
import { homedir as homedir45 } from "node:os";
|
|
8997
|
-
import { join as
|
|
9175
|
+
import { join as join75 } from "node:path";
|
|
8998
9176
|
function translateLegacyConfig(raw) {
|
|
8999
9177
|
const out = {};
|
|
9000
9178
|
for (const key of Object.keys(DEFAULT_COMPACTOR_CONFIG)) {
|
|
@@ -9165,7 +9343,7 @@ var init_manager = __esm({
|
|
|
9165
9343
|
}
|
|
9166
9344
|
]
|
|
9167
9345
|
});
|
|
9168
|
-
COMPACTOR_CONFIG_PATH =
|
|
9346
|
+
COMPACTOR_CONFIG_PATH = join75(homedir45(), ".unipi", "config", "compactor", "config.json");
|
|
9169
9347
|
isRecord12 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
9170
9348
|
}
|
|
9171
9349
|
});
|
|
@@ -9395,12 +9573,12 @@ init_core();
|
|
|
9395
9573
|
|
|
9396
9574
|
// packages/utility/src/index.ts
|
|
9397
9575
|
init_core();
|
|
9398
|
-
import { dirname as
|
|
9399
|
-
import { fileURLToPath as
|
|
9576
|
+
import { dirname as dirname7 } from "node:path";
|
|
9577
|
+
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
9400
9578
|
import { ToolExecutionComponent as ToolExecutionComponent2 } from "@earendil-works/pi-coding-agent";
|
|
9401
9579
|
|
|
9402
9580
|
// packages/utility/src/browser/state.ts
|
|
9403
|
-
import { existsSync as existsSync7, readFileSync as
|
|
9581
|
+
import { existsSync as existsSync7, readFileSync as readFileSync9 } from "node:fs";
|
|
9404
9582
|
import { homedir as homedir8 } from "node:os";
|
|
9405
9583
|
import { join as join11 } from "node:path";
|
|
9406
9584
|
import { execFile } from "node:child_process";
|
|
@@ -9410,7 +9588,7 @@ function hostDir(env = process.env) {
|
|
|
9410
9588
|
function readHostConfig(path31) {
|
|
9411
9589
|
if (!existsSync7(path31)) return { kind: "missing" };
|
|
9412
9590
|
try {
|
|
9413
|
-
const raw =
|
|
9591
|
+
const raw = readFileSync9(path31, "utf8");
|
|
9414
9592
|
const parsed = JSON.parse(raw);
|
|
9415
9593
|
if (!parsed || typeof parsed !== "object") return { kind: "malformed" };
|
|
9416
9594
|
return { kind: "ok", config: parsed };
|
|
@@ -9468,7 +9646,7 @@ function browserSectionText(running) {
|
|
|
9468
9646
|
}
|
|
9469
9647
|
function readAgentEndpoint(env = process.env) {
|
|
9470
9648
|
try {
|
|
9471
|
-
const raw = JSON.parse(
|
|
9649
|
+
const raw = JSON.parse(readFileSync9(join11(hostDir(env), "browser-agent.json"), "utf8"));
|
|
9472
9650
|
if (typeof raw.port !== "number" || raw.port <= 0 || raw.port > 65535) return void 0;
|
|
9473
9651
|
return { port: raw.port, profile: typeof raw.profile === "string" ? raw.profile : "default", ...typeof raw.pid === "number" ? { pid: raw.pid } : {} };
|
|
9474
9652
|
} catch {
|
|
@@ -10004,7 +10182,7 @@ Removed ${result2.removed} item(s), ${formatBytes2(result2.bytes)}.${failed}`);
|
|
|
10004
10182
|
|
|
10005
10183
|
// packages/utility/src/rename/index.ts
|
|
10006
10184
|
init_core();
|
|
10007
|
-
import { appendFileSync as appendFileSync2, mkdirSync as
|
|
10185
|
+
import { appendFileSync as appendFileSync2, mkdirSync as mkdirSync9 } from "node:fs";
|
|
10008
10186
|
import { homedir as homedir11 } from "node:os";
|
|
10009
10187
|
import { join as join14 } from "node:path";
|
|
10010
10188
|
|
|
@@ -10464,7 +10642,7 @@ function debugLog(line) {
|
|
|
10464
10642
|
if (process.env.UNIPI_DEBUG_RENAME !== "1") return;
|
|
10465
10643
|
try {
|
|
10466
10644
|
const dir = join14(homedir11(), ".unipi", "logs");
|
|
10467
|
-
|
|
10645
|
+
mkdirSync9(dir, { recursive: true });
|
|
10468
10646
|
appendFileSync2(join14(dir, "rename.log"), `${(/* @__PURE__ */ new Date()).toISOString()} ${line}
|
|
10469
10647
|
`);
|
|
10470
10648
|
} catch {
|
|
@@ -10607,12 +10785,12 @@ function registerAutoRename(pi) {
|
|
|
10607
10785
|
// packages/utility/src/move/index.ts
|
|
10608
10786
|
init_core();
|
|
10609
10787
|
import { execFileSync as execFileSync3 } from "node:child_process";
|
|
10610
|
-
import { appendFileSync as appendFileSync3, copyFileSync as copyFileSync2, existsSync as existsSync13, mkdirSync as
|
|
10788
|
+
import { appendFileSync as appendFileSync3, copyFileSync as copyFileSync2, existsSync as existsSync13, mkdirSync as mkdirSync11, realpathSync as realpathSync3 } from "node:fs";
|
|
10611
10789
|
import { homedir as homedir13 } from "node:os";
|
|
10612
|
-
import { basename as basename3, dirname as
|
|
10790
|
+
import { basename as basename3, dirname as dirname5, join as join17, resolve as resolve6 } from "node:path";
|
|
10613
10791
|
|
|
10614
10792
|
// packages/utility/src/move/pi-state.ts
|
|
10615
|
-
import { constants as constants2, copyFileSync, existsSync as existsSync11, mkdirSync as
|
|
10793
|
+
import { constants as constants2, copyFileSync, existsSync as existsSync11, mkdirSync as mkdirSync10, readdirSync as readdirSync4, readFileSync as readFileSync11, rmdirSync, statSync as statSync6, unlinkSync as unlinkSync3, writeFileSync as writeFileSync10, openSync, readSync, closeSync, linkSync, renameSync as renameSync5 } from "node:fs";
|
|
10616
10794
|
import { createReadStream, createWriteStream } from "node:fs";
|
|
10617
10795
|
import { pipeline } from "node:stream/promises";
|
|
10618
10796
|
import { homedir as homedir12 } from "node:os";
|
|
@@ -10691,14 +10869,14 @@ var piSessionsHandler = {
|
|
|
10691
10869
|
return;
|
|
10692
10870
|
}
|
|
10693
10871
|
const original = header(from);
|
|
10694
|
-
|
|
10872
|
+
mkdirSync10(targetDir, { recursive: true });
|
|
10695
10873
|
ctx.log({ area: "pi-sessions", action: "mkdir", from: "", to: targetDir, result: "ok" });
|
|
10696
10874
|
const temporary = `${to}.move-${process.pid}-${Date.now()}`;
|
|
10697
10875
|
try {
|
|
10698
10876
|
if (original.cwd === ctx.oldRoot) {
|
|
10699
10877
|
const parsed = JSON.parse(original.line.replace(/^\uFEFF/, ""));
|
|
10700
10878
|
parsed.cwd = ctx.newRoot;
|
|
10701
|
-
|
|
10879
|
+
writeFileSync10(temporary, `${JSON.stringify(parsed)}
|
|
10702
10880
|
`, { flag: "wx", mode: statSync6(from).mode });
|
|
10703
10881
|
ctx.log({ area: "pi-sessions", action: "rewrite-header", from, to: temporary, result: "ok", originalHeader: original.line });
|
|
10704
10882
|
await pipeline(createReadStream(from, { start: original.offset }), createWriteStream(temporary, { flags: "a" }));
|
|
@@ -10732,7 +10910,7 @@ var piTrustHandler = {
|
|
|
10732
10910
|
scan(ctx) {
|
|
10733
10911
|
const file = join15(agentDir(), "trust.json");
|
|
10734
10912
|
if (!existsSync11(file)) return [];
|
|
10735
|
-
const data = JSON.parse(
|
|
10913
|
+
const data = JSON.parse(readFileSync11(file, "utf8"));
|
|
10736
10914
|
if (!Object.hasOwn(data, ctx.oldRoot)) return [];
|
|
10737
10915
|
return [{
|
|
10738
10916
|
area: "pi-trust",
|
|
@@ -10740,19 +10918,19 @@ var piTrustHandler = {
|
|
|
10740
10918
|
apply() {
|
|
10741
10919
|
if (ctx.dryRun) return;
|
|
10742
10920
|
const lock = `${file}.lock`;
|
|
10743
|
-
|
|
10921
|
+
mkdirSync10(lock);
|
|
10744
10922
|
ctx.log({ area: "pi-trust", action: "lock", from: "", to: lock, result: "ok" });
|
|
10745
10923
|
const temporary = `${file}.move-${process.pid}`;
|
|
10746
10924
|
try {
|
|
10747
|
-
const current = JSON.parse(
|
|
10925
|
+
const current = JSON.parse(readFileSync11(file, "utf8"));
|
|
10748
10926
|
if (!Object.hasOwn(current, ctx.oldRoot)) return;
|
|
10749
10927
|
ctx.backup(file);
|
|
10750
10928
|
current[ctx.newRoot] = current[ctx.oldRoot];
|
|
10751
10929
|
delete current[ctx.oldRoot];
|
|
10752
|
-
|
|
10930
|
+
writeFileSync10(temporary, `${JSON.stringify(current, null, 2)}
|
|
10753
10931
|
`, { flag: "wx", mode: statSync6(file).mode });
|
|
10754
10932
|
ctx.log({ area: "pi-trust", action: "write", from: file, to: temporary, result: "ok" });
|
|
10755
|
-
|
|
10933
|
+
renameSync5(temporary, file);
|
|
10756
10934
|
ctx.log({ area: "pi-trust", action: "replace-key", from: ctx.oldRoot, to: ctx.newRoot, result: "ok" });
|
|
10757
10935
|
} finally {
|
|
10758
10936
|
if (existsSync11(temporary)) {
|
|
@@ -10769,7 +10947,7 @@ var piTrustHandler = {
|
|
|
10769
10947
|
|
|
10770
10948
|
// packages/utility/src/move/git.ts
|
|
10771
10949
|
import { execFileSync as execFileSync2 } from "node:child_process";
|
|
10772
|
-
import { existsSync as existsSync12, readFileSync as
|
|
10950
|
+
import { existsSync as existsSync12, readFileSync as readFileSync12, statSync as statSync7 } from "node:fs";
|
|
10773
10951
|
import { join as join16 } from "node:path";
|
|
10774
10952
|
var gitWorktreesHandler = {
|
|
10775
10953
|
id: "git-worktrees",
|
|
@@ -10784,7 +10962,7 @@ var gitWorktreesHandler = {
|
|
|
10784
10962
|
const entries2 = execFileSync2("git", ["-C", ctx.newRoot, "worktree", "list", "--porcelain"], { encoding: "utf8" }).matchAll(/^worktree (.+)$/gm);
|
|
10785
10963
|
for (const [, root] of entries2) {
|
|
10786
10964
|
const dotgit = join16(root, ".git");
|
|
10787
|
-
if (existsSync12(dotgit) && statSync7(dotgit).isFile() &&
|
|
10965
|
+
if (existsSync12(dotgit) && statSync7(dotgit).isFile() && readFileSync12(dotgit, "utf8").includes(`${ctx.oldRoot}/`)) return true;
|
|
10788
10966
|
}
|
|
10789
10967
|
} catch {
|
|
10790
10968
|
return false;
|
|
@@ -10838,7 +11016,7 @@ function createMoveContext(oldRoot, newRoot, dryRun) {
|
|
|
10838
11016
|
const log = (entry) => {
|
|
10839
11017
|
entries2.push(entry);
|
|
10840
11018
|
if (dryRun) return;
|
|
10841
|
-
|
|
11019
|
+
mkdirSync11(dirname5(logFile), { recursive: true });
|
|
10842
11020
|
appendFileSync3(logFile, `${JSON.stringify(entry)}
|
|
10843
11021
|
`);
|
|
10844
11022
|
};
|
|
@@ -10850,7 +11028,7 @@ function createMoveContext(oldRoot, newRoot, dryRun) {
|
|
|
10850
11028
|
backup(file) {
|
|
10851
11029
|
if (dryRun || !existsSync13(file) || backedUp.has(file)) return;
|
|
10852
11030
|
const destination = join17(backupRoot, resolve6(file).replace(/^[/\\]/, ""));
|
|
10853
|
-
|
|
11031
|
+
mkdirSync11(dirname5(destination), { recursive: true });
|
|
10854
11032
|
copyFileSync2(file, destination);
|
|
10855
11033
|
backedUp.add(file);
|
|
10856
11034
|
log({ area: "backup", action: "copy", from: file, to: destination, result: "ok" });
|
|
@@ -11511,7 +11689,7 @@ function registerSummarizeCommand(pi) {
|
|
|
11511
11689
|
}
|
|
11512
11690
|
|
|
11513
11691
|
// packages/utility/src/attach/index.ts
|
|
11514
|
-
import { readFileSync as
|
|
11692
|
+
import { readFileSync as readFileSync13 } from "node:fs";
|
|
11515
11693
|
import { getCapabilities as getCapabilities2, Image, Key as Key8, matchesKey as matchesKey7, truncateToWidth as truncateToWidth11 } from "@earendil-works/pi-tui";
|
|
11516
11694
|
init_core();
|
|
11517
11695
|
var ATTACHMENTS_ENTRY = "unipi:attachments";
|
|
@@ -11537,7 +11715,7 @@ function attachmentView(items, theme, preview, hint) {
|
|
|
11537
11715
|
if (preview && canPreview()) {
|
|
11538
11716
|
for (const a of items.filter((i) => i.kind === "image").slice(0, PREVIEW_MAX)) {
|
|
11539
11717
|
try {
|
|
11540
|
-
images.push(new Image(
|
|
11718
|
+
images.push(new Image(readFileSync13(a.path).toString("base64"), a.mimeType ?? "image/png", { fallbackColor: (s) => theme.fg("muted", s) }, { maxHeightCells: PREVIEW_ROWS, maxWidthCells: 32, filename: a.name }));
|
|
11541
11719
|
} catch {
|
|
11542
11720
|
}
|
|
11543
11721
|
}
|
|
@@ -13134,12 +13312,12 @@ import {
|
|
|
13134
13312
|
} from "@earendil-works/pi-coding-agent";
|
|
13135
13313
|
|
|
13136
13314
|
// packages/utility/src/render/pi-settings.ts
|
|
13137
|
-
import { readFileSync as
|
|
13315
|
+
import { readFileSync as readFileSync16 } from "node:fs";
|
|
13138
13316
|
import { homedir as homedir15 } from "node:os";
|
|
13139
13317
|
import { join as join22 } from "node:path";
|
|
13140
13318
|
function readJson4(file) {
|
|
13141
13319
|
try {
|
|
13142
|
-
return JSON.parse(
|
|
13320
|
+
return JSON.parse(readFileSync16(file, "utf-8"));
|
|
13143
13321
|
} catch {
|
|
13144
13322
|
return {};
|
|
13145
13323
|
}
|
|
@@ -14958,7 +15136,7 @@ registerSettings({
|
|
|
14958
15136
|
});
|
|
14959
15137
|
|
|
14960
15138
|
// packages/utility/src/index.ts
|
|
14961
|
-
var VERSION = getPackageVersion(
|
|
15139
|
+
var VERSION = getPackageVersion(dirname7(fileURLToPath3(import.meta.url)));
|
|
14962
15140
|
var ALL_COMMANDS = [
|
|
14963
15141
|
UTILITY_COMMANDS.CONTINUE,
|
|
14964
15142
|
UTILITY_COMMANDS.RETRY,
|
|
@@ -15037,12 +15215,12 @@ function src_default(pi) {
|
|
|
15037
15215
|
// packages/workflow/index.ts
|
|
15038
15216
|
init_core();
|
|
15039
15217
|
import { tmpdir as tmpdir4 } from "node:os";
|
|
15040
|
-
import { dirname as
|
|
15041
|
-
import { fileURLToPath as
|
|
15218
|
+
import { dirname as dirname9 } from "node:path";
|
|
15219
|
+
import { fileURLToPath as fileURLToPath4 } from "node:url";
|
|
15042
15220
|
|
|
15043
15221
|
// packages/workflow/src/permission/index.ts
|
|
15044
15222
|
init_core();
|
|
15045
|
-
import { appendFileSync as appendFileSync4, mkdirSync as
|
|
15223
|
+
import { appendFileSync as appendFileSync4, mkdirSync as mkdirSync14 } from "node:fs";
|
|
15046
15224
|
import { homedir as homedir18, tmpdir as tmpdir3 } from "node:os";
|
|
15047
15225
|
|
|
15048
15226
|
// packages/workflow/src/status.ts
|
|
@@ -15643,7 +15821,7 @@ function debugLog2(line) {
|
|
|
15643
15821
|
if (process.env.UNIPI_DEBUG_PERMISSION !== "1") return;
|
|
15644
15822
|
try {
|
|
15645
15823
|
const dir = `${homedir18()}/.unipi/logs`;
|
|
15646
|
-
|
|
15824
|
+
mkdirSync14(dir, { recursive: true });
|
|
15647
15825
|
appendFileSync4(`${dir}/permission.log`, `${(/* @__PURE__ */ new Date()).toISOString()} ${line}
|
|
15648
15826
|
`);
|
|
15649
15827
|
} catch {
|
|
@@ -15790,8 +15968,8 @@ function registerPermissionModes(pi, controller) {
|
|
|
15790
15968
|
import { join as join24, resolve as resolve10, sep as sep3 } from "node:path";
|
|
15791
15969
|
|
|
15792
15970
|
// packages/workflow/src/plan/state.ts
|
|
15793
|
-
import { mkdirSync as
|
|
15794
|
-
import { dirname as
|
|
15971
|
+
import { mkdirSync as mkdirSync15 } from "node:fs";
|
|
15972
|
+
import { dirname as dirname8, join as join23, resolve as resolve9 } from "node:path";
|
|
15795
15973
|
var PLAN_STATE_ENTRY = "unipi:plan-mode";
|
|
15796
15974
|
var PLAN_MESSAGE_TYPE = "unipi:plan-mode-message";
|
|
15797
15975
|
var sessionState = null;
|
|
@@ -15804,7 +15982,7 @@ function planFilePath(cwd, sessionId3) {
|
|
|
15804
15982
|
return resolve9(cwd, "docs", "plans", planFileName(sessionId3));
|
|
15805
15983
|
}
|
|
15806
15984
|
function ensurePlanDir(planFile) {
|
|
15807
|
-
|
|
15985
|
+
mkdirSync15(dirname8(planFile), { recursive: true });
|
|
15808
15986
|
}
|
|
15809
15987
|
function restorePlanState(sessionId3, entries2, cwd) {
|
|
15810
15988
|
sessionState = { sessionId: sessionId3, active: false, planFile: null, lastKeptHash: null };
|
|
@@ -15870,7 +16048,7 @@ function enforcePlanMode(input, state2, cwd, deps) {
|
|
|
15870
16048
|
// packages/workflow/src/plan/index.ts
|
|
15871
16049
|
init_core();
|
|
15872
16050
|
import { createHash } from "node:crypto";
|
|
15873
|
-
import { existsSync as existsSync15, readFileSync as
|
|
16051
|
+
import { existsSync as existsSync15, readFileSync as readFileSync17 } from "node:fs";
|
|
15874
16052
|
import { Type as Type3 } from "typebox";
|
|
15875
16053
|
|
|
15876
16054
|
// packages/workflow/src/plan/review.ts
|
|
@@ -16082,7 +16260,7 @@ function sessionId2(ctx) {
|
|
|
16082
16260
|
}
|
|
16083
16261
|
function readPlanFile(planFile) {
|
|
16084
16262
|
if (!planFile || !existsSync15(planFile)) return null;
|
|
16085
|
-
const content =
|
|
16263
|
+
const content = readFileSync17(planFile, "utf-8").trim();
|
|
16086
16264
|
return content.length > 0 ? content : null;
|
|
16087
16265
|
}
|
|
16088
16266
|
function planContentHash(content) {
|
|
@@ -16391,7 +16569,7 @@ Feedback: ${result2.feedback}` : ""}`
|
|
|
16391
16569
|
}
|
|
16392
16570
|
|
|
16393
16571
|
// packages/workflow/index.ts
|
|
16394
|
-
var VERSION2 = getPackageVersion(
|
|
16572
|
+
var VERSION2 = getPackageVersion(dirname9(fileURLToPath4(import.meta.url)));
|
|
16395
16573
|
function describeToolCall(event) {
|
|
16396
16574
|
const input = event.input ?? {};
|
|
16397
16575
|
const toolName = event.toolName;
|
|
@@ -16466,8 +16644,7 @@ function workflow_default(pi) {
|
|
|
16466
16644
|
|
|
16467
16645
|
// packages/long-horizon/index.ts
|
|
16468
16646
|
init_core();
|
|
16469
|
-
import {
|
|
16470
|
-
import { join as join27, resolve as resolve11 } from "node:path";
|
|
16647
|
+
import { join as join28, resolve as resolve11 } from "node:path";
|
|
16471
16648
|
import { Text as Text2 } from "@earendil-works/pi-tui";
|
|
16472
16649
|
|
|
16473
16650
|
// packages/long-horizon/src/compaction-brief.ts
|
|
@@ -16544,6 +16721,7 @@ var OwnerCoordinator = class {
|
|
|
16544
16721
|
if (this.active) return void 0;
|
|
16545
16722
|
const ownerId = randomUUID3();
|
|
16546
16723
|
const now2 = new Date(this.deps.now?.() ?? Date.now()).toISOString();
|
|
16724
|
+
const session = this.deps.session?.();
|
|
16547
16725
|
const owner = Object.freeze({
|
|
16548
16726
|
ownerId,
|
|
16549
16727
|
kind,
|
|
@@ -16551,7 +16729,10 @@ var OwnerCoordinator = class {
|
|
|
16551
16729
|
status: "active",
|
|
16552
16730
|
revision: 0,
|
|
16553
16731
|
lease: Object.freeze({ ownerId, generation: 0 }),
|
|
16554
|
-
updatedAt: now2
|
|
16732
|
+
updatedAt: now2,
|
|
16733
|
+
...session?.id ? { sessionId: session.id } : {},
|
|
16734
|
+
...session?.name ? { sessionName: session.name } : {},
|
|
16735
|
+
...session?.pid ? { pid: session.pid } : {}
|
|
16555
16736
|
});
|
|
16556
16737
|
this.active = owner;
|
|
16557
16738
|
return this.commit({ type: "activated", owner });
|
|
@@ -16635,6 +16816,19 @@ var OwnerCoordinator = class {
|
|
|
16635
16816
|
} catch {
|
|
16636
16817
|
}
|
|
16637
16818
|
}
|
|
16819
|
+
const session = this.deps.session?.();
|
|
16820
|
+
const refresh = (owner) => {
|
|
16821
|
+
if (!owner) return owner;
|
|
16822
|
+
const stamp = owner.sessionId === void 0 && session?.id ? { sessionId: session.id } : {};
|
|
16823
|
+
const nameInfo = !owner.sessionName && session?.name ? { sessionName: session.name } : {};
|
|
16824
|
+
const pidInfo = session?.pid !== void 0 && owner.pid !== session.pid ? { pid: session.pid } : {};
|
|
16825
|
+
if (!("sessionId" in stamp) && !("sessionName" in nameInfo) && !("pid" in pidInfo)) return owner;
|
|
16826
|
+
const next = this.withOwner(owner, { ...stamp, ...nameInfo, ...pidInfo });
|
|
16827
|
+
this.persist();
|
|
16828
|
+
return next;
|
|
16829
|
+
};
|
|
16830
|
+
if (this.active) this.active = refresh(this.active);
|
|
16831
|
+
if (this.parked) this.parked = refresh(this.parked);
|
|
16638
16832
|
const snapshot2 = this.snapshot();
|
|
16639
16833
|
this.deps.onChange?.(snapshot2, { type: "restored", snapshot: snapshot2 });
|
|
16640
16834
|
return snapshot2;
|
|
@@ -16981,8 +17175,8 @@ async function resolveMode(deps) {
|
|
|
16981
17175
|
|
|
16982
17176
|
// packages/long-horizon/src/settings.ts
|
|
16983
17177
|
init_core();
|
|
16984
|
-
import { existsSync as existsSync16, mkdirSync as
|
|
16985
|
-
import { dirname as
|
|
17178
|
+
import { existsSync as existsSync16, mkdirSync as mkdirSync16, readFileSync as readFileSync18, writeFileSync as writeFileSync13 } from "node:fs";
|
|
17179
|
+
import { dirname as dirname10, join as join25 } from "node:path";
|
|
16986
17180
|
import { homedir as homedir19 } from "node:os";
|
|
16987
17181
|
var DEFAULT_SETTINGS3 = {
|
|
16988
17182
|
judge: {
|
|
@@ -17104,8 +17298,8 @@ function withDecisionModel(settings, cwd) {
|
|
|
17104
17298
|
import { Type as Type4 } from "typebox";
|
|
17105
17299
|
|
|
17106
17300
|
// packages/long-horizon/src/graph/engine.ts
|
|
17107
|
-
import { existsSync as existsSync17, mkdirSync as
|
|
17108
|
-
import { dirname as
|
|
17301
|
+
import { existsSync as existsSync17, mkdirSync as mkdirSync17, readFileSync as readFileSync19, renameSync as renameSync6, writeFileSync as writeFileSync14 } from "node:fs";
|
|
17302
|
+
import { dirname as dirname11 } from "node:path";
|
|
17109
17303
|
var GRAPH_SCHEMA_VERSION = 1;
|
|
17110
17304
|
var MAX_ADD_WORK = 32;
|
|
17111
17305
|
var MAX_STOP = 20;
|
|
@@ -17142,7 +17336,7 @@ function emptyGraphFile() {
|
|
|
17142
17336
|
function readGraphFile(path31) {
|
|
17143
17337
|
try {
|
|
17144
17338
|
if (!existsSync17(path31)) return emptyGraphFile();
|
|
17145
|
-
const parsed = JSON.parse(
|
|
17339
|
+
const parsed = JSON.parse(readFileSync19(path31, "utf8"));
|
|
17146
17340
|
if (parsed?.v !== GRAPH_SCHEMA_VERSION || !Array.isArray(parsed.history)) return emptyGraphFile();
|
|
17147
17341
|
return { v: GRAPH_SCHEMA_VERSION, history: parsed.history, ...parsed.current ? { current: parsed.current } : {} };
|
|
17148
17342
|
} catch {
|
|
@@ -17150,10 +17344,10 @@ function readGraphFile(path31) {
|
|
|
17150
17344
|
}
|
|
17151
17345
|
}
|
|
17152
17346
|
function writeGraphFile(path31, file) {
|
|
17153
|
-
|
|
17347
|
+
mkdirSync17(dirname11(path31), { recursive: true });
|
|
17154
17348
|
const tmp = `${path31}.${process.pid}.tmp`;
|
|
17155
|
-
|
|
17156
|
-
|
|
17349
|
+
writeFileSync14(tmp, JSON.stringify(file));
|
|
17350
|
+
renameSync6(tmp, path31);
|
|
17157
17351
|
}
|
|
17158
17352
|
var GraphEngine = class {
|
|
17159
17353
|
constructor(deps) {
|
|
@@ -17782,6 +17976,7 @@ var GRAPH_ORCHESTRATION_PROMPT = `<orchestration_mode>
|
|
|
17782
17976
|
Graph Mode is active for this session. You are the main-agent supervisor beside the data path.
|
|
17783
17977
|
- Use update_agent_graph to schedule bounded work onto child subagents when a graph materially improves the task. The host runs the work; do not call run_subagent for graph work.
|
|
17784
17978
|
- Each add_work item needs a self-contained instruction (the child does not see this conversation). Give items a short work_id so later work can name them.
|
|
17979
|
+
- Each item's profile is your choice: pick per item (a read-only investigation uses subagent_explore; write-capable work uses subagent_general or a custom profile). view_agent_graph lists the profiles available right now; a profile you name that does not exist is refused.
|
|
17785
17980
|
- Dependencies are input_ids: work ids (or result ids r-<work_id>) of this graph whose committed results the item consumes. Work waits until its inputs complete; the host attaches bounded upstream handoffs, so do not restate upstream conclusions in the instruction. You may declare the whole DAG in one update.
|
|
17786
17981
|
- Use view_agent_graph to observe work status, operators, waits, failures and committed result ids.
|
|
17787
17982
|
- After scheduling, call yield_agent_graph instead of polling, sleeping, or writing a waiting message. Yield ends only the current supervisor turn; the host wakes you at the next durable checkpoint (failure, nothing runnable, or everything settled) and the graph stays open.
|
|
@@ -17801,7 +17996,7 @@ Swarm Mode is active for this session. Treat the durable asynchronous agent grap
|
|
|
17801
17996
|
- Perform only the lightweight exploration needed to establish boundaries before dispatch.
|
|
17802
17997
|
- Make every item bounded and self-contained with an explicit scope, expected output, and constraints.
|
|
17803
17998
|
- Avoid overlapping writes. Prefer read-only investigation (profile subagent_explore) unless isolated workspaces are available.
|
|
17804
|
-
- Schedule all independent items together with one update_agent_graph add_work (pick each item's profile). The host runs them; do not call run_subagent for swarm items.
|
|
17999
|
+
- Schedule all independent items together with one update_agent_graph add_work (pick each item's profile \u2014 view_agent_graph lists the profiles available right now; a read-only investigation uses subagent_explore, write-capable work uses subagent_general or a custom profile). The host runs them; do not call run_subagent for swarm items.
|
|
17805
18000
|
- After scheduling, call yield_agent_graph. Do not poll, sleep, watch child logs, or wait synchronously; the host will wake you only when work needs attention or the whole swarm is settled.
|
|
17806
18001
|
- On wake, call agent_swarm_status for compact statuses only. Read agent_output only for completed final results or narrow failed-item diagnosis.
|
|
17807
18002
|
- Replace failed work with update_agent_graph using replaces=<failed work id> so the failed item no longer keeps the swarm in needs_attention. When all useful work is settled, finish the graph (operation=finish, result_ids, reason), deduplicate, verify, and semantically synthesize the results.
|
|
@@ -17829,6 +18024,7 @@ function graphView(engine, graph, options = {}) {
|
|
|
17829
18024
|
revision: graph.revision,
|
|
17830
18025
|
state: graph.finish ? "finished" : graph.abandoned ? "stopped" : "open",
|
|
17831
18026
|
counts: countStatuses(graph, status2),
|
|
18027
|
+
...options.profiles !== void 0 && options.profiles.length > 0 ? { available_profiles: [...options.profiles] } : {},
|
|
17832
18028
|
work: shown.map((work) => ({
|
|
17833
18029
|
work_id: work.workId,
|
|
17834
18030
|
status: status2(work),
|
|
@@ -17884,7 +18080,7 @@ function swarmStatus(engine, graph) {
|
|
|
17884
18080
|
var workSchema = Type4.Object({
|
|
17885
18081
|
work_id: Type4.Optional(Type4.String({ description: "Short stable id for this work (e.g. scan-api). Later work names it in input_ids; its result id is r-<work_id>. Auto-assigned when omitted." })),
|
|
17886
18082
|
instruction: Type4.String({ description: "Bounded, self-contained instruction: scope, expected output, constraints. The child does not see this conversation." }),
|
|
17887
|
-
profile: Type4.Optional(Type4.String({ description: `Subagent profile for
|
|
18083
|
+
profile: Type4.Optional(Type4.String({ description: `Subagent profile for this work (default ${DEFAULT_PROFILE}). Pick per work item: subagent_explore for read-only investigation, subagent_general for write-capable work on your model, or any custom profile listed in the Subagents section of your prompt. view_agent_graph reports the profiles available right now.` })),
|
|
17888
18084
|
operator_id: Type4.Optional(Type4.String({ description: "Follow-up work on an EXISTING operator (from view_agent_graph): resumes that child's session. Omit for new work." })),
|
|
17889
18085
|
input_ids: Type4.Optional(Type4.Array(Type4.String(), { description: `Work ids or result ids (r-<work_id>) of THIS graph whose committed results this work consumes (its dependencies). Max ${MAX_INPUT_IDS}.` })),
|
|
17890
18086
|
selected_result_inputs: Type4.Optional(
|
|
@@ -17983,11 +18179,11 @@ function registerGraphTools(pi, deps) {
|
|
|
17983
18179
|
const graph = p.graph_id ? engine.graph(p.graph_id) : engine.current();
|
|
17984
18180
|
if (!graph) {
|
|
17985
18181
|
if (p.history && engine.history().length > 0) {
|
|
17986
|
-
return textResult(JSON.stringify({ current: null, history: engine.history().slice(0, 10).map((past) => ({ graph_id: past.graphId, task: past.task, state: past.finish ? "finished" : "stopped", selected_result_ids: past.finish?.resultIds ?? [] })) }, null, 2));
|
|
18182
|
+
return textResult(JSON.stringify({ current: null, profiles: deps.profiles(), history: engine.history().slice(0, 10).map((past) => ({ graph_id: past.graphId, task: past.task, state: past.finish ? "finished" : "stopped", selected_result_ids: past.finish?.resultIds ?? [] })) }, null, 2));
|
|
17987
18183
|
}
|
|
17988
|
-
return textResult(p.graph_id ? `No graph ${p.graph_id}.` :
|
|
18184
|
+
return textResult(p.graph_id ? `No graph ${p.graph_id}. Available profiles: ${deps.profiles().join(", ") || "none"}.` : `No agent graph yet \u2014 schedule work with update_agent_graph operation=add_work. Available profiles: ${deps.profiles().join(", ") || "none"}.`);
|
|
17989
18185
|
}
|
|
17990
|
-
return textResult(JSON.stringify(graphView(engine, graph, { history: p.history === true }), null, 2));
|
|
18186
|
+
return textResult(JSON.stringify(graphView(engine, graph, { history: p.history === true, profiles: deps.profiles() }), null, 2));
|
|
17991
18187
|
}
|
|
17992
18188
|
});
|
|
17993
18189
|
pi.registerTool({
|
|
@@ -19804,7 +20000,7 @@ function ownerEventClearsStash(event) {
|
|
|
19804
20000
|
|
|
19805
20001
|
// packages/long-horizon/src/engine/ralph.ts
|
|
19806
20002
|
init_core();
|
|
19807
|
-
import { writeFileSync as
|
|
20003
|
+
import { writeFileSync as writeFileSync15 } from "node:fs";
|
|
19808
20004
|
import { randomUUID as randomUUID5 } from "node:crypto";
|
|
19809
20005
|
var RALPH_COMPLETE_MARKER2 = "<promise>COMPLETE</promise>";
|
|
19810
20006
|
function parseChecklist(markdown) {
|
|
@@ -19954,7 +20150,7 @@ var RalphLoop = class {
|
|
|
19954
20150
|
return { ok: false, reason: `unfinished goal exists (${goal.goal.status}) \u2014 clear or complete it first` };
|
|
19955
20151
|
}
|
|
19956
20152
|
ensureDir(this.taskPath(name));
|
|
19957
|
-
|
|
20153
|
+
writeFileSync15(this.taskPath(name), taskContent, "utf-8");
|
|
19958
20154
|
const now2 = new Date(this.deps.now?.() ?? Date.now()).toISOString();
|
|
19959
20155
|
const state2 = {
|
|
19960
20156
|
version: 1,
|
|
@@ -20802,6 +20998,228 @@ function wireRuntime(pi, deps) {
|
|
|
20802
20998
|
return { estimateGoal: (ctx) => estimateGoal(ctx) };
|
|
20803
20999
|
}
|
|
20804
21000
|
|
|
21001
|
+
// packages/long-horizon/src/session-state.ts
|
|
21002
|
+
import { existsSync as existsSync18, mkdirSync as mkdirSync18, readFileSync as readFileSync20, readdirSync as readdirSync5, renameSync as renameSync7, rmSync as rmSync6, statSync as statSync9 } from "node:fs";
|
|
21003
|
+
import { join as join26 } from "node:path";
|
|
21004
|
+
function sessionStateDir(workspaceStateDir2, sessionId3) {
|
|
21005
|
+
return join26(workspaceStateDir2, "sessions", sessionId3);
|
|
21006
|
+
}
|
|
21007
|
+
function legacyWorkspaceDir(workspaceStateDir2) {
|
|
21008
|
+
return workspaceStateDir2;
|
|
21009
|
+
}
|
|
21010
|
+
function legacyInRepoDir(cwd) {
|
|
21011
|
+
return join26(cwd, ".unipi", "long-horizon");
|
|
21012
|
+
}
|
|
21013
|
+
function isContinuedSession(reason, priorEntryCount) {
|
|
21014
|
+
if (reason === "resume" || reason === "reload") return true;
|
|
21015
|
+
if (reason === "new" || reason === "fork") return false;
|
|
21016
|
+
return priorEntryCount > 0;
|
|
21017
|
+
}
|
|
21018
|
+
function legacyOwnershipEvidence(entriesJson, legacyDirs) {
|
|
21019
|
+
if (!entriesJson) return false;
|
|
21020
|
+
for (const dir of legacyDirs) {
|
|
21021
|
+
const state2 = readOwnerState(join26(dir, "state.json"));
|
|
21022
|
+
const owner = state2?.active ?? state2?.parked;
|
|
21023
|
+
const kind = owner?.kind;
|
|
21024
|
+
if (kind === "graph" || kind === "swarm") {
|
|
21025
|
+
try {
|
|
21026
|
+
const graph = JSON.parse(readJsonFile(join26(dir, "graph.json")));
|
|
21027
|
+
const graphId = graph?.current?.graphId;
|
|
21028
|
+
if (graphId && entriesJson.includes(graphId)) return true;
|
|
21029
|
+
} catch {
|
|
21030
|
+
}
|
|
21031
|
+
} else if (kind === "goal") {
|
|
21032
|
+
try {
|
|
21033
|
+
const goal = JSON.parse(readJsonFile(join26(dir, "goal.json")));
|
|
21034
|
+
if (goal?.goalId && entriesJson.includes(goal.goalId) || goal?.objective && entriesJson.includes(goal.objective)) return true;
|
|
21035
|
+
} catch {
|
|
21036
|
+
}
|
|
21037
|
+
} else if (kind === "ralph") {
|
|
21038
|
+
const loopName = owner?.label;
|
|
21039
|
+
if (loopName && entriesJson.includes(loopName)) return true;
|
|
21040
|
+
}
|
|
21041
|
+
}
|
|
21042
|
+
return false;
|
|
21043
|
+
}
|
|
21044
|
+
function adoptLegacyState(sessionDir2, sources, files) {
|
|
21045
|
+
const moved = [];
|
|
21046
|
+
if (existsSync18(join26(sessionDir2, "state.json"))) return moved;
|
|
21047
|
+
try {
|
|
21048
|
+
mkdirSync18(sessionDir2, { recursive: true });
|
|
21049
|
+
} catch {
|
|
21050
|
+
return moved;
|
|
21051
|
+
}
|
|
21052
|
+
for (const source of sources) {
|
|
21053
|
+
for (const file of files) {
|
|
21054
|
+
const from = join26(source, file);
|
|
21055
|
+
const to = join26(sessionDir2, file);
|
|
21056
|
+
if (!existsSync18(to) && existsSync18(from)) {
|
|
21057
|
+
try {
|
|
21058
|
+
renameSync7(from, to);
|
|
21059
|
+
moved.push(from);
|
|
21060
|
+
} catch {
|
|
21061
|
+
}
|
|
21062
|
+
}
|
|
21063
|
+
}
|
|
21064
|
+
const fromDir = join26(source, "ralph");
|
|
21065
|
+
const toDir = join26(sessionDir2, "ralph");
|
|
21066
|
+
if (!existsSync18(toDir) && existsSync18(fromDir)) {
|
|
21067
|
+
try {
|
|
21068
|
+
renameSync7(fromDir, toDir);
|
|
21069
|
+
moved.push(fromDir);
|
|
21070
|
+
} catch {
|
|
21071
|
+
}
|
|
21072
|
+
}
|
|
21073
|
+
}
|
|
21074
|
+
return moved;
|
|
21075
|
+
}
|
|
21076
|
+
function readOwnerState(path31) {
|
|
21077
|
+
if (!existsSync18(path31)) return void 0;
|
|
21078
|
+
try {
|
|
21079
|
+
const parsed = JSON.parse(readJsonFile(path31));
|
|
21080
|
+
return parsed && typeof parsed === "object" ? parsed : void 0;
|
|
21081
|
+
} catch {
|
|
21082
|
+
return void 0;
|
|
21083
|
+
}
|
|
21084
|
+
}
|
|
21085
|
+
function readJsonFile(path31) {
|
|
21086
|
+
return readFileSync20(path31, "utf8");
|
|
21087
|
+
}
|
|
21088
|
+
function scanSiblingGraphOwners(sessionsDir, ownSessionId, ...legacyDirs) {
|
|
21089
|
+
const out = [];
|
|
21090
|
+
const push = (sessionId3, state2, sessionName, ownDir = true) => {
|
|
21091
|
+
for (const slot of ["active", "parked"]) {
|
|
21092
|
+
const owner = state2?.[slot];
|
|
21093
|
+
if (!owner || owner.kind !== "graph" && owner.kind !== "swarm") continue;
|
|
21094
|
+
if (ownDir && owner.sessionId && owner.sessionId !== sessionId3) continue;
|
|
21095
|
+
out.push({
|
|
21096
|
+
sessionId: sessionId3,
|
|
21097
|
+
kind: owner.kind === "swarm" ? "swarm" : "graph",
|
|
21098
|
+
label: owner.label ?? "",
|
|
21099
|
+
...sessionName !== void 0 ? { sessionName } : {},
|
|
21100
|
+
...owner.pid !== void 0 ? { pid: owner.pid } : {},
|
|
21101
|
+
updatedAt: state2?.updatedAt ?? ""
|
|
21102
|
+
});
|
|
21103
|
+
break;
|
|
21104
|
+
}
|
|
21105
|
+
};
|
|
21106
|
+
try {
|
|
21107
|
+
for (const entry of readdirSync5(sessionsDir, { withFileTypes: true })) {
|
|
21108
|
+
if (!entry.isDirectory() || entry.name === ownSessionId) continue;
|
|
21109
|
+
const state2 = readOwnerState(join26(sessionsDir, entry.name, "state.json"));
|
|
21110
|
+
if (state2?.active?.sessionId === ownSessionId || state2?.parked?.sessionId === ownSessionId) continue;
|
|
21111
|
+
push(entry.name, state2);
|
|
21112
|
+
}
|
|
21113
|
+
} catch {
|
|
21114
|
+
}
|
|
21115
|
+
for (const legacyDir of legacyDirs) {
|
|
21116
|
+
if (!legacyDir) continue;
|
|
21117
|
+
const state2 = readOwnerState(join26(legacyDir, "state.json"));
|
|
21118
|
+
if (state2 && state2.active?.sessionId !== ownSessionId && state2.parked?.sessionId !== ownSessionId) {
|
|
21119
|
+
push("(legacy)", state2, void 0, false);
|
|
21120
|
+
}
|
|
21121
|
+
}
|
|
21122
|
+
return out.sort((a, b) => a.updatedAt < b.updatedAt ? 1 : -1);
|
|
21123
|
+
}
|
|
21124
|
+
function pidAlive(pid) {
|
|
21125
|
+
if (pid === void 0 || pid <= 0) return false;
|
|
21126
|
+
try {
|
|
21127
|
+
process.kill(pid, 0);
|
|
21128
|
+
return true;
|
|
21129
|
+
} catch {
|
|
21130
|
+
return false;
|
|
21131
|
+
}
|
|
21132
|
+
}
|
|
21133
|
+
function graphOwnerNote(owner) {
|
|
21134
|
+
if (!owner) return void 0;
|
|
21135
|
+
const name = owner.sessionName ?? (owner.sessionId !== "(workspace)" ? owner.sessionId.slice(0, 12) : "another session");
|
|
21136
|
+
if (pidAlive(owner.pid)) {
|
|
21137
|
+
return `Agent ${owner.kind} "${owner.label}" is running in another session (${name}) \u2014 /resume it to follow it.`;
|
|
21138
|
+
}
|
|
21139
|
+
return `Agent ${owner.kind} "${owner.label}" is paused in another session (${name}) \u2014 /resume it to continue.`;
|
|
21140
|
+
}
|
|
21141
|
+
function readGraphFile2(path31) {
|
|
21142
|
+
if (!existsSync18(path31)) return void 0;
|
|
21143
|
+
try {
|
|
21144
|
+
const parsed = JSON.parse(readJsonFile(path31));
|
|
21145
|
+
if (!parsed || !Array.isArray(parsed.history)) return void 0;
|
|
21146
|
+
return parsed;
|
|
21147
|
+
} catch {
|
|
21148
|
+
return void 0;
|
|
21149
|
+
}
|
|
21150
|
+
}
|
|
21151
|
+
function graphUpdatedAt(graph) {
|
|
21152
|
+
const at = graph.updatedAt ?? graph.createdAt;
|
|
21153
|
+
return typeof at === "number" ? at : 0;
|
|
21154
|
+
}
|
|
21155
|
+
function isClosed(graph) {
|
|
21156
|
+
return !!(graph.finish || graph.abandoned);
|
|
21157
|
+
}
|
|
21158
|
+
function aggregateGraphHistory(own, sessionsDir, ownSessionId) {
|
|
21159
|
+
const byId2 = /* @__PURE__ */ new Map();
|
|
21160
|
+
for (const graph of own) {
|
|
21161
|
+
const id = graph.graphId;
|
|
21162
|
+
if (typeof id === "string") byId2.set(id, graph);
|
|
21163
|
+
}
|
|
21164
|
+
try {
|
|
21165
|
+
for (const entry of readdirSync5(sessionsDir, { withFileTypes: true })) {
|
|
21166
|
+
if (!entry.isDirectory() || entry.name === ownSessionId) continue;
|
|
21167
|
+
const file = readGraphFile2(join26(sessionsDir, entry.name, "graph.json"));
|
|
21168
|
+
if (!file) continue;
|
|
21169
|
+
for (const graph of file.history) {
|
|
21170
|
+
if (typeof graph.graphId === "string" && !byId2.has(graph.graphId)) byId2.set(graph.graphId, graph);
|
|
21171
|
+
}
|
|
21172
|
+
if (file.current && isClosed(file.current) && typeof file.current.graphId === "string" && !byId2.has(file.current.graphId)) {
|
|
21173
|
+
byId2.set(file.current.graphId, file.current);
|
|
21174
|
+
}
|
|
21175
|
+
}
|
|
21176
|
+
} catch {
|
|
21177
|
+
}
|
|
21178
|
+
return [...byId2.values()].sort((a, b) => graphUpdatedAt(b) - graphUpdatedAt(a));
|
|
21179
|
+
}
|
|
21180
|
+
function findSiblingWork(sessionsDir, ownSessionId, graphId, workId) {
|
|
21181
|
+
try {
|
|
21182
|
+
for (const entry of readdirSync5(sessionsDir, { withFileTypes: true })) {
|
|
21183
|
+
if (!entry.isDirectory() || entry.name === ownSessionId) continue;
|
|
21184
|
+
const file = readGraphFile2(join26(sessionsDir, entry.name, "graph.json"));
|
|
21185
|
+
if (!file) continue;
|
|
21186
|
+
const candidates = [...file.history, ...file.current && isClosed(file.current) ? [file.current] : []];
|
|
21187
|
+
const graph = candidates.find((g) => g.graphId === graphId);
|
|
21188
|
+
if (!graph) continue;
|
|
21189
|
+
const work = graph["work"]?.find((w) => w.workId === workId);
|
|
21190
|
+
if (work) return { work, graph };
|
|
21191
|
+
}
|
|
21192
|
+
} catch {
|
|
21193
|
+
return void 0;
|
|
21194
|
+
}
|
|
21195
|
+
return void 0;
|
|
21196
|
+
}
|
|
21197
|
+
var PRUNE_AGE_MS = 30 * 24 * 60 * 60 * 1e3;
|
|
21198
|
+
function pruneSiblingSessionDirs(sessionsDir, ownSessionId, now2) {
|
|
21199
|
+
const pruned = [];
|
|
21200
|
+
try {
|
|
21201
|
+
for (const entry of readdirSync5(sessionsDir, { withFileTypes: true })) {
|
|
21202
|
+
if (!entry.isDirectory() || entry.name === ownSessionId) continue;
|
|
21203
|
+
const dir = join26(sessionsDir, entry.name);
|
|
21204
|
+
try {
|
|
21205
|
+
if (now2 - statSync9(dir).mtimeMs <= PRUNE_AGE_MS) continue;
|
|
21206
|
+
const state2 = readOwnerState(join26(dir, "state.json"));
|
|
21207
|
+
if (state2?.active || state2?.parked) continue;
|
|
21208
|
+
const file = readGraphFile2(join26(dir, "graph.json"));
|
|
21209
|
+
if (file?.current && !isClosed(file.current)) continue;
|
|
21210
|
+
rmSync6(dir, { recursive: true, force: true });
|
|
21211
|
+
pruned.push(entry.name);
|
|
21212
|
+
} catch {
|
|
21213
|
+
}
|
|
21214
|
+
}
|
|
21215
|
+
} catch {
|
|
21216
|
+
}
|
|
21217
|
+
return pruned;
|
|
21218
|
+
}
|
|
21219
|
+
function sessionHasState(sessionDir2) {
|
|
21220
|
+
return existsSync18(join26(sessionDir2, "state.json")) || existsSync18(join26(sessionDir2, "goal.json")) || existsSync18(join26(sessionDir2, "graph.json"));
|
|
21221
|
+
}
|
|
21222
|
+
|
|
20805
21223
|
// packages/long-horizon/src/progress-snapshot.ts
|
|
20806
21224
|
var LABEL_MAX = 160;
|
|
20807
21225
|
var SUMMARY_MAX = 300;
|
|
@@ -21499,9 +21917,9 @@ function renderProgressView(t, progress, width, height, now2, chart, workingMode
|
|
|
21499
21917
|
}
|
|
21500
21918
|
|
|
21501
21919
|
// packages/long-horizon/src/progress-chart.ts
|
|
21502
|
-
import { existsSync as
|
|
21920
|
+
import { existsSync as existsSync19, readFileSync as readFileSync21 } from "node:fs";
|
|
21503
21921
|
import { createRequire } from "node:module";
|
|
21504
|
-
import { join as
|
|
21922
|
+
import { join as join27 } from "node:path";
|
|
21505
21923
|
import { allocateImageId, encodeKitty as encodeKitty2, getCapabilities as getCapabilities3, getPngDimensions, getCellDimensions } from "@earendil-works/pi-tui";
|
|
21506
21924
|
|
|
21507
21925
|
// packages/long-horizon/src/progress-mermaid.ts
|
|
@@ -21661,7 +22079,7 @@ async function createDefaultRenderer() {
|
|
|
21661
22079
|
if (!wasmReady) {
|
|
21662
22080
|
const require2 = createRequire(import.meta.url);
|
|
21663
22081
|
const wasmPath = require2.resolve("@resvg/resvg-wasm/index_bg.wasm");
|
|
21664
|
-
wasmReady = resvg.initWasm(
|
|
22082
|
+
wasmReady = resvg.initWasm(readFileSync21(wasmPath)).catch((err) => {
|
|
21665
22083
|
if (/already initiali[sz]ed/i.test(err?.message ?? "")) return;
|
|
21666
22084
|
wasmReady = null;
|
|
21667
22085
|
throw err;
|
|
@@ -21670,12 +22088,12 @@ async function createDefaultRenderer() {
|
|
|
21670
22088
|
await wasmReady;
|
|
21671
22089
|
const fontFiles = FONT_CANDIDATES.filter((f) => {
|
|
21672
22090
|
try {
|
|
21673
|
-
return
|
|
22091
|
+
return existsSync19(f);
|
|
21674
22092
|
} catch {
|
|
21675
22093
|
return false;
|
|
21676
22094
|
}
|
|
21677
22095
|
});
|
|
21678
|
-
const fontBuffers = fontFiles.map((f) =>
|
|
22096
|
+
const fontBuffers = fontFiles.map((f) => readFileSync21(f));
|
|
21679
22097
|
if (!fontBuffers.length) throw new Error("no system font found for chart labels");
|
|
21680
22098
|
return {
|
|
21681
22099
|
async render(source) {
|
|
@@ -21922,19 +22340,12 @@ function createChartState(requestRender, supported = chartSupported()) {
|
|
|
21922
22340
|
}
|
|
21923
22341
|
|
|
21924
22342
|
// packages/long-horizon/index.ts
|
|
21925
|
-
var
|
|
22343
|
+
var currentSessionId;
|
|
22344
|
+
var workspaceStateDir = () => stateDir("long-horizon", "state");
|
|
22345
|
+
var lhSessionsDir = () => join28(workspaceStateDir(), "sessions");
|
|
21926
22346
|
function lhStatePath(file) {
|
|
21927
|
-
const
|
|
21928
|
-
|
|
21929
|
-
const legacy = join27(resolve11(process.cwd()), LH_DIR, file);
|
|
21930
|
-
if (existsSync19(legacy)) {
|
|
21931
|
-
try {
|
|
21932
|
-
renameSync6(legacy, dest);
|
|
21933
|
-
} catch {
|
|
21934
|
-
}
|
|
21935
|
-
}
|
|
21936
|
-
}
|
|
21937
|
-
return dest;
|
|
22347
|
+
const dir = currentSessionId ? sessionStateDir(workspaceStateDir(), currentSessionId) : workspaceStateDir();
|
|
22348
|
+
return join28(dir, file);
|
|
21938
22349
|
}
|
|
21939
22350
|
function longHorizon(pi) {
|
|
21940
22351
|
const version = getPackageVersion("long-horizon");
|
|
@@ -21983,8 +22394,10 @@ function longHorizon(pi) {
|
|
|
21983
22394
|
}
|
|
21984
22395
|
}
|
|
21985
22396
|
let graphOwnerChanged;
|
|
22397
|
+
const sessionInfo = {};
|
|
21986
22398
|
const owner = new OwnerCoordinator({
|
|
21987
22399
|
statePath: statePath2,
|
|
22400
|
+
session: () => sessionInfo,
|
|
21988
22401
|
onChange: (_snapshot, event) => {
|
|
21989
22402
|
gate.onOwnerChanged(event);
|
|
21990
22403
|
if (ownerEventClearsStash(event)) {
|
|
@@ -22116,7 +22529,7 @@ function longHorizon(pi) {
|
|
|
22116
22529
|
listActionableTasks: () => todoStore.get().filter((item) => item.status === "pending" || item.status === "in_progress").map((item) => `${item.status === "in_progress" ? "[in_progress] " : ""}${item.content}`)
|
|
22117
22530
|
}
|
|
22118
22531
|
});
|
|
22119
|
-
const ralphDir = () =>
|
|
22532
|
+
const ralphDir = () => join28(stateDir("long-horizon", "state"), "ralph");
|
|
22120
22533
|
const ralph = new RalphLoop({
|
|
22121
22534
|
machine,
|
|
22122
22535
|
owner,
|
|
@@ -22337,6 +22750,39 @@ function longHorizon(pi) {
|
|
|
22337
22750
|
}, machine, toolset);
|
|
22338
22751
|
pi.on("session_start", (event, ctx) => {
|
|
22339
22752
|
const reason = event?.reason;
|
|
22753
|
+
const manager = ctx?.sessionManager;
|
|
22754
|
+
try {
|
|
22755
|
+
currentSessionId = manager?.getSessionId?.();
|
|
22756
|
+
} catch {
|
|
22757
|
+
}
|
|
22758
|
+
sessionInfo.id = currentSessionId;
|
|
22759
|
+
try {
|
|
22760
|
+
const name = pi.getSessionName?.();
|
|
22761
|
+
if (name) sessionInfo.name = name;
|
|
22762
|
+
} catch {
|
|
22763
|
+
}
|
|
22764
|
+
sessionInfo.pid = process.pid;
|
|
22765
|
+
const priorEntries = (() => {
|
|
22766
|
+
try {
|
|
22767
|
+
return manager?.getEntries?.().length ?? 0;
|
|
22768
|
+
} catch {
|
|
22769
|
+
return 0;
|
|
22770
|
+
}
|
|
22771
|
+
})();
|
|
22772
|
+
const continued = isContinuedSession(reason, priorEntries);
|
|
22773
|
+
const legacyDirs = [legacyWorkspaceDir(workspaceStateDir()), legacyInRepoDir(resolve11(process.cwd()))];
|
|
22774
|
+
const entriesJson = (() => {
|
|
22775
|
+
try {
|
|
22776
|
+
return JSON.stringify(manager?.getEntries?.() ?? []);
|
|
22777
|
+
} catch {
|
|
22778
|
+
return "";
|
|
22779
|
+
}
|
|
22780
|
+
})();
|
|
22781
|
+
const legacyEvidence = continued && !sessionHasState(sessionStateDir(workspaceStateDir(), currentSessionId ?? "")) ? legacyOwnershipEvidence(entriesJson, legacyDirs) : false;
|
|
22782
|
+
if (continued && legacyEvidence && !sessionHasState(sessionStateDir(workspaceStateDir(), currentSessionId ?? ""))) {
|
|
22783
|
+
adoptLegacyState(sessionStateDir(workspaceStateDir(), currentSessionId ?? ""), legacyDirs, ["state.json", "goal.json", "graph.json"]);
|
|
22784
|
+
}
|
|
22785
|
+
if (currentSessionId) pruneSiblingSessionDirs(lhSessionsDir(), currentSessionId, Date.now());
|
|
22340
22786
|
if (reason === "new" || reason === "resume" || reason === "fork") gate.dropStickyWorkMode();
|
|
22341
22787
|
gate.resetModeTools();
|
|
22342
22788
|
gate.resetDisplay(loadSettings().defaultMode);
|
|
@@ -22354,7 +22800,7 @@ function longHorizon(pi) {
|
|
|
22354
22800
|
ralph.restoreFromOwner();
|
|
22355
22801
|
const goalStatus = machine.get()?.status;
|
|
22356
22802
|
if (goalStatus === "active" || goalStatus === "waiting") {
|
|
22357
|
-
const redeliver = !isChildProcess() &&
|
|
22803
|
+
const redeliver = !isChildProcess() && ctx?.hasUI !== false;
|
|
22358
22804
|
const recovery = redeliver ? continuation.recoverOnRestart() : (continuation.armRecovery(), void 0);
|
|
22359
22805
|
if (recovery?.action === "redeliver") {
|
|
22360
22806
|
setTimeout(() => {
|
|
@@ -22363,14 +22809,31 @@ function longHorizon(pi) {
|
|
|
22363
22809
|
}, 0);
|
|
22364
22810
|
}
|
|
22365
22811
|
}
|
|
22812
|
+
if (!isChildProcess() && (reason === "new" || reason === "fork" || reason === "startup" || reason === void 0) && ctx?.hasUI) {
|
|
22813
|
+
try {
|
|
22814
|
+
const siblings = scanSiblingGraphOwners(lhSessionsDir(), currentSessionId ?? "", legacyWorkspaceDir(workspaceStateDir()), legacyInRepoDir(resolve11(process.cwd()))).filter((o) => o.sessionId !== currentSessionId);
|
|
22815
|
+
const note = graphOwnerNote(siblings[0]);
|
|
22816
|
+
if (note) {
|
|
22817
|
+
const ui = ctx.ui;
|
|
22818
|
+
ui?.notify?.(note, "info");
|
|
22819
|
+
}
|
|
22820
|
+
} catch {
|
|
22821
|
+
}
|
|
22822
|
+
}
|
|
22366
22823
|
publishLh();
|
|
22367
22824
|
});
|
|
22368
22825
|
registerCommandRunner("unipi:lh-graph", async (_ctx, args) => {
|
|
22369
22826
|
const a = args ?? {};
|
|
22370
22827
|
const op = String(a.op ?? "");
|
|
22371
22828
|
if (op === "output") {
|
|
22372
|
-
const
|
|
22373
|
-
|
|
22829
|
+
const graphId = typeof a.graphId === "string" ? a.graphId : void 0;
|
|
22830
|
+
const found = graphEngine.readResult(String(a.id ?? ""), graphId);
|
|
22831
|
+
const sibling = !found && graphId && currentSessionId ? findSiblingWork(lhSessionsDir(), currentSessionId, graphId, String(a.id ?? "")) : void 0;
|
|
22832
|
+
if (!found) {
|
|
22833
|
+
if (!sibling) return { ok: false, reason: "That step is gone." };
|
|
22834
|
+
const w2 = sibling.work;
|
|
22835
|
+
return { ok: true, output: { graphId, id: String(w2.workId ?? a.id ?? ""), status: String(w2.status ?? ""), ...w2.resultId ? { resultId: w2.resultId } : {}, ...w2.operatorId ? { operatorId: w2.operatorId } : {}, instruction: String(w2.instruction ?? ""), ...w2.result ? { text: w2.result } : {}, ...w2.failure ? { failure: w2.failure } : {}, ...w2.resultTruncated ? { truncated: true } : {} } };
|
|
22836
|
+
}
|
|
22374
22837
|
const w = found.work;
|
|
22375
22838
|
return { ok: true, output: { graphId: found.graphId, id: w.workId, status: w.status, ...w.resultId ? { resultId: w.resultId } : {}, ...w.operatorId ? { operatorId: w.operatorId } : {}, instruction: w.instruction, ...w.result ? { text: w.result } : {}, ...w.failure ? { failure: w.failure } : {}, ...w.resultTruncated ? { truncated: true } : {} } };
|
|
22376
22839
|
}
|
|
@@ -22382,14 +22845,18 @@ function longHorizon(pi) {
|
|
|
22382
22845
|
return { ok: true };
|
|
22383
22846
|
}
|
|
22384
22847
|
if (op === "history") {
|
|
22385
|
-
const
|
|
22386
|
-
|
|
22387
|
-
|
|
22388
|
-
|
|
22848
|
+
const aggregate = currentSessionId ? aggregateGraphHistory(graphEngine.history().map((g) => g), lhSessionsDir(), currentSessionId) : graphEngine.history().map((g) => g);
|
|
22849
|
+
const runs = aggregate.slice(0, 20).map((g) => {
|
|
22850
|
+
const graph = g;
|
|
22851
|
+
const finish = g["finish"];
|
|
22852
|
+
const abandoned = g["abandoned"];
|
|
22853
|
+
return lhProgressSnapshot({
|
|
22854
|
+
finished: { kind: g["mode"], label: String(g["task"] ?? ""), terminalReason: finish ? "complete(finish)" : abandoned?.reason ?? "stopped", endedAt: new Date(finish?.at ?? abandoned?.at ?? graphUpdatedAt(g)).toISOString() },
|
|
22855
|
+
graph,
|
|
22389
22856
|
graphEngine,
|
|
22390
22857
|
now: Date.now()
|
|
22391
|
-
}).last
|
|
22392
|
-
).filter((run4) => run4 !== void 0);
|
|
22858
|
+
}).last;
|
|
22859
|
+
}).filter((run4) => run4 !== void 0);
|
|
22393
22860
|
return { ok: true, runs };
|
|
22394
22861
|
}
|
|
22395
22862
|
return { ok: false, reason: `unknown op "${op}"` };
|
|
@@ -22416,8 +22883,8 @@ function longHorizon(pi) {
|
|
|
22416
22883
|
init_core();
|
|
22417
22884
|
import * as fs15 from "node:fs";
|
|
22418
22885
|
import * as os5 from "node:os";
|
|
22419
|
-
import { dirname as
|
|
22420
|
-
import { fileURLToPath as
|
|
22886
|
+
import { dirname as dirname17, join as join38 } from "node:path";
|
|
22887
|
+
import { fileURLToPath as fileURLToPath5 } from "node:url";
|
|
22421
22888
|
|
|
22422
22889
|
// packages/memory/session.ts
|
|
22423
22890
|
import * as fs11 from "node:fs";
|
|
@@ -24004,7 +24471,7 @@ function writeConversionState(state2) {
|
|
|
24004
24471
|
} catch {
|
|
24005
24472
|
}
|
|
24006
24473
|
}
|
|
24007
|
-
function
|
|
24474
|
+
function pidAlive2(pid) {
|
|
24008
24475
|
try {
|
|
24009
24476
|
process.kill(pid, 0);
|
|
24010
24477
|
return true;
|
|
@@ -24016,7 +24483,7 @@ function acquireConversionLock() {
|
|
|
24016
24483
|
const p = LOCK_PATH();
|
|
24017
24484
|
try {
|
|
24018
24485
|
const cur = JSON.parse(fs12.readFileSync(p, "utf-8"));
|
|
24019
|
-
if (typeof cur.pid === "number" && cur.pid !== process.pid &&
|
|
24486
|
+
if (typeof cur.pid === "number" && cur.pid !== process.pid && pidAlive2(cur.pid)) {
|
|
24020
24487
|
return false;
|
|
24021
24488
|
}
|
|
24022
24489
|
} catch {
|
|
@@ -25407,7 +25874,7 @@ var memoryMoveHandler = createMemoryMoveHandler();
|
|
|
25407
25874
|
function getInfoRegistry() {
|
|
25408
25875
|
return globalThis.__unipi_info_registry;
|
|
25409
25876
|
}
|
|
25410
|
-
var VERSION3 = getPackageVersion(
|
|
25877
|
+
var VERSION3 = getPackageVersion(dirname17(fileURLToPath5(import.meta.url)));
|
|
25411
25878
|
var RECALL_CUSTOM_TYPE = "unipi-memory-recall-reminder";
|
|
25412
25879
|
var RETRO_CUSTOM_TYPE = "unipi-memory-retro-reminder";
|
|
25413
25880
|
var CARD_CUSTOM_TYPE = "unipi-memory-session-card";
|
|
@@ -25417,9 +25884,9 @@ function saveUsageLine(usage) {
|
|
|
25417
25884
|
function memoryDebug(line) {
|
|
25418
25885
|
if (process.env.UNIPI_DEBUG_MEMORY !== "1") return;
|
|
25419
25886
|
try {
|
|
25420
|
-
const dir =
|
|
25887
|
+
const dir = join38(os5.homedir(), ".unipi", "logs");
|
|
25421
25888
|
fs15.mkdirSync(dir, { recursive: true });
|
|
25422
|
-
fs15.appendFileSync(
|
|
25889
|
+
fs15.appendFileSync(join38(dir, "memory.log"), `${(/* @__PURE__ */ new Date()).toISOString()} ${line}
|
|
25423
25890
|
`);
|
|
25424
25891
|
} catch {
|
|
25425
25892
|
}
|
|
@@ -25497,7 +25964,7 @@ function memory_default(pi) {
|
|
|
25497
25964
|
const walk2 = (d) => {
|
|
25498
25965
|
for (const e of fs15.readdirSync(d, { withFileTypes: true })) {
|
|
25499
25966
|
if (e.name.startsWith(".")) continue;
|
|
25500
|
-
const p =
|
|
25967
|
+
const p = join38(d, e.name);
|
|
25501
25968
|
if (e.isDirectory()) walk2(p);
|
|
25502
25969
|
else if (e.name.endsWith(".md")) n += 1;
|
|
25503
25970
|
}
|
|
@@ -25627,7 +26094,7 @@ function memory_default(pi) {
|
|
|
25627
26094
|
}, 12e4);
|
|
25628
26095
|
pendingTimer.unref?.();
|
|
25629
26096
|
if (migrating && ctx.hasUI) {
|
|
25630
|
-
const askedFile =
|
|
26097
|
+
const askedFile = join38(memoryRoot(), ".v3-migrate-asked");
|
|
25631
26098
|
if (!fs15.existsSync(askedFile) && typeof ctx.ui.confirm === "function") {
|
|
25632
26099
|
try {
|
|
25633
26100
|
fs15.mkdirSync(memoryRoot(), { recursive: true });
|
|
@@ -26323,7 +26790,7 @@ function patchRunMeta(staging, patch) {
|
|
|
26323
26790
|
if (!cur) return;
|
|
26324
26791
|
writeRunMeta(staging, { ...cur, ...patch });
|
|
26325
26792
|
}
|
|
26326
|
-
function
|
|
26793
|
+
function pidAlive3(pid) {
|
|
26327
26794
|
if (!(pid > 0)) return false;
|
|
26328
26795
|
try {
|
|
26329
26796
|
process.kill(pid, 0);
|
|
@@ -26339,7 +26806,7 @@ function mtime(file) {
|
|
|
26339
26806
|
return void 0;
|
|
26340
26807
|
}
|
|
26341
26808
|
}
|
|
26342
|
-
function runFromStaging(staging, decisions = {}, now2 = Date.now(), alive2 =
|
|
26809
|
+
function runFromStaging(staging, decisions = {}, now2 = Date.now(), alive2 = pidAlive3) {
|
|
26343
26810
|
const id = path20.basename(staging);
|
|
26344
26811
|
const fromName = Number(id.replace(/^staging-/, ""));
|
|
26345
26812
|
const meta2 = readRunMeta(staging);
|
|
@@ -27390,17 +27857,17 @@ Watch it in the work tray (\u2193 \u2192 Dream).`);
|
|
|
27390
27857
|
|
|
27391
27858
|
// packages/info-screen/index.ts
|
|
27392
27859
|
init_core();
|
|
27393
|
-
import { dirname as
|
|
27394
|
-
import { fileURLToPath as
|
|
27860
|
+
import { dirname as dirname24 } from "node:path";
|
|
27861
|
+
import { fileURLToPath as fileURLToPath6 } from "node:url";
|
|
27395
27862
|
|
|
27396
27863
|
// packages/info-screen/registry.ts
|
|
27397
|
-
import { existsSync as existsSync31, mkdirSync as
|
|
27398
|
-
import { dirname as
|
|
27864
|
+
import { existsSync as existsSync31, mkdirSync as mkdirSync28, readFileSync as readFileSync34, renameSync as renameSync11, writeFileSync as writeFileSync26 } from "node:fs";
|
|
27865
|
+
import { dirname as dirname21, join as join47 } from "node:path";
|
|
27399
27866
|
import { homedir as homedir26 } from "node:os";
|
|
27400
27867
|
|
|
27401
27868
|
// packages/info-screen/config.ts
|
|
27402
|
-
import { readFileSync as
|
|
27403
|
-
import { join as
|
|
27869
|
+
import { readFileSync as readFileSync33, writeFileSync as writeFileSync25, existsSync as existsSync30, mkdirSync as mkdirSync27 } from "node:fs";
|
|
27870
|
+
import { join as join46, dirname as dirname20 } from "node:path";
|
|
27404
27871
|
import { homedir as homedir25 } from "node:os";
|
|
27405
27872
|
|
|
27406
27873
|
// packages/info-screen/types.ts
|
|
@@ -27414,7 +27881,7 @@ var DEFAULT_SETTINGS4 = {
|
|
|
27414
27881
|
|
|
27415
27882
|
// packages/info-screen/config.ts
|
|
27416
27883
|
init_core();
|
|
27417
|
-
var SETTINGS_PATH =
|
|
27884
|
+
var SETTINGS_PATH = join46(homedir25(), ".pi", "agent", "settings.json");
|
|
27418
27885
|
var cachedSettings = null;
|
|
27419
27886
|
function isRecord5(value) {
|
|
27420
27887
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
@@ -27975,17 +28442,17 @@ var SNAPSHOT_VERSION = 2;
|
|
|
27975
28442
|
var scopeOf = (id) => PAGE_SCOPE[id] ?? "global";
|
|
27976
28443
|
var VOLATILE = { has: (id) => scopeOf(id) === "session" };
|
|
27977
28444
|
function cacheDir2() {
|
|
27978
|
-
return
|
|
28445
|
+
return join47(process.env.UNIPI_DIR || join47(homedir26(), ".unipi"), "cache");
|
|
27979
28446
|
}
|
|
27980
28447
|
function snapshotPath(bucket, cwd) {
|
|
27981
|
-
if (bucket === "global") return
|
|
28448
|
+
if (bucket === "global") return join47(cacheDir2(), "info-screen.json");
|
|
27982
28449
|
let id = "default";
|
|
27983
28450
|
try {
|
|
27984
28451
|
id = workspaceId(cwd);
|
|
27985
28452
|
} catch {
|
|
27986
28453
|
id = "default";
|
|
27987
28454
|
}
|
|
27988
|
-
return
|
|
28455
|
+
return join47(cacheDir2(), "info-screen", `${id.replace(/[^\w.-]/g, "_")}.json`);
|
|
27989
28456
|
}
|
|
27990
28457
|
var InfoRegistry = class {
|
|
27991
28458
|
groups = /* @__PURE__ */ new Map();
|
|
@@ -28126,7 +28593,7 @@ var InfoRegistry = class {
|
|
|
28126
28593
|
try {
|
|
28127
28594
|
const path31 = snapshotPath(bucket, this.cwd);
|
|
28128
28595
|
if (existsSync31(path31)) {
|
|
28129
|
-
const parsed = JSON.parse(
|
|
28596
|
+
const parsed = JSON.parse(readFileSync34(path31, "utf-8"));
|
|
28130
28597
|
if (parsed?.version === SNAPSHOT_VERSION && parsed.pages && typeof parsed.pages === "object") {
|
|
28131
28598
|
pages2 = Object.fromEntries(Object.entries(parsed.pages).filter(([id]) => scopeOf(id) === bucket));
|
|
28132
28599
|
}
|
|
@@ -28161,10 +28628,10 @@ var InfoRegistry = class {
|
|
|
28161
28628
|
if (!changed) continue;
|
|
28162
28629
|
try {
|
|
28163
28630
|
const path31 = snapshotPath(bucket, this.cwd);
|
|
28164
|
-
|
|
28631
|
+
mkdirSync28(dirname21(path31), { recursive: true });
|
|
28165
28632
|
const tmp = `${path31}.${process.pid}.tmp`;
|
|
28166
|
-
|
|
28167
|
-
|
|
28633
|
+
writeFileSync26(tmp, JSON.stringify({ version: SNAPSHOT_VERSION, pages: pages2 }), "utf-8");
|
|
28634
|
+
renameSync11(tmp, path31);
|
|
28168
28635
|
} catch {
|
|
28169
28636
|
}
|
|
28170
28637
|
}
|
|
@@ -28188,14 +28655,14 @@ init_core();
|
|
|
28188
28655
|
|
|
28189
28656
|
// packages/info-screen/usage-parser.ts
|
|
28190
28657
|
init_core();
|
|
28191
|
-
import { readdirSync as
|
|
28192
|
-
import { join as
|
|
28658
|
+
import { readdirSync as readdirSync15, readFileSync as readFileSync35, statSync as statSync12, existsSync as existsSync32, mkdirSync as mkdirSync29, writeFileSync as writeFileSync27, renameSync as renameSync12, openSync as openSync4, readSync as readSync3, closeSync as closeSync3 } from "node:fs";
|
|
28659
|
+
import { join as join48, basename as basename14, dirname as dirname22 } from "node:path";
|
|
28193
28660
|
import { homedir as homedir27 } from "node:os";
|
|
28194
28661
|
var DAILY_DAYS = 30;
|
|
28195
28662
|
var CACHE_VERSION = 2;
|
|
28196
28663
|
function getCachePath() {
|
|
28197
|
-
const base = process.env.UNIPI_DIR ||
|
|
28198
|
-
return
|
|
28664
|
+
const base = process.env.UNIPI_DIR || join48(homedir27(), ".unipi");
|
|
28665
|
+
return join48(base, "cache", "usage-stats.json");
|
|
28199
28666
|
}
|
|
28200
28667
|
var memCache = null;
|
|
28201
28668
|
var writeTimer = null;
|
|
@@ -28235,7 +28702,7 @@ function readCache() {
|
|
|
28235
28702
|
try {
|
|
28236
28703
|
const path31 = getCachePath();
|
|
28237
28704
|
if (!existsSync32(path31)) return empty2;
|
|
28238
|
-
const parsed = JSON.parse(
|
|
28705
|
+
const parsed = JSON.parse(readFileSync35(path31, "utf-8"));
|
|
28239
28706
|
if (!parsed || parsed.version !== CACHE_VERSION) return empty2;
|
|
28240
28707
|
if (!Array.isArray(parsed.models) || typeof parsed.files !== "object") return empty2;
|
|
28241
28708
|
memCache = parsed;
|
|
@@ -28247,16 +28714,16 @@ function readCache() {
|
|
|
28247
28714
|
function writeCache(cache6) {
|
|
28248
28715
|
try {
|
|
28249
28716
|
const path31 = getCachePath();
|
|
28250
|
-
|
|
28717
|
+
mkdirSync29(dirname22(path31), { recursive: true });
|
|
28251
28718
|
const tmp = `${path31}.${process.pid}.tmp`;
|
|
28252
|
-
|
|
28253
|
-
|
|
28719
|
+
writeFileSync27(tmp, JSON.stringify(cache6), "utf-8");
|
|
28720
|
+
renameSync12(tmp, path31);
|
|
28254
28721
|
} catch {
|
|
28255
28722
|
}
|
|
28256
28723
|
}
|
|
28257
28724
|
function getSessionsDir() {
|
|
28258
|
-
const agentDir2 = process.env.PI_CODING_AGENT_DIR ||
|
|
28259
|
-
return
|
|
28725
|
+
const agentDir2 = process.env.PI_CODING_AGENT_DIR || join48(homedir27(), ".pi", "agent");
|
|
28726
|
+
return join48(agentDir2, "sessions");
|
|
28260
28727
|
}
|
|
28261
28728
|
function getPeriodBounds() {
|
|
28262
28729
|
const now2 = /* @__PURE__ */ new Date();
|
|
@@ -28371,9 +28838,9 @@ function extractRecords(filePath, modelIndex, models) {
|
|
|
28371
28838
|
}
|
|
28372
28839
|
function collectSessionFiles(dir, files) {
|
|
28373
28840
|
try {
|
|
28374
|
-
const entries2 =
|
|
28841
|
+
const entries2 = readdirSync15(dir, { withFileTypes: true });
|
|
28375
28842
|
for (const entry of entries2) {
|
|
28376
|
-
const entryPath =
|
|
28843
|
+
const entryPath = join48(dir, entry.name);
|
|
28377
28844
|
if (entry.isDirectory()) {
|
|
28378
28845
|
collectSessionFiles(entryPath, files);
|
|
28379
28846
|
} else if (entry.isFile() && entry.name.endsWith(".jsonl")) {
|
|
@@ -28421,7 +28888,7 @@ function collectStats() {
|
|
|
28421
28888
|
let mtimeMs = 0;
|
|
28422
28889
|
let size = 0;
|
|
28423
28890
|
try {
|
|
28424
|
-
const st =
|
|
28891
|
+
const st = statSync12(filePath);
|
|
28425
28892
|
mtimeMs = st.mtimeMs;
|
|
28426
28893
|
size = st.size;
|
|
28427
28894
|
} catch {
|
|
@@ -28514,7 +28981,7 @@ function collectStats() {
|
|
|
28514
28981
|
const dirSavings = /* @__PURE__ */ new Map();
|
|
28515
28982
|
const aggregateSavings = (path31, rows) => {
|
|
28516
28983
|
if (!rows) return;
|
|
28517
|
-
const dir = basename14(
|
|
28984
|
+
const dir = basename14(dirname22(path31));
|
|
28518
28985
|
for (const [at, before, after, replies, paid, context2] of rows) {
|
|
28519
28986
|
const key = `${at}:${before}`;
|
|
28520
28987
|
if (seenCompactions.has(key)) continue;
|
|
@@ -28561,8 +29028,8 @@ function collectStats() {
|
|
|
28561
29028
|
|
|
28562
29029
|
// packages/info-screen/pages/session.ts
|
|
28563
29030
|
init_core();
|
|
28564
|
-
import { existsSync as existsSync33, readFileSync as
|
|
28565
|
-
import { dirname as
|
|
29031
|
+
import { existsSync as existsSync33, readFileSync as readFileSync36, statSync as statSync13 } from "node:fs";
|
|
29032
|
+
import { dirname as dirname23, join as join49, resolve as resolve15 } from "node:path";
|
|
28566
29033
|
import { homedir as homedir28 } from "node:os";
|
|
28567
29034
|
|
|
28568
29035
|
// packages/info-screen/pages/context.ts
|
|
@@ -28726,22 +29193,22 @@ function gitBranch(cwd) {
|
|
|
28726
29193
|
let head2 = null;
|
|
28727
29194
|
let dir = cwd;
|
|
28728
29195
|
for (let i = 0; i < 40 && head2 === null; i++) {
|
|
28729
|
-
const git =
|
|
29196
|
+
const git = join49(dir, ".git");
|
|
28730
29197
|
if (existsSync33(git)) {
|
|
28731
29198
|
try {
|
|
28732
|
-
let headPath =
|
|
28733
|
-
if (
|
|
28734
|
-
const txt =
|
|
28735
|
-
if (txt.startsWith("gitdir:")) headPath =
|
|
29199
|
+
let headPath = join49(git, "HEAD");
|
|
29200
|
+
if (statSync13(git).isFile()) {
|
|
29201
|
+
const txt = readFileSync36(git, "utf-8").trim();
|
|
29202
|
+
if (txt.startsWith("gitdir:")) headPath = join49(resolve15(dir, txt.slice(7).trim()), "HEAD");
|
|
28736
29203
|
}
|
|
28737
|
-
const ref =
|
|
29204
|
+
const ref = readFileSync36(headPath, "utf-8").trim();
|
|
28738
29205
|
head2 = ref.startsWith("ref: refs/heads/") ? ref.slice(16) : ref.slice(0, 7);
|
|
28739
29206
|
} catch {
|
|
28740
29207
|
head2 = null;
|
|
28741
29208
|
}
|
|
28742
29209
|
break;
|
|
28743
29210
|
}
|
|
28744
|
-
const up =
|
|
29211
|
+
const up = dirname23(dir);
|
|
28745
29212
|
if (up === dir) break;
|
|
28746
29213
|
dir = up;
|
|
28747
29214
|
}
|
|
@@ -29999,7 +30466,7 @@ function armSelfDismiss(ms, hooks) {
|
|
|
29999
30466
|
|
|
30000
30467
|
// packages/info-screen/index.ts
|
|
30001
30468
|
init_core();
|
|
30002
|
-
var VERSION4 = getPackageVersion(
|
|
30469
|
+
var VERSION4 = getPackageVersion(dirname24(fileURLToPath6(import.meta.url)));
|
|
30003
30470
|
function info_screen_default(pi) {
|
|
30004
30471
|
setPiApi(pi);
|
|
30005
30472
|
registerCoreGroups();
|
|
@@ -30395,7 +30862,7 @@ init_core();
|
|
|
30395
30862
|
// packages/core/src/child-agent/pi-spawn.ts
|
|
30396
30863
|
import * as fs22 from "node:fs";
|
|
30397
30864
|
import * as path24 from "node:path";
|
|
30398
|
-
import { fileURLToPath as
|
|
30865
|
+
import { fileURLToPath as fileURLToPath7 } from "node:url";
|
|
30399
30866
|
var PI_CODING_AGENT_PACKAGE = "@earendil-works/pi-coding-agent";
|
|
30400
30867
|
var UNIPI_SUBAGENT_PI_BINARY_ENV = "UNIPI_SUBAGENT_PI_BINARY";
|
|
30401
30868
|
function findPiPackageRootFromEntry(entryPoint) {
|
|
@@ -30411,7 +30878,7 @@ function findPiPackageRootFromEntry(entryPoint) {
|
|
|
30411
30878
|
return void 0;
|
|
30412
30879
|
}
|
|
30413
30880
|
function resolveInstalledPiPackageRoot() {
|
|
30414
|
-
return findPiPackageRootFromEntry(
|
|
30881
|
+
return findPiPackageRootFromEntry(fileURLToPath7(import.meta.resolve(PI_CODING_AGENT_PACKAGE)));
|
|
30415
30882
|
}
|
|
30416
30883
|
function resolvePiPackageRoot() {
|
|
30417
30884
|
try {
|
|
@@ -30435,7 +30902,7 @@ function isStandalonePiExecutable(execPath) {
|
|
|
30435
30902
|
function resolvePiCliScript(deps = {}) {
|
|
30436
30903
|
const existsSync67 = deps.existsSync ?? fs22.existsSync;
|
|
30437
30904
|
const realpathSync8 = deps.realpathSync ?? fs22.realpathSync;
|
|
30438
|
-
const
|
|
30905
|
+
const readFileSync72 = deps.readFileSync ?? ((filePath, encoding) => fs22.readFileSync(filePath, encoding));
|
|
30439
30906
|
const argv1 = deps.argv1 ?? process.argv[1];
|
|
30440
30907
|
if (argv1) {
|
|
30441
30908
|
const argvPath = normalizePath(argv1);
|
|
@@ -30460,7 +30927,7 @@ function resolvePiCliScript(deps = {}) {
|
|
|
30460
30927
|
return path24.join(packageRoot, "package.json");
|
|
30461
30928
|
});
|
|
30462
30929
|
const packageJsonPath = resolvePackageJson();
|
|
30463
|
-
const packageJson = JSON.parse(
|
|
30930
|
+
const packageJson = JSON.parse(readFileSync72(packageJsonPath, "utf8"));
|
|
30464
30931
|
const binField = packageJson.bin;
|
|
30465
30932
|
const binPath = typeof binField === "string" ? binField : binField?.pi ?? Object.values(binField ?? {})[0];
|
|
30466
30933
|
if (!binPath) return void 0;
|
|
@@ -30517,9 +30984,9 @@ function leadExtensionArgs(argv) {
|
|
|
30517
30984
|
|
|
30518
30985
|
// packages/core/src/child-agent/runtime.ts
|
|
30519
30986
|
import { spawn as defaultSpawn } from "node:child_process";
|
|
30520
|
-
import { mkdirSync as
|
|
30987
|
+
import { mkdirSync as mkdirSync30, unlinkSync as unlinkSync7, writeFileSync as writeFileSync28 } from "node:fs";
|
|
30521
30988
|
import { tmpdir as tmpdir5 } from "node:os";
|
|
30522
|
-
import { dirname as
|
|
30989
|
+
import { dirname as dirname26, join as join51 } from "node:path";
|
|
30523
30990
|
import { randomUUID as randomUUID6 } from "node:crypto";
|
|
30524
30991
|
function primaryArg(name, args) {
|
|
30525
30992
|
if (!args) return "";
|
|
@@ -30654,9 +31121,9 @@ var ChildAgentRuntime = class {
|
|
|
30654
31121
|
this.promptPath = void 0;
|
|
30655
31122
|
}
|
|
30656
31123
|
spawn() {
|
|
30657
|
-
|
|
30658
|
-
this.promptPath =
|
|
30659
|
-
|
|
31124
|
+
mkdirSync30(dirname26(this.cfg.sessionFile), { recursive: true });
|
|
31125
|
+
this.promptPath = join51(tmpdir5(), `unipi-fusion-${randomUUID6()}.txt`);
|
|
31126
|
+
writeFileSync28(this.promptPath, this.cfg.systemPrompt, "utf8");
|
|
30660
31127
|
const command = this.cfg.command ?? getPiSpawnCommand([
|
|
30661
31128
|
...leadExtensionArgs(process.argv),
|
|
30662
31129
|
"--mode",
|
|
@@ -31123,8 +31590,8 @@ function createCompletionDelivery(send) {
|
|
|
31123
31590
|
|
|
31124
31591
|
// packages/subagents/src/manager.ts
|
|
31125
31592
|
import { randomBytes as randomBytes2 } from "node:crypto";
|
|
31126
|
-
import { existsSync as existsSync35, readFileSync as
|
|
31127
|
-
import { join as
|
|
31593
|
+
import { existsSync as existsSync35, readFileSync as readFileSync38, writeFileSync as writeFileSync29, renameSync as renameSync13, mkdirSync as mkdirSync31 } from "node:fs";
|
|
31594
|
+
import { join as join52 } from "node:path";
|
|
31128
31595
|
init_core();
|
|
31129
31596
|
var MAX_CONCURRENT = 8;
|
|
31130
31597
|
var DEPTH_ENV = "UNIPI_SUBAGENT_DEPTH";
|
|
@@ -31182,8 +31649,8 @@ var SubagentManager = class {
|
|
|
31182
31649
|
this.runtimeFactory = runtimeFactory;
|
|
31183
31650
|
}
|
|
31184
31651
|
sessionDir(cwd, leadSessionId2) {
|
|
31185
|
-
const dir =
|
|
31186
|
-
|
|
31652
|
+
const dir = join52(stateDir("subagents", "state", cwd), "sessions", leadSessionId2);
|
|
31653
|
+
mkdirSync31(dir, { recursive: true });
|
|
31187
31654
|
this.activeDir = dir;
|
|
31188
31655
|
return dir;
|
|
31189
31656
|
}
|
|
@@ -31192,13 +31659,13 @@ var SubagentManager = class {
|
|
|
31192
31659
|
records.clear();
|
|
31193
31660
|
this.finishedEvents.clear();
|
|
31194
31661
|
const dir = this.sessionDir(cwd, leadSessionId2);
|
|
31195
|
-
const indexPath =
|
|
31662
|
+
const indexPath = join52(dir, "index.json");
|
|
31196
31663
|
if (!existsSync35(indexPath)) {
|
|
31197
31664
|
publish();
|
|
31198
31665
|
return;
|
|
31199
31666
|
}
|
|
31200
31667
|
try {
|
|
31201
|
-
const list = JSON.parse(
|
|
31668
|
+
const list = JSON.parse(readFileSync38(indexPath, "utf8"));
|
|
31202
31669
|
for (const rec of list) {
|
|
31203
31670
|
records.set(rec.id, rec.status === "running" ? { ...rec, status: "failed", error: "interrupted \u2014 pi exited while it ran", endedAt: rec.lastActivity } : rec);
|
|
31204
31671
|
}
|
|
@@ -31210,10 +31677,10 @@ var SubagentManager = class {
|
|
|
31210
31677
|
persist() {
|
|
31211
31678
|
if (this.activeDir === void 0) return;
|
|
31212
31679
|
try {
|
|
31213
|
-
const indexPath =
|
|
31680
|
+
const indexPath = join52(this.activeDir, "index.json");
|
|
31214
31681
|
const tmp = `${indexPath}.tmp-${String(process.pid)}`;
|
|
31215
|
-
|
|
31216
|
-
|
|
31682
|
+
writeFileSync29(tmp, JSON.stringify([...records.values()], null, 2), "utf8");
|
|
31683
|
+
renameSync13(tmp, indexPath);
|
|
31217
31684
|
} catch {
|
|
31218
31685
|
}
|
|
31219
31686
|
}
|
|
@@ -31327,7 +31794,7 @@ var SubagentManager = class {
|
|
|
31327
31794
|
toolCalls: 0,
|
|
31328
31795
|
lastActivity: Date.now(),
|
|
31329
31796
|
task: opts.task.length > MAX_TASK_CHARS ? `${opts.task.slice(0, MAX_TASK_CHARS)}\u2026` : opts.task,
|
|
31330
|
-
sessionFile: prev?.sessionFile ??
|
|
31797
|
+
sessionFile: prev?.sessionFile ?? join52(this.sessionDir(opts.cwd, opts.leadSessionId), `${id}.jsonl`),
|
|
31331
31798
|
depth: prev?.depth ?? currentDepth() + 1
|
|
31332
31799
|
};
|
|
31333
31800
|
const runtime = this.spawnRuntime({
|
|
@@ -31451,8 +31918,8 @@ function setGraphRunPort(port) {
|
|
|
31451
31918
|
}
|
|
31452
31919
|
|
|
31453
31920
|
// packages/subagents/src/profiles.ts
|
|
31454
|
-
import { existsSync as existsSync36, readdirSync as
|
|
31455
|
-
import { basename as basename15, join as
|
|
31921
|
+
import { existsSync as existsSync36, readdirSync as readdirSync16, readFileSync as readFileSync39 } from "node:fs";
|
|
31922
|
+
import { basename as basename15, join as join53 } from "node:path";
|
|
31456
31923
|
import { homedir as homedir29 } from "node:os";
|
|
31457
31924
|
import { parseFrontmatter } from "@earendil-works/pi-coding-agent";
|
|
31458
31925
|
var EXPLORE_TOOLS = ["read", "grep", "find", "ls", "web_search", "memory_search", "memory_list"];
|
|
@@ -31473,7 +31940,7 @@ function parseToolList(value) {
|
|
|
31473
31940
|
function loadAgentFile(path31, source, pathName) {
|
|
31474
31941
|
let raw;
|
|
31475
31942
|
try {
|
|
31476
|
-
raw =
|
|
31943
|
+
raw = readFileSync39(path31, "utf8");
|
|
31477
31944
|
} catch (e) {
|
|
31478
31945
|
return { error: String(e) };
|
|
31479
31946
|
}
|
|
@@ -31495,15 +31962,15 @@ function loadAgentFile(path31, source, pathName) {
|
|
|
31495
31962
|
function agentsIn(dir, source, warnings) {
|
|
31496
31963
|
const out = /* @__PURE__ */ new Map();
|
|
31497
31964
|
if (!existsSync36(dir)) return out;
|
|
31498
|
-
for (const entry of
|
|
31965
|
+
for (const entry of readdirSync16(dir, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name))) {
|
|
31499
31966
|
if (entry.isFile() && entry.name.endsWith(".md")) {
|
|
31500
31967
|
const name = basename15(entry.name, ".md");
|
|
31501
|
-
const r = loadAgentFile(
|
|
31968
|
+
const r = loadAgentFile(join53(dir, entry.name), source, name);
|
|
31502
31969
|
if ("error" in r) warnings.push(`${entry.name}: ${r.error}`);
|
|
31503
31970
|
else out.set(r.profile.id, r.profile);
|
|
31504
31971
|
} else if (entry.isDirectory()) {
|
|
31505
31972
|
for (const cand of DIR_CANDIDATES) {
|
|
31506
|
-
const file =
|
|
31973
|
+
const file = join53(dir, entry.name, cand);
|
|
31507
31974
|
if (!existsSync36(file)) continue;
|
|
31508
31975
|
const r = loadAgentFile(file, source, entry.name);
|
|
31509
31976
|
if ("error" in r) warnings.push(`${entry.name}/${cand}: ${r.error}`);
|
|
@@ -31528,13 +31995,13 @@ function loadProfiles(cwd, home = homedir29()) {
|
|
|
31528
31995
|
merged.set(id, profile);
|
|
31529
31996
|
}
|
|
31530
31997
|
};
|
|
31531
|
-
load2(
|
|
31532
|
-
load2(
|
|
31998
|
+
load2(join53(home, ".unipi", "config", "agents"), "global");
|
|
31999
|
+
load2(join53(cwd, ".unipi", "config", "agents"), "project");
|
|
31533
32000
|
return { profiles: [...builtins, ...merged.values()], warnings };
|
|
31534
32001
|
}
|
|
31535
32002
|
|
|
31536
32003
|
// packages/subagents/src/transcript.ts
|
|
31537
|
-
import { existsSync as existsSync37, readFileSync as
|
|
32004
|
+
import { existsSync as existsSync37, readFileSync as readFileSync40, statSync as statSync14 } from "node:fs";
|
|
31538
32005
|
function firstLine(value) {
|
|
31539
32006
|
return value.split("\n", 1)[0] ?? "";
|
|
31540
32007
|
}
|
|
@@ -31569,10 +32036,10 @@ var fileCache = /* @__PURE__ */ new Map();
|
|
|
31569
32036
|
function itemsFromSessionFile(path31) {
|
|
31570
32037
|
if (!existsSync37(path31)) return [];
|
|
31571
32038
|
try {
|
|
31572
|
-
const st =
|
|
32039
|
+
const st = statSync14(path31);
|
|
31573
32040
|
const hit = fileCache.get(path31);
|
|
31574
32041
|
if (hit !== void 0 && hit.mtimeMs === st.mtimeMs && hit.size === st.size) return hit.items;
|
|
31575
|
-
const items = parseSession(
|
|
32042
|
+
const items = parseSession(readFileSync40(path31, "utf8"));
|
|
31576
32043
|
if (fileCache.size > 50) fileCache.clear();
|
|
31577
32044
|
fileCache.set(path31, { mtimeMs: st.mtimeMs, size: st.size, items });
|
|
31578
32045
|
return items;
|
|
@@ -31863,8 +32330,8 @@ var SubagentDock = class {
|
|
|
31863
32330
|
|
|
31864
32331
|
// packages/subagents/src/agents.ts
|
|
31865
32332
|
init_core();
|
|
31866
|
-
import { existsSync as existsSync38, mkdirSync as
|
|
31867
|
-
import { dirname as
|
|
32333
|
+
import { existsSync as existsSync38, mkdirSync as mkdirSync32, readFileSync as readFileSync41, rmSync as rmSync7, writeFileSync as writeFileSync30 } from "node:fs";
|
|
32334
|
+
import { dirname as dirname27, join as join54 } from "node:path";
|
|
31868
32335
|
import { homedir as homedir30 } from "node:os";
|
|
31869
32336
|
import { parseFrontmatter as parseFrontmatter2 } from "@earendil-works/pi-coding-agent";
|
|
31870
32337
|
|
|
@@ -31917,12 +32384,12 @@ var AGENTS_COMMAND = "unipi:agents";
|
|
|
31917
32384
|
var NAME_RE = /^[a-z0-9][a-z0-9_-]{0,47}$/;
|
|
31918
32385
|
var NEW_LABEL = "\uFF0B New agent\u2026";
|
|
31919
32386
|
function agentsDir(scope, cwd, home = homedir30()) {
|
|
31920
|
-
return
|
|
32387
|
+
return join54(scope === "global" ? home : cwd, ".unipi", "config", "agents");
|
|
31921
32388
|
}
|
|
31922
32389
|
function agentFile(profile, cwd, home = homedir30()) {
|
|
31923
32390
|
if (profile.source === "builtin") return void 0;
|
|
31924
32391
|
const dir = agentsDir(profile.source, cwd, home);
|
|
31925
|
-
for (const candidate of [
|
|
32392
|
+
for (const candidate of [join54(dir, `${profile.id}.md`), ...["AGENT.md", "AGENTS.md", "agent.md", "agents.md"].map((f) => join54(dir, profile.id, f))]) {
|
|
31926
32393
|
if (existsSync38(candidate)) return candidate;
|
|
31927
32394
|
}
|
|
31928
32395
|
return void 0;
|
|
@@ -32012,14 +32479,14 @@ async function createAgent(ctx, existing, onChange) {
|
|
|
32012
32479
|
if (tools === null) return;
|
|
32013
32480
|
const prompt = await ui.editor(`${name} \u2014 system prompt (enter saves)`, promptTemplate(name, description));
|
|
32014
32481
|
if (prompt === void 0 || !prompt.trim()) return;
|
|
32015
|
-
const file =
|
|
32016
|
-
|
|
32017
|
-
|
|
32482
|
+
const file = join54(agentsDir(scope, ctx.cwd), `${name}.md`);
|
|
32483
|
+
mkdirSync32(dirname27(file), { recursive: true });
|
|
32484
|
+
writeFileSync30(file, agentMarkdown({ name, description, model, tools, prompt }), "utf8");
|
|
32018
32485
|
onChange();
|
|
32019
32486
|
ui.notify(`Agent ${name} saved to ${file}. The agent can use it from the next turn.`, "info");
|
|
32020
32487
|
}
|
|
32021
32488
|
async function editAgent(ctx, file, onChange) {
|
|
32022
|
-
const before =
|
|
32489
|
+
const before = readFileSync41(file, "utf8");
|
|
32023
32490
|
const after = await ctx.ui.editor(`Edit ${file}`, before);
|
|
32024
32491
|
if (after === void 0 || after === before) return;
|
|
32025
32492
|
try {
|
|
@@ -32028,7 +32495,7 @@ async function editAgent(ctx, file, onChange) {
|
|
|
32028
32495
|
ctx.ui.notify(`Not saved \u2014 frontmatter doesn't parse: ${e instanceof Error ? e.message : String(e)}`, "error");
|
|
32029
32496
|
return;
|
|
32030
32497
|
}
|
|
32031
|
-
|
|
32498
|
+
writeFileSync30(file, after, "utf8");
|
|
32032
32499
|
onChange();
|
|
32033
32500
|
ctx.ui.notify(`Saved ${file}.`, "info");
|
|
32034
32501
|
}
|
|
@@ -32045,16 +32512,16 @@ async function manageCustom(ctx, profile, onChange) {
|
|
|
32045
32512
|
const choice = await ctx.ui.select(`${profile.id} (${profile.source}) \u2014 ${file}`, [EDIT, COPY, DELETE]);
|
|
32046
32513
|
if (choice === EDIT) return editAgent(ctx, file, onChange);
|
|
32047
32514
|
if (choice === COPY) {
|
|
32048
|
-
const target =
|
|
32515
|
+
const target = join54(agentsDir(other, ctx.cwd), `${profile.id}.md`);
|
|
32049
32516
|
if (existsSync38(target) && !await ctx.ui.confirm("Overwrite?", `${target} already exists.`)) return;
|
|
32050
|
-
|
|
32051
|
-
|
|
32517
|
+
mkdirSync32(dirname27(target), { recursive: true });
|
|
32518
|
+
writeFileSync30(target, readFileSync41(file, "utf8"), "utf8");
|
|
32052
32519
|
onChange();
|
|
32053
32520
|
ctx.ui.notify(`Copied to ${target}.`, "info");
|
|
32054
32521
|
return;
|
|
32055
32522
|
}
|
|
32056
32523
|
if (choice === DELETE && await ctx.ui.confirm(`Delete ${profile.id}?`, file)) {
|
|
32057
|
-
|
|
32524
|
+
rmSync7(file);
|
|
32058
32525
|
onChange();
|
|
32059
32526
|
ctx.ui.notify(`Deleted ${file}.`, "info");
|
|
32060
32527
|
}
|
|
@@ -32338,6 +32805,13 @@ ${body}
|
|
|
32338
32805
|
profiles = loaded.profiles;
|
|
32339
32806
|
return loaded.warnings;
|
|
32340
32807
|
}
|
|
32808
|
+
function currentProfiles(cwd) {
|
|
32809
|
+
try {
|
|
32810
|
+
profiles = loadProfiles(cwd).profiles;
|
|
32811
|
+
} catch {
|
|
32812
|
+
}
|
|
32813
|
+
return profiles;
|
|
32814
|
+
}
|
|
32341
32815
|
function refresh(cwd, ctx) {
|
|
32342
32816
|
for (const w of reload(cwd)) {
|
|
32343
32817
|
if (warned.has(w)) continue;
|
|
@@ -32542,7 +33016,7 @@ ${body}
|
|
|
32542
33016
|
const cwd = ctx.cwd ?? process.cwd();
|
|
32543
33017
|
const resumeId = params.resume?.trim() || void 0;
|
|
32544
33018
|
const profileName = resumeId !== void 0 ? manager.record(resumeId)?.profile ?? params.profile : params.profile;
|
|
32545
|
-
const profile =
|
|
33019
|
+
const profile = currentProfiles(cwd).find((p) => p.id === profileName);
|
|
32546
33020
|
if (!profile) {
|
|
32547
33021
|
return textResult5(`Unknown profile "${params.profile}". Available: ${profiles.map((p) => p.id).join(", ")}`, { owner: "subagents", status: "failed", title: params.title }, true);
|
|
32548
33022
|
}
|
|
@@ -32684,15 +33158,17 @@ ${body}
|
|
|
32684
33158
|
});
|
|
32685
33159
|
registerAgentsCommand(pi, { onChange: (cwd) => refresh(cwd) });
|
|
32686
33160
|
const graphPort = {
|
|
32687
|
-
|
|
33161
|
+
// Fresh list: the graph validates a work item's profile against this, and
|
|
33162
|
+
// a profile created earlier in this turn must be accepted, not refused.
|
|
33163
|
+
profiles: () => enabled && canSpawn() ? currentProfiles(uiCtx2?.cwd ?? process.cwd()).map((p) => p.id) : [],
|
|
32688
33164
|
start: (request) => {
|
|
32689
33165
|
const ctx = uiCtx2;
|
|
32690
33166
|
if (ctx === void 0) return { error: "subagents are not ready (no session)", retryable: true };
|
|
32691
33167
|
if (!enabled || !canSpawn()) return { error: "subagents are disabled in this session" };
|
|
33168
|
+
const cwd = ctx.cwd ?? process.cwd();
|
|
32692
33169
|
const resumeProfile = request.resume !== void 0 ? manager.record(request.resume)?.profile : void 0;
|
|
32693
|
-
const profile =
|
|
33170
|
+
const profile = currentProfiles(cwd).find((p) => p.id === (resumeProfile ?? request.profile));
|
|
32694
33171
|
if (!profile) return { error: `unknown subagent profile "${request.profile}" (available: ${profiles.map((p) => p.id).join(", ")})` };
|
|
32695
|
-
const cwd = ctx.cwd ?? process.cwd();
|
|
32696
33172
|
const start = manager.start({
|
|
32697
33173
|
title: request.title,
|
|
32698
33174
|
task: request.task,
|
|
@@ -32758,9 +33234,9 @@ init_core();
|
|
|
32758
33234
|
|
|
32759
33235
|
// packages/background-tasks/src/config.ts
|
|
32760
33236
|
init_core();
|
|
32761
|
-
import { existsSync as existsSync39, mkdirSync as
|
|
33237
|
+
import { existsSync as existsSync39, mkdirSync as mkdirSync33, readFileSync as readFileSync42, renameSync as renameSync14, writeFileSync as writeFileSync31 } from "node:fs";
|
|
32762
33238
|
import { homedir as homedir31 } from "node:os";
|
|
32763
|
-
import { join as
|
|
33239
|
+
import { join as join55 } from "node:path";
|
|
32764
33240
|
var DEFAULT_CONFIG3 = {
|
|
32765
33241
|
enabled: true,
|
|
32766
33242
|
notifyOnCompletion: true,
|
|
@@ -32769,15 +33245,15 @@ var DEFAULT_CONFIG3 = {
|
|
|
32769
33245
|
maxOutputBytes: 20 * 1024 * 1024
|
|
32770
33246
|
};
|
|
32771
33247
|
function getGlobalConfigPath() {
|
|
32772
|
-
return
|
|
33248
|
+
return join55(homedir31(), ".unipi", "config", "background-tasks.json");
|
|
32773
33249
|
}
|
|
32774
33250
|
function getWorkspaceConfigPath(cwd) {
|
|
32775
|
-
return
|
|
33251
|
+
return join55(cwd, ".unipi", "config", "background-tasks.json");
|
|
32776
33252
|
}
|
|
32777
33253
|
function loadConfigFromPath(filePath) {
|
|
32778
33254
|
if (!existsSync39(filePath)) return null;
|
|
32779
33255
|
try {
|
|
32780
|
-
const parsed = JSON.parse(
|
|
33256
|
+
const parsed = JSON.parse(readFileSync42(filePath, "utf-8"));
|
|
32781
33257
|
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) return null;
|
|
32782
33258
|
return parsed;
|
|
32783
33259
|
} catch {
|
|
@@ -32869,12 +33345,12 @@ import { spawn as nodeSpawn2 } from "node:child_process";
|
|
|
32869
33345
|
import { randomBytes as randomBytes4 } from "node:crypto";
|
|
32870
33346
|
import { createWriteStream as createWriteStream2, existsSync as existsSync40 } from "node:fs";
|
|
32871
33347
|
import { mkdir, writeFile as writeFile3 } from "node:fs/promises";
|
|
32872
|
-
import { join as
|
|
33348
|
+
import { join as join59 } from "node:path";
|
|
32873
33349
|
import { formatSize } from "@earendil-works/pi-coding-agent";
|
|
32874
33350
|
|
|
32875
33351
|
// packages/background-tasks/src/types.ts
|
|
32876
|
-
import { statSync as
|
|
32877
|
-
import { join as
|
|
33352
|
+
import { statSync as statSync15 } from "node:fs";
|
|
33353
|
+
import { join as join56 } from "node:path";
|
|
32878
33354
|
import { open } from "node:fs/promises";
|
|
32879
33355
|
import { extname as extname3, isAbsolute as isAbsolute7, win32 } from "node:path";
|
|
32880
33356
|
function deriveCompletionDeliveryGuidance(notifyOnCompletion, triggerOnCompletion) {
|
|
@@ -33186,7 +33662,7 @@ function validateWindowsShellPath(path31, label) {
|
|
|
33186
33662
|
}
|
|
33187
33663
|
let stats;
|
|
33188
33664
|
try {
|
|
33189
|
-
stats =
|
|
33665
|
+
stats = statSync15(path31);
|
|
33190
33666
|
} catch (error) {
|
|
33191
33667
|
failShellInvocation(`${label} stat failed: ${shellErrorMessage(error)}`);
|
|
33192
33668
|
}
|
|
@@ -33198,7 +33674,7 @@ function inspectWindowsShellCandidate(path31) {
|
|
|
33198
33674
|
return { found: false, diagnostic: `${path31} is not a .exe or .com path` };
|
|
33199
33675
|
}
|
|
33200
33676
|
try {
|
|
33201
|
-
const stats =
|
|
33677
|
+
const stats = statSync15(path31);
|
|
33202
33678
|
if (stats.isFile()) return { found: true };
|
|
33203
33679
|
return { found: false, diagnostic: `${path31} is not a regular file` };
|
|
33204
33680
|
} catch (error) {
|
|
@@ -33213,7 +33689,7 @@ function resolveWindowsBash(env) {
|
|
|
33213
33689
|
const diagnostics = [];
|
|
33214
33690
|
for (const dir of pathValue.split(";").filter((entry) => entry.length > 0)) {
|
|
33215
33691
|
for (const name of ["bash.exe", "bash.com"]) {
|
|
33216
|
-
const candidate =
|
|
33692
|
+
const candidate = join56(dir, name);
|
|
33217
33693
|
const result2 = inspectWindowsShellCandidate(candidate);
|
|
33218
33694
|
if (result2.found) return candidate;
|
|
33219
33695
|
diagnostics.push(result2.diagnostic);
|
|
@@ -33303,7 +33779,7 @@ function appendOutputTail(task, chunk) {
|
|
|
33303
33779
|
task.outputTail = tail.slice(-OUTPUT_TAIL_LINES);
|
|
33304
33780
|
}
|
|
33305
33781
|
async function boundedRead(filePath, maxBytes, tail) {
|
|
33306
|
-
const stats =
|
|
33782
|
+
const stats = statSync15(filePath);
|
|
33307
33783
|
const totalBytes = stats.size;
|
|
33308
33784
|
const bytesToRead = Math.min(totalBytes, maxBytes);
|
|
33309
33785
|
if (bytesToRead === 0) return { content: "", truncated: false, bytesRead: 0, totalBytes };
|
|
@@ -33348,7 +33824,7 @@ import { createHash as createHash7 } from "node:crypto";
|
|
|
33348
33824
|
// packages/background-tasks/src/durable-fs.ts
|
|
33349
33825
|
import { randomBytes as randomBytes3 } from "node:crypto";
|
|
33350
33826
|
import { open as nodeOpen, rename as nodeRename, rm as nodeRm } from "node:fs/promises";
|
|
33351
|
-
import { basename as basename16, dirname as
|
|
33827
|
+
import { basename as basename16, dirname as dirname28, join as join57 } from "node:path";
|
|
33352
33828
|
var DurableFileError = class extends Error {
|
|
33353
33829
|
operation;
|
|
33354
33830
|
path;
|
|
@@ -33486,7 +33962,7 @@ async function writeWithOperations(operations, path31, data) {
|
|
|
33486
33962
|
}
|
|
33487
33963
|
async function syncDirectoryAfterRename(operations, targetPath, temporaryPath) {
|
|
33488
33964
|
if (operations.platform === "win32") return;
|
|
33489
|
-
const directoryPath =
|
|
33965
|
+
const directoryPath = dirname28(targetPath);
|
|
33490
33966
|
let handle;
|
|
33491
33967
|
try {
|
|
33492
33968
|
handle = await operations.openDirectory(directoryPath);
|
|
@@ -33545,7 +34021,7 @@ async function renameWithWindowsContention(operations, temporaryPath, targetPath
|
|
|
33545
34021
|
return lastError;
|
|
33546
34022
|
}
|
|
33547
34023
|
function temporaryPathForTarget(target) {
|
|
33548
|
-
return
|
|
34024
|
+
return join57(dirname28(target), `.${basename16(target)}.${String(process.pid)}.${randomBytes3(6).toString("hex")}.tmp`);
|
|
33549
34025
|
}
|
|
33550
34026
|
var nodeOperations = {
|
|
33551
34027
|
platform: process.platform,
|
|
@@ -33610,10 +34086,10 @@ async function closeAndFsyncOutputStream(stream) {
|
|
|
33610
34086
|
}
|
|
33611
34087
|
|
|
33612
34088
|
// packages/background-tasks/src/pi-launch.ts
|
|
33613
|
-
import { readFileSync as
|
|
34089
|
+
import { readFileSync as readFileSync43, realpathSync as realpathSync6, statSync as statSync16 } from "node:fs";
|
|
33614
34090
|
import { createRequire as createRequire3 } from "node:module";
|
|
33615
|
-
import { dirname as
|
|
33616
|
-
import { fileURLToPath as
|
|
34091
|
+
import { dirname as dirname29, extname as extname4, isAbsolute as isAbsolute8, join as join58, relative as relative3, sep as sep5 } from "node:path";
|
|
34092
|
+
import { fileURLToPath as fileURLToPath8 } from "node:url";
|
|
33617
34093
|
var PiLaunchResolutionError = class extends Error {
|
|
33618
34094
|
code = "pi_executable_resolution_failed";
|
|
33619
34095
|
constructor(message) {
|
|
@@ -33631,23 +34107,23 @@ function defaultResolvePackageJson(specifier) {
|
|
|
33631
34107
|
if (specifier !== PI_PACKAGE_MANIFEST) throw manifestError;
|
|
33632
34108
|
let packageEntry;
|
|
33633
34109
|
try {
|
|
33634
|
-
packageEntry =
|
|
34110
|
+
packageEntry = fileURLToPath8(import.meta.resolve(PI_PACKAGE_NAME));
|
|
33635
34111
|
} catch (entryError) {
|
|
33636
34112
|
throw new Error(
|
|
33637
34113
|
`${errorMessage(manifestError)}; package entry resolve failed: ${errorMessage(entryError)}`
|
|
33638
34114
|
);
|
|
33639
34115
|
}
|
|
33640
34116
|
const diagnostics = [];
|
|
33641
|
-
let dir =
|
|
34117
|
+
let dir = dirname29(packageEntry);
|
|
33642
34118
|
for (; ; ) {
|
|
33643
|
-
const candidate =
|
|
34119
|
+
const candidate = join58(dir, "package.json");
|
|
33644
34120
|
try {
|
|
33645
|
-
if (
|
|
34121
|
+
if (statSync16(candidate).isFile()) return candidate;
|
|
33646
34122
|
diagnostics.push(`${candidate} is not a regular file`);
|
|
33647
34123
|
} catch (statError) {
|
|
33648
34124
|
diagnostics.push(`${candidate}: ${errorMessage(statError)}`);
|
|
33649
34125
|
}
|
|
33650
|
-
const parent =
|
|
34126
|
+
const parent = dirname29(dir);
|
|
33651
34127
|
if (parent === dir) {
|
|
33652
34128
|
throw new Error(
|
|
33653
34129
|
`${errorMessage(manifestError)}; package entry search failed: ${diagnostics.join("; ")}`
|
|
@@ -33700,9 +34176,9 @@ function resolvePiLaunch(deps = {}) {
|
|
|
33700
34176
|
const platform = deps.platform ?? process.platform;
|
|
33701
34177
|
if (platform !== "win32") return { executable: "pi", argvPrefix: [], kind: "path" };
|
|
33702
34178
|
const resolvePackageJson = deps.resolvePackageJson ?? defaultResolvePackageJson;
|
|
33703
|
-
const readFile2 = deps.readFile ??
|
|
34179
|
+
const readFile2 = deps.readFile ?? readFileSync43;
|
|
33704
34180
|
const realpath2 = deps.realpath ?? realpathSync6;
|
|
33705
|
-
const stat = deps.stat ??
|
|
34181
|
+
const stat = deps.stat ?? statSync16;
|
|
33706
34182
|
const execPath = deps.execPath ?? process.execPath;
|
|
33707
34183
|
let manifestPath;
|
|
33708
34184
|
try {
|
|
@@ -33710,14 +34186,14 @@ function resolvePiLaunch(deps = {}) {
|
|
|
33710
34186
|
} catch (error) {
|
|
33711
34187
|
failResolution(`package manifest resolve failed for ${PI_PACKAGE_MANIFEST}: ${errorMessage(error)}`);
|
|
33712
34188
|
}
|
|
33713
|
-
const packageRoot =
|
|
34189
|
+
const packageRoot = dirname29(manifestPath);
|
|
33714
34190
|
const packageRootReal = readPath("package root realpath", packageRoot, () => realpath2(packageRoot));
|
|
33715
34191
|
const manifest = parseManifest(
|
|
33716
34192
|
readPath("manifest read", manifestPath, () => readFile2(manifestPath)),
|
|
33717
34193
|
manifestPath
|
|
33718
34194
|
);
|
|
33719
34195
|
const bin = readPiBin(manifest, manifestPath);
|
|
33720
|
-
const targetCandidate =
|
|
34196
|
+
const targetCandidate = join58(packageRoot, bin);
|
|
33721
34197
|
const targetReal = readPath("bin target realpath", targetCandidate, () => realpath2(targetCandidate));
|
|
33722
34198
|
if (!pathInside(packageRootReal, targetReal)) {
|
|
33723
34199
|
failResolution("Pi package bin target resolves outside the package root");
|
|
@@ -34405,8 +34881,8 @@ var BackgroundTaskRegistry = class _BackgroundTaskRegistry {
|
|
|
34405
34881
|
const sessionId3 = sanitizePathSegment(ctx.sessionId ?? `session-${String(process.pid)}`);
|
|
34406
34882
|
const runId = `${sessionId3}-${String(process.pid)}-${this.runtimeNonce}`;
|
|
34407
34883
|
const tmpBase = process.env["UNIPI_BG_TMP_DIR"] ?? (process.env["TMPDIR"] ?? "/tmp");
|
|
34408
|
-
const runtimeDirAbs =
|
|
34409
|
-
const runtimeDirDisplay =
|
|
34884
|
+
const runtimeDirAbs = join59(tmpBase, "unipi-bg-tasks", runId);
|
|
34885
|
+
const runtimeDirDisplay = join59(tmpBase, "unipi-bg-tasks", runId);
|
|
34410
34886
|
await mkdir(runtimeDirAbs, { recursive: true });
|
|
34411
34887
|
this.runtimeDir = { abs: runtimeDirAbs, display: runtimeDirDisplay };
|
|
34412
34888
|
return this.runtimeDir;
|
|
@@ -34422,9 +34898,9 @@ var BackgroundTaskRegistry = class _BackgroundTaskRegistry {
|
|
|
34422
34898
|
const piTelemetryLaunch = piTelemetryRequested && baseInvocation.dialect === "posix" ? resolvePiLaunch({ platform: this.platform }) : void 0;
|
|
34423
34899
|
const dir = await this.ensureRuntimeDir(ctx);
|
|
34424
34900
|
const id = this.makeTaskIdFn();
|
|
34425
|
-
const outputAbsPath =
|
|
34426
|
-
const metadataAbsPath =
|
|
34427
|
-
const outputPath =
|
|
34901
|
+
const outputAbsPath = join59(dir.abs, `${id}.output`);
|
|
34902
|
+
const metadataAbsPath = join59(dir.abs, `${id}.json`);
|
|
34903
|
+
const outputPath = join59(dir.display, `${id}.output`);
|
|
34428
34904
|
const timeoutSeconds = typeof options.timeoutSeconds === "number" && Number.isFinite(options.timeoutSeconds) && options.timeoutSeconds > 0 ? Math.floor(options.timeoutSeconds) : void 0;
|
|
34429
34905
|
const taskName = normalizeTaskName(options.name) ?? normalizeTaskName(options.description) ?? deriveTaskNameFromCommand(normalizedCommand);
|
|
34430
34906
|
const trimmedDescription = options.description?.trim();
|
|
@@ -34477,7 +34953,7 @@ var BackgroundTaskRegistry = class _BackgroundTaskRegistry {
|
|
|
34477
34953
|
if (baseInvocation.dialect === "posix") {
|
|
34478
34954
|
if (piTelemetryLaunch === void 0)
|
|
34479
34955
|
throw new Error("Pi telemetry launch spec was not resolved");
|
|
34480
|
-
const wrapperAbsPath =
|
|
34956
|
+
const wrapperAbsPath = join59(dir.abs, `${id}.pi-telemetry-wrapper.cjs`);
|
|
34481
34957
|
await writeFile3(
|
|
34482
34958
|
wrapperAbsPath,
|
|
34483
34959
|
createPiTelemetryWrapperSource(buildModelWindowIndex(ctx), piTelemetryLaunch),
|
|
@@ -34530,9 +35006,9 @@ ${normalizedCommand}`;
|
|
|
34530
35006
|
throw new Error("Cannot adopt a background task while Pi is shutting down");
|
|
34531
35007
|
const dir = await this.ensureRuntimeDir(ctx);
|
|
34532
35008
|
const id = this.makeTaskIdFn();
|
|
34533
|
-
const outputAbsPath =
|
|
34534
|
-
const metadataAbsPath =
|
|
34535
|
-
const outputPath =
|
|
35009
|
+
const outputAbsPath = join59(dir.abs, `${id}.output`);
|
|
35010
|
+
const metadataAbsPath = join59(dir.abs, `${id}.json`);
|
|
35011
|
+
const outputPath = join59(dir.display, `${id}.output`);
|
|
34536
35012
|
const taskName = normalizeTaskName(options.name) ?? deriveTaskNameFromCommand(normalizedCommand);
|
|
34537
35013
|
const task = {
|
|
34538
35014
|
id,
|
|
@@ -37245,8 +37721,8 @@ function btwExtension(pi) {
|
|
|
37245
37721
|
|
|
37246
37722
|
// packages/web-api/src/index.ts
|
|
37247
37723
|
init_core();
|
|
37248
|
-
import { dirname as
|
|
37249
|
-
import { fileURLToPath as
|
|
37724
|
+
import { dirname as dirname30 } from "node:path";
|
|
37725
|
+
import { fileURLToPath as fileURLToPath9 } from "node:url";
|
|
37250
37726
|
|
|
37251
37727
|
// packages/web-api/src/tools.ts
|
|
37252
37728
|
init_registry();
|
|
@@ -39134,7 +39610,7 @@ var perplexityProvider = {
|
|
|
39134
39610
|
registry4.register(perplexityProvider);
|
|
39135
39611
|
|
|
39136
39612
|
// packages/web-api/src/index.ts
|
|
39137
|
-
var VERSION5 = getPackageVersion(
|
|
39613
|
+
var VERSION5 = getPackageVersion(dirname30(fileURLToPath9(import.meta.url)));
|
|
39138
39614
|
function getInfoRegistry2() {
|
|
39139
39615
|
return globalThis.__unipi_info_registry;
|
|
39140
39616
|
}
|
|
@@ -39235,8 +39711,8 @@ function src_default2(pi) {
|
|
|
39235
39711
|
// packages/skill-registry/index.ts
|
|
39236
39712
|
init_core();
|
|
39237
39713
|
import { existsSync as existsSync46 } from "node:fs";
|
|
39238
|
-
import { dirname as
|
|
39239
|
-
import { fileURLToPath as
|
|
39714
|
+
import { dirname as dirname32 } from "node:path";
|
|
39715
|
+
import { fileURLToPath as fileURLToPath10 } from "node:url";
|
|
39240
39716
|
|
|
39241
39717
|
// packages/skill-registry/src/registry.ts
|
|
39242
39718
|
import { homedir as homedir34 } from "node:os";
|
|
@@ -39604,11 +40080,11 @@ var SkillEditor = class {
|
|
|
39604
40080
|
};
|
|
39605
40081
|
|
|
39606
40082
|
// packages/skill-registry/src/vault.ts
|
|
39607
|
-
import { existsSync as existsSync45, readdirSync as
|
|
40083
|
+
import { existsSync as existsSync45, readdirSync as readdirSync18, readFileSync as readFileSync47, statSync as statSync18 } from "node:fs";
|
|
39608
40084
|
import { homedir as homedir36 } from "node:os";
|
|
39609
|
-
import { join as
|
|
40085
|
+
import { join as join63 } from "node:path";
|
|
39610
40086
|
function vaultDir() {
|
|
39611
|
-
return process.env.UNIPI_SKILL_VAULT ||
|
|
40087
|
+
return process.env.UNIPI_SKILL_VAULT || join63(homedir36(), ".unipi", "skill-vault");
|
|
39612
40088
|
}
|
|
39613
40089
|
function parseFrontmatter3(text) {
|
|
39614
40090
|
const match = text.match(/^---\r?\n([\s\S]*?)\r?\n---/);
|
|
@@ -39635,14 +40111,14 @@ function listVaultSkills(dir = vaultDir()) {
|
|
|
39635
40111
|
if (depth > 3 || !existsSync45(d)) return;
|
|
39636
40112
|
let names;
|
|
39637
40113
|
try {
|
|
39638
|
-
names =
|
|
40114
|
+
names = readdirSync18(d);
|
|
39639
40115
|
} catch {
|
|
39640
40116
|
return;
|
|
39641
40117
|
}
|
|
39642
40118
|
if (names.includes("SKILL.md") && d !== dir) {
|
|
39643
|
-
const filePath =
|
|
40119
|
+
const filePath = join63(d, "SKILL.md");
|
|
39644
40120
|
try {
|
|
39645
|
-
const fm = parseFrontmatter3(
|
|
40121
|
+
const fm = parseFrontmatter3(readFileSync47(filePath, "utf-8"));
|
|
39646
40122
|
const name = fm.name || d.split("/").pop();
|
|
39647
40123
|
if (fm.description) out.push({ name, description: fm.description, filePath, baseDir: d });
|
|
39648
40124
|
} catch {
|
|
@@ -39651,9 +40127,9 @@ function listVaultSkills(dir = vaultDir()) {
|
|
|
39651
40127
|
}
|
|
39652
40128
|
for (const n of names) {
|
|
39653
40129
|
if (n.startsWith(".")) continue;
|
|
39654
|
-
const p =
|
|
40130
|
+
const p = join63(d, n);
|
|
39655
40131
|
try {
|
|
39656
|
-
if (
|
|
40132
|
+
if (statSync18(p).isDirectory()) walk2(p, depth + 1);
|
|
39657
40133
|
} catch {
|
|
39658
40134
|
}
|
|
39659
40135
|
}
|
|
@@ -39664,7 +40140,7 @@ function listVaultSkills(dir = vaultDir()) {
|
|
|
39664
40140
|
|
|
39665
40141
|
// packages/skill-registry/src/judge.ts
|
|
39666
40142
|
init_core();
|
|
39667
|
-
import { basename as basename17, dirname as
|
|
40143
|
+
import { basename as basename17, dirname as dirname31 } from "node:path";
|
|
39668
40144
|
import { homedir as homedir37 } from "node:os";
|
|
39669
40145
|
var SKILLS_JUDGED_ENTRY = "unipi:skills-judged";
|
|
39670
40146
|
var SKILLS_REVEALED_ENTRY = "unipi:skills-revealed";
|
|
@@ -39783,7 +40259,7 @@ function hiddenIndex(hidden) {
|
|
|
39783
40259
|
const odd = [];
|
|
39784
40260
|
for (const e of [...hidden].sort((a, b) => a.name.localeCompare(b.name))) {
|
|
39785
40261
|
if (e.location && basename17(e.location) === e.name) {
|
|
39786
|
-
const parent = tilde(
|
|
40262
|
+
const parent = tilde(dirname31(e.location));
|
|
39787
40263
|
groups.set(parent, [...groups.get(parent) ?? [], e.name]);
|
|
39788
40264
|
} else {
|
|
39789
40265
|
odd.push(`${e.name} (${tilde(e.location)}/SKILL.md)`);
|
|
@@ -39872,7 +40348,7 @@ Read a skill's SKILL.md before using it.`;
|
|
|
39872
40348
|
}
|
|
39873
40349
|
|
|
39874
40350
|
// packages/skill-registry/index.ts
|
|
39875
|
-
var VERSION6 = getPackageVersion(
|
|
40351
|
+
var VERSION6 = getPackageVersion(dirname32(fileURLToPath10(import.meta.url)));
|
|
39876
40352
|
function skillRegistry(pi) {
|
|
39877
40353
|
let state2 = null;
|
|
39878
40354
|
let lastCatalog = [];
|
|
@@ -40051,8 +40527,8 @@ function skillRegistry(pi) {
|
|
|
40051
40527
|
|
|
40052
40528
|
// packages/ask-user/index.ts
|
|
40053
40529
|
init_core();
|
|
40054
|
-
import { dirname as
|
|
40055
|
-
import { fileURLToPath as
|
|
40530
|
+
import { dirname as dirname33 } from "node:path";
|
|
40531
|
+
import { fileURLToPath as fileURLToPath11 } from "node:url";
|
|
40056
40532
|
|
|
40057
40533
|
// packages/ask-user/config.ts
|
|
40058
40534
|
init_core();
|
|
@@ -40134,7 +40610,7 @@ function getAskUserSettings(cwd = process.cwd()) {
|
|
|
40134
40610
|
|
|
40135
40611
|
// packages/ask-user/tools.ts
|
|
40136
40612
|
init_core();
|
|
40137
|
-
import { readFileSync as
|
|
40613
|
+
import { readFileSync as readFileSync48 } from "node:fs";
|
|
40138
40614
|
import { Type as Type13 } from "typebox";
|
|
40139
40615
|
import { Text as Text7 } from "@earendil-works/pi-tui";
|
|
40140
40616
|
|
|
@@ -40145,9 +40621,9 @@ import { Input as Input4, Key as Key17, matchesKey as matchesKey17, truncateToWi
|
|
|
40145
40621
|
// packages/ask-user/clipboard.ts
|
|
40146
40622
|
import { spawnSync as spawnSync3 } from "node:child_process";
|
|
40147
40623
|
import { randomUUID as randomUUID7 } from "node:crypto";
|
|
40148
|
-
import { writeFileSync as
|
|
40624
|
+
import { writeFileSync as writeFileSync34 } from "node:fs";
|
|
40149
40625
|
import { tmpdir as tmpdir6 } from "node:os";
|
|
40150
|
-
import { join as
|
|
40626
|
+
import { join as join64 } from "node:path";
|
|
40151
40627
|
function run2(cmd, args) {
|
|
40152
40628
|
try {
|
|
40153
40629
|
const r = spawnSync3(cmd, args, { timeout: 3e3, maxBuffer: 64 * 1024 * 1024 });
|
|
@@ -40172,9 +40648,9 @@ function readClipboardImageFile(env = process.env) {
|
|
|
40172
40648
|
data = wayland ? run2("wl-paste", ["--type", found]) : run2("xclip", ["-selection", "clipboard", "-t", found, "-o"]);
|
|
40173
40649
|
}
|
|
40174
40650
|
if (!data) return void 0;
|
|
40175
|
-
const file =
|
|
40651
|
+
const file = join64(tmpdir6(), `unipi-ask-${randomUUID7()}${EXT2[type] ?? ".png"}`);
|
|
40176
40652
|
try {
|
|
40177
|
-
|
|
40653
|
+
writeFileSync34(file, data);
|
|
40178
40654
|
return file;
|
|
40179
40655
|
} catch {
|
|
40180
40656
|
return void 0;
|
|
@@ -40776,7 +41252,7 @@ function imageParts(attachments) {
|
|
|
40776
41252
|
for (const a of attachments) {
|
|
40777
41253
|
if (a.kind !== "image") continue;
|
|
40778
41254
|
try {
|
|
40779
|
-
parts.push({ type: "image", data:
|
|
41255
|
+
parts.push({ type: "image", data: readFileSync48(a.path).toString("base64"), mimeType: a.mimeType ?? "image/png" });
|
|
40780
41256
|
} catch {
|
|
40781
41257
|
}
|
|
40782
41258
|
}
|
|
@@ -40942,7 +41418,7 @@ function renderAskResult(details, theme) {
|
|
|
40942
41418
|
}
|
|
40943
41419
|
|
|
40944
41420
|
// packages/ask-user/index.ts
|
|
40945
|
-
var VERSION7 = getPackageVersion(
|
|
41421
|
+
var VERSION7 = getPackageVersion(dirname33(fileURLToPath11(import.meta.url)));
|
|
40946
41422
|
function ask_user_default(pi) {
|
|
40947
41423
|
registerAskUserTools(pi);
|
|
40948
41424
|
const sync = (cwd) => {
|
|
@@ -40968,8 +41444,8 @@ function ask_user_default(pi) {
|
|
|
40968
41444
|
|
|
40969
41445
|
// packages/mcp/src/index.ts
|
|
40970
41446
|
init_core();
|
|
40971
|
-
import { dirname as
|
|
40972
|
-
import { fileURLToPath as
|
|
41447
|
+
import { dirname as dirname36 } from "node:path";
|
|
41448
|
+
import { fileURLToPath as fileURLToPath12 } from "node:url";
|
|
40973
41449
|
|
|
40974
41450
|
// packages/mcp/src/config/manager.ts
|
|
40975
41451
|
import * as fs26 from "node:fs";
|
|
@@ -41052,7 +41528,7 @@ function ensureDir2(dir) {
|
|
|
41052
41528
|
fs26.mkdirSync(dir, { recursive: true });
|
|
41053
41529
|
}
|
|
41054
41530
|
}
|
|
41055
|
-
function
|
|
41531
|
+
function readJsonFile2(filePath) {
|
|
41056
41532
|
try {
|
|
41057
41533
|
const content = fs26.readFileSync(filePath, "utf-8");
|
|
41058
41534
|
return JSON.parse(content);
|
|
@@ -41076,7 +41552,7 @@ function writeJsonFile(filePath, data, chmod) {
|
|
|
41076
41552
|
}
|
|
41077
41553
|
function loadMcpConfig(dir) {
|
|
41078
41554
|
const filePath = path28.join(dir, "mcp-config.json");
|
|
41079
|
-
const raw =
|
|
41555
|
+
const raw = readJsonFile2(filePath);
|
|
41080
41556
|
if (!raw) return { ...DEFAULT_MCP_CONFIG };
|
|
41081
41557
|
const validation = validateMcpConfig(raw);
|
|
41082
41558
|
if (!validation.valid) {
|
|
@@ -41089,7 +41565,7 @@ ${validation.errors.join("\n")}`
|
|
|
41089
41565
|
}
|
|
41090
41566
|
function loadMetadata(dir) {
|
|
41091
41567
|
const filePath = path28.join(dir, "config.json");
|
|
41092
|
-
const raw =
|
|
41568
|
+
const raw = readJsonFile2(filePath);
|
|
41093
41569
|
if (!raw) return { ...DEFAULT_METADATA, servers: {}, sync: { ...DEFAULT_METADATA.sync } };
|
|
41094
41570
|
return {
|
|
41095
41571
|
servers: raw.servers ?? {},
|
|
@@ -42854,7 +43330,7 @@ registerSettings({
|
|
|
42854
43330
|
});
|
|
42855
43331
|
|
|
42856
43332
|
// packages/mcp/src/index.ts
|
|
42857
|
-
var VERSION8 = getPackageVersion(
|
|
43333
|
+
var VERSION8 = getPackageVersion(dirname36(fileURLToPath12(import.meta.url)));
|
|
42858
43334
|
var registry5 = null;
|
|
42859
43335
|
function getInfoRegistry3() {
|
|
42860
43336
|
return globalThis.__unipi_info_registry;
|
|
@@ -43051,8 +43527,8 @@ Updated: ${catalog.lastUpdated}`,
|
|
|
43051
43527
|
|
|
43052
43528
|
// packages/notify/index.ts
|
|
43053
43529
|
init_core();
|
|
43054
|
-
import { dirname as
|
|
43055
|
-
import { fileURLToPath as
|
|
43530
|
+
import { dirname as dirname40 } from "node:path";
|
|
43531
|
+
import { fileURLToPath as fileURLToPath13 } from "node:url";
|
|
43056
43532
|
|
|
43057
43533
|
// packages/notify/tools.ts
|
|
43058
43534
|
init_core();
|
|
@@ -43060,7 +43536,7 @@ import { Type as Type14 } from "typebox";
|
|
|
43060
43536
|
|
|
43061
43537
|
// packages/notify/settings.ts
|
|
43062
43538
|
init_core();
|
|
43063
|
-
import { join as
|
|
43539
|
+
import { join as join67 } from "path";
|
|
43064
43540
|
import { homedir as homedir39 } from "os";
|
|
43065
43541
|
|
|
43066
43542
|
// packages/notify/activity.ts
|
|
@@ -43380,8 +43856,8 @@ init_core();
|
|
|
43380
43856
|
|
|
43381
43857
|
// packages/notify/ntfy-config.ts
|
|
43382
43858
|
init_core();
|
|
43383
|
-
import { readFileSync as
|
|
43384
|
-
import { dirname as
|
|
43859
|
+
import { readFileSync as readFileSync51, writeFileSync as writeFileSync37, mkdirSync as mkdirSync39, existsSync as existsSync49 } from "fs";
|
|
43860
|
+
import { dirname as dirname38, join as join68 } from "path";
|
|
43385
43861
|
import { homedir as homedir40 } from "os";
|
|
43386
43862
|
var DEFAULT_NTFY_CONFIG = {
|
|
43387
43863
|
enabled: false,
|
|
@@ -43389,14 +43865,14 @@ var DEFAULT_NTFY_CONFIG = {
|
|
|
43389
43865
|
priority: 3
|
|
43390
43866
|
};
|
|
43391
43867
|
function getGlobalNtfyPath() {
|
|
43392
|
-
return
|
|
43868
|
+
return join68(homedir40(), ".unipi", "config", "notify", "ntfy.json");
|
|
43393
43869
|
}
|
|
43394
43870
|
function getProjectNtfyPath(cwd) {
|
|
43395
|
-
return
|
|
43871
|
+
return join68(cwd, ".unipi", "config", "notify", "ntfy.json");
|
|
43396
43872
|
}
|
|
43397
43873
|
function readNtfyJson(filePath) {
|
|
43398
43874
|
try {
|
|
43399
|
-
const raw =
|
|
43875
|
+
const raw = readFileSync51(filePath, "utf-8");
|
|
43400
43876
|
const parsed = JSON.parse(raw);
|
|
43401
43877
|
return { ...DEFAULT_NTFY_CONFIG, ...parsed };
|
|
43402
43878
|
} catch (err) {
|
|
@@ -43446,7 +43922,7 @@ function migrateFromLegacyConfig() {
|
|
|
43446
43922
|
if (existsSync49(globalNtfyPath)) {
|
|
43447
43923
|
return;
|
|
43448
43924
|
}
|
|
43449
|
-
const legacyConfigPath =
|
|
43925
|
+
const legacyConfigPath = join68(
|
|
43450
43926
|
homedir40(),
|
|
43451
43927
|
".unipi",
|
|
43452
43928
|
"config",
|
|
@@ -43455,7 +43931,7 @@ function migrateFromLegacyConfig() {
|
|
|
43455
43931
|
);
|
|
43456
43932
|
try {
|
|
43457
43933
|
if (!existsSync49(legacyConfigPath)) return;
|
|
43458
|
-
const raw =
|
|
43934
|
+
const raw = readFileSync51(legacyConfigPath, "utf-8");
|
|
43459
43935
|
const parsed = JSON.parse(raw);
|
|
43460
43936
|
const ntfySection = parsed.ntfy;
|
|
43461
43937
|
if (!ntfySection) return;
|
|
@@ -43468,9 +43944,9 @@ function migrateFromLegacyConfig() {
|
|
|
43468
43944
|
token: ntfySection.token,
|
|
43469
43945
|
priority: ntfySection.priority ?? 3
|
|
43470
43946
|
};
|
|
43471
|
-
const dir =
|
|
43472
|
-
|
|
43473
|
-
|
|
43947
|
+
const dir = dirname38(globalNtfyPath);
|
|
43948
|
+
mkdirSync39(dir, { recursive: true });
|
|
43949
|
+
writeFileSync37(
|
|
43474
43950
|
globalNtfyPath,
|
|
43475
43951
|
JSON.stringify(migratedConfig, null, 2) + "\n",
|
|
43476
43952
|
"utf-8"
|
|
@@ -43484,8 +43960,8 @@ import notifier from "node-notifier";
|
|
|
43484
43960
|
|
|
43485
43961
|
// packages/notify/platforms/focus-win.ts
|
|
43486
43962
|
import { execFile as execFile4 } from "child_process";
|
|
43487
|
-
import { writeFileSync as
|
|
43488
|
-
import { join as
|
|
43963
|
+
import { writeFileSync as writeFileSync38, rmSync as rmSync8, mkdtempSync } from "fs";
|
|
43964
|
+
import { join as join69 } from "path";
|
|
43489
43965
|
import { tmpdir as tmpdir7 } from "os";
|
|
43490
43966
|
var POWERCHECK_SCRIPT = `
|
|
43491
43967
|
param($targetPid)
|
|
@@ -43521,9 +43997,9 @@ async function isWindowFocusedOnWindows() {
|
|
|
43521
43997
|
}
|
|
43522
43998
|
let tmpDir = null;
|
|
43523
43999
|
try {
|
|
43524
|
-
tmpDir = mkdtempSync(
|
|
43525
|
-
const scriptPath =
|
|
43526
|
-
|
|
44000
|
+
tmpDir = mkdtempSync(join69(tmpdir7(), "pi-focus-"));
|
|
44001
|
+
const scriptPath = join69(tmpDir, "check.ps1");
|
|
44002
|
+
writeFileSync38(scriptPath, POWERCHECK_SCRIPT, "utf-8");
|
|
43527
44003
|
const stdout = await new Promise((resolve18, reject) => {
|
|
43528
44004
|
execFile4(
|
|
43529
44005
|
"powershell.exe",
|
|
@@ -43551,7 +44027,7 @@ async function isWindowFocusedOnWindows() {
|
|
|
43551
44027
|
} finally {
|
|
43552
44028
|
if (tmpDir) {
|
|
43553
44029
|
try {
|
|
43554
|
-
|
|
44030
|
+
rmSync8(tmpDir, { recursive: true });
|
|
43555
44031
|
} catch {
|
|
43556
44032
|
}
|
|
43557
44033
|
}
|
|
@@ -43759,15 +44235,15 @@ async function publishToEndpoint(endpoint, title, message, priority, options) {
|
|
|
43759
44235
|
}
|
|
43760
44236
|
|
|
43761
44237
|
// packages/notify/app-endpoints.ts
|
|
43762
|
-
import { mkdirSync as
|
|
43763
|
-
import { dirname as
|
|
44238
|
+
import { mkdirSync as mkdirSync40, readFileSync as readFileSync52, renameSync as renameSync16, writeFileSync as writeFileSync39 } from "fs";
|
|
44239
|
+
import { dirname as dirname39, join as join70 } from "path";
|
|
43764
44240
|
import { homedir as homedir41 } from "os";
|
|
43765
44241
|
function path30() {
|
|
43766
|
-
return
|
|
44242
|
+
return join70(homedir41(), ".unipi", "config", "notify", "app-endpoints.json");
|
|
43767
44243
|
}
|
|
43768
44244
|
function loadAppEndpoints() {
|
|
43769
44245
|
try {
|
|
43770
|
-
const raw =
|
|
44246
|
+
const raw = readFileSync52(path30(), "utf-8");
|
|
43771
44247
|
const parsed = JSON.parse(raw);
|
|
43772
44248
|
if (!Array.isArray(parsed.endpoints)) return [];
|
|
43773
44249
|
return parsed.endpoints.filter((e) => !!e && typeof e.url === "string");
|
|
@@ -43777,17 +44253,17 @@ function loadAppEndpoints() {
|
|
|
43777
44253
|
}
|
|
43778
44254
|
|
|
43779
44255
|
// packages/notify/notify-key.ts
|
|
43780
|
-
import { readFileSync as
|
|
43781
|
-
import { join as
|
|
44256
|
+
import { readFileSync as readFileSync53 } from "fs";
|
|
44257
|
+
import { join as join71 } from "path";
|
|
43782
44258
|
import { homedir as homedir42 } from "os";
|
|
43783
44259
|
function notifyKeyPath() {
|
|
43784
44260
|
const dir = process.env.UNIPI_HOST_DIR;
|
|
43785
|
-
if (dir && dir.trim() !== "") return
|
|
43786
|
-
return
|
|
44261
|
+
if (dir && dir.trim() !== "") return join71(dir, "notify-key");
|
|
44262
|
+
return join71(homedir42(), ".unipi", "app-host", "notify-key");
|
|
43787
44263
|
}
|
|
43788
44264
|
function loadNotifyKey() {
|
|
43789
44265
|
try {
|
|
43790
|
-
const bytes =
|
|
44266
|
+
const bytes = readFileSync53(notifyKeyPath());
|
|
43791
44267
|
if (bytes.length !== 32) return void 0;
|
|
43792
44268
|
return bytes;
|
|
43793
44269
|
} catch {
|
|
@@ -45939,7 +46415,7 @@ ${results.join("\n")}`, "info");
|
|
|
45939
46415
|
}
|
|
45940
46416
|
|
|
45941
46417
|
// packages/notify/index.ts
|
|
45942
|
-
var VERSION9 = getPackageVersion(
|
|
46418
|
+
var VERSION9 = getPackageVersion(dirname40(fileURLToPath13(import.meta.url)));
|
|
45943
46419
|
var unsubTerminalInput;
|
|
45944
46420
|
function notify_default(pi) {
|
|
45945
46421
|
registerNotifyTools(pi);
|
|
@@ -45982,15 +46458,15 @@ function notify_default(pi) {
|
|
|
45982
46458
|
|
|
45983
46459
|
// packages/kanboard/index.ts
|
|
45984
46460
|
init_core();
|
|
45985
|
-
import { dirname as
|
|
45986
|
-
import { fileURLToPath as
|
|
46461
|
+
import { dirname as dirname42 } from "node:path";
|
|
46462
|
+
import { fileURLToPath as fileURLToPath15 } from "node:url";
|
|
45987
46463
|
|
|
45988
46464
|
// packages/kanboard/src/bin.ts
|
|
45989
46465
|
import { execFile as execFile5 } from "node:child_process";
|
|
45990
46466
|
import { existsSync as existsSync50 } from "node:fs";
|
|
45991
46467
|
import { createRequire as createRequire4 } from "node:module";
|
|
45992
|
-
import { dirname as
|
|
45993
|
-
import { fileURLToPath as
|
|
46468
|
+
import { dirname as dirname41, join as join72, resolve as resolve17 } from "node:path";
|
|
46469
|
+
import { fileURLToPath as fileURLToPath14 } from "node:url";
|
|
45994
46470
|
function platformKey(platform = process.platform, arch = process.arch) {
|
|
45995
46471
|
return `${platform}-${arch}`;
|
|
45996
46472
|
}
|
|
@@ -45998,7 +46474,7 @@ function exeSuffix(platform = process.platform) {
|
|
|
45998
46474
|
return platform === "win32" ? ".exe" : "";
|
|
45999
46475
|
}
|
|
46000
46476
|
function repoRoot() {
|
|
46001
|
-
return resolve17(
|
|
46477
|
+
return resolve17(dirname41(fileURLToPath14(import.meta.url)), "..", "..", "..");
|
|
46002
46478
|
}
|
|
46003
46479
|
function isRunnable(path31) {
|
|
46004
46480
|
try {
|
|
@@ -46012,7 +46488,7 @@ function platformPackagePath(from) {
|
|
|
46012
46488
|
try {
|
|
46013
46489
|
const require2 = createRequire4(from ?? import.meta.url);
|
|
46014
46490
|
const pkg = require2.resolve(`${name}/package.json`);
|
|
46015
|
-
return
|
|
46491
|
+
return join72(dirname41(pkg), "bin", `unipi-kanboard${exeSuffix()}`);
|
|
46016
46492
|
} catch {
|
|
46017
46493
|
return null;
|
|
46018
46494
|
}
|
|
@@ -46022,7 +46498,7 @@ function devBuildPath() {
|
|
|
46022
46498
|
const names = [`unipi-kanboard${exeSuffix()}`];
|
|
46023
46499
|
for (const profile of ["release", "debug"]) {
|
|
46024
46500
|
for (const name of names) {
|
|
46025
|
-
const candidate =
|
|
46501
|
+
const candidate = join72(root, "crates", "kanboard", "target", profile, name);
|
|
46026
46502
|
if (isRunnable(candidate)) return candidate;
|
|
46027
46503
|
}
|
|
46028
46504
|
}
|
|
@@ -46161,9 +46637,9 @@ function boardProgressData(tasks, slug) {
|
|
|
46161
46637
|
// packages/kanboard/src/commands.ts
|
|
46162
46638
|
init_core();
|
|
46163
46639
|
import { execFile as execFile6, spawn as spawn6 } from "node:child_process";
|
|
46164
|
-
import { existsSync as existsSync52, mkdtempSync as mkdtempSync2, readFileSync as
|
|
46640
|
+
import { existsSync as existsSync52, mkdtempSync as mkdtempSync2, readFileSync as readFileSync55, rmSync as rmSync9, writeFileSync as writeFileSync40 } from "node:fs";
|
|
46165
46641
|
import { homedir as homedir43, hostname as osHostname, networkInterfaces, tmpdir as tmpdir8 } from "node:os";
|
|
46166
|
-
import { join as
|
|
46642
|
+
import { join as join73 } from "node:path";
|
|
46167
46643
|
import { promisify } from "node:util";
|
|
46168
46644
|
import { truncateToWidth as truncateToWidth28, visibleWidth as visibleWidth27 } from "@earendil-works/pi-tui";
|
|
46169
46645
|
|
|
@@ -46246,7 +46722,7 @@ function asStopResult(value) {
|
|
|
46246
46722
|
|
|
46247
46723
|
// packages/kanboard/src/settings.ts
|
|
46248
46724
|
init_core();
|
|
46249
|
-
import { existsSync as existsSync51, readFileSync as
|
|
46725
|
+
import { existsSync as existsSync51, readFileSync as readFileSync54 } from "node:fs";
|
|
46250
46726
|
var DEFAULT_SETTINGS6 = {
|
|
46251
46727
|
chainGate: "in_review",
|
|
46252
46728
|
idleMin: 10,
|
|
@@ -46364,7 +46840,7 @@ function storedDoWritesSet(cwd) {
|
|
|
46364
46840
|
for (const file of [projectSettingsPath(cwd, KANBOARD_NAMESPACE), globalSettingsPath(KANBOARD_NAMESPACE)]) {
|
|
46365
46841
|
try {
|
|
46366
46842
|
if (!existsSync51(file)) continue;
|
|
46367
|
-
const parsed = JSON.parse(
|
|
46843
|
+
const parsed = JSON.parse(readFileSync54(file, "utf-8"));
|
|
46368
46844
|
if (typeof parsed.doWrites === "number") return true;
|
|
46369
46845
|
} catch {
|
|
46370
46846
|
}
|
|
@@ -46375,7 +46851,7 @@ function storedLegacyDoCredits(cwd) {
|
|
|
46375
46851
|
for (const file of [projectSettingsPath(cwd, KANBOARD_NAMESPACE), globalSettingsPath(KANBOARD_NAMESPACE)]) {
|
|
46376
46852
|
try {
|
|
46377
46853
|
if (!existsSync51(file)) continue;
|
|
46378
|
-
const parsed = JSON.parse(
|
|
46854
|
+
const parsed = JSON.parse(readFileSync54(file, "utf-8"));
|
|
46379
46855
|
const value = parsed.doCredits;
|
|
46380
46856
|
if (typeof value === "number" && value >= 0) return value;
|
|
46381
46857
|
} catch {
|
|
@@ -46504,7 +46980,7 @@ function detectFilePaths(text) {
|
|
|
46504
46980
|
const wrapped = token.match(/^!?\[[^\]]*\]\((.+)\)[.,;:]?$/) ?? token.match(/^\((.+)\)[.,;:]?$/);
|
|
46505
46981
|
if (wrapped) token = wrapped[1];
|
|
46506
46982
|
token = token.replace(/[.,;:]+$/, "");
|
|
46507
|
-
const expanded = token.startsWith("~/") ?
|
|
46983
|
+
const expanded = token.startsWith("~/") ? join73(homedir43(), token.slice(2)) : token;
|
|
46508
46984
|
if (!(token.startsWith("/") || token.startsWith("~/"))) continue;
|
|
46509
46985
|
if (!existsSync52(expanded)) continue;
|
|
46510
46986
|
if (!found.includes(expanded)) found.push(expanded);
|
|
@@ -46591,11 +47067,11 @@ function formatBoardUrls(options) {
|
|
|
46591
47067
|
};
|
|
46592
47068
|
}
|
|
46593
47069
|
function kanboardHome() {
|
|
46594
|
-
return process.env.UNIPI_KANBOARD_HOME?.trim() ||
|
|
47070
|
+
return process.env.UNIPI_KANBOARD_HOME?.trim() || join73(homedir43(), ".unipi", "kanboard");
|
|
46595
47071
|
}
|
|
46596
47072
|
function readDaemonInfo() {
|
|
46597
47073
|
try {
|
|
46598
|
-
const raw =
|
|
47074
|
+
const raw = readFileSync55(join73(kanboardHome(), "daemon.json"), "utf-8");
|
|
46599
47075
|
const parsed = JSON.parse(raw);
|
|
46600
47076
|
return typeof parsed?.port === "number" ? parsed : null;
|
|
46601
47077
|
} catch {
|
|
@@ -46805,8 +47281,8 @@ async function runAdd(deps, ctx, text) {
|
|
|
46805
47281
|
try {
|
|
46806
47282
|
const argv = ["add", ...parsed.title ? [parsed.title] : [], ...parsed.flags];
|
|
46807
47283
|
if (parsed.description) {
|
|
46808
|
-
bodyFile =
|
|
46809
|
-
|
|
47284
|
+
bodyFile = join73(mkdtempSync2(join73(tmpdir8(), "kb-add-")), "body.md");
|
|
47285
|
+
writeFileSync40(bodyFile, parsed.description);
|
|
46810
47286
|
argv.push("--body-file", bodyFile);
|
|
46811
47287
|
}
|
|
46812
47288
|
for (const file of parsed.attaches) argv.push("--attach", file);
|
|
@@ -46821,7 +47297,7 @@ async function runAdd(deps, ctx, text) {
|
|
|
46821
47297
|
"error"
|
|
46822
47298
|
);
|
|
46823
47299
|
} finally {
|
|
46824
|
-
if (bodyFile)
|
|
47300
|
+
if (bodyFile) rmSync9(join73(bodyFile, ".."), { recursive: true, force: true });
|
|
46825
47301
|
}
|
|
46826
47302
|
}
|
|
46827
47303
|
async function captureToBacklog(deps, opts) {
|
|
@@ -46842,8 +47318,8 @@ async function captureToBacklog(deps, opts) {
|
|
|
46842
47318
|
const attaches = detectFilePaths(text);
|
|
46843
47319
|
let bodyFile = null;
|
|
46844
47320
|
try {
|
|
46845
|
-
bodyFile =
|
|
46846
|
-
|
|
47321
|
+
bodyFile = join73(mkdtempSync2(join73(tmpdir8(), "kb-capture-")), "body.md");
|
|
47322
|
+
writeFileSync40(bodyFile, text);
|
|
46847
47323
|
const argv = ["--project", slug, "add", "--status", "backlog", "--body-file", bodyFile];
|
|
46848
47324
|
for (const file of attaches) argv.push("--attach", file);
|
|
46849
47325
|
const task = asTask("add", await client.run(argv, { cwd: opts.cwd }));
|
|
@@ -46855,7 +47331,7 @@ async function captureToBacklog(deps, opts) {
|
|
|
46855
47331
|
reason: error instanceof KanboardCliError ? error.message : String(error)
|
|
46856
47332
|
};
|
|
46857
47333
|
} finally {
|
|
46858
|
-
if (bodyFile)
|
|
47334
|
+
if (bodyFile) rmSync9(join73(bodyFile, ".."), { recursive: true, force: true });
|
|
46859
47335
|
}
|
|
46860
47336
|
}
|
|
46861
47337
|
async function runStatus(deps, ctx) {
|
|
@@ -46927,8 +47403,8 @@ async function runDoctor(deps, ctx, pi) {
|
|
|
46927
47403
|
}
|
|
46928
47404
|
}
|
|
46929
47405
|
try {
|
|
46930
|
-
const settingsPath =
|
|
46931
|
-
const raw = JSON.parse(
|
|
47406
|
+
const settingsPath = join73(kanboardHome(), "settings.json");
|
|
47407
|
+
const raw = JSON.parse(readFileSync55(settingsPath, "utf-8"));
|
|
46932
47408
|
const argv = Array.isArray(raw.piCommand) ? raw.piCommand : [];
|
|
46933
47409
|
if (argv.length === 0) {
|
|
46934
47410
|
lines4.push(check(null, "summarize via pi: not configured (open the board from pi once)"));
|
|
@@ -47697,20 +48173,20 @@ function createWriteGuard(options = {}) {
|
|
|
47697
48173
|
|
|
47698
48174
|
// packages/kanboard/src/move.ts
|
|
47699
48175
|
init_core();
|
|
47700
|
-
import { existsSync as existsSync53, readdirSync as
|
|
48176
|
+
import { existsSync as existsSync53, readdirSync as readdirSync19, readFileSync as readFileSync56 } from "node:fs";
|
|
47701
48177
|
import { homedir as homedir44 } from "node:os";
|
|
47702
|
-
import { join as
|
|
48178
|
+
import { join as join74 } from "node:path";
|
|
47703
48179
|
function kanboardHome2(env = process.env) {
|
|
47704
|
-
return env.UNIPI_KANBOARD_HOME?.trim() ||
|
|
48180
|
+
return env.UNIPI_KANBOARD_HOME?.trim() || join74(homedir44(), ".unipi", "kanboard");
|
|
47705
48181
|
}
|
|
47706
48182
|
function projects() {
|
|
47707
|
-
const root =
|
|
48183
|
+
const root = join74(kanboardHome2(), "projects");
|
|
47708
48184
|
if (!existsSync53(root)) return [];
|
|
47709
48185
|
const result2 = [];
|
|
47710
|
-
for (const entry of
|
|
48186
|
+
for (const entry of readdirSync19(root, { withFileTypes: true })) {
|
|
47711
48187
|
if (!entry.isDirectory()) continue;
|
|
47712
48188
|
try {
|
|
47713
|
-
const parsed = JSON.parse(
|
|
48189
|
+
const parsed = JSON.parse(readFileSync56(join74(root, entry.name, "project.json"), "utf8"));
|
|
47714
48190
|
if (typeof parsed.slug === "string" && typeof parsed.root === "string") result2.push(parsed);
|
|
47715
48191
|
} catch {
|
|
47716
48192
|
}
|
|
@@ -47739,7 +48215,7 @@ var kanboardMoveHandler = {
|
|
|
47739
48215
|
async apply() {
|
|
47740
48216
|
if (ctx.dryRun) return;
|
|
47741
48217
|
if (!binary) throw new Error("kanboard binary unavailable \u2014 update kanboard binary or build the dev binary");
|
|
47742
|
-
ctx.backup(
|
|
48218
|
+
ctx.backup(join74(kanboardHome2(), "projects", match.slug, "project.json"));
|
|
47743
48219
|
const client = createCli(binary, { ...process.env, UNIPI_KANBOARD_HOME: kanboardHome2(), UNIPI_KANBOARD_ACTOR: "user" });
|
|
47744
48220
|
try {
|
|
47745
48221
|
await client.run(["project", "rebind", match.slug, "--root", ctx.newRoot], { cwd: ctx.newRoot });
|
|
@@ -48262,10 +48738,10 @@ function createDebugLog(env = process.env) {
|
|
|
48262
48738
|
if (env.UNIPI_DEBUG_KANBOARD !== "1") return () => void 0;
|
|
48263
48739
|
return (line) => {
|
|
48264
48740
|
try {
|
|
48265
|
-
const { appendFileSync: appendFileSync7, mkdirSync:
|
|
48741
|
+
const { appendFileSync: appendFileSync7, mkdirSync: mkdirSync49 } = __require("node:fs");
|
|
48266
48742
|
const { homedir: homedir58 } = __require("node:os");
|
|
48267
48743
|
const dir = `${homedir58()}/.unipi/logs`;
|
|
48268
|
-
|
|
48744
|
+
mkdirSync49(dir, { recursive: true });
|
|
48269
48745
|
appendFileSync7(`${dir}/kanboard.log`, `${(/* @__PURE__ */ new Date()).toISOString()} ${line}
|
|
48270
48746
|
`);
|
|
48271
48747
|
} catch {
|
|
@@ -48274,7 +48750,7 @@ function createDebugLog(env = process.env) {
|
|
|
48274
48750
|
}
|
|
48275
48751
|
|
|
48276
48752
|
// packages/kanboard/index.ts
|
|
48277
|
-
var VERSION10 = getPackageVersion(
|
|
48753
|
+
var VERSION10 = getPackageVersion(dirname42(fileURLToPath15(import.meta.url)));
|
|
48278
48754
|
var KANBOARD_SKILL = "kanboard";
|
|
48279
48755
|
var lastCliPrefix = null;
|
|
48280
48756
|
function kanboard_default(pi) {
|
|
@@ -50901,7 +51377,7 @@ function buildCardData(opts) {
|
|
|
50901
51377
|
}
|
|
50902
51378
|
var dbg = (debug, data) => {
|
|
50903
51379
|
if (!debug) return;
|
|
50904
|
-
import("node:fs").then(({ writeFileSync:
|
|
51380
|
+
import("node:fs").then(({ writeFileSync: writeFileSync49 }) => writeFileSync49("/tmp/compactor-debug.json", JSON.stringify(data, null, 2))).catch(() => {
|
|
50905
51381
|
});
|
|
50906
51382
|
};
|
|
50907
51383
|
var readReason = (event) => {
|
|
@@ -52012,13 +52488,13 @@ function vccRecall(blocks, input) {
|
|
|
52012
52488
|
}
|
|
52013
52489
|
|
|
52014
52490
|
// packages/compactor/src/tools/ctx-doctor.ts
|
|
52015
|
-
import { existsSync as existsSync54, readFileSync as
|
|
52491
|
+
import { existsSync as existsSync54, readFileSync as readFileSync57, readdirSync as readdirSync20, statSync as statSync19 } from "node:fs";
|
|
52016
52492
|
import { homedir as homedir46 } from "node:os";
|
|
52017
|
-
import { join as
|
|
52018
|
-
var LEGACY_DB_DIR =
|
|
52493
|
+
import { join as join76 } from "node:path";
|
|
52494
|
+
var LEGACY_DB_DIR = join76(homedir46(), ".unipi", "db", "compactor");
|
|
52019
52495
|
function piCompactionEnabled() {
|
|
52020
52496
|
try {
|
|
52021
|
-
const raw = JSON.parse(
|
|
52497
|
+
const raw = JSON.parse(readFileSync57(join76(homedir46(), ".pi", "agent", "settings.json"), "utf-8"));
|
|
52022
52498
|
const enabled = raw?.compaction?.enabled;
|
|
52023
52499
|
return typeof enabled === "boolean" ? enabled : true;
|
|
52024
52500
|
} catch {
|
|
@@ -52027,7 +52503,7 @@ function piCompactionEnabled() {
|
|
|
52027
52503
|
}
|
|
52028
52504
|
function dirSizeMb(dir) {
|
|
52029
52505
|
try {
|
|
52030
|
-
return
|
|
52506
|
+
return readdirSync20(dir).reduce((sum, name) => sum + statSync19(join76(dir, name)).size, 0) / (1024 * 1024);
|
|
52031
52507
|
} catch {
|
|
52032
52508
|
return 0;
|
|
52033
52509
|
}
|
|
@@ -52339,8 +52815,8 @@ function compactorExtension(pi) {
|
|
|
52339
52815
|
|
|
52340
52816
|
// packages/footer/src/index.ts
|
|
52341
52817
|
init_core();
|
|
52342
|
-
import { dirname as
|
|
52343
|
-
import { fileURLToPath as
|
|
52818
|
+
import { dirname as dirname43 } from "node:path";
|
|
52819
|
+
import { fileURLToPath as fileURLToPath16 } from "node:url";
|
|
52344
52820
|
|
|
52345
52821
|
// packages/footer/src/registry/index.ts
|
|
52346
52822
|
var FooterRegistry = class {
|
|
@@ -52403,7 +52879,7 @@ function getFooterRegistry() {
|
|
|
52403
52879
|
|
|
52404
52880
|
// packages/footer/src/config.ts
|
|
52405
52881
|
init_core();
|
|
52406
|
-
import { statSync as
|
|
52882
|
+
import { statSync as statSync20 } from "node:fs";
|
|
52407
52883
|
|
|
52408
52884
|
// packages/footer/src/rendering/icons.ts
|
|
52409
52885
|
function detectNerdFontSupport() {
|
|
@@ -52744,7 +53220,7 @@ function configFileStamp(cwd) {
|
|
|
52744
53220
|
let stamp = "";
|
|
52745
53221
|
for (const file of [globalSettingsPath("footer"), projectSettingsPath(cwd, "footer")]) {
|
|
52746
53222
|
try {
|
|
52747
|
-
stamp += `${
|
|
53223
|
+
stamp += `${statSync20(file).mtimeMs};`;
|
|
52748
53224
|
} catch {
|
|
52749
53225
|
stamp += "-1;";
|
|
52750
53226
|
}
|
|
@@ -53986,7 +54462,7 @@ function trayHasItems() {
|
|
|
53986
54462
|
}
|
|
53987
54463
|
publishSharedTps();
|
|
53988
54464
|
var VERSION11 = getPackageVersion(
|
|
53989
|
-
findPackageRoot(
|
|
54465
|
+
findPackageRoot(dirname43(fileURLToPath16(import.meta.url)), "@pi-unipi/footer") ?? dirname43(fileURLToPath16(import.meta.url))
|
|
53990
54466
|
);
|
|
53991
54467
|
function footerExtension(pi) {
|
|
53992
54468
|
const state2 = {
|
|
@@ -54357,21 +54833,21 @@ function wireTpsStreamingEvents(pi) {
|
|
|
54357
54833
|
|
|
54358
54834
|
// packages/updater/src/index.ts
|
|
54359
54835
|
init_core();
|
|
54360
|
-
import { fileURLToPath as
|
|
54836
|
+
import { fileURLToPath as fileURLToPath22 } from "node:url";
|
|
54361
54837
|
|
|
54362
54838
|
// packages/updater/src/commands.ts
|
|
54363
54839
|
init_core();
|
|
54364
54840
|
|
|
54365
54841
|
// packages/updater/src/tui/readme-overlay.ts
|
|
54366
|
-
import { readFileSync as
|
|
54842
|
+
import { readFileSync as readFileSync59 } from "fs";
|
|
54367
54843
|
|
|
54368
54844
|
// packages/updater/src/readme.ts
|
|
54369
54845
|
init_core();
|
|
54370
54846
|
init_core();
|
|
54371
|
-
import { dirname as
|
|
54372
|
-
import { fileURLToPath as
|
|
54373
|
-
import { existsSync as existsSync55, readFileSync as
|
|
54374
|
-
import { join as
|
|
54847
|
+
import { dirname as dirname44 } from "node:path";
|
|
54848
|
+
import { fileURLToPath as fileURLToPath17 } from "node:url";
|
|
54849
|
+
import { existsSync as existsSync55, readFileSync as readFileSync58 } from "fs";
|
|
54850
|
+
import { join as join77 } from "path";
|
|
54375
54851
|
var PACKAGE_MAP = {
|
|
54376
54852
|
core: MODULES.CORE,
|
|
54377
54853
|
workflow: MODULES.WORKFLOW,
|
|
@@ -54394,15 +54870,15 @@ var PACKAGE_MAP = {
|
|
|
54394
54870
|
updater: MODULES.UPDATER
|
|
54395
54871
|
};
|
|
54396
54872
|
function resolveUnipiRoot() {
|
|
54397
|
-
const dir =
|
|
54873
|
+
const dir = dirname44(fileURLToPath17(import.meta.url));
|
|
54398
54874
|
const root = findPackageRoot(dir, "@pi-unipi/unipi");
|
|
54399
|
-
return root ??
|
|
54875
|
+
return root ?? join77(dir, "..");
|
|
54400
54876
|
}
|
|
54401
54877
|
function getPackageVersion2(dir) {
|
|
54402
54878
|
try {
|
|
54403
|
-
const pkgPath =
|
|
54879
|
+
const pkgPath = join77(dir, "package.json");
|
|
54404
54880
|
if (existsSync55(pkgPath)) {
|
|
54405
|
-
const raw =
|
|
54881
|
+
const raw = readFileSync58(pkgPath, "utf-8");
|
|
54406
54882
|
const pkg = JSON.parse(raw);
|
|
54407
54883
|
return pkg.version ?? "0.0.0";
|
|
54408
54884
|
}
|
|
@@ -54413,7 +54889,7 @@ function getPackageVersion2(dir) {
|
|
|
54413
54889
|
function discoverReadmes() {
|
|
54414
54890
|
const root = resolveUnipiRoot();
|
|
54415
54891
|
const entries2 = [];
|
|
54416
|
-
const rootReadme =
|
|
54892
|
+
const rootReadme = join77(root, "README.md");
|
|
54417
54893
|
if (existsSync55(rootReadme)) {
|
|
54418
54894
|
entries2.push({
|
|
54419
54895
|
name: "unipi",
|
|
@@ -54423,16 +54899,16 @@ function discoverReadmes() {
|
|
|
54423
54899
|
});
|
|
54424
54900
|
}
|
|
54425
54901
|
for (const [shortName2, fullName] of Object.entries(PACKAGE_MAP)) {
|
|
54426
|
-
const workspacePath =
|
|
54427
|
-
const nodeModulesPath =
|
|
54902
|
+
const workspacePath = join77(root, "packages", shortName2, "README.md");
|
|
54903
|
+
const nodeModulesPath = join77(root, "node_modules", fullName, "README.md");
|
|
54428
54904
|
let readmePath = null;
|
|
54429
54905
|
let versionDir = null;
|
|
54430
54906
|
if (existsSync55(workspacePath)) {
|
|
54431
54907
|
readmePath = workspacePath;
|
|
54432
|
-
versionDir =
|
|
54908
|
+
versionDir = join77(root, "packages", shortName2);
|
|
54433
54909
|
} else if (existsSync55(nodeModulesPath)) {
|
|
54434
54910
|
readmePath = nodeModulesPath;
|
|
54435
|
-
versionDir =
|
|
54911
|
+
versionDir = join77(root, "node_modules", fullName);
|
|
54436
54912
|
}
|
|
54437
54913
|
if (readmePath && versionDir) {
|
|
54438
54914
|
entries2.push({
|
|
@@ -54448,14 +54924,14 @@ function discoverReadmes() {
|
|
|
54448
54924
|
function resolveReadmePath(packageName) {
|
|
54449
54925
|
const root = resolveUnipiRoot();
|
|
54450
54926
|
if (!packageName || packageName === "unipi") {
|
|
54451
|
-
const rootReadme =
|
|
54927
|
+
const rootReadme = join77(root, "README.md");
|
|
54452
54928
|
return existsSync55(rootReadme) ? rootReadme : null;
|
|
54453
54929
|
}
|
|
54454
54930
|
const fullName = PACKAGE_MAP[packageName];
|
|
54455
54931
|
if (!fullName) return null;
|
|
54456
|
-
const workspacePath =
|
|
54932
|
+
const workspacePath = join77(root, "packages", packageName, "README.md");
|
|
54457
54933
|
if (existsSync55(workspacePath)) return workspacePath;
|
|
54458
|
-
const nodeModulesPath =
|
|
54934
|
+
const nodeModulesPath = join77(root, "node_modules", fullName, "README.md");
|
|
54459
54935
|
if (existsSync55(nodeModulesPath)) return nodeModulesPath;
|
|
54460
54936
|
return null;
|
|
54461
54937
|
}
|
|
@@ -54651,7 +55127,7 @@ function renderReadmeOverlay(params) {
|
|
|
54651
55127
|
const idx = entries2.findIndex((e) => e.path === readmePath);
|
|
54652
55128
|
if (idx >= 0) {
|
|
54653
55129
|
openDirectIndex = idx;
|
|
54654
|
-
const content =
|
|
55130
|
+
const content = readFileSync59(readmePath, "utf-8");
|
|
54655
55131
|
const lines4 = renderMarkdown(content, (process.stdout.columns ?? 80) - 4, void 0);
|
|
54656
55132
|
contentCache.set(readmePath, lines4);
|
|
54657
55133
|
}
|
|
@@ -54673,7 +55149,7 @@ function renderReadmeOverlay(params) {
|
|
|
54673
55149
|
return contentCache.get(entry.path);
|
|
54674
55150
|
}
|
|
54675
55151
|
try {
|
|
54676
|
-
const content =
|
|
55152
|
+
const content = readFileSync59(entry.path, "utf-8");
|
|
54677
55153
|
const lines4 = renderMarkdown(content, (process.stdout.columns ?? 80) - 4, theme);
|
|
54678
55154
|
contentCache.set(entry.path, lines4);
|
|
54679
55155
|
return lines4;
|
|
@@ -54686,13 +55162,13 @@ function renderReadmeOverlay(params) {
|
|
|
54686
55162
|
|
|
54687
55163
|
// packages/updater/src/tui/changelog-overlay.ts
|
|
54688
55164
|
import { existsSync as existsSync57 } from "fs";
|
|
54689
|
-
import { fileURLToPath as
|
|
55165
|
+
import { fileURLToPath as fileURLToPath19 } from "node:url";
|
|
54690
55166
|
|
|
54691
55167
|
// packages/updater/src/changelog.ts
|
|
54692
55168
|
init_core();
|
|
54693
|
-
import { existsSync as existsSync56, readFileSync as
|
|
54694
|
-
import { dirname as
|
|
54695
|
-
import { fileURLToPath as
|
|
55169
|
+
import { existsSync as existsSync56, readFileSync as readFileSync60 } from "fs";
|
|
55170
|
+
import { dirname as dirname45, join as join78 } from "node:path";
|
|
55171
|
+
import { fileURLToPath as fileURLToPath18 } from "node:url";
|
|
54696
55172
|
|
|
54697
55173
|
// packages/updater/src/version.ts
|
|
54698
55174
|
init_core();
|
|
@@ -54700,21 +55176,21 @@ init_core();
|
|
|
54700
55176
|
// packages/updater/src/changelog.ts
|
|
54701
55177
|
function resolveChangelogPath() {
|
|
54702
55178
|
try {
|
|
54703
|
-
const dir =
|
|
55179
|
+
const dir = dirname45(fileURLToPath18(import.meta.url));
|
|
54704
55180
|
const root = findPackageRoot(dir, "@pi-unipi/unipi");
|
|
54705
55181
|
if (root) {
|
|
54706
|
-
const packaged =
|
|
55182
|
+
const packaged = join78(root, "CHANGELOG.md");
|
|
54707
55183
|
if (existsSync56(packaged)) return packaged;
|
|
54708
55184
|
}
|
|
54709
55185
|
} catch {
|
|
54710
55186
|
}
|
|
54711
|
-
return
|
|
55187
|
+
return join78(process.cwd(), "CHANGELOG.md");
|
|
54712
55188
|
}
|
|
54713
55189
|
var VERSION_HEADER_RE = /^## \[(.+?)\](?:\s*[-—–]\s*(.+))?$/;
|
|
54714
55190
|
var SECTION_HEADER_RE = /^### (.+)$/;
|
|
54715
55191
|
function parseChangelog(filePath) {
|
|
54716
55192
|
if (!existsSync56(filePath)) return [];
|
|
54717
|
-
return parseChangelogContent(
|
|
55193
|
+
return parseChangelogContent(readFileSync60(filePath, "utf-8"));
|
|
54718
55194
|
}
|
|
54719
55195
|
function parseChangelogContent(content) {
|
|
54720
55196
|
const trimmed = content.trim();
|
|
@@ -54802,7 +55278,7 @@ function getNewerVersions(entries2, installedVersion) {
|
|
|
54802
55278
|
init_core();
|
|
54803
55279
|
function renderChangelogOverlay() {
|
|
54804
55280
|
const installedVersion = getInstalledPackageVersion(
|
|
54805
|
-
|
|
55281
|
+
fileURLToPath19(new URL("..", import.meta.url)),
|
|
54806
55282
|
"@pi-unipi/unipi"
|
|
54807
55283
|
);
|
|
54808
55284
|
return createListDetailOverlay({
|
|
@@ -54882,7 +55358,7 @@ function registerCommands3(pi) {
|
|
|
54882
55358
|
|
|
54883
55359
|
// packages/updater/src/settings.ts
|
|
54884
55360
|
init_core();
|
|
54885
|
-
import { join as
|
|
55361
|
+
import { join as join79 } from "path";
|
|
54886
55362
|
import { homedir as homedir47 } from "os";
|
|
54887
55363
|
var DEFAULT_CONFIG7 = {
|
|
54888
55364
|
checkIntervalMs: 36e5,
|
|
@@ -54942,23 +55418,23 @@ function mergeWithDefaults2(loaded) {
|
|
|
54942
55418
|
|
|
54943
55419
|
// packages/updater/src/checker.ts
|
|
54944
55420
|
init_core();
|
|
54945
|
-
import { dirname as
|
|
54946
|
-
import { fileURLToPath as
|
|
55421
|
+
import { dirname as dirname48 } from "node:path";
|
|
55422
|
+
import { fileURLToPath as fileURLToPath20 } from "node:url";
|
|
54947
55423
|
|
|
54948
55424
|
// packages/updater/src/cache.ts
|
|
54949
55425
|
init_core();
|
|
54950
|
-
import { readFileSync as
|
|
54951
|
-
import { dirname as
|
|
55426
|
+
import { readFileSync as readFileSync61, writeFileSync as writeFileSync41, mkdirSync as mkdirSync41, existsSync as existsSync58 } from "fs";
|
|
55427
|
+
import { dirname as dirname47, join as join80 } from "path";
|
|
54952
55428
|
import { homedir as homedir48 } from "os";
|
|
54953
55429
|
function resolveCachePath() {
|
|
54954
55430
|
const base = UPDATER_DIRS.CACHE.replace("~", homedir48());
|
|
54955
|
-
return
|
|
55431
|
+
return join80(base, "last-check.json");
|
|
54956
55432
|
}
|
|
54957
55433
|
function readLastCheck() {
|
|
54958
55434
|
const cachePath = resolveCachePath();
|
|
54959
55435
|
try {
|
|
54960
55436
|
if (existsSync58(cachePath)) {
|
|
54961
|
-
const raw =
|
|
55437
|
+
const raw = readFileSync61(cachePath, "utf-8");
|
|
54962
55438
|
const parsed = JSON.parse(raw);
|
|
54963
55439
|
if (parsed.lastCheck && parsed.latestVersion) {
|
|
54964
55440
|
return parsed;
|
|
@@ -54970,9 +55446,9 @@ function readLastCheck() {
|
|
|
54970
55446
|
}
|
|
54971
55447
|
function writeLastCheck(cache6) {
|
|
54972
55448
|
const cachePath = resolveCachePath();
|
|
54973
|
-
const dir =
|
|
54974
|
-
|
|
54975
|
-
|
|
55449
|
+
const dir = dirname47(cachePath);
|
|
55450
|
+
mkdirSync41(dir, { recursive: true });
|
|
55451
|
+
writeFileSync41(cachePath, JSON.stringify(cache6, null, 2) + "\n", "utf-8");
|
|
54976
55452
|
}
|
|
54977
55453
|
function isCheckDue(intervalMs) {
|
|
54978
55454
|
const cache6 = readLastCheck();
|
|
@@ -54994,9 +55470,9 @@ function isVersionSkipped(version) {
|
|
|
54994
55470
|
|
|
54995
55471
|
// packages/updater/src/channel.ts
|
|
54996
55472
|
init_core();
|
|
54997
|
-
import { existsSync as existsSync59, readFileSync as
|
|
55473
|
+
import { existsSync as existsSync59, readFileSync as readFileSync62 } from "node:fs";
|
|
54998
55474
|
import { homedir as homedir49 } from "node:os";
|
|
54999
|
-
import { join as
|
|
55475
|
+
import { join as join81 } from "node:path";
|
|
55000
55476
|
var UNIPI_PACKAGE = "@pi-unipi/unipi";
|
|
55001
55477
|
function prereleaseChannel(version) {
|
|
55002
55478
|
const m = /^v?\d+\.\d+\.\d+-([0-9A-Za-z-]+)/.exec(version.trim());
|
|
@@ -55014,15 +55490,15 @@ function channelFromSpec(spec) {
|
|
|
55014
55490
|
}
|
|
55015
55491
|
function piAgentDir(env = process.env) {
|
|
55016
55492
|
const dir = env.PI_CODING_AGENT_DIR;
|
|
55017
|
-
if (dir) return dir.startsWith("~") ?
|
|
55018
|
-
return
|
|
55493
|
+
if (dir) return dir.startsWith("~") ? join81(homedir49(), dir.slice(1)) : dir;
|
|
55494
|
+
return join81(homedir49(), ".pi", "agent");
|
|
55019
55495
|
}
|
|
55020
55496
|
function readUnipiPackageSpec(cwd = process.cwd(), env = process.env) {
|
|
55021
|
-
const files = [
|
|
55497
|
+
const files = [join81(cwd, ".pi", "settings.json"), join81(piAgentDir(env), "settings.json")];
|
|
55022
55498
|
for (const file of files) {
|
|
55023
55499
|
try {
|
|
55024
55500
|
if (!existsSync59(file)) continue;
|
|
55025
|
-
const settings = JSON.parse(
|
|
55501
|
+
const settings = JSON.parse(readFileSync62(file, "utf8"));
|
|
55026
55502
|
for (const pkg of settings.packages ?? []) {
|
|
55027
55503
|
const source = typeof pkg === "string" ? pkg : pkg?.source;
|
|
55028
55504
|
if (typeof source !== "string") continue;
|
|
@@ -55059,7 +55535,7 @@ function registryUrl(env = process.env) {
|
|
|
55059
55535
|
return `${base}/-/package/${UNIPI_PACKAGE}/dist-tags`;
|
|
55060
55536
|
}
|
|
55061
55537
|
function getInstalledVersion() {
|
|
55062
|
-
const dir =
|
|
55538
|
+
const dir = dirname48(dirname48(fileURLToPath20(import.meta.url)));
|
|
55063
55539
|
return getInstalledPackageVersion(dir, UNIPI_PACKAGE);
|
|
55064
55540
|
}
|
|
55065
55541
|
function currentChannel(currentVersion = getInstalledVersion()) {
|
|
@@ -55129,12 +55605,12 @@ import { Key as Key22, matchesKey as matchesKey24, truncateToWidth as truncateTo
|
|
|
55129
55605
|
init_core();
|
|
55130
55606
|
import { exec } from "child_process";
|
|
55131
55607
|
import { promisify as promisify2 } from "util";
|
|
55132
|
-
import { dirname as
|
|
55133
|
-
import { fileURLToPath as
|
|
55608
|
+
import { dirname as dirname49 } from "node:path";
|
|
55609
|
+
import { fileURLToPath as fileURLToPath21 } from "node:url";
|
|
55134
55610
|
var execAsync = promisify2(exec);
|
|
55135
55611
|
var INSTALL_TIMEOUT_MS = 6e4;
|
|
55136
55612
|
async function installUpdate(channel = "latest") {
|
|
55137
|
-
const thisDir =
|
|
55613
|
+
const thisDir = dirname49(dirname49(fileURLToPath21(import.meta.url)));
|
|
55138
55614
|
try {
|
|
55139
55615
|
await execAsync(
|
|
55140
55616
|
`pi install ${installSpec(channel)}`,
|
|
@@ -55331,9 +55807,9 @@ function renderUpdateOverlay(checkResult, providedNewerVersions) {
|
|
|
55331
55807
|
|
|
55332
55808
|
// packages/updater/src/remote-changelog.ts
|
|
55333
55809
|
init_core();
|
|
55334
|
-
import { existsSync as existsSync60, mkdirSync as
|
|
55810
|
+
import { existsSync as existsSync60, mkdirSync as mkdirSync42, readFileSync as readFileSync63, writeFileSync as writeFileSync42 } from "node:fs";
|
|
55335
55811
|
import { homedir as homedir50 } from "node:os";
|
|
55336
|
-
import { join as
|
|
55812
|
+
import { join as join82 } from "node:path";
|
|
55337
55813
|
var CHANGELOG_RAW_BASE = "https://raw.githubusercontent.com/Neuron-Mr-White/unipi";
|
|
55338
55814
|
function cacheDirectory(opts) {
|
|
55339
55815
|
return (opts?.cacheDir ?? UPDATER_DIRS.CACHE).replace("~", homedir50());
|
|
@@ -55344,9 +55820,9 @@ function fallbackRefs(version) {
|
|
|
55344
55820
|
}
|
|
55345
55821
|
async function fetchRemoteChangelog(version, opts = {}) {
|
|
55346
55822
|
const cacheDir3 = cacheDirectory(opts);
|
|
55347
|
-
const cachePath =
|
|
55823
|
+
const cachePath = join82(cacheDir3, `changelog-${version}.md`);
|
|
55348
55824
|
try {
|
|
55349
|
-
if (existsSync60(cachePath)) return
|
|
55825
|
+
if (existsSync60(cachePath)) return readFileSync63(cachePath, "utf8");
|
|
55350
55826
|
} catch {
|
|
55351
55827
|
}
|
|
55352
55828
|
const fetchImpl = opts.fetchImpl ?? fetch;
|
|
@@ -55361,8 +55837,8 @@ async function fetchRemoteChangelog(version, opts = {}) {
|
|
|
55361
55837
|
if (!response.ok) return null;
|
|
55362
55838
|
const content = await response.text();
|
|
55363
55839
|
if (cacheable) {
|
|
55364
|
-
|
|
55365
|
-
|
|
55840
|
+
mkdirSync42(cacheDir3, { recursive: true });
|
|
55841
|
+
writeFileSync42(cachePath, content, "utf8");
|
|
55366
55842
|
}
|
|
55367
55843
|
return content;
|
|
55368
55844
|
} catch {
|
|
@@ -55379,7 +55855,7 @@ async function loadUpdateChangelog(currentVersion, latestVersion, opts) {
|
|
|
55379
55855
|
}
|
|
55380
55856
|
|
|
55381
55857
|
// packages/updater/src/index.ts
|
|
55382
|
-
var VERSION12 = getPackageVersion(
|
|
55858
|
+
var VERSION12 = getPackageVersion(fileURLToPath22(new URL("..", import.meta.url)));
|
|
55383
55859
|
function updaterExtension(pi) {
|
|
55384
55860
|
registerCommands3(pi);
|
|
55385
55861
|
pi.on("session_start", async (_event, ctx) => {
|
|
@@ -55501,8 +55977,8 @@ import { copyToClipboard } from "@earendil-works/pi-coding-agent";
|
|
|
55501
55977
|
import { Key as Key24 } from "@earendil-works/pi-tui";
|
|
55502
55978
|
|
|
55503
55979
|
// packages/input-shortcuts/src/registers.ts
|
|
55504
|
-
import { existsSync as existsSync61, mkdirSync as
|
|
55505
|
-
import { dirname as
|
|
55980
|
+
import { existsSync as existsSync61, mkdirSync as mkdirSync43, readFileSync as readFileSync64, renameSync as renameSync17, writeFileSync as writeFileSync43 } from "node:fs";
|
|
55981
|
+
import { dirname as dirname50, join as join83 } from "node:path";
|
|
55506
55982
|
|
|
55507
55983
|
// packages/input-shortcuts/src/types.ts
|
|
55508
55984
|
var DEFAULT_CONFIG8 = {
|
|
@@ -55518,7 +55994,7 @@ var RegisterStore = class {
|
|
|
55518
55994
|
filePath;
|
|
55519
55995
|
loaded = false;
|
|
55520
55996
|
constructor(baseDir) {
|
|
55521
|
-
this.filePath = baseDir ?
|
|
55997
|
+
this.filePath = baseDir ? join83(baseDir, REGISTERS_FILE) : REGISTERS_FILE;
|
|
55522
55998
|
}
|
|
55523
55999
|
/** Get the stash register contents. */
|
|
55524
56000
|
getStash() {
|
|
@@ -55537,7 +56013,7 @@ var RegisterStore = class {
|
|
|
55537
56013
|
this.loaded = true;
|
|
55538
56014
|
try {
|
|
55539
56015
|
if (existsSync61(this.filePath)) {
|
|
55540
|
-
const raw =
|
|
56016
|
+
const raw = readFileSync64(this.filePath, "utf-8");
|
|
55541
56017
|
const parsed = JSON.parse(raw);
|
|
55542
56018
|
this.data = { stash: typeof parsed.stash === "string" ? parsed.stash : "" };
|
|
55543
56019
|
} else {
|
|
@@ -55550,13 +56026,13 @@ var RegisterStore = class {
|
|
|
55550
56026
|
/** Atomic write: write to .tmp then rename. */
|
|
55551
56027
|
save() {
|
|
55552
56028
|
try {
|
|
55553
|
-
const dir =
|
|
56029
|
+
const dir = dirname50(this.filePath);
|
|
55554
56030
|
if (!existsSync61(dir)) {
|
|
55555
|
-
|
|
56031
|
+
mkdirSync43(dir, { recursive: true });
|
|
55556
56032
|
}
|
|
55557
56033
|
const tmpPath = this.filePath + ".tmp";
|
|
55558
|
-
|
|
55559
|
-
|
|
56034
|
+
writeFileSync43(tmpPath, JSON.stringify(this.data, null, 2), "utf-8");
|
|
56035
|
+
renameSync17(tmpPath, this.filePath);
|
|
55560
56036
|
} catch {
|
|
55561
56037
|
}
|
|
55562
56038
|
}
|
|
@@ -55818,8 +56294,8 @@ var ChordOverlay = class extends Container {
|
|
|
55818
56294
|
};
|
|
55819
56295
|
|
|
55820
56296
|
// packages/input-shortcuts/src/settings.ts
|
|
55821
|
-
import { existsSync as existsSync62, mkdirSync as
|
|
55822
|
-
import { dirname as
|
|
56297
|
+
import { existsSync as existsSync62, mkdirSync as mkdirSync44, readFileSync as readFileSync65, renameSync as renameSync18, writeFileSync as writeFileSync44 } from "node:fs";
|
|
56298
|
+
import { dirname as dirname51, join as join84 } from "node:path";
|
|
55823
56299
|
init_core();
|
|
55824
56300
|
var ALT_KEY_OPTIONS = [
|
|
55825
56301
|
"alt+a",
|
|
@@ -55962,17 +56438,17 @@ function importLegacyInputShortcuts() {
|
|
|
55962
56438
|
const layers = settingsLayers("input-shortcuts", process.cwd());
|
|
55963
56439
|
if (layers.global || layers.project) return;
|
|
55964
56440
|
try {
|
|
55965
|
-
const raw =
|
|
56441
|
+
const raw = readFileSync65(CONFIG_FILE, "utf-8");
|
|
55966
56442
|
setSettings("input-shortcuts", JSON.parse(raw), "project", process.cwd());
|
|
55967
56443
|
} catch {
|
|
55968
56444
|
}
|
|
55969
56445
|
}
|
|
55970
56446
|
function loadConfig8(baseDir) {
|
|
55971
56447
|
if (baseDir) {
|
|
55972
|
-
const filePath =
|
|
56448
|
+
const filePath = join84(baseDir, CONFIG_FILE);
|
|
55973
56449
|
try {
|
|
55974
56450
|
if (existsSync62(filePath)) {
|
|
55975
|
-
const raw =
|
|
56451
|
+
const raw = readFileSync65(filePath, "utf-8");
|
|
55976
56452
|
const parsed = JSON.parse(raw);
|
|
55977
56453
|
return {
|
|
55978
56454
|
chordKey: typeof parsed.chordKey === "string" ? parsed.chordKey : DEFAULT_CONFIG8.chordKey,
|
|
@@ -56286,21 +56762,21 @@ function inputShortcutsExtension(pi) {
|
|
|
56286
56762
|
|
|
56287
56763
|
// packages/fusion/src/index.ts
|
|
56288
56764
|
init_core();
|
|
56289
|
-
import { join as
|
|
56765
|
+
import { join as join87 } from "node:path";
|
|
56290
56766
|
|
|
56291
56767
|
// packages/fusion/src/preset.ts
|
|
56292
56768
|
init_core();
|
|
56293
|
-
import { existsSync as existsSync63, mkdirSync as
|
|
56769
|
+
import { existsSync as existsSync63, mkdirSync as mkdirSync45, readFileSync as readFileSync67, writeFileSync as writeFileSync46, renameSync as renameSync20 } from "node:fs";
|
|
56294
56770
|
import { homedir as homedir52 } from "node:os";
|
|
56295
|
-
import { dirname as
|
|
56771
|
+
import { dirname as dirname52, join as join86 } from "node:path";
|
|
56296
56772
|
|
|
56297
56773
|
// packages/fusion/src/pi-settings.ts
|
|
56298
|
-
import { readFileSync as
|
|
56774
|
+
import { readFileSync as readFileSync66, renameSync as renameSync19, writeFileSync as writeFileSync45 } from "node:fs";
|
|
56299
56775
|
import { homedir as homedir51 } from "node:os";
|
|
56300
|
-
import { join as
|
|
56776
|
+
import { join as join85 } from "node:path";
|
|
56301
56777
|
function piSettingsPath2(env = process.env, home = homedir51()) {
|
|
56302
56778
|
const envDir = env.PI_CODING_AGENT_DIR?.trim();
|
|
56303
|
-
return
|
|
56779
|
+
return join85(envDir !== void 0 && envDir.length > 0 ? envDir : join85(home, ".pi", "agent"), "settings.json");
|
|
56304
56780
|
}
|
|
56305
56781
|
function mergeDefaultModel(raw, patch) {
|
|
56306
56782
|
const settings = typeof raw === "object" && raw !== null && !Array.isArray(raw) ? { ...raw } : {};
|
|
@@ -56312,7 +56788,7 @@ function mergeDefaultModel(raw, patch) {
|
|
|
56312
56788
|
function readDefaultModel(deps = {}) {
|
|
56313
56789
|
try {
|
|
56314
56790
|
const path31 = piSettingsPath2(deps.env);
|
|
56315
|
-
const raw = JSON.parse(deps.readFile !== void 0 ? deps.readFile(path31) :
|
|
56791
|
+
const raw = JSON.parse(deps.readFile !== void 0 ? deps.readFile(path31) : readFileSync66(path31, "utf8"));
|
|
56316
56792
|
const key = typeof raw.defaultProvider === "string" && typeof raw.defaultModel === "string" ? `${raw.defaultProvider}/${raw.defaultModel}` : void 0;
|
|
56317
56793
|
return { key, thinking: typeof raw.defaultThinkingLevel === "string" ? raw.defaultThinkingLevel : void 0 };
|
|
56318
56794
|
} catch {
|
|
@@ -56323,15 +56799,15 @@ function persistDefaultModel(patch, deps = {}) {
|
|
|
56323
56799
|
const path31 = piSettingsPath2(deps.env);
|
|
56324
56800
|
let current = {};
|
|
56325
56801
|
try {
|
|
56326
|
-
current = JSON.parse(deps.readFile !== void 0 ? deps.readFile(path31) :
|
|
56802
|
+
current = JSON.parse(deps.readFile !== void 0 ? deps.readFile(path31) : readFileSync66(path31, "utf8"));
|
|
56327
56803
|
} catch {
|
|
56328
56804
|
current = {};
|
|
56329
56805
|
}
|
|
56330
56806
|
const next = mergeDefaultModel(current, patch);
|
|
56331
56807
|
const tmp = `${path31}.tmp-${String(process.pid)}`;
|
|
56332
|
-
|
|
56808
|
+
writeFileSync45(tmp, `${JSON.stringify(next, null, 2)}
|
|
56333
56809
|
`, "utf8");
|
|
56334
|
-
|
|
56810
|
+
renameSync19(tmp, path31);
|
|
56335
56811
|
return path31;
|
|
56336
56812
|
}
|
|
56337
56813
|
|
|
@@ -56352,10 +56828,10 @@ function emptyPreset() {
|
|
|
56352
56828
|
};
|
|
56353
56829
|
}
|
|
56354
56830
|
function globalPresetPath(home = homedir52()) {
|
|
56355
|
-
return
|
|
56831
|
+
return join86(home, ".unipi", "config", "fusion", "preset.json");
|
|
56356
56832
|
}
|
|
56357
56833
|
function projectPresetPath(cwd) {
|
|
56358
|
-
return
|
|
56834
|
+
return join86(cwd, ".unipi", "fusion-preset.json");
|
|
56359
56835
|
}
|
|
56360
56836
|
function modelKey(model) {
|
|
56361
56837
|
return `${model.provider}/${model.id}`;
|
|
@@ -56450,7 +56926,7 @@ function mergePresets(base, over) {
|
|
|
56450
56926
|
function readJson6(path31) {
|
|
56451
56927
|
try {
|
|
56452
56928
|
if (!existsSync63(path31)) return void 0;
|
|
56453
|
-
return JSON.parse(
|
|
56929
|
+
return JSON.parse(readFileSync67(path31, "utf8"));
|
|
56454
56930
|
} catch {
|
|
56455
56931
|
return void 0;
|
|
56456
56932
|
}
|
|
@@ -56531,11 +57007,11 @@ function loadPreset(cwd, home = homedir52()) {
|
|
|
56531
57007
|
return { preset, globalPath, projectPath, hasProjectLayer };
|
|
56532
57008
|
}
|
|
56533
57009
|
function writeJsonAtomic2(path31, value) {
|
|
56534
|
-
|
|
57010
|
+
mkdirSync45(dirname52(path31), { recursive: true });
|
|
56535
57011
|
const tmp = `${path31}.${String(process.pid)}.tmp`;
|
|
56536
|
-
|
|
57012
|
+
writeFileSync46(tmp, `${JSON.stringify(value, null, 2)}
|
|
56537
57013
|
`, "utf8");
|
|
56538
|
-
|
|
57014
|
+
renameSync20(tmp, path31);
|
|
56539
57015
|
}
|
|
56540
57016
|
function saveCuration(path31, curation) {
|
|
56541
57017
|
const existing = parsePreset(readJson6(path31));
|
|
@@ -57787,7 +58263,7 @@ ${progressText(runtime, id)}`, { progress: runtime.progress(id), id, owner: "fus
|
|
|
57787
58263
|
}
|
|
57788
58264
|
|
|
57789
58265
|
// packages/fusion/src/index.ts
|
|
57790
|
-
import { readFileSync as
|
|
58266
|
+
import { readFileSync as readFileSync68 } from "node:fs";
|
|
57791
58267
|
|
|
57792
58268
|
// packages/fusion/src/api.ts
|
|
57793
58269
|
var FUSION_API_KEY = /* @__PURE__ */ Symbol.for("unipi.fusion.api");
|
|
@@ -57798,7 +58274,7 @@ function publishFusionApi(api) {
|
|
|
57798
58274
|
// packages/fusion/src/index.ts
|
|
57799
58275
|
var MODEL_COMMAND = `${UNIPI_PREFIX}model`;
|
|
57800
58276
|
function sidekickSessionPath(leadSessionId2) {
|
|
57801
|
-
return
|
|
58277
|
+
return join87(stateDir("fusion", "session"), "sidekick", `${leadSessionId2 ?? "default"}.jsonl`);
|
|
57802
58278
|
}
|
|
57803
58279
|
var SIDEKICK_WAKE_WIDGET_KEY = "fusion-sidekick-wake";
|
|
57804
58280
|
function isLeadIdle(ctx) {
|
|
@@ -58165,7 +58641,7 @@ Handoffs: ${String(runtime.reports.size)} \xB7 runtime alive: ${String(runtime.i
|
|
|
58165
58641
|
const currentKey = ctx.model ? modelKey(ctx.model) : void 0;
|
|
58166
58642
|
let defaultKey;
|
|
58167
58643
|
try {
|
|
58168
|
-
const raw = JSON.parse(
|
|
58644
|
+
const raw = JSON.parse(readFileSync68(piSettingsPath2(), "utf8"));
|
|
58169
58645
|
if (typeof raw.defaultProvider === "string" && typeof raw.defaultModel === "string") {
|
|
58170
58646
|
defaultKey = `${raw.defaultProvider}/${raw.defaultModel}`;
|
|
58171
58647
|
}
|
|
@@ -58337,7 +58813,7 @@ ${String(result2.curation.lead.length)} lead \xB7 ${String(result2.curation.side
|
|
|
58337
58813
|
|
|
58338
58814
|
// packages/watchdog/index.ts
|
|
58339
58815
|
init_core();
|
|
58340
|
-
import { appendFileSync as appendFileSync6, mkdirSync as
|
|
58816
|
+
import { appendFileSync as appendFileSync6, mkdirSync as mkdirSync46 } from "node:fs";
|
|
58341
58817
|
import * as os10 from "node:os";
|
|
58342
58818
|
|
|
58343
58819
|
// packages/watchdog/src/config.ts
|
|
@@ -58643,7 +59119,7 @@ ${tail || unfinished ? tail + unfinished : "(no output yet)"}`;
|
|
|
58643
59119
|
}
|
|
58644
59120
|
|
|
58645
59121
|
// packages/watchdog/src/bash-kill.ts
|
|
58646
|
-
import { existsSync as existsSync64, readdirSync as
|
|
59122
|
+
import { existsSync as existsSync64, readdirSync as readdirSync21, readFileSync as readFileSync69 } from "node:fs";
|
|
58647
59123
|
import { execFileSync as execFileSync5 } from "node:child_process";
|
|
58648
59124
|
import { homedir as homedir53 } from "node:os";
|
|
58649
59125
|
function commandNeedles(command, env = process.env, home = homedir53()) {
|
|
@@ -58668,13 +59144,13 @@ function fromLinux(parentPid, command) {
|
|
|
58668
59144
|
const pgids = [];
|
|
58669
59145
|
const needles = commandNeedles(command);
|
|
58670
59146
|
try {
|
|
58671
|
-
for (const entry of existsSync64("/proc") ?
|
|
59147
|
+
for (const entry of existsSync64("/proc") ? readdirSync21("/proc") : []) {
|
|
58672
59148
|
if (!/^\d+$/.test(entry)) continue;
|
|
58673
59149
|
const pid = Number(entry);
|
|
58674
59150
|
if (pid === parentPid) continue;
|
|
58675
59151
|
let stat;
|
|
58676
59152
|
try {
|
|
58677
|
-
stat =
|
|
59153
|
+
stat = readFileSync69(`/proc/${entry}/stat`, "utf-8");
|
|
58678
59154
|
} catch {
|
|
58679
59155
|
continue;
|
|
58680
59156
|
}
|
|
@@ -58685,7 +59161,7 @@ function fromLinux(parentPid, command) {
|
|
|
58685
59161
|
if (ppid !== parentPid) continue;
|
|
58686
59162
|
let cmdline = "";
|
|
58687
59163
|
try {
|
|
58688
|
-
cmdline =
|
|
59164
|
+
cmdline = readFileSync69(`/proc/${entry}/cmdline`, "utf-8").replace(/\0/g, " ");
|
|
58689
59165
|
} catch {
|
|
58690
59166
|
continue;
|
|
58691
59167
|
}
|
|
@@ -58795,7 +59271,7 @@ function debugLog3(line) {
|
|
|
58795
59271
|
if (process.env.UNIPI_DEBUG_WATCHDOG !== "1") return;
|
|
58796
59272
|
try {
|
|
58797
59273
|
const dir = `${os10.homedir()}/.unipi/logs`;
|
|
58798
|
-
|
|
59274
|
+
mkdirSync46(dir, { recursive: true });
|
|
58799
59275
|
appendFileSync6(`${dir}/watchdog.log`, `${(/* @__PURE__ */ new Date()).toISOString()} ${line}
|
|
58800
59276
|
`);
|
|
58801
59277
|
} catch {
|
|
@@ -59222,9 +59698,9 @@ function queueWarn(item, decision, reason) {
|
|
|
59222
59698
|
import { AgentSession, SessionManager as SessionManager4 } from "@earendil-works/pi-coding-agent";
|
|
59223
59699
|
import { createRequire as createRequire5 } from "node:module";
|
|
59224
59700
|
import { createServer as createServer2 } from "node:net";
|
|
59225
|
-
import { chmodSync as chmodSync3, existsSync as existsSync66, mkdirSync as
|
|
59701
|
+
import { chmodSync as chmodSync3, existsSync as existsSync66, mkdirSync as mkdirSync48, readdirSync as readdirSync24, readFileSync as readFileSync71, renameSync as renameSync22, rmSync as rmSync10, writeFileSync as writeFileSync48 } from "node:fs";
|
|
59226
59702
|
import { homedir as homedir57 } from "node:os";
|
|
59227
|
-
import { dirname as
|
|
59703
|
+
import { dirname as dirname53, join as join91, relative as relative7, resolve as resolvePath3 } from "node:path";
|
|
59228
59704
|
|
|
59229
59705
|
// packages/app-bridge/src/dialogs.ts
|
|
59230
59706
|
var DialogHub = class {
|
|
@@ -59356,24 +59832,24 @@ function wrapUi(ui, hub, onNotify) {
|
|
|
59356
59832
|
}
|
|
59357
59833
|
|
|
59358
59834
|
// packages/app-bridge/src/media.ts
|
|
59359
|
-
import { mkdirSync as
|
|
59835
|
+
import { mkdirSync as mkdirSync47, renameSync as renameSync21, writeFileSync as writeFileSync47 } from "node:fs";
|
|
59360
59836
|
import { homedir as homedir55 } from "node:os";
|
|
59361
|
-
import { join as
|
|
59837
|
+
import { join as join88 } from "node:path";
|
|
59362
59838
|
var MAX_ENTRIES = 500;
|
|
59363
59839
|
var seq = 0;
|
|
59364
59840
|
var entries = /* @__PURE__ */ new Map();
|
|
59365
59841
|
var registeredPaths = /* @__PURE__ */ new Set();
|
|
59366
59842
|
function bridgeDir() {
|
|
59367
|
-
return process.env.UNIPI_BRIDGE_DIR ||
|
|
59843
|
+
return process.env.UNIPI_BRIDGE_DIR || join88(homedir55(), ".unipi", "bridge");
|
|
59368
59844
|
}
|
|
59369
59845
|
function writeAllowList() {
|
|
59370
59846
|
try {
|
|
59371
59847
|
const dir = bridgeDir();
|
|
59372
|
-
|
|
59373
|
-
const file =
|
|
59848
|
+
mkdirSync47(dir, { recursive: true, mode: 448 });
|
|
59849
|
+
const file = join88(dir, `${process.pid}.files.json`);
|
|
59374
59850
|
const tmp = `${file}.tmp`;
|
|
59375
|
-
|
|
59376
|
-
|
|
59851
|
+
writeFileSync47(tmp, JSON.stringify([...registeredPaths]), { mode: 384 });
|
|
59852
|
+
renameSync21(tmp, file);
|
|
59377
59853
|
} catch {
|
|
59378
59854
|
}
|
|
59379
59855
|
}
|
|
@@ -60052,8 +60528,8 @@ function setRemoteDialogs(hub) {
|
|
|
60052
60528
|
import { CombinedAutocompleteProvider } from "@earendil-works/pi-tui";
|
|
60053
60529
|
import { getAgentDir } from "@earendil-works/pi-coding-agent";
|
|
60054
60530
|
import { spawnSync as spawnSync4 } from "node:child_process";
|
|
60055
|
-
import { existsSync as existsSync65, readdirSync as
|
|
60056
|
-
import { join as
|
|
60531
|
+
import { existsSync as existsSync65, readdirSync as readdirSync22 } from "node:fs";
|
|
60532
|
+
import { join as join89, relative as relative5, sep as sep6 } from "node:path";
|
|
60057
60533
|
var MAX_ITEMS = 30;
|
|
60058
60534
|
var TIMEOUT_MS2 = 4e3;
|
|
60059
60535
|
var fdCache;
|
|
@@ -60061,7 +60537,7 @@ function findFd() {
|
|
|
60061
60537
|
if (fdCache !== void 0) return fdCache;
|
|
60062
60538
|
const exe = process.platform === "win32" ? ".exe" : "";
|
|
60063
60539
|
try {
|
|
60064
|
-
const local =
|
|
60540
|
+
const local = join89(getAgentDir(), "bin", `fd${exe}`);
|
|
60065
60541
|
if (existsSync65(local)) return fdCache = local;
|
|
60066
60542
|
} catch {
|
|
60067
60543
|
}
|
|
@@ -60083,14 +60559,14 @@ function walk(cwd, query) {
|
|
|
60083
60559
|
const { dir, depth } = queue.shift();
|
|
60084
60560
|
let names;
|
|
60085
60561
|
try {
|
|
60086
|
-
names =
|
|
60562
|
+
names = readdirSync22(dir, { withFileTypes: true });
|
|
60087
60563
|
} catch {
|
|
60088
60564
|
continue;
|
|
60089
60565
|
}
|
|
60090
60566
|
for (const d of names) {
|
|
60091
60567
|
seen++;
|
|
60092
60568
|
if (SKIP.has(d.name)) continue;
|
|
60093
|
-
const full =
|
|
60569
|
+
const full = join89(dir, d.name);
|
|
60094
60570
|
const rel = relative5(cwd, full).split(sep6).join("/");
|
|
60095
60571
|
const isDir = d.isDirectory();
|
|
60096
60572
|
if (isDir && depth < 5) queue.push({ dir: full, depth: depth + 1 });
|
|
@@ -60129,9 +60605,9 @@ async function fileSuggestions(cwd, query) {
|
|
|
60129
60605
|
|
|
60130
60606
|
// packages/app-bridge/src/paths.ts
|
|
60131
60607
|
import { spawn as spawn7 } from "node:child_process";
|
|
60132
|
-
import { readFileSync as
|
|
60608
|
+
import { readFileSync as readFileSync70, readdirSync as readdirSync23, realpathSync as realpathSync7, statSync as statSync21 } from "node:fs";
|
|
60133
60609
|
import { homedir as homedir56, userInfo } from "node:os";
|
|
60134
|
-
import { join as
|
|
60610
|
+
import { join as join90, relative as relative6, resolve as resolvePath2, sep as sep7 } from "node:path";
|
|
60135
60611
|
var PATHS_STAT_MAX = 200;
|
|
60136
60612
|
var PATH_MAX_CHARS = 4096;
|
|
60137
60613
|
function inside(target, root) {
|
|
@@ -60140,12 +60616,12 @@ function inside(target, root) {
|
|
|
60140
60616
|
}
|
|
60141
60617
|
function resolveAgainst(path31, cwd, home) {
|
|
60142
60618
|
if (path31 === "~") return home;
|
|
60143
|
-
if (path31.startsWith("~/")) return
|
|
60619
|
+
if (path31.startsWith("~/")) return join90(home, path31.slice(2));
|
|
60144
60620
|
return resolvePath2(cwd, path31);
|
|
60145
60621
|
}
|
|
60146
60622
|
var kindOf2 = (abs) => {
|
|
60147
60623
|
try {
|
|
60148
|
-
const st =
|
|
60624
|
+
const st = statSync21(abs);
|
|
60149
60625
|
return st.isDirectory() ? "dir" : st.isFile() ? "file" : "missing";
|
|
60150
60626
|
} catch {
|
|
60151
60627
|
return "missing";
|
|
@@ -60183,13 +60659,13 @@ function resolveSafeRoots(config, home, user) {
|
|
|
60183
60659
|
}
|
|
60184
60660
|
return out;
|
|
60185
60661
|
}
|
|
60186
|
-
var hostConfigPath = () =>
|
|
60662
|
+
var hostConfigPath = () => join90(process.env.UNIPI_HOST_DIR || join90(homedir56(), ".unipi", "app-host"), "config.json");
|
|
60187
60663
|
var rootsCache;
|
|
60188
60664
|
function hostSafeRoots(now2 = Date.now(), home = homedir56()) {
|
|
60189
60665
|
if (rootsCache && now2 - rootsCache.at < 5e3) return rootsCache;
|
|
60190
60666
|
let fs28 = {};
|
|
60191
60667
|
try {
|
|
60192
|
-
const parsed = JSON.parse(
|
|
60668
|
+
const parsed = JSON.parse(readFileSync70(hostConfigPath(), "utf8"));
|
|
60193
60669
|
if (parsed && typeof parsed.fs === "object" && parsed.fs) fs28 = parsed.fs;
|
|
60194
60670
|
} catch {
|
|
60195
60671
|
}
|
|
@@ -60281,14 +60757,14 @@ function walkTree(cwd, files, dirs) {
|
|
|
60281
60757
|
const { dir, depth } = queue.shift();
|
|
60282
60758
|
let names;
|
|
60283
60759
|
try {
|
|
60284
|
-
names =
|
|
60760
|
+
names = readdirSync23(dir, { withFileTypes: true });
|
|
60285
60761
|
} catch {
|
|
60286
60762
|
continue;
|
|
60287
60763
|
}
|
|
60288
60764
|
for (const d of names) {
|
|
60289
60765
|
if (SKIP2.has(d.name)) continue;
|
|
60290
60766
|
seen++;
|
|
60291
|
-
const full =
|
|
60767
|
+
const full = join90(dir, d.name);
|
|
60292
60768
|
const rel = relative6(cwd, full).split(sep7).join("/");
|
|
60293
60769
|
if (d.isDirectory()) {
|
|
60294
60770
|
dirs.push(rel);
|
|
@@ -60335,7 +60811,7 @@ async function statPaths(paths, cwd, home = homedir56(), extra = hostSafeRoots(D
|
|
|
60335
60811
|
idx ??= await treeIndex(cwd);
|
|
60336
60812
|
const m = suffixMatch(idx, path31);
|
|
60337
60813
|
if (m) {
|
|
60338
|
-
at =
|
|
60814
|
+
at = join90(cwd, m.rel);
|
|
60339
60815
|
kind = kindOf2(at);
|
|
60340
60816
|
}
|
|
60341
60817
|
} catch {
|
|
@@ -60407,11 +60883,11 @@ function entryPreview(entry, max = 120) {
|
|
|
60407
60883
|
return text.length > max ? `${text.slice(0, max - 1)}\u2026` : text;
|
|
60408
60884
|
}
|
|
60409
60885
|
function bridgeDir2() {
|
|
60410
|
-
return process.env.UNIPI_BRIDGE_DIR ||
|
|
60886
|
+
return process.env.UNIPI_BRIDGE_DIR || join91(homedir57(), ".unipi", "bridge");
|
|
60411
60887
|
}
|
|
60412
60888
|
function bridgeSocketPath(dir, pid, platform = process.platform) {
|
|
60413
60889
|
if (platform === "win32") return "\\\\.\\pipe\\unipi-bridge-" + pid;
|
|
60414
|
-
return
|
|
60890
|
+
return join91(dir, `${pid}.sock`);
|
|
60415
60891
|
}
|
|
60416
60892
|
function isBridgePipe(path31) {
|
|
60417
60893
|
return path31.startsWith("\\\\.\\pipe\\");
|
|
@@ -60427,7 +60903,7 @@ function alive(pid) {
|
|
|
60427
60903
|
function sweepDead(dir) {
|
|
60428
60904
|
let names;
|
|
60429
60905
|
try {
|
|
60430
|
-
names =
|
|
60906
|
+
names = readdirSync24(dir);
|
|
60431
60907
|
} catch {
|
|
60432
60908
|
return;
|
|
60433
60909
|
}
|
|
@@ -60435,7 +60911,7 @@ function sweepDead(dir) {
|
|
|
60435
60911
|
const m = /^(\d+)\.(json|sock)$/.exec(name);
|
|
60436
60912
|
if (!m) continue;
|
|
60437
60913
|
const pid = Number(m[1]);
|
|
60438
|
-
if (pid !== process.pid && !alive(pid))
|
|
60914
|
+
if (pid !== process.pid && !alive(pid)) rmSync10(join91(dir, name), { force: true });
|
|
60439
60915
|
}
|
|
60440
60916
|
}
|
|
60441
60917
|
function isInsideCwd(path31, cwd) {
|
|
@@ -60467,11 +60943,11 @@ var patchAgentSessionPrototype = (Ctor) => {
|
|
|
60467
60943
|
};
|
|
60468
60944
|
var patchAllRuntimeCopies = () => {
|
|
60469
60945
|
patchAgentSessionPrototype(AgentSession);
|
|
60470
|
-
const pkgRoot =
|
|
60946
|
+
const pkgRoot = join91(dirname53(dirname53(process.execPath)), "lib", "node_modules", "@earendil-works", "pi-coding-agent");
|
|
60471
60947
|
const candidates = [
|
|
60472
|
-
|
|
60473
|
-
|
|
60474
|
-
process.argv[1] ? resolvePath3(
|
|
60948
|
+
join91(pkgRoot, "dist", "bundle", "index.js"),
|
|
60949
|
+
join91(pkgRoot, "dist", "index.js"),
|
|
60950
|
+
process.argv[1] ? resolvePath3(dirname53(process.argv[1]), "..", "lib", "node_modules", "@earendil-works", "pi-coding-agent", "dist", "bundle", "index.js") : ""
|
|
60475
60951
|
];
|
|
60476
60952
|
for (const index of candidates) {
|
|
60477
60953
|
if (!index) continue;
|
|
@@ -60906,10 +61382,10 @@ function createBridge(pi, deps = defaultDeps2) {
|
|
|
60906
61382
|
...recordLhMode(lhMode())
|
|
60907
61383
|
};
|
|
60908
61384
|
try {
|
|
60909
|
-
const file =
|
|
61385
|
+
const file = join91(dir, `${process.pid}.json`);
|
|
60910
61386
|
const tmp = `${file}.tmp`;
|
|
60911
|
-
|
|
60912
|
-
|
|
61387
|
+
writeFileSync48(tmp, JSON.stringify(record), { mode: 384 });
|
|
61388
|
+
renameSync22(tmp, file);
|
|
60913
61389
|
} catch {
|
|
60914
61390
|
}
|
|
60915
61391
|
};
|
|
@@ -61082,7 +61558,7 @@ function createBridge(pi, deps = defaultDeps2) {
|
|
|
61082
61558
|
const imageContent = (i) => {
|
|
61083
61559
|
if ("data" in i) return { type: "image", mimeType: i.mime, data: i.data };
|
|
61084
61560
|
try {
|
|
61085
|
-
return { type: "image", mimeType: i.mime, data:
|
|
61561
|
+
return { type: "image", mimeType: i.mime, data: readFileSync71(i.path).toString("base64") };
|
|
61086
61562
|
} catch {
|
|
61087
61563
|
return { type: "text", text: `[image unavailable: ${i.path}]` };
|
|
61088
61564
|
}
|
|
@@ -61575,7 +62051,7 @@ function createBridge(pi, deps = defaultDeps2) {
|
|
|
61575
62051
|
const entry = resolveMedia(msg.mediaRef);
|
|
61576
62052
|
if (!entry) return write(sock, { t: "media_error", mediaRef: msg.mediaRef, message: "That image is no longer available. Re-open the message." });
|
|
61577
62053
|
try {
|
|
61578
|
-
const data = entry.kind === "base64" ? entry.data :
|
|
62054
|
+
const data = entry.kind === "base64" ? entry.data : readFileSync71(entry.path).toString("base64");
|
|
61579
62055
|
for (let i = 0; i < data.length || i === 0; i += MEDIA_CHUNK_CHARS) {
|
|
61580
62056
|
const piece = data.slice(i, i + MEDIA_CHUNK_CHARS);
|
|
61581
62057
|
const done = i + MEDIA_CHUNK_CHARS >= data.length;
|
|
@@ -61726,14 +62202,14 @@ function createBridge(pi, deps = defaultDeps2) {
|
|
|
61726
62202
|
if (server || !ctx) return;
|
|
61727
62203
|
const dir = bridgeDir2();
|
|
61728
62204
|
try {
|
|
61729
|
-
|
|
62205
|
+
mkdirSync48(dir, { recursive: true, mode: 448 });
|
|
61730
62206
|
chmodSync3(dir, 448);
|
|
61731
62207
|
} catch {
|
|
61732
62208
|
return;
|
|
61733
62209
|
}
|
|
61734
62210
|
sweepDead(dir);
|
|
61735
62211
|
socketPath = bridgeSocketPath(dir, process.pid);
|
|
61736
|
-
if (!isBridgePipe(socketPath))
|
|
62212
|
+
if (!isBridgePipe(socketPath)) rmSync10(socketPath, { force: true });
|
|
61737
62213
|
const srv = createServer2((sock) => {
|
|
61738
62214
|
clients.add(sock);
|
|
61739
62215
|
if (idleWaitingSince !== void 0) {
|
|
@@ -61802,8 +62278,8 @@ function createBridge(pi, deps = defaultDeps2) {
|
|
|
61802
62278
|
server?.close();
|
|
61803
62279
|
server = void 0;
|
|
61804
62280
|
const dir = bridgeDir2();
|
|
61805
|
-
|
|
61806
|
-
if (socketPath && !isBridgePipe(socketPath))
|
|
62281
|
+
rmSync10(join91(dir, `${process.pid}.json`), { force: true });
|
|
62282
|
+
if (socketPath && !isBridgePipe(socketPath)) rmSync10(socketPath, { force: true });
|
|
61807
62283
|
socketPath = void 0;
|
|
61808
62284
|
};
|
|
61809
62285
|
const safe = (fn) => (...args) => {
|
|
@@ -62221,6 +62697,16 @@ function index_default(pi) {
|
|
|
62221
62697
|
}
|
|
62222
62698
|
}
|
|
62223
62699
|
}
|
|
62700
|
+
try {
|
|
62701
|
+
writeSettingsSnapshot();
|
|
62702
|
+
} catch {
|
|
62703
|
+
}
|
|
62704
|
+
api.on("session_start", () => {
|
|
62705
|
+
try {
|
|
62706
|
+
writeSettingsSnapshot();
|
|
62707
|
+
} catch {
|
|
62708
|
+
}
|
|
62709
|
+
});
|
|
62224
62710
|
}
|
|
62225
62711
|
export {
|
|
62226
62712
|
index_default as default
|