@fml-inc/panopticon 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (124) hide show
  1. package/.claude-plugin/plugin.json +10 -0
  2. package/LICENSE +5 -0
  3. package/README.md +363 -0
  4. package/bin/hook-handler +3 -0
  5. package/bin/mcp-server +3 -0
  6. package/bin/panopticon +3 -0
  7. package/bin/proxy +3 -0
  8. package/bin/server +3 -0
  9. package/dist/api/client.d.ts +67 -0
  10. package/dist/api/client.js +48 -0
  11. package/dist/api/client.js.map +1 -0
  12. package/dist/chunk-3BUJ7URA.js +387 -0
  13. package/dist/chunk-3BUJ7URA.js.map +1 -0
  14. package/dist/chunk-3TZAKV3M.js +158 -0
  15. package/dist/chunk-3TZAKV3M.js.map +1 -0
  16. package/dist/chunk-4SM2H22C.js +169 -0
  17. package/dist/chunk-4SM2H22C.js.map +1 -0
  18. package/dist/chunk-7Q3BJMLG.js +62 -0
  19. package/dist/chunk-7Q3BJMLG.js.map +1 -0
  20. package/dist/chunk-BVOE7A2Z.js +412 -0
  21. package/dist/chunk-BVOE7A2Z.js.map +1 -0
  22. package/dist/chunk-CF4GPWLI.js +170 -0
  23. package/dist/chunk-CF4GPWLI.js.map +1 -0
  24. package/dist/chunk-DZ5HJFB4.js +467 -0
  25. package/dist/chunk-DZ5HJFB4.js.map +1 -0
  26. package/dist/chunk-HQCY722C.js +428 -0
  27. package/dist/chunk-HQCY722C.js.map +1 -0
  28. package/dist/chunk-HRCEIYKU.js +134 -0
  29. package/dist/chunk-HRCEIYKU.js.map +1 -0
  30. package/dist/chunk-K7YUPLES.js +76 -0
  31. package/dist/chunk-K7YUPLES.js.map +1 -0
  32. package/dist/chunk-L7G27XWF.js +130 -0
  33. package/dist/chunk-L7G27XWF.js.map +1 -0
  34. package/dist/chunk-LWXF7YRG.js +626 -0
  35. package/dist/chunk-LWXF7YRG.js.map +1 -0
  36. package/dist/chunk-NXH7AONS.js +1120 -0
  37. package/dist/chunk-NXH7AONS.js.map +1 -0
  38. package/dist/chunk-QK5442ZP.js +55 -0
  39. package/dist/chunk-QK5442ZP.js.map +1 -0
  40. package/dist/chunk-QVK6VGCV.js +1703 -0
  41. package/dist/chunk-QVK6VGCV.js.map +1 -0
  42. package/dist/chunk-RX2RXHBH.js +1699 -0
  43. package/dist/chunk-RX2RXHBH.js.map +1 -0
  44. package/dist/chunk-SEXU2WYG.js +788 -0
  45. package/dist/chunk-SEXU2WYG.js.map +1 -0
  46. package/dist/chunk-SUGSQ4YI.js +264 -0
  47. package/dist/chunk-SUGSQ4YI.js.map +1 -0
  48. package/dist/chunk-TGXFVAID.js +138 -0
  49. package/dist/chunk-TGXFVAID.js.map +1 -0
  50. package/dist/chunk-WLBNFVIG.js +447 -0
  51. package/dist/chunk-WLBNFVIG.js.map +1 -0
  52. package/dist/chunk-XLTCUH5A.js +1072 -0
  53. package/dist/chunk-XLTCUH5A.js.map +1 -0
  54. package/dist/chunk-YVRWVDIA.js +146 -0
  55. package/dist/chunk-YVRWVDIA.js.map +1 -0
  56. package/dist/chunk-ZEC4LRKS.js +176 -0
  57. package/dist/chunk-ZEC4LRKS.js.map +1 -0
  58. package/dist/cli.d.ts +1 -0
  59. package/dist/cli.js +1084 -0
  60. package/dist/cli.js.map +1 -0
  61. package/dist/config-NwoZC-GM.d.ts +20 -0
  62. package/dist/db.d.ts +46 -0
  63. package/dist/db.js +15 -0
  64. package/dist/db.js.map +1 -0
  65. package/dist/doctor.d.ts +37 -0
  66. package/dist/doctor.js +14 -0
  67. package/dist/doctor.js.map +1 -0
  68. package/dist/hooks/handler.d.ts +23 -0
  69. package/dist/hooks/handler.js +295 -0
  70. package/dist/hooks/handler.js.map +1 -0
  71. package/dist/index.d.ts +57 -0
  72. package/dist/index.js +101 -0
  73. package/dist/index.js.map +1 -0
  74. package/dist/mcp/server.d.ts +1 -0
  75. package/dist/mcp/server.js +243 -0
  76. package/dist/mcp/server.js.map +1 -0
  77. package/dist/otlp/server.d.ts +7 -0
  78. package/dist/otlp/server.js +17 -0
  79. package/dist/otlp/server.js.map +1 -0
  80. package/dist/permissions.d.ts +33 -0
  81. package/dist/permissions.js +14 -0
  82. package/dist/permissions.js.map +1 -0
  83. package/dist/pricing.d.ts +29 -0
  84. package/dist/pricing.js +13 -0
  85. package/dist/pricing.js.map +1 -0
  86. package/dist/proxy/server.d.ts +10 -0
  87. package/dist/proxy/server.js +20 -0
  88. package/dist/proxy/server.js.map +1 -0
  89. package/dist/prune.d.ts +18 -0
  90. package/dist/prune.js +13 -0
  91. package/dist/prune.js.map +1 -0
  92. package/dist/query.d.ts +56 -0
  93. package/dist/query.js +27 -0
  94. package/dist/query.js.map +1 -0
  95. package/dist/reparse-636YZCE3.js +14 -0
  96. package/dist/reparse-636YZCE3.js.map +1 -0
  97. package/dist/repo.d.ts +17 -0
  98. package/dist/repo.js +9 -0
  99. package/dist/repo.js.map +1 -0
  100. package/dist/scanner.d.ts +73 -0
  101. package/dist/scanner.js +15 -0
  102. package/dist/scanner.js.map +1 -0
  103. package/dist/sdk.d.ts +82 -0
  104. package/dist/sdk.js +208 -0
  105. package/dist/sdk.js.map +1 -0
  106. package/dist/server.d.ts +5 -0
  107. package/dist/server.js +25 -0
  108. package/dist/server.js.map +1 -0
  109. package/dist/setup.d.ts +35 -0
  110. package/dist/setup.js +19 -0
  111. package/dist/setup.js.map +1 -0
  112. package/dist/sync/index.d.ts +29 -0
  113. package/dist/sync/index.js +32 -0
  114. package/dist/sync/index.js.map +1 -0
  115. package/dist/targets.d.ts +279 -0
  116. package/dist/targets.js +20 -0
  117. package/dist/targets.js.map +1 -0
  118. package/dist/types-D-MYCBol.d.ts +128 -0
  119. package/dist/types.d.ts +164 -0
  120. package/dist/types.js +1 -0
  121. package/dist/types.js.map +1 -0
  122. package/hooks/hooks.json +274 -0
  123. package/package.json +124 -0
  124. package/skills/panopticon-optimize/SKILL.md +222 -0
@@ -0,0 +1,76 @@
1
+ // src/config.ts
2
+ import fs from "fs";
3
+ import os from "os";
4
+ import path from "path";
5
+ function defaultDataDir() {
6
+ switch (process.platform) {
7
+ case "darwin":
8
+ return path.join(
9
+ os.homedir(),
10
+ "Library",
11
+ "Application Support",
12
+ "panopticon"
13
+ );
14
+ case "win32":
15
+ return path.join(
16
+ process.env.APPDATA ?? path.join(os.homedir(), "AppData", "Roaming"),
17
+ "panopticon"
18
+ );
19
+ default:
20
+ return path.join(os.homedir(), ".local", "share", "panopticon");
21
+ }
22
+ }
23
+ function resolveDataDir() {
24
+ if (process.env.PANOPTICON_DATA_DIR) return process.env.PANOPTICON_DATA_DIR;
25
+ return defaultDataDir();
26
+ }
27
+ var DATA_DIR = resolveDataDir();
28
+ var CLAUDE_DIR = path.join(os.homedir(), ".claude");
29
+ var MARKETPLACE_DIR = path.join(
30
+ os.homedir(),
31
+ ".local",
32
+ "share",
33
+ "claude-plugins"
34
+ );
35
+ var DEFAULT_PORT = 4318;
36
+ var config = {
37
+ dataDir: DATA_DIR,
38
+ dbPath: path.join(DATA_DIR, "panopticon.db"),
39
+ // Unified server port — replaces separate OTLP and proxy ports
40
+ port: parseInt(
41
+ process.env.PANOPTICON_PORT ?? process.env.PANOPTICON_OTLP_PORT ?? String(DEFAULT_PORT),
42
+ 10
43
+ ),
44
+ host: process.env.PANOPTICON_HOST ?? "127.0.0.1",
45
+ serverPidFile: path.join(DATA_DIR, "panopticon.pid"),
46
+ // Legacy — kept for backward compat during transition
47
+ pidFile: path.join(DATA_DIR, "otlp-receiver.pid"),
48
+ otlpPort: parseInt(process.env.PANOPTICON_OTLP_PORT ?? "4318", 10),
49
+ otlpHost: process.env.PANOPTICON_OTLP_HOST ?? "0.0.0.0",
50
+ marketplaceDir: MARKETPLACE_DIR,
51
+ marketplaceManifest: path.join(
52
+ MARKETPLACE_DIR,
53
+ ".claude-plugin",
54
+ "marketplace.json"
55
+ ),
56
+ pluginCacheDir: path.join(
57
+ CLAUDE_DIR,
58
+ "plugins",
59
+ "cache",
60
+ "local-plugins",
61
+ "panopticon"
62
+ ),
63
+ proxyPort: parseInt(process.env.PANOPTICON_PROXY_PORT ?? "4320", 10),
64
+ proxyHost: process.env.PANOPTICON_PROXY_HOST ?? "127.0.0.1",
65
+ proxyPidFile: path.join(DATA_DIR, "proxy.pid"),
66
+ proxyIdleSessionMs: 30 * 60 * 1e3
67
+ };
68
+ function ensureDataDir() {
69
+ fs.mkdirSync(config.dataDir, { recursive: true });
70
+ }
71
+
72
+ export {
73
+ config,
74
+ ensureDataDir
75
+ };
76
+ //# sourceMappingURL=chunk-K7YUPLES.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/config.ts"],"sourcesContent":["import fs from \"node:fs\";\nimport os from \"node:os\";\nimport path from \"node:path\";\n\nfunction defaultDataDir(): string {\n switch (process.platform) {\n case \"darwin\":\n return path.join(\n os.homedir(),\n \"Library\",\n \"Application Support\",\n \"panopticon\",\n );\n case \"win32\":\n return path.join(\n process.env.APPDATA ?? path.join(os.homedir(), \"AppData\", \"Roaming\"),\n \"panopticon\",\n );\n default:\n return path.join(os.homedir(), \".local\", \"share\", \"panopticon\");\n }\n}\n\nfunction resolveDataDir(): string {\n if (process.env.PANOPTICON_DATA_DIR) return process.env.PANOPTICON_DATA_DIR;\n return defaultDataDir();\n}\n\nconst DATA_DIR = resolveDataDir();\n\nconst CLAUDE_DIR = path.join(os.homedir(), \".claude\");\nconst MARKETPLACE_DIR = path.join(\n os.homedir(),\n \".local\",\n \"share\",\n \"claude-plugins\",\n);\n\nconst DEFAULT_PORT = 4318;\n\nexport const config = {\n dataDir: DATA_DIR,\n dbPath: path.join(DATA_DIR, \"panopticon.db\"),\n // Unified server port — replaces separate OTLP and proxy ports\n port: parseInt(\n process.env.PANOPTICON_PORT ??\n process.env.PANOPTICON_OTLP_PORT ??\n String(DEFAULT_PORT),\n 10,\n ),\n host: process.env.PANOPTICON_HOST ?? \"127.0.0.1\",\n serverPidFile: path.join(DATA_DIR, \"panopticon.pid\"),\n // Legacy — kept for backward compat during transition\n pidFile: path.join(DATA_DIR, \"otlp-receiver.pid\"),\n otlpPort: parseInt(process.env.PANOPTICON_OTLP_PORT ?? \"4318\", 10),\n otlpHost: process.env.PANOPTICON_OTLP_HOST ?? \"0.0.0.0\",\n marketplaceDir: MARKETPLACE_DIR,\n marketplaceManifest: path.join(\n MARKETPLACE_DIR,\n \".claude-plugin\",\n \"marketplace.json\",\n ),\n pluginCacheDir: path.join(\n CLAUDE_DIR,\n \"plugins\",\n \"cache\",\n \"local-plugins\",\n \"panopticon\",\n ),\n proxyPort: parseInt(process.env.PANOPTICON_PROXY_PORT ?? \"4320\", 10),\n proxyHost: process.env.PANOPTICON_PROXY_HOST ?? \"127.0.0.1\",\n proxyPidFile: path.join(DATA_DIR, \"proxy.pid\"),\n proxyIdleSessionMs: 30 * 60 * 1000,\n} as const;\n\nexport function ensureDataDir(): void {\n fs.mkdirSync(config.dataDir, { recursive: true });\n}\n"],"mappings":";AAAA,OAAO,QAAQ;AACf,OAAO,QAAQ;AACf,OAAO,UAAU;AAEjB,SAAS,iBAAyB;AAChC,UAAQ,QAAQ,UAAU;AAAA,IACxB,KAAK;AACH,aAAO,KAAK;AAAA,QACV,GAAG,QAAQ;AAAA,QACX;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,IACF,KAAK;AACH,aAAO,KAAK;AAAA,QACV,QAAQ,IAAI,WAAW,KAAK,KAAK,GAAG,QAAQ,GAAG,WAAW,SAAS;AAAA,QACnE;AAAA,MACF;AAAA,IACF;AACE,aAAO,KAAK,KAAK,GAAG,QAAQ,GAAG,UAAU,SAAS,YAAY;AAAA,EAClE;AACF;AAEA,SAAS,iBAAyB;AAChC,MAAI,QAAQ,IAAI,oBAAqB,QAAO,QAAQ,IAAI;AACxD,SAAO,eAAe;AACxB;AAEA,IAAM,WAAW,eAAe;AAEhC,IAAM,aAAa,KAAK,KAAK,GAAG,QAAQ,GAAG,SAAS;AACpD,IAAM,kBAAkB,KAAK;AAAA,EAC3B,GAAG,QAAQ;AAAA,EACX;AAAA,EACA;AAAA,EACA;AACF;AAEA,IAAM,eAAe;AAEd,IAAM,SAAS;AAAA,EACpB,SAAS;AAAA,EACT,QAAQ,KAAK,KAAK,UAAU,eAAe;AAAA;AAAA,EAE3C,MAAM;AAAA,IACJ,QAAQ,IAAI,mBACV,QAAQ,IAAI,wBACZ,OAAO,YAAY;AAAA,IACrB;AAAA,EACF;AAAA,EACA,MAAM,QAAQ,IAAI,mBAAmB;AAAA,EACrC,eAAe,KAAK,KAAK,UAAU,gBAAgB;AAAA;AAAA,EAEnD,SAAS,KAAK,KAAK,UAAU,mBAAmB;AAAA,EAChD,UAAU,SAAS,QAAQ,IAAI,wBAAwB,QAAQ,EAAE;AAAA,EACjE,UAAU,QAAQ,IAAI,wBAAwB;AAAA,EAC9C,gBAAgB;AAAA,EAChB,qBAAqB,KAAK;AAAA,IACxB;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAAA,EACA,gBAAgB,KAAK;AAAA,IACnB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAAA,EACA,WAAW,SAAS,QAAQ,IAAI,yBAAyB,QAAQ,EAAE;AAAA,EACnE,WAAW,QAAQ,IAAI,yBAAyB;AAAA,EAChD,cAAc,KAAK,KAAK,UAAU,WAAW;AAAA,EAC7C,oBAAoB,KAAK,KAAK;AAChC;AAEO,SAAS,gBAAsB;AACpC,KAAG,UAAU,OAAO,SAAS,EAAE,WAAW,KAAK,CAAC;AAClD;","names":[]}
@@ -0,0 +1,130 @@
1
+ import {
2
+ refreshPricing
3
+ } from "./chunk-3TZAKV3M.js";
4
+ import {
5
+ allTargets
6
+ } from "./chunk-QVK6VGCV.js";
7
+ import {
8
+ closeDb,
9
+ getDb
10
+ } from "./chunk-DZ5HJFB4.js";
11
+ import {
12
+ config,
13
+ ensureDataDir
14
+ } from "./chunk-K7YUPLES.js";
15
+
16
+ // src/setup.ts
17
+ import fs from "fs";
18
+ import os from "os";
19
+ import path from "path";
20
+ function initDb() {
21
+ ensureDataDir();
22
+ getDb();
23
+ closeDb();
24
+ }
25
+ async function fetchPricing() {
26
+ const result = await refreshPricing();
27
+ return result ? Object.keys(result.models).length : null;
28
+ }
29
+ function configureShellEnv(opts = {}) {
30
+ const force = opts.force ?? false;
31
+ const target = opts.target ?? "claude";
32
+ const proxy = opts.proxy ?? false;
33
+ const shellRc = path.join(
34
+ os.homedir(),
35
+ process.env.SHELL?.includes("zsh") ? ".zshrc" : ".bashrc"
36
+ );
37
+ const rcContent = fs.existsSync(shellRc) ? fs.readFileSync(shellRc, "utf-8") : "";
38
+ const allTargetVarNames = /* @__PURE__ */ new Set();
39
+ for (const v of allTargets()) {
40
+ for (const [varName] of v.shellEnv.envVars(config.port, true)) {
41
+ allTargetVarNames.add(varName);
42
+ }
43
+ }
44
+ const PANOPTICON_VARS = [
45
+ "OTEL_EXPORTER_OTLP_ENDPOINT",
46
+ "OTEL_EXPORTER_OTLP_PROTOCOL",
47
+ "OTEL_METRICS_EXPORTER",
48
+ "OTEL_LOGS_EXPORTER",
49
+ "OTEL_LOG_TOOL_DETAILS",
50
+ "OTEL_LOG_USER_PROMPTS",
51
+ "OTEL_METRIC_EXPORT_INTERVAL",
52
+ ...allTargetVarNames
53
+ ];
54
+ const PANOPTICON_COMMENTS = ["# >>> panopticon", "# <<< panopticon"];
55
+ const isPanopticonLine = (line) => {
56
+ const trimmed = line.trim();
57
+ if (PANOPTICON_COMMENTS.some((c) => trimmed.startsWith(c))) return true;
58
+ for (const v of PANOPTICON_VARS) {
59
+ if (trimmed === `export ${v}` || trimmed.startsWith(`export ${v}=`))
60
+ return true;
61
+ }
62
+ return false;
63
+ };
64
+ const wantedLines = [
65
+ ["# >>> panopticon >>>", "# >>> panopticon >>>"],
66
+ [
67
+ "OTEL_EXPORTER_OTLP_ENDPOINT",
68
+ `export OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:${config.port}`
69
+ ],
70
+ [
71
+ "OTEL_EXPORTER_OTLP_PROTOCOL",
72
+ "export OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf"
73
+ ],
74
+ ["OTEL_METRICS_EXPORTER", "export OTEL_METRICS_EXPORTER=otlp"],
75
+ ["OTEL_LOGS_EXPORTER", "export OTEL_LOGS_EXPORTER=otlp"],
76
+ ["OTEL_LOG_TOOL_DETAILS", "export OTEL_LOG_TOOL_DETAILS=1"],
77
+ ["OTEL_LOG_USER_PROMPTS", "export OTEL_LOG_USER_PROMPTS=1"],
78
+ ["OTEL_METRIC_EXPORT_INTERVAL", "export OTEL_METRIC_EXPORT_INTERVAL=10000"]
79
+ ];
80
+ const selectedTargetList = target === "all" ? allTargets() : allTargets().filter((v) => v.id === target);
81
+ for (const t of selectedTargetList) {
82
+ for (const [varName, value] of t.shellEnv.envVars(config.port, proxy)) {
83
+ wantedLines.push([varName, `export ${varName}=${value}`]);
84
+ }
85
+ }
86
+ wantedLines.push(["# <<< panopticon <<<", "# <<< panopticon <<<"]);
87
+ if (!rcContent.includes(".local/bin")) {
88
+ wantedLines.splice(1, 0, [
89
+ "PATH_LOCAL_BIN",
90
+ 'export PATH="$HOME/.local/bin:$PATH"'
91
+ ]);
92
+ }
93
+ const lines = rcContent.split("\n");
94
+ const seen = /* @__PURE__ */ new Set();
95
+ let lastPanopticonIdx = -1;
96
+ for (let i = 0; i < lines.length; i++) {
97
+ if (!isPanopticonLine(lines[i])) continue;
98
+ lastPanopticonIdx = i;
99
+ const match = wantedLines.find(([key]) => {
100
+ if (key.startsWith("#")) return lines[i].trim().startsWith(key);
101
+ return lines[i].trim() === `export ${key}` || lines[i].trim().startsWith(`export ${key}=`);
102
+ });
103
+ if (match) {
104
+ if (!force && lines[i].trim() !== match[1] && !match[0].startsWith("#")) {
105
+ } else {
106
+ lines[i] = match[1];
107
+ }
108
+ seen.add(match[0]);
109
+ } else {
110
+ lines[i] = "";
111
+ }
112
+ }
113
+ const newLines = wantedLines.filter(([key]) => !seen.has(key)).map(([, val]) => val);
114
+ if (newLines.length > 0) {
115
+ if (lastPanopticonIdx >= 0) {
116
+ lines.splice(lastPanopticonIdx + 1, 0, ...newLines);
117
+ } else {
118
+ lines.push("", ...newLines, "");
119
+ }
120
+ }
121
+ fs.writeFileSync(shellRc, lines.join("\n"));
122
+ return shellRc;
123
+ }
124
+
125
+ export {
126
+ initDb,
127
+ fetchPricing,
128
+ configureShellEnv
129
+ };
130
+ //# sourceMappingURL=chunk-L7G27XWF.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/setup.ts"],"sourcesContent":["/**\n * Setup/install utilities for external consumers.\n *\n * Extracted from cli.ts so fml-plugin (and other integrators) can run\n * panopticon setup steps without shelling out to the panopticon CLI.\n */\n\nimport fs from \"node:fs\";\nimport os from \"node:os\";\nimport path from \"node:path\";\nimport { config, ensureDataDir } from \"./config.js\";\nimport { refreshPricing } from \"./db/pricing.js\";\nimport { closeDb, getDb } from \"./db/schema.js\";\nimport { allTargets } from \"./targets/index.js\";\n\n/**\n * Initialize the panopticon database — creates the data directory,\n * schema, indexes, and runs migrations.\n */\nexport function initDb(): void {\n ensureDataDir();\n getDb();\n closeDb();\n}\n\n/**\n * Fetch model pricing from LiteLLM and cache locally.\n * Returns the number of models cached, or null if the fetch failed.\n */\nexport async function fetchPricing(): Promise<number | null> {\n const result = await refreshPricing();\n return result ? Object.keys(result.models).length : null;\n}\n\nexport interface ShellEnvOptions {\n /** Overwrite user-customized env vars (default false) */\n force?: boolean;\n /** Target CLI target id or \"all\" (default \"claude\") */\n target?: string;\n /** Also configure API proxy (default false) */\n proxy?: boolean;\n}\n\n/**\n * Configure shell environment variables (.zshrc / .bashrc) so that\n * coding tools send telemetry to panopticon.\n *\n * Returns the path to the shell rc file that was updated.\n */\nexport function configureShellEnv(opts: ShellEnvOptions = {}): string {\n const force = opts.force ?? false;\n const target = opts.target ?? \"claude\";\n const proxy = opts.proxy ?? false;\n\n const shellRc = path.join(\n os.homedir(),\n process.env.SHELL?.includes(\"zsh\") ? \".zshrc\" : \".bashrc\",\n );\n const rcContent = fs.existsSync(shellRc)\n ? fs.readFileSync(shellRc, \"utf-8\")\n : \"\";\n\n // Collect all known target env var names for detection/cleanup\n const allTargetVarNames = new Set<string>();\n for (const v of allTargets()) {\n for (const [varName] of v.shellEnv.envVars(config.port, true)) {\n allTargetVarNames.add(varName);\n }\n }\n\n const PANOPTICON_VARS = [\n \"OTEL_EXPORTER_OTLP_ENDPOINT\",\n \"OTEL_EXPORTER_OTLP_PROTOCOL\",\n \"OTEL_METRICS_EXPORTER\",\n \"OTEL_LOGS_EXPORTER\",\n \"OTEL_LOG_TOOL_DETAILS\",\n \"OTEL_LOG_USER_PROMPTS\",\n \"OTEL_METRIC_EXPORT_INTERVAL\",\n ...allTargetVarNames,\n ];\n const PANOPTICON_COMMENTS = [\"# >>> panopticon\", \"# <<< panopticon\"];\n\n const isPanopticonLine = (line: string): boolean => {\n const trimmed = line.trim();\n if (PANOPTICON_COMMENTS.some((c) => trimmed.startsWith(c))) return true;\n for (const v of PANOPTICON_VARS) {\n if (trimmed === `export ${v}` || trimmed.startsWith(`export ${v}=`))\n return true;\n }\n return false;\n };\n\n // Build the wanted env vars: shared OTEL vars + target-specific vars\n const wantedLines: [string, string][] = [\n [\"# >>> panopticon >>>\", \"# >>> panopticon >>>\"],\n [\n \"OTEL_EXPORTER_OTLP_ENDPOINT\",\n `export OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:${config.port}`,\n ],\n [\n \"OTEL_EXPORTER_OTLP_PROTOCOL\",\n \"export OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf\",\n ],\n [\"OTEL_METRICS_EXPORTER\", \"export OTEL_METRICS_EXPORTER=otlp\"],\n [\"OTEL_LOGS_EXPORTER\", \"export OTEL_LOGS_EXPORTER=otlp\"],\n [\"OTEL_LOG_TOOL_DETAILS\", \"export OTEL_LOG_TOOL_DETAILS=1\"],\n [\"OTEL_LOG_USER_PROMPTS\", \"export OTEL_LOG_USER_PROMPTS=1\"],\n [\"OTEL_METRIC_EXPORT_INTERVAL\", \"export OTEL_METRIC_EXPORT_INTERVAL=10000\"],\n ];\n\n // Add target-specific env vars for selected targets\n const selectedTargetList =\n target === \"all\"\n ? allTargets()\n : allTargets().filter((v) => v.id === target);\n\n for (const t of selectedTargetList) {\n for (const [varName, value] of t.shellEnv.envVars(config.port, proxy)) {\n wantedLines.push([varName, `export ${varName}=${value}`]);\n }\n }\n\n wantedLines.push([\"# <<< panopticon <<<\", \"# <<< panopticon <<<\"]);\n\n if (!rcContent.includes(\".local/bin\")) {\n wantedLines.splice(1, 0, [\n \"PATH_LOCAL_BIN\",\n 'export PATH=\"$HOME/.local/bin:$PATH\"',\n ]);\n }\n\n const lines = rcContent.split(\"\\n\");\n const seen = new Set<string>();\n let lastPanopticonIdx = -1;\n\n for (let i = 0; i < lines.length; i++) {\n if (!isPanopticonLine(lines[i])) continue;\n lastPanopticonIdx = i;\n\n const match = wantedLines.find(([key]) => {\n if (key.startsWith(\"#\")) return lines[i].trim().startsWith(key);\n return (\n lines[i].trim() === `export ${key}` ||\n lines[i].trim().startsWith(`export ${key}=`)\n );\n });\n if (match) {\n if (!force && lines[i].trim() !== match[1] && !match[0].startsWith(\"#\")) {\n // Keep user-customized value\n } else {\n lines[i] = match[1];\n }\n seen.add(match[0]);\n } else {\n lines[i] = \"\";\n }\n }\n\n const newLines = wantedLines\n .filter(([key]) => !seen.has(key))\n .map(([, val]) => val);\n\n if (newLines.length > 0) {\n if (lastPanopticonIdx >= 0) {\n lines.splice(lastPanopticonIdx + 1, 0, ...newLines);\n } else {\n lines.push(\"\", ...newLines, \"\");\n }\n }\n\n fs.writeFileSync(shellRc, lines.join(\"\\n\"));\n return shellRc;\n}\n\n// Re-export config for convenience (port, paths, etc.)\nexport { config } from \"./config.js\";\n"],"mappings":"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","names":[]}