panopticon-cli 0.5.6 → 0.5.7
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/{agents-5HWTDR4S.js → agents-QXVDAW2M.js} +2 -2
- package/dist/{chunk-FUUP55PE.js → chunk-4XR62WWV.js} +2 -1
- package/dist/{chunk-FUUP55PE.js.map → chunk-4XR62WWV.js.map} +1 -1
- package/dist/{chunk-WJJ3ZIQ6.js → chunk-TFPJD2I2.js} +16 -16
- package/dist/cli/index.js +186 -233
- package/dist/cli/index.js.map +1 -1
- package/dist/dashboard/public/assets/{index-Db9NOz4z.js → index-C7hJ5-o1.js} +56 -56
- package/dist/dashboard/public/index.html +1 -1
- package/dist/dashboard/server.js +6 -1
- package/dist/{merge-agent-WM7ZKUET.js → merge-agent-O3TSBTLC.js} +4 -4
- package/dist/{specialist-context-74RQF5SR.js → specialist-context-IKG6VMNH.js} +2 -2
- package/dist/{specialist-logs-T5GW7CSU.js → specialist-logs-GFKUXCFG.js} +2 -2
- package/dist/{specialists-HTYYFXHQ.js → specialists-XMFCFGYQ.js} +2 -2
- package/package.json +1 -1
- /package/dist/{agents-5HWTDR4S.js.map → agents-QXVDAW2M.js.map} +0 -0
- /package/dist/{chunk-WJJ3ZIQ6.js.map → chunk-TFPJD2I2.js.map} +0 -0
- /package/dist/{merge-agent-WM7ZKUET.js.map → merge-agent-O3TSBTLC.js.map} +0 -0
- /package/dist/{specialist-context-74RQF5SR.js.map → specialist-context-IKG6VMNH.js.map} +0 -0
- /package/dist/{specialist-logs-T5GW7CSU.js.map → specialist-logs-GFKUXCFG.js.map} +0 -0
- /package/dist/{specialists-HTYYFXHQ.js.map → specialists-XMFCFGYQ.js.map} +0 -0
package/dist/cli/index.js
CHANGED
|
@@ -16,7 +16,8 @@ import {
|
|
|
16
16
|
init_database,
|
|
17
17
|
init_review_status,
|
|
18
18
|
loadReviewStatuses,
|
|
19
|
-
saveReviewStatuses
|
|
19
|
+
saveReviewStatuses,
|
|
20
|
+
setReviewStatus
|
|
20
21
|
} from "../chunk-IZIXJYXZ.js";
|
|
21
22
|
import {
|
|
22
23
|
checkBudget,
|
|
@@ -49,7 +50,7 @@ import {
|
|
|
49
50
|
setSessionId,
|
|
50
51
|
summarizeCosts,
|
|
51
52
|
wakeSpecialistOrQueue
|
|
52
|
-
} from "../chunk-
|
|
53
|
+
} from "../chunk-TFPJD2I2.js";
|
|
53
54
|
import "../chunk-JQBV3Q2W.js";
|
|
54
55
|
import {
|
|
55
56
|
archivePlanning,
|
|
@@ -108,7 +109,7 @@ import {
|
|
|
108
109
|
saveSessionId,
|
|
109
110
|
spawnAgent,
|
|
110
111
|
stopAgent
|
|
111
|
-
} from "../chunk-
|
|
112
|
+
} from "../chunk-4XR62WWV.js";
|
|
112
113
|
import {
|
|
113
114
|
checkHook,
|
|
114
115
|
clearHook,
|
|
@@ -244,9 +245,9 @@ import {
|
|
|
244
245
|
|
|
245
246
|
// src/cli/index.ts
|
|
246
247
|
init_esm_shims();
|
|
247
|
-
import { readFileSync as
|
|
248
|
-
import { join as
|
|
249
|
-
import { homedir as
|
|
248
|
+
import { readFileSync as readFileSync45, existsSync as existsSync51 } from "fs";
|
|
249
|
+
import { join as join51 } from "path";
|
|
250
|
+
import { homedir as homedir23 } from "os";
|
|
250
251
|
import { Command as Command2 } from "commander";
|
|
251
252
|
import chalk62 from "chalk";
|
|
252
253
|
|
|
@@ -2200,15 +2201,13 @@ async function updateLinearStatus(apiKey, issueIdentifier) {
|
|
|
2200
2201
|
try {
|
|
2201
2202
|
const { LinearClient: LinearClient2 } = await import("@linear/sdk");
|
|
2202
2203
|
const client = new LinearClient2({ apiKey });
|
|
2203
|
-
const
|
|
2204
|
-
const
|
|
2205
|
-
const team = teams.nodes[0];
|
|
2206
|
-
if (!team) return false;
|
|
2207
|
-
const issues = await team.issues({ first: 100 });
|
|
2208
|
-
const issue = issues.nodes.find(
|
|
2204
|
+
const searchResults = await client.searchIssues(issueIdentifier, { first: 1 });
|
|
2205
|
+
const issue = searchResults.nodes.find(
|
|
2209
2206
|
(i) => i.identifier.toUpperCase() === issueIdentifier.toUpperCase()
|
|
2210
2207
|
);
|
|
2211
2208
|
if (!issue) return false;
|
|
2209
|
+
const team = await issue.team;
|
|
2210
|
+
if (!team) return false;
|
|
2212
2211
|
const states = await team.states();
|
|
2213
2212
|
const doneState = states.nodes.find((s) => s.type === "completed" && s.name === "Done");
|
|
2214
2213
|
if (!doneState) return false;
|
|
@@ -2467,15 +2466,13 @@ async function updateLinearToInReview(apiKey, issueIdentifier, comment) {
|
|
|
2467
2466
|
try {
|
|
2468
2467
|
const { LinearClient: LinearClient2 } = await import("@linear/sdk");
|
|
2469
2468
|
const client = new LinearClient2({ apiKey });
|
|
2470
|
-
const
|
|
2471
|
-
const
|
|
2472
|
-
const team = teams.nodes[0];
|
|
2473
|
-
if (!team) return false;
|
|
2474
|
-
const issues = await team.issues({ first: 100 });
|
|
2475
|
-
const issue = issues.nodes.find(
|
|
2469
|
+
const searchResults = await client.searchIssues(issueIdentifier, { first: 1 });
|
|
2470
|
+
const issue = searchResults.nodes.find(
|
|
2476
2471
|
(i) => i.identifier.toUpperCase() === issueIdentifier.toUpperCase()
|
|
2477
2472
|
);
|
|
2478
2473
|
if (!issue) return false;
|
|
2474
|
+
const team = await issue.team;
|
|
2475
|
+
if (!team) return false;
|
|
2479
2476
|
const states = await team.states();
|
|
2480
2477
|
const targetStateName = getLinearStateName("in_review");
|
|
2481
2478
|
const targetState = findLinearStateByName(states.nodes, targetStateName);
|
|
@@ -2557,7 +2554,7 @@ async function doneCommand(id, options = {}) {
|
|
|
2557
2554
|
const issueId = id.replace(/^agent-/i, "").toUpperCase();
|
|
2558
2555
|
const agentId = `agent-${issueId.toLowerCase()}`;
|
|
2559
2556
|
if (!options.force) {
|
|
2560
|
-
const { getAgentState: getAgentState2 } = await import("../agents-
|
|
2557
|
+
const { getAgentState: getAgentState2 } = await import("../agents-QXVDAW2M.js");
|
|
2561
2558
|
const agentState = getAgentState2(agentId);
|
|
2562
2559
|
const workspacePath = agentState?.workspace;
|
|
2563
2560
|
if (workspacePath && existsSync12(workspacePath)) {
|
|
@@ -2656,7 +2653,7 @@ async function doneCommand(id, options = {}) {
|
|
|
2656
2653
|
console.log(chalk12.dim(" LINEAR_API_KEY not set - skipping status update"));
|
|
2657
2654
|
}
|
|
2658
2655
|
}
|
|
2659
|
-
const { getAgentState: getAgentState2, saveAgentState: saveAgentState2 } = await import("../agents-
|
|
2656
|
+
const { getAgentState: getAgentState2, saveAgentState: saveAgentState2 } = await import("../agents-QXVDAW2M.js");
|
|
2660
2657
|
const existingState = getAgentState2(agentId);
|
|
2661
2658
|
if (existingState) {
|
|
2662
2659
|
existingState.status = "stopped";
|
|
@@ -3315,21 +3312,15 @@ async function planCommand(id, options = {}) {
|
|
|
3315
3312
|
spinner.text = "Fetching issue from Linear...";
|
|
3316
3313
|
const { LinearClient: LinearClient2 } = await import("@linear/sdk");
|
|
3317
3314
|
const client = new LinearClient2({ apiKey });
|
|
3318
|
-
const
|
|
3319
|
-
const
|
|
3320
|
-
const team = teams.nodes[0];
|
|
3321
|
-
if (!team) {
|
|
3322
|
-
spinner.fail("No Linear team found");
|
|
3323
|
-
process.exit(1);
|
|
3324
|
-
}
|
|
3325
|
-
const searchResult = await team.issues({ first: 100 });
|
|
3326
|
-
const issue = searchResult.nodes.find(
|
|
3315
|
+
const searchResults = await client.searchIssues(id, { first: 1 });
|
|
3316
|
+
const searchHit = searchResults.nodes.find(
|
|
3327
3317
|
(i) => i.identifier.toUpperCase() === id.toUpperCase()
|
|
3328
3318
|
);
|
|
3329
|
-
if (!
|
|
3319
|
+
if (!searchHit) {
|
|
3330
3320
|
spinner.fail(`Issue not found: ${id}`);
|
|
3331
3321
|
process.exit(1);
|
|
3332
3322
|
}
|
|
3323
|
+
const issue = await client.issue(searchHit.id);
|
|
3333
3324
|
const state = await issue.state;
|
|
3334
3325
|
const assignee = await issue.assignee;
|
|
3335
3326
|
const project2 = await issue.project;
|
|
@@ -5201,7 +5192,7 @@ Previous state: ${issue.state}`
|
|
|
5201
5192
|
console.log(chalk21.green(`\u2713 ${issue.identifier} reopened and ready for re-work`));
|
|
5202
5193
|
console.log("");
|
|
5203
5194
|
try {
|
|
5204
|
-
const { getAgentState: getAgentState2 } = await import("../agents-
|
|
5195
|
+
const { getAgentState: getAgentState2 } = await import("../agents-QXVDAW2M.js");
|
|
5205
5196
|
const agentId = `agent-${id.toLowerCase()}`;
|
|
5206
5197
|
const agentState = getAgentState2(agentId);
|
|
5207
5198
|
const agentRunning = agentState?.status === "running" || agentState?.status === "starting";
|
|
@@ -5620,14 +5611,8 @@ async function syncToLinear(apiKey, issueId, targetState) {
|
|
|
5620
5611
|
try {
|
|
5621
5612
|
const { LinearClient: LinearClient2 } = await import("@linear/sdk");
|
|
5622
5613
|
const client = new LinearClient2({ apiKey });
|
|
5623
|
-
const
|
|
5624
|
-
const
|
|
5625
|
-
const team = teams.nodes[0];
|
|
5626
|
-
if (!team) {
|
|
5627
|
-
return { success: false, error: "No Linear team found" };
|
|
5628
|
-
}
|
|
5629
|
-
const issues = await team.issues({ first: 100 });
|
|
5630
|
-
const issue = issues.nodes.find(
|
|
5614
|
+
const searchResults = await client.searchIssues(issueId, { first: 1 });
|
|
5615
|
+
const issue = searchResults.nodes.find(
|
|
5631
5616
|
(i) => i.identifier.toUpperCase() === issueId.toUpperCase()
|
|
5632
5617
|
);
|
|
5633
5618
|
if (!issue) {
|
|
@@ -5635,6 +5620,10 @@ async function syncToLinear(apiKey, issueId, targetState) {
|
|
|
5635
5620
|
}
|
|
5636
5621
|
const currentState = await issue.state;
|
|
5637
5622
|
const previousState = currentState?.type === "completed" ? "closed" : currentState?.type === "started" ? "in_progress" : "open";
|
|
5623
|
+
const team = await issue.team;
|
|
5624
|
+
if (!team) {
|
|
5625
|
+
return { success: false, error: "Could not resolve team from issue" };
|
|
5626
|
+
}
|
|
5638
5627
|
const states = await team.states();
|
|
5639
5628
|
let targetLinearState = null;
|
|
5640
5629
|
switch (targetState) {
|
|
@@ -5839,14 +5828,8 @@ async function refreshFromLinear(apiKey, issueId) {
|
|
|
5839
5828
|
try {
|
|
5840
5829
|
const { LinearClient: LinearClient2 } = await import("@linear/sdk");
|
|
5841
5830
|
const client = new LinearClient2({ apiKey });
|
|
5842
|
-
const
|
|
5843
|
-
const
|
|
5844
|
-
const team = teams.nodes[0];
|
|
5845
|
-
if (!team) {
|
|
5846
|
-
return { success: false, error: "No Linear team found" };
|
|
5847
|
-
}
|
|
5848
|
-
const issues = await team.issues({ first: 100 });
|
|
5849
|
-
const issue = issues.nodes.find(
|
|
5831
|
+
const searchResults = await client.searchIssues(issueId, { first: 1 });
|
|
5832
|
+
const issue = searchResults.nodes.find(
|
|
5850
5833
|
(i) => i.identifier.toUpperCase() === issueId.toUpperCase()
|
|
5851
5834
|
);
|
|
5852
5835
|
if (!issue) {
|
|
@@ -6523,8 +6506,8 @@ async function verifyBranchMerged(ctx) {
|
|
|
6523
6506
|
const branchName = `feature/${issueLower}`;
|
|
6524
6507
|
try {
|
|
6525
6508
|
try {
|
|
6526
|
-
const { loadReviewStatuses:
|
|
6527
|
-
const statuses =
|
|
6509
|
+
const { loadReviewStatuses: loadReviewStatuses2 } = await import("../review-status-J2YJGL3E.js");
|
|
6510
|
+
const statuses = loadReviewStatuses2();
|
|
6528
6511
|
const issueKey = ctx.issueId.toUpperCase();
|
|
6529
6512
|
if (statuses[issueKey]?.mergeStatus === "merged") {
|
|
6530
6513
|
return stepOk(step, ["Merge specialist confirmed merge completed"]);
|
|
@@ -6592,8 +6575,8 @@ async function clearReviewStatusStep(issueId) {
|
|
|
6592
6575
|
const upperKey = issueId.toUpperCase();
|
|
6593
6576
|
if (data[upperKey]) {
|
|
6594
6577
|
delete data[upperKey];
|
|
6595
|
-
const { writeFileSync:
|
|
6596
|
-
|
|
6578
|
+
const { writeFileSync: writeFileSync26 } = await import("fs");
|
|
6579
|
+
writeFileSync26(statusFile, JSON.stringify(data, null, 2));
|
|
6597
6580
|
}
|
|
6598
6581
|
}
|
|
6599
6582
|
return stepOk(step, ["Review status cleared (direct)"]);
|
|
@@ -10849,7 +10832,7 @@ async function checkOrphanedReviewStatuses() {
|
|
|
10849
10832
|
(h) => h.type === "review" && h.status === "passed"
|
|
10850
10833
|
);
|
|
10851
10834
|
const hasPassedTest = status.history?.some(
|
|
10852
|
-
(h) => h.type === "test" &&
|
|
10835
|
+
(h) => h.type === "test" && h.status === "passed"
|
|
10853
10836
|
);
|
|
10854
10837
|
const reviewAgentActive = activeReviewSessions.has(issueId.toUpperCase());
|
|
10855
10838
|
if (status.reviewStatus === "reviewing" && !reviewAgentActive && !hasPassedReview) {
|
|
@@ -10885,7 +10868,7 @@ async function checkOrphanedReviewStatuses() {
|
|
|
10885
10868
|
const { resolveProjectFromIssue: resolveProjectFromIssue2 } = await import("../projects-3CRF57ZU.js");
|
|
10886
10869
|
const resolved = resolveProjectFromIssue2(issueId);
|
|
10887
10870
|
if (resolved) {
|
|
10888
|
-
const { spawnEphemeralSpecialist } = await import("../specialists-
|
|
10871
|
+
const { spawnEphemeralSpecialist } = await import("../specialists-XMFCFGYQ.js");
|
|
10889
10872
|
const result = await spawnEphemeralSpecialist(resolved.projectKey, "test-agent", {
|
|
10890
10873
|
issueId,
|
|
10891
10874
|
workspace,
|
|
@@ -11287,7 +11270,7 @@ async function runPatrol() {
|
|
|
11287
11270
|
statuses[issueId].mergeStatus = "merged";
|
|
11288
11271
|
statuses[issueId].readyForMerge = false;
|
|
11289
11272
|
writeFileSync19(REVIEW_STATUS_FILE, JSON.stringify(statuses, null, 2), "utf-8");
|
|
11290
|
-
const { postMergeLifecycle } = await import("../merge-agent-
|
|
11273
|
+
const { postMergeLifecycle } = await import("../merge-agent-O3TSBTLC.js");
|
|
11291
11274
|
postMergeLifecycle(issueId, resolved.projectPath).catch(
|
|
11292
11275
|
(err) => console.warn(`[deacon] postMergeLifecycle failed for ${issueId}: ${err}`)
|
|
11293
11276
|
);
|
|
@@ -11738,6 +11721,10 @@ var CloisterService = class {
|
|
|
11738
11721
|
console.log(`\u{1F514} Agent ${agentId} is suspended, skipping restart`);
|
|
11739
11722
|
return;
|
|
11740
11723
|
}
|
|
11724
|
+
if (runtimeState?.state === "stopped") {
|
|
11725
|
+
console.log(`\u{1F514} Agent ${agentId} runtime is stopped, skipping restart`);
|
|
11726
|
+
return;
|
|
11727
|
+
}
|
|
11741
11728
|
const now = /* @__PURE__ */ new Date();
|
|
11742
11729
|
this.deathTimestamps.push(now);
|
|
11743
11730
|
this.checkForMassDeaths();
|
|
@@ -13049,24 +13036,8 @@ function confirm2(question) {
|
|
|
13049
13036
|
|
|
13050
13037
|
// src/cli/commands/specialists/done.ts
|
|
13051
13038
|
init_esm_shims();
|
|
13039
|
+
init_review_status();
|
|
13052
13040
|
import chalk45 from "chalk";
|
|
13053
|
-
import { existsSync as existsSync44, readFileSync as readFileSync38, writeFileSync as writeFileSync24 } from "fs";
|
|
13054
|
-
import { join as join43 } from "path";
|
|
13055
|
-
import { homedir as homedir20 } from "os";
|
|
13056
|
-
var REVIEW_STATUS_FILE3 = join43(homedir20(), ".panopticon", "review-status.json");
|
|
13057
|
-
function loadReviewStatuses2() {
|
|
13058
|
-
try {
|
|
13059
|
-
if (existsSync44(REVIEW_STATUS_FILE3)) {
|
|
13060
|
-
return JSON.parse(readFileSync38(REVIEW_STATUS_FILE3, "utf-8"));
|
|
13061
|
-
}
|
|
13062
|
-
} catch (error) {
|
|
13063
|
-
console.error(chalk45.yellow("Warning: Could not load review statuses"));
|
|
13064
|
-
}
|
|
13065
|
-
return {};
|
|
13066
|
-
}
|
|
13067
|
-
function saveReviewStatuses2(statuses) {
|
|
13068
|
-
writeFileSync24(REVIEW_STATUS_FILE3, JSON.stringify(statuses, null, 2));
|
|
13069
|
-
}
|
|
13070
13041
|
async function doneCommand2(specialist, issueId, options) {
|
|
13071
13042
|
const validSpecialists = ["review", "test", "merge"];
|
|
13072
13043
|
if (!validSpecialists.includes(specialist)) {
|
|
@@ -13084,57 +13055,39 @@ async function doneCommand2(specialist, issueId, options) {
|
|
|
13084
13055
|
process.exit(1);
|
|
13085
13056
|
}
|
|
13086
13057
|
const normalizedIssueId = issueId.toUpperCase();
|
|
13087
|
-
const
|
|
13088
|
-
let status = statuses[normalizedIssueId];
|
|
13089
|
-
if (!status) {
|
|
13090
|
-
status = {
|
|
13091
|
-
issueId: normalizedIssueId,
|
|
13092
|
-
reviewStatus: "pending",
|
|
13093
|
-
testStatus: "pending",
|
|
13094
|
-
updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
13095
|
-
readyForMerge: false
|
|
13096
|
-
};
|
|
13097
|
-
}
|
|
13058
|
+
const update = {};
|
|
13098
13059
|
switch (specialist) {
|
|
13099
13060
|
case "review":
|
|
13100
|
-
|
|
13101
|
-
if (options.notes)
|
|
13102
|
-
status.reviewNotes = options.notes;
|
|
13103
|
-
}
|
|
13061
|
+
update.reviewStatus = options.status;
|
|
13062
|
+
if (options.notes) update.reviewNotes = options.notes;
|
|
13104
13063
|
console.log(chalk45.green(`\u2713 Review ${options.status} for ${normalizedIssueId}`));
|
|
13105
13064
|
if (options.status === "passed") {
|
|
13106
13065
|
console.log(chalk45.dim(" Test agent can now proceed"));
|
|
13107
13066
|
}
|
|
13108
13067
|
break;
|
|
13109
13068
|
case "test":
|
|
13110
|
-
|
|
13111
|
-
if (options.notes)
|
|
13112
|
-
|
|
13113
|
-
}
|
|
13114
|
-
if (options.status === "passed" && status.reviewStatus === "passed") {
|
|
13115
|
-
status.readyForMerge = true;
|
|
13116
|
-
console.log(chalk45.green(`\u2713 Tests ${options.status} for ${normalizedIssueId}`));
|
|
13117
|
-
console.log(chalk45.green("\u2713 Ready for merge!"));
|
|
13118
|
-
} else if (options.status === "passed") {
|
|
13069
|
+
update.testStatus = options.status;
|
|
13070
|
+
if (options.notes) update.testNotes = options.notes;
|
|
13071
|
+
if (options.status === "passed") {
|
|
13119
13072
|
console.log(chalk45.green(`\u2713 Tests ${options.status} for ${normalizedIssueId}`));
|
|
13120
13073
|
} else {
|
|
13121
13074
|
console.log(chalk45.yellow(`\u2717 Tests ${options.status} for ${normalizedIssueId}`));
|
|
13122
|
-
status.readyForMerge = false;
|
|
13123
13075
|
}
|
|
13124
13076
|
break;
|
|
13125
13077
|
case "merge":
|
|
13126
|
-
|
|
13078
|
+
update.mergeStatus = options.status === "passed" ? "merged" : "failed";
|
|
13127
13079
|
if (options.status === "passed") {
|
|
13080
|
+
update.readyForMerge = false;
|
|
13128
13081
|
console.log(chalk45.green(`\u2713 Merge completed for ${normalizedIssueId}`));
|
|
13129
|
-
status.readyForMerge = false;
|
|
13130
13082
|
} else {
|
|
13131
13083
|
console.log(chalk45.red(`\u2717 Merge failed for ${normalizedIssueId}`));
|
|
13132
13084
|
}
|
|
13133
13085
|
break;
|
|
13134
13086
|
}
|
|
13135
|
-
status
|
|
13136
|
-
|
|
13137
|
-
|
|
13087
|
+
const status = setReviewStatus(normalizedIssueId, update);
|
|
13088
|
+
if (specialist === "test" && status.readyForMerge) {
|
|
13089
|
+
console.log(chalk45.green("\u2713 Ready for merge!"));
|
|
13090
|
+
}
|
|
13138
13091
|
if (options.notes) {
|
|
13139
13092
|
console.log(chalk45.dim(` Notes: ${options.notes}`));
|
|
13140
13093
|
}
|
|
@@ -13166,13 +13119,13 @@ function formatStatus(status) {
|
|
|
13166
13119
|
|
|
13167
13120
|
// src/cli/commands/specialists/logs.ts
|
|
13168
13121
|
init_esm_shims();
|
|
13169
|
-
import { existsSync as
|
|
13122
|
+
import { existsSync as existsSync44 } from "fs";
|
|
13170
13123
|
import { exec as exec15 } from "child_process";
|
|
13171
13124
|
import { promisify as promisify15 } from "util";
|
|
13172
13125
|
var execAsync15 = promisify15(exec15);
|
|
13173
13126
|
async function listLogsCommand(project2, type, options) {
|
|
13174
13127
|
try {
|
|
13175
|
-
const { listRunLogs } = await import("../specialist-logs-
|
|
13128
|
+
const { listRunLogs } = await import("../specialist-logs-GFKUXCFG.js");
|
|
13176
13129
|
const limit = options.limit ? parseInt(options.limit) : 10;
|
|
13177
13130
|
const runs = listRunLogs(project2, type, { limit });
|
|
13178
13131
|
if (options.json) {
|
|
@@ -13217,7 +13170,7 @@ View a specific run: pan specialists logs ${project2} ${type} <runId>
|
|
|
13217
13170
|
}
|
|
13218
13171
|
async function viewLogCommand(project2, type, runId, options) {
|
|
13219
13172
|
try {
|
|
13220
|
-
const { getRunLog, parseLogMetadata, getRunLogPath } = await import("../specialist-logs-
|
|
13173
|
+
const { getRunLog, parseLogMetadata, getRunLogPath } = await import("../specialist-logs-GFKUXCFG.js");
|
|
13221
13174
|
const content = getRunLog(project2, type, runId);
|
|
13222
13175
|
if (!content) {
|
|
13223
13176
|
console.error(`\u274C Run log not found: ${runId}`);
|
|
@@ -13241,15 +13194,15 @@ async function viewLogCommand(project2, type, runId, options) {
|
|
|
13241
13194
|
}
|
|
13242
13195
|
async function tailLogCommand(project2, type) {
|
|
13243
13196
|
try {
|
|
13244
|
-
const { getRunLogPath } = await import("../specialist-logs-
|
|
13245
|
-
const { getProjectSpecialistMetadata } = await import("../specialists-
|
|
13197
|
+
const { getRunLogPath } = await import("../specialist-logs-GFKUXCFG.js");
|
|
13198
|
+
const { getProjectSpecialistMetadata } = await import("../specialists-XMFCFGYQ.js");
|
|
13246
13199
|
const metadata = getProjectSpecialistMetadata(project2, type);
|
|
13247
13200
|
if (!metadata.currentRun) {
|
|
13248
13201
|
console.error(`\u274C No active run for ${project2}/${type}`);
|
|
13249
13202
|
process.exit(1);
|
|
13250
13203
|
}
|
|
13251
13204
|
const logPath = getRunLogPath(project2, type, metadata.currentRun);
|
|
13252
|
-
if (!
|
|
13205
|
+
if (!existsSync44(logPath)) {
|
|
13253
13206
|
console.error(`\u274C Log file not found: ${logPath}`);
|
|
13254
13207
|
process.exit(1);
|
|
13255
13208
|
}
|
|
@@ -13311,7 +13264,7 @@ async function cleanupLogsCommand(projectOrAll, type, options) {
|
|
|
13311
13264
|
console.log(" Use --force to confirm.");
|
|
13312
13265
|
process.exit(1);
|
|
13313
13266
|
}
|
|
13314
|
-
const { cleanupAllLogs } = await import("../specialist-logs-
|
|
13267
|
+
const { cleanupAllLogs } = await import("../specialist-logs-GFKUXCFG.js");
|
|
13315
13268
|
console.log("\u{1F9F9} Cleaning up old logs for all projects...\n");
|
|
13316
13269
|
const results = cleanupAllLogs();
|
|
13317
13270
|
console.log(`
|
|
@@ -13338,7 +13291,7 @@ async function cleanupLogsCommand(projectOrAll, type, options) {
|
|
|
13338
13291
|
console.log(" Use --force to confirm.");
|
|
13339
13292
|
process.exit(1);
|
|
13340
13293
|
}
|
|
13341
|
-
const { cleanupOldLogs } = await import("../specialist-logs-
|
|
13294
|
+
const { cleanupOldLogs } = await import("../specialist-logs-GFKUXCFG.js");
|
|
13342
13295
|
const { getSpecialistRetention } = await import("../projects-3CRF57ZU.js");
|
|
13343
13296
|
const retention = getSpecialistRetention(projectOrAll);
|
|
13344
13297
|
console.log(`\u{1F9F9} Cleaning up old logs for ${projectOrAll}/${type}...`);
|
|
@@ -13377,9 +13330,9 @@ import ora19 from "ora";
|
|
|
13377
13330
|
// src/lib/convoy.ts
|
|
13378
13331
|
init_esm_shims();
|
|
13379
13332
|
init_tmux();
|
|
13380
|
-
import { existsSync as
|
|
13381
|
-
import { join as
|
|
13382
|
-
import { homedir as
|
|
13333
|
+
import { existsSync as existsSync45, mkdirSync as mkdirSync22, writeFileSync as writeFileSync24, readFileSync as readFileSync39, readdirSync as readdirSync19 } from "fs";
|
|
13334
|
+
import { join as join43 } from "path";
|
|
13335
|
+
import { homedir as homedir20 } from "os";
|
|
13383
13336
|
import { exec as exec16 } from "child_process";
|
|
13384
13337
|
import { promisify as promisify16 } from "util";
|
|
13385
13338
|
import { parse as parseYaml } from "yaml";
|
|
@@ -13487,25 +13440,25 @@ function getExecutionOrder(template) {
|
|
|
13487
13440
|
init_paths();
|
|
13488
13441
|
init_work_type_router();
|
|
13489
13442
|
var execAsync16 = promisify16(exec16);
|
|
13490
|
-
var CONVOY_DIR =
|
|
13443
|
+
var CONVOY_DIR = join43(homedir20(), ".panopticon", "convoys");
|
|
13491
13444
|
function getConvoyStateFile(convoyId) {
|
|
13492
|
-
return
|
|
13445
|
+
return join43(CONVOY_DIR, `${convoyId}.json`);
|
|
13493
13446
|
}
|
|
13494
13447
|
function getConvoyOutputDir(convoyId, template) {
|
|
13495
13448
|
const baseDir = template.config?.outputDir || ".panopticon/convoy-output";
|
|
13496
|
-
return
|
|
13449
|
+
return join43(process.cwd(), baseDir, convoyId);
|
|
13497
13450
|
}
|
|
13498
13451
|
function saveConvoyState(state) {
|
|
13499
13452
|
mkdirSync22(CONVOY_DIR, { recursive: true });
|
|
13500
|
-
|
|
13453
|
+
writeFileSync24(getConvoyStateFile(state.id), JSON.stringify(state, null, 2));
|
|
13501
13454
|
}
|
|
13502
13455
|
function loadConvoyState(convoyId) {
|
|
13503
13456
|
const stateFile = getConvoyStateFile(convoyId);
|
|
13504
|
-
if (!
|
|
13457
|
+
if (!existsSync45(stateFile)) {
|
|
13505
13458
|
return void 0;
|
|
13506
13459
|
}
|
|
13507
13460
|
try {
|
|
13508
|
-
const content =
|
|
13461
|
+
const content = readFileSync39(stateFile, "utf-8");
|
|
13509
13462
|
return JSON.parse(content);
|
|
13510
13463
|
} catch {
|
|
13511
13464
|
return void 0;
|
|
@@ -13515,7 +13468,7 @@ function getConvoyStatus(convoyId) {
|
|
|
13515
13468
|
return loadConvoyState(convoyId);
|
|
13516
13469
|
}
|
|
13517
13470
|
function listConvoys(filter) {
|
|
13518
|
-
if (!
|
|
13471
|
+
if (!existsSync45(CONVOY_DIR)) {
|
|
13519
13472
|
return [];
|
|
13520
13473
|
}
|
|
13521
13474
|
const files = readdirSync19(CONVOY_DIR).filter((f) => f.endsWith(".json"));
|
|
@@ -13534,10 +13487,10 @@ function listConvoys(filter) {
|
|
|
13534
13487
|
);
|
|
13535
13488
|
}
|
|
13536
13489
|
function parseAgentTemplate(templatePath) {
|
|
13537
|
-
if (!
|
|
13490
|
+
if (!existsSync45(templatePath)) {
|
|
13538
13491
|
throw new Error(`Agent template not found: ${templatePath}`);
|
|
13539
13492
|
}
|
|
13540
|
-
const content =
|
|
13493
|
+
const content = readFileSync39(templatePath, "utf-8");
|
|
13541
13494
|
const frontmatterMatch = content.match(/^---\n([\s\S]+?)\n---\n([\s\S]*)$/);
|
|
13542
13495
|
if (!frontmatterMatch) {
|
|
13543
13496
|
throw new Error(`Invalid agent template format (missing frontmatter): ${templatePath}`);
|
|
@@ -13563,7 +13516,7 @@ function mapConvoyRoleToWorkType(role) {
|
|
|
13563
13516
|
}
|
|
13564
13517
|
async function spawnConvoyAgent(convoy, agent, agentState, context) {
|
|
13565
13518
|
const { role, subagent } = agent;
|
|
13566
|
-
const templatePath =
|
|
13519
|
+
const templatePath = join43(AGENTS_DIR, `${subagent}.md`);
|
|
13567
13520
|
const template = parseAgentTemplate(templatePath);
|
|
13568
13521
|
let model = template.model;
|
|
13569
13522
|
try {
|
|
@@ -13602,8 +13555,8 @@ ${context.issueId ? `**Issue ID**: ${context.issueId}` : ""}
|
|
|
13602
13555
|
`;
|
|
13603
13556
|
prompt = contextInstructions + prompt;
|
|
13604
13557
|
mkdirSync22(convoy.outputDir, { recursive: true });
|
|
13605
|
-
const promptFile =
|
|
13606
|
-
|
|
13558
|
+
const promptFile = join43(convoy.outputDir, `${role}-prompt.md`);
|
|
13559
|
+
writeFileSync24(promptFile, prompt);
|
|
13607
13560
|
const claudeCmd = `claude --dangerously-skip-permissions --model ${model}`;
|
|
13608
13561
|
createSession(agentState.tmuxSession, convoy.context.projectPath, claudeCmd, {
|
|
13609
13562
|
env: {
|
|
@@ -13641,7 +13594,7 @@ async function startConvoy(templateName, context) {
|
|
|
13641
13594
|
};
|
|
13642
13595
|
for (const agent of template.agents) {
|
|
13643
13596
|
const tmuxSession = `${convoyId}-${agent.role}`;
|
|
13644
|
-
const outputFile =
|
|
13597
|
+
const outputFile = join43(outputDir, `${agent.role}.md`);
|
|
13645
13598
|
state.agents.push({
|
|
13646
13599
|
role: agent.role,
|
|
13647
13600
|
subagent: agent.subagent,
|
|
@@ -13676,8 +13629,8 @@ async function executePhase(convoy, template, phaseAgents, context) {
|
|
|
13676
13629
|
const agentContext = { ...context };
|
|
13677
13630
|
for (const depRole of deps) {
|
|
13678
13631
|
const depAgent = convoy.agents.find((a) => a.role === depRole);
|
|
13679
|
-
if (depAgent?.outputFile &&
|
|
13680
|
-
agentContext[`${depRole}_output`] =
|
|
13632
|
+
if (depAgent?.outputFile && existsSync45(depAgent.outputFile)) {
|
|
13633
|
+
agentContext[`${depRole}_output`] = readFileSync39(depAgent.outputFile, "utf-8");
|
|
13681
13634
|
}
|
|
13682
13635
|
}
|
|
13683
13636
|
spawnPromises.push(spawnConvoyAgent(convoy, agent, agentState, agentContext));
|
|
@@ -13740,7 +13693,7 @@ function updateAgentStatuses(convoy) {
|
|
|
13740
13693
|
agent.status = "completed";
|
|
13741
13694
|
agent.completedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
13742
13695
|
updated = true;
|
|
13743
|
-
if (agent.outputFile &&
|
|
13696
|
+
if (agent.outputFile && existsSync45(agent.outputFile)) {
|
|
13744
13697
|
agent.exitCode = 0;
|
|
13745
13698
|
} else {
|
|
13746
13699
|
agent.exitCode = 1;
|
|
@@ -13986,30 +13939,30 @@ function registerConvoyCommands(program2) {
|
|
|
13986
13939
|
init_esm_shims();
|
|
13987
13940
|
init_projects();
|
|
13988
13941
|
import chalk50 from "chalk";
|
|
13989
|
-
import { existsSync as
|
|
13990
|
-
import { join as
|
|
13942
|
+
import { existsSync as existsSync46, readFileSync as readFileSync40, symlinkSync as symlinkSync2, mkdirSync as mkdirSync23, readdirSync as readdirSync20, statSync as statSync10 } from "fs";
|
|
13943
|
+
import { join as join44, resolve as resolve2, dirname as dirname13 } from "path";
|
|
13991
13944
|
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
13992
13945
|
var __filename5 = fileURLToPath4(import.meta.url);
|
|
13993
13946
|
var __dirname5 = dirname13(__filename5);
|
|
13994
|
-
var BUNDLED_HOOKS_DIR =
|
|
13947
|
+
var BUNDLED_HOOKS_DIR = join44(__dirname5, "..", "..", "scripts", "git-hooks");
|
|
13995
13948
|
function installGitHooks(gitDir) {
|
|
13996
|
-
const hooksTarget =
|
|
13949
|
+
const hooksTarget = join44(gitDir, "hooks");
|
|
13997
13950
|
let installed = 0;
|
|
13998
|
-
if (!
|
|
13951
|
+
if (!existsSync46(hooksTarget)) {
|
|
13999
13952
|
mkdirSync23(hooksTarget, { recursive: true });
|
|
14000
13953
|
}
|
|
14001
|
-
if (!
|
|
13954
|
+
if (!existsSync46(BUNDLED_HOOKS_DIR)) {
|
|
14002
13955
|
return 0;
|
|
14003
13956
|
}
|
|
14004
13957
|
try {
|
|
14005
13958
|
const hooks = readdirSync20(BUNDLED_HOOKS_DIR).filter((f) => {
|
|
14006
|
-
const p =
|
|
14007
|
-
return
|
|
13959
|
+
const p = join44(BUNDLED_HOOKS_DIR, f);
|
|
13960
|
+
return existsSync46(p) && statSync10(p).isFile();
|
|
14008
13961
|
});
|
|
14009
13962
|
for (const hook of hooks) {
|
|
14010
|
-
const source =
|
|
14011
|
-
const target =
|
|
14012
|
-
if (
|
|
13963
|
+
const source = join44(BUNDLED_HOOKS_DIR, hook);
|
|
13964
|
+
const target = join44(hooksTarget, hook);
|
|
13965
|
+
if (existsSync46(target)) {
|
|
14013
13966
|
try {
|
|
14014
13967
|
const { readlinkSync: readlinkSync2 } = __require("fs");
|
|
14015
13968
|
if (readlinkSync2(target) === source) {
|
|
@@ -14018,7 +13971,7 @@ function installGitHooks(gitDir) {
|
|
|
14018
13971
|
} catch {
|
|
14019
13972
|
}
|
|
14020
13973
|
}
|
|
14021
|
-
if (
|
|
13974
|
+
if (existsSync46(target)) {
|
|
14022
13975
|
const { renameSync: renameSync4 } = __require("fs");
|
|
14023
13976
|
renameSync4(target, `${target}.backup`);
|
|
14024
13977
|
}
|
|
@@ -14031,7 +13984,7 @@ function installGitHooks(gitDir) {
|
|
|
14031
13984
|
}
|
|
14032
13985
|
async function projectAddCommand(projectPath, options = {}) {
|
|
14033
13986
|
const fullPath = resolve2(projectPath);
|
|
14034
|
-
if (!
|
|
13987
|
+
if (!existsSync46(fullPath)) {
|
|
14035
13988
|
console.log(chalk50.red(`Path does not exist: ${fullPath}`));
|
|
14036
13989
|
return;
|
|
14037
13990
|
}
|
|
@@ -14046,9 +13999,9 @@ async function projectAddCommand(projectPath, options = {}) {
|
|
|
14046
13999
|
}
|
|
14047
14000
|
let linearTeam = options.linearTeam;
|
|
14048
14001
|
if (!linearTeam) {
|
|
14049
|
-
const projectToml =
|
|
14050
|
-
if (
|
|
14051
|
-
const content =
|
|
14002
|
+
const projectToml = join44(fullPath, ".panopticon", "project.toml");
|
|
14003
|
+
if (existsSync46(projectToml)) {
|
|
14004
|
+
const content = readFileSync40(projectToml, "utf-8");
|
|
14052
14005
|
const match = content.match(/team\s*=\s*"([^"]+)"/);
|
|
14053
14006
|
if (match) linearTeam = match[1];
|
|
14054
14007
|
}
|
|
@@ -14074,19 +14027,19 @@ async function projectAddCommand(projectPath, options = {}) {
|
|
|
14074
14027
|
console.log(chalk50.dim(` Rally project: ${options.rallyProject}`));
|
|
14075
14028
|
}
|
|
14076
14029
|
console.log("");
|
|
14077
|
-
const hasDevcontainer =
|
|
14078
|
-
const hasInfra =
|
|
14079
|
-
const hasDevcontainerTemplate =
|
|
14080
|
-
const hasRootGit =
|
|
14030
|
+
const hasDevcontainer = existsSync46(join44(fullPath, ".devcontainer"));
|
|
14031
|
+
const hasInfra = existsSync46(join44(fullPath, "infra"));
|
|
14032
|
+
const hasDevcontainerTemplate = existsSync46(join44(fullPath, "infra", ".devcontainer-template")) || existsSync46(join44(fullPath, ".devcontainer-template"));
|
|
14033
|
+
const hasRootGit = existsSync46(join44(fullPath, ".git"));
|
|
14081
14034
|
const subRepos = [];
|
|
14082
14035
|
if (!hasRootGit) {
|
|
14083
14036
|
const { readdirSync: readdirSync22, statSync: statSync12 } = await import("fs");
|
|
14084
14037
|
try {
|
|
14085
14038
|
const entries = readdirSync22(fullPath);
|
|
14086
14039
|
for (const entry of entries) {
|
|
14087
|
-
const entryPath =
|
|
14040
|
+
const entryPath = join44(fullPath, entry);
|
|
14088
14041
|
try {
|
|
14089
|
-
if (statSync12(entryPath).isDirectory() &&
|
|
14042
|
+
if (statSync12(entryPath).isDirectory() && existsSync46(join44(entryPath, ".git"))) {
|
|
14090
14043
|
subRepos.push(entry);
|
|
14091
14044
|
}
|
|
14092
14045
|
} catch {
|
|
@@ -14103,13 +14056,13 @@ async function projectAddCommand(projectPath, options = {}) {
|
|
|
14103
14056
|
}
|
|
14104
14057
|
let hooksInstalled = 0;
|
|
14105
14058
|
if (hasRootGit) {
|
|
14106
|
-
hooksInstalled = installGitHooks(
|
|
14059
|
+
hooksInstalled = installGitHooks(join44(fullPath, ".git"));
|
|
14107
14060
|
if (hooksInstalled > 0) {
|
|
14108
14061
|
console.log(chalk50.green(`\u2713 Installed ${hooksInstalled} git hook(s) for branch protection`));
|
|
14109
14062
|
}
|
|
14110
14063
|
} else if (isPolyrepo) {
|
|
14111
14064
|
for (const repo of subRepos) {
|
|
14112
|
-
const count = installGitHooks(
|
|
14065
|
+
const count = installGitHooks(join44(fullPath, repo, ".git"));
|
|
14113
14066
|
hooksInstalled += count;
|
|
14114
14067
|
}
|
|
14115
14068
|
if (hooksInstalled > 0) {
|
|
@@ -14181,7 +14134,7 @@ async function projectListCommand(options = {}) {
|
|
|
14181
14134
|
}
|
|
14182
14135
|
console.log(chalk50.bold("\nRegistered Projects:\n"));
|
|
14183
14136
|
for (const { key, config: config2 } of projects) {
|
|
14184
|
-
const exists =
|
|
14137
|
+
const exists = existsSync46(config2.path);
|
|
14185
14138
|
const statusIcon = exists ? chalk50.green("\u2713") : chalk50.red("\u2717");
|
|
14186
14139
|
console.log(`${statusIcon} ${chalk50.bold(config2.name)} ${chalk50.dim(`(${key})`)}`);
|
|
14187
14140
|
console.log(` ${chalk50.dim(config2.path)}`);
|
|
@@ -14215,7 +14168,7 @@ async function projectRemoveCommand(nameOrPath) {
|
|
|
14215
14168
|
console.log(chalk50.dim(`Use 'pan project list' to see registered projects.`));
|
|
14216
14169
|
}
|
|
14217
14170
|
async function projectInitCommand() {
|
|
14218
|
-
if (
|
|
14171
|
+
if (existsSync46(PROJECTS_CONFIG_FILE)) {
|
|
14219
14172
|
console.log(chalk50.yellow(`Config already exists: ${PROJECTS_CONFIG_FILE}`));
|
|
14220
14173
|
return;
|
|
14221
14174
|
}
|
|
@@ -14249,7 +14202,7 @@ async function projectShowCommand(keyOrName) {
|
|
|
14249
14202
|
console.log(chalk50.dim(`Use 'pan project list' to see registered projects.`));
|
|
14250
14203
|
process.exit(1);
|
|
14251
14204
|
}
|
|
14252
|
-
const pathExists =
|
|
14205
|
+
const pathExists = existsSync46(found.path);
|
|
14253
14206
|
const pathStatus = pathExists ? chalk50.green("\u2713") : chalk50.red("\u2717");
|
|
14254
14207
|
console.log(chalk50.bold(`
|
|
14255
14208
|
Project: ${foundKey}
|
|
@@ -14281,10 +14234,10 @@ Project: ${foundKey}
|
|
|
14281
14234
|
init_esm_shims();
|
|
14282
14235
|
init_paths();
|
|
14283
14236
|
import chalk51 from "chalk";
|
|
14284
|
-
import { existsSync as
|
|
14237
|
+
import { existsSync as existsSync47, readdirSync as readdirSync21, readFileSync as readFileSync41 } from "fs";
|
|
14285
14238
|
import { execSync as execSync6 } from "child_process";
|
|
14286
|
-
import { homedir as
|
|
14287
|
-
import { join as
|
|
14239
|
+
import { homedir as homedir21 } from "os";
|
|
14240
|
+
import { join as join45 } from "path";
|
|
14288
14241
|
function checkCommand3(cmd) {
|
|
14289
14242
|
try {
|
|
14290
14243
|
execSync6(`which ${cmd}`, { encoding: "utf-8", stdio: "pipe" });
|
|
@@ -14294,10 +14247,10 @@ function checkCommand3(cmd) {
|
|
|
14294
14247
|
}
|
|
14295
14248
|
}
|
|
14296
14249
|
function checkDirectory(path) {
|
|
14297
|
-
return
|
|
14250
|
+
return existsSync47(path);
|
|
14298
14251
|
}
|
|
14299
14252
|
function countItems(path) {
|
|
14300
|
-
if (!
|
|
14253
|
+
if (!existsSync47(path)) return 0;
|
|
14301
14254
|
try {
|
|
14302
14255
|
return readdirSync21(path).length;
|
|
14303
14256
|
} catch {
|
|
@@ -14348,8 +14301,8 @@ async function doctorCommand() {
|
|
|
14348
14301
|
}
|
|
14349
14302
|
}
|
|
14350
14303
|
if (checkDirectory(CLAUDE_DIR)) {
|
|
14351
|
-
const skillsCount = countItems(
|
|
14352
|
-
const commandsCount = countItems(
|
|
14304
|
+
const skillsCount = countItems(join45(CLAUDE_DIR, "skills"));
|
|
14305
|
+
const commandsCount = countItems(join45(CLAUDE_DIR, "commands"));
|
|
14353
14306
|
checks.push({
|
|
14354
14307
|
name: "Claude Code Skills",
|
|
14355
14308
|
status: skillsCount > 0 ? "ok" : "warn",
|
|
@@ -14370,8 +14323,8 @@ async function doctorCommand() {
|
|
|
14370
14323
|
fix: "Install Claude Code first"
|
|
14371
14324
|
});
|
|
14372
14325
|
}
|
|
14373
|
-
const envFile =
|
|
14374
|
-
if (
|
|
14326
|
+
const envFile = join45(homedir21(), ".panopticon.env");
|
|
14327
|
+
if (existsSync47(envFile)) {
|
|
14375
14328
|
checks.push({ name: "Config File", status: "ok", message: "~/.panopticon.env exists" });
|
|
14376
14329
|
} else {
|
|
14377
14330
|
checks.push({
|
|
@@ -14383,8 +14336,8 @@ async function doctorCommand() {
|
|
|
14383
14336
|
}
|
|
14384
14337
|
if (process.env.LINEAR_API_KEY) {
|
|
14385
14338
|
checks.push({ name: "LINEAR_API_KEY", status: "ok", message: "Set in environment" });
|
|
14386
|
-
} else if (
|
|
14387
|
-
const content =
|
|
14339
|
+
} else if (existsSync47(envFile)) {
|
|
14340
|
+
const content = readFileSync41(envFile, "utf-8");
|
|
14388
14341
|
if (content.includes("LINEAR_API_KEY")) {
|
|
14389
14342
|
checks.push({ name: "LINEAR_API_KEY", status: "ok", message: "Set in config file" });
|
|
14390
14343
|
} else {
|
|
@@ -14452,15 +14405,15 @@ init_esm_shims();
|
|
|
14452
14405
|
init_config();
|
|
14453
14406
|
import { execSync as execSync7 } from "child_process";
|
|
14454
14407
|
import chalk52 from "chalk";
|
|
14455
|
-
import { readFileSync as
|
|
14408
|
+
import { readFileSync as readFileSync42 } from "fs";
|
|
14456
14409
|
import { fileURLToPath as fileURLToPath5 } from "url";
|
|
14457
|
-
import { dirname as dirname14, join as
|
|
14410
|
+
import { dirname as dirname14, join as join46 } from "path";
|
|
14458
14411
|
function getCurrentVersion() {
|
|
14459
14412
|
try {
|
|
14460
14413
|
const __filename6 = fileURLToPath5(import.meta.url);
|
|
14461
14414
|
const __dirname6 = dirname14(__filename6);
|
|
14462
|
-
const pkgPath =
|
|
14463
|
-
const pkg = JSON.parse(
|
|
14415
|
+
const pkgPath = join46(__dirname6, "..", "..", "..", "package.json");
|
|
14416
|
+
const pkg = JSON.parse(readFileSync42(pkgPath, "utf-8"));
|
|
14464
14417
|
return pkg.version;
|
|
14465
14418
|
} catch {
|
|
14466
14419
|
return "unknown";
|
|
@@ -14546,8 +14499,8 @@ init_esm_shims();
|
|
|
14546
14499
|
init_projects();
|
|
14547
14500
|
import chalk53 from "chalk";
|
|
14548
14501
|
import ora21 from "ora";
|
|
14549
|
-
import { existsSync as
|
|
14550
|
-
import { join as
|
|
14502
|
+
import { existsSync as existsSync48, readFileSync as readFileSync43, writeFileSync as writeFileSync25, mkdirSync as mkdirSync24, statSync as statSync11 } from "fs";
|
|
14503
|
+
import { join as join47, dirname as dirname15 } from "path";
|
|
14551
14504
|
import { exec as exec17 } from "child_process";
|
|
14552
14505
|
import { promisify as promisify17 } from "util";
|
|
14553
14506
|
var execAsync17 = promisify17(exec17);
|
|
@@ -14609,9 +14562,9 @@ async function snapshotCommand(options) {
|
|
|
14609
14562
|
`));
|
|
14610
14563
|
return;
|
|
14611
14564
|
}
|
|
14612
|
-
const outputPath = options.output || dbConfig.seed_file ||
|
|
14565
|
+
const outputPath = options.output || dbConfig.seed_file || join47(projectConfig.path, "infra", "seed", "seed.sql");
|
|
14613
14566
|
const outputDir = dirname15(outputPath);
|
|
14614
|
-
if (!
|
|
14567
|
+
if (!existsSync48(outputDir)) {
|
|
14615
14568
|
mkdirSync24(outputDir, { recursive: true });
|
|
14616
14569
|
}
|
|
14617
14570
|
spinner.text = "Running snapshot command...";
|
|
@@ -14634,8 +14587,8 @@ async function snapshotCommand(options) {
|
|
|
14634
14587
|
try {
|
|
14635
14588
|
await execAsync17(fullCmd, { timeout: 3e5 });
|
|
14636
14589
|
} catch (error) {
|
|
14637
|
-
if (
|
|
14638
|
-
const content2 =
|
|
14590
|
+
if (existsSync48(outputPath)) {
|
|
14591
|
+
const content2 = readFileSync43(outputPath, "utf-8");
|
|
14639
14592
|
if (content2.includes("PostgreSQL database dump")) {
|
|
14640
14593
|
spinner.warn("Snapshot completed with warnings (stderr captured)");
|
|
14641
14594
|
console.log(chalk53.dim(" Run `pan db clean` to remove stderr noise from the file"));
|
|
@@ -14648,7 +14601,7 @@ async function snapshotCommand(options) {
|
|
|
14648
14601
|
return;
|
|
14649
14602
|
}
|
|
14650
14603
|
}
|
|
14651
|
-
const content =
|
|
14604
|
+
const content = readFileSync43(outputPath, "utf-8");
|
|
14652
14605
|
if (content.includes("Defaulted container") || content.includes("Unable to use a TTY")) {
|
|
14653
14606
|
spinner.text = "Cleaning kubectl output from snapshot...";
|
|
14654
14607
|
await cleanFile(outputPath);
|
|
@@ -14680,14 +14633,14 @@ async function seedCommand(workspaceOrIssue, options) {
|
|
|
14680
14633
|
spinner.fail("Could not find project workspace configuration");
|
|
14681
14634
|
return;
|
|
14682
14635
|
}
|
|
14683
|
-
const workspacePath =
|
|
14684
|
-
if (!
|
|
14636
|
+
const workspacePath = join47(projectConfig.path, projectConfig.workspace.workspaces_dir || "workspaces", folderName);
|
|
14637
|
+
if (!existsSync48(workspacePath)) {
|
|
14685
14638
|
spinner.fail(`Workspace not found: ${workspacePath}`);
|
|
14686
14639
|
return;
|
|
14687
14640
|
}
|
|
14688
14641
|
const dbConfig = projectConfig.workspace.database;
|
|
14689
14642
|
const seedFile = options.file || dbConfig?.seed_file;
|
|
14690
|
-
if (!seedFile || !
|
|
14643
|
+
if (!seedFile || !existsSync48(seedFile)) {
|
|
14691
14644
|
spinner.fail(`Seed file not found: ${seedFile || "(not configured)"}`);
|
|
14692
14645
|
console.log(chalk53.dim("\nConfigure seed_file in projects.yaml or use --file"));
|
|
14693
14646
|
return;
|
|
@@ -14829,11 +14782,11 @@ async function statusCommand5(workspaceOrIssue) {
|
|
|
14829
14782
|
async function cleanCommand(file, options) {
|
|
14830
14783
|
const spinner = ora21("Cleaning database dump file...").start();
|
|
14831
14784
|
try {
|
|
14832
|
-
if (!
|
|
14785
|
+
if (!existsSync48(file)) {
|
|
14833
14786
|
spinner.fail(`File not found: ${file}`);
|
|
14834
14787
|
return;
|
|
14835
14788
|
}
|
|
14836
|
-
const content =
|
|
14789
|
+
const content = readFileSync43(file, "utf-8");
|
|
14837
14790
|
const lines = content.split("\n");
|
|
14838
14791
|
const patternsToRemove = [
|
|
14839
14792
|
/^Defaulted container/,
|
|
@@ -14893,7 +14846,7 @@ async function cleanCommand(file, options) {
|
|
|
14893
14846
|
return;
|
|
14894
14847
|
}
|
|
14895
14848
|
const outputPath = options.output || file;
|
|
14896
|
-
|
|
14849
|
+
writeFileSync25(outputPath, cleanedContent);
|
|
14897
14850
|
spinner.succeed(`Cleaned ${removedLines} lines`);
|
|
14898
14851
|
console.log(chalk53.dim(` Output: ${outputPath}`));
|
|
14899
14852
|
console.log(chalk53.dim(` Original: ${lines.length} lines`));
|
|
@@ -14903,7 +14856,7 @@ async function cleanCommand(file, options) {
|
|
|
14903
14856
|
}
|
|
14904
14857
|
}
|
|
14905
14858
|
async function cleanFile(filePath) {
|
|
14906
|
-
const content =
|
|
14859
|
+
const content = readFileSync43(filePath, "utf-8");
|
|
14907
14860
|
const lines = content.split("\n");
|
|
14908
14861
|
let startIndex = 0;
|
|
14909
14862
|
for (let i = 0; i < lines.length; i++) {
|
|
@@ -14923,7 +14876,7 @@ async function cleanFile(filePath) {
|
|
|
14923
14876
|
/^error: timed out waiting/
|
|
14924
14877
|
];
|
|
14925
14878
|
const cleanedLines = lines.slice(startIndex).filter((line) => !patternsToRemove.some((p) => p.test(line)));
|
|
14926
|
-
|
|
14879
|
+
writeFileSync25(filePath, cleanedLines.join("\n"));
|
|
14927
14880
|
}
|
|
14928
14881
|
async function configCommand(project2) {
|
|
14929
14882
|
const projects = loadFullProjects();
|
|
@@ -14957,7 +14910,7 @@ async function configCommand(project2) {
|
|
|
14957
14910
|
return;
|
|
14958
14911
|
}
|
|
14959
14912
|
if (dbConfig.seed_file) {
|
|
14960
|
-
const exists =
|
|
14913
|
+
const exists = existsSync48(dbConfig.seed_file);
|
|
14961
14914
|
console.log(` Seed file: ${dbConfig.seed_file}`);
|
|
14962
14915
|
console.log(chalk53.dim(` Status: ${exists ? chalk53.green("exists") : chalk53.red("not found")}`));
|
|
14963
14916
|
if (exists) {
|
|
@@ -14986,8 +14939,8 @@ async function configCommand(project2) {
|
|
|
14986
14939
|
init_esm_shims();
|
|
14987
14940
|
import chalk54 from "chalk";
|
|
14988
14941
|
import ora22 from "ora";
|
|
14989
|
-
import { existsSync as
|
|
14990
|
-
import { join as
|
|
14942
|
+
import { existsSync as existsSync49, readFileSync as readFileSync44 } from "fs";
|
|
14943
|
+
import { join as join48 } from "path";
|
|
14991
14944
|
import { exec as exec18, execSync as execSync8 } from "child_process";
|
|
14992
14945
|
import { promisify as promisify18 } from "util";
|
|
14993
14946
|
import { platform } from "os";
|
|
@@ -14996,7 +14949,7 @@ function detectPlatform2() {
|
|
|
14996
14949
|
const os = platform();
|
|
14997
14950
|
if (os === "linux") {
|
|
14998
14951
|
try {
|
|
14999
|
-
const release =
|
|
14952
|
+
const release = readFileSync44("/proc/version", "utf8").toLowerCase();
|
|
15000
14953
|
if (release.includes("microsoft") || release.includes("wsl")) {
|
|
15001
14954
|
return "wsl";
|
|
15002
14955
|
}
|
|
@@ -15034,8 +14987,8 @@ async function compactCommand(options) {
|
|
|
15034
14987
|
console.log(chalk54.dim("Install beads: https://github.com/steveyegge/beads"));
|
|
15035
14988
|
process.exit(1);
|
|
15036
14989
|
}
|
|
15037
|
-
const beadsDir =
|
|
15038
|
-
if (!
|
|
14990
|
+
const beadsDir = join48(cwd, ".beads");
|
|
14991
|
+
if (!existsSync49(beadsDir)) {
|
|
15039
14992
|
console.error(chalk54.red("Error: No .beads directory found in current directory"));
|
|
15040
14993
|
console.log(chalk54.dim("Run bd init to initialize beads"));
|
|
15041
14994
|
process.exit(1);
|
|
@@ -15094,8 +15047,8 @@ async function statsCommand() {
|
|
|
15094
15047
|
console.error(chalk54.red("Error: bd (beads) CLI not found"));
|
|
15095
15048
|
process.exit(1);
|
|
15096
15049
|
}
|
|
15097
|
-
const beadsDir =
|
|
15098
|
-
if (!
|
|
15050
|
+
const beadsDir = join48(cwd, ".beads");
|
|
15051
|
+
if (!existsSync49(beadsDir)) {
|
|
15099
15052
|
console.error(chalk54.red("Error: No .beads directory found"));
|
|
15100
15053
|
process.exit(1);
|
|
15101
15054
|
}
|
|
@@ -15739,9 +15692,9 @@ import chalk60 from "chalk";
|
|
|
15739
15692
|
|
|
15740
15693
|
// src/lib/env-loader.ts
|
|
15741
15694
|
init_esm_shims();
|
|
15742
|
-
import { join as
|
|
15743
|
-
import { homedir as
|
|
15744
|
-
var ENV_FILE_PATH =
|
|
15695
|
+
import { join as join49 } from "path";
|
|
15696
|
+
import { homedir as homedir22 } from "os";
|
|
15697
|
+
var ENV_FILE_PATH = join49(homedir22(), ".panopticon.env");
|
|
15745
15698
|
function getShadowModeFromEnv() {
|
|
15746
15699
|
const value = process.env.SHADOW_MODE;
|
|
15747
15700
|
if (!value) return false;
|
|
@@ -15844,9 +15797,9 @@ import chalk61 from "chalk";
|
|
|
15844
15797
|
// src/lib/costs/sync-wal.ts
|
|
15845
15798
|
init_esm_shims();
|
|
15846
15799
|
init_projects();
|
|
15847
|
-
import { existsSync as
|
|
15800
|
+
import { existsSync as existsSync50 } from "fs";
|
|
15848
15801
|
import { readdir, readFile } from "fs/promises";
|
|
15849
|
-
import { join as
|
|
15802
|
+
import { join as join50 } from "path";
|
|
15850
15803
|
|
|
15851
15804
|
// src/lib/database/cost-events-db.ts
|
|
15852
15805
|
init_esm_shims();
|
|
@@ -15911,8 +15864,8 @@ async function syncWalFromAllProjects() {
|
|
|
15911
15864
|
for (const { key, config: config2 } of projects) {
|
|
15912
15865
|
const repoPath = config2.events_repo ?? config2.path;
|
|
15913
15866
|
const eventsSubdir = config2.events_path ?? DEFAULT_EVENTS_SUBDIR;
|
|
15914
|
-
const eventsDir =
|
|
15915
|
-
if (!
|
|
15867
|
+
const eventsDir = join50(repoPath, eventsSubdir);
|
|
15868
|
+
if (!existsSync50(eventsDir)) continue;
|
|
15916
15869
|
const projectStats = { imported: 0, duplicates: 0, files: 0 };
|
|
15917
15870
|
let files;
|
|
15918
15871
|
try {
|
|
@@ -15922,7 +15875,7 @@ async function syncWalFromAllProjects() {
|
|
|
15922
15875
|
continue;
|
|
15923
15876
|
}
|
|
15924
15877
|
for (const file of files) {
|
|
15925
|
-
const filePath =
|
|
15878
|
+
const filePath = join50(eventsDir, file);
|
|
15926
15879
|
const events = await parseWalFile(filePath, result.errors);
|
|
15927
15880
|
if (events.length === 0) continue;
|
|
15928
15881
|
try {
|
|
@@ -16249,10 +16202,10 @@ function createCostCommand() {
|
|
|
16249
16202
|
}
|
|
16250
16203
|
|
|
16251
16204
|
// src/cli/index.ts
|
|
16252
|
-
var PANOPTICON_ENV_FILE =
|
|
16253
|
-
if (
|
|
16205
|
+
var PANOPTICON_ENV_FILE = join51(homedir23(), ".panopticon.env");
|
|
16206
|
+
if (existsSync51(PANOPTICON_ENV_FILE)) {
|
|
16254
16207
|
try {
|
|
16255
|
-
const envContent =
|
|
16208
|
+
const envContent = readFileSync45(PANOPTICON_ENV_FILE, "utf-8");
|
|
16256
16209
|
for (const line of envContent.split("\n")) {
|
|
16257
16210
|
const trimmed = line.trim();
|
|
16258
16211
|
if (!trimmed || trimmed.startsWith("#")) continue;
|
|
@@ -16269,7 +16222,7 @@ if (existsSync52(PANOPTICON_ENV_FILE)) {
|
|
|
16269
16222
|
}
|
|
16270
16223
|
}
|
|
16271
16224
|
var program = new Command2();
|
|
16272
|
-
program.name("pan").description("Multi-agent orchestration for AI coding assistants").version(JSON.parse(
|
|
16225
|
+
program.name("pan").description("Multi-agent orchestration for AI coding assistants").version(JSON.parse(readFileSync45(join51(import.meta.dirname, "../../package.json"), "utf-8")).version);
|
|
16273
16226
|
program.command("init").description("Initialize Panopticon (~/.panopticon/)").action(initCommand);
|
|
16274
16227
|
program.command("sync").description("Sync skills/agents/rules to devroot").option("--dry-run", "Show what would be synced").option("--force", "Overwrite files modified since Panopticon installed them").option("--diff", "Show diff for modified files").option("--backup-only", "Only create backup").action(syncCommand);
|
|
16275
16228
|
program.command("restore [timestamp]").description("Restore from backup").action(restoreCommand);
|
|
@@ -16293,21 +16246,21 @@ program.command("migrate-config").description("Migrate from settings.json to con
|
|
|
16293
16246
|
program.command("status").description("Show running agents (shorthand for work status)").option("--json", "Output as JSON").option("--tldr", "Show TLDR index health across all workspaces").option("--context", "Show context window usage % for each agent").action(statusCommand);
|
|
16294
16247
|
program.command("up").description("Start dashboard (and Traefik if enabled)").option("--detach", "Run in background").option("--skip-traefik", "Skip Traefik startup").action(async (options) => {
|
|
16295
16248
|
const { spawn: spawn2, execSync: execSync9 } = await import("child_process");
|
|
16296
|
-
const { join:
|
|
16249
|
+
const { join: join52, dirname: dirname16 } = await import("path");
|
|
16297
16250
|
const { fileURLToPath: fileURLToPath6 } = await import("url");
|
|
16298
|
-
const { readFileSync:
|
|
16251
|
+
const { readFileSync: readFileSync46, existsSync: existsSync52 } = await import("fs");
|
|
16299
16252
|
const { parse } = await import("@iarna/toml");
|
|
16300
16253
|
const __dirname6 = dirname16(fileURLToPath6(import.meta.url));
|
|
16301
|
-
const bundledServer =
|
|
16302
|
-
const srcDashboard =
|
|
16303
|
-
const configFile =
|
|
16254
|
+
const bundledServer = join52(__dirname6, "..", "dashboard", "server.js");
|
|
16255
|
+
const srcDashboard = join52(__dirname6, "..", "..", "src", "dashboard");
|
|
16256
|
+
const configFile = join52(process.env.HOME || "", ".panopticon", "config.toml");
|
|
16304
16257
|
let traefikEnabled = false;
|
|
16305
16258
|
let traefikDomain = "pan.localhost";
|
|
16306
16259
|
let dashboardPort = 3010;
|
|
16307
16260
|
let dashboardApiPort = 3011;
|
|
16308
|
-
if (
|
|
16261
|
+
if (existsSync52(configFile)) {
|
|
16309
16262
|
try {
|
|
16310
|
-
const configContent =
|
|
16263
|
+
const configContent = readFileSync46(configFile, "utf-8");
|
|
16311
16264
|
const config2 = parse(configContent);
|
|
16312
16265
|
traefikEnabled = config2.traefik?.enabled === true;
|
|
16313
16266
|
traefikDomain = config2.traefik?.domain || "pan.localhost";
|
|
@@ -16337,7 +16290,7 @@ program.command("up").description("Start dashboard (and Traefik if enabled)").op
|
|
|
16337
16290
|
}
|
|
16338
16291
|
try {
|
|
16339
16292
|
const { ensureBaseDomain: ensureBaseDomain2, detectDnsSyncMethod: detectDnsSyncMethod2, syncDnsToWindows: syncDnsToWindows2 } = await import("../dns-7BDJSD3E.js");
|
|
16340
|
-
const dnsMethod = (
|
|
16293
|
+
const dnsMethod = (existsSync52(configFile) ? parse(readFileSync46(configFile, "utf-8")).traefik?.dns_sync_method : null) || detectDnsSyncMethod2();
|
|
16341
16294
|
ensureBaseDomain2(dnsMethod, traefikDomain);
|
|
16342
16295
|
if (dnsMethod === "wsl2hosts") {
|
|
16343
16296
|
syncDnsToWindows2().catch(() => {
|
|
@@ -16360,19 +16313,19 @@ program.command("up").description("Start dashboard (and Traefik if enabled)").op
|
|
|
16360
16313
|
}
|
|
16361
16314
|
}
|
|
16362
16315
|
if (traefikEnabled && !options.skipTraefik) {
|
|
16363
|
-
const traefikDir =
|
|
16364
|
-
if (
|
|
16316
|
+
const traefikDir = join52(process.env.HOME || "", ".panopticon", "traefik");
|
|
16317
|
+
if (existsSync52(traefikDir)) {
|
|
16365
16318
|
try {
|
|
16366
|
-
const composeFile =
|
|
16367
|
-
if (
|
|
16368
|
-
const content =
|
|
16319
|
+
const composeFile = join52(traefikDir, "docker-compose.yml");
|
|
16320
|
+
if (existsSync52(composeFile)) {
|
|
16321
|
+
const content = readFileSync46(composeFile, "utf-8");
|
|
16369
16322
|
if (!content.includes("external: true") && content.includes("panopticon:")) {
|
|
16370
16323
|
const patched = content.replace(
|
|
16371
16324
|
/networks:\s*\n\s*panopticon:\s*\n\s*name: panopticon\s*\n\s*driver: bridge/,
|
|
16372
16325
|
"networks:\n panopticon:\n name: panopticon\n external: true # Network created by 'pan install'"
|
|
16373
16326
|
);
|
|
16374
|
-
const { writeFileSync:
|
|
16375
|
-
|
|
16327
|
+
const { writeFileSync: writeFileSync26 } = await import("fs");
|
|
16328
|
+
writeFileSync26(composeFile, patched);
|
|
16376
16329
|
console.log(chalk62.dim(" (migrated network config)"));
|
|
16377
16330
|
}
|
|
16378
16331
|
}
|
|
@@ -16390,8 +16343,8 @@ program.command("up").description("Start dashboard (and Traefik if enabled)").op
|
|
|
16390
16343
|
}
|
|
16391
16344
|
}
|
|
16392
16345
|
}
|
|
16393
|
-
const isProduction =
|
|
16394
|
-
const isDevelopment =
|
|
16346
|
+
const isProduction = existsSync52(bundledServer);
|
|
16347
|
+
const isDevelopment = existsSync52(srcDashboard);
|
|
16395
16348
|
if (!isProduction && !isDevelopment) {
|
|
16396
16349
|
console.error(chalk62.red("Error: Dashboard not found"));
|
|
16397
16350
|
console.error(chalk62.dim("This may be a corrupted installation. Try reinstalling panopticon-cli."));
|
|
@@ -16466,8 +16419,8 @@ program.command("up").description("Start dashboard (and Traefik if enabled)").op
|
|
|
16466
16419
|
try {
|
|
16467
16420
|
const { getTldrDaemonService: getTldrDaemonService2 } = await import("../tldr-daemon-T3THOUGT.js");
|
|
16468
16421
|
const projectRoot = process.cwd();
|
|
16469
|
-
const venvPath =
|
|
16470
|
-
if (
|
|
16422
|
+
const venvPath = join52(projectRoot, ".venv");
|
|
16423
|
+
if (existsSync52(venvPath)) {
|
|
16471
16424
|
console.log(chalk62.dim("\nStarting TLDR daemon for project root..."));
|
|
16472
16425
|
const tldrService = getTldrDaemonService2(projectRoot, venvPath);
|
|
16473
16426
|
await tldrService.start(true);
|
|
@@ -16483,17 +16436,17 @@ program.command("up").description("Start dashboard (and Traefik if enabled)").op
|
|
|
16483
16436
|
});
|
|
16484
16437
|
program.command("down").description("Stop dashboard (and Traefik if enabled)").option("--skip-traefik", "Skip Traefik shutdown").action(async (options) => {
|
|
16485
16438
|
const { execSync: execSync9 } = await import("child_process");
|
|
16486
|
-
const { join:
|
|
16487
|
-
const { readFileSync:
|
|
16439
|
+
const { join: join52 } = await import("path");
|
|
16440
|
+
const { readFileSync: readFileSync46, existsSync: existsSync52 } = await import("fs");
|
|
16488
16441
|
const { parse } = await import("@iarna/toml");
|
|
16489
16442
|
console.log(chalk62.bold("Stopping Panopticon...\n"));
|
|
16490
|
-
const configFile =
|
|
16443
|
+
const configFile = join52(process.env.HOME || "", ".panopticon", "config.toml");
|
|
16491
16444
|
let traefikEnabled = false;
|
|
16492
16445
|
let dashboardPort = 3010;
|
|
16493
16446
|
let dashboardApiPort = 3011;
|
|
16494
|
-
if (
|
|
16447
|
+
if (existsSync52(configFile)) {
|
|
16495
16448
|
try {
|
|
16496
|
-
const configContent =
|
|
16449
|
+
const configContent = readFileSync46(configFile, "utf-8");
|
|
16497
16450
|
const config2 = parse(configContent);
|
|
16498
16451
|
traefikEnabled = config2.traefik?.enabled === true;
|
|
16499
16452
|
dashboardPort = config2.dashboard?.port || 3010;
|
|
@@ -16510,8 +16463,8 @@ program.command("down").description("Stop dashboard (and Traefik if enabled)").o
|
|
|
16510
16463
|
console.log(chalk62.dim(" No dashboard processes found"));
|
|
16511
16464
|
}
|
|
16512
16465
|
if (traefikEnabled && !options.skipTraefik) {
|
|
16513
|
-
const traefikDir =
|
|
16514
|
-
if (
|
|
16466
|
+
const traefikDir = join52(process.env.HOME || "", ".panopticon", "traefik");
|
|
16467
|
+
if (existsSync52(traefikDir)) {
|
|
16515
16468
|
console.log(chalk62.dim("Stopping Traefik..."));
|
|
16516
16469
|
try {
|
|
16517
16470
|
execSync9("docker compose down", {
|
|
@@ -16530,8 +16483,8 @@ program.command("down").description("Stop dashboard (and Traefik if enabled)").o
|
|
|
16530
16483
|
const { promisify: promisify21 } = await import("util");
|
|
16531
16484
|
const execAsync21 = promisify21(exec21);
|
|
16532
16485
|
const projectRoot = process.cwd();
|
|
16533
|
-
const venvPath =
|
|
16534
|
-
if (
|
|
16486
|
+
const venvPath = join52(projectRoot, ".venv");
|
|
16487
|
+
if (existsSync52(venvPath)) {
|
|
16535
16488
|
console.log(chalk62.dim("\nStopping TLDR daemon..."));
|
|
16536
16489
|
const tldrService = getTldrDaemonService2(projectRoot, venvPath);
|
|
16537
16490
|
await tldrService.stop();
|