@runfusion/fusion 0.0.6 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin.js +2107 -510
- package/dist/client/assets/index-B3ZN3sln.css +1 -0
- package/dist/client/assets/index-cgKoCmZP.js +1241 -0
- package/dist/client/index.html +2 -2
- package/dist/extension.js +513 -196
- package/package.json +1 -1
- package/dist/client/assets/index-CYkQfLYV.css +0 -1
- package/dist/client/assets/index-zTogbMzz.js +0 -1241
package/dist/bin.js
CHANGED
|
@@ -138,7 +138,7 @@ var init_settings_schema = __esm({
|
|
|
138
138
|
worktreeRebaseRemote: "",
|
|
139
139
|
strictScopeEnforcement: false,
|
|
140
140
|
buildRetryCount: 0,
|
|
141
|
-
verificationFixRetries:
|
|
141
|
+
verificationFixRetries: 3,
|
|
142
142
|
buildTimeoutMs: 3e5,
|
|
143
143
|
requirePlanApproval: false,
|
|
144
144
|
specStalenessEnabled: false,
|
|
@@ -1975,6 +1975,18 @@ function fromJson(json) {
|
|
|
1975
1975
|
return void 0;
|
|
1976
1976
|
}
|
|
1977
1977
|
}
|
|
1978
|
+
function probeFts5(db) {
|
|
1979
|
+
if (process.env.FUSION_DISABLE_FTS5 === "1" || process.env.FUSION_DISABLE_FTS5 === "true") {
|
|
1980
|
+
return false;
|
|
1981
|
+
}
|
|
1982
|
+
try {
|
|
1983
|
+
db.exec("CREATE VIRTUAL TABLE IF NOT EXISTS __fusion_fts5_probe USING fts5(x)");
|
|
1984
|
+
db.exec("DROP TABLE IF EXISTS __fusion_fts5_probe");
|
|
1985
|
+
return true;
|
|
1986
|
+
} catch {
|
|
1987
|
+
return false;
|
|
1988
|
+
}
|
|
1989
|
+
}
|
|
1978
1990
|
function normalizeTaskComments(steeringComments, comments) {
|
|
1979
1991
|
const normalizedComments = [];
|
|
1980
1992
|
const seenKeys = /* @__PURE__ */ new Set();
|
|
@@ -2495,6 +2507,7 @@ CREATE INDEX IF NOT EXISTS idxInsightRunsProjectId
|
|
|
2495
2507
|
dbPath;
|
|
2496
2508
|
/** Tracks transaction nesting depth for savepoint-based nested transactions. */
|
|
2497
2509
|
transactionDepth = 0;
|
|
2510
|
+
_fts5Available;
|
|
2498
2511
|
constructor(kbDir) {
|
|
2499
2512
|
this.dbPath = join(kbDir, "fusion.db");
|
|
2500
2513
|
if (!isAbsolute(kbDir)) {
|
|
@@ -2507,6 +2520,16 @@ CREATE INDEX IF NOT EXISTS idxInsightRunsProjectId
|
|
|
2507
2520
|
this.db.exec("PRAGMA journal_mode = WAL");
|
|
2508
2521
|
this.db.exec("PRAGMA busy_timeout = 5000");
|
|
2509
2522
|
this.db.exec("PRAGMA foreign_keys = ON");
|
|
2523
|
+
this._fts5Available = probeFts5(this.db);
|
|
2524
|
+
}
|
|
2525
|
+
/**
|
|
2526
|
+
* True when the underlying SQLite build has FTS5 (`CREATE VIRTUAL TABLE … USING fts5`).
|
|
2527
|
+
* Node's bundled SQLite only exposes FTS5 when built with `SQLITE_ENABLE_FTS5`;
|
|
2528
|
+
* older Node 22.x LTS builds do not. Consumers must fall back to LIKE-based scans
|
|
2529
|
+
* when this is false. Override with `FUSION_DISABLE_FTS5=1` to force the fallback path.
|
|
2530
|
+
*/
|
|
2531
|
+
get fts5Available() {
|
|
2532
|
+
return this._fts5Available;
|
|
2510
2533
|
}
|
|
2511
2534
|
/**
|
|
2512
2535
|
* Initialize the database: create tables if they don't exist
|
|
@@ -2816,6 +2839,9 @@ CREATE INDEX IF NOT EXISTS idxInsightRunsProjectId
|
|
|
2816
2839
|
}
|
|
2817
2840
|
if (version < 21) {
|
|
2818
2841
|
this.applyMigration(21, () => {
|
|
2842
|
+
if (!this._fts5Available) {
|
|
2843
|
+
return;
|
|
2844
|
+
}
|
|
2819
2845
|
this.db.exec(`
|
|
2820
2846
|
CREATE VIRTUAL TABLE IF NOT EXISTS tasks_fts USING fts5(
|
|
2821
2847
|
id,
|
|
@@ -3225,6 +3251,9 @@ CREATE INDEX IF NOT EXISTS idxInsightRunsProjectId
|
|
|
3225
3251
|
}
|
|
3226
3252
|
if (version < 35) {
|
|
3227
3253
|
this.applyMigration(35, () => {
|
|
3254
|
+
if (!this._fts5Available) {
|
|
3255
|
+
return;
|
|
3256
|
+
}
|
|
3228
3257
|
const hasTaskTitle = this.hasColumn("tasks", "title");
|
|
3229
3258
|
const updateColumns = hasTaskTitle ? "id, title, description, comments" : "id, description, comments";
|
|
3230
3259
|
const oldTitle = hasTaskTitle ? "COALESCE(old.title, '')" : "''";
|
|
@@ -3518,6 +3547,9 @@ function resolveCreationRuntimeConfig(incoming, metadata) {
|
|
|
3518
3547
|
return incoming;
|
|
3519
3548
|
}
|
|
3520
3549
|
const rc = { ...incoming ?? {} };
|
|
3550
|
+
if (typeof rc.enabled !== "boolean") {
|
|
3551
|
+
rc.enabled = true;
|
|
3552
|
+
}
|
|
3521
3553
|
if (typeof rc.heartbeatIntervalMs !== "number" || !Number.isFinite(rc.heartbeatIntervalMs)) {
|
|
3522
3554
|
rc.heartbeatIntervalMs = DEFAULT_AGENT_HEARTBEAT_INTERVAL_MS;
|
|
3523
3555
|
}
|
|
@@ -3563,6 +3595,7 @@ var init_agent_store = __esm({
|
|
|
3563
3595
|
const _2 = this.db;
|
|
3564
3596
|
await mkdir(this.agentsDir, { recursive: true });
|
|
3565
3597
|
await this.importLegacyFileDataOnce();
|
|
3598
|
+
await this.normalizeHeartbeatDefaultsOnce();
|
|
3566
3599
|
}
|
|
3567
3600
|
/**
|
|
3568
3601
|
* One-way migration helper for projects that still have legacy agent JSON
|
|
@@ -3667,6 +3700,51 @@ var init_agent_store = __esm({
|
|
|
3667
3700
|
`).run(migrationKey, migrationVersion);
|
|
3668
3701
|
this.db.bumpLastModified();
|
|
3669
3702
|
}
|
|
3703
|
+
/**
|
|
3704
|
+
* One-time normalization for durable agents created before the heartbeat
|
|
3705
|
+
* toggle was exposed in the UI. Those agents could persist
|
|
3706
|
+
* `runtimeConfig.enabled = false` even though users had no supported way to
|
|
3707
|
+
* manage that flag, which caused timers to stay disabled after restart.
|
|
3708
|
+
*
|
|
3709
|
+
* We normalize only once per project. After this migration lands, explicit
|
|
3710
|
+
* user choices are preserved because the version gate prevents reruns.
|
|
3711
|
+
*/
|
|
3712
|
+
async normalizeHeartbeatDefaultsOnce() {
|
|
3713
|
+
const migrationKey = "agentHeartbeatDefaultVersion";
|
|
3714
|
+
const migrationVersion = "1";
|
|
3715
|
+
const row = this.db.prepare("SELECT value FROM __meta WHERE key = ?").get(migrationKey);
|
|
3716
|
+
if (row?.value === migrationVersion) {
|
|
3717
|
+
return;
|
|
3718
|
+
}
|
|
3719
|
+
const agents = await this.listAgents({ includeEphemeral: true });
|
|
3720
|
+
let changed = 0;
|
|
3721
|
+
for (const agent of agents) {
|
|
3722
|
+
if (isEphemeralAgent(agent)) {
|
|
3723
|
+
continue;
|
|
3724
|
+
}
|
|
3725
|
+
const nextRuntimeConfig = {
|
|
3726
|
+
...resolveCreationRuntimeConfig(agent.runtimeConfig, agent.metadata) ?? {},
|
|
3727
|
+
enabled: true
|
|
3728
|
+
};
|
|
3729
|
+
const currentRuntimeConfig = agent.runtimeConfig ?? void 0;
|
|
3730
|
+
if (JSON.stringify(nextRuntimeConfig) === JSON.stringify(currentRuntimeConfig)) {
|
|
3731
|
+
continue;
|
|
3732
|
+
}
|
|
3733
|
+
await this.writeAgent({
|
|
3734
|
+
...agent,
|
|
3735
|
+
runtimeConfig: nextRuntimeConfig
|
|
3736
|
+
});
|
|
3737
|
+
changed++;
|
|
3738
|
+
}
|
|
3739
|
+
this.db.prepare(`
|
|
3740
|
+
INSERT INTO __meta (key, value)
|
|
3741
|
+
VALUES (?, ?)
|
|
3742
|
+
ON CONFLICT(key) DO UPDATE SET value = excluded.value
|
|
3743
|
+
`).run(migrationKey, migrationVersion);
|
|
3744
|
+
if (changed > 0) {
|
|
3745
|
+
this.db.bumpLastModified();
|
|
3746
|
+
}
|
|
3747
|
+
}
|
|
3670
3748
|
/**
|
|
3671
3749
|
* Create a new agent with "idle" state.
|
|
3672
3750
|
*
|
|
@@ -5776,11 +5854,12 @@ var init_global_settings = __esm({
|
|
|
5776
5854
|
import { DatabaseSync as DatabaseSync2 } from "node:sqlite";
|
|
5777
5855
|
import { existsSync as existsSync4, mkdirSync as mkdirSync3 } from "node:fs";
|
|
5778
5856
|
import { join as join5 } from "node:path";
|
|
5779
|
-
var
|
|
5857
|
+
var BASE_SCHEMA_SQL, FTS5_SCHEMA_SQL, ArchiveDatabase;
|
|
5780
5858
|
var init_archive_db = __esm({
|
|
5781
5859
|
"../core/src/archive-db.ts"() {
|
|
5782
5860
|
"use strict";
|
|
5783
|
-
|
|
5861
|
+
init_db();
|
|
5862
|
+
BASE_SCHEMA_SQL = `
|
|
5784
5863
|
CREATE TABLE IF NOT EXISTS archived_tasks (
|
|
5785
5864
|
id TEXT PRIMARY KEY,
|
|
5786
5865
|
taskJson TEXT NOT NULL,
|
|
@@ -5796,7 +5875,8 @@ CREATE TABLE IF NOT EXISTS archived_tasks (
|
|
|
5796
5875
|
|
|
5797
5876
|
CREATE INDEX IF NOT EXISTS idxArchivedTasksArchivedAt ON archived_tasks(archivedAt);
|
|
5798
5877
|
CREATE INDEX IF NOT EXISTS idxArchivedTasksCreatedAt ON archived_tasks(createdAt);
|
|
5799
|
-
|
|
5878
|
+
`;
|
|
5879
|
+
FTS5_SCHEMA_SQL = `
|
|
5800
5880
|
CREATE VIRTUAL TABLE IF NOT EXISTS archived_tasks_fts USING fts5(
|
|
5801
5881
|
id,
|
|
5802
5882
|
title,
|
|
@@ -5824,18 +5904,26 @@ CREATE TRIGGER IF NOT EXISTS archived_tasks_fts_ad AFTER DELETE ON archived_task
|
|
|
5824
5904
|
END;
|
|
5825
5905
|
`;
|
|
5826
5906
|
ArchiveDatabase = class {
|
|
5907
|
+
db;
|
|
5908
|
+
_fts5Available;
|
|
5827
5909
|
constructor(kbDir) {
|
|
5828
|
-
this.kbDir = kbDir;
|
|
5829
5910
|
if (!existsSync4(kbDir)) {
|
|
5830
5911
|
mkdirSync3(kbDir, { recursive: true });
|
|
5831
5912
|
}
|
|
5832
5913
|
this.db = new DatabaseSync2(join5(kbDir, "archive.db"));
|
|
5833
5914
|
this.db.exec("PRAGMA journal_mode = WAL");
|
|
5834
5915
|
this.db.exec("PRAGMA busy_timeout = 5000");
|
|
5916
|
+
this._fts5Available = probeFts5(this.db);
|
|
5917
|
+
}
|
|
5918
|
+
/** True when this SQLite build has FTS5. See db.ts#probeFts5. */
|
|
5919
|
+
get fts5Available() {
|
|
5920
|
+
return this._fts5Available;
|
|
5835
5921
|
}
|
|
5836
|
-
db;
|
|
5837
5922
|
init() {
|
|
5838
|
-
this.db.exec(
|
|
5923
|
+
this.db.exec(BASE_SCHEMA_SQL);
|
|
5924
|
+
if (this._fts5Available) {
|
|
5925
|
+
this.db.exec(FTS5_SCHEMA_SQL);
|
|
5926
|
+
}
|
|
5839
5927
|
this.addColumnIfMissing("archived_tasks", "prompt", "TEXT");
|
|
5840
5928
|
}
|
|
5841
5929
|
upsert(entry) {
|
|
@@ -5876,15 +5964,48 @@ END;
|
|
|
5876
5964
|
delete(id) {
|
|
5877
5965
|
this.db.prepare("DELETE FROM archived_tasks WHERE id = ?").run(id);
|
|
5878
5966
|
}
|
|
5967
|
+
/**
|
|
5968
|
+
* Full-text search over archived tasks. Accepts a raw user query and routes
|
|
5969
|
+
* through FTS5 when available, or a LIKE-based scan when not.
|
|
5970
|
+
*/
|
|
5879
5971
|
search(query, limit) {
|
|
5972
|
+
const trimmed = query?.trim();
|
|
5973
|
+
if (!trimmed) return [];
|
|
5974
|
+
const tokens = trimmed.split(/\s+/).filter((t) => t.length > 0).map((t) => t.replace(/["{}:*^+()]/g, "")).filter((t) => t.length > 0);
|
|
5975
|
+
if (tokens.length === 0) return [];
|
|
5976
|
+
if (this._fts5Available) {
|
|
5977
|
+
const ftsQuery = tokens.map((token) => {
|
|
5978
|
+
if (/[":(){}*^+-]/.test(token)) {
|
|
5979
|
+
return `"${token.replace(/"/g, '\\"')}"`;
|
|
5980
|
+
}
|
|
5981
|
+
return token;
|
|
5982
|
+
}).join(" OR ");
|
|
5983
|
+
const rows2 = this.db.prepare(`
|
|
5984
|
+
SELECT a.taskJson
|
|
5985
|
+
FROM archived_tasks a
|
|
5986
|
+
JOIN archived_tasks_fts fts ON a.rowid = fts.rowid
|
|
5987
|
+
WHERE archived_tasks_fts MATCH ?
|
|
5988
|
+
ORDER BY rank
|
|
5989
|
+
LIMIT ?
|
|
5990
|
+
`).all(ftsQuery, limit);
|
|
5991
|
+
return rows2.map((row) => JSON.parse(row.taskJson));
|
|
5992
|
+
}
|
|
5993
|
+
const searchColumns = ["id", "title", "description", "comments"];
|
|
5994
|
+
const perTokenClause = `(${searchColumns.map((c) => `"${c}" LIKE ? ESCAPE '\\'`).join(" OR ")})`;
|
|
5995
|
+
const whereTokens = tokens.map(() => perTokenClause).join(" OR ");
|
|
5996
|
+
const params = [];
|
|
5997
|
+
for (const token of tokens) {
|
|
5998
|
+
const pattern = `%${token.replace(/[\\%_]/g, "\\$&")}%`;
|
|
5999
|
+
for (let i = 0; i < searchColumns.length; i++) params.push(pattern);
|
|
6000
|
+
}
|
|
6001
|
+
params.push(limit);
|
|
5880
6002
|
const rows = this.db.prepare(`
|
|
5881
|
-
SELECT
|
|
5882
|
-
FROM archived_tasks
|
|
5883
|
-
|
|
5884
|
-
|
|
5885
|
-
ORDER BY rank
|
|
6003
|
+
SELECT taskJson
|
|
6004
|
+
FROM archived_tasks
|
|
6005
|
+
WHERE ${whereTokens}
|
|
6006
|
+
ORDER BY archivedAt DESC
|
|
5886
6007
|
LIMIT ?
|
|
5887
|
-
`).all(
|
|
6008
|
+
`).all(...params);
|
|
5888
6009
|
return rows.map((row) => JSON.parse(row.taskJson));
|
|
5889
6010
|
}
|
|
5890
6011
|
close() {
|
|
@@ -12197,6 +12318,9 @@ var init_migration = __esm({
|
|
|
12197
12318
|
* @returns Generated name
|
|
12198
12319
|
*/
|
|
12199
12320
|
async generateProjectName(projectPath) {
|
|
12321
|
+
if (!existsSync7(join9(projectPath, ".git"))) {
|
|
12322
|
+
return basename3(projectPath);
|
|
12323
|
+
}
|
|
12200
12324
|
try {
|
|
12201
12325
|
const { execFile: execFile5 } = await import("node:child_process");
|
|
12202
12326
|
const { promisify: promisify14 } = await import("node:util");
|
|
@@ -12204,7 +12328,7 @@ var init_migration = __esm({
|
|
|
12204
12328
|
const { stdout } = await execFileAsync3(
|
|
12205
12329
|
"git",
|
|
12206
12330
|
["remote", "get-url", "origin"],
|
|
12207
|
-
{ cwd: projectPath, timeout:
|
|
12331
|
+
{ cwd: projectPath, timeout: 1e3 }
|
|
12208
12332
|
);
|
|
12209
12333
|
const remoteUrl = stdout.trim();
|
|
12210
12334
|
if (remoteUrl) {
|
|
@@ -28698,6 +28822,27 @@ var init_run_command = __esm({
|
|
|
28698
28822
|
}
|
|
28699
28823
|
});
|
|
28700
28824
|
|
|
28825
|
+
// ../core/src/logger.ts
|
|
28826
|
+
function createLogger(prefix) {
|
|
28827
|
+
const tag = `[${prefix}]`;
|
|
28828
|
+
return {
|
|
28829
|
+
log(message, ...args) {
|
|
28830
|
+
console.error(`${tag} ${message}`, ...args);
|
|
28831
|
+
},
|
|
28832
|
+
warn(message, ...args) {
|
|
28833
|
+
console.warn(`${tag} ${message}`, ...args);
|
|
28834
|
+
},
|
|
28835
|
+
error(message, ...args) {
|
|
28836
|
+
console.error(`${tag} ${message}`, ...args);
|
|
28837
|
+
}
|
|
28838
|
+
};
|
|
28839
|
+
}
|
|
28840
|
+
var init_logger = __esm({
|
|
28841
|
+
"../core/src/logger.ts"() {
|
|
28842
|
+
"use strict";
|
|
28843
|
+
}
|
|
28844
|
+
});
|
|
28845
|
+
|
|
28701
28846
|
// ../core/src/store.ts
|
|
28702
28847
|
import { EventEmitter as EventEmitter11 } from "node:events";
|
|
28703
28848
|
import { randomUUID as randomUUID6 } from "node:crypto";
|
|
@@ -28746,7 +28891,7 @@ function canonicalizeSettings(settings) {
|
|
|
28746
28891
|
}
|
|
28747
28892
|
return settings;
|
|
28748
28893
|
}
|
|
28749
|
-
var LEGACY_BACKUP_DIR, TASK_ACTIVITY_LOG_ENTRY_LIMIT, TASK_ACTIVITY_LOG_OUTCOME_LIMIT, ARCHIVE_AGENT_LOG_SNAPSHOT_LIMIT, ARCHIVE_AGENT_LOG_SNIPPET_LIMIT, TaskHasDependentsError, TaskStore;
|
|
28894
|
+
var LEGACY_BACKUP_DIR, TASK_ACTIVITY_LOG_ENTRY_LIMIT, TASK_ACTIVITY_LOG_OUTCOME_LIMIT, ARCHIVE_AGENT_LOG_SNAPSHOT_LIMIT, ARCHIVE_AGENT_LOG_SNIPPET_LIMIT, storeLog, TaskHasDependentsError, TaskStore;
|
|
28750
28895
|
var init_store = __esm({
|
|
28751
28896
|
"../core/src/store.ts"() {
|
|
28752
28897
|
"use strict";
|
|
@@ -28764,11 +28909,13 @@ var init_store = __esm({
|
|
|
28764
28909
|
init_task_merge();
|
|
28765
28910
|
init_project_memory();
|
|
28766
28911
|
init_run_command();
|
|
28912
|
+
init_logger();
|
|
28767
28913
|
LEGACY_BACKUP_DIR = ".kb/backups";
|
|
28768
28914
|
TASK_ACTIVITY_LOG_ENTRY_LIMIT = 1e3;
|
|
28769
28915
|
TASK_ACTIVITY_LOG_OUTCOME_LIMIT = 4e3;
|
|
28770
28916
|
ARCHIVE_AGENT_LOG_SNAPSHOT_LIMIT = 25;
|
|
28771
28917
|
ARCHIVE_AGENT_LOG_SNIPPET_LIMIT = 160;
|
|
28918
|
+
storeLog = createLogger("task-store");
|
|
28772
28919
|
TaskHasDependentsError = class extends Error {
|
|
28773
28920
|
taskId;
|
|
28774
28921
|
dependentIds;
|
|
@@ -29478,45 +29625,53 @@ ${recentText}` : void 0
|
|
|
29478
29625
|
*/
|
|
29479
29626
|
setupActivityLogListeners() {
|
|
29480
29627
|
this.on("task:created", (task) => {
|
|
29481
|
-
this.
|
|
29482
|
-
|
|
29483
|
-
|
|
29484
|
-
|
|
29485
|
-
|
|
29486
|
-
|
|
29487
|
-
|
|
29628
|
+
this.recordActivityFromListener(
|
|
29629
|
+
{
|
|
29630
|
+
type: "task:created",
|
|
29631
|
+
taskId: task.id,
|
|
29632
|
+
taskTitle: task.title,
|
|
29633
|
+
details: `Task ${task.id} created${task.title ? `: ${task.title}` : ""}`
|
|
29634
|
+
},
|
|
29635
|
+
"task:created"
|
|
29636
|
+
);
|
|
29488
29637
|
});
|
|
29489
29638
|
this.on("task:moved", (data) => {
|
|
29490
|
-
this.
|
|
29491
|
-
|
|
29492
|
-
|
|
29493
|
-
|
|
29494
|
-
|
|
29495
|
-
|
|
29496
|
-
|
|
29497
|
-
|
|
29639
|
+
this.recordActivityFromListener(
|
|
29640
|
+
{
|
|
29641
|
+
type: "task:moved",
|
|
29642
|
+
taskId: data.task.id,
|
|
29643
|
+
taskTitle: data.task.title,
|
|
29644
|
+
details: `Task ${data.task.id} moved: ${data.from} \u2192 ${data.to}`,
|
|
29645
|
+
metadata: { from: data.from, to: data.to }
|
|
29646
|
+
},
|
|
29647
|
+
"task:moved"
|
|
29648
|
+
);
|
|
29498
29649
|
});
|
|
29499
29650
|
this.on("task:merged", (result) => {
|
|
29500
29651
|
const status = result.merged ? "successfully merged" : "merge attempted";
|
|
29501
|
-
this.
|
|
29502
|
-
|
|
29503
|
-
|
|
29504
|
-
|
|
29505
|
-
|
|
29506
|
-
|
|
29507
|
-
|
|
29508
|
-
|
|
29652
|
+
this.recordActivityFromListener(
|
|
29653
|
+
{
|
|
29654
|
+
type: "task:merged",
|
|
29655
|
+
taskId: result.task.id,
|
|
29656
|
+
taskTitle: result.task.title,
|
|
29657
|
+
details: `Task ${result.task.id} ${status} to main`,
|
|
29658
|
+
metadata: { merged: result.merged, branch: result.branch }
|
|
29659
|
+
},
|
|
29660
|
+
"task:merged"
|
|
29661
|
+
);
|
|
29509
29662
|
});
|
|
29510
29663
|
this.on("task:updated", (task) => {
|
|
29511
29664
|
if (task.status === "failed") {
|
|
29512
|
-
this.
|
|
29513
|
-
|
|
29514
|
-
|
|
29515
|
-
|
|
29516
|
-
|
|
29517
|
-
|
|
29518
|
-
|
|
29519
|
-
|
|
29665
|
+
this.recordActivityFromListener(
|
|
29666
|
+
{
|
|
29667
|
+
type: "task:failed",
|
|
29668
|
+
taskId: task.id,
|
|
29669
|
+
taskTitle: task.title,
|
|
29670
|
+
details: `Task ${task.id} failed${task.error ? `: ${task.error}` : ""}`,
|
|
29671
|
+
metadata: task.error ? { error: task.error } : void 0
|
|
29672
|
+
},
|
|
29673
|
+
"task:updated"
|
|
29674
|
+
);
|
|
29520
29675
|
}
|
|
29521
29676
|
});
|
|
29522
29677
|
this.on("settings:updated", (data) => {
|
|
@@ -29534,21 +29689,35 @@ ${recentText}` : void 0
|
|
|
29534
29689
|
importantChanges.push(`engine pause ${data.settings.enginePaused ? "enabled" : "disabled"}`);
|
|
29535
29690
|
}
|
|
29536
29691
|
if (importantChanges.length > 0) {
|
|
29537
|
-
this.
|
|
29538
|
-
|
|
29539
|
-
|
|
29540
|
-
|
|
29541
|
-
|
|
29542
|
-
|
|
29692
|
+
this.recordActivityFromListener(
|
|
29693
|
+
{
|
|
29694
|
+
type: "settings:updated",
|
|
29695
|
+
details: `Settings updated: ${importantChanges.join(", ")}`,
|
|
29696
|
+
metadata: { changes: importantChanges }
|
|
29697
|
+
},
|
|
29698
|
+
"settings:updated"
|
|
29699
|
+
);
|
|
29543
29700
|
}
|
|
29544
29701
|
});
|
|
29545
29702
|
this.on("task:deleted", (task) => {
|
|
29546
|
-
this.
|
|
29547
|
-
|
|
29548
|
-
|
|
29549
|
-
|
|
29550
|
-
|
|
29551
|
-
|
|
29703
|
+
this.recordActivityFromListener(
|
|
29704
|
+
{
|
|
29705
|
+
type: "task:deleted",
|
|
29706
|
+
taskId: task.id,
|
|
29707
|
+
taskTitle: task.title,
|
|
29708
|
+
details: `Task ${task.id} deleted${task.title ? `: ${task.title}` : ""}`
|
|
29709
|
+
},
|
|
29710
|
+
"task:deleted"
|
|
29711
|
+
);
|
|
29712
|
+
});
|
|
29713
|
+
}
|
|
29714
|
+
recordActivityFromListener(entry, sourceEvent) {
|
|
29715
|
+
this.recordActivity(entry).catch((err) => {
|
|
29716
|
+
storeLog.warn("Activity logging listener failed", {
|
|
29717
|
+
sourceEvent,
|
|
29718
|
+
type: entry.type,
|
|
29719
|
+
taskId: entry.taskId,
|
|
29720
|
+
error: err instanceof Error ? err.message : String(err)
|
|
29552
29721
|
});
|
|
29553
29722
|
});
|
|
29554
29723
|
}
|
|
@@ -30070,7 +30239,11 @@ ${recentText}` : void 0
|
|
|
30070
30239
|
if (defaultOnSteps.length > 0) {
|
|
30071
30240
|
resolvedWorkflowSteps = defaultOnSteps;
|
|
30072
30241
|
}
|
|
30073
|
-
} catch {
|
|
30242
|
+
} catch (err) {
|
|
30243
|
+
storeLog.warn("Failed to auto-apply default workflow steps during task creation", {
|
|
30244
|
+
error: err instanceof Error ? err.message : String(err),
|
|
30245
|
+
descriptionLength: input.description.length
|
|
30246
|
+
});
|
|
30074
30247
|
}
|
|
30075
30248
|
} else if (input.enabledWorkflowSteps.length === 0) {
|
|
30076
30249
|
resolvedWorkflowSteps = void 0;
|
|
@@ -30088,13 +30261,26 @@ ${recentText}` : void 0
|
|
|
30088
30261
|
}
|
|
30089
30262
|
}
|
|
30090
30263
|
} catch (err) {
|
|
30091
|
-
const errorMsg = err instanceof Error ? err.message : String(err);
|
|
30092
30264
|
const autoEnabled = options?.settings?.autoSummarizeTitles === true;
|
|
30093
|
-
|
|
30094
|
-
|
|
30265
|
+
const errorMessage = err instanceof Error ? err.message : String(err);
|
|
30266
|
+
storeLog.warn(
|
|
30267
|
+
`Title summarization failed for task ${id}: ${errorMessage} (desc length: ${input.description.length}, auto-summarize: ${autoEnabled})`,
|
|
30268
|
+
{
|
|
30269
|
+
taskId: id,
|
|
30270
|
+
descriptionLength: input.description.length,
|
|
30271
|
+
autoSummarizeEnabled: autoEnabled,
|
|
30272
|
+
error: errorMessage
|
|
30273
|
+
}
|
|
30095
30274
|
);
|
|
30096
30275
|
}
|
|
30097
|
-
}).catch(() => {
|
|
30276
|
+
}).catch((err) => {
|
|
30277
|
+
const autoEnabled = options?.settings?.autoSummarizeTitles === true;
|
|
30278
|
+
storeLog.error("Unexpected title summarization promise-chain failure", {
|
|
30279
|
+
taskId: id,
|
|
30280
|
+
descriptionLength: input.description.length,
|
|
30281
|
+
autoSummarizeEnabled: autoEnabled,
|
|
30282
|
+
error: err instanceof Error ? err.message : String(err)
|
|
30283
|
+
});
|
|
30098
30284
|
});
|
|
30099
30285
|
}
|
|
30100
30286
|
return task;
|
|
@@ -30361,26 +30547,46 @@ ${newTask.description}
|
|
|
30361
30547
|
if (sanitizedTokens.length === 0) {
|
|
30362
30548
|
return this.listTasks(options);
|
|
30363
30549
|
}
|
|
30364
|
-
const ftsQuery = sanitizedTokens.map((token) => {
|
|
30365
|
-
if (/[":(){}*^+-]/.test(token)) {
|
|
30366
|
-
return `"${token.replace(/"/g, '\\"')}"`;
|
|
30367
|
-
}
|
|
30368
|
-
return token;
|
|
30369
|
-
}).join(" OR ");
|
|
30370
30550
|
const limit = options?.limit ?? -1;
|
|
30371
30551
|
const offset = options?.offset ?? 0;
|
|
30372
30552
|
const offsetClause = offset > 0 ? ` OFFSET ${offset}` : "";
|
|
30373
30553
|
const includeArchived = options?.includeArchived ?? true;
|
|
30374
|
-
const
|
|
30375
|
-
const selectClause = this.getTaskSelectClause(
|
|
30376
|
-
|
|
30377
|
-
|
|
30378
|
-
|
|
30379
|
-
|
|
30380
|
-
|
|
30381
|
-
|
|
30382
|
-
|
|
30383
|
-
|
|
30554
|
+
const slim = options?.slim ?? false;
|
|
30555
|
+
const selectClause = this.getTaskSelectClause(slim, "t");
|
|
30556
|
+
let rows;
|
|
30557
|
+
if (this.db.fts5Available) {
|
|
30558
|
+
const ftsQuery = sanitizedTokens.map((token) => {
|
|
30559
|
+
if (/[":(){}*^+-]/.test(token)) {
|
|
30560
|
+
return `"${token.replace(/"/g, '\\"')}"`;
|
|
30561
|
+
}
|
|
30562
|
+
return token;
|
|
30563
|
+
}).join(" OR ");
|
|
30564
|
+
const whereClause = includeArchived ? "" : ` AND t."column" != 'archived'`;
|
|
30565
|
+
rows = this.db.prepare(`
|
|
30566
|
+
SELECT ${selectClause} FROM tasks t
|
|
30567
|
+
JOIN tasks_fts fts ON t.rowid = fts.rowid
|
|
30568
|
+
WHERE tasks_fts MATCH ?
|
|
30569
|
+
${whereClause}
|
|
30570
|
+
ORDER BY rank
|
|
30571
|
+
LIMIT ${limit >= 0 ? limit : -1}${offsetClause}
|
|
30572
|
+
`).all(ftsQuery);
|
|
30573
|
+
} else {
|
|
30574
|
+
const searchColumns = ["id", "title", "description", "comments"];
|
|
30575
|
+
const perTokenClause = `(${searchColumns.map((c) => `t."${c}" LIKE ? ESCAPE '\\'`).join(" OR ")})`;
|
|
30576
|
+
const whereTokens = sanitizedTokens.map(() => perTokenClause).join(" OR ");
|
|
30577
|
+
const params = [];
|
|
30578
|
+
for (const token of sanitizedTokens) {
|
|
30579
|
+
const pattern = `%${token.replace(/[\\%_]/g, "\\$&")}%`;
|
|
30580
|
+
for (let i = 0; i < searchColumns.length; i++) params.push(pattern);
|
|
30581
|
+
}
|
|
30582
|
+
const archivedClause = includeArchived ? "" : ` AND t."column" != 'archived'`;
|
|
30583
|
+
rows = this.db.prepare(`
|
|
30584
|
+
SELECT ${selectClause} FROM tasks t
|
|
30585
|
+
WHERE (${whereTokens})${archivedClause}
|
|
30586
|
+
ORDER BY t.createdAt ASC
|
|
30587
|
+
LIMIT ${limit >= 0 ? limit : -1}${offsetClause}
|
|
30588
|
+
`).all(...params);
|
|
30589
|
+
}
|
|
30384
30590
|
const activeMatches = await Promise.all(rows.map(async (row) => {
|
|
30385
30591
|
const task = this.rowToTask(row);
|
|
30386
30592
|
if (task.steps.length > 0) {
|
|
@@ -30389,7 +30595,7 @@ ${newTask.description}
|
|
|
30389
30595
|
const steps = await this.parseStepsFromPrompt(task.id);
|
|
30390
30596
|
return steps.length > 0 ? { ...task, steps } : task;
|
|
30391
30597
|
}));
|
|
30392
|
-
const archiveMatches = includeArchived ? this.archiveDb.search(
|
|
30598
|
+
const archiveMatches = includeArchived ? this.archiveDb.search(trimmedQuery, limit >= 0 ? limit : 100).map((entry) => this.archiveEntryToTask(entry, slim)) : [];
|
|
30393
30599
|
const matches = [...activeMatches, ...archiveMatches];
|
|
30394
30600
|
return limit >= 0 ? matches.slice(0, limit) : matches;
|
|
30395
30601
|
}
|
|
@@ -31525,9 +31731,17 @@ ${task.description}
|
|
|
31525
31731
|
try {
|
|
31526
31732
|
this.watcher = watch(this.tasksDir, { recursive: true }, (_event, _filename) => {
|
|
31527
31733
|
});
|
|
31528
|
-
this.watcher.on("error", () => {
|
|
31734
|
+
this.watcher.on("error", (err) => {
|
|
31735
|
+
storeLog.warn("fs.watch emitted an error; polling will continue", {
|
|
31736
|
+
error: err instanceof Error ? err.message : String(err),
|
|
31737
|
+
tasksDir: this.tasksDir
|
|
31738
|
+
});
|
|
31739
|
+
});
|
|
31740
|
+
} catch (err) {
|
|
31741
|
+
storeLog.warn("fs.watch unavailable; falling back to polling-only updates", {
|
|
31742
|
+
error: err instanceof Error ? err.message : String(err),
|
|
31743
|
+
tasksDir: this.tasksDir
|
|
31529
31744
|
});
|
|
31530
|
-
} catch {
|
|
31531
31745
|
}
|
|
31532
31746
|
this.pollInterval = setInterval(() => {
|
|
31533
31747
|
void this.checkForChanges();
|
|
@@ -31583,9 +31797,17 @@ ${task.description}
|
|
|
31583
31797
|
}
|
|
31584
31798
|
const elapsed = Date.now() - startTime;
|
|
31585
31799
|
if (elapsed > 100) {
|
|
31586
|
-
|
|
31800
|
+
storeLog.warn("checkForChanges took longer than expected", {
|
|
31801
|
+
elapsedMs: elapsed,
|
|
31802
|
+
thresholdMs: 100
|
|
31803
|
+
});
|
|
31587
31804
|
}
|
|
31588
|
-
} catch {
|
|
31805
|
+
} catch (err) {
|
|
31806
|
+
storeLog.warn("checkForChanges poll cycle failed", {
|
|
31807
|
+
lastKnownModified: this.lastKnownModified,
|
|
31808
|
+
lastPollTime: this.lastPollTime,
|
|
31809
|
+
error: err instanceof Error ? err.message : String(err)
|
|
31810
|
+
});
|
|
31589
31811
|
} finally {
|
|
31590
31812
|
this.pollingInProgress = false;
|
|
31591
31813
|
}
|
|
@@ -32840,7 +33062,15 @@ ${notificationsSection}
|
|
|
32840
33062
|
);
|
|
32841
33063
|
this.db.bumpLastModified();
|
|
32842
33064
|
} catch (err) {
|
|
32843
|
-
|
|
33065
|
+
storeLog.error("Failed to record activity", {
|
|
33066
|
+
id: fullEntry.id,
|
|
33067
|
+
type: fullEntry.type,
|
|
33068
|
+
taskId: fullEntry.taskId,
|
|
33069
|
+
taskTitle: fullEntry.taskTitle,
|
|
33070
|
+
detailsLength: fullEntry.details.length,
|
|
33071
|
+
hasMetadata: fullEntry.metadata !== void 0,
|
|
33072
|
+
error: err instanceof Error ? err.message : String(err)
|
|
33073
|
+
});
|
|
32844
33074
|
}
|
|
32845
33075
|
return fullEntry;
|
|
32846
33076
|
}
|
|
@@ -33822,27 +34052,6 @@ var init_routine_store = __esm({
|
|
|
33822
34052
|
}
|
|
33823
34053
|
});
|
|
33824
34054
|
|
|
33825
|
-
// ../core/src/logger.ts
|
|
33826
|
-
function createLogger(prefix) {
|
|
33827
|
-
const tag = `[${prefix}]`;
|
|
33828
|
-
return {
|
|
33829
|
-
log(message, ...args) {
|
|
33830
|
-
console.error(`${tag} ${message}`, ...args);
|
|
33831
|
-
},
|
|
33832
|
-
warn(message, ...args) {
|
|
33833
|
-
console.warn(`${tag} ${message}`, ...args);
|
|
33834
|
-
},
|
|
33835
|
-
error(message, ...args) {
|
|
33836
|
-
console.error(`${tag} ${message}`, ...args);
|
|
33837
|
-
}
|
|
33838
|
-
};
|
|
33839
|
-
}
|
|
33840
|
-
var init_logger = __esm({
|
|
33841
|
-
"../core/src/logger.ts"() {
|
|
33842
|
-
"use strict";
|
|
33843
|
-
}
|
|
33844
|
-
});
|
|
33845
|
-
|
|
33846
34055
|
// ../core/src/plugin-loader.ts
|
|
33847
34056
|
import { isAbsolute as isAbsolute5, resolve as resolve8 } from "node:path";
|
|
33848
34057
|
import { EventEmitter as EventEmitter13 } from "node:events";
|
|
@@ -37141,9 +37350,9 @@ var require_pump = __commonJS({
|
|
|
37141
37350
|
"use strict";
|
|
37142
37351
|
var once3 = require_once();
|
|
37143
37352
|
var eos = require_end_of_stream();
|
|
37144
|
-
var
|
|
37353
|
+
var fs2;
|
|
37145
37354
|
try {
|
|
37146
|
-
|
|
37355
|
+
fs2 = __require("fs");
|
|
37147
37356
|
} catch (e) {
|
|
37148
37357
|
}
|
|
37149
37358
|
var noop = function() {
|
|
@@ -37154,8 +37363,8 @@ var require_pump = __commonJS({
|
|
|
37154
37363
|
};
|
|
37155
37364
|
var isFS = function(stream) {
|
|
37156
37365
|
if (!ancient) return false;
|
|
37157
|
-
if (!
|
|
37158
|
-
return (stream instanceof (
|
|
37366
|
+
if (!fs2) return false;
|
|
37367
|
+
return (stream instanceof (fs2.ReadStream || noop) || stream instanceof (fs2.WriteStream || noop)) && isFn(stream.close);
|
|
37159
37368
|
};
|
|
37160
37369
|
var isRequest = function(stream) {
|
|
37161
37370
|
return stream.setHeader && isFn(stream.abort);
|
|
@@ -37369,7 +37578,7 @@ var require_pend = __commonJS({
|
|
|
37369
37578
|
var require_fd_slicer = __commonJS({
|
|
37370
37579
|
"../../node_modules/.pnpm/fd-slicer@1.1.0/node_modules/fd-slicer/index.js"(exports) {
|
|
37371
37580
|
"use strict";
|
|
37372
|
-
var
|
|
37581
|
+
var fs2 = __require("fs");
|
|
37373
37582
|
var util = __require("util");
|
|
37374
37583
|
var stream = __require("stream");
|
|
37375
37584
|
var Readable2 = stream.Readable;
|
|
@@ -37394,7 +37603,7 @@ var require_fd_slicer = __commonJS({
|
|
|
37394
37603
|
FdSlicer.prototype.read = function(buffer, offset, length, position, callback) {
|
|
37395
37604
|
var self2 = this;
|
|
37396
37605
|
self2.pend.go(function(cb) {
|
|
37397
|
-
|
|
37606
|
+
fs2.read(self2.fd, buffer, offset, length, position, function(err, bytesRead, buffer2) {
|
|
37398
37607
|
cb();
|
|
37399
37608
|
callback(err, bytesRead, buffer2);
|
|
37400
37609
|
});
|
|
@@ -37403,7 +37612,7 @@ var require_fd_slicer = __commonJS({
|
|
|
37403
37612
|
FdSlicer.prototype.write = function(buffer, offset, length, position, callback) {
|
|
37404
37613
|
var self2 = this;
|
|
37405
37614
|
self2.pend.go(function(cb) {
|
|
37406
|
-
|
|
37615
|
+
fs2.write(self2.fd, buffer, offset, length, position, function(err, written, buffer2) {
|
|
37407
37616
|
cb();
|
|
37408
37617
|
callback(err, written, buffer2);
|
|
37409
37618
|
});
|
|
@@ -37424,7 +37633,7 @@ var require_fd_slicer = __commonJS({
|
|
|
37424
37633
|
if (self2.refCount > 0) return;
|
|
37425
37634
|
if (self2.refCount < 0) throw new Error("invalid unref");
|
|
37426
37635
|
if (self2.autoClose) {
|
|
37427
|
-
|
|
37636
|
+
fs2.close(self2.fd, onCloseDone);
|
|
37428
37637
|
}
|
|
37429
37638
|
function onCloseDone(err) {
|
|
37430
37639
|
if (err) {
|
|
@@ -37461,7 +37670,7 @@ var require_fd_slicer = __commonJS({
|
|
|
37461
37670
|
self2.context.pend.go(function(cb) {
|
|
37462
37671
|
if (self2.destroyed) return cb();
|
|
37463
37672
|
var buffer = new Buffer(toRead);
|
|
37464
|
-
|
|
37673
|
+
fs2.read(self2.context.fd, buffer, 0, toRead, self2.pos, function(err, bytesRead) {
|
|
37465
37674
|
if (err) {
|
|
37466
37675
|
self2.destroy(err);
|
|
37467
37676
|
} else if (bytesRead === 0) {
|
|
@@ -37508,7 +37717,7 @@ var require_fd_slicer = __commonJS({
|
|
|
37508
37717
|
}
|
|
37509
37718
|
self2.context.pend.go(function(cb) {
|
|
37510
37719
|
if (self2.destroyed) return cb();
|
|
37511
|
-
|
|
37720
|
+
fs2.write(self2.context.fd, buffer, 0, buffer.length, self2.pos, function(err2, bytes) {
|
|
37512
37721
|
if (err2) {
|
|
37513
37722
|
self2.destroy();
|
|
37514
37723
|
cb();
|
|
@@ -37937,7 +38146,7 @@ var require_buffer_crc32 = __commonJS({
|
|
|
37937
38146
|
var require_yauzl = __commonJS({
|
|
37938
38147
|
"../../node_modules/.pnpm/yauzl@2.10.0/node_modules/yauzl/index.js"(exports) {
|
|
37939
38148
|
"use strict";
|
|
37940
|
-
var
|
|
38149
|
+
var fs2 = __require("fs");
|
|
37941
38150
|
var zlib = __require("zlib");
|
|
37942
38151
|
var fd_slicer = require_fd_slicer();
|
|
37943
38152
|
var crc32 = require_buffer_crc32();
|
|
@@ -37967,10 +38176,10 @@ var require_yauzl = __commonJS({
|
|
|
37967
38176
|
if (options.validateEntrySizes == null) options.validateEntrySizes = true;
|
|
37968
38177
|
if (options.strictFileNames == null) options.strictFileNames = false;
|
|
37969
38178
|
if (callback == null) callback = defaultCallback;
|
|
37970
|
-
|
|
38179
|
+
fs2.open(path4, "r", function(err, fd) {
|
|
37971
38180
|
if (err) return callback(err);
|
|
37972
38181
|
fromFd(fd, options, function(err2, zipfile) {
|
|
37973
|
-
if (err2)
|
|
38182
|
+
if (err2) fs2.close(fd, defaultCallback);
|
|
37974
38183
|
callback(err2, zipfile);
|
|
37975
38184
|
});
|
|
37976
38185
|
});
|
|
@@ -37987,7 +38196,7 @@ var require_yauzl = __commonJS({
|
|
|
37987
38196
|
if (options.validateEntrySizes == null) options.validateEntrySizes = true;
|
|
37988
38197
|
if (options.strictFileNames == null) options.strictFileNames = false;
|
|
37989
38198
|
if (callback == null) callback = defaultCallback;
|
|
37990
|
-
|
|
38199
|
+
fs2.fstat(fd, function(err, stats) {
|
|
37991
38200
|
if (err) return callback(err);
|
|
37992
38201
|
var reader = fd_slicer.createFromFd(fd, { autoClose: true });
|
|
37993
38202
|
fromRandomAccessReader(reader, stats.size, options, callback);
|
|
@@ -38568,7 +38777,7 @@ var require_extract_zip = __commonJS({
|
|
|
38568
38777
|
"../../node_modules/.pnpm/extract-zip@2.0.1/node_modules/extract-zip/index.js"(exports, module) {
|
|
38569
38778
|
"use strict";
|
|
38570
38779
|
var debug = require_src()("extract-zip");
|
|
38571
|
-
var { createWriteStream: createWriteStream2, promises:
|
|
38780
|
+
var { createWriteStream: createWriteStream2, promises: fs2 } = __require("fs");
|
|
38572
38781
|
var getStream = require_get_stream();
|
|
38573
38782
|
var path4 = __require("path");
|
|
38574
38783
|
var { promisify: promisify14 } = __require("util");
|
|
@@ -38609,8 +38818,8 @@ var require_extract_zip = __commonJS({
|
|
|
38609
38818
|
}
|
|
38610
38819
|
const destDir = path4.dirname(path4.join(this.opts.dir, entry.fileName));
|
|
38611
38820
|
try {
|
|
38612
|
-
await
|
|
38613
|
-
const canonicalDestDir = await
|
|
38821
|
+
await fs2.mkdir(destDir, { recursive: true });
|
|
38822
|
+
const canonicalDestDir = await fs2.realpath(destDir);
|
|
38614
38823
|
const relativeDestDir = path4.relative(this.opts.dir, canonicalDestDir);
|
|
38615
38824
|
if (relativeDestDir.split(path4.sep).includes("..")) {
|
|
38616
38825
|
throw new Error(`Out of bound path "${canonicalDestDir}" found while processing file ${entry.fileName}`);
|
|
@@ -38654,14 +38863,14 @@ var require_extract_zip = __commonJS({
|
|
|
38654
38863
|
mkdirOptions.mode = procMode;
|
|
38655
38864
|
}
|
|
38656
38865
|
debug("mkdir", { dir: destDir, ...mkdirOptions });
|
|
38657
|
-
await
|
|
38866
|
+
await fs2.mkdir(destDir, mkdirOptions);
|
|
38658
38867
|
if (isDir) return;
|
|
38659
38868
|
debug("opening read stream", dest);
|
|
38660
38869
|
const readStream = await promisify14(this.zipfile.openReadStream.bind(this.zipfile))(entry);
|
|
38661
38870
|
if (symlink) {
|
|
38662
38871
|
const link = await getStream(readStream);
|
|
38663
38872
|
debug("creating symlink", link, dest);
|
|
38664
|
-
await
|
|
38873
|
+
await fs2.symlink(link, dest);
|
|
38665
38874
|
} else {
|
|
38666
38875
|
await pipeline(readStream, createWriteStream2(dest, { mode: procMode }));
|
|
38667
38876
|
}
|
|
@@ -38693,8 +38902,8 @@ var require_extract_zip = __commonJS({
|
|
|
38693
38902
|
if (!path4.isAbsolute(opts.dir)) {
|
|
38694
38903
|
throw new Error("Target directory is expected to be absolute");
|
|
38695
38904
|
}
|
|
38696
|
-
await
|
|
38697
|
-
opts.dir = await
|
|
38905
|
+
await fs2.mkdir(opts.dir, { recursive: true });
|
|
38906
|
+
opts.dir = await fs2.realpath(opts.dir);
|
|
38698
38907
|
return new Extractor(zipPath, opts).extract();
|
|
38699
38908
|
};
|
|
38700
38909
|
}
|
|
@@ -45553,14 +45762,14 @@ var require_parser = __commonJS({
|
|
|
45553
45762
|
case "scalar":
|
|
45554
45763
|
case "single-quoted-scalar":
|
|
45555
45764
|
case "double-quoted-scalar": {
|
|
45556
|
-
const
|
|
45765
|
+
const fs2 = this.flowScalar(this.type);
|
|
45557
45766
|
if (atNextItem || it.value) {
|
|
45558
|
-
map2.items.push({ start, key:
|
|
45767
|
+
map2.items.push({ start, key: fs2, sep: [] });
|
|
45559
45768
|
this.onKeyLine = true;
|
|
45560
45769
|
} else if (it.sep) {
|
|
45561
|
-
this.stack.push(
|
|
45770
|
+
this.stack.push(fs2);
|
|
45562
45771
|
} else {
|
|
45563
|
-
Object.assign(it, { key:
|
|
45772
|
+
Object.assign(it, { key: fs2, sep: [] });
|
|
45564
45773
|
this.onKeyLine = true;
|
|
45565
45774
|
}
|
|
45566
45775
|
return;
|
|
@@ -45688,13 +45897,13 @@ var require_parser = __commonJS({
|
|
|
45688
45897
|
case "scalar":
|
|
45689
45898
|
case "single-quoted-scalar":
|
|
45690
45899
|
case "double-quoted-scalar": {
|
|
45691
|
-
const
|
|
45900
|
+
const fs2 = this.flowScalar(this.type);
|
|
45692
45901
|
if (!it || it.value)
|
|
45693
|
-
fc.items.push({ start: [], key:
|
|
45902
|
+
fc.items.push({ start: [], key: fs2, sep: [] });
|
|
45694
45903
|
else if (it.sep)
|
|
45695
|
-
this.stack.push(
|
|
45904
|
+
this.stack.push(fs2);
|
|
45696
45905
|
else
|
|
45697
|
-
Object.assign(it, { key:
|
|
45906
|
+
Object.assign(it, { key: fs2, sep: [] });
|
|
45698
45907
|
return;
|
|
45699
45908
|
}
|
|
45700
45909
|
case "flow-map-end":
|
|
@@ -49975,7 +50184,7 @@ var require_windowsPtyAgent = __commonJS({
|
|
|
49975
50184
|
"use strict";
|
|
49976
50185
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
49977
50186
|
exports.argsToCommandLine = exports.WindowsPtyAgent = void 0;
|
|
49978
|
-
var
|
|
50187
|
+
var fs2 = __require("fs");
|
|
49979
50188
|
var os3 = __require("os");
|
|
49980
50189
|
var path4 = __require("path");
|
|
49981
50190
|
var child_process_1 = __require("child_process");
|
|
@@ -50034,7 +50243,7 @@ var require_windowsPtyAgent = __commonJS({
|
|
|
50034
50243
|
this._outSocket.on("connect", function() {
|
|
50035
50244
|
_this._outSocket.emit("ready_datapipe");
|
|
50036
50245
|
});
|
|
50037
|
-
var inSocketFD =
|
|
50246
|
+
var inSocketFD = fs2.openSync(term.conin, "w");
|
|
50038
50247
|
this._inSocket = new net_1.Socket({
|
|
50039
50248
|
fd: inSocketFD,
|
|
50040
50249
|
readable: false,
|
|
@@ -50468,7 +50677,7 @@ var require_unixTerminal = __commonJS({
|
|
|
50468
50677
|
})();
|
|
50469
50678
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
50470
50679
|
exports.UnixTerminal = void 0;
|
|
50471
|
-
var
|
|
50680
|
+
var fs2 = __require("fs");
|
|
50472
50681
|
var path4 = __require("path");
|
|
50473
50682
|
var tty = __require("tty");
|
|
50474
50683
|
var terminal_1 = require_terminal();
|
|
@@ -50731,7 +50940,7 @@ var require_unixTerminal = __commonJS({
|
|
|
50731
50940
|
return;
|
|
50732
50941
|
}
|
|
50733
50942
|
var task = this._writeQueue[0];
|
|
50734
|
-
|
|
50943
|
+
fs2.write(this._fd, task.buffer, task.offset, function(err, written) {
|
|
50735
50944
|
if (err) {
|
|
50736
50945
|
if ("code" in err && err.code === "EAGAIN") {
|
|
50737
50946
|
_this._writeImmediate = setImmediate(function() {
|
|
@@ -50793,7 +51002,8 @@ var require_lib = __commonJS({
|
|
|
50793
51002
|
import { EventEmitter as EventEmitter17 } from "events";
|
|
50794
51003
|
import * as os2 from "os";
|
|
50795
51004
|
import * as path from "path";
|
|
50796
|
-
import
|
|
51005
|
+
import * as fs from "node:fs";
|
|
51006
|
+
import { createRequire } from "node:module";
|
|
50797
51007
|
import { join as join22, dirname as dirname7 } from "node:path";
|
|
50798
51008
|
function getNativePrebuildName() {
|
|
50799
51009
|
const platform3 = process.platform === "darwin" ? "darwin" : process.platform === "linux" ? "linux" : process.platform === "win32" ? "win32" : "unknown";
|
|
@@ -50802,9 +51012,9 @@ function getNativePrebuildName() {
|
|
|
50802
51012
|
}
|
|
50803
51013
|
function findInstalledNodePtyNativeDir() {
|
|
50804
51014
|
try {
|
|
50805
|
-
const packageJsonPath =
|
|
51015
|
+
const packageJsonPath = require2.resolve("node-pty/package.json");
|
|
50806
51016
|
const nativeDir = join22(dirname7(packageJsonPath), "prebuilds", getNativePrebuildName());
|
|
50807
|
-
return
|
|
51017
|
+
return fs.existsSync(join22(nativeDir, "pty.node")) ? nativeDir : null;
|
|
50808
51018
|
} catch {
|
|
50809
51019
|
return null;
|
|
50810
51020
|
}
|
|
@@ -50830,12 +51040,11 @@ function ensureNodePtyNativePermissions() {
|
|
|
50830
51040
|
const helperPath = join22(nativeDir, "spawn-helper");
|
|
50831
51041
|
const nativeModulePath = join22(nativeDir, "pty.node");
|
|
50832
51042
|
try {
|
|
50833
|
-
|
|
50834
|
-
|
|
50835
|
-
|
|
50836
|
-
|
|
50837
|
-
|
|
50838
|
-
}
|
|
51043
|
+
fs.chmodSync(helperPath, 493);
|
|
51044
|
+
} catch {
|
|
51045
|
+
}
|
|
51046
|
+
try {
|
|
51047
|
+
fs.chmodSync(nativeModulePath, 493);
|
|
50839
51048
|
} catch (err) {
|
|
50840
51049
|
console.warn("[terminal] Failed to repair node-pty native permissions:", {
|
|
50841
51050
|
nativeDir,
|
|
@@ -50848,18 +51057,19 @@ function findStagedNativeDir() {
|
|
|
50848
51057
|
const prebuildName = getNativePrebuildName();
|
|
50849
51058
|
if (process.env.FUSION_RUNTIME_DIR) {
|
|
50850
51059
|
const envPath = join22(process.env.FUSION_RUNTIME_DIR, prebuildName);
|
|
50851
|
-
if (
|
|
51060
|
+
if (fs.existsSync(join22(envPath, "pty.node"))) {
|
|
50852
51061
|
return envPath;
|
|
50853
51062
|
}
|
|
50854
51063
|
}
|
|
50855
51064
|
const execDir = dirname7(process.execPath);
|
|
50856
51065
|
const nextToBinary = join22(execDir, "runtime", prebuildName);
|
|
50857
|
-
if (
|
|
51066
|
+
if (fs.existsSync(join22(nextToBinary, "pty.node"))) {
|
|
50858
51067
|
return nextToBinary;
|
|
50859
51068
|
}
|
|
50860
51069
|
return null;
|
|
50861
51070
|
}
|
|
50862
51071
|
async function loadPtyModule() {
|
|
51072
|
+
ensureNodePtyNativePermissions();
|
|
50863
51073
|
if (ptyModule) {
|
|
50864
51074
|
return ptyModule;
|
|
50865
51075
|
}
|
|
@@ -50874,7 +51084,7 @@ async function loadPtyModule() {
|
|
|
50874
51084
|
}
|
|
50875
51085
|
process.env.FUSION_NATIVE_ASSETS_PATH = nativeDir;
|
|
50876
51086
|
const nativePath = join22(nativeDir, "pty.node");
|
|
50877
|
-
if (
|
|
51087
|
+
if (fs.existsSync(nativePath)) {
|
|
50878
51088
|
try {
|
|
50879
51089
|
const nativeModule = { exports: {} };
|
|
50880
51090
|
process.dlopen(nativeModule, nativePath);
|
|
@@ -50886,7 +51096,6 @@ async function loadPtyModule() {
|
|
|
50886
51096
|
}
|
|
50887
51097
|
}
|
|
50888
51098
|
try {
|
|
50889
|
-
ensureNodePtyNativePermissions();
|
|
50890
51099
|
const mod = await Promise.resolve().then(() => __toESM(require_lib(), 1));
|
|
50891
51100
|
ptyModule = mod;
|
|
50892
51101
|
return ptyModule;
|
|
@@ -50912,13 +51121,14 @@ function getTerminalService(projectRoot, maxSessions) {
|
|
|
50912
51121
|
terminalServices.set(resolvedRoot, service);
|
|
50913
51122
|
return service;
|
|
50914
51123
|
}
|
|
50915
|
-
var isBunBinary, ptyModule, ptyLoadError, MAX_SCROLLBACK_SIZE, MIN_MAX_SESSIONS, MAX_MAX_SESSIONS, DEFAULT_MAX_SESSIONS, OUTPUT_THROTTLE_MS, OUTPUT_BATCH_SIZE, STALE_SESSION_THRESHOLD_MS, SESSION_ID_PATTERN, ALLOWED_SHELL_PATHS, STRIP_ENV_VARS, TerminalService, terminalServices;
|
|
51124
|
+
var isBunBinary, ptyModule, ptyLoadError, require2, MAX_SCROLLBACK_SIZE, MIN_MAX_SESSIONS, MAX_MAX_SESSIONS, DEFAULT_MAX_SESSIONS, OUTPUT_THROTTLE_MS, OUTPUT_BATCH_SIZE, STALE_SESSION_THRESHOLD_MS, SESSION_ID_PATTERN, ALLOWED_SHELL_PATHS, STRIP_ENV_VARS, TerminalService, terminalServices;
|
|
50916
51125
|
var init_terminal_service = __esm({
|
|
50917
51126
|
"../dashboard/src/terminal-service.ts"() {
|
|
50918
51127
|
"use strict";
|
|
50919
51128
|
isBunBinary = typeof Bun !== "undefined" && !!Bun.embeddedFiles;
|
|
50920
51129
|
ptyModule = null;
|
|
50921
51130
|
ptyLoadError = null;
|
|
51131
|
+
require2 = createRequire(import.meta.url);
|
|
50922
51132
|
MAX_SCROLLBACK_SIZE = 5e4;
|
|
50923
51133
|
MIN_MAX_SESSIONS = 1;
|
|
50924
51134
|
MAX_MAX_SESSIONS = 100;
|
|
@@ -51008,13 +51218,13 @@ var init_terminal_service = __esm({
|
|
|
51008
51218
|
const normalizedUserShell = this.isWindows ? userShell.toLowerCase() : userShell;
|
|
51009
51219
|
for (const allowed of allowedShells) {
|
|
51010
51220
|
const normalizedAllowed = this.isWindows ? allowed.toLowerCase() : allowed;
|
|
51011
|
-
if (normalizedAllowed === normalizedUserShell &&
|
|
51221
|
+
if (normalizedAllowed === normalizedUserShell && fs.existsSync(allowed)) {
|
|
51012
51222
|
return { shell: allowed, args: getShellArgs(allowed) };
|
|
51013
51223
|
}
|
|
51014
51224
|
}
|
|
51015
51225
|
}
|
|
51016
51226
|
for (const shell of allowedShells) {
|
|
51017
|
-
if (
|
|
51227
|
+
if (fs.existsSync(shell)) {
|
|
51018
51228
|
return { shell, args: getShellArgs(shell) };
|
|
51019
51229
|
}
|
|
51020
51230
|
}
|
|
@@ -51035,7 +51245,7 @@ var init_terminal_service = __esm({
|
|
|
51035
51245
|
detectedShell,
|
|
51036
51246
|
detectedArgs,
|
|
51037
51247
|
envShell: process.env.SHELL ?? null,
|
|
51038
|
-
allowedShells: this.getAllowedShells().filter((shellPath) =>
|
|
51248
|
+
allowedShells: this.getAllowedShells().filter((shellPath) => fs.existsSync(shellPath))
|
|
51039
51249
|
};
|
|
51040
51250
|
}
|
|
51041
51251
|
/**
|
|
@@ -51056,7 +51266,7 @@ var init_terminal_service = __esm({
|
|
|
51056
51266
|
return this.projectRoot;
|
|
51057
51267
|
}
|
|
51058
51268
|
try {
|
|
51059
|
-
const stat11 = await import("node:fs/promises").then((
|
|
51269
|
+
const stat11 = await import("node:fs/promises").then((fs2) => fs2.stat(cwd));
|
|
51060
51270
|
if (stat11.isDirectory()) {
|
|
51061
51271
|
return cwd;
|
|
51062
51272
|
}
|
|
@@ -51219,7 +51429,7 @@ var init_terminal_service = __esm({
|
|
|
51219
51429
|
addSpawnAttempt(shell, [], "retry-without-login");
|
|
51220
51430
|
}
|
|
51221
51431
|
for (const allowedShell of this.getAllowedShells()) {
|
|
51222
|
-
if (allowedShell === shell || !
|
|
51432
|
+
if (allowedShell === shell || !fs.existsSync(allowedShell)) continue;
|
|
51223
51433
|
const shellName = path.basename(allowedShell).toLowerCase().replace(".exe", "");
|
|
51224
51434
|
const fallbackArgs = shellName === "bash" || shellName === "zsh" ? [] : [];
|
|
51225
51435
|
addSpawnAttempt(allowedShell, fallbackArgs, "allowed-fallback");
|
|
@@ -59047,13 +59257,13 @@ function createLogger2(prefix) {
|
|
|
59047
59257
|
const tag = `[${prefix}]`;
|
|
59048
59258
|
return {
|
|
59049
59259
|
log(message, ...args) {
|
|
59050
|
-
console.error(`${tag} ${message}`, ...args);
|
|
59260
|
+
globalThis.console.error(`${tag} ${message}`, ...args);
|
|
59051
59261
|
},
|
|
59052
59262
|
warn(message, ...args) {
|
|
59053
|
-
console.warn(`${tag} ${message}`, ...args);
|
|
59263
|
+
globalThis.console.warn(`${tag} ${message}`, ...args);
|
|
59054
59264
|
},
|
|
59055
59265
|
error(message, ...args) {
|
|
59056
|
-
console.error(`${tag} ${message}`, ...args);
|
|
59266
|
+
globalThis.console.error(`${tag} ${message}`, ...args);
|
|
59057
59267
|
}
|
|
59058
59268
|
};
|
|
59059
59269
|
}
|
|
@@ -60371,7 +60581,6 @@ function createSkillsOverrideFromSelection(selection, options = {}) {
|
|
|
60371
60581
|
}
|
|
60372
60582
|
}
|
|
60373
60583
|
if (newDiagnostics.length > 0) {
|
|
60374
|
-
const _purpose = sessionPurpose ? `[${sessionPurpose}]` : "skills";
|
|
60375
60584
|
for (const diag of newDiagnostics) {
|
|
60376
60585
|
piLog.warn(`[skills] ${diag.type}: ${diag.message}`);
|
|
60377
60586
|
}
|
|
@@ -60441,7 +60650,7 @@ import { join as join27 } from "node:path";
|
|
|
60441
60650
|
import { AuthStorage } from "@mariozechner/pi-coding-agent";
|
|
60442
60651
|
import { getOAuthProvider } from "@mariozechner/pi-ai/oauth";
|
|
60443
60652
|
function getHomeDir2() {
|
|
60444
|
-
return process.env.HOME || process.env.USERPROFILE || homedir6();
|
|
60653
|
+
return globalThis.process.env.HOME || globalThis.process.env.USERPROFILE || homedir6();
|
|
60445
60654
|
}
|
|
60446
60655
|
function getFusionAuthPath2(home = getHomeDir2()) {
|
|
60447
60656
|
return join27(home, ".fusion", "agent", "auth.json");
|
|
@@ -60487,7 +60696,7 @@ function readLegacyCredentials(authPaths = getLegacyAuthPaths()) {
|
|
|
60487
60696
|
function resolveStoredApiKey(key) {
|
|
60488
60697
|
if (!key)
|
|
60489
60698
|
return void 0;
|
|
60490
|
-
return process.env[key] ?? key;
|
|
60699
|
+
return globalThis.process.env[key] ?? key;
|
|
60491
60700
|
}
|
|
60492
60701
|
function resolveOAuthApiKey(providerId, credential) {
|
|
60493
60702
|
if (credential.type !== "oauth" || typeof credential.access !== "string" || typeof credential.refresh !== "string" || typeof credential.expires !== "number" || Date.now() >= credential.expires) {
|
|
@@ -60790,8 +60999,8 @@ function createReadOnlyPiSettingsView(cwd, agentDir) {
|
|
|
60790
60999
|
const fusionProjectSettings = readJsonObject2(join28(projectRoot, ".fusion", "settings.json"));
|
|
60791
61000
|
const mergedSettings = { ...globalSettings, ...fusionProjectSettings };
|
|
60792
61001
|
return {
|
|
60793
|
-
getGlobalSettings: () => structuredClone(globalSettings),
|
|
60794
|
-
getProjectSettings: () => structuredClone(fusionProjectSettings),
|
|
61002
|
+
getGlobalSettings: () => globalThis.structuredClone(globalSettings),
|
|
61003
|
+
getProjectSettings: () => globalThis.structuredClone(fusionProjectSettings),
|
|
60795
61004
|
getNpmCommand: () => Array.isArray(mergedSettings.npmCommand) ? [...mergedSettings.npmCommand] : void 0
|
|
60796
61005
|
};
|
|
60797
61006
|
}
|
|
@@ -60910,9 +61119,7 @@ function wrapToolsWithBoundary(tools, worktreePath, projectRoot) {
|
|
|
60910
61119
|
return {
|
|
60911
61120
|
...tool,
|
|
60912
61121
|
execute: async (...args) => {
|
|
60913
|
-
const _toolCallId = args[0];
|
|
60914
61122
|
const params = args[1];
|
|
60915
|
-
const _signal = args[2];
|
|
60916
61123
|
const pathArg = params.path;
|
|
60917
61124
|
if (pathArg && !isWorktreeAllowedPath(worktreePath, projectRoot, pathArg)) {
|
|
60918
61125
|
const relToProject = relative4(projectRoot, pathArg);
|
|
@@ -65286,7 +65493,7 @@ async function aiMergeTask(store, rootDir, taskId, options = {}) {
|
|
|
65286
65493
|
} catch (error) {
|
|
65287
65494
|
if (error.name === "VerificationError") {
|
|
65288
65495
|
const verificationErr = error;
|
|
65289
|
-
const maxFixRetries = Math.min(settings.verificationFixRetries ??
|
|
65496
|
+
const maxFixRetries = Math.min(settings.verificationFixRetries ?? 3, 3);
|
|
65290
65497
|
if (maxFixRetries > 0 && (verificationErr.verificationResult.testResult || verificationErr.verificationResult.buildResult)) {
|
|
65291
65498
|
mergerLog.log(`${taskId}: deterministic verification failed \u2014 attempting in-merge fix (up to ${maxFixRetries} attempts)`);
|
|
65292
65499
|
await store.logEntry(taskId, `Verification failed during merge \u2014 attempting in-merge fix (up to ${maxFixRetries} attempts)`);
|
|
@@ -65331,7 +65538,7 @@ async function aiMergeTask(store, rootDir, taskId, options = {}) {
|
|
|
65331
65538
|
throw error;
|
|
65332
65539
|
}
|
|
65333
65540
|
if (error.message?.includes("Build verification failed")) {
|
|
65334
|
-
const maxFixRetries = Math.min(settings.verificationFixRetries ??
|
|
65541
|
+
const maxFixRetries = Math.min(settings.verificationFixRetries ?? 3, 3);
|
|
65335
65542
|
if (maxFixRetries > 0 && (effectiveTestCommand || effectiveBuildCommand)) {
|
|
65336
65543
|
mergerLog.log(`${taskId}: build verification failed \u2014 attempting in-merge fix`);
|
|
65337
65544
|
await store.logEntry(taskId, `Build verification failed during merge \u2014 attempting in-merge fix`);
|
|
@@ -67130,6 +67337,36 @@ function buildReducedStepPrompt(taskDetail, stepIndex) {
|
|
|
67130
67337
|
];
|
|
67131
67338
|
return parts.join("\n").replace(/\n{3,}/g, "\n\n");
|
|
67132
67339
|
}
|
|
67340
|
+
function resolveExecutorModelPair(taskModelProvider, taskModelId, settings) {
|
|
67341
|
+
if (taskModelProvider && taskModelId) {
|
|
67342
|
+
return { provider: taskModelProvider, modelId: taskModelId };
|
|
67343
|
+
}
|
|
67344
|
+
if (settings?.executionProvider && settings?.executionModelId) {
|
|
67345
|
+
return {
|
|
67346
|
+
provider: settings.executionProvider,
|
|
67347
|
+
modelId: settings.executionModelId
|
|
67348
|
+
};
|
|
67349
|
+
}
|
|
67350
|
+
if (settings?.executionGlobalProvider && settings?.executionGlobalModelId) {
|
|
67351
|
+
return {
|
|
67352
|
+
provider: settings.executionGlobalProvider,
|
|
67353
|
+
modelId: settings.executionGlobalModelId
|
|
67354
|
+
};
|
|
67355
|
+
}
|
|
67356
|
+
if (settings?.defaultProviderOverride && settings?.defaultModelIdOverride) {
|
|
67357
|
+
return {
|
|
67358
|
+
provider: settings.defaultProviderOverride,
|
|
67359
|
+
modelId: settings.defaultModelIdOverride
|
|
67360
|
+
};
|
|
67361
|
+
}
|
|
67362
|
+
if (settings?.defaultProvider && settings?.defaultModelId) {
|
|
67363
|
+
return {
|
|
67364
|
+
provider: settings.defaultProvider,
|
|
67365
|
+
modelId: settings.defaultModelId
|
|
67366
|
+
};
|
|
67367
|
+
}
|
|
67368
|
+
return { provider: void 0, modelId: void 0 };
|
|
67369
|
+
}
|
|
67133
67370
|
function sleep2(ms) {
|
|
67134
67371
|
return new Promise((resolve29) => setTimeout(resolve29, ms));
|
|
67135
67372
|
}
|
|
@@ -67322,8 +67559,11 @@ var init_step_session_executor = __esm({
|
|
|
67322
67559
|
createSendMessageTool(this.options.messageStore, taskDetail.assignedAgentId),
|
|
67323
67560
|
createReadMessagesTool(this.options.messageStore, taskDetail.assignedAgentId)
|
|
67324
67561
|
] : [];
|
|
67325
|
-
const
|
|
67326
|
-
|
|
67562
|
+
const { provider: executorProvider, modelId: executorModelId } = resolveExecutorModelPair(
|
|
67563
|
+
taskDetail.modelProvider,
|
|
67564
|
+
taskDetail.modelId,
|
|
67565
|
+
settings
|
|
67566
|
+
);
|
|
67327
67567
|
const createResult = await createFnAgent5({
|
|
67328
67568
|
cwd: worktreePath,
|
|
67329
67569
|
systemPrompt: `You are an AI agent executing step ${stepIndex} of task ${taskDetail.id}. Follow instructions precisely.`,
|
|
@@ -67757,6 +67997,36 @@ function getExecutorSystemPrompt(settings) {
|
|
|
67757
67997
|
const customPrompt = resolveAgentPrompt("executor", settings.agentPrompts);
|
|
67758
67998
|
return customPrompt || EXECUTOR_SYSTEM_PROMPT;
|
|
67759
67999
|
}
|
|
68000
|
+
function resolveExecutorModelPair2(taskModelProvider, taskModelId, settings) {
|
|
68001
|
+
if (taskModelProvider && taskModelId) {
|
|
68002
|
+
return { provider: taskModelProvider, modelId: taskModelId };
|
|
68003
|
+
}
|
|
68004
|
+
if (settings?.executionProvider && settings?.executionModelId) {
|
|
68005
|
+
return {
|
|
68006
|
+
provider: settings.executionProvider,
|
|
68007
|
+
modelId: settings.executionModelId
|
|
68008
|
+
};
|
|
68009
|
+
}
|
|
68010
|
+
if (settings?.executionGlobalProvider && settings?.executionGlobalModelId) {
|
|
68011
|
+
return {
|
|
68012
|
+
provider: settings.executionGlobalProvider,
|
|
68013
|
+
modelId: settings.executionGlobalModelId
|
|
68014
|
+
};
|
|
68015
|
+
}
|
|
68016
|
+
if (settings?.defaultProviderOverride && settings?.defaultModelIdOverride) {
|
|
68017
|
+
return {
|
|
68018
|
+
provider: settings.defaultProviderOverride,
|
|
68019
|
+
modelId: settings.defaultModelIdOverride
|
|
68020
|
+
};
|
|
68021
|
+
}
|
|
68022
|
+
if (settings?.defaultProvider && settings?.defaultModelId) {
|
|
68023
|
+
return {
|
|
68024
|
+
provider: settings.defaultProvider,
|
|
68025
|
+
modelId: settings.defaultModelId
|
|
68026
|
+
};
|
|
68027
|
+
}
|
|
68028
|
+
return { provider: void 0, modelId: void 0 };
|
|
68029
|
+
}
|
|
67760
68030
|
function formatTimestamp2(iso) {
|
|
67761
68031
|
const date = new Date(iso);
|
|
67762
68032
|
const now = /* @__PURE__ */ new Date();
|
|
@@ -67913,7 +68183,7 @@ function detectReviewHandoffIntent(commentText) {
|
|
|
67913
68183
|
];
|
|
67914
68184
|
return handoffPhrases.some((phrase) => text.includes(phrase));
|
|
67915
68185
|
}
|
|
67916
|
-
var execAsync5, STEP_STATUSES, MAX_WORKFLOW_STEP_RETRIES, WORKFLOW_SCRIPT_OUTPUT_MAX_CHARS2, NonRetryableWorktreeError, taskUpdateParams, taskAddDepParams, spawnAgentParams, reviewStepParams, EXECUTOR_SYSTEM_PROMPT, TaskExecutor;
|
|
68186
|
+
var execAsync5, STEP_STATUSES, MAX_WORKFLOW_STEP_RETRIES, MAX_TASK_DONE_SESSION_RETRIES, MAX_TASK_DONE_REQUEUE_RETRIES, WORKFLOW_SCRIPT_OUTPUT_MAX_CHARS2, NonRetryableWorktreeError, taskUpdateParams, taskAddDepParams, spawnAgentParams, reviewStepParams, EXECUTOR_SYSTEM_PROMPT, TaskExecutor;
|
|
67917
68187
|
var init_executor = __esm({
|
|
67918
68188
|
"../engine/src/executor.ts"() {
|
|
67919
68189
|
"use strict";
|
|
@@ -67946,6 +68216,8 @@ var init_executor = __esm({
|
|
|
67946
68216
|
execAsync5 = promisify6(exec5);
|
|
67947
68217
|
STEP_STATUSES = ["pending", "in-progress", "done", "skipped"];
|
|
67948
68218
|
MAX_WORKFLOW_STEP_RETRIES = 3;
|
|
68219
|
+
MAX_TASK_DONE_SESSION_RETRIES = 3;
|
|
68220
|
+
MAX_TASK_DONE_REQUEUE_RETRIES = 3;
|
|
67949
68221
|
WORKFLOW_SCRIPT_OUTPUT_MAX_CHARS2 = 4e3;
|
|
67950
68222
|
NonRetryableWorktreeError = class extends Error {
|
|
67951
68223
|
};
|
|
@@ -68233,8 +68505,11 @@ Lint, tests, and typecheck are also hard quality gates:
|
|
|
68233
68505
|
activeEntry.lastModelProvider = task.modelProvider;
|
|
68234
68506
|
activeEntry.lastModelId = task.modelId;
|
|
68235
68507
|
const settings = await this.store.getSettings();
|
|
68236
|
-
const
|
|
68237
|
-
|
|
68508
|
+
const { provider: newProvider, modelId: newModelId } = resolveExecutorModelPair2(
|
|
68509
|
+
task.modelProvider,
|
|
68510
|
+
task.modelId,
|
|
68511
|
+
settings
|
|
68512
|
+
);
|
|
68238
68513
|
if (newProvider && newModelId) {
|
|
68239
68514
|
try {
|
|
68240
68515
|
const model = this.modelRegistry.find(newProvider, newModelId);
|
|
@@ -69141,8 +69416,11 @@ Lint, tests, and typecheck are also hard quality gates:
|
|
|
69141
69416
|
}
|
|
69142
69417
|
});
|
|
69143
69418
|
const agentWork = async () => {
|
|
69144
|
-
const
|
|
69145
|
-
|
|
69419
|
+
const { provider: executorProvider, modelId: executorModelId } = resolveExecutorModelPair2(
|
|
69420
|
+
detail.modelProvider,
|
|
69421
|
+
detail.modelId,
|
|
69422
|
+
settings
|
|
69423
|
+
);
|
|
69146
69424
|
const executorFallbackProvider = settings.fallbackProvider;
|
|
69147
69425
|
const executorFallbackModelId = settings.fallbackModelId;
|
|
69148
69426
|
const executorThinkingLevel = detail.thinkingLevel ?? settings.defaultThinkingLevel;
|
|
@@ -69324,63 +69602,74 @@ Lint, tests, and typecheck are also hard quality gates:
|
|
|
69324
69602
|
executorLog.log(`\u2713 ${task.id} completed \u2192 in-review`);
|
|
69325
69603
|
this.options.onComplete?.(task);
|
|
69326
69604
|
} else {
|
|
69327
|
-
|
|
69328
|
-
|
|
69329
|
-
|
|
69330
|
-
|
|
69331
|
-
|
|
69332
|
-
|
|
69333
|
-
|
|
69334
|
-
|
|
69335
|
-
|
|
69336
|
-
|
|
69337
|
-
|
|
69338
|
-
|
|
69339
|
-
|
|
69340
|
-
|
|
69341
|
-
|
|
69342
|
-
|
|
69343
|
-
|
|
69344
|
-
|
|
69345
|
-
|
|
69346
|
-
|
|
69347
|
-
|
|
69348
|
-
|
|
69349
|
-
|
|
69350
|
-
|
|
69351
|
-
|
|
69352
|
-
|
|
69353
|
-
|
|
69354
|
-
|
|
69605
|
+
let taskDoneSessionRetries = 0;
|
|
69606
|
+
while (!taskDone && taskDoneSessionRetries < MAX_TASK_DONE_SESSION_RETRIES) {
|
|
69607
|
+
taskDoneSessionRetries++;
|
|
69608
|
+
executorLog.log(
|
|
69609
|
+
`\u26A0 ${task.id} finished without task_done \u2014 retrying with new session (${taskDoneSessionRetries}/${MAX_TASK_DONE_SESSION_RETRIES})`
|
|
69610
|
+
);
|
|
69611
|
+
await this.store.logEntry(
|
|
69612
|
+
task.id,
|
|
69613
|
+
`Agent finished without calling task_done \u2014 retrying with new session (${taskDoneSessionRetries}/${MAX_TASK_DONE_SESSION_RETRIES})`,
|
|
69614
|
+
void 0,
|
|
69615
|
+
this.currentRunContext
|
|
69616
|
+
);
|
|
69617
|
+
this.activeSessions.delete(task.id);
|
|
69618
|
+
session.dispose();
|
|
69619
|
+
const { session: retrySession2, sessionFile: retrySessionFile } = await createResolvedAgentSession({
|
|
69620
|
+
sessionPurpose: "executor",
|
|
69621
|
+
pluginRunner: this.options.pluginRunner,
|
|
69622
|
+
cwd: worktreePath,
|
|
69623
|
+
systemPrompt: executorSystemPrompt,
|
|
69624
|
+
tools: "coding",
|
|
69625
|
+
customTools,
|
|
69626
|
+
onText: agentLogger.onText,
|
|
69627
|
+
onThinking: agentLogger.onThinking,
|
|
69628
|
+
onToolStart: agentLogger.onToolStart,
|
|
69629
|
+
onToolEnd: agentLogger.onToolEnd,
|
|
69630
|
+
defaultProvider: executorProvider,
|
|
69631
|
+
defaultModelId: executorModelId,
|
|
69632
|
+
fallbackProvider: executorFallbackProvider,
|
|
69633
|
+
fallbackModelId: executorFallbackModelId,
|
|
69634
|
+
defaultThinkingLevel: executorThinkingLevel,
|
|
69635
|
+
sessionManager: SessionManager2.create(worktreePath),
|
|
69636
|
+
// Skill selection: use assigned agent skills if available, otherwise role fallback
|
|
69637
|
+
...skillContext.skillSelectionContext ? { skillSelection: skillContext.skillSelectionContext } : {}
|
|
69355
69638
|
});
|
|
69356
|
-
|
|
69357
|
-
|
|
69358
|
-
|
|
69359
|
-
|
|
69360
|
-
|
|
69361
|
-
|
|
69362
|
-
|
|
69363
|
-
|
|
69364
|
-
|
|
69365
|
-
|
|
69366
|
-
|
|
69367
|
-
|
|
69368
|
-
|
|
69369
|
-
|
|
69370
|
-
|
|
69371
|
-
|
|
69372
|
-
|
|
69373
|
-
|
|
69374
|
-
|
|
69375
|
-
|
|
69376
|
-
|
|
69377
|
-
|
|
69378
|
-
|
|
69379
|
-
|
|
69380
|
-
|
|
69381
|
-
|
|
69382
|
-
|
|
69383
|
-
|
|
69639
|
+
if (retrySessionFile) {
|
|
69640
|
+
this.store.updateTask(task.id, { sessionFile: retrySessionFile }).catch((err) => {
|
|
69641
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
69642
|
+
executorLog.warn(`${task.id} failed to persist retry sessionFile: ${msg}`);
|
|
69643
|
+
});
|
|
69644
|
+
}
|
|
69645
|
+
session = retrySession2;
|
|
69646
|
+
sessionRef.current = retrySession2;
|
|
69647
|
+
this.activeSessions.set(task.id, {
|
|
69648
|
+
session: retrySession2,
|
|
69649
|
+
seenSteeringIds,
|
|
69650
|
+
lastModelProvider: detail.modelProvider,
|
|
69651
|
+
lastModelId: detail.modelId
|
|
69652
|
+
});
|
|
69653
|
+
stuckDetector?.trackTask(task.id, retrySession2);
|
|
69654
|
+
const retryPrompt = [
|
|
69655
|
+
"Your previous session ended without calling the task_done tool.",
|
|
69656
|
+
"The task may already be complete \u2014 review the current state of the worktree and either:",
|
|
69657
|
+
"1. If the work is done, call task_done with a summary of what was accomplished.",
|
|
69658
|
+
"2. If there is remaining work, finish it and then call task_done.",
|
|
69659
|
+
"",
|
|
69660
|
+
"Original task:",
|
|
69661
|
+
buildExecutionPrompt(detail, this.rootDir, settings, worktreePath)
|
|
69662
|
+
].join("\n");
|
|
69663
|
+
stuckDetector?.recordActivity(task.id);
|
|
69664
|
+
await promptWithFallback(retrySession2, retryPrompt);
|
|
69665
|
+
checkSessionError(retrySession2);
|
|
69666
|
+
if (!taskDone) {
|
|
69667
|
+
const implicitCheck = await this.store.getTask(task.id);
|
|
69668
|
+
if (implicitCheck.steps.length > 0 && implicitCheck.steps.every((s) => s.status === "done" || s.status === "skipped")) {
|
|
69669
|
+
taskDone = true;
|
|
69670
|
+
executorLog.log(`${task.id} all steps done \u2014 treating as implicit task_done`);
|
|
69671
|
+
await this.store.logEntry(task.id, "All steps complete \u2014 implicit task_done (agent did not call tool explicitly)", void 0, this.currentRunContext);
|
|
69672
|
+
}
|
|
69384
69673
|
}
|
|
69385
69674
|
}
|
|
69386
69675
|
if (taskDone) {
|
|
@@ -69409,11 +69698,29 @@ Lint, tests, and typecheck are also hard quality gates:
|
|
|
69409
69698
|
executorLog.log(`\u2713 ${task.id} completed on retry \u2192 in-review`);
|
|
69410
69699
|
this.options.onComplete?.(task);
|
|
69411
69700
|
} else {
|
|
69412
|
-
const
|
|
69413
|
-
|
|
69414
|
-
|
|
69415
|
-
|
|
69416
|
-
|
|
69701
|
+
const priorRequeues = task.taskDoneRetryCount ?? 0;
|
|
69702
|
+
const nextRequeueCount = priorRequeues + 1;
|
|
69703
|
+
const errorMessage = `Agent finished without calling task_done (after ${MAX_TASK_DONE_SESSION_RETRIES} retries)`;
|
|
69704
|
+
if (priorRequeues < MAX_TASK_DONE_REQUEUE_RETRIES) {
|
|
69705
|
+
await this.store.updateTask(task.id, {
|
|
69706
|
+
status: "failed",
|
|
69707
|
+
error: errorMessage,
|
|
69708
|
+
taskDoneRetryCount: nextRequeueCount
|
|
69709
|
+
});
|
|
69710
|
+
await this.store.logEntry(
|
|
69711
|
+
task.id,
|
|
69712
|
+
`${errorMessage} \u2014 requeued to todo immediately (${nextRequeueCount}/${MAX_TASK_DONE_REQUEUE_RETRIES})`,
|
|
69713
|
+
void 0,
|
|
69714
|
+
this.currentRunContext
|
|
69715
|
+
);
|
|
69716
|
+
await this.store.moveTask(task.id, "todo");
|
|
69717
|
+
executorLog.log(`\u2717 ${task.id} failed after ${MAX_TASK_DONE_SESSION_RETRIES} retries \u2014 requeued to todo (${nextRequeueCount}/${MAX_TASK_DONE_REQUEUE_RETRIES})`);
|
|
69718
|
+
} else {
|
|
69719
|
+
await this.store.updateTask(task.id, { status: "failed", error: errorMessage });
|
|
69720
|
+
await this.store.logEntry(task.id, `${errorMessage} \u2014 moved to in-review for inspection`, void 0, this.currentRunContext);
|
|
69721
|
+
await this.store.moveTask(task.id, "in-review");
|
|
69722
|
+
executorLog.log(`\u2717 ${task.id} failed after ${MAX_TASK_DONE_SESSION_RETRIES} retries \u2014 no task_done \u2192 in-review`);
|
|
69723
|
+
}
|
|
69417
69724
|
this.options.onError?.(task, new Error(errorMessage));
|
|
69418
69725
|
}
|
|
69419
69726
|
}
|
|
@@ -75999,7 +76306,7 @@ async function getHeartbeatMemorySettings(taskStore) {
|
|
|
75999
76306
|
return maybeGetSettings.call(taskStore);
|
|
76000
76307
|
}
|
|
76001
76308
|
function isTickableState(state) {
|
|
76002
|
-
return state === "active" || state === "running";
|
|
76309
|
+
return state === "active" || state === "running" || state === "idle";
|
|
76003
76310
|
}
|
|
76004
76311
|
function isHeartbeatManaged(agent) {
|
|
76005
76312
|
return !isEphemeralAgent(agent);
|
|
@@ -77329,8 +77636,13 @@ ${taskDetail.prompt}` : "No PROMPT.md available.",
|
|
|
77329
77636
|
this.assignedListener = async (agent, taskId) => {
|
|
77330
77637
|
if (!this.running) return;
|
|
77331
77638
|
try {
|
|
77332
|
-
if (!isHeartbeatManaged(agent)
|
|
77333
|
-
heartbeatLog.log(`Assignment trigger skipped for ${agent.id} (
|
|
77639
|
+
if (!isHeartbeatManaged(agent)) {
|
|
77640
|
+
heartbeatLog.log(`Assignment trigger skipped for ${agent.id} (ephemeral/internal)`);
|
|
77641
|
+
return;
|
|
77642
|
+
}
|
|
77643
|
+
const runtimeConfig = agent.runtimeConfig ?? {};
|
|
77644
|
+
if (runtimeConfig.enabled === false) {
|
|
77645
|
+
heartbeatLog.log(`Assignment trigger skipped for ${agent.id} (disabled)`);
|
|
77334
77646
|
return;
|
|
77335
77647
|
}
|
|
77336
77648
|
const activeRun = await this.store.getActiveHeartbeatRun(agent.id);
|
|
@@ -77789,6 +78101,10 @@ var init_self_healing = __esm({
|
|
|
77789
78101
|
const result = await readLog("HEAD");
|
|
77790
78102
|
stdout = result.stdout;
|
|
77791
78103
|
}
|
|
78104
|
+
if (!stdout.trim() && task.baseCommitSha) {
|
|
78105
|
+
const result = await readLog("HEAD");
|
|
78106
|
+
stdout = result.stdout;
|
|
78107
|
+
}
|
|
77792
78108
|
const firstLine = stdout.trim().split("\n").find(Boolean);
|
|
77793
78109
|
if (!firstLine) return null;
|
|
77794
78110
|
const [sha, subject] = firstLine.split("");
|
|
@@ -79650,10 +79966,10 @@ var init_in_process_runtime = __esm({
|
|
|
79650
79966
|
this.taskStore
|
|
79651
79967
|
);
|
|
79652
79968
|
this.triggerScheduler.start();
|
|
79653
|
-
const
|
|
79969
|
+
const isHeartbeatEnabledAgent = (agent) => !isEphemeralAgent(agent) && agent.runtimeConfig?.enabled !== false;
|
|
79654
79970
|
this.agentCreatedListener = (agent) => {
|
|
79655
79971
|
if (!this.triggerScheduler) return;
|
|
79656
|
-
if (!
|
|
79972
|
+
if (!isHeartbeatEnabledAgent(agent)) return;
|
|
79657
79973
|
const rc = agent.runtimeConfig;
|
|
79658
79974
|
this.triggerScheduler.registerAgent(agent.id, {
|
|
79659
79975
|
heartbeatIntervalMs: rc?.heartbeatIntervalMs,
|
|
@@ -79664,9 +79980,9 @@ var init_in_process_runtime = __esm({
|
|
|
79664
79980
|
this.agentStore.on("agent:created", this.agentCreatedListener);
|
|
79665
79981
|
this.agentUpdatedListener = (agent) => {
|
|
79666
79982
|
if (!this.triggerScheduler) return;
|
|
79667
|
-
if (!
|
|
79983
|
+
if (!isHeartbeatEnabledAgent(agent)) {
|
|
79668
79984
|
this.triggerScheduler.unregisterAgent(agent.id);
|
|
79669
|
-
runtimeLog.log(`Unregistered agent ${agent.id} from heartbeat triggers
|
|
79985
|
+
runtimeLog.log(`Unregistered agent ${agent.id} from heartbeat triggers`);
|
|
79670
79986
|
return;
|
|
79671
79987
|
}
|
|
79672
79988
|
const rc = agent.runtimeConfig;
|
|
@@ -79674,7 +79990,7 @@ var init_in_process_runtime = __esm({
|
|
|
79674
79990
|
heartbeatIntervalMs: rc?.heartbeatIntervalMs,
|
|
79675
79991
|
maxConcurrentRuns: rc?.maxConcurrentRuns
|
|
79676
79992
|
});
|
|
79677
|
-
runtimeLog.log(`Re-registered agent ${agent.id} for heartbeat triggers
|
|
79993
|
+
runtimeLog.log(`Re-registered agent ${agent.id} for heartbeat triggers`);
|
|
79678
79994
|
};
|
|
79679
79995
|
this.agentStore.on("agent:updated", this.agentUpdatedListener);
|
|
79680
79996
|
this.ephemeralTerminationListener = (agentId, from, to) => {
|
|
@@ -79709,7 +80025,7 @@ var init_in_process_runtime = __esm({
|
|
|
79709
80025
|
const agents = await this.agentStore.listAgents();
|
|
79710
80026
|
let registeredCount = 0;
|
|
79711
80027
|
for (const agent of agents) {
|
|
79712
|
-
if (!
|
|
80028
|
+
if (!isHeartbeatEnabledAgent(agent)) continue;
|
|
79713
80029
|
const rc = agent.runtimeConfig;
|
|
79714
80030
|
this.triggerScheduler.registerAgent(agent.id, {
|
|
79715
80031
|
heartbeatIntervalMs: rc?.heartbeatIntervalMs,
|
|
@@ -88192,13 +88508,13 @@ var require_readdir_glob = __commonJS({
|
|
|
88192
88508
|
"../../node_modules/.pnpm/readdir-glob@1.1.3/node_modules/readdir-glob/index.js"(exports, module) {
|
|
88193
88509
|
"use strict";
|
|
88194
88510
|
module.exports = readdirGlob;
|
|
88195
|
-
var
|
|
88511
|
+
var fs2 = __require("fs");
|
|
88196
88512
|
var { EventEmitter: EventEmitter33 } = __require("events");
|
|
88197
88513
|
var { Minimatch } = require_minimatch();
|
|
88198
88514
|
var { resolve: resolve29 } = __require("path");
|
|
88199
88515
|
function readdir11(dir2, strict) {
|
|
88200
88516
|
return new Promise((resolve30, reject2) => {
|
|
88201
|
-
|
|
88517
|
+
fs2.readdir(dir2, { withFileTypes: true }, (err, files) => {
|
|
88202
88518
|
if (err) {
|
|
88203
88519
|
switch (err.code) {
|
|
88204
88520
|
case "ENOTDIR":
|
|
@@ -88231,7 +88547,7 @@ var require_readdir_glob = __commonJS({
|
|
|
88231
88547
|
}
|
|
88232
88548
|
function stat11(file, followSymlinks) {
|
|
88233
88549
|
return new Promise((resolve30, reject2) => {
|
|
88234
|
-
const statFunc = followSymlinks ?
|
|
88550
|
+
const statFunc = followSymlinks ? fs2.stat : fs2.lstat;
|
|
88235
88551
|
statFunc(file, (err, stats) => {
|
|
88236
88552
|
if (err) {
|
|
88237
88553
|
switch (err.code) {
|
|
@@ -90294,54 +90610,54 @@ var require_polyfills = __commonJS({
|
|
|
90294
90610
|
}
|
|
90295
90611
|
var chdir;
|
|
90296
90612
|
module.exports = patch;
|
|
90297
|
-
function patch(
|
|
90613
|
+
function patch(fs2) {
|
|
90298
90614
|
if (constants2.hasOwnProperty("O_SYMLINK") && process.version.match(/^v0\.6\.[0-2]|^v0\.5\./)) {
|
|
90299
|
-
patchLchmod(
|
|
90300
|
-
}
|
|
90301
|
-
if (!
|
|
90302
|
-
patchLutimes(
|
|
90303
|
-
}
|
|
90304
|
-
|
|
90305
|
-
|
|
90306
|
-
|
|
90307
|
-
|
|
90308
|
-
|
|
90309
|
-
|
|
90310
|
-
|
|
90311
|
-
|
|
90312
|
-
|
|
90313
|
-
|
|
90314
|
-
|
|
90315
|
-
|
|
90316
|
-
|
|
90317
|
-
|
|
90318
|
-
|
|
90319
|
-
|
|
90320
|
-
|
|
90321
|
-
|
|
90322
|
-
if (
|
|
90323
|
-
|
|
90615
|
+
patchLchmod(fs2);
|
|
90616
|
+
}
|
|
90617
|
+
if (!fs2.lutimes) {
|
|
90618
|
+
patchLutimes(fs2);
|
|
90619
|
+
}
|
|
90620
|
+
fs2.chown = chownFix(fs2.chown);
|
|
90621
|
+
fs2.fchown = chownFix(fs2.fchown);
|
|
90622
|
+
fs2.lchown = chownFix(fs2.lchown);
|
|
90623
|
+
fs2.chmod = chmodFix(fs2.chmod);
|
|
90624
|
+
fs2.fchmod = chmodFix(fs2.fchmod);
|
|
90625
|
+
fs2.lchmod = chmodFix(fs2.lchmod);
|
|
90626
|
+
fs2.chownSync = chownFixSync(fs2.chownSync);
|
|
90627
|
+
fs2.fchownSync = chownFixSync(fs2.fchownSync);
|
|
90628
|
+
fs2.lchownSync = chownFixSync(fs2.lchownSync);
|
|
90629
|
+
fs2.chmodSync = chmodFixSync(fs2.chmodSync);
|
|
90630
|
+
fs2.fchmodSync = chmodFixSync(fs2.fchmodSync);
|
|
90631
|
+
fs2.lchmodSync = chmodFixSync(fs2.lchmodSync);
|
|
90632
|
+
fs2.stat = statFix(fs2.stat);
|
|
90633
|
+
fs2.fstat = statFix(fs2.fstat);
|
|
90634
|
+
fs2.lstat = statFix(fs2.lstat);
|
|
90635
|
+
fs2.statSync = statFixSync(fs2.statSync);
|
|
90636
|
+
fs2.fstatSync = statFixSync(fs2.fstatSync);
|
|
90637
|
+
fs2.lstatSync = statFixSync(fs2.lstatSync);
|
|
90638
|
+
if (fs2.chmod && !fs2.lchmod) {
|
|
90639
|
+
fs2.lchmod = function(path4, mode, cb) {
|
|
90324
90640
|
if (cb) process.nextTick(cb);
|
|
90325
90641
|
};
|
|
90326
|
-
|
|
90642
|
+
fs2.lchmodSync = function() {
|
|
90327
90643
|
};
|
|
90328
90644
|
}
|
|
90329
|
-
if (
|
|
90330
|
-
|
|
90645
|
+
if (fs2.chown && !fs2.lchown) {
|
|
90646
|
+
fs2.lchown = function(path4, uid, gid, cb) {
|
|
90331
90647
|
if (cb) process.nextTick(cb);
|
|
90332
90648
|
};
|
|
90333
|
-
|
|
90649
|
+
fs2.lchownSync = function() {
|
|
90334
90650
|
};
|
|
90335
90651
|
}
|
|
90336
90652
|
if (platform3 === "win32") {
|
|
90337
|
-
|
|
90653
|
+
fs2.rename = typeof fs2.rename !== "function" ? fs2.rename : (function(fs$rename) {
|
|
90338
90654
|
function rename6(from, to, cb) {
|
|
90339
90655
|
var start = Date.now();
|
|
90340
90656
|
var backoff = 0;
|
|
90341
90657
|
fs$rename(from, to, function CB(er) {
|
|
90342
90658
|
if (er && (er.code === "EACCES" || er.code === "EPERM" || er.code === "EBUSY") && Date.now() - start < 6e4) {
|
|
90343
90659
|
setTimeout(function() {
|
|
90344
|
-
|
|
90660
|
+
fs2.stat(to, function(stater, st) {
|
|
90345
90661
|
if (stater && stater.code === "ENOENT")
|
|
90346
90662
|
fs$rename(from, to, CB);
|
|
90347
90663
|
else
|
|
@@ -90357,9 +90673,9 @@ var require_polyfills = __commonJS({
|
|
|
90357
90673
|
}
|
|
90358
90674
|
if (Object.setPrototypeOf) Object.setPrototypeOf(rename6, fs$rename);
|
|
90359
90675
|
return rename6;
|
|
90360
|
-
})(
|
|
90676
|
+
})(fs2.rename);
|
|
90361
90677
|
}
|
|
90362
|
-
|
|
90678
|
+
fs2.read = typeof fs2.read !== "function" ? fs2.read : (function(fs$read) {
|
|
90363
90679
|
function read(fd, buffer, offset, length, position, callback_) {
|
|
90364
90680
|
var callback;
|
|
90365
90681
|
if (callback_ && typeof callback_ === "function") {
|
|
@@ -90367,22 +90683,22 @@ var require_polyfills = __commonJS({
|
|
|
90367
90683
|
callback = function(er, _2, __) {
|
|
90368
90684
|
if (er && er.code === "EAGAIN" && eagCounter < 10) {
|
|
90369
90685
|
eagCounter++;
|
|
90370
|
-
return fs$read.call(
|
|
90686
|
+
return fs$read.call(fs2, fd, buffer, offset, length, position, callback);
|
|
90371
90687
|
}
|
|
90372
90688
|
callback_.apply(this, arguments);
|
|
90373
90689
|
};
|
|
90374
90690
|
}
|
|
90375
|
-
return fs$read.call(
|
|
90691
|
+
return fs$read.call(fs2, fd, buffer, offset, length, position, callback);
|
|
90376
90692
|
}
|
|
90377
90693
|
if (Object.setPrototypeOf) Object.setPrototypeOf(read, fs$read);
|
|
90378
90694
|
return read;
|
|
90379
|
-
})(
|
|
90380
|
-
|
|
90695
|
+
})(fs2.read);
|
|
90696
|
+
fs2.readSync = typeof fs2.readSync !== "function" ? fs2.readSync : /* @__PURE__ */ (function(fs$readSync) {
|
|
90381
90697
|
return function(fd, buffer, offset, length, position) {
|
|
90382
90698
|
var eagCounter = 0;
|
|
90383
90699
|
while (true) {
|
|
90384
90700
|
try {
|
|
90385
|
-
return fs$readSync.call(
|
|
90701
|
+
return fs$readSync.call(fs2, fd, buffer, offset, length, position);
|
|
90386
90702
|
} catch (er) {
|
|
90387
90703
|
if (er.code === "EAGAIN" && eagCounter < 10) {
|
|
90388
90704
|
eagCounter++;
|
|
@@ -90392,10 +90708,10 @@ var require_polyfills = __commonJS({
|
|
|
90392
90708
|
}
|
|
90393
90709
|
}
|
|
90394
90710
|
};
|
|
90395
|
-
})(
|
|
90396
|
-
function patchLchmod(
|
|
90397
|
-
|
|
90398
|
-
|
|
90711
|
+
})(fs2.readSync);
|
|
90712
|
+
function patchLchmod(fs3) {
|
|
90713
|
+
fs3.lchmod = function(path4, mode, callback) {
|
|
90714
|
+
fs3.open(
|
|
90399
90715
|
path4,
|
|
90400
90716
|
constants2.O_WRONLY | constants2.O_SYMLINK,
|
|
90401
90717
|
mode,
|
|
@@ -90404,80 +90720,80 @@ var require_polyfills = __commonJS({
|
|
|
90404
90720
|
if (callback) callback(err);
|
|
90405
90721
|
return;
|
|
90406
90722
|
}
|
|
90407
|
-
|
|
90408
|
-
|
|
90723
|
+
fs3.fchmod(fd, mode, function(err2) {
|
|
90724
|
+
fs3.close(fd, function(err22) {
|
|
90409
90725
|
if (callback) callback(err2 || err22);
|
|
90410
90726
|
});
|
|
90411
90727
|
});
|
|
90412
90728
|
}
|
|
90413
90729
|
);
|
|
90414
90730
|
};
|
|
90415
|
-
|
|
90416
|
-
var fd =
|
|
90731
|
+
fs3.lchmodSync = function(path4, mode) {
|
|
90732
|
+
var fd = fs3.openSync(path4, constants2.O_WRONLY | constants2.O_SYMLINK, mode);
|
|
90417
90733
|
var threw = true;
|
|
90418
90734
|
var ret;
|
|
90419
90735
|
try {
|
|
90420
|
-
ret =
|
|
90736
|
+
ret = fs3.fchmodSync(fd, mode);
|
|
90421
90737
|
threw = false;
|
|
90422
90738
|
} finally {
|
|
90423
90739
|
if (threw) {
|
|
90424
90740
|
try {
|
|
90425
|
-
|
|
90741
|
+
fs3.closeSync(fd);
|
|
90426
90742
|
} catch (er) {
|
|
90427
90743
|
}
|
|
90428
90744
|
} else {
|
|
90429
|
-
|
|
90745
|
+
fs3.closeSync(fd);
|
|
90430
90746
|
}
|
|
90431
90747
|
}
|
|
90432
90748
|
return ret;
|
|
90433
90749
|
};
|
|
90434
90750
|
}
|
|
90435
|
-
function patchLutimes(
|
|
90436
|
-
if (constants2.hasOwnProperty("O_SYMLINK") &&
|
|
90437
|
-
|
|
90438
|
-
|
|
90751
|
+
function patchLutimes(fs3) {
|
|
90752
|
+
if (constants2.hasOwnProperty("O_SYMLINK") && fs3.futimes) {
|
|
90753
|
+
fs3.lutimes = function(path4, at, mt, cb) {
|
|
90754
|
+
fs3.open(path4, constants2.O_SYMLINK, function(er, fd) {
|
|
90439
90755
|
if (er) {
|
|
90440
90756
|
if (cb) cb(er);
|
|
90441
90757
|
return;
|
|
90442
90758
|
}
|
|
90443
|
-
|
|
90444
|
-
|
|
90759
|
+
fs3.futimes(fd, at, mt, function(er2) {
|
|
90760
|
+
fs3.close(fd, function(er22) {
|
|
90445
90761
|
if (cb) cb(er2 || er22);
|
|
90446
90762
|
});
|
|
90447
90763
|
});
|
|
90448
90764
|
});
|
|
90449
90765
|
};
|
|
90450
|
-
|
|
90451
|
-
var fd =
|
|
90766
|
+
fs3.lutimesSync = function(path4, at, mt) {
|
|
90767
|
+
var fd = fs3.openSync(path4, constants2.O_SYMLINK);
|
|
90452
90768
|
var ret;
|
|
90453
90769
|
var threw = true;
|
|
90454
90770
|
try {
|
|
90455
|
-
ret =
|
|
90771
|
+
ret = fs3.futimesSync(fd, at, mt);
|
|
90456
90772
|
threw = false;
|
|
90457
90773
|
} finally {
|
|
90458
90774
|
if (threw) {
|
|
90459
90775
|
try {
|
|
90460
|
-
|
|
90776
|
+
fs3.closeSync(fd);
|
|
90461
90777
|
} catch (er) {
|
|
90462
90778
|
}
|
|
90463
90779
|
} else {
|
|
90464
|
-
|
|
90780
|
+
fs3.closeSync(fd);
|
|
90465
90781
|
}
|
|
90466
90782
|
}
|
|
90467
90783
|
return ret;
|
|
90468
90784
|
};
|
|
90469
|
-
} else if (
|
|
90470
|
-
|
|
90785
|
+
} else if (fs3.futimes) {
|
|
90786
|
+
fs3.lutimes = function(_a, _b, _c, cb) {
|
|
90471
90787
|
if (cb) process.nextTick(cb);
|
|
90472
90788
|
};
|
|
90473
|
-
|
|
90789
|
+
fs3.lutimesSync = function() {
|
|
90474
90790
|
};
|
|
90475
90791
|
}
|
|
90476
90792
|
}
|
|
90477
90793
|
function chmodFix(orig) {
|
|
90478
90794
|
if (!orig) return orig;
|
|
90479
90795
|
return function(target, mode, cb) {
|
|
90480
|
-
return orig.call(
|
|
90796
|
+
return orig.call(fs2, target, mode, function(er) {
|
|
90481
90797
|
if (chownErOk(er)) er = null;
|
|
90482
90798
|
if (cb) cb.apply(this, arguments);
|
|
90483
90799
|
});
|
|
@@ -90487,7 +90803,7 @@ var require_polyfills = __commonJS({
|
|
|
90487
90803
|
if (!orig) return orig;
|
|
90488
90804
|
return function(target, mode) {
|
|
90489
90805
|
try {
|
|
90490
|
-
return orig.call(
|
|
90806
|
+
return orig.call(fs2, target, mode);
|
|
90491
90807
|
} catch (er) {
|
|
90492
90808
|
if (!chownErOk(er)) throw er;
|
|
90493
90809
|
}
|
|
@@ -90496,7 +90812,7 @@ var require_polyfills = __commonJS({
|
|
|
90496
90812
|
function chownFix(orig) {
|
|
90497
90813
|
if (!orig) return orig;
|
|
90498
90814
|
return function(target, uid, gid, cb) {
|
|
90499
|
-
return orig.call(
|
|
90815
|
+
return orig.call(fs2, target, uid, gid, function(er) {
|
|
90500
90816
|
if (chownErOk(er)) er = null;
|
|
90501
90817
|
if (cb) cb.apply(this, arguments);
|
|
90502
90818
|
});
|
|
@@ -90506,7 +90822,7 @@ var require_polyfills = __commonJS({
|
|
|
90506
90822
|
if (!orig) return orig;
|
|
90507
90823
|
return function(target, uid, gid) {
|
|
90508
90824
|
try {
|
|
90509
|
-
return orig.call(
|
|
90825
|
+
return orig.call(fs2, target, uid, gid);
|
|
90510
90826
|
} catch (er) {
|
|
90511
90827
|
if (!chownErOk(er)) throw er;
|
|
90512
90828
|
}
|
|
@@ -90526,13 +90842,13 @@ var require_polyfills = __commonJS({
|
|
|
90526
90842
|
}
|
|
90527
90843
|
if (cb) cb.apply(this, arguments);
|
|
90528
90844
|
}
|
|
90529
|
-
return options ? orig.call(
|
|
90845
|
+
return options ? orig.call(fs2, target, options, callback) : orig.call(fs2, target, callback);
|
|
90530
90846
|
};
|
|
90531
90847
|
}
|
|
90532
90848
|
function statFixSync(orig) {
|
|
90533
90849
|
if (!orig) return orig;
|
|
90534
90850
|
return function(target, options) {
|
|
90535
|
-
var stats = options ? orig.call(
|
|
90851
|
+
var stats = options ? orig.call(fs2, target, options) : orig.call(fs2, target);
|
|
90536
90852
|
if (stats) {
|
|
90537
90853
|
if (stats.uid < 0) stats.uid += 4294967296;
|
|
90538
90854
|
if (stats.gid < 0) stats.gid += 4294967296;
|
|
@@ -90562,7 +90878,7 @@ var require_legacy_streams = __commonJS({
|
|
|
90562
90878
|
"use strict";
|
|
90563
90879
|
var Stream = __require("stream").Stream;
|
|
90564
90880
|
module.exports = legacy;
|
|
90565
|
-
function legacy(
|
|
90881
|
+
function legacy(fs2) {
|
|
90566
90882
|
return {
|
|
90567
90883
|
ReadStream,
|
|
90568
90884
|
WriteStream
|
|
@@ -90605,7 +90921,7 @@ var require_legacy_streams = __commonJS({
|
|
|
90605
90921
|
});
|
|
90606
90922
|
return;
|
|
90607
90923
|
}
|
|
90608
|
-
|
|
90924
|
+
fs2.open(this.path, this.flags, this.mode, function(err, fd) {
|
|
90609
90925
|
if (err) {
|
|
90610
90926
|
self2.emit("error", err);
|
|
90611
90927
|
self2.readable = false;
|
|
@@ -90644,7 +90960,7 @@ var require_legacy_streams = __commonJS({
|
|
|
90644
90960
|
this.busy = false;
|
|
90645
90961
|
this._queue = [];
|
|
90646
90962
|
if (this.fd === null) {
|
|
90647
|
-
this._open =
|
|
90963
|
+
this._open = fs2.open;
|
|
90648
90964
|
this._queue.push([this._open, this.path, this.flags, this.mode, void 0]);
|
|
90649
90965
|
this.flush();
|
|
90650
90966
|
}
|
|
@@ -90680,7 +90996,7 @@ var require_clone = __commonJS({
|
|
|
90680
90996
|
var require_graceful_fs = __commonJS({
|
|
90681
90997
|
"../../node_modules/.pnpm/graceful-fs@4.2.11/node_modules/graceful-fs/graceful-fs.js"(exports, module) {
|
|
90682
90998
|
"use strict";
|
|
90683
|
-
var
|
|
90999
|
+
var fs2 = __require("fs");
|
|
90684
91000
|
var polyfills = require_polyfills();
|
|
90685
91001
|
var legacy = require_legacy_streams();
|
|
90686
91002
|
var clone = require_clone();
|
|
@@ -90712,12 +91028,12 @@ var require_graceful_fs = __commonJS({
|
|
|
90712
91028
|
m = "GFS4: " + m.split(/\n/).join("\nGFS4: ");
|
|
90713
91029
|
console.error(m);
|
|
90714
91030
|
};
|
|
90715
|
-
if (!
|
|
91031
|
+
if (!fs2[gracefulQueue]) {
|
|
90716
91032
|
queue2 = global[gracefulQueue] || [];
|
|
90717
|
-
publishQueue(
|
|
90718
|
-
|
|
91033
|
+
publishQueue(fs2, queue2);
|
|
91034
|
+
fs2.close = (function(fs$close) {
|
|
90719
91035
|
function close(fd, cb) {
|
|
90720
|
-
return fs$close.call(
|
|
91036
|
+
return fs$close.call(fs2, fd, function(err) {
|
|
90721
91037
|
if (!err) {
|
|
90722
91038
|
resetQueue();
|
|
90723
91039
|
}
|
|
@@ -90729,40 +91045,40 @@ var require_graceful_fs = __commonJS({
|
|
|
90729
91045
|
value: fs$close
|
|
90730
91046
|
});
|
|
90731
91047
|
return close;
|
|
90732
|
-
})(
|
|
90733
|
-
|
|
91048
|
+
})(fs2.close);
|
|
91049
|
+
fs2.closeSync = (function(fs$closeSync) {
|
|
90734
91050
|
function closeSync(fd) {
|
|
90735
|
-
fs$closeSync.apply(
|
|
91051
|
+
fs$closeSync.apply(fs2, arguments);
|
|
90736
91052
|
resetQueue();
|
|
90737
91053
|
}
|
|
90738
91054
|
Object.defineProperty(closeSync, previousSymbol, {
|
|
90739
91055
|
value: fs$closeSync
|
|
90740
91056
|
});
|
|
90741
91057
|
return closeSync;
|
|
90742
|
-
})(
|
|
91058
|
+
})(fs2.closeSync);
|
|
90743
91059
|
if (/\bgfs4\b/i.test(process.env.NODE_DEBUG || "")) {
|
|
90744
91060
|
process.on("exit", function() {
|
|
90745
|
-
debug(
|
|
90746
|
-
__require("assert").equal(
|
|
91061
|
+
debug(fs2[gracefulQueue]);
|
|
91062
|
+
__require("assert").equal(fs2[gracefulQueue].length, 0);
|
|
90747
91063
|
});
|
|
90748
91064
|
}
|
|
90749
91065
|
}
|
|
90750
91066
|
var queue2;
|
|
90751
91067
|
if (!global[gracefulQueue]) {
|
|
90752
|
-
publishQueue(global,
|
|
90753
|
-
}
|
|
90754
|
-
module.exports = patch(clone(
|
|
90755
|
-
if (process.env.TEST_GRACEFUL_FS_GLOBAL_PATCH && !
|
|
90756
|
-
module.exports = patch(
|
|
90757
|
-
|
|
90758
|
-
}
|
|
90759
|
-
function patch(
|
|
90760
|
-
polyfills(
|
|
90761
|
-
|
|
90762
|
-
|
|
90763
|
-
|
|
90764
|
-
var fs$readFile =
|
|
90765
|
-
|
|
91068
|
+
publishQueue(global, fs2[gracefulQueue]);
|
|
91069
|
+
}
|
|
91070
|
+
module.exports = patch(clone(fs2));
|
|
91071
|
+
if (process.env.TEST_GRACEFUL_FS_GLOBAL_PATCH && !fs2.__patched) {
|
|
91072
|
+
module.exports = patch(fs2);
|
|
91073
|
+
fs2.__patched = true;
|
|
91074
|
+
}
|
|
91075
|
+
function patch(fs3) {
|
|
91076
|
+
polyfills(fs3);
|
|
91077
|
+
fs3.gracefulify = patch;
|
|
91078
|
+
fs3.createReadStream = createReadStream2;
|
|
91079
|
+
fs3.createWriteStream = createWriteStream2;
|
|
91080
|
+
var fs$readFile = fs3.readFile;
|
|
91081
|
+
fs3.readFile = readFile24;
|
|
90766
91082
|
function readFile24(path4, options, cb) {
|
|
90767
91083
|
if (typeof options === "function")
|
|
90768
91084
|
cb = options, options = null;
|
|
@@ -90778,8 +91094,8 @@ var require_graceful_fs = __commonJS({
|
|
|
90778
91094
|
});
|
|
90779
91095
|
}
|
|
90780
91096
|
}
|
|
90781
|
-
var fs$writeFile =
|
|
90782
|
-
|
|
91097
|
+
var fs$writeFile = fs3.writeFile;
|
|
91098
|
+
fs3.writeFile = writeFile16;
|
|
90783
91099
|
function writeFile16(path4, data, options, cb) {
|
|
90784
91100
|
if (typeof options === "function")
|
|
90785
91101
|
cb = options, options = null;
|
|
@@ -90795,9 +91111,9 @@ var require_graceful_fs = __commonJS({
|
|
|
90795
91111
|
});
|
|
90796
91112
|
}
|
|
90797
91113
|
}
|
|
90798
|
-
var fs$appendFile =
|
|
91114
|
+
var fs$appendFile = fs3.appendFile;
|
|
90799
91115
|
if (fs$appendFile)
|
|
90800
|
-
|
|
91116
|
+
fs3.appendFile = appendFile3;
|
|
90801
91117
|
function appendFile3(path4, data, options, cb) {
|
|
90802
91118
|
if (typeof options === "function")
|
|
90803
91119
|
cb = options, options = null;
|
|
@@ -90813,9 +91129,9 @@ var require_graceful_fs = __commonJS({
|
|
|
90813
91129
|
});
|
|
90814
91130
|
}
|
|
90815
91131
|
}
|
|
90816
|
-
var fs$copyFile =
|
|
91132
|
+
var fs$copyFile = fs3.copyFile;
|
|
90817
91133
|
if (fs$copyFile)
|
|
90818
|
-
|
|
91134
|
+
fs3.copyFile = copyFile;
|
|
90819
91135
|
function copyFile(src, dest, flags, cb) {
|
|
90820
91136
|
if (typeof flags === "function") {
|
|
90821
91137
|
cb = flags;
|
|
@@ -90833,8 +91149,8 @@ var require_graceful_fs = __commonJS({
|
|
|
90833
91149
|
});
|
|
90834
91150
|
}
|
|
90835
91151
|
}
|
|
90836
|
-
var fs$readdir =
|
|
90837
|
-
|
|
91152
|
+
var fs$readdir = fs3.readdir;
|
|
91153
|
+
fs3.readdir = readdir11;
|
|
90838
91154
|
var noReaddirOptionVersions = /^v[0-5]\./;
|
|
90839
91155
|
function readdir11(path4, options, cb) {
|
|
90840
91156
|
if (typeof options === "function")
|
|
@@ -90875,21 +91191,21 @@ var require_graceful_fs = __commonJS({
|
|
|
90875
91191
|
}
|
|
90876
91192
|
}
|
|
90877
91193
|
if (process.version.substr(0, 4) === "v0.8") {
|
|
90878
|
-
var legStreams = legacy(
|
|
91194
|
+
var legStreams = legacy(fs3);
|
|
90879
91195
|
ReadStream = legStreams.ReadStream;
|
|
90880
91196
|
WriteStream = legStreams.WriteStream;
|
|
90881
91197
|
}
|
|
90882
|
-
var fs$ReadStream =
|
|
91198
|
+
var fs$ReadStream = fs3.ReadStream;
|
|
90883
91199
|
if (fs$ReadStream) {
|
|
90884
91200
|
ReadStream.prototype = Object.create(fs$ReadStream.prototype);
|
|
90885
91201
|
ReadStream.prototype.open = ReadStream$open;
|
|
90886
91202
|
}
|
|
90887
|
-
var fs$WriteStream =
|
|
91203
|
+
var fs$WriteStream = fs3.WriteStream;
|
|
90888
91204
|
if (fs$WriteStream) {
|
|
90889
91205
|
WriteStream.prototype = Object.create(fs$WriteStream.prototype);
|
|
90890
91206
|
WriteStream.prototype.open = WriteStream$open;
|
|
90891
91207
|
}
|
|
90892
|
-
Object.defineProperty(
|
|
91208
|
+
Object.defineProperty(fs3, "ReadStream", {
|
|
90893
91209
|
get: function() {
|
|
90894
91210
|
return ReadStream;
|
|
90895
91211
|
},
|
|
@@ -90899,7 +91215,7 @@ var require_graceful_fs = __commonJS({
|
|
|
90899
91215
|
enumerable: true,
|
|
90900
91216
|
configurable: true
|
|
90901
91217
|
});
|
|
90902
|
-
Object.defineProperty(
|
|
91218
|
+
Object.defineProperty(fs3, "WriteStream", {
|
|
90903
91219
|
get: function() {
|
|
90904
91220
|
return WriteStream;
|
|
90905
91221
|
},
|
|
@@ -90910,7 +91226,7 @@ var require_graceful_fs = __commonJS({
|
|
|
90910
91226
|
configurable: true
|
|
90911
91227
|
});
|
|
90912
91228
|
var FileReadStream = ReadStream;
|
|
90913
|
-
Object.defineProperty(
|
|
91229
|
+
Object.defineProperty(fs3, "FileReadStream", {
|
|
90914
91230
|
get: function() {
|
|
90915
91231
|
return FileReadStream;
|
|
90916
91232
|
},
|
|
@@ -90921,7 +91237,7 @@ var require_graceful_fs = __commonJS({
|
|
|
90921
91237
|
configurable: true
|
|
90922
91238
|
});
|
|
90923
91239
|
var FileWriteStream = WriteStream;
|
|
90924
|
-
Object.defineProperty(
|
|
91240
|
+
Object.defineProperty(fs3, "FileWriteStream", {
|
|
90925
91241
|
get: function() {
|
|
90926
91242
|
return FileWriteStream;
|
|
90927
91243
|
},
|
|
@@ -90970,13 +91286,13 @@ var require_graceful_fs = __commonJS({
|
|
|
90970
91286
|
});
|
|
90971
91287
|
}
|
|
90972
91288
|
function createReadStream2(path4, options) {
|
|
90973
|
-
return new
|
|
91289
|
+
return new fs3.ReadStream(path4, options);
|
|
90974
91290
|
}
|
|
90975
91291
|
function createWriteStream2(path4, options) {
|
|
90976
|
-
return new
|
|
91292
|
+
return new fs3.WriteStream(path4, options);
|
|
90977
91293
|
}
|
|
90978
|
-
var fs$open =
|
|
90979
|
-
|
|
91294
|
+
var fs$open = fs3.open;
|
|
91295
|
+
fs3.open = open;
|
|
90980
91296
|
function open(path4, flags, mode, cb) {
|
|
90981
91297
|
if (typeof mode === "function")
|
|
90982
91298
|
cb = mode, mode = null;
|
|
@@ -90992,20 +91308,20 @@ var require_graceful_fs = __commonJS({
|
|
|
90992
91308
|
});
|
|
90993
91309
|
}
|
|
90994
91310
|
}
|
|
90995
|
-
return
|
|
91311
|
+
return fs3;
|
|
90996
91312
|
}
|
|
90997
91313
|
function enqueue(elem) {
|
|
90998
91314
|
debug("ENQUEUE", elem[0].name, elem[1]);
|
|
90999
|
-
|
|
91315
|
+
fs2[gracefulQueue].push(elem);
|
|
91000
91316
|
retry2();
|
|
91001
91317
|
}
|
|
91002
91318
|
var retryTimer;
|
|
91003
91319
|
function resetQueue() {
|
|
91004
91320
|
var now = Date.now();
|
|
91005
|
-
for (var i = 0; i <
|
|
91006
|
-
if (
|
|
91007
|
-
|
|
91008
|
-
|
|
91321
|
+
for (var i = 0; i < fs2[gracefulQueue].length; ++i) {
|
|
91322
|
+
if (fs2[gracefulQueue][i].length > 2) {
|
|
91323
|
+
fs2[gracefulQueue][i][3] = now;
|
|
91324
|
+
fs2[gracefulQueue][i][4] = now;
|
|
91009
91325
|
}
|
|
91010
91326
|
}
|
|
91011
91327
|
retry2();
|
|
@@ -91013,9 +91329,9 @@ var require_graceful_fs = __commonJS({
|
|
|
91013
91329
|
function retry2() {
|
|
91014
91330
|
clearTimeout(retryTimer);
|
|
91015
91331
|
retryTimer = void 0;
|
|
91016
|
-
if (
|
|
91332
|
+
if (fs2[gracefulQueue].length === 0)
|
|
91017
91333
|
return;
|
|
91018
|
-
var elem =
|
|
91334
|
+
var elem = fs2[gracefulQueue].shift();
|
|
91019
91335
|
var fn = elem[0];
|
|
91020
91336
|
var args = elem[1];
|
|
91021
91337
|
var err = elem[2];
|
|
@@ -91037,7 +91353,7 @@ var require_graceful_fs = __commonJS({
|
|
|
91037
91353
|
debug("RETRY", fn.name, args);
|
|
91038
91354
|
fn.apply(null, args.concat([startTime]));
|
|
91039
91355
|
} else {
|
|
91040
|
-
|
|
91356
|
+
fs2[gracefulQueue].push(elem);
|
|
91041
91357
|
}
|
|
91042
91358
|
}
|
|
91043
91359
|
if (retryTimer === void 0) {
|
|
@@ -106230,8 +106546,8 @@ var require_commonjs4 = __commonJS({
|
|
|
106230
106546
|
*
|
|
106231
106547
|
* @internal
|
|
106232
106548
|
*/
|
|
106233
|
-
constructor(cwd = process.cwd(), pathImpl, sep6, { nocase, childrenCacheSize = 16 * 1024, fs = defaultFS } = {}) {
|
|
106234
|
-
this.#fs = fsFromOption(
|
|
106549
|
+
constructor(cwd = process.cwd(), pathImpl, sep6, { nocase, childrenCacheSize = 16 * 1024, fs: fs2 = defaultFS } = {}) {
|
|
106550
|
+
this.#fs = fsFromOption(fs2);
|
|
106235
106551
|
if (cwd instanceof URL || cwd.startsWith("file://")) {
|
|
106236
106552
|
cwd = (0, node_url_1.fileURLToPath)(cwd);
|
|
106237
106553
|
}
|
|
@@ -106790,8 +107106,8 @@ var require_commonjs4 = __commonJS({
|
|
|
106790
107106
|
/**
|
|
106791
107107
|
* @internal
|
|
106792
107108
|
*/
|
|
106793
|
-
newRoot(
|
|
106794
|
-
return new PathWin32(this.rootPath, IFDIR, void 0, this.roots, this.nocase, this.childrenCache(), { fs });
|
|
107109
|
+
newRoot(fs2) {
|
|
107110
|
+
return new PathWin32(this.rootPath, IFDIR, void 0, this.roots, this.nocase, this.childrenCache(), { fs: fs2 });
|
|
106795
107111
|
}
|
|
106796
107112
|
/**
|
|
106797
107113
|
* Return true if the provided path string is an absolute path
|
|
@@ -106820,8 +107136,8 @@ var require_commonjs4 = __commonJS({
|
|
|
106820
107136
|
/**
|
|
106821
107137
|
* @internal
|
|
106822
107138
|
*/
|
|
106823
|
-
newRoot(
|
|
106824
|
-
return new PathPosix(this.rootPath, IFDIR, void 0, this.roots, this.nocase, this.childrenCache(), { fs });
|
|
107139
|
+
newRoot(fs2) {
|
|
107140
|
+
return new PathPosix(this.rootPath, IFDIR, void 0, this.roots, this.nocase, this.childrenCache(), { fs: fs2 });
|
|
106825
107141
|
}
|
|
106826
107142
|
/**
|
|
106827
107143
|
* Return true if the provided path string is an absolute path
|
|
@@ -108007,7 +108323,7 @@ var require_commonjs5 = __commonJS({
|
|
|
108007
108323
|
var require_file = __commonJS({
|
|
108008
108324
|
"../../node_modules/.pnpm/archiver-utils@5.0.2/node_modules/archiver-utils/file.js"(exports, module) {
|
|
108009
108325
|
"use strict";
|
|
108010
|
-
var
|
|
108326
|
+
var fs2 = require_graceful_fs();
|
|
108011
108327
|
var path4 = __require("path");
|
|
108012
108328
|
var flatten = require_flatten();
|
|
108013
108329
|
var difference = require_difference();
|
|
@@ -108034,7 +108350,7 @@ var require_file = __commonJS({
|
|
|
108034
108350
|
};
|
|
108035
108351
|
file.exists = function() {
|
|
108036
108352
|
var filepath = path4.join.apply(path4, arguments);
|
|
108037
|
-
return
|
|
108353
|
+
return fs2.existsSync(filepath);
|
|
108038
108354
|
};
|
|
108039
108355
|
file.expand = function(...args) {
|
|
108040
108356
|
var options = isPlainObject(args[0]) ? args.shift() : {};
|
|
@@ -108052,7 +108368,7 @@ var require_file = __commonJS({
|
|
|
108052
108368
|
if (typeof options.filter === "function") {
|
|
108053
108369
|
return options.filter(filepath);
|
|
108054
108370
|
} else {
|
|
108055
|
-
return
|
|
108371
|
+
return fs2.statSync(filepath)[options.filter]();
|
|
108056
108372
|
}
|
|
108057
108373
|
} catch (e) {
|
|
108058
108374
|
return false;
|
|
@@ -108161,7 +108477,7 @@ var require_file = __commonJS({
|
|
|
108161
108477
|
var require_archiver_utils = __commonJS({
|
|
108162
108478
|
"../../node_modules/.pnpm/archiver-utils@5.0.2/node_modules/archiver-utils/index.js"(exports, module) {
|
|
108163
108479
|
"use strict";
|
|
108164
|
-
var
|
|
108480
|
+
var fs2 = require_graceful_fs();
|
|
108165
108481
|
var path4 = __require("path");
|
|
108166
108482
|
var isStream = require_is_stream();
|
|
108167
108483
|
var lazystream = require_lazystream();
|
|
@@ -108210,7 +108526,7 @@ var require_archiver_utils = __commonJS({
|
|
|
108210
108526
|
};
|
|
108211
108527
|
utils.lazyReadStream = function(filepath) {
|
|
108212
108528
|
return new lazystream.Readable(function() {
|
|
108213
|
-
return
|
|
108529
|
+
return fs2.createReadStream(filepath);
|
|
108214
108530
|
});
|
|
108215
108531
|
};
|
|
108216
108532
|
utils.normalizeInputSource = function(source) {
|
|
@@ -108238,7 +108554,7 @@ var require_archiver_utils = __commonJS({
|
|
|
108238
108554
|
callback = base;
|
|
108239
108555
|
base = dirpath;
|
|
108240
108556
|
}
|
|
108241
|
-
|
|
108557
|
+
fs2.readdir(dirpath, function(err, list) {
|
|
108242
108558
|
var i = 0;
|
|
108243
108559
|
var file;
|
|
108244
108560
|
var filepath;
|
|
@@ -108251,7 +108567,7 @@ var require_archiver_utils = __commonJS({
|
|
|
108251
108567
|
return callback(null, results);
|
|
108252
108568
|
}
|
|
108253
108569
|
filepath = path4.join(dirpath, file);
|
|
108254
|
-
|
|
108570
|
+
fs2.stat(filepath, function(err2, stats) {
|
|
108255
108571
|
results.push({
|
|
108256
108572
|
path: filepath,
|
|
108257
108573
|
relative: path4.relative(base, filepath).replace(/\\/g, "/"),
|
|
@@ -108315,7 +108631,7 @@ var require_error = __commonJS({
|
|
|
108315
108631
|
var require_core = __commonJS({
|
|
108316
108632
|
"../../node_modules/.pnpm/archiver@7.0.1/node_modules/archiver/lib/core.js"(exports, module) {
|
|
108317
108633
|
"use strict";
|
|
108318
|
-
var
|
|
108634
|
+
var fs2 = __require("fs");
|
|
108319
108635
|
var glob2 = require_readdir_glob();
|
|
108320
108636
|
var async = (init_async(), __toCommonJS(async_exports));
|
|
108321
108637
|
var path4 = __require("path");
|
|
@@ -108379,7 +108695,7 @@ var require_core = __commonJS({
|
|
|
108379
108695
|
data.sourcePath = filepath;
|
|
108380
108696
|
task.data = data;
|
|
108381
108697
|
this._entriesCount++;
|
|
108382
|
-
if (data.stats && data.stats instanceof
|
|
108698
|
+
if (data.stats && data.stats instanceof fs2.Stats) {
|
|
108383
108699
|
task = this._updateQueueTaskWithStats(task, data.stats);
|
|
108384
108700
|
if (task) {
|
|
108385
108701
|
if (data.stats.size) {
|
|
@@ -108550,7 +108866,7 @@ var require_core = __commonJS({
|
|
|
108550
108866
|
callback();
|
|
108551
108867
|
return;
|
|
108552
108868
|
}
|
|
108553
|
-
|
|
108869
|
+
fs2.lstat(task.filepath, function(err, stats) {
|
|
108554
108870
|
if (this._state.aborted) {
|
|
108555
108871
|
setImmediate(callback);
|
|
108556
108872
|
return;
|
|
@@ -108593,7 +108909,7 @@ var require_core = __commonJS({
|
|
|
108593
108909
|
task.data.sourceType = "buffer";
|
|
108594
108910
|
task.source = Buffer.concat([]);
|
|
108595
108911
|
} else if (stats.isSymbolicLink() && this._moduleSupports("symlink")) {
|
|
108596
|
-
var linkPath =
|
|
108912
|
+
var linkPath = fs2.readlinkSync(task.filepath);
|
|
108597
108913
|
var dirName = path4.dirname(task.filepath);
|
|
108598
108914
|
task.data.type = "symlink";
|
|
108599
108915
|
task.data.linkname = path4.relative(dirName, path4.resolve(dirName, linkPath));
|
|
@@ -115135,9 +115451,10 @@ function createApiRoutes(store, options) {
|
|
|
115135
115451
|
try {
|
|
115136
115452
|
const { store: scopedStore } = await getProjectContext2(req);
|
|
115137
115453
|
const settings = await scopedStore.getSettingsFast();
|
|
115454
|
+
const prAuthAvailable = isGhAvailable() && isGhAuthenticated() || Boolean(githubToken);
|
|
115138
115455
|
res.json({
|
|
115139
115456
|
...settings,
|
|
115140
|
-
|
|
115457
|
+
prAuthAvailable
|
|
115141
115458
|
});
|
|
115142
115459
|
} catch (err) {
|
|
115143
115460
|
if (err instanceof ApiError) {
|
|
@@ -115149,7 +115466,7 @@ function createApiRoutes(store, options) {
|
|
|
115149
115466
|
router.put("/settings", async (req, res) => {
|
|
115150
115467
|
try {
|
|
115151
115468
|
const { store: scopedStore, engine } = await getProjectContext2(req);
|
|
115152
|
-
const { githubTokenConfigured, ...clientSettings } = req.body;
|
|
115469
|
+
const { githubTokenConfigured, prAuthAvailable, ...clientSettings } = req.body;
|
|
115153
115470
|
const globalKeySet = new Set(GLOBAL_SETTINGS_KEYS);
|
|
115154
115471
|
const globalFieldsFound = Object.keys(clientSettings).filter((k) => globalKeySet.has(k));
|
|
115155
115472
|
if (globalFieldsFound.length > 0) {
|
|
@@ -132288,7 +132605,7 @@ function setupTerminalWebSocket(app, server, store, options) {
|
|
|
132288
132605
|
if (pathname !== "/api/terminal/ws") {
|
|
132289
132606
|
return;
|
|
132290
132607
|
}
|
|
132291
|
-
if (wsDaemonToken && !authenticateUpgradeRequest(wsDaemonToken, req)) {
|
|
132608
|
+
if (wsDaemonToken && !options?.noAuth && !authenticateUpgradeRequest(wsDaemonToken, req)) {
|
|
132292
132609
|
socket.write("HTTP/1.1 401 Unauthorized\r\nConnection: close\r\n\r\n");
|
|
132293
132610
|
socket.destroy();
|
|
132294
132611
|
return;
|
|
@@ -132479,7 +132796,7 @@ function setupBadgeWebSocket(app, server, store, options) {
|
|
|
132479
132796
|
if (pathname !== "/api/ws") {
|
|
132480
132797
|
return;
|
|
132481
132798
|
}
|
|
132482
|
-
if (badgeWsDaemonToken && !authenticateUpgradeRequest(badgeWsDaemonToken, req)) {
|
|
132799
|
+
if (badgeWsDaemonToken && !options?.noAuth && !authenticateUpgradeRequest(badgeWsDaemonToken, req)) {
|
|
132483
132800
|
socket.write("HTTP/1.1 401 Unauthorized\r\nConnection: close\r\n\r\n");
|
|
132484
132801
|
socket.destroy();
|
|
132485
132802
|
return;
|
|
@@ -133738,9 +134055,1014 @@ var init_project_context = __esm({
|
|
|
133738
134055
|
}
|
|
133739
134056
|
});
|
|
133740
134057
|
|
|
134058
|
+
// src/commands/dashboard-tui.ts
|
|
134059
|
+
import * as readline from "node:readline";
|
|
134060
|
+
function moveCursorTo(x, y) {
|
|
134061
|
+
process.stdout.write(`\x1B[${y};${x}H`);
|
|
134062
|
+
}
|
|
134063
|
+
function clearLine() {
|
|
134064
|
+
process.stdout.write("\x1B[2K");
|
|
134065
|
+
}
|
|
134066
|
+
function clearScreen() {
|
|
134067
|
+
process.stdout.write("\x1B[2J");
|
|
134068
|
+
}
|
|
134069
|
+
function hideCursor() {
|
|
134070
|
+
process.stdout.write("\x1B[?25l");
|
|
134071
|
+
}
|
|
134072
|
+
function showCursor() {
|
|
134073
|
+
process.stdout.write("\x1B[?25h");
|
|
134074
|
+
}
|
|
134075
|
+
function enableAlternateScreen() {
|
|
134076
|
+
process.stdout.write("\x1B[?47h");
|
|
134077
|
+
}
|
|
134078
|
+
function disableAlternateScreen() {
|
|
134079
|
+
process.stdout.write("\x1B[?47l");
|
|
134080
|
+
}
|
|
134081
|
+
function colorize(text, color) {
|
|
134082
|
+
const colors = {
|
|
134083
|
+
reset: "\x1B[0m",
|
|
134084
|
+
bold: "\x1B[1m",
|
|
134085
|
+
dim: "\x1B[2m",
|
|
134086
|
+
red: "\x1B[31m",
|
|
134087
|
+
green: "\x1B[32m",
|
|
134088
|
+
yellow: "\x1B[33m",
|
|
134089
|
+
blue: "\x1B[34m",
|
|
134090
|
+
magenta: "\x1B[35m",
|
|
134091
|
+
cyan: "\x1B[36m",
|
|
134092
|
+
white: "\x1B[37m",
|
|
134093
|
+
gray: "\x1B[90m",
|
|
134094
|
+
brightRed: "\x1B[91m",
|
|
134095
|
+
brightGreen: "\x1B[92m",
|
|
134096
|
+
brightYellow: "\x1B[93m",
|
|
134097
|
+
brightBlue: "\x1B[94m",
|
|
134098
|
+
brightMagenta: "\x1B[95m",
|
|
134099
|
+
brightCyan: "\x1B[96m"
|
|
134100
|
+
};
|
|
134101
|
+
return `${colors[color] || ""}${text}${colors.reset}`;
|
|
134102
|
+
}
|
|
134103
|
+
function formatTimestamp3(date) {
|
|
134104
|
+
const h = date.getHours().toString().padStart(2, "0");
|
|
134105
|
+
const m = date.getMinutes().toString().padStart(2, "0");
|
|
134106
|
+
const s = date.getSeconds().toString().padStart(2, "0");
|
|
134107
|
+
const ms = date.getMilliseconds().toString().padStart(3, "0");
|
|
134108
|
+
return `${h}:${m}:${s}.${ms}`;
|
|
134109
|
+
}
|
|
134110
|
+
function formatUptime(ms) {
|
|
134111
|
+
const seconds = Math.floor(ms / 1e3);
|
|
134112
|
+
const minutes = Math.floor(seconds / 60);
|
|
134113
|
+
const hours = Math.floor(minutes / 60);
|
|
134114
|
+
const days = Math.floor(hours / 24);
|
|
134115
|
+
if (days > 0) return `${days}d ${hours % 24}h ${minutes % 60}m`;
|
|
134116
|
+
if (hours > 0) return `${hours}h ${minutes % 60}m ${seconds % 60}s`;
|
|
134117
|
+
if (minutes > 0) return `${minutes}m ${seconds % 60}s`;
|
|
134118
|
+
return `${seconds}s`;
|
|
134119
|
+
}
|
|
134120
|
+
function visibleLength(str) {
|
|
134121
|
+
return str.replace(/\x1b\[[0-9;]*[a-zA-Z]/g, "").length;
|
|
134122
|
+
}
|
|
134123
|
+
function visibleTruncate(text, maxWidth) {
|
|
134124
|
+
if (maxWidth <= 0) return "";
|
|
134125
|
+
const currentLength = visibleLength(text);
|
|
134126
|
+
if (currentLength <= maxWidth) return text;
|
|
134127
|
+
const ansiRegex = /\x1b\[[0-9;]*[a-zA-Z]/g;
|
|
134128
|
+
let result = "";
|
|
134129
|
+
let visibleCount = 0;
|
|
134130
|
+
let match;
|
|
134131
|
+
const ansiMatches = [];
|
|
134132
|
+
while ((match = ansiRegex.exec(text)) !== null) {
|
|
134133
|
+
ansiMatches.push({
|
|
134134
|
+
start: match.index,
|
|
134135
|
+
end: match.index + match[0].length,
|
|
134136
|
+
seq: match[0]
|
|
134137
|
+
});
|
|
134138
|
+
}
|
|
134139
|
+
for (let i = 0; i < text.length; i++) {
|
|
134140
|
+
const char = text[i];
|
|
134141
|
+
const ansiMatch = ansiMatches.find((m) => m.start === i);
|
|
134142
|
+
if (ansiMatch) {
|
|
134143
|
+
result += ansiMatch.seq;
|
|
134144
|
+
continue;
|
|
134145
|
+
}
|
|
134146
|
+
visibleCount++;
|
|
134147
|
+
result += char;
|
|
134148
|
+
if (visibleCount >= maxWidth - 3) {
|
|
134149
|
+
break;
|
|
134150
|
+
}
|
|
134151
|
+
}
|
|
134152
|
+
if (visibleCount >= maxWidth - 3 && visibleCount < currentLength) {
|
|
134153
|
+
result += "...";
|
|
134154
|
+
}
|
|
134155
|
+
return result;
|
|
134156
|
+
}
|
|
134157
|
+
function formatConsoleArgs(args) {
|
|
134158
|
+
const stringified = args.map((arg) => {
|
|
134159
|
+
if (typeof arg === "string") return arg;
|
|
134160
|
+
if (arg instanceof Error) return arg.stack ?? arg.message;
|
|
134161
|
+
if (arg === null || arg === void 0) return String(arg);
|
|
134162
|
+
if (typeof arg === "object") {
|
|
134163
|
+
try {
|
|
134164
|
+
return JSON.stringify(arg);
|
|
134165
|
+
} catch {
|
|
134166
|
+
return String(arg);
|
|
134167
|
+
}
|
|
134168
|
+
}
|
|
134169
|
+
return String(arg);
|
|
134170
|
+
}).join(" ");
|
|
134171
|
+
const match = stringified.match(/^\[([^\]]+)\]\s*(.*)$/s);
|
|
134172
|
+
if (match) {
|
|
134173
|
+
return { prefix: match[1], message: match[2] };
|
|
134174
|
+
}
|
|
134175
|
+
return { message: stringified };
|
|
134176
|
+
}
|
|
134177
|
+
function centerText(text, width, padChar = " ") {
|
|
134178
|
+
const visibleLen = visibleLength(text);
|
|
134179
|
+
const padding = Math.max(0, width - visibleLen);
|
|
134180
|
+
const leftPad = Math.floor(padding / 2);
|
|
134181
|
+
const rightPad = padding - leftPad;
|
|
134182
|
+
return padChar.repeat(leftPad) + text + padChar.repeat(rightPad);
|
|
134183
|
+
}
|
|
134184
|
+
function isTTYAvailable() {
|
|
134185
|
+
return Boolean(process.stdout.isTTY && process.stdin.isTTY);
|
|
134186
|
+
}
|
|
134187
|
+
var MAX_LOG_ENTRIES, LogRingBuffer, SECTION_ORDER, DashboardTUI, DashboardLogSink;
|
|
134188
|
+
var init_dashboard_tui = __esm({
|
|
134189
|
+
"src/commands/dashboard-tui.ts"() {
|
|
134190
|
+
"use strict";
|
|
134191
|
+
MAX_LOG_ENTRIES = 1e3;
|
|
134192
|
+
LogRingBuffer = class {
|
|
134193
|
+
entries = [];
|
|
134194
|
+
count = 0;
|
|
134195
|
+
push(entry) {
|
|
134196
|
+
if (this.entries.length < MAX_LOG_ENTRIES) {
|
|
134197
|
+
this.entries.push(entry);
|
|
134198
|
+
} else {
|
|
134199
|
+
this.entries[this.count % MAX_LOG_ENTRIES] = entry;
|
|
134200
|
+
}
|
|
134201
|
+
this.count++;
|
|
134202
|
+
}
|
|
134203
|
+
getAll() {
|
|
134204
|
+
if (this.count <= MAX_LOG_ENTRIES) {
|
|
134205
|
+
return this.entries.slice();
|
|
134206
|
+
}
|
|
134207
|
+
const start = this.count % MAX_LOG_ENTRIES;
|
|
134208
|
+
return [
|
|
134209
|
+
...this.entries.slice(start),
|
|
134210
|
+
...this.entries.slice(0, start)
|
|
134211
|
+
];
|
|
134212
|
+
}
|
|
134213
|
+
clear() {
|
|
134214
|
+
this.entries = [];
|
|
134215
|
+
this.count = 0;
|
|
134216
|
+
}
|
|
134217
|
+
get total() {
|
|
134218
|
+
return this.count;
|
|
134219
|
+
}
|
|
134220
|
+
};
|
|
134221
|
+
SECTION_ORDER = ["system", "logs", "utilities", "stats", "settings"];
|
|
134222
|
+
DashboardTUI = class {
|
|
134223
|
+
activeSection = "system";
|
|
134224
|
+
logBuffer;
|
|
134225
|
+
systemInfo = null;
|
|
134226
|
+
taskStats = null;
|
|
134227
|
+
settings = null;
|
|
134228
|
+
callbacks = null;
|
|
134229
|
+
isRunning = false;
|
|
134230
|
+
rl = null;
|
|
134231
|
+
originalHandlers = /* @__PURE__ */ new Map();
|
|
134232
|
+
lastRenderHeight = 0;
|
|
134233
|
+
showHelp = false;
|
|
134234
|
+
uptimeTimer = null;
|
|
134235
|
+
resizeHandler = null;
|
|
134236
|
+
// Logs interaction state
|
|
134237
|
+
selectedLogIndex = 0;
|
|
134238
|
+
logsViewportStart = 0;
|
|
134239
|
+
logsWrapEnabled = false;
|
|
134240
|
+
logsExpandedMode = false;
|
|
134241
|
+
constructor() {
|
|
134242
|
+
this.logBuffer = new LogRingBuffer();
|
|
134243
|
+
}
|
|
134244
|
+
// ── Public API ─────────────────────────────────────────────────────────────
|
|
134245
|
+
/** Returns whether the TUI is currently running */
|
|
134246
|
+
get running() {
|
|
134247
|
+
return this.isRunning;
|
|
134248
|
+
}
|
|
134249
|
+
setCallbacks(callbacks) {
|
|
134250
|
+
this.callbacks = callbacks;
|
|
134251
|
+
}
|
|
134252
|
+
setSystemInfo(info) {
|
|
134253
|
+
this.systemInfo = info;
|
|
134254
|
+
this.render();
|
|
134255
|
+
}
|
|
134256
|
+
setTaskStats(stats) {
|
|
134257
|
+
this.taskStats = stats;
|
|
134258
|
+
this.render();
|
|
134259
|
+
}
|
|
134260
|
+
setSettings(settings) {
|
|
134261
|
+
this.settings = settings;
|
|
134262
|
+
this.render();
|
|
134263
|
+
}
|
|
134264
|
+
addLog(entry) {
|
|
134265
|
+
this.logBuffer.push({
|
|
134266
|
+
...entry,
|
|
134267
|
+
timestamp: /* @__PURE__ */ new Date()
|
|
134268
|
+
});
|
|
134269
|
+
const newLength = this.logBuffer.getAll().length;
|
|
134270
|
+
if (this.selectedLogIndex >= newLength) {
|
|
134271
|
+
this.selectedLogIndex = Math.max(0, newLength - 1);
|
|
134272
|
+
}
|
|
134273
|
+
this.render();
|
|
134274
|
+
}
|
|
134275
|
+
/**
|
|
134276
|
+
* Clear logs and reset selection state.
|
|
134277
|
+
*/
|
|
134278
|
+
clearLogs() {
|
|
134279
|
+
this.logBuffer.clear();
|
|
134280
|
+
this.selectedLogIndex = 0;
|
|
134281
|
+
this.logsViewportStart = 0;
|
|
134282
|
+
this.logsExpandedMode = false;
|
|
134283
|
+
}
|
|
134284
|
+
log(message, prefix) {
|
|
134285
|
+
this.addLog({ level: "info", message, prefix });
|
|
134286
|
+
}
|
|
134287
|
+
warn(message, prefix) {
|
|
134288
|
+
this.addLog({ level: "warn", message, prefix });
|
|
134289
|
+
}
|
|
134290
|
+
error(message, prefix) {
|
|
134291
|
+
this.addLog({ level: "error", message, prefix });
|
|
134292
|
+
}
|
|
134293
|
+
async start() {
|
|
134294
|
+
if (this.isRunning) return;
|
|
134295
|
+
this.isRunning = true;
|
|
134296
|
+
enableAlternateScreen();
|
|
134297
|
+
hideCursor();
|
|
134298
|
+
this.saveSignalHandlers();
|
|
134299
|
+
this.rl = readline.createInterface({
|
|
134300
|
+
input: process.stdin,
|
|
134301
|
+
output: process.stdout,
|
|
134302
|
+
terminal: true
|
|
134303
|
+
});
|
|
134304
|
+
process.stdin.setRawMode?.(true);
|
|
134305
|
+
process.stdin.resume();
|
|
134306
|
+
process.stdin.setEncoding("utf8");
|
|
134307
|
+
readline.emitKeypressEvents(process.stdin);
|
|
134308
|
+
process.stdin.on("keypress", (str, key) => {
|
|
134309
|
+
if (str) {
|
|
134310
|
+
this.handleKeypress(str);
|
|
134311
|
+
} else if (key.ctrl && key.name === "c") {
|
|
134312
|
+
this.handleKeypress("");
|
|
134313
|
+
} else if (key.name === "return" || key.name === "enter") {
|
|
134314
|
+
this.handleKeypress("\r");
|
|
134315
|
+
} else if (key.name === "right") {
|
|
134316
|
+
this.handleKeypress("\x1B[C");
|
|
134317
|
+
} else if (key.name === "left") {
|
|
134318
|
+
this.handleKeypress("\x1B[D");
|
|
134319
|
+
} else if (key.name === "up") {
|
|
134320
|
+
this.handleKeypress("\x1B[A");
|
|
134321
|
+
} else if (key.name === "down") {
|
|
134322
|
+
this.handleKeypress("\x1B[B");
|
|
134323
|
+
} else if (key.name === "escape") {
|
|
134324
|
+
this.handleKeypress("\x1B");
|
|
134325
|
+
} else if (key.name === "home") {
|
|
134326
|
+
this.handleKeypress("Home");
|
|
134327
|
+
} else if (key.name === "end") {
|
|
134328
|
+
this.handleKeypress("End");
|
|
134329
|
+
} else if (key.name === "space") {
|
|
134330
|
+
this.handleKeypress(" ");
|
|
134331
|
+
}
|
|
134332
|
+
});
|
|
134333
|
+
this.uptimeTimer = setInterval(() => {
|
|
134334
|
+
if (this.isRunning) {
|
|
134335
|
+
this.renderFooter();
|
|
134336
|
+
}
|
|
134337
|
+
}, 5e3);
|
|
134338
|
+
this.resizeHandler = () => {
|
|
134339
|
+
if (this.isRunning) {
|
|
134340
|
+
this.render();
|
|
134341
|
+
}
|
|
134342
|
+
};
|
|
134343
|
+
process.stdout.on("resize", this.resizeHandler);
|
|
134344
|
+
this.render();
|
|
134345
|
+
}
|
|
134346
|
+
async stop() {
|
|
134347
|
+
if (!this.isRunning) return;
|
|
134348
|
+
this.isRunning = false;
|
|
134349
|
+
if (this.uptimeTimer) {
|
|
134350
|
+
clearInterval(this.uptimeTimer);
|
|
134351
|
+
this.uptimeTimer = null;
|
|
134352
|
+
}
|
|
134353
|
+
if (this.resizeHandler) {
|
|
134354
|
+
process.stdout.off("resize", this.resizeHandler);
|
|
134355
|
+
this.resizeHandler = null;
|
|
134356
|
+
}
|
|
134357
|
+
this.restoreTerminal();
|
|
134358
|
+
this.restoreSignalHandlers();
|
|
134359
|
+
if (this.rl) {
|
|
134360
|
+
this.rl.close();
|
|
134361
|
+
this.rl = null;
|
|
134362
|
+
}
|
|
134363
|
+
}
|
|
134364
|
+
// ── Private: Signal Handling ───────────────────────────────────────────────
|
|
134365
|
+
saveSignalHandlers() {
|
|
134366
|
+
const signals = ["SIGINT", "SIGTERM", "SIGHUP"];
|
|
134367
|
+
for (const sig of signals) {
|
|
134368
|
+
const listeners = process.listeners(sig);
|
|
134369
|
+
if (listeners.length > 0) {
|
|
134370
|
+
this.originalHandlers.set(sig, listeners[listeners.length - 1]);
|
|
134371
|
+
}
|
|
134372
|
+
}
|
|
134373
|
+
}
|
|
134374
|
+
restoreSignalHandlers() {
|
|
134375
|
+
for (const [sig, handler] of this.originalHandlers) {
|
|
134376
|
+
process.on(sig, handler);
|
|
134377
|
+
}
|
|
134378
|
+
this.originalHandlers.clear();
|
|
134379
|
+
}
|
|
134380
|
+
// ── Private: Terminal Restoration ────────────────────────────────────────
|
|
134381
|
+
restoreTerminal() {
|
|
134382
|
+
showCursor();
|
|
134383
|
+
disableAlternateScreen();
|
|
134384
|
+
process.stdout.write("\n");
|
|
134385
|
+
process.stdin.pause?.();
|
|
134386
|
+
process.stdin.setRawMode?.(false);
|
|
134387
|
+
}
|
|
134388
|
+
// ── Private: Key Handling ────────────────────────────────────────────────
|
|
134389
|
+
handleKeypress(key) {
|
|
134390
|
+
if (key === "") {
|
|
134391
|
+
void this.stop();
|
|
134392
|
+
process.exit(0);
|
|
134393
|
+
return;
|
|
134394
|
+
}
|
|
134395
|
+
if (key === "q" || key === "Q") {
|
|
134396
|
+
void this.stop();
|
|
134397
|
+
process.exit(0);
|
|
134398
|
+
return;
|
|
134399
|
+
}
|
|
134400
|
+
if (key === "?" || key === "h" || key === "H") {
|
|
134401
|
+
this.showHelp = !this.showHelp;
|
|
134402
|
+
this.render();
|
|
134403
|
+
return;
|
|
134404
|
+
}
|
|
134405
|
+
if (key >= "1" && key <= "5") {
|
|
134406
|
+
const index2 = parseInt(key, 10) - 1;
|
|
134407
|
+
if (index2 >= 0 && index2 < SECTION_ORDER.length) {
|
|
134408
|
+
this.activeSection = SECTION_ORDER[index2];
|
|
134409
|
+
this.showHelp = false;
|
|
134410
|
+
this.render();
|
|
134411
|
+
}
|
|
134412
|
+
return;
|
|
134413
|
+
}
|
|
134414
|
+
if (key === "\x1B[C" || key === "n" || key === "N") {
|
|
134415
|
+
const currentIndex = SECTION_ORDER.indexOf(this.activeSection);
|
|
134416
|
+
this.activeSection = SECTION_ORDER[(currentIndex + 1) % SECTION_ORDER.length];
|
|
134417
|
+
this.showHelp = false;
|
|
134418
|
+
this.render();
|
|
134419
|
+
return;
|
|
134420
|
+
}
|
|
134421
|
+
if (key === "\x1B[D" || key === "p" || key === "P") {
|
|
134422
|
+
const currentIndex = SECTION_ORDER.indexOf(this.activeSection);
|
|
134423
|
+
this.activeSection = SECTION_ORDER[(currentIndex - 1 + SECTION_ORDER.length) % SECTION_ORDER.length];
|
|
134424
|
+
this.showHelp = false;
|
|
134425
|
+
this.render();
|
|
134426
|
+
return;
|
|
134427
|
+
}
|
|
134428
|
+
if (this.activeSection === "utilities") {
|
|
134429
|
+
this.handleUtilityKeypress(key);
|
|
134430
|
+
return;
|
|
134431
|
+
}
|
|
134432
|
+
if (this.activeSection === "logs") {
|
|
134433
|
+
this.handleLogsKeypress(key);
|
|
134434
|
+
return;
|
|
134435
|
+
}
|
|
134436
|
+
}
|
|
134437
|
+
handleLogsKeypress(key) {
|
|
134438
|
+
const entries = this.logBuffer.getAll();
|
|
134439
|
+
const maxIndex = Math.max(0, entries.length - 1);
|
|
134440
|
+
if (key === "\x1B") {
|
|
134441
|
+
if (this.logsExpandedMode) {
|
|
134442
|
+
this.logsExpandedMode = false;
|
|
134443
|
+
this.showHelp = false;
|
|
134444
|
+
this.render();
|
|
134445
|
+
} else if (this.showHelp) {
|
|
134446
|
+
this.showHelp = false;
|
|
134447
|
+
this.render();
|
|
134448
|
+
}
|
|
134449
|
+
return;
|
|
134450
|
+
}
|
|
134451
|
+
if (key === "\r") {
|
|
134452
|
+
if (entries.length === 0) {
|
|
134453
|
+
return;
|
|
134454
|
+
}
|
|
134455
|
+
this.logsExpandedMode = !this.logsExpandedMode;
|
|
134456
|
+
this.render();
|
|
134457
|
+
return;
|
|
134458
|
+
}
|
|
134459
|
+
if (key === "w" || key === "W") {
|
|
134460
|
+
this.logsWrapEnabled = !this.logsWrapEnabled;
|
|
134461
|
+
this.render();
|
|
134462
|
+
return;
|
|
134463
|
+
}
|
|
134464
|
+
if (key === "\x1B[A" || key === "k" || key === "K") {
|
|
134465
|
+
if (entries.length === 0) return;
|
|
134466
|
+
if (this.selectedLogIndex > 0) {
|
|
134467
|
+
this.selectedLogIndex--;
|
|
134468
|
+
this.render();
|
|
134469
|
+
}
|
|
134470
|
+
return;
|
|
134471
|
+
}
|
|
134472
|
+
if (key === "\x1B[B" || key === "j" || key === "J") {
|
|
134473
|
+
if (entries.length === 0) return;
|
|
134474
|
+
if (this.selectedLogIndex < maxIndex) {
|
|
134475
|
+
this.selectedLogIndex++;
|
|
134476
|
+
this.render();
|
|
134477
|
+
}
|
|
134478
|
+
return;
|
|
134479
|
+
}
|
|
134480
|
+
if (key === "Home") {
|
|
134481
|
+
if (entries.length === 0) return;
|
|
134482
|
+
if (this.selectedLogIndex !== 0) {
|
|
134483
|
+
this.selectedLogIndex = 0;
|
|
134484
|
+
this.render();
|
|
134485
|
+
}
|
|
134486
|
+
return;
|
|
134487
|
+
}
|
|
134488
|
+
if (key === "End") {
|
|
134489
|
+
if (entries.length === 0) return;
|
|
134490
|
+
if (this.selectedLogIndex !== maxIndex) {
|
|
134491
|
+
this.selectedLogIndex = maxIndex;
|
|
134492
|
+
this.render();
|
|
134493
|
+
}
|
|
134494
|
+
return;
|
|
134495
|
+
}
|
|
134496
|
+
if (key === " " || key === "e" || key === "E") {
|
|
134497
|
+
if (entries.length === 0) {
|
|
134498
|
+
return;
|
|
134499
|
+
}
|
|
134500
|
+
this.logsExpandedMode = !this.logsExpandedMode;
|
|
134501
|
+
this.render();
|
|
134502
|
+
return;
|
|
134503
|
+
}
|
|
134504
|
+
}
|
|
134505
|
+
async handleUtilityKeypress(key) {
|
|
134506
|
+
if (!this.callbacks) return;
|
|
134507
|
+
switch (key.toLowerCase()) {
|
|
134508
|
+
case "r":
|
|
134509
|
+
await this.callbacks.onRefreshStats();
|
|
134510
|
+
break;
|
|
134511
|
+
case "c":
|
|
134512
|
+
this.callbacks.onClearLogs();
|
|
134513
|
+
this.clearLogs();
|
|
134514
|
+
break;
|
|
134515
|
+
case "t":
|
|
134516
|
+
if (this.systemInfo) {
|
|
134517
|
+
const newPaused = this.systemInfo.engineMode !== "paused";
|
|
134518
|
+
const newSettings = await this.callbacks.onTogglePause(newPaused);
|
|
134519
|
+
const newEngineMode = newSettings.enginePaused ? "paused" : "active";
|
|
134520
|
+
this.setSystemInfo({ ...this.systemInfo, engineMode: newEngineMode });
|
|
134521
|
+
this.setSettings(newSettings);
|
|
134522
|
+
}
|
|
134523
|
+
break;
|
|
134524
|
+
}
|
|
134525
|
+
}
|
|
134526
|
+
// ── Private: Rendering ───────────────────────────────────────────────────
|
|
134527
|
+
render() {
|
|
134528
|
+
if (!this.isRunning) return;
|
|
134529
|
+
clearScreen();
|
|
134530
|
+
moveCursorTo(1, 1);
|
|
134531
|
+
this.renderHeader();
|
|
134532
|
+
this.renderSection();
|
|
134533
|
+
this.renderFooter();
|
|
134534
|
+
if (this.showHelp) {
|
|
134535
|
+
this.renderHelpOverlay();
|
|
134536
|
+
}
|
|
134537
|
+
}
|
|
134538
|
+
renderHeader() {
|
|
134539
|
+
const cols = process.stdout.columns || 80;
|
|
134540
|
+
const title = colorize(" fusion ", "cyan");
|
|
134541
|
+
const titleLen = visibleLength(title);
|
|
134542
|
+
process.stdout.write(title);
|
|
134543
|
+
if (cols >= 70) {
|
|
134544
|
+
for (let i = 0; i < SECTION_ORDER.length; i++) {
|
|
134545
|
+
const section = SECTION_ORDER[i];
|
|
134546
|
+
const isActive = section === this.activeSection;
|
|
134547
|
+
const num = (i + 1).toString();
|
|
134548
|
+
const label = section.charAt(0).toUpperCase() + section.slice(1);
|
|
134549
|
+
const tabText = `[${num}] ${label}`;
|
|
134550
|
+
const style = isActive ? "brightBlue" : "dim";
|
|
134551
|
+
process.stdout.write(colorize(` ${tabText} `, style));
|
|
134552
|
+
}
|
|
134553
|
+
} else if (cols >= 40) {
|
|
134554
|
+
const shortLabels = {
|
|
134555
|
+
logs: "L",
|
|
134556
|
+
system: "S",
|
|
134557
|
+
utilities: "U",
|
|
134558
|
+
stats: "St",
|
|
134559
|
+
settings: "Se"
|
|
134560
|
+
};
|
|
134561
|
+
for (let i = 0; i < SECTION_ORDER.length; i++) {
|
|
134562
|
+
const section = SECTION_ORDER[i];
|
|
134563
|
+
const isActive = section === this.activeSection;
|
|
134564
|
+
const num = (i + 1).toString();
|
|
134565
|
+
const shortLabel = shortLabels[section];
|
|
134566
|
+
const tabText = `[${num}]${shortLabel}`;
|
|
134567
|
+
const style = isActive ? "brightBlue" : "dim";
|
|
134568
|
+
process.stdout.write(colorize(` ${tabText} `, style));
|
|
134569
|
+
}
|
|
134570
|
+
} else {
|
|
134571
|
+
const activeIndex = SECTION_ORDER.indexOf(this.activeSection);
|
|
134572
|
+
const activeLabel = this.activeSection.charAt(0).toUpperCase() + this.activeSection.slice(1);
|
|
134573
|
+
process.stdout.write(colorize(` [${activeIndex + 1}]${activeLabel} `, "brightBlue"));
|
|
134574
|
+
process.stdout.write(colorize(" [n/p]nav ", "dim"));
|
|
134575
|
+
}
|
|
134576
|
+
const tabsLength = SECTION_ORDER.reduce((acc, s, i) => {
|
|
134577
|
+
let label;
|
|
134578
|
+
if (cols >= 70) {
|
|
134579
|
+
label = s.charAt(0).toUpperCase() + s.slice(1);
|
|
134580
|
+
} else if (cols >= 40) {
|
|
134581
|
+
const shortLabels = {
|
|
134582
|
+
logs: "L",
|
|
134583
|
+
system: "S",
|
|
134584
|
+
utilities: "U",
|
|
134585
|
+
stats: "St",
|
|
134586
|
+
settings: "Se"
|
|
134587
|
+
};
|
|
134588
|
+
label = shortLabels[s];
|
|
134589
|
+
} else {
|
|
134590
|
+
label = s.charAt(0).toUpperCase() + s.slice(1);
|
|
134591
|
+
}
|
|
134592
|
+
const tabText = `[${i + 1}]${label} `;
|
|
134593
|
+
return acc + tabText.length;
|
|
134594
|
+
}, 0);
|
|
134595
|
+
const headerLen = titleLen + tabsLength;
|
|
134596
|
+
const remaining = cols - headerLen;
|
|
134597
|
+
if (remaining > 0) {
|
|
134598
|
+
process.stdout.write(" ".repeat(remaining));
|
|
134599
|
+
}
|
|
134600
|
+
process.stdout.write("\n");
|
|
134601
|
+
process.stdout.write(colorize("\u2500".repeat(Math.max(20, cols)), "dim") + "\n");
|
|
134602
|
+
}
|
|
134603
|
+
renderSection() {
|
|
134604
|
+
switch (this.activeSection) {
|
|
134605
|
+
case "logs":
|
|
134606
|
+
this.renderLogsSection();
|
|
134607
|
+
break;
|
|
134608
|
+
case "system":
|
|
134609
|
+
this.renderSystemSection();
|
|
134610
|
+
break;
|
|
134611
|
+
case "utilities":
|
|
134612
|
+
this.renderUtilitiesSection();
|
|
134613
|
+
break;
|
|
134614
|
+
case "stats":
|
|
134615
|
+
this.renderStatsSection();
|
|
134616
|
+
break;
|
|
134617
|
+
case "settings":
|
|
134618
|
+
this.renderSettingsSection();
|
|
134619
|
+
break;
|
|
134620
|
+
}
|
|
134621
|
+
}
|
|
134622
|
+
getLogViewportStart(totalEntries, maxRows) {
|
|
134623
|
+
if (totalEntries <= 0) {
|
|
134624
|
+
this.logsViewportStart = 0;
|
|
134625
|
+
return 0;
|
|
134626
|
+
}
|
|
134627
|
+
const maxStart = Math.max(0, totalEntries - maxRows);
|
|
134628
|
+
let start = Math.min(this.logsViewportStart, maxStart);
|
|
134629
|
+
if (this.selectedLogIndex < start) {
|
|
134630
|
+
start = this.selectedLogIndex;
|
|
134631
|
+
} else if (this.selectedLogIndex >= start + maxRows) {
|
|
134632
|
+
start = this.selectedLogIndex - maxRows + 1;
|
|
134633
|
+
}
|
|
134634
|
+
this.logsViewportStart = Math.max(0, Math.min(start, maxStart));
|
|
134635
|
+
return this.logsViewportStart;
|
|
134636
|
+
}
|
|
134637
|
+
renderLogsSection() {
|
|
134638
|
+
const cols = process.stdout.columns || 80;
|
|
134639
|
+
const entries = this.logBuffer.getAll();
|
|
134640
|
+
const maxRows = Math.max(1, (process.stdout.rows ?? 38) - 9);
|
|
134641
|
+
process.stdout.write(colorize("\n LOGS\n", "bold"));
|
|
134642
|
+
process.stdout.write(colorize(` Ring buffer: ${this.logBuffer.total}/${MAX_LOG_ENTRIES} entries
|
|
134643
|
+
`, "dim"));
|
|
134644
|
+
if (entries.length === 0) {
|
|
134645
|
+
process.stdout.write(colorize(" No log entries yet.\n", "dim"));
|
|
134646
|
+
return;
|
|
134647
|
+
}
|
|
134648
|
+
const safeSelectedIndex = Math.min(this.selectedLogIndex, Math.max(0, entries.length - 1));
|
|
134649
|
+
if (safeSelectedIndex !== this.selectedLogIndex) {
|
|
134650
|
+
this.selectedLogIndex = safeSelectedIndex;
|
|
134651
|
+
}
|
|
134652
|
+
if (this.logsExpandedMode) {
|
|
134653
|
+
this.renderLogsExpandedPane(entries[safeSelectedIndex], safeSelectedIndex, entries.length);
|
|
134654
|
+
return;
|
|
134655
|
+
}
|
|
134656
|
+
const modeIndicator = this.logsWrapEnabled ? colorize(" [w] wrap on", "dim") : colorize(" [w] wrap off", "dim");
|
|
134657
|
+
process.stdout.write(modeIndicator + "\n\n");
|
|
134658
|
+
const startIndex = this.getLogViewportStart(entries.length, maxRows);
|
|
134659
|
+
const visibleEntries = entries.slice(startIndex, startIndex + maxRows);
|
|
134660
|
+
const visibleReversed = [...visibleEntries].reverse();
|
|
134661
|
+
const selectedDisplayIndex = safeSelectedIndex >= startIndex && safeSelectedIndex < startIndex + visibleEntries.length ? visibleEntries.length - 1 - (safeSelectedIndex - startIndex) : -1;
|
|
134662
|
+
const prefixLen = 30;
|
|
134663
|
+
const availableWidth = Math.max(8, cols - prefixLen);
|
|
134664
|
+
for (let displayIdx = 0; displayIdx < visibleReversed.length; displayIdx++) {
|
|
134665
|
+
const entry = visibleReversed[displayIdx];
|
|
134666
|
+
const isSelected = displayIdx === selectedDisplayIndex;
|
|
134667
|
+
const selector = isSelected ? colorize("\u25B8 ", "brightGreen") : " ";
|
|
134668
|
+
const ts = colorize(formatTimestamp3(entry.timestamp), "dim");
|
|
134669
|
+
const prefix = entry.prefix ? colorize(`[${entry.prefix}]`, "gray") : "";
|
|
134670
|
+
const levelChar = entry.level === "error" ? colorize("\u2717", "brightRed") : entry.level === "warn" ? colorize("\u26A0", "brightYellow") : colorize("\u2713", "brightGreen");
|
|
134671
|
+
if (this.logsWrapEnabled) {
|
|
134672
|
+
const wrappedLines = this.wrapText(entry.message, availableWidth);
|
|
134673
|
+
const firstLine = `${selector}${ts} ${levelChar} ${prefix ? prefix + " " : ""}${wrappedLines[0]}`;
|
|
134674
|
+
process.stdout.write(visibleTruncate(firstLine, cols - 1) + "\n");
|
|
134675
|
+
for (let i = 1; i < wrappedLines.length; i++) {
|
|
134676
|
+
const continuation = ` ${wrappedLines[i]}`;
|
|
134677
|
+
process.stdout.write(visibleTruncate(continuation, cols - 1) + "\n");
|
|
134678
|
+
}
|
|
134679
|
+
} else {
|
|
134680
|
+
const messageWidth = Math.max(8, cols - prefixLen);
|
|
134681
|
+
const message = visibleTruncate(entry.message, messageWidth);
|
|
134682
|
+
const line = `${selector}${ts} ${levelChar} ${prefix ? prefix + " " : ""}${message}`;
|
|
134683
|
+
process.stdout.write(visibleTruncate(line, cols - 1) + "\n");
|
|
134684
|
+
}
|
|
134685
|
+
}
|
|
134686
|
+
}
|
|
134687
|
+
/**
|
|
134688
|
+
* Render the expanded log entry detail pane.
|
|
134689
|
+
* Replaces the normal list view with a focused view of a single entry.
|
|
134690
|
+
*/
|
|
134691
|
+
renderLogsExpandedPane(entry, index2, total) {
|
|
134692
|
+
const cols = process.stdout.columns || 80;
|
|
134693
|
+
const rows = process.stdout.rows ?? 24;
|
|
134694
|
+
const maxContentRows = Math.max(1, rows - 12);
|
|
134695
|
+
process.stdout.write(colorize(" EXPANDED LOG ENTRY\n", "bold"));
|
|
134696
|
+
const navHint = colorize(` Entry ${index2 + 1} of ${total} | [\u2191/k] older [\u2193/j] newer [Enter/Esc] close
|
|
134697
|
+
`, "dim");
|
|
134698
|
+
process.stdout.write(navHint);
|
|
134699
|
+
process.stdout.write(colorize(" " + "\u2500".repeat(Math.max(20, cols - 4)) + "\n", "dim"));
|
|
134700
|
+
const ts = formatTimestamp3(entry.timestamp);
|
|
134701
|
+
const levelLabel = entry.level === "error" ? colorize("ERROR", "brightRed") : entry.level === "warn" ? colorize("WARN", "brightYellow") : colorize("INFO", "brightGreen");
|
|
134702
|
+
process.stdout.write(colorize(` Timestamp: `, "gray") + colorize(ts, "white") + "\n");
|
|
134703
|
+
process.stdout.write(colorize(` Level: `, "gray") + levelLabel + "\n");
|
|
134704
|
+
if (entry.prefix) {
|
|
134705
|
+
process.stdout.write(colorize(` Prefix: `, "gray") + colorize(entry.prefix, "dim") + "\n");
|
|
134706
|
+
}
|
|
134707
|
+
process.stdout.write("\n");
|
|
134708
|
+
process.stdout.write(colorize(" MESSAGE\n", "bold"));
|
|
134709
|
+
const messageIndent = " ";
|
|
134710
|
+
const availableWidth = Math.max(8, cols - messageIndent.length);
|
|
134711
|
+
const wrappedMessage = this.wrapText(entry.message, availableWidth);
|
|
134712
|
+
let linesPrinted = 5;
|
|
134713
|
+
for (const line of wrappedMessage) {
|
|
134714
|
+
if (linesPrinted >= maxContentRows) {
|
|
134715
|
+
process.stdout.write(colorize(`
|
|
134716
|
+
... (truncated)
|
|
134717
|
+
`, "dim"));
|
|
134718
|
+
break;
|
|
134719
|
+
}
|
|
134720
|
+
process.stdout.write(messageIndent + line + "\n");
|
|
134721
|
+
linesPrinted++;
|
|
134722
|
+
}
|
|
134723
|
+
const footerHint = colorize(`
|
|
134724
|
+
[Esc] or [Enter] to close expanded view
|
|
134725
|
+
`, "dim");
|
|
134726
|
+
process.stdout.write(footerHint);
|
|
134727
|
+
}
|
|
134728
|
+
/**
|
|
134729
|
+
* Wrap text to fit within available width, returning an array of lines.
|
|
134730
|
+
* Respects ANSI escape sequences via visibleLength.
|
|
134731
|
+
*/
|
|
134732
|
+
wrapText(text, maxWidth) {
|
|
134733
|
+
if (maxWidth <= 0) return [""];
|
|
134734
|
+
if (visibleLength(text) <= maxWidth) return [text];
|
|
134735
|
+
const lines = [];
|
|
134736
|
+
let remaining = text;
|
|
134737
|
+
while (visibleLength(remaining) > maxWidth) {
|
|
134738
|
+
let breakIdx = 0;
|
|
134739
|
+
for (let i = 0; i < remaining.length; i++) {
|
|
134740
|
+
const char = remaining[i];
|
|
134741
|
+
if (char === " " || char === " ") {
|
|
134742
|
+
if (visibleLength(remaining.substring(0, i)) <= maxWidth) {
|
|
134743
|
+
breakIdx = i;
|
|
134744
|
+
}
|
|
134745
|
+
}
|
|
134746
|
+
if (visibleLength(remaining.substring(0, i + 1)) > maxWidth) {
|
|
134747
|
+
break;
|
|
134748
|
+
}
|
|
134749
|
+
}
|
|
134750
|
+
if (breakIdx === 0) {
|
|
134751
|
+
const firstTokenMatch = remaining.match(/^(\S+)/);
|
|
134752
|
+
if (firstTokenMatch) {
|
|
134753
|
+
const firstToken = firstTokenMatch[1];
|
|
134754
|
+
if (visibleLength(firstToken) > maxWidth) {
|
|
134755
|
+
const chunkSize = Math.max(1, maxWidth - 1);
|
|
134756
|
+
let chunkStart = 0;
|
|
134757
|
+
while (chunkStart < firstToken.length) {
|
|
134758
|
+
const chunk = firstToken.substring(chunkStart, chunkStart + chunkSize);
|
|
134759
|
+
lines.push(chunk);
|
|
134760
|
+
chunkStart += chunkSize;
|
|
134761
|
+
}
|
|
134762
|
+
remaining = remaining.substring(firstToken.length).trimStart();
|
|
134763
|
+
continue;
|
|
134764
|
+
}
|
|
134765
|
+
}
|
|
134766
|
+
breakIdx = Math.min(maxWidth, remaining.length);
|
|
134767
|
+
}
|
|
134768
|
+
lines.push(remaining.substring(0, breakIdx).trimEnd());
|
|
134769
|
+
remaining = remaining.substring(breakIdx).trimStart();
|
|
134770
|
+
}
|
|
134771
|
+
if (remaining.length > 0) {
|
|
134772
|
+
lines.push(remaining);
|
|
134773
|
+
}
|
|
134774
|
+
return lines.length > 0 ? lines : [""];
|
|
134775
|
+
}
|
|
134776
|
+
renderSystemSection() {
|
|
134777
|
+
if (!this.systemInfo) {
|
|
134778
|
+
process.stdout.write(colorize("\n System information not available.\n", "dim"));
|
|
134779
|
+
return;
|
|
134780
|
+
}
|
|
134781
|
+
const cols = process.stdout.columns || 80;
|
|
134782
|
+
const info = this.systemInfo;
|
|
134783
|
+
const rows = [];
|
|
134784
|
+
rows.push(colorize("\n SYSTEM INFORMATION\n", "bold"));
|
|
134785
|
+
rows.push("");
|
|
134786
|
+
const labelWidth = 12;
|
|
134787
|
+
const availableValueWidth = Math.max(8, cols - labelWidth - 1);
|
|
134788
|
+
rows.push(` ${colorize("Host:", "white")} ${info.host}`);
|
|
134789
|
+
rows.push(` ${colorize("Port:", "white")} ${info.port}`);
|
|
134790
|
+
rows.push(` ${colorize("URL:", "white")} ${colorize(visibleTruncate(info.baseUrl, availableValueWidth), "brightCyan")}`);
|
|
134791
|
+
rows.push("");
|
|
134792
|
+
if (info.authEnabled) {
|
|
134793
|
+
rows.push(` ${colorize("Auth:", "white")} ${colorize("bearer token required", "yellow")}`);
|
|
134794
|
+
if (info.authToken) {
|
|
134795
|
+
rows.push(` ${colorize("Token:", "white")} ${visibleTruncate(info.authToken, availableValueWidth)}`);
|
|
134796
|
+
}
|
|
134797
|
+
if (info.tokenizedUrl) {
|
|
134798
|
+
rows.push(` ${colorize("Open:", "white")} ${visibleTruncate(info.tokenizedUrl, availableValueWidth)}`);
|
|
134799
|
+
rows.push(colorize(" (browser stores token, click once)", "dim"));
|
|
134800
|
+
}
|
|
134801
|
+
} else {
|
|
134802
|
+
rows.push(` ${colorize("Auth:", "white")} ${colorize("disabled (--no-auth)", "dim")}`);
|
|
134803
|
+
}
|
|
134804
|
+
rows.push("");
|
|
134805
|
+
rows.push(` ${colorize("AI Engine:", "white")} ${info.engineMode === "dev" ? colorize("\u2717 disabled (dev mode)", "yellow") : info.engineMode === "paused" ? colorize("\u23F8 paused", "brightYellow") : colorize("\u2713 active", "brightGreen")}`);
|
|
134806
|
+
rows.push(` ${colorize("File Watcher:", "white")} ${info.fileWatcher ? colorize("\u2713 active", "brightGreen") : colorize("\u2717 inactive", "brightRed")}`);
|
|
134807
|
+
rows.push(` ${colorize("Uptime:", "white")} ${formatUptime(Date.now() - info.startTimeMs)}`);
|
|
134808
|
+
for (const row of rows) {
|
|
134809
|
+
process.stdout.write(visibleTruncate(row, cols) + "\n");
|
|
134810
|
+
}
|
|
134811
|
+
}
|
|
134812
|
+
renderUtilitiesSection() {
|
|
134813
|
+
const cols = process.stdout.columns || 80;
|
|
134814
|
+
const actions = [
|
|
134815
|
+
{ id: "refresh", label: "Refresh Stats", key: "r", description: "Re-fetch task and agent counts" },
|
|
134816
|
+
{ id: "clear", label: "Clear Logs", key: "c", description: "Clear the log ring buffer" },
|
|
134817
|
+
{ id: "pause", label: "Toggle Engine Pause", key: "t", description: "Pause/resume AI engine automation" },
|
|
134818
|
+
{ id: "help", label: "Help", key: "?", description: "Show keyboard shortcuts" }
|
|
134819
|
+
];
|
|
134820
|
+
process.stdout.write(colorize("\n UTILITIES\n", "bold"));
|
|
134821
|
+
process.stdout.write(colorize(" Press key to execute action\n\n", "dim"));
|
|
134822
|
+
const prefixWidth = 2 + 3 + 1 + 20 + 3;
|
|
134823
|
+
const descriptionWidth = Math.max(8, cols - prefixWidth - 1);
|
|
134824
|
+
for (const action of actions) {
|
|
134825
|
+
const keyDisplay = colorize(`[${action.key}]`, "brightYellow");
|
|
134826
|
+
const label = colorize(action.label.padEnd(20), "white");
|
|
134827
|
+
const description = visibleTruncate(action.description, descriptionWidth);
|
|
134828
|
+
const line = ` ${keyDisplay} ${label} - ${description}`;
|
|
134829
|
+
process.stdout.write(visibleTruncate(line, cols - 1) + "\n");
|
|
134830
|
+
}
|
|
134831
|
+
}
|
|
134832
|
+
renderStatsSection() {
|
|
134833
|
+
const cols = process.stdout.columns || 80;
|
|
134834
|
+
if (!this.taskStats) {
|
|
134835
|
+
process.stdout.write(colorize("\n Statistics not available.\n", "dim"));
|
|
134836
|
+
return;
|
|
134837
|
+
}
|
|
134838
|
+
const stats = this.taskStats;
|
|
134839
|
+
const rows = [];
|
|
134840
|
+
rows.push(colorize("\n STATISTICS\n", "bold"));
|
|
134841
|
+
rows.push("");
|
|
134842
|
+
rows.push(` ${colorize("Total Tasks:", "white")} ${stats.total}`);
|
|
134843
|
+
rows.push("");
|
|
134844
|
+
rows.push(` ${colorize("By Column:", "dim")}`);
|
|
134845
|
+
for (const [column, count] of Object.entries(stats.byColumn)) {
|
|
134846
|
+
const colName = column.replace("-", " ").replace(/\b\w/g, (l) => l.toUpperCase());
|
|
134847
|
+
const activeMark = (column === "in-progress" || column === "in-review") && count > 0 ? colorize(" \u25CF", "brightGreen") : "";
|
|
134848
|
+
rows.push(` ${colName}: ${count}${activeMark}`);
|
|
134849
|
+
}
|
|
134850
|
+
rows.push("");
|
|
134851
|
+
rows.push(` ${colorize("Active Tasks:", "white")} ${stats.active} (in-progress + in-review)`);
|
|
134852
|
+
rows.push("");
|
|
134853
|
+
rows.push(` ${colorize("Agents:", "dim")}`);
|
|
134854
|
+
rows.push(` Idle: ${stats.agents.idle}`);
|
|
134855
|
+
rows.push(` Active: ${stats.agents.active}`);
|
|
134856
|
+
rows.push(` Running: ${stats.agents.running}`);
|
|
134857
|
+
rows.push(` Error: ${stats.agents.error}`);
|
|
134858
|
+
for (const row of rows) {
|
|
134859
|
+
process.stdout.write(visibleTruncate(row, cols) + "\n");
|
|
134860
|
+
}
|
|
134861
|
+
}
|
|
134862
|
+
renderSettingsSection() {
|
|
134863
|
+
const cols = process.stdout.columns || 80;
|
|
134864
|
+
if (!this.settings) {
|
|
134865
|
+
process.stdout.write(colorize("\n Settings not available.\n", "dim"));
|
|
134866
|
+
return;
|
|
134867
|
+
}
|
|
134868
|
+
const s = this.settings;
|
|
134869
|
+
const rows = [];
|
|
134870
|
+
rows.push(colorize("\n SETTINGS\n", "bold"));
|
|
134871
|
+
rows.push("");
|
|
134872
|
+
const settingsList = [
|
|
134873
|
+
["maxConcurrent", s.maxConcurrent.toString()],
|
|
134874
|
+
["maxWorktrees", s.maxWorktrees.toString()],
|
|
134875
|
+
["autoMerge", s.autoMerge ? "enabled" : "disabled"],
|
|
134876
|
+
["mergeStrategy", s.mergeStrategy],
|
|
134877
|
+
["pollIntervalMs", `${s.pollIntervalMs}ms`],
|
|
134878
|
+
["enginePaused", s.enginePaused ? "yes" : "no"],
|
|
134879
|
+
["globalPause", s.globalPause ? "yes" : "no"]
|
|
134880
|
+
];
|
|
134881
|
+
const keyWidth = Math.max(...settingsList.map(([k]) => k.length));
|
|
134882
|
+
for (const [key, value] of settingsList) {
|
|
134883
|
+
const keyPad = key.padEnd(keyWidth);
|
|
134884
|
+
const isEnabled = value === "enabled" || value === "yes";
|
|
134885
|
+
const isDisabled = value === "disabled" || value === "no";
|
|
134886
|
+
const valueColor = isEnabled ? "brightGreen" : isDisabled ? "brightYellow" : "white";
|
|
134887
|
+
rows.push(` ${colorize(keyPad, "gray")} ${colorize(value, valueColor)}`);
|
|
134888
|
+
}
|
|
134889
|
+
for (const row of rows) {
|
|
134890
|
+
process.stdout.write(visibleTruncate(row, cols) + "\n");
|
|
134891
|
+
}
|
|
134892
|
+
}
|
|
134893
|
+
renderFooter() {
|
|
134894
|
+
const cols = process.stdout.columns || 80;
|
|
134895
|
+
const footerY = Math.max(1, (process.stdout.rows ?? 22) - 2);
|
|
134896
|
+
moveCursorTo(1, footerY);
|
|
134897
|
+
clearLine();
|
|
134898
|
+
const status = this.systemInfo ? `${this.systemInfo.baseUrl} | ${formatUptime(Date.now() - this.systemInfo.startTimeMs)}` : "";
|
|
134899
|
+
const left = colorize("Press ? for help", "dim");
|
|
134900
|
+
const right = colorize(visibleTruncate(status, Math.max(20, cols - 20)), "dim");
|
|
134901
|
+
const leftLen = visibleLength(left);
|
|
134902
|
+
const rightLen = visibleLength(right);
|
|
134903
|
+
process.stdout.write(left);
|
|
134904
|
+
const padding = Math.max(1, cols - leftLen - rightLen - 2);
|
|
134905
|
+
process.stdout.write(" ".repeat(padding));
|
|
134906
|
+
process.stdout.write(right);
|
|
134907
|
+
process.stdout.write("\n");
|
|
134908
|
+
}
|
|
134909
|
+
/**
|
|
134910
|
+
* Build help overlay lines as an array of strings.
|
|
134911
|
+
* Uses dynamic visibleLength calculation to ensure consistent box width.
|
|
134912
|
+
* All box-drawing rows (including borders) have the same total visible width.
|
|
134913
|
+
*
|
|
134914
|
+
* @param boxWidth - The interior content width (excluding the two box characters)
|
|
134915
|
+
* @param useBoxDrawing - Whether to use box-drawing characters (true) or compact text (false)
|
|
134916
|
+
* @returns Array of help lines
|
|
134917
|
+
*/
|
|
134918
|
+
buildHelpLines(boxWidth, useBoxDrawing) {
|
|
134919
|
+
if (useBoxDrawing) {
|
|
134920
|
+
const boxRow = (content) => {
|
|
134921
|
+
const padding = Math.max(0, boxWidth - visibleLength(content));
|
|
134922
|
+
return "\u2502" + content + " ".repeat(padding) + "\u2502";
|
|
134923
|
+
};
|
|
134924
|
+
return [
|
|
134925
|
+
"\u250C" + "\u2500".repeat(boxWidth) + "\u2510",
|
|
134926
|
+
boxRow(centerText("KEYBOARD SHORTCUTS", boxWidth, " ")),
|
|
134927
|
+
"\u251C" + "\u2500".repeat(boxWidth) + "\u2524",
|
|
134928
|
+
boxRow(" [1-5] Switch to tab by number"),
|
|
134929
|
+
boxRow(" [n] / \u2192 Next tab"),
|
|
134930
|
+
boxRow(" [p] / \u2190 Previous tab"),
|
|
134931
|
+
boxRow(" [r] Refresh stats (Utilities)"),
|
|
134932
|
+
boxRow(" [c] Clear logs (Utilities)"),
|
|
134933
|
+
boxRow(" [t] Toggle engine pause (Utilities)"),
|
|
134934
|
+
boxRow(" [\u2191/\u2193/k/j] Navigate log entries (Logs)"),
|
|
134935
|
+
boxRow(" [Home/End] First/last log entry (Logs)"),
|
|
134936
|
+
boxRow(" [Enter/Space/e] Expand log (Logs)"),
|
|
134937
|
+
boxRow(" [w] Toggle word wrap (Logs)"),
|
|
134938
|
+
boxRow(" [?] / [h] Toggle help"),
|
|
134939
|
+
boxRow(" [q] Quit"),
|
|
134940
|
+
boxRow(" [Ctrl+C] Force quit"),
|
|
134941
|
+
"\u2514" + "\u2500".repeat(boxWidth) + "\u2518"
|
|
134942
|
+
];
|
|
134943
|
+
} else {
|
|
134944
|
+
return [
|
|
134945
|
+
"KEYBOARD SHORTCUTS",
|
|
134946
|
+
" [1-5] Switch tab | [n/p] Next/Prev | [q] Quit",
|
|
134947
|
+
" [\u2191\u2193/k/j] Navigate logs | [Home/End] First/Last (Logs)",
|
|
134948
|
+
" [Enter/Space/e] Expand log | [w] Toggle wrap (Logs)",
|
|
134949
|
+
" [r] Refresh | [c] Clear logs | [t] Toggle engine",
|
|
134950
|
+
" [?/h] Help | [Ctrl+C] Force quit"
|
|
134951
|
+
];
|
|
134952
|
+
}
|
|
134953
|
+
}
|
|
134954
|
+
renderHelpOverlay() {
|
|
134955
|
+
const cols = process.stdout.columns || 80;
|
|
134956
|
+
const rows = process.stdout.rows || 24;
|
|
134957
|
+
const boxWidth = Math.min(62, Math.max(cols - 4, 20));
|
|
134958
|
+
const useBoxDrawing = cols >= boxWidth + 4;
|
|
134959
|
+
const rawHelpLines = this.buildHelpLines(boxWidth, useBoxDrawing);
|
|
134960
|
+
const compactBoxWidth = useBoxDrawing ? boxWidth : Math.max(...rawHelpLines.map(visibleLength));
|
|
134961
|
+
const boxHeight = rawHelpLines.length;
|
|
134962
|
+
const safeStartX = Math.max(1, Math.floor((cols - compactBoxWidth) / 2));
|
|
134963
|
+
const safeStartY = Math.max(1, Math.floor((rows - boxHeight) / 2));
|
|
134964
|
+
const clearTop = Math.max(1, safeStartY - 1);
|
|
134965
|
+
const clearBottom = Math.min(rows, safeStartY + boxHeight);
|
|
134966
|
+
for (let y = clearTop; y <= clearBottom; y++) {
|
|
134967
|
+
moveCursorTo(1, y);
|
|
134968
|
+
clearLine();
|
|
134969
|
+
}
|
|
134970
|
+
for (let i = 0; i < rawHelpLines.length; i++) {
|
|
134971
|
+
const color = i === 0 || i === 2 || i === rawHelpLines.length - 1 ? "brightBlue" : "white";
|
|
134972
|
+
moveCursorTo(safeStartX, safeStartY + i);
|
|
134973
|
+
process.stdout.write(colorize(rawHelpLines[i], color));
|
|
134974
|
+
}
|
|
134975
|
+
}
|
|
134976
|
+
};
|
|
134977
|
+
DashboardLogSink = class {
|
|
134978
|
+
tui = null;
|
|
134979
|
+
isTTY;
|
|
134980
|
+
originalConsole = null;
|
|
134981
|
+
constructor(tui) {
|
|
134982
|
+
this.tui = tui ?? null;
|
|
134983
|
+
this.isTTY = tui?.running ?? false;
|
|
134984
|
+
}
|
|
134985
|
+
setTUI(tui) {
|
|
134986
|
+
this.tui = tui;
|
|
134987
|
+
this.isTTY = true;
|
|
134988
|
+
}
|
|
134989
|
+
log(message, prefix) {
|
|
134990
|
+
const line = prefix ? `[${prefix}] ${message}` : message;
|
|
134991
|
+
if (this.tui && this.isTTY) {
|
|
134992
|
+
this.tui.log(message, prefix);
|
|
134993
|
+
} else if (this.originalConsole) {
|
|
134994
|
+
this.originalConsole.log.call(console, line);
|
|
134995
|
+
} else {
|
|
134996
|
+
console.log(line);
|
|
134997
|
+
}
|
|
134998
|
+
}
|
|
134999
|
+
warn(message, prefix) {
|
|
135000
|
+
const line = prefix ? `[${prefix}] ${message}` : message;
|
|
135001
|
+
if (this.tui && this.isTTY) {
|
|
135002
|
+
this.tui.warn(message, prefix);
|
|
135003
|
+
} else if (this.originalConsole) {
|
|
135004
|
+
this.originalConsole.warn.call(console, line);
|
|
135005
|
+
} else {
|
|
135006
|
+
console.warn(line);
|
|
135007
|
+
}
|
|
135008
|
+
}
|
|
135009
|
+
error(message, prefix) {
|
|
135010
|
+
const line = prefix ? `[${prefix}] ${message}` : message;
|
|
135011
|
+
if (this.tui && this.isTTY) {
|
|
135012
|
+
this.tui.error(message, prefix);
|
|
135013
|
+
} else if (this.originalConsole) {
|
|
135014
|
+
this.originalConsole.error.call(console, line);
|
|
135015
|
+
} else {
|
|
135016
|
+
console.error(line);
|
|
135017
|
+
}
|
|
135018
|
+
}
|
|
135019
|
+
/**
|
|
135020
|
+
* Monkey-patch `console.log/warn/error` so everything (including the engine's
|
|
135021
|
+
* createLogger() output, which writes directly to console.error) surfaces in
|
|
135022
|
+
* the TUI's log ring buffer. Without this, most runtime logs render beneath
|
|
135023
|
+
* the alt-screen TUI and are immediately overwritten on the next render,
|
|
135024
|
+
* leaving the Logs tab nearly empty.
|
|
135025
|
+
*
|
|
135026
|
+
* Messages that start with `[prefix] rest` are unpacked so the TUI stores
|
|
135027
|
+
* `prefix="prefix"` and `message="rest"`. Idempotent; call `releaseConsole()`
|
|
135028
|
+
* on TUI shutdown to restore the originals.
|
|
135029
|
+
*/
|
|
135030
|
+
captureConsole() {
|
|
135031
|
+
if (this.originalConsole) return;
|
|
135032
|
+
this.originalConsole = {
|
|
135033
|
+
log: console.log,
|
|
135034
|
+
warn: console.warn,
|
|
135035
|
+
error: console.error
|
|
135036
|
+
};
|
|
135037
|
+
console.log = (...args) => {
|
|
135038
|
+
const { message, prefix } = formatConsoleArgs(args);
|
|
135039
|
+
this.log(message, prefix);
|
|
135040
|
+
};
|
|
135041
|
+
console.warn = (...args) => {
|
|
135042
|
+
const { message, prefix } = formatConsoleArgs(args);
|
|
135043
|
+
this.warn(message, prefix);
|
|
135044
|
+
};
|
|
135045
|
+
console.error = (...args) => {
|
|
135046
|
+
const { message, prefix } = formatConsoleArgs(args);
|
|
135047
|
+
this.error(message, prefix);
|
|
135048
|
+
};
|
|
135049
|
+
}
|
|
135050
|
+
/** Restore console.log/warn/error to their pre-capture implementations. */
|
|
135051
|
+
releaseConsole() {
|
|
135052
|
+
if (!this.originalConsole) return;
|
|
135053
|
+
console.log = this.originalConsole.log;
|
|
135054
|
+
console.warn = this.originalConsole.warn;
|
|
135055
|
+
console.error = this.originalConsole.error;
|
|
135056
|
+
this.originalConsole = null;
|
|
135057
|
+
}
|
|
135058
|
+
};
|
|
135059
|
+
}
|
|
135060
|
+
});
|
|
135061
|
+
|
|
133741
135062
|
// src/commands/dashboard.ts
|
|
133742
135063
|
var dashboard_exports = {};
|
|
133743
135064
|
__export(dashboard_exports, {
|
|
135065
|
+
StreamedLogBuffer: () => StreamedLogBuffer,
|
|
133744
135066
|
promptForPort: () => promptForPort,
|
|
133745
135067
|
runDashboard: () => runDashboard
|
|
133746
135068
|
});
|
|
@@ -133753,7 +135075,7 @@ function formatBytes2(bytes) {
|
|
|
133753
135075
|
if (bytes < 1024 * 1024 * 1024) return `${Math.round(bytes / (1024 * 1024))}MB`;
|
|
133754
135076
|
return `${(bytes / (1024 * 1024 * 1024)).toFixed(1)}GB`;
|
|
133755
135077
|
}
|
|
133756
|
-
function
|
|
135078
|
+
function formatUptime2(ms) {
|
|
133757
135079
|
const seconds = Math.floor(ms / 1e3);
|
|
133758
135080
|
const minutes = Math.floor(seconds / 60);
|
|
133759
135081
|
const hours = Math.floor(minutes / 60);
|
|
@@ -133790,7 +135112,7 @@ function logDiagnostics(prefix, startTime, dbHealthCheck) {
|
|
|
133790
135112
|
} catch {
|
|
133791
135113
|
}
|
|
133792
135114
|
}
|
|
133793
|
-
const logLine = `[${prefix}] diagnostics: uptime=${
|
|
135115
|
+
const logLine = `[${prefix}] diagnostics: uptime=${formatUptime2(uptime)} rss=${formatBytes2(mem.rss)} heap=${formatBytes2(mem.heapUsed)}/${formatBytes2(mem.heapTotal)} external=${formatBytes2(mem.external)} arrayBuffers=${formatBytes2(mem.arrayBuffers)} handles=${handleCount} requests=${requestCount} db=${dbHealth}${listenerInfo}`;
|
|
133794
135116
|
console.log(logLine);
|
|
133795
135117
|
}
|
|
133796
135118
|
function ensureProcessDiagnostics() {
|
|
@@ -133813,11 +135135,11 @@ function ensureProcessDiagnostics() {
|
|
|
133813
135135
|
requestCount = process._getActiveRequests?.()?.length ?? -1;
|
|
133814
135136
|
} catch {
|
|
133815
135137
|
}
|
|
133816
|
-
console.log(`[dashboard] beforeExit code=${code} uptime=${
|
|
135138
|
+
console.log(`[dashboard] beforeExit code=${code} uptime=${formatUptime2(uptime)} handles=${handleCount} requests=${requestCount}`);
|
|
133817
135139
|
});
|
|
133818
135140
|
process.on("exit", (code) => {
|
|
133819
135141
|
const uptime = Date.now() - diagnosticStartTime;
|
|
133820
|
-
console.log(`[dashboard] exit code=${code} uptime=${
|
|
135142
|
+
console.log(`[dashboard] exit code=${code} uptime=${formatUptime2(uptime)}`);
|
|
133821
135143
|
});
|
|
133822
135144
|
process.on("uncaughtExceptionMonitor", (error) => {
|
|
133823
135145
|
console.error(`[dashboard] uncaught exception pid=${process.pid}: ${error.stack || error.message}`);
|
|
@@ -133863,7 +135185,74 @@ async function runDashboard(port, opts = {}) {
|
|
|
133863
135185
|
}
|
|
133864
135186
|
}
|
|
133865
135187
|
const cwd = await resolveRuntimeProjectPath();
|
|
133866
|
-
const
|
|
135188
|
+
const isTTY = isTTYAvailable();
|
|
135189
|
+
let tui;
|
|
135190
|
+
const dashboardStartedAt = Date.now();
|
|
135191
|
+
let store;
|
|
135192
|
+
let agentStore;
|
|
135193
|
+
const logSink = new DashboardLogSink();
|
|
135194
|
+
if (isTTY) {
|
|
135195
|
+
tui = new DashboardTUI();
|
|
135196
|
+
tui.setCallbacks({
|
|
135197
|
+
onRefreshStats: async () => {
|
|
135198
|
+
if (store && agentStore) {
|
|
135199
|
+
const tasks = await store.listTasks({ slim: true, includeArchived: false });
|
|
135200
|
+
const counts = /* @__PURE__ */ new Map();
|
|
135201
|
+
for (const task of tasks) {
|
|
135202
|
+
counts.set(task.column, (counts.get(task.column) ?? 0) + 1);
|
|
135203
|
+
}
|
|
135204
|
+
const active = tasks.filter(
|
|
135205
|
+
(task) => task.column === "in-progress" || task.column === "in-review"
|
|
135206
|
+
).length;
|
|
135207
|
+
const agents = await agentStore.listAgents();
|
|
135208
|
+
const agentStats = { idle: 0, active: 0, running: 0, error: 0 };
|
|
135209
|
+
for (const agent of agents) {
|
|
135210
|
+
const state = agent.state;
|
|
135211
|
+
if (state in agentStats) {
|
|
135212
|
+
agentStats[state]++;
|
|
135213
|
+
}
|
|
135214
|
+
}
|
|
135215
|
+
tui.setTaskStats({
|
|
135216
|
+
total: tasks.length,
|
|
135217
|
+
byColumn: Object.fromEntries(counts),
|
|
135218
|
+
active,
|
|
135219
|
+
agents: agentStats
|
|
135220
|
+
});
|
|
135221
|
+
}
|
|
135222
|
+
},
|
|
135223
|
+
onClearLogs: () => {
|
|
135224
|
+
},
|
|
135225
|
+
onTogglePause: async (paused) => {
|
|
135226
|
+
if (store) {
|
|
135227
|
+
await store.updateSettings({ enginePaused: paused });
|
|
135228
|
+
tui.log(`Engine ${paused ? "paused" : "resumed"}`);
|
|
135229
|
+
const fullSettings = await store.getSettings();
|
|
135230
|
+
return {
|
|
135231
|
+
maxConcurrent: fullSettings.maxConcurrent ?? 1,
|
|
135232
|
+
maxWorktrees: fullSettings.maxWorktrees ?? 2,
|
|
135233
|
+
autoMerge: fullSettings.autoMerge ?? false,
|
|
135234
|
+
mergeStrategy: fullSettings.mergeStrategy ?? "direct",
|
|
135235
|
+
pollIntervalMs: fullSettings.pollIntervalMs ?? 6e4,
|
|
135236
|
+
enginePaused: fullSettings.enginePaused ?? false,
|
|
135237
|
+
globalPause: fullSettings.globalPause ?? false
|
|
135238
|
+
};
|
|
135239
|
+
}
|
|
135240
|
+
return {
|
|
135241
|
+
maxConcurrent: 1,
|
|
135242
|
+
maxWorktrees: 2,
|
|
135243
|
+
autoMerge: false,
|
|
135244
|
+
mergeStrategy: "direct",
|
|
135245
|
+
pollIntervalMs: 6e4,
|
|
135246
|
+
enginePaused: paused,
|
|
135247
|
+
globalPause: false
|
|
135248
|
+
};
|
|
135249
|
+
}
|
|
135250
|
+
});
|
|
135251
|
+
await tui.start();
|
|
135252
|
+
logSink.setTUI(tui);
|
|
135253
|
+
logSink.captureConsole();
|
|
135254
|
+
}
|
|
135255
|
+
store = new TaskStore(cwd);
|
|
133867
135256
|
await store.init();
|
|
133868
135257
|
await store.watch();
|
|
133869
135258
|
setDiagnosticDbHealthCheck(() => store.healthCheck());
|
|
@@ -133875,15 +135264,78 @@ async function runDashboard(port, opts = {}) {
|
|
|
133875
135264
|
"settings:updated": store.listenerCount("settings:updated"),
|
|
133876
135265
|
"agent:log": store.listenerCount("agent:log")
|
|
133877
135266
|
}));
|
|
135267
|
+
let tuiRefreshPending = false;
|
|
135268
|
+
let tuiRefreshDebounceTimer = null;
|
|
135269
|
+
async function refreshTUIStats() {
|
|
135270
|
+
if (!tui || !isTTY) return;
|
|
135271
|
+
if (!store || !agentStore) return;
|
|
135272
|
+
if (tuiRefreshPending) return;
|
|
135273
|
+
tuiRefreshPending = true;
|
|
135274
|
+
try {
|
|
135275
|
+
const tasks = await store.listTasks({ slim: true, includeArchived: false });
|
|
135276
|
+
const counts = /* @__PURE__ */ new Map();
|
|
135277
|
+
for (const task of tasks) {
|
|
135278
|
+
counts.set(task.column, (counts.get(task.column) ?? 0) + 1);
|
|
135279
|
+
}
|
|
135280
|
+
const active = tasks.filter(
|
|
135281
|
+
(task) => task.column === "in-progress" || task.column === "in-review"
|
|
135282
|
+
).length;
|
|
135283
|
+
const agents = await agentStore.listAgents();
|
|
135284
|
+
const agentStats = { idle: 0, active: 0, running: 0, error: 0 };
|
|
135285
|
+
for (const agent of agents) {
|
|
135286
|
+
const state = agent.state;
|
|
135287
|
+
if (state in agentStats) {
|
|
135288
|
+
agentStats[state]++;
|
|
135289
|
+
}
|
|
135290
|
+
}
|
|
135291
|
+
tui.setTaskStats({
|
|
135292
|
+
total: tasks.length,
|
|
135293
|
+
byColumn: Object.fromEntries(counts),
|
|
135294
|
+
active,
|
|
135295
|
+
agents: agentStats
|
|
135296
|
+
});
|
|
135297
|
+
} finally {
|
|
135298
|
+
tuiRefreshPending = false;
|
|
135299
|
+
}
|
|
135300
|
+
}
|
|
135301
|
+
async function refreshTUISettings() {
|
|
135302
|
+
if (!tui || !isTTY) return;
|
|
135303
|
+
if (!store) return;
|
|
135304
|
+
try {
|
|
135305
|
+
const settings = await store.getSettings();
|
|
135306
|
+
tui.setSettings({
|
|
135307
|
+
maxConcurrent: settings.maxConcurrent ?? 1,
|
|
135308
|
+
maxWorktrees: settings.maxWorktrees ?? 2,
|
|
135309
|
+
autoMerge: settings.autoMerge ?? false,
|
|
135310
|
+
mergeStrategy: settings.mergeStrategy ?? "direct",
|
|
135311
|
+
pollIntervalMs: settings.pollIntervalMs ?? 6e4,
|
|
135312
|
+
enginePaused: settings.enginePaused ?? false,
|
|
135313
|
+
globalPause: settings.globalPause ?? false
|
|
135314
|
+
});
|
|
135315
|
+
} catch {
|
|
135316
|
+
}
|
|
135317
|
+
}
|
|
135318
|
+
function scheduleStatsRefresh() {
|
|
135319
|
+
if (tuiRefreshDebounceTimer) {
|
|
135320
|
+
clearTimeout(tuiRefreshDebounceTimer);
|
|
135321
|
+
}
|
|
135322
|
+
tuiRefreshDebounceTimer = setTimeout(() => {
|
|
135323
|
+
void refreshTUIStats();
|
|
135324
|
+
}, 500);
|
|
135325
|
+
}
|
|
133878
135326
|
const handlers = [];
|
|
133879
135327
|
const disposeCallbacks = [];
|
|
133880
135328
|
let disposed = false;
|
|
133881
135329
|
let shutdownInProgress = false;
|
|
133882
|
-
const dashboardStartedAt = Date.now();
|
|
133883
135330
|
async function logShutdownDiagnostics(reason) {
|
|
133884
135331
|
const uptimeSeconds = Math.round((Date.now() - dashboardStartedAt) / 1e3);
|
|
133885
135332
|
let taskSummary = "tasks=unknown";
|
|
133886
135333
|
try {
|
|
135334
|
+
if (!store) {
|
|
135335
|
+
taskSummary = "tasks=unavailable (store not initialized)";
|
|
135336
|
+
logSink.log(`shutdown requested reason=${reason} pid=${process.pid} ppid=${process.ppid} uptime=${uptimeSeconds}s ${taskSummary}`, "dashboard");
|
|
135337
|
+
return;
|
|
135338
|
+
}
|
|
133887
135339
|
const tasks = await store.listTasks({ slim: true, includeArchived: false });
|
|
133888
135340
|
const counts = /* @__PURE__ */ new Map();
|
|
133889
135341
|
for (const task of tasks) {
|
|
@@ -133897,8 +135349,9 @@ async function runDashboard(port, opts = {}) {
|
|
|
133897
135349
|
const message = error instanceof Error ? error.message : String(error);
|
|
133898
135350
|
taskSummary = `tasks=unavailable (${message})`;
|
|
133899
135351
|
}
|
|
133900
|
-
|
|
133901
|
-
`
|
|
135352
|
+
logSink.log(
|
|
135353
|
+
`shutdown requested reason=${reason} pid=${process.pid} ppid=${process.ppid} uptime=${uptimeSeconds}s ${taskSummary}`,
|
|
135354
|
+
"dashboard"
|
|
133902
135355
|
);
|
|
133903
135356
|
}
|
|
133904
135357
|
function registerHandler(target, event, handler) {
|
|
@@ -133907,8 +135360,20 @@ async function runDashboard(port, opts = {}) {
|
|
|
133907
135360
|
}
|
|
133908
135361
|
const automationStore = new AutomationStore(cwd);
|
|
133909
135362
|
await automationStore.init();
|
|
133910
|
-
|
|
135363
|
+
agentStore = new AgentStore({ rootDir: store.getFusionDir() });
|
|
133911
135364
|
await agentStore.init();
|
|
135365
|
+
if (tui && isTTY) {
|
|
135366
|
+
registerHandler(store, "task:created", scheduleStatsRefresh);
|
|
135367
|
+
registerHandler(store, "task:moved", scheduleStatsRefresh);
|
|
135368
|
+
registerHandler(store, "task:updated", scheduleStatsRefresh);
|
|
135369
|
+
registerHandler(store, "task:deleted", scheduleStatsRefresh);
|
|
135370
|
+
registerHandler(store, "settings:updated", () => {
|
|
135371
|
+
void refreshTUISettings();
|
|
135372
|
+
});
|
|
135373
|
+
registerHandler(agentStore, "agent:created", scheduleStatsRefresh);
|
|
135374
|
+
registerHandler(agentStore, "agent:updated", scheduleStatsRefresh);
|
|
135375
|
+
registerHandler(agentStore, "agent:deleted", scheduleStatsRefresh);
|
|
135376
|
+
}
|
|
133912
135377
|
const pluginStore = new PluginStore(store.getFusionDir());
|
|
133913
135378
|
await pluginStore.init();
|
|
133914
135379
|
const pluginLoader = new PluginLoader({
|
|
@@ -133919,12 +135384,23 @@ async function runDashboard(port, opts = {}) {
|
|
|
133919
135384
|
let triggerScheduler;
|
|
133920
135385
|
if (opts.paused) {
|
|
133921
135386
|
await store.updateSettings({ enginePaused: true });
|
|
133922
|
-
|
|
135387
|
+
logSink.log("Starting in paused mode \u2014 automation disabled", "engine");
|
|
133923
135388
|
}
|
|
133924
|
-
const onMergeImpl = (taskId) =>
|
|
133925
|
-
|
|
133926
|
-
|
|
133927
|
-
|
|
135389
|
+
const onMergeImpl = async (taskId) => {
|
|
135390
|
+
const streamedMergeLog = new StreamedLogBuffer(
|
|
135391
|
+
(line) => logSink.log(line, "merge"),
|
|
135392
|
+
STREAM_LOG_FLUSH_IDLE_MS
|
|
135393
|
+
);
|
|
135394
|
+
try {
|
|
135395
|
+
return await aiMergeTask(store, cwd, taskId, {
|
|
135396
|
+
agentStore,
|
|
135397
|
+
onAgentText: (delta) => streamedMergeLog.push(delta)
|
|
135398
|
+
});
|
|
135399
|
+
} finally {
|
|
135400
|
+
streamedMergeLog.flush();
|
|
135401
|
+
streamedMergeLog.dispose();
|
|
135402
|
+
}
|
|
135403
|
+
};
|
|
133928
135404
|
const onMerge = (taskId) => onMergeImpl(taskId);
|
|
133929
135405
|
const missionAutopilotImpl = new MissionAutopilot(store, store.getMissionStore());
|
|
133930
135406
|
const missionExecutionLoopImpl = new MissionExecutionLoop({
|
|
@@ -133964,14 +135440,14 @@ async function runDashboard(port, opts = {}) {
|
|
|
133964
135440
|
join48(cwd, ".fusion", "disabled-auto-extension-discovery")
|
|
133965
135441
|
);
|
|
133966
135442
|
for (const { path: path4, error } of extensionsResult.errors) {
|
|
133967
|
-
|
|
135443
|
+
logSink.log(`Failed to load ${path4}: ${error}`, "extensions");
|
|
133968
135444
|
}
|
|
133969
135445
|
for (const { name, config, extensionPath } of extensionsResult.runtime.pendingProviderRegistrations) {
|
|
133970
135446
|
try {
|
|
133971
135447
|
modelRegistry.registerProvider(name, config);
|
|
133972
135448
|
} catch (error) {
|
|
133973
135449
|
const message = error instanceof Error ? error.message : String(error);
|
|
133974
|
-
|
|
135450
|
+
logSink.log(`Failed to register provider from ${extensionPath}: ${message}`, "extensions");
|
|
133975
135451
|
}
|
|
133976
135452
|
}
|
|
133977
135453
|
extensionsResult.runtime.pendingProviderRegistrations = [];
|
|
@@ -134011,15 +135487,15 @@ async function runDashboard(port, opts = {}) {
|
|
|
134011
135487
|
api: "openai-completions",
|
|
134012
135488
|
models: orModels
|
|
134013
135489
|
});
|
|
134014
|
-
|
|
135490
|
+
logSink.log(`Synced ${orModels.length} models from OpenRouter API`, "openrouter");
|
|
134015
135491
|
} catch (err) {
|
|
134016
135492
|
const message = err instanceof Error ? err.message : String(err);
|
|
134017
|
-
|
|
135493
|
+
logSink.log(`Failed to sync models: ${message}`, "openrouter");
|
|
134018
135494
|
}
|
|
134019
135495
|
})();
|
|
134020
135496
|
} catch (error) {
|
|
134021
135497
|
const message = error instanceof Error ? error.message : String(error);
|
|
134022
|
-
|
|
135498
|
+
logSink.log(`Failed to discover extensions: ${message}`, "extensions");
|
|
134023
135499
|
createExtensionRuntime2();
|
|
134024
135500
|
modelRegistry.refresh();
|
|
134025
135501
|
}
|
|
@@ -134031,6 +135507,14 @@ async function runDashboard(port, opts = {}) {
|
|
|
134031
135507
|
function dispose() {
|
|
134032
135508
|
if (disposed) return;
|
|
134033
135509
|
disposed = true;
|
|
135510
|
+
if (tuiRefreshDebounceTimer) {
|
|
135511
|
+
clearTimeout(tuiRefreshDebounceTimer);
|
|
135512
|
+
tuiRefreshDebounceTimer = null;
|
|
135513
|
+
}
|
|
135514
|
+
if (tui) {
|
|
135515
|
+
logSink.releaseConsole();
|
|
135516
|
+
void tui.stop();
|
|
135517
|
+
}
|
|
134034
135518
|
for (const { target, event, handler } of handlers) {
|
|
134035
135519
|
target.off(event, handler);
|
|
134036
135520
|
}
|
|
@@ -134062,7 +135546,7 @@ async function runDashboard(port, opts = {}) {
|
|
|
134062
135546
|
peerExchangeService.start();
|
|
134063
135547
|
} catch (err) {
|
|
134064
135548
|
const message = err instanceof Error ? err.message : String(err);
|
|
134065
|
-
|
|
135549
|
+
logSink.warn(`Failed to start peer exchange service: ${message}`, "dashboard");
|
|
134066
135550
|
}
|
|
134067
135551
|
centralCoreForMesh = centralCoreForEngine;
|
|
134068
135552
|
let cwdEngine;
|
|
@@ -134112,7 +135596,7 @@ async function runDashboard(port, opts = {}) {
|
|
|
134112
135596
|
handleTypes[type] = (handleTypes[type] ?? 0) + 1;
|
|
134113
135597
|
}
|
|
134114
135598
|
const handleSummary = Object.entries(handleTypes).sort((a, b) => b[1] - a[1]).map(([type, count]) => `${type}:${count}`).join(", ");
|
|
134115
|
-
|
|
135599
|
+
logSink.log(`active handles at shutdown: ${handleSummary}`, "dashboard");
|
|
134116
135600
|
} catch {
|
|
134117
135601
|
}
|
|
134118
135602
|
await logShutdownDiagnostics(signal);
|
|
@@ -134124,7 +135608,7 @@ async function runDashboard(port, opts = {}) {
|
|
|
134124
135608
|
await peerExchangeService.stop();
|
|
134125
135609
|
} catch (err) {
|
|
134126
135610
|
const message = err instanceof Error ? err.message : String(err);
|
|
134127
|
-
|
|
135611
|
+
logSink.warn(`Failed to stop peer exchange service: ${message}`, "dashboard");
|
|
134128
135612
|
}
|
|
134129
135613
|
}
|
|
134130
135614
|
if (centralCoreForMesh && localNodeIdForMesh) {
|
|
@@ -134132,13 +135616,13 @@ async function runDashboard(port, opts = {}) {
|
|
|
134132
135616
|
centralCoreForMesh.stopDiscovery();
|
|
134133
135617
|
} catch (err) {
|
|
134134
135618
|
const message = err instanceof Error ? err.message : String(err);
|
|
134135
|
-
|
|
135619
|
+
logSink.warn(`Failed to stop mDNS discovery: ${message}`, "dashboard");
|
|
134136
135620
|
}
|
|
134137
135621
|
try {
|
|
134138
135622
|
await centralCoreForMesh.updateNode(localNodeIdForMesh, { status: "offline" });
|
|
134139
135623
|
} catch (err) {
|
|
134140
135624
|
const message = err instanceof Error ? err.message : String(err);
|
|
134141
|
-
|
|
135625
|
+
logSink.warn(`Failed to set local node offline: ${message}`, "dashboard");
|
|
134142
135626
|
}
|
|
134143
135627
|
}
|
|
134144
135628
|
await centralCoreForEngine.close().catch(() => {
|
|
@@ -134149,7 +135633,7 @@ async function runDashboard(port, opts = {}) {
|
|
|
134149
135633
|
registerHandler(process, "SIGINT", () => void shutdown("SIGINT"));
|
|
134150
135634
|
registerHandler(process, "SIGTERM", () => void shutdown("SIGTERM"));
|
|
134151
135635
|
registerHandler(process, "SIGHUP", () => {
|
|
134152
|
-
|
|
135636
|
+
logSink.log("Received SIGHUP (terminal disconnected) \u2014 ignoring", "dashboard");
|
|
134153
135637
|
});
|
|
134154
135638
|
} else {
|
|
134155
135639
|
try {
|
|
@@ -134159,7 +135643,7 @@ async function runDashboard(port, opts = {}) {
|
|
|
134159
135643
|
peerExchangeService.start();
|
|
134160
135644
|
} catch (err) {
|
|
134161
135645
|
const message = err instanceof Error ? err.message : String(err);
|
|
134162
|
-
|
|
135646
|
+
logSink.warn(`Failed to initialize mesh networking: ${message}`, "dashboard");
|
|
134163
135647
|
}
|
|
134164
135648
|
try {
|
|
134165
135649
|
heartbeatMonitorImpl = new HeartbeatMonitor({
|
|
@@ -134168,10 +135652,10 @@ async function runDashboard(port, opts = {}) {
|
|
|
134168
135652
|
taskStore: store,
|
|
134169
135653
|
rootDir: cwd,
|
|
134170
135654
|
onMissed: (agentId) => {
|
|
134171
|
-
|
|
135655
|
+
logSink.log(`Agent ${agentId} missed heartbeat`, "engine");
|
|
134172
135656
|
},
|
|
134173
135657
|
onTerminated: (agentId) => {
|
|
134174
|
-
|
|
135658
|
+
logSink.log(`Agent ${agentId} terminated (unresponsive)`, "engine");
|
|
134175
135659
|
}
|
|
134176
135660
|
});
|
|
134177
135661
|
heartbeatMonitorImpl.start();
|
|
@@ -134203,10 +135687,11 @@ async function runDashboard(port, opts = {}) {
|
|
|
134203
135687
|
});
|
|
134204
135688
|
}
|
|
134205
135689
|
if (agents.length > 0) {
|
|
134206
|
-
|
|
135690
|
+
logSink.log(`Registered ${triggerScheduler.getRegisteredAgents().length} agents for heartbeat triggers`, "engine");
|
|
134207
135691
|
}
|
|
134208
135692
|
} catch (err) {
|
|
134209
|
-
|
|
135693
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
135694
|
+
logSink.log(`HeartbeatMonitor initialization failed (continuing without agent monitoring): ${message}`, "engine");
|
|
134210
135695
|
}
|
|
134211
135696
|
app = createServer(store, {
|
|
134212
135697
|
onMerge,
|
|
@@ -134255,7 +135740,7 @@ async function runDashboard(port, opts = {}) {
|
|
|
134255
135740
|
handleTypes[type] = (handleTypes[type] ?? 0) + 1;
|
|
134256
135741
|
}
|
|
134257
135742
|
const handleSummary = Object.entries(handleTypes).sort((a, b) => b[1] - a[1]).map(([type, count]) => `${type}:${count}`).join(", ");
|
|
134258
|
-
|
|
135743
|
+
logSink.log(`active handles at shutdown: ${handleSummary}`, "dashboard");
|
|
134259
135744
|
} catch {
|
|
134260
135745
|
}
|
|
134261
135746
|
await logShutdownDiagnostics(signal);
|
|
@@ -134268,7 +135753,7 @@ async function runDashboard(port, opts = {}) {
|
|
|
134268
135753
|
await peerExchangeService.stop();
|
|
134269
135754
|
} catch (err) {
|
|
134270
135755
|
const message = err instanceof Error ? err.message : String(err);
|
|
134271
|
-
|
|
135756
|
+
logSink.warn(`Failed to stop peer exchange service: ${message}`, "dashboard");
|
|
134272
135757
|
}
|
|
134273
135758
|
}
|
|
134274
135759
|
if (centralCoreForMesh && localNodeIdForMesh) {
|
|
@@ -134276,13 +135761,13 @@ async function runDashboard(port, opts = {}) {
|
|
|
134276
135761
|
centralCoreForMesh.stopDiscovery();
|
|
134277
135762
|
} catch (err) {
|
|
134278
135763
|
const message = err instanceof Error ? err.message : String(err);
|
|
134279
|
-
|
|
135764
|
+
logSink.warn(`Failed to stop mDNS discovery: ${message}`, "dashboard");
|
|
134280
135765
|
}
|
|
134281
135766
|
try {
|
|
134282
135767
|
await centralCoreForMesh.updateNode(localNodeIdForMesh, { status: "offline" });
|
|
134283
135768
|
} catch (err) {
|
|
134284
135769
|
const message = err instanceof Error ? err.message : String(err);
|
|
134285
|
-
|
|
135770
|
+
logSink.warn(`Failed to set local node offline: ${message}`, "dashboard");
|
|
134286
135771
|
}
|
|
134287
135772
|
}
|
|
134288
135773
|
if (centralCoreForMesh) {
|
|
@@ -134295,7 +135780,7 @@ async function runDashboard(port, opts = {}) {
|
|
|
134295
135780
|
registerHandler(process, "SIGINT", () => void devShutdown("SIGINT"));
|
|
134296
135781
|
registerHandler(process, "SIGTERM", () => void devShutdown("SIGTERM"));
|
|
134297
135782
|
registerHandler(process, "SIGHUP", () => {
|
|
134298
|
-
|
|
135783
|
+
logSink.log("Received SIGHUP (terminal disconnected) \u2014 ignoring", "dashboard");
|
|
134299
135784
|
});
|
|
134300
135785
|
}
|
|
134301
135786
|
const server = app.listen(selectedPort, selectedHost);
|
|
@@ -134303,14 +135788,14 @@ async function runDashboard(port, opts = {}) {
|
|
|
134303
135788
|
if (err.code === "EADDRINUSE") {
|
|
134304
135789
|
server.listen(0, selectedHost);
|
|
134305
135790
|
} else {
|
|
134306
|
-
|
|
135791
|
+
logSink.error(`Failed to start server: ${err.message}`, "dashboard");
|
|
134307
135792
|
process.exit(1);
|
|
134308
135793
|
}
|
|
134309
135794
|
});
|
|
134310
135795
|
server.on("listening", async () => {
|
|
134311
135796
|
const actualPort = server.address().port;
|
|
134312
135797
|
if (actualPort !== selectedPort) {
|
|
134313
|
-
|
|
135798
|
+
logSink.warn(`Port ${selectedPort} in use, using ${actualPort} instead`, "dashboard");
|
|
134314
135799
|
}
|
|
134315
135800
|
if (centralCoreForMesh) {
|
|
134316
135801
|
try {
|
|
@@ -134323,7 +135808,7 @@ async function runDashboard(port, opts = {}) {
|
|
|
134323
135808
|
});
|
|
134324
135809
|
} catch (err) {
|
|
134325
135810
|
const message = err instanceof Error ? err.message : String(err);
|
|
134326
|
-
|
|
135811
|
+
logSink.warn(`Failed to start mDNS discovery: ${message}`, "dashboard");
|
|
134327
135812
|
}
|
|
134328
135813
|
}
|
|
134329
135814
|
if (centralCoreForMesh) {
|
|
@@ -134336,42 +135821,99 @@ async function runDashboard(port, opts = {}) {
|
|
|
134336
135821
|
}
|
|
134337
135822
|
} catch (err) {
|
|
134338
135823
|
const message = err instanceof Error ? err.message : String(err);
|
|
134339
|
-
|
|
135824
|
+
logSink.warn(`Failed to set local node online: ${message}`, "dashboard");
|
|
134340
135825
|
}
|
|
134341
135826
|
}
|
|
134342
135827
|
const displayHost = selectedHost === "0.0.0.0" || selectedHost === "::" ? selectedHost : "localhost";
|
|
134343
135828
|
const baseUrl = `http://${displayHost}:${actualPort}`;
|
|
134344
135829
|
const tokenizedUrl = dashboardAuthToken ? `${baseUrl}/?token=${encodeURIComponent(dashboardAuthToken)}` : baseUrl;
|
|
134345
|
-
|
|
134346
|
-
|
|
134347
|
-
|
|
134348
|
-
|
|
134349
|
-
|
|
134350
|
-
|
|
134351
|
-
|
|
134352
|
-
|
|
134353
|
-
|
|
134354
|
-
|
|
134355
|
-
|
|
134356
|
-
|
|
134357
|
-
|
|
134358
|
-
|
|
134359
|
-
|
|
134360
|
-
|
|
134361
|
-
|
|
135830
|
+
if (isTTY && tui) {
|
|
135831
|
+
const settings = await store.getSettings();
|
|
135832
|
+
const engineMode = opts.dev ? "dev" : settings.enginePaused ? "paused" : "active";
|
|
135833
|
+
const systemInfo = {
|
|
135834
|
+
host: displayHost,
|
|
135835
|
+
port: actualPort,
|
|
135836
|
+
baseUrl,
|
|
135837
|
+
authEnabled: Boolean(dashboardAuthToken),
|
|
135838
|
+
authToken: dashboardAuthToken,
|
|
135839
|
+
tokenizedUrl: dashboardAuthToken ? tokenizedUrl : void 0,
|
|
135840
|
+
engineMode,
|
|
135841
|
+
fileWatcher: true,
|
|
135842
|
+
startTimeMs: dashboardStartedAt
|
|
135843
|
+
};
|
|
135844
|
+
tui.setSystemInfo(systemInfo);
|
|
135845
|
+
tui.setSettings({
|
|
135846
|
+
maxConcurrent: settings.maxConcurrent ?? 1,
|
|
135847
|
+
maxWorktrees: settings.maxWorktrees ?? 2,
|
|
135848
|
+
autoMerge: settings.autoMerge ?? false,
|
|
135849
|
+
mergeStrategy: settings.mergeStrategy ?? "direct",
|
|
135850
|
+
pollIntervalMs: settings.pollIntervalMs ?? 6e4,
|
|
135851
|
+
enginePaused: settings.enginePaused ?? false,
|
|
135852
|
+
globalPause: settings.globalPause ?? false
|
|
135853
|
+
});
|
|
135854
|
+
const tasks = await store.listTasks({ slim: true, includeArchived: false });
|
|
135855
|
+
const counts = /* @__PURE__ */ new Map();
|
|
135856
|
+
for (const task of tasks) {
|
|
135857
|
+
counts.set(task.column, (counts.get(task.column) ?? 0) + 1);
|
|
135858
|
+
}
|
|
135859
|
+
const active = tasks.filter(
|
|
135860
|
+
(task) => task.column === "in-progress" || task.column === "in-review"
|
|
135861
|
+
).length;
|
|
135862
|
+
const agents = await agentStore.listAgents();
|
|
135863
|
+
const agentStats = { idle: 0, active: 0, running: 0, error: 0 };
|
|
135864
|
+
for (const agent of agents) {
|
|
135865
|
+
const state = agent.state;
|
|
135866
|
+
if (state in agentStats) {
|
|
135867
|
+
agentStats[state]++;
|
|
135868
|
+
}
|
|
135869
|
+
}
|
|
135870
|
+
tui.setTaskStats({
|
|
135871
|
+
total: tasks.length,
|
|
135872
|
+
byColumn: Object.fromEntries(counts),
|
|
135873
|
+
active,
|
|
135874
|
+
agents: agentStats
|
|
135875
|
+
});
|
|
135876
|
+
tui.log(`Dashboard started at ${baseUrl}`);
|
|
135877
|
+
if (engineMode === "active") {
|
|
135878
|
+
tui.log("AI engine active");
|
|
135879
|
+
} else if (engineMode === "dev") {
|
|
135880
|
+
tui.log("AI engine disabled (dev mode)");
|
|
135881
|
+
} else {
|
|
135882
|
+
tui.log("AI engine paused");
|
|
135883
|
+
}
|
|
135884
|
+
tui.log("File watcher active");
|
|
134362
135885
|
} else {
|
|
134363
|
-
console.log(
|
|
134364
|
-
console.log(`
|
|
134365
|
-
console.log(`
|
|
134366
|
-
console.log(`
|
|
135886
|
+
console.log();
|
|
135887
|
+
console.log(` fn board`);
|
|
135888
|
+
console.log(` \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500`);
|
|
135889
|
+
console.log(` \u2192 ${baseUrl}`);
|
|
135890
|
+
if (dashboardAuthToken) {
|
|
135891
|
+
console.log(` Auth: bearer token required`);
|
|
135892
|
+
console.log(` Token: ${dashboardAuthToken}`);
|
|
135893
|
+
console.log(` Open: ${tokenizedUrl}`);
|
|
135894
|
+
console.log(` (the browser stores the token so you only need to click once)`);
|
|
135895
|
+
} else {
|
|
135896
|
+
console.log(` Auth: disabled (--no-auth)`);
|
|
135897
|
+
}
|
|
135898
|
+
console.log();
|
|
135899
|
+
console.log(` Tasks stored in .fusion/tasks/`);
|
|
135900
|
+
console.log(` Merge: AI-assisted (conflict resolution + commit messages)`);
|
|
135901
|
+
if (opts.dev) {
|
|
135902
|
+
console.log(` AI engine: \u2717 disabled (dev mode)`);
|
|
135903
|
+
} else {
|
|
135904
|
+
console.log(` AI engine: \u2713 active`);
|
|
135905
|
+
console.log(` \u2022 triage: auto-specifying tasks`);
|
|
135906
|
+
console.log(` \u2022 scheduler: dependency-aware execution`);
|
|
135907
|
+
console.log(` \u2022 cron: scheduled task execution`);
|
|
135908
|
+
}
|
|
135909
|
+
console.log(` File watcher: \u2713 active`);
|
|
135910
|
+
console.log(` Press Ctrl+C to stop`);
|
|
135911
|
+
console.log();
|
|
134367
135912
|
}
|
|
134368
|
-
console.log(` File watcher: \u2713 active`);
|
|
134369
|
-
console.log(` Press Ctrl+C to stop`);
|
|
134370
|
-
console.log();
|
|
134371
135913
|
});
|
|
134372
135914
|
return { dispose };
|
|
134373
135915
|
}
|
|
134374
|
-
var processDiagnosticsRegistered, diagnosticIntervalHandle, DIAGNOSTIC_INTERVAL_MS, diagnosticStartTime, diagnosticDbHealthCheck, diagnosticStoreListenerCheck;
|
|
135916
|
+
var processDiagnosticsRegistered, diagnosticIntervalHandle, DIAGNOSTIC_INTERVAL_MS, diagnosticStartTime, diagnosticDbHealthCheck, diagnosticStoreListenerCheck, STREAM_LOG_FLUSH_IDLE_MS, StreamedLogBuffer;
|
|
134375
135917
|
var init_dashboard = __esm({
|
|
134376
135918
|
"src/commands/dashboard.ts"() {
|
|
134377
135919
|
"use strict";
|
|
@@ -134384,12 +135926,67 @@ var init_dashboard = __esm({
|
|
|
134384
135926
|
init_provider_auth();
|
|
134385
135927
|
init_auth_paths2();
|
|
134386
135928
|
init_project_context();
|
|
135929
|
+
init_dashboard_tui();
|
|
134387
135930
|
processDiagnosticsRegistered = false;
|
|
134388
135931
|
diagnosticIntervalHandle = null;
|
|
134389
135932
|
DIAGNOSTIC_INTERVAL_MS = 30 * 60 * 1e3;
|
|
134390
135933
|
diagnosticStartTime = 0;
|
|
134391
135934
|
diagnosticDbHealthCheck = null;
|
|
134392
135935
|
diagnosticStoreListenerCheck = null;
|
|
135936
|
+
STREAM_LOG_FLUSH_IDLE_MS = 100;
|
|
135937
|
+
StreamedLogBuffer = class {
|
|
135938
|
+
constructor(emitLine, flushIdleMs = STREAM_LOG_FLUSH_IDLE_MS) {
|
|
135939
|
+
this.emitLine = emitLine;
|
|
135940
|
+
this.flushIdleMs = flushIdleMs;
|
|
135941
|
+
}
|
|
135942
|
+
pending = "";
|
|
135943
|
+
flushTimer = null;
|
|
135944
|
+
push(delta) {
|
|
135945
|
+
if (!delta) return;
|
|
135946
|
+
this.pending += delta;
|
|
135947
|
+
this.flushCompletedLines();
|
|
135948
|
+
this.scheduleFlush();
|
|
135949
|
+
}
|
|
135950
|
+
flush() {
|
|
135951
|
+
this.clearFlushTimer();
|
|
135952
|
+
const trailing = this.pending.trim();
|
|
135953
|
+
if (trailing.length > 0) {
|
|
135954
|
+
this.emitLine(trailing);
|
|
135955
|
+
}
|
|
135956
|
+
this.pending = "";
|
|
135957
|
+
}
|
|
135958
|
+
dispose() {
|
|
135959
|
+
this.clearFlushTimer();
|
|
135960
|
+
this.pending = "";
|
|
135961
|
+
}
|
|
135962
|
+
flushCompletedLines() {
|
|
135963
|
+
if (!this.pending.includes("\n")) {
|
|
135964
|
+
return;
|
|
135965
|
+
}
|
|
135966
|
+
const splitLines = this.pending.split(/\r?\n/);
|
|
135967
|
+
const completeLines = splitLines.slice(0, -1);
|
|
135968
|
+
this.pending = splitLines[splitLines.length - 1] ?? "";
|
|
135969
|
+
for (const line of completeLines) {
|
|
135970
|
+
const normalized = line.trim();
|
|
135971
|
+
if (normalized.length > 0) {
|
|
135972
|
+
this.emitLine(normalized);
|
|
135973
|
+
}
|
|
135974
|
+
}
|
|
135975
|
+
}
|
|
135976
|
+
scheduleFlush() {
|
|
135977
|
+
this.clearFlushTimer();
|
|
135978
|
+
this.flushTimer = setTimeout(() => {
|
|
135979
|
+
this.flush();
|
|
135980
|
+
}, this.flushIdleMs);
|
|
135981
|
+
this.flushTimer.unref?.();
|
|
135982
|
+
}
|
|
135983
|
+
clearFlushTimer() {
|
|
135984
|
+
if (this.flushTimer) {
|
|
135985
|
+
clearTimeout(this.flushTimer);
|
|
135986
|
+
this.flushTimer = null;
|
|
135987
|
+
}
|
|
135988
|
+
}
|
|
135989
|
+
};
|
|
134393
135990
|
}
|
|
134394
135991
|
});
|
|
134395
135992
|
|
|
@@ -134400,7 +135997,7 @@ __export(node_exports, {
|
|
|
134400
135997
|
formatBytes: () => formatBytes3,
|
|
134401
135998
|
formatLastActivity: () => formatLastActivity,
|
|
134402
135999
|
formatStatusBar: () => formatStatusBar,
|
|
134403
|
-
formatUptime: () =>
|
|
136000
|
+
formatUptime: () => formatUptime3,
|
|
134404
136001
|
isValidNodeName: () => isValidNodeName,
|
|
134405
136002
|
maskApiKey: () => maskApiKey,
|
|
134406
136003
|
runMeshStatus: () => runMeshStatus,
|
|
@@ -134413,7 +136010,7 @@ __export(node_exports, {
|
|
|
134413
136010
|
runNodeRemove: () => runNodeRemove,
|
|
134414
136011
|
runNodeShow: () => runNodeShow
|
|
134415
136012
|
});
|
|
134416
|
-
import { createInterface as
|
|
136013
|
+
import { createInterface as createInterface3 } from "node:readline/promises";
|
|
134417
136014
|
function maskApiKey(key) {
|
|
134418
136015
|
if (!key) return "none";
|
|
134419
136016
|
if (key.length < 4) return "****";
|
|
@@ -134430,7 +136027,7 @@ function formatBytes3(bytes) {
|
|
|
134430
136027
|
if (value >= 10) return `${value.toFixed(1)} ${units[i]}`;
|
|
134431
136028
|
return `${value.toFixed(2)} ${units[i]}`;
|
|
134432
136029
|
}
|
|
134433
|
-
function
|
|
136030
|
+
function formatUptime3(ms) {
|
|
134434
136031
|
if (ms < 0) return "0s";
|
|
134435
136032
|
const seconds = Math.floor(ms / 1e3);
|
|
134436
136033
|
const minutes = Math.floor(seconds / 60);
|
|
@@ -134608,7 +136205,7 @@ async function runNodeDisconnect(name, options = {}) {
|
|
|
134608
136205
|
process.exit(1);
|
|
134609
136206
|
}
|
|
134610
136207
|
if (!options.force) {
|
|
134611
|
-
const rl =
|
|
136208
|
+
const rl = createInterface3({ input: process.stdin, output: process.stdout });
|
|
134612
136209
|
const answer = await rl.question(`Disconnect node '${node.name}'? [y/N] `);
|
|
134613
136210
|
rl.close();
|
|
134614
136211
|
if (answer.trim().toLowerCase() !== "y") {
|
|
@@ -134678,7 +136275,7 @@ async function runNodeShow(name, options = {}) {
|
|
|
134678
136275
|
console.log(` CPU Usage: ${formatStatusBar(metrics.cpuUsage)}`);
|
|
134679
136276
|
console.log(` Memory: ${formatBytes3(metrics.memoryUsed)} / ${formatBytes3(metrics.memoryTotal)}`);
|
|
134680
136277
|
console.log(` Storage: ${formatBytes3(metrics.storageUsed)} / ${formatBytes3(metrics.storageTotal)}`);
|
|
134681
|
-
console.log(` Uptime: ${
|
|
136278
|
+
console.log(` Uptime: ${formatUptime3(metrics.uptime)}`);
|
|
134682
136279
|
console.log(` Reported: ${formatLastActivity(metrics.reportedAt)}`);
|
|
134683
136280
|
} else {
|
|
134684
136281
|
console.log();
|
|
@@ -134834,7 +136431,7 @@ function formatBytes4(bytes) {
|
|
|
134834
136431
|
if (bytes < 1024 * 1024 * 1024) return `${Math.round(bytes / (1024 * 1024))}MB`;
|
|
134835
136432
|
return `${(bytes / (1024 * 1024 * 1024)).toFixed(1)}GB`;
|
|
134836
136433
|
}
|
|
134837
|
-
function
|
|
136434
|
+
function formatUptime4(ms) {
|
|
134838
136435
|
const seconds = Math.floor(ms / 1e3);
|
|
134839
136436
|
const minutes = Math.floor(seconds / 60);
|
|
134840
136437
|
const hours = Math.floor(minutes / 60);
|
|
@@ -134869,7 +136466,7 @@ function logDiagnostics2(prefix, dbHealthCheck) {
|
|
|
134869
136466
|
} catch {
|
|
134870
136467
|
}
|
|
134871
136468
|
}
|
|
134872
|
-
const logLine = `[${prefix}] diagnostics: uptime=${
|
|
136469
|
+
const logLine = `[${prefix}] diagnostics: uptime=${formatUptime4(uptime)} rss=${formatBytes4(mem.rss)} heap=${formatBytes4(mem.heapUsed)}/${formatBytes4(mem.heapTotal)} external=${formatBytes4(mem.external)} arrayBuffers=${formatBytes4(mem.arrayBuffers)} handles=${handleCount} requests=${requestCount} db=${dbHealth}${listenerInfo}`;
|
|
134873
136470
|
console.log(logLine);
|
|
134874
136471
|
}
|
|
134875
136472
|
function stopDiagnosticInterval2() {
|
|
@@ -134896,11 +136493,11 @@ function ensureProcessDiagnostics2() {
|
|
|
134896
136493
|
requestCount = process._getActiveRequests?.()?.length ?? -1;
|
|
134897
136494
|
} catch {
|
|
134898
136495
|
}
|
|
134899
|
-
console.log(`[serve] beforeExit code=${code} uptime=${
|
|
136496
|
+
console.log(`[serve] beforeExit code=${code} uptime=${formatUptime4(uptime)} handles=${handleCount} requests=${requestCount}`);
|
|
134900
136497
|
});
|
|
134901
136498
|
process.on("exit", (code) => {
|
|
134902
136499
|
const uptime = Date.now() - serveStartTime;
|
|
134903
|
-
console.log(`[serve] exit code=${code} uptime=${
|
|
136500
|
+
console.log(`[serve] exit code=${code} uptime=${formatUptime4(uptime)}`);
|
|
134904
136501
|
});
|
|
134905
136502
|
process.on("uncaughtExceptionMonitor", (error) => {
|
|
134906
136503
|
console.error(`[serve] uncaught exception pid=${process.pid}: ${error.stack || error.message}`);
|
|
@@ -135335,7 +136932,7 @@ function formatBytes5(bytes) {
|
|
|
135335
136932
|
if (bytes < 1024 * 1024 * 1024) return `${Math.round(bytes / (1024 * 1024))}MB`;
|
|
135336
136933
|
return `${(bytes / (1024 * 1024 * 1024)).toFixed(1)}GB`;
|
|
135337
136934
|
}
|
|
135338
|
-
function
|
|
136935
|
+
function formatUptime5(ms) {
|
|
135339
136936
|
const seconds = Math.floor(ms / 1e3);
|
|
135340
136937
|
const minutes = Math.floor(seconds / 60);
|
|
135341
136938
|
const hours = Math.floor(minutes / 60);
|
|
@@ -135363,7 +136960,7 @@ function logDiagnostics3(dbHealthCheck) {
|
|
|
135363
136960
|
dbHealth = "error";
|
|
135364
136961
|
}
|
|
135365
136962
|
}
|
|
135366
|
-
const logLine = `[daemon] diagnostics: uptime=${
|
|
136963
|
+
const logLine = `[daemon] diagnostics: uptime=${formatUptime5(uptime)} rss=${formatBytes5(mem.rss)} heap=${formatBytes5(mem.heapUsed)}/${formatBytes5(mem.heapTotal)} external=${formatBytes5(mem.external)} arrayBuffers=${formatBytes5(mem.arrayBuffers)} handles=${handleCount} requests=${requestCount} db=${dbHealth}`;
|
|
135367
136964
|
console.log(logLine);
|
|
135368
136965
|
}
|
|
135369
136966
|
function maskToken(token) {
|
|
@@ -135706,7 +137303,7 @@ __export(desktop_exports, {
|
|
|
135706
137303
|
import { spawn as spawn4 } from "node:child_process";
|
|
135707
137304
|
import { once as once2 } from "node:events";
|
|
135708
137305
|
import { join as join51 } from "node:path";
|
|
135709
|
-
import { createRequire } from "node:module";
|
|
137306
|
+
import { createRequire as createRequire2 } from "node:module";
|
|
135710
137307
|
function runCommand(command, args, cwd) {
|
|
135711
137308
|
return new Promise((resolve29, reject2) => {
|
|
135712
137309
|
const child = spawn4(command, args, {
|
|
@@ -135769,7 +137366,7 @@ function resolveElectronBinary() {
|
|
|
135769
137366
|
if (process.env.FUSION_ELECTRON_BINARY) {
|
|
135770
137367
|
return process.env.FUSION_ELECTRON_BINARY;
|
|
135771
137368
|
}
|
|
135772
|
-
return
|
|
137369
|
+
return require3("electron");
|
|
135773
137370
|
}
|
|
135774
137371
|
function terminateProcess(child, signal = "SIGTERM") {
|
|
135775
137372
|
if (!child || child.killed) {
|
|
@@ -135827,13 +137424,13 @@ async function runDesktop(options = {}) {
|
|
|
135827
137424
|
void shutdown(code ?? 0);
|
|
135828
137425
|
});
|
|
135829
137426
|
}
|
|
135830
|
-
var
|
|
137427
|
+
var require3;
|
|
135831
137428
|
var init_desktop = __esm({
|
|
135832
137429
|
"src/commands/desktop.ts"() {
|
|
135833
137430
|
"use strict";
|
|
135834
137431
|
init_src();
|
|
135835
137432
|
init_src3();
|
|
135836
|
-
|
|
137433
|
+
require3 = createRequire2(import.meta.url);
|
|
135837
137434
|
}
|
|
135838
137435
|
});
|
|
135839
137436
|
|
|
@@ -135866,7 +137463,7 @@ __export(task_exports, {
|
|
|
135866
137463
|
runTaskUnpause: () => runTaskUnpause,
|
|
135867
137464
|
runTaskUpdate: () => runTaskUpdate
|
|
135868
137465
|
});
|
|
135869
|
-
import { createInterface as
|
|
137466
|
+
import { createInterface as createInterface4 } from "node:readline/promises";
|
|
135870
137467
|
import { watchFile, unwatchFile, statSync as statSync7, existsSync as existsSync35, readFileSync as readFileSync14 } from "node:fs";
|
|
135871
137468
|
import { join as join52 } from "node:path";
|
|
135872
137469
|
function asLocalProjectContext(store) {
|
|
@@ -135935,7 +137532,7 @@ async function runTaskCreate(descriptionArg, attachFiles, depends, projectName)
|
|
|
135935
137532
|
let description = descriptionArg;
|
|
135936
137533
|
const projectContext = await getProjectContext(projectName);
|
|
135937
137534
|
if (!description) {
|
|
135938
|
-
const rl =
|
|
137535
|
+
const rl = createInterface4({ input: process.stdin, output: process.stdout });
|
|
135939
137536
|
description = await rl.question("Task description: ");
|
|
135940
137537
|
rl.close();
|
|
135941
137538
|
}
|
|
@@ -136036,11 +137633,11 @@ async function runTaskLog(id, message, outcome, projectName) {
|
|
|
136036
137633
|
console.log(` \u2713 ${id}: logged "${message}"`);
|
|
136037
137634
|
console.log();
|
|
136038
137635
|
}
|
|
136039
|
-
function
|
|
137636
|
+
function formatTimestamp4(timestamp) {
|
|
136040
137637
|
return new Date(timestamp).toLocaleTimeString();
|
|
136041
137638
|
}
|
|
136042
137639
|
function formatLogEntry(entry) {
|
|
136043
|
-
const ts =
|
|
137640
|
+
const ts = formatTimestamp4(entry.timestamp);
|
|
136044
137641
|
const agent = entry.agent ? `[${entry.agent.toUpperCase()}] ` : "";
|
|
136045
137642
|
switch (entry.type) {
|
|
136046
137643
|
case "text":
|
|
@@ -136272,7 +137869,7 @@ async function runTaskRefine(id, feedbackArg, projectName) {
|
|
|
136272
137869
|
const store = await getStore(projectName);
|
|
136273
137870
|
let feedback = feedbackArg;
|
|
136274
137871
|
if (feedback === void 0) {
|
|
136275
|
-
const rl =
|
|
137872
|
+
const rl = createInterface4({ input: process.stdin, output: process.stdout });
|
|
136276
137873
|
feedback = await rl.question("What needs to be refined? ");
|
|
136277
137874
|
rl.close();
|
|
136278
137875
|
}
|
|
@@ -136344,7 +137941,7 @@ async function runTaskDelete(id, force, projectName) {
|
|
|
136344
137941
|
return;
|
|
136345
137942
|
}
|
|
136346
137943
|
if (!force) {
|
|
136347
|
-
const rl =
|
|
137944
|
+
const rl = createInterface4({ input: process.stdin, output: process.stdout });
|
|
136348
137945
|
const answer = await rl.question(`Are you sure you want to delete ${id}? [y/N] `);
|
|
136349
137946
|
rl.close();
|
|
136350
137947
|
const trimmed = answer.trim().toLowerCase();
|
|
@@ -136408,7 +138005,7 @@ async function runTaskImportGitHubInteractive(ownerRepo, options = {}, projectNa
|
|
|
136408
138005
|
console.log(` ${i + 1}. #${issue.number} ${issue.title.slice(0, 80)}${issue.title.length > 80 ? "\u2026" : ""}${status}`);
|
|
136409
138006
|
}
|
|
136410
138007
|
console.log();
|
|
136411
|
-
const rl =
|
|
138008
|
+
const rl = createInterface4({ input: process.stdin, output: process.stdout });
|
|
136412
138009
|
let selectedIndices = [];
|
|
136413
138010
|
let validInput = false;
|
|
136414
138011
|
while (!validInput) {
|
|
@@ -136551,7 +138148,7 @@ async function runTaskComment(id, message, author = "user", projectName) {
|
|
|
136551
138148
|
const store = await getStore(projectName);
|
|
136552
138149
|
let text = message;
|
|
136553
138150
|
if (text === void 0) {
|
|
136554
|
-
const rl =
|
|
138151
|
+
const rl = createInterface4({ input: process.stdin, output: process.stdout });
|
|
136555
138152
|
text = await rl.question("Comment: ");
|
|
136556
138153
|
rl.close();
|
|
136557
138154
|
}
|
|
@@ -136594,7 +138191,7 @@ async function runTaskSteer(id, message, projectName) {
|
|
|
136594
138191
|
const store = await getStore(projectName);
|
|
136595
138192
|
let text = message;
|
|
136596
138193
|
if (text === void 0) {
|
|
136597
|
-
const rl =
|
|
138194
|
+
const rl = createInterface4({ input: process.stdin, output: process.stdout });
|
|
136598
138195
|
text = await rl.question("Message: ");
|
|
136599
138196
|
rl.close();
|
|
136600
138197
|
}
|
|
@@ -136724,7 +138321,7 @@ async function promptText(question) {
|
|
|
136724
138321
|
console.log(` ${question.description}`);
|
|
136725
138322
|
}
|
|
136726
138323
|
console.log(" (Enter your response. Type DONE on its own line when finished):\n");
|
|
136727
|
-
const rl =
|
|
138324
|
+
const rl = createInterface4({ input: process.stdin, output: process.stdout });
|
|
136728
138325
|
const lines = [];
|
|
136729
138326
|
return new Promise((resolve29) => {
|
|
136730
138327
|
const askLine = () => {
|
|
@@ -136758,7 +138355,7 @@ async function promptSingleSelect(question) {
|
|
|
136758
138355
|
console.log(` ${opt.description}`);
|
|
136759
138356
|
}
|
|
136760
138357
|
}
|
|
136761
|
-
const rl =
|
|
138358
|
+
const rl = createInterface4({ input: process.stdin, output: process.stdout });
|
|
136762
138359
|
while (true) {
|
|
136763
138360
|
const answer = await rl.question("\n Select (1-" + question.options.length + "): ");
|
|
136764
138361
|
const num = parseInt(answer.trim(), 10);
|
|
@@ -136786,7 +138383,7 @@ async function promptMultiSelect(question) {
|
|
|
136786
138383
|
console.log(` ${opt.description}`);
|
|
136787
138384
|
}
|
|
136788
138385
|
}
|
|
136789
|
-
const rl =
|
|
138386
|
+
const rl = createInterface4({ input: process.stdin, output: process.stdout });
|
|
136790
138387
|
while (true) {
|
|
136791
138388
|
const answer = await rl.question("\n Select (comma-separated): ");
|
|
136792
138389
|
const nums = answer.split(",").map((s) => parseInt(s.trim(), 10)).filter((n) => !isNaN(n));
|
|
@@ -136809,7 +138406,7 @@ async function promptConfirm(question) {
|
|
|
136809
138406
|
if (question.description) {
|
|
136810
138407
|
console.log(` ${question.description}`);
|
|
136811
138408
|
}
|
|
136812
|
-
const rl =
|
|
138409
|
+
const rl = createInterface4({ input: process.stdin, output: process.stdout });
|
|
136813
138410
|
const answer = await rl.question("\n [Y/n]: ");
|
|
136814
138411
|
rl.close();
|
|
136815
138412
|
const trimmed = answer.trim().toLowerCase();
|
|
@@ -136874,7 +138471,7 @@ function wrapText(text, width) {
|
|
|
136874
138471
|
async function runTaskPlan(initialPlanArg, yesFlag = false, projectName) {
|
|
136875
138472
|
let initialPlan = initialPlanArg;
|
|
136876
138473
|
if (!initialPlan) {
|
|
136877
|
-
const rl =
|
|
138474
|
+
const rl = createInterface4({ input: process.stdin, output: process.stdout });
|
|
136878
138475
|
console.log("\n Let's plan your task. What would you like to accomplish?\n");
|
|
136879
138476
|
initialPlan = await rl.question(" Describe your idea: ");
|
|
136880
138477
|
rl.close();
|
|
@@ -136975,7 +138572,7 @@ async function runTaskPlan(initialPlanArg, yesFlag = false, projectName) {
|
|
|
136975
138572
|
displaySummary(result.data);
|
|
136976
138573
|
let confirmed = yesFlag;
|
|
136977
138574
|
if (!yesFlag) {
|
|
136978
|
-
const rl =
|
|
138575
|
+
const rl = createInterface4({ input: process.stdin, output: process.stdout });
|
|
136979
138576
|
const answer = await rl.question(" Create this task? [Y/n]: ");
|
|
136980
138577
|
rl.close();
|
|
136981
138578
|
const trimmed = answer.trim().toLowerCase();
|
|
@@ -137459,7 +139056,7 @@ __export(git_exports, {
|
|
|
137459
139056
|
});
|
|
137460
139057
|
import { exec as exec10 } from "node:child_process";
|
|
137461
139058
|
import { promisify as promisify12 } from "node:util";
|
|
137462
|
-
import { createInterface as
|
|
139059
|
+
import { createInterface as createInterface5 } from "node:readline/promises";
|
|
137463
139060
|
async function resolveGitCwd(projectName) {
|
|
137464
139061
|
if (projectName) {
|
|
137465
139062
|
return (await resolveProject(projectName)).projectPath;
|
|
@@ -137647,7 +139244,7 @@ async function runGitPull(options = {}) {
|
|
|
137647
139244
|
console.log();
|
|
137648
139245
|
console.log(" \u26A0 Warning: You have uncommitted changes.");
|
|
137649
139246
|
console.log(` Branch: ${status.branch}`);
|
|
137650
|
-
const rl =
|
|
139247
|
+
const rl = createInterface5({ input: process.stdin, output: process.stdout });
|
|
137651
139248
|
const answer = await rl.question(" Continue with pull? [y/N] ");
|
|
137652
139249
|
rl.close();
|
|
137653
139250
|
const trimmed = answer.trim().toLowerCase();
|
|
@@ -137698,7 +139295,7 @@ async function runGitPush(options = {}) {
|
|
|
137698
139295
|
}
|
|
137699
139296
|
if (!options.skipConfirm) {
|
|
137700
139297
|
console.log();
|
|
137701
|
-
const rl =
|
|
139298
|
+
const rl = createInterface5({ input: process.stdin, output: process.stdout });
|
|
137702
139299
|
const answer = await rl.question(` Push branch ${status.branch} to remote? [Y/n] `);
|
|
137703
139300
|
rl.close();
|
|
137704
139301
|
const trimmed = answer.trim().toLowerCase();
|
|
@@ -137835,7 +139432,7 @@ var init_backup2 = __esm({
|
|
|
137835
139432
|
// src/project-resolver.ts
|
|
137836
139433
|
import { existsSync as existsSync37, statSync as statSync8 } from "node:fs";
|
|
137837
139434
|
import { dirname as dirname18, resolve as resolve24, normalize as normalize4 } from "node:path";
|
|
137838
|
-
import { createInterface as
|
|
139435
|
+
import { createInterface as createInterface6 } from "node:readline/promises";
|
|
137839
139436
|
async function getCentralCore() {
|
|
137840
139437
|
if (!centralCoreInstance) {
|
|
137841
139438
|
centralCoreInstance = new CentralCore();
|
|
@@ -137866,7 +139463,7 @@ function findKbDir(startPath) {
|
|
|
137866
139463
|
return null;
|
|
137867
139464
|
}
|
|
137868
139465
|
async function promptProjectSelection(projects, message = "Select a project:") {
|
|
137869
|
-
const rl =
|
|
139466
|
+
const rl = createInterface6({ input: process.stdin, output: process.stdout });
|
|
137870
139467
|
console.log(`
|
|
137871
139468
|
${message}`);
|
|
137872
139469
|
for (let i = 0; i < projects.length; i++) {
|
|
@@ -137883,7 +139480,7 @@ async function promptProjectSelection(projects, message = "Select a project:") {
|
|
|
137883
139480
|
}
|
|
137884
139481
|
}
|
|
137885
139482
|
async function promptConfirm2(message, defaultYes = false) {
|
|
137886
|
-
const rl =
|
|
139483
|
+
const rl = createInterface6({ input: process.stdin, output: process.stdout });
|
|
137887
139484
|
const prompt = defaultYes ? "[Y/n]" : "[y/N]";
|
|
137888
139485
|
const answer = await rl.question(` ${message} ${prompt}: `);
|
|
137889
139486
|
rl.close();
|
|
@@ -137943,7 +139540,7 @@ Run \`fn project remove ` + match.name + "` to clean up the registry entry.",
|
|
|
137943
139540
|
Found fn project at ${kbDir} but it's not registered.`);
|
|
137944
139541
|
const shouldRegister = await promptConfirm2("Register this project now?", true);
|
|
137945
139542
|
if (shouldRegister) {
|
|
137946
|
-
const rl =
|
|
139543
|
+
const rl = createInterface6({ input: process.stdin, output: process.stdout });
|
|
137947
139544
|
const defaultName = kbDir.split("/").pop() || "unnamed";
|
|
137948
139545
|
const name = await rl.question(` Project name [${defaultName}]: `);
|
|
137949
139546
|
rl.close();
|
|
@@ -138104,12 +139701,12 @@ __export(mission_exports, {
|
|
|
138104
139701
|
runMissionShow: () => runMissionShow,
|
|
138105
139702
|
runSliceAdd: () => runSliceAdd
|
|
138106
139703
|
});
|
|
138107
|
-
import { createInterface as
|
|
139704
|
+
import { createInterface as createInterface7 } from "node:readline/promises";
|
|
138108
139705
|
async function promptForTitleAndDescription(titleArg, titlePrompt, descriptionPrompt) {
|
|
138109
139706
|
let title = titleArg;
|
|
138110
139707
|
let description;
|
|
138111
139708
|
if (!title) {
|
|
138112
|
-
const rl =
|
|
139709
|
+
const rl = createInterface7({ input: process.stdin, output: process.stdout });
|
|
138113
139710
|
title = await rl.question(titlePrompt);
|
|
138114
139711
|
if (!title?.trim()) {
|
|
138115
139712
|
rl.close();
|
|
@@ -138238,7 +139835,7 @@ async function runMissionDelete(id, force, projectName) {
|
|
|
138238
139835
|
process.exit(1);
|
|
138239
139836
|
}
|
|
138240
139837
|
if (!force) {
|
|
138241
|
-
const rl =
|
|
139838
|
+
const rl = createInterface7({ input: process.stdin, output: process.stdout });
|
|
138242
139839
|
const answer = await rl.question(`Are you sure you want to delete ${id}: "${mission.title}"? [y/N] `);
|
|
138243
139840
|
rl.close();
|
|
138244
139841
|
const trimmed = answer.trim().toLowerCase();
|
|
@@ -138339,7 +139936,7 @@ async function runFeatureAdd(sliceId, titleArg, descriptionArg, acceptanceCriter
|
|
|
138339
139936
|
let description = descriptionArg?.trim() || void 0;
|
|
138340
139937
|
let acceptanceCriteria = acceptanceCriteriaArg?.trim() || void 0;
|
|
138341
139938
|
if (!title) {
|
|
138342
|
-
const rl =
|
|
139939
|
+
const rl = createInterface7({ input: process.stdin, output: process.stdout });
|
|
138343
139940
|
title = await rl.question("Feature title: ");
|
|
138344
139941
|
if (!title?.trim()) {
|
|
138345
139942
|
rl.close();
|
|
@@ -138433,7 +140030,7 @@ __export(project_exports, {
|
|
|
138433
140030
|
});
|
|
138434
140031
|
import { resolve as resolve25, isAbsolute as isAbsolute13, relative as relative11, basename as basename11 } from "node:path";
|
|
138435
140032
|
import { existsSync as existsSync38, statSync as statSync9 } from "node:fs";
|
|
138436
|
-
import { createInterface as
|
|
140033
|
+
import { createInterface as createInterface8 } from "node:readline/promises";
|
|
138437
140034
|
function formatDisplayPath(projectPath) {
|
|
138438
140035
|
const rel = relative11(process.cwd(), projectPath);
|
|
138439
140036
|
if (rel && !rel.startsWith("..") && rel !== "") {
|
|
@@ -138554,7 +140151,7 @@ async function runProjectAdd(name, path4, options = {}) {
|
|
|
138554
140151
|
let projectName = name;
|
|
138555
140152
|
let projectPath = path4;
|
|
138556
140153
|
if (!projectName || !projectPath || options.interactive) {
|
|
138557
|
-
const rl =
|
|
140154
|
+
const rl = createInterface8({ input: process.stdin, output: process.stdout });
|
|
138558
140155
|
if (!projectPath) {
|
|
138559
140156
|
const defaultPath = process.cwd();
|
|
138560
140157
|
const pathInput = await rl.question(` Project path [${defaultPath}]: `);
|
|
@@ -138679,7 +140276,7 @@ async function runProjectRemove(name, options = {}) {
|
|
|
138679
140276
|
process.exit(1);
|
|
138680
140277
|
}
|
|
138681
140278
|
if (!options.force) {
|
|
138682
|
-
const rl =
|
|
140279
|
+
const rl = createInterface8({ input: process.stdin, output: process.stdout });
|
|
138683
140280
|
const answer = await rl.question(`Unregister project '${project.name}'? [y/N] `);
|
|
138684
140281
|
rl.close();
|
|
138685
140282
|
if (answer.trim().toLowerCase() !== "y") {
|
|
@@ -139651,7 +141248,7 @@ __export(plugin_exports, {
|
|
|
139651
141248
|
import { existsSync as existsSync41 } from "node:fs";
|
|
139652
141249
|
import { join as join55 } from "node:path";
|
|
139653
141250
|
import { readFile as readFile23 } from "node:fs/promises";
|
|
139654
|
-
import * as
|
|
141251
|
+
import * as readline2 from "node:readline";
|
|
139655
141252
|
async function getProjectPath6(projectName) {
|
|
139656
141253
|
if (projectName) {
|
|
139657
141254
|
const context = await resolveProject(projectName);
|
|
@@ -139791,7 +141388,7 @@ async function runPluginUninstall(id, options) {
|
|
|
139791
141388
|
console.log(` This will stop and remove the plugin.`);
|
|
139792
141389
|
console.log();
|
|
139793
141390
|
const response = await new Promise((resolve29) => {
|
|
139794
|
-
const rl =
|
|
141391
|
+
const rl = readline2.createInterface({
|
|
139795
141392
|
input: process.stdin,
|
|
139796
141393
|
output: process.stdout
|
|
139797
141394
|
});
|
|
@@ -140309,7 +141906,7 @@ var init_native_patch = __esm({
|
|
|
140309
141906
|
|
|
140310
141907
|
// src/bin.ts
|
|
140311
141908
|
import { existsSync as existsSync44, mkdtempSync as mkdtempSync2, readFileSync as readFileSync17, symlinkSync as symlinkSync2, writeFileSync as writeFileSync6 } from "node:fs";
|
|
140312
|
-
import { createRequire as
|
|
141909
|
+
import { createRequire as createRequire3 } from "node:module";
|
|
140313
141910
|
import { join as join58, dirname as dirname20 } from "node:path";
|
|
140314
141911
|
import { tmpdir as tmpdir4 } from "node:os";
|
|
140315
141912
|
var isBunBinary3 = typeof Bun !== "undefined" && !!Bun.embeddedFiles;
|
|
@@ -140324,8 +141921,8 @@ function configurePiPackage() {
|
|
|
140324
141921
|
type: "module"
|
|
140325
141922
|
};
|
|
140326
141923
|
try {
|
|
140327
|
-
const
|
|
140328
|
-
const piPackagePath =
|
|
141924
|
+
const require4 = createRequire3(import.meta.url);
|
|
141925
|
+
const piPackagePath = require4.resolve("@mariozechner/pi-coding-agent/package.json");
|
|
140329
141926
|
const piPackageDir = dirname20(piPackagePath);
|
|
140330
141927
|
packageJson = JSON.parse(readFileSync17(piPackagePath, "utf-8"));
|
|
140331
141928
|
for (const entry of ["dist", "docs", "examples", "README.md", "CHANGELOG.md"]) {
|