panopticon-cli 0.4.21 → 0.4.23

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.
Files changed (43) hide show
  1. package/dist/{agents-2Q6TCHNN.js → agents-ND4NKCK2.js} +5 -5
  2. package/dist/{chunk-KQAEUOML.js → chunk-46DPNFMW.js} +2 -2
  3. package/dist/{chunk-26QM7CPN.js → chunk-6CIBLKFZ.js} +4 -3
  4. package/dist/{chunk-26QM7CPN.js.map → chunk-6CIBLKFZ.js.map} +1 -1
  5. package/dist/{chunk-KGPRXDMX.js → chunk-6HXKTOD7.js} +5 -1
  6. package/dist/chunk-6HXKTOD7.js.map +1 -0
  7. package/dist/{chunk-QB3W4NX6.js → chunk-G4H6KZDC.js} +29 -22
  8. package/dist/{chunk-QB3W4NX6.js.map → chunk-G4H6KZDC.js.map} +1 -1
  9. package/dist/{chunk-SOL4WQJD.js → chunk-JY7R7V4G.js} +2 -2
  10. package/dist/{chunk-65DGYSS4.js → chunk-ON5NIBGW.js} +2 -2
  11. package/dist/{chunk-YOQLBJ7B.js → chunk-SIAUVHVO.js} +3 -3
  12. package/dist/{chunk-ZAM2Q52Q.js → chunk-VTMXR7JF.js} +2 -2
  13. package/dist/{chunk-XTXWSLT3.js → chunk-ZLB6G4NW.js} +4 -4
  14. package/dist/cli/index.js +20 -20
  15. package/dist/{config-WCEPLNXI.js → config-QWTS63TU.js} +3 -3
  16. package/dist/dashboard/server.js +170 -44
  17. package/dist/index.d.ts +3 -1
  18. package/dist/index.js +6 -4
  19. package/dist/index.js.map +1 -1
  20. package/dist/{projects-AMR3XQM4.js → projects-VXRUCMLM.js} +3 -3
  21. package/dist/{remote-workspace-V57IZJRC.js → remote-workspace-FNXLMNBG.js} +4 -4
  22. package/dist/{specialist-context-2G6YOU3M.js → specialist-context-VWST6O2N.js} +13 -14
  23. package/dist/specialist-context-VWST6O2N.js.map +1 -0
  24. package/dist/{specialist-logs-5OTCVAVH.js → specialist-logs-OU3KESAI.js} +5 -5
  25. package/dist/{specialists-H5QEVLNN.js → specialists-QVAZGJPU.js} +5 -5
  26. package/dist/{traefik-DRNZMPGZ.js → traefik-7OLLXUD7.js} +4 -4
  27. package/package.json +1 -1
  28. package/skills/pan-oversee/SKILL.md +63 -11
  29. package/dist/chunk-KGPRXDMX.js.map +0 -1
  30. package/dist/specialist-context-2G6YOU3M.js.map +0 -1
  31. /package/dist/{agents-2Q6TCHNN.js.map → agents-ND4NKCK2.js.map} +0 -0
  32. /package/dist/{chunk-KQAEUOML.js.map → chunk-46DPNFMW.js.map} +0 -0
  33. /package/dist/{chunk-SOL4WQJD.js.map → chunk-JY7R7V4G.js.map} +0 -0
  34. /package/dist/{chunk-65DGYSS4.js.map → chunk-ON5NIBGW.js.map} +0 -0
  35. /package/dist/{chunk-YOQLBJ7B.js.map → chunk-SIAUVHVO.js.map} +0 -0
  36. /package/dist/{chunk-ZAM2Q52Q.js.map → chunk-VTMXR7JF.js.map} +0 -0
  37. /package/dist/{chunk-XTXWSLT3.js.map → chunk-ZLB6G4NW.js.map} +0 -0
  38. /package/dist/{config-WCEPLNXI.js.map → config-QWTS63TU.js.map} +0 -0
  39. /package/dist/{projects-AMR3XQM4.js.map → projects-VXRUCMLM.js.map} +0 -0
  40. /package/dist/{remote-workspace-V57IZJRC.js.map → remote-workspace-FNXLMNBG.js.map} +0 -0
  41. /package/dist/{specialist-logs-5OTCVAVH.js.map → specialist-logs-OU3KESAI.js.map} +0 -0
  42. /package/dist/{specialists-H5QEVLNN.js.map → specialists-QVAZGJPU.js.map} +0 -0
  43. /package/dist/{traefik-DRNZMPGZ.js.map → traefik-7OLLXUD7.js.map} +0 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/lib/paths.ts"],"sourcesContent":["import { homedir } from 'os';\nimport { join } from 'path';\nimport { existsSync } from 'fs';\n\n// Panopticon home directory (can be overridden for testing)\nexport const PANOPTICON_HOME = process.env.PANOPTICON_HOME || join(homedir(), '.panopticon');\n\n/** Get PANOPTICON_HOME dynamically (reads env var on each call, useful for testing) */\nexport function getPanopticonHome(): string {\n return process.env.PANOPTICON_HOME || join(homedir(), '.panopticon');\n}\n\n// Subdirectories\nexport const CONFIG_DIR = PANOPTICON_HOME;\nexport const SKILLS_DIR = join(PANOPTICON_HOME, 'skills');\nexport const COMMANDS_DIR = join(PANOPTICON_HOME, 'commands');\nexport const AGENTS_DIR = join(PANOPTICON_HOME, 'agents');\nexport const BIN_DIR = join(PANOPTICON_HOME, 'bin');\nexport const BACKUPS_DIR = join(PANOPTICON_HOME, 'backups');\nexport const COSTS_DIR = join(PANOPTICON_HOME, 'costs');\nexport const HEARTBEATS_DIR = join(PANOPTICON_HOME, 'heartbeats');\n\n// Traefik directories\nexport const TRAEFIK_DIR = join(PANOPTICON_HOME, 'traefik');\nexport const TRAEFIK_DYNAMIC_DIR = join(TRAEFIK_DIR, 'dynamic');\nexport const TRAEFIK_CERTS_DIR = join(TRAEFIK_DIR, 'certs');\n\n// Legacy certs directory (for backwards compatibility)\nexport const CERTS_DIR = join(PANOPTICON_HOME, 'certs');\n\n// Config files\nexport const CONFIG_FILE = join(CONFIG_DIR, 'config.toml');\nexport const SETTINGS_FILE = join(CONFIG_DIR, 'settings.json');\n\n// AI tool directories\nexport const CLAUDE_DIR = join(homedir(), '.claude');\nexport const CODEX_DIR = join(homedir(), '.codex');\nexport const CURSOR_DIR = join(homedir(), '.cursor');\nexport const GEMINI_DIR = join(homedir(), '.gemini');\nexport const OPENCODE_DIR = join(homedir(), '.opencode');\n\n// Target sync locations\nexport const SYNC_TARGETS = {\n claude: {\n skills: join(CLAUDE_DIR, 'skills'),\n commands: join(CLAUDE_DIR, 'commands'),\n agents: join(CLAUDE_DIR, 'agents'),\n },\n codex: {\n skills: join(CODEX_DIR, 'skills'),\n commands: join(CODEX_DIR, 'commands'),\n agents: join(CODEX_DIR, 'agents'),\n },\n cursor: {\n skills: join(CURSOR_DIR, 'skills'),\n commands: join(CURSOR_DIR, 'commands'),\n agents: join(CURSOR_DIR, 'agents'),\n },\n gemini: {\n skills: join(GEMINI_DIR, 'skills'),\n commands: join(GEMINI_DIR, 'commands'),\n agents: join(GEMINI_DIR, 'agents'),\n },\n opencode: {\n skills: join(OPENCODE_DIR, 'skills'),\n commands: join(OPENCODE_DIR, 'commands'),\n agents: join(OPENCODE_DIR, 'agents'),\n },\n} as const;\n\nexport type Runtime = keyof typeof SYNC_TARGETS;\n\n// Templates directory (in user's ~/.panopticon)\nexport const TEMPLATES_DIR = join(PANOPTICON_HOME, 'templates');\nexport const CLAUDE_MD_TEMPLATES = join(TEMPLATES_DIR, 'claude-md', 'sections');\n\n// Source templates directory (bundled with the package)\n// This is resolved at runtime from the package root\nimport { fileURLToPath } from 'url';\nimport { dirname } from 'path';\n\nconst currentFile = fileURLToPath(import.meta.url);\nconst currentDir = dirname(currentFile);\n\n// Handle both development (src/lib/) and production (dist/) modes\n// In dev: /path/to/panopticon/src/lib/paths.ts -> /path/to/panopticon\n// In prod: /path/to/panopticon/dist/lib/paths.js -> /path/to/panopticon\nlet packageRoot: string;\nif (currentDir.includes('/src/')) {\n // Development mode - go up from src/lib to package root\n packageRoot = dirname(dirname(currentDir));\n} else {\n // Production mode - go up from dist (or dist/lib) to package root\n packageRoot = currentDir.endsWith('/lib')\n ? dirname(dirname(currentDir))\n : dirname(currentDir);\n}\n\nexport const SOURCE_TEMPLATES_DIR = join(packageRoot, 'templates');\nexport const SOURCE_TRAEFIK_TEMPLATES = join(SOURCE_TEMPLATES_DIR, 'traefik');\nexport const SOURCE_SCRIPTS_DIR = join(packageRoot, 'scripts');\nexport const SOURCE_SKILLS_DIR = join(packageRoot, 'skills');\nexport const SOURCE_DEV_SKILLS_DIR = join(packageRoot, 'dev-skills');\n\n/**\n * Detect if running in development mode (from npm link or panopticon repo)\n *\n * Dev mode is detected if:\n * 1. Running from the panopticon source directory (npm link)\n * 2. The SOURCE_DEV_SKILLS_DIR exists (only present in repo, not in npm package)\n */\nexport function isDevMode(): boolean {\n try {\n // Check if dev-skills directory exists - this is only in the repo, not npm package\n return existsSync(SOURCE_DEV_SKILLS_DIR);\n } catch {\n return false;\n }\n}\n\n// All directories to create on init\nexport const INIT_DIRS = [\n PANOPTICON_HOME,\n SKILLS_DIR,\n COMMANDS_DIR,\n AGENTS_DIR,\n BIN_DIR,\n BACKUPS_DIR,\n COSTS_DIR,\n HEARTBEATS_DIR,\n TEMPLATES_DIR,\n CLAUDE_MD_TEMPLATES,\n CERTS_DIR,\n TRAEFIK_DIR,\n TRAEFIK_DYNAMIC_DIR,\n TRAEFIK_CERTS_DIR,\n];\n"],"mappings":"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","names":[]}
@@ -7,16 +7,17 @@ import {
7
7
  popFromHook,
8
8
  pushToHook,
9
9
  sendKeys
10
- } from "./chunk-65DGYSS4.js";
10
+ } from "./chunk-ON5NIBGW.js";
11
11
  import {
12
12
  init_projects,
13
13
  projects_exports
14
- } from "./chunk-SOL4WQJD.js";
14
+ } from "./chunk-JY7R7V4G.js";
15
15
  import {
16
16
  COSTS_DIR,
17
17
  PANOPTICON_HOME,
18
+ getPanopticonHome,
18
19
  init_paths
19
- } from "./chunk-KGPRXDMX.js";
20
+ } from "./chunk-6HXKTOD7.js";
20
21
  import {
21
22
  __esm,
22
23
  __export,
@@ -552,9 +553,9 @@ function recordWake(name, sessionId) {
552
553
  }
553
554
  async function spawnEphemeralSpecialist(projectKey, specialistType, task) {
554
555
  ensureProjectSpecialistDir(projectKey, specialistType);
555
- const { loadContextDigest } = await import("./specialist-context-2G6YOU3M.js");
556
+ const { loadContextDigest } = await import("./specialist-context-VWST6O2N.js");
556
557
  const contextDigest = loadContextDigest(projectKey, specialistType);
557
- const { createRunLog: createRunLog2 } = await import("./specialist-logs-5OTCVAVH.js");
558
+ const { createRunLog: createRunLog2 } = await import("./specialist-logs-OU3KESAI.js");
558
559
  const { runId, filePath: logFilePath } = createRunLog2(
559
560
  projectKey,
560
561
  specialistType,
@@ -595,7 +596,7 @@ echo "## Specialist completed task"
595
596
  `tmux new-session -d -s "${tmuxSession}" "bash '${launcherScript}'"`,
596
597
  { encoding: "utf-8" }
597
598
  );
598
- const { saveAgentRuntimeState } = await import("./agents-2Q6TCHNN.js");
599
+ const { saveAgentRuntimeState } = await import("./agents-ND4NKCK2.js");
599
600
  saveAgentRuntimeState(tmuxSession, {
600
601
  state: "active",
601
602
  lastActivity: (/* @__PURE__ */ new Date()).toISOString(),
@@ -619,7 +620,7 @@ echo "## Specialist completed task"
619
620
  }
620
621
  }
621
622
  async function buildTaskPrompt(projectKey, specialistType, task, contextDigest) {
622
- const { getSpecialistPromptOverride } = await import("./projects-AMR3XQM4.js");
623
+ const { getSpecialistPromptOverride } = await import("./projects-VXRUCMLM.js");
623
624
  const customPrompt = getSpecialistPromptOverride(projectKey, specialistType);
624
625
  let prompt = `# ${specialistType} Task - ${task.issueId}
625
626
 
@@ -777,7 +778,7 @@ async function terminateSpecialist(projectKey, specialistType) {
777
778
  console.error(`[specialist] Failed to kill tmux session ${tmuxSession}:`, error);
778
779
  }
779
780
  if (metadata.currentRun) {
780
- const { finalizeRunLog: finalizeRunLog2 } = await import("./specialist-logs-5OTCVAVH.js");
781
+ const { finalizeRunLog: finalizeRunLog2 } = await import("./specialist-logs-OU3KESAI.js");
781
782
  try {
782
783
  finalizeRunLog2(projectKey, specialistType, metadata.currentRun, {
783
784
  status: metadata.lastRunStatus || "incomplete",
@@ -790,20 +791,20 @@ async function terminateSpecialist(projectKey, specialistType) {
790
791
  }
791
792
  const key = `${projectKey}-${specialistType}`;
792
793
  gracePeriodStates.delete(key);
793
- const { saveAgentRuntimeState } = await import("./agents-2Q6TCHNN.js");
794
+ const { saveAgentRuntimeState } = await import("./agents-ND4NKCK2.js");
794
795
  saveAgentRuntimeState(tmuxSession, {
795
796
  state: "suspended",
796
797
  lastActivity: (/* @__PURE__ */ new Date()).toISOString()
797
798
  });
798
- const { scheduleDigestGeneration } = await import("./specialist-context-2G6YOU3M.js");
799
+ const { scheduleDigestGeneration } = await import("./specialist-context-VWST6O2N.js");
799
800
  scheduleDigestGeneration(projectKey, specialistType);
800
801
  scheduleLogCleanup(projectKey, specialistType);
801
802
  }
802
803
  function scheduleLogCleanup(projectKey, specialistType) {
803
804
  Promise.resolve().then(async () => {
804
805
  try {
805
- const { cleanupOldLogs: cleanupOldLogs2 } = await import("./specialist-logs-5OTCVAVH.js");
806
- const { getSpecialistRetention } = await import("./projects-AMR3XQM4.js");
806
+ const { cleanupOldLogs: cleanupOldLogs2 } = await import("./specialist-logs-OU3KESAI.js");
807
+ const { getSpecialistRetention } = await import("./projects-VXRUCMLM.js");
807
808
  const retention = getSpecialistRetention(projectKey);
808
809
  const deleted = cleanupOldLogs2(projectKey, specialistType, { maxDays: retention.max_days, maxRuns: retention.max_runs });
809
810
  if (deleted > 0) {
@@ -981,7 +982,7 @@ async function getSpecialistStatus(name, projectKey) {
981
982
  const sessionId = getSessionId(name);
982
983
  const running = await isRunning(name, projectKey);
983
984
  const contextTokens = countContextTokens(name);
984
- const { getAgentRuntimeState } = await import("./agents-2Q6TCHNN.js");
985
+ const { getAgentRuntimeState } = await import("./agents-ND4NKCK2.js");
985
986
  const tmuxSession = getTmuxSessionName(name, projectKey);
986
987
  const runtimeState = getAgentRuntimeState(tmuxSession);
987
988
  let state;
@@ -1173,7 +1174,7 @@ async function wakeSpecialist(name, taskPrompt, options = {}) {
1173
1174
  sendKeys(tmuxSession, taskPrompt);
1174
1175
  }
1175
1176
  recordWake(name, sessionId || void 0);
1176
- const { saveAgentRuntimeState } = await import("./agents-2Q6TCHNN.js");
1177
+ const { saveAgentRuntimeState } = await import("./agents-ND4NKCK2.js");
1177
1178
  saveAgentRuntimeState(tmuxSession, {
1178
1179
  state: "active",
1179
1180
  lastActivity: (/* @__PURE__ */ new Date()).toISOString(),
@@ -1362,7 +1363,7 @@ IMPORTANT: Do NOT hand off to merge-agent. Human clicks Merge button when ready.
1362
1363
  async function wakeSpecialistOrQueue(name, task, options = {}) {
1363
1364
  const { priority = "normal", source = "handoff" } = options;
1364
1365
  const running = await isRunning(name);
1365
- const { getAgentRuntimeState } = await import("./agents-2Q6TCHNN.js");
1366
+ const { getAgentRuntimeState } = await import("./agents-ND4NKCK2.js");
1366
1367
  const tmuxSession = getTmuxSessionName(name);
1367
1368
  const runtimeState = getAgentRuntimeState(tmuxSession);
1368
1369
  const idle = runtimeState?.state === "idle" || runtimeState?.state === "suspended";
@@ -1393,7 +1394,7 @@ async function wakeSpecialistOrQueue(name, task, options = {}) {
1393
1394
  };
1394
1395
  }
1395
1396
  }
1396
- const { saveAgentRuntimeState } = await import("./agents-2Q6TCHNN.js");
1397
+ const { saveAgentRuntimeState } = await import("./agents-ND4NKCK2.js");
1397
1398
  saveAgentRuntimeState(tmuxSession, {
1398
1399
  state: "active",
1399
1400
  lastActivity: (/* @__PURE__ */ new Date()).toISOString(),
@@ -1492,7 +1493,7 @@ async function sendFeedbackToAgent(feedback) {
1492
1493
  }
1493
1494
  const agentSession = `agent-${toIssueId.toLowerCase()}`;
1494
1495
  try {
1495
- const { messageAgent } = await import("./agents-2Q6TCHNN.js");
1496
+ const { messageAgent } = await import("./agents-ND4NKCK2.js");
1496
1497
  const feedbackMessage = formatFeedbackForAgent(fullFeedback);
1497
1498
  await messageAgent(agentSession, feedbackMessage);
1498
1499
  console.log(`[specialist] Sent feedback from ${fromSpecialist} to ${agentSession}`);
@@ -1655,8 +1656,11 @@ __export(specialist_logs_exports, {
1655
1656
  });
1656
1657
  import { existsSync as existsSync4, mkdirSync as mkdirSync3, writeFileSync as writeFileSync2, appendFileSync as appendFileSync3, readFileSync as readFileSync4, readdirSync as readdirSync3, statSync as statSync2, unlinkSync as unlinkSync2 } from "fs";
1657
1658
  import { join as join5, basename as basename3 } from "path";
1659
+ function getSpecialistsDir() {
1660
+ return join5(getPanopticonHome(), "specialists");
1661
+ }
1658
1662
  function getRunsDirectory(projectKey, specialistType) {
1659
- return join5(SPECIALISTS_DIR2, projectKey, specialistType, "runs");
1663
+ return join5(getSpecialistsDir(), projectKey, specialistType, "runs");
1660
1664
  }
1661
1665
  function generateRunId(issueId) {
1662
1666
  const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-").substring(0, 19);
@@ -1791,7 +1795,11 @@ function listRunLogs(projectKey, specialistType, options = {}) {
1791
1795
  createdAt: stats.birthtime
1792
1796
  };
1793
1797
  });
1794
- files.sort((a, b) => b.createdAt.getTime() - a.createdAt.getTime());
1798
+ files.sort((a, b) => {
1799
+ const timeDiff = b.createdAt.getTime() - a.createdAt.getTime();
1800
+ if (timeDiff !== 0) return timeDiff;
1801
+ return b.runId.localeCompare(a.runId);
1802
+ });
1795
1803
  const { limit, offset = 0 } = options;
1796
1804
  if (limit !== void 0) {
1797
1805
  return files.slice(offset, offset + limit);
@@ -1887,12 +1895,11 @@ function cleanupAllLogs() {
1887
1895
  console.log(`[specialist-logs] Cleanup complete: deleted ${results.totalDeleted} old logs`);
1888
1896
  return results;
1889
1897
  }
1890
- var SPECIALISTS_DIR2, MAX_LOG_SIZE;
1898
+ var MAX_LOG_SIZE;
1891
1899
  var init_specialist_logs = __esm({
1892
1900
  "src/lib/cloister/specialist-logs.ts"() {
1893
1901
  init_esm_shims();
1894
1902
  init_paths();
1895
- SPECIALISTS_DIR2 = join5(PANOPTICON_HOME, "specialists");
1896
1903
  MAX_LOG_SIZE = 10 * 1024 * 1024;
1897
1904
  }
1898
1905
  });
@@ -1976,4 +1983,4 @@ export {
1976
1983
  getFeedbackStats,
1977
1984
  init_specialists
1978
1985
  };
1979
- //# sourceMappingURL=chunk-QB3W4NX6.js.map
1986
+ //# sourceMappingURL=chunk-G4H6KZDC.js.map