panopticon-cli 0.4.8 → 0.4.9
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-54LDKMHR.js → agents-2Q6TCHNN.js} +4 -3
- package/dist/{chunk-VTDDVLCK.js → chunk-45PZFXJM.js} +21 -19
- package/dist/{chunk-VTDDVLCK.js.map → chunk-45PZFXJM.js.map} +1 -1
- package/dist/{chunk-PUR532O7.js → chunk-65DGYSS4.js} +5 -207
- package/dist/chunk-65DGYSS4.js.map +1 -0
- package/dist/chunk-BBCUK6N2.js +241 -0
- package/dist/chunk-BBCUK6N2.js.map +1 -0
- package/dist/{chunk-ZZ3477GY.js → chunk-NRPHRN6M.js} +26 -9
- package/dist/chunk-NRPHRN6M.js.map +1 -0
- package/dist/{chunk-Z24TY3XN.js → chunk-XTXWSLT3.js} +2 -2
- package/dist/{chunk-F7NQZD6H.js → chunk-YOQLBJ7B.js} +2 -2
- package/dist/{chunk-NYVQC3D7.js → chunk-ZAM2Q52Q.js} +9 -2
- package/dist/{chunk-NYVQC3D7.js.map → chunk-ZAM2Q52Q.js.map} +1 -1
- package/dist/cli/index.js +59 -45
- package/dist/cli/index.js.map +1 -1
- package/dist/config-WCEPLNXI.js +15 -0
- package/dist/dashboard/public/assets/{index-DPSUbu4A.js → index-BnjdXycj.js} +109 -109
- package/dist/dashboard/public/assets/{index-CRqsEkmn.css → index-iqMjcW09.css} +1 -1
- package/dist/dashboard/public/index.html +2 -2
- package/dist/dashboard/server.js +6529 -6407
- package/dist/index.d.ts +6 -1
- package/dist/index.js +5 -2
- package/dist/index.js.map +1 -1
- package/dist/{remote-workspace-HI4VML6H.js → remote-workspace-WZVEDYQA.js} +4 -4
- package/dist/{specialist-context-SNCJ7O7G.js → specialist-context-JO4RB7UC.js} +4 -3
- package/dist/{specialist-context-SNCJ7O7G.js.map → specialist-context-JO4RB7UC.js.map} +1 -1
- package/dist/{specialist-logs-A7ODEK2T.js → specialist-logs-7P5EUIUT.js} +4 -3
- package/dist/{specialists-C7XLNSXQ.js → specialists-B4QAT244.js} +4 -3
- package/dist/{traefik-WI3KSRGG.js → traefik-DRNZMPGZ.js} +3 -3
- package/dist/traefik-DRNZMPGZ.js.map +1 -0
- package/package.json +1 -1
- package/dist/chunk-PUR532O7.js.map +0 -1
- package/dist/chunk-ZZ3477GY.js.map +0 -1
- /package/dist/{agents-54LDKMHR.js.map → agents-2Q6TCHNN.js.map} +0 -0
- /package/dist/{chunk-Z24TY3XN.js.map → chunk-XTXWSLT3.js.map} +0 -0
- /package/dist/{chunk-F7NQZD6H.js.map → chunk-YOQLBJ7B.js.map} +0 -0
- /package/dist/{specialist-logs-A7ODEK2T.js.map → config-WCEPLNXI.js.map} +0 -0
- /package/dist/{remote-workspace-HI4VML6H.js.map → remote-workspace-WZVEDYQA.js.map} +0 -0
- /package/dist/{specialists-C7XLNSXQ.js.map → specialist-logs-7P5EUIUT.js.map} +0 -0
- /package/dist/{traefik-WI3KSRGG.js.map → specialists-B4QAT244.js.map} +0 -0
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
import {
|
|
2
|
+
__esm,
|
|
3
|
+
init_esm_shims
|
|
4
|
+
} from "./chunk-ZHC57RCV.js";
|
|
5
|
+
|
|
6
|
+
// src/lib/config-yaml.ts
|
|
7
|
+
import { readFileSync, existsSync } from "fs";
|
|
8
|
+
import { join } from "path";
|
|
9
|
+
import { homedir } from "os";
|
|
10
|
+
import yaml from "js-yaml";
|
|
11
|
+
function normalizeProviderConfig(providerConfig, fallbackKey) {
|
|
12
|
+
if (providerConfig === void 0) {
|
|
13
|
+
return { enabled: false };
|
|
14
|
+
}
|
|
15
|
+
if (typeof providerConfig === "boolean") {
|
|
16
|
+
return { enabled: providerConfig, api_key: fallbackKey };
|
|
17
|
+
}
|
|
18
|
+
return {
|
|
19
|
+
enabled: providerConfig.enabled,
|
|
20
|
+
api_key: providerConfig.api_key || fallbackKey
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
function resolveEnvVar(value) {
|
|
24
|
+
if (!value) return void 0;
|
|
25
|
+
return value.replace(/\$\{?([A-Z_][A-Z0-9_]*)\}?/g, (match, varName) => {
|
|
26
|
+
const envValue = process.env[varName];
|
|
27
|
+
return envValue !== void 0 ? envValue : match;
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
function loadYamlFile(filePath) {
|
|
31
|
+
if (!existsSync(filePath)) {
|
|
32
|
+
return null;
|
|
33
|
+
}
|
|
34
|
+
try {
|
|
35
|
+
const content = readFileSync(filePath, "utf-8");
|
|
36
|
+
const parsed = yaml.load(content);
|
|
37
|
+
return parsed || {};
|
|
38
|
+
} catch (error) {
|
|
39
|
+
console.error(`Error loading YAML config from ${filePath}:`, error);
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
function findProjectRoot(startDir = process.cwd()) {
|
|
44
|
+
let currentDir = startDir;
|
|
45
|
+
while (currentDir !== "/") {
|
|
46
|
+
if (existsSync(join(currentDir, ".git"))) {
|
|
47
|
+
return currentDir;
|
|
48
|
+
}
|
|
49
|
+
currentDir = join(currentDir, "..");
|
|
50
|
+
}
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
53
|
+
function loadProjectConfig() {
|
|
54
|
+
const projectRoot = findProjectRoot();
|
|
55
|
+
if (!projectRoot) {
|
|
56
|
+
return null;
|
|
57
|
+
}
|
|
58
|
+
const projectConfigPath = join(projectRoot, ".panopticon.yaml");
|
|
59
|
+
return loadYamlFile(projectConfigPath);
|
|
60
|
+
}
|
|
61
|
+
function loadGlobalConfig() {
|
|
62
|
+
return loadYamlFile(GLOBAL_CONFIG_PATH);
|
|
63
|
+
}
|
|
64
|
+
function mergeShadowConfig(result, config) {
|
|
65
|
+
if (!config?.shadow) return;
|
|
66
|
+
if (config.shadow.enabled !== void 0) {
|
|
67
|
+
result.enabled = config.shadow.enabled;
|
|
68
|
+
}
|
|
69
|
+
if (config.shadow.trackers) {
|
|
70
|
+
if (config.shadow.trackers.linear !== void 0) {
|
|
71
|
+
result.trackers.linear = config.shadow.trackers.linear;
|
|
72
|
+
}
|
|
73
|
+
if (config.shadow.trackers.github !== void 0) {
|
|
74
|
+
result.trackers.github = config.shadow.trackers.github;
|
|
75
|
+
}
|
|
76
|
+
if (config.shadow.trackers.gitlab !== void 0) {
|
|
77
|
+
result.trackers.gitlab = config.shadow.trackers.gitlab;
|
|
78
|
+
}
|
|
79
|
+
if (config.shadow.trackers.rally !== void 0) {
|
|
80
|
+
result.trackers.rally = config.shadow.trackers.rally;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
function mergeConfigs(...configs) {
|
|
85
|
+
const result = {
|
|
86
|
+
...DEFAULT_CONFIG,
|
|
87
|
+
enabledProviders: new Set(DEFAULT_CONFIG.enabledProviders),
|
|
88
|
+
shadow: {
|
|
89
|
+
enabled: DEFAULT_CONFIG.shadow.enabled,
|
|
90
|
+
trackers: { ...DEFAULT_CONFIG.shadow.trackers }
|
|
91
|
+
}
|
|
92
|
+
};
|
|
93
|
+
const validConfigs = configs.filter((c) => c !== null);
|
|
94
|
+
for (const config of validConfigs.reverse()) {
|
|
95
|
+
if (config.models?.providers) {
|
|
96
|
+
const providers = config.models.providers;
|
|
97
|
+
const legacyKeys = config.api_keys || {};
|
|
98
|
+
result.enabledProviders.add("anthropic");
|
|
99
|
+
const openai = normalizeProviderConfig(providers.openai, legacyKeys.openai);
|
|
100
|
+
if (openai.enabled) {
|
|
101
|
+
result.enabledProviders.add("openai");
|
|
102
|
+
if (openai.api_key) {
|
|
103
|
+
result.apiKeys.openai = resolveEnvVar(openai.api_key);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
const google = normalizeProviderConfig(providers.google, legacyKeys.google);
|
|
107
|
+
if (google.enabled) {
|
|
108
|
+
result.enabledProviders.add("google");
|
|
109
|
+
if (google.api_key) {
|
|
110
|
+
result.apiKeys.google = resolveEnvVar(google.api_key);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
const zai = normalizeProviderConfig(providers.zai, legacyKeys.zai);
|
|
114
|
+
if (zai.enabled) {
|
|
115
|
+
result.enabledProviders.add("zai");
|
|
116
|
+
if (zai.api_key) {
|
|
117
|
+
result.apiKeys.zai = resolveEnvVar(zai.api_key);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
const kimi = normalizeProviderConfig(providers.kimi, legacyKeys.kimi);
|
|
121
|
+
if (kimi.enabled) {
|
|
122
|
+
result.enabledProviders.add("kimi");
|
|
123
|
+
if (kimi.api_key) {
|
|
124
|
+
result.apiKeys.kimi = resolveEnvVar(kimi.api_key);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
if (config.api_keys) {
|
|
129
|
+
if (config.api_keys.openai) {
|
|
130
|
+
result.apiKeys.openai = resolveEnvVar(config.api_keys.openai);
|
|
131
|
+
result.enabledProviders.add("openai");
|
|
132
|
+
}
|
|
133
|
+
if (config.api_keys.google) {
|
|
134
|
+
result.apiKeys.google = resolveEnvVar(config.api_keys.google);
|
|
135
|
+
result.enabledProviders.add("google");
|
|
136
|
+
}
|
|
137
|
+
if (config.api_keys.zai) {
|
|
138
|
+
result.apiKeys.zai = resolveEnvVar(config.api_keys.zai);
|
|
139
|
+
result.enabledProviders.add("zai");
|
|
140
|
+
}
|
|
141
|
+
if (config.api_keys.kimi) {
|
|
142
|
+
result.apiKeys.kimi = resolveEnvVar(config.api_keys.kimi);
|
|
143
|
+
result.enabledProviders.add("kimi");
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
if (config.models?.overrides) {
|
|
147
|
+
result.overrides = {
|
|
148
|
+
...result.overrides,
|
|
149
|
+
...config.models.overrides
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
if (config.models?.gemini_thinking_level) {
|
|
153
|
+
result.geminiThinkingLevel = config.models.gemini_thinking_level;
|
|
154
|
+
}
|
|
155
|
+
if (config.tracker_keys) {
|
|
156
|
+
if (config.tracker_keys.linear) {
|
|
157
|
+
result.trackerKeys.linear = resolveEnvVar(config.tracker_keys.linear);
|
|
158
|
+
}
|
|
159
|
+
if (config.tracker_keys.github) {
|
|
160
|
+
result.trackerKeys.github = resolveEnvVar(config.tracker_keys.github);
|
|
161
|
+
}
|
|
162
|
+
if (config.tracker_keys.gitlab) {
|
|
163
|
+
result.trackerKeys.gitlab = resolveEnvVar(config.tracker_keys.gitlab);
|
|
164
|
+
}
|
|
165
|
+
if (config.tracker_keys.rally) {
|
|
166
|
+
result.trackerKeys.rally = resolveEnvVar(config.tracker_keys.rally);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
mergeShadowConfig(result.shadow, config);
|
|
170
|
+
}
|
|
171
|
+
return result;
|
|
172
|
+
}
|
|
173
|
+
function loadConfig() {
|
|
174
|
+
const globalConfig = loadGlobalConfig();
|
|
175
|
+
const projectConfig = loadProjectConfig();
|
|
176
|
+
const config = mergeConfigs(projectConfig, globalConfig);
|
|
177
|
+
if (process.env.OPENAI_API_KEY && !config.apiKeys.openai) {
|
|
178
|
+
config.apiKeys.openai = process.env.OPENAI_API_KEY;
|
|
179
|
+
config.enabledProviders.add("openai");
|
|
180
|
+
}
|
|
181
|
+
if (process.env.GOOGLE_API_KEY && !config.apiKeys.google) {
|
|
182
|
+
config.apiKeys.google = process.env.GOOGLE_API_KEY;
|
|
183
|
+
config.enabledProviders.add("google");
|
|
184
|
+
}
|
|
185
|
+
if (process.env.ZAI_API_KEY && !config.apiKeys.zai) {
|
|
186
|
+
config.apiKeys.zai = process.env.ZAI_API_KEY;
|
|
187
|
+
config.enabledProviders.add("zai");
|
|
188
|
+
}
|
|
189
|
+
if (process.env.KIMI_API_KEY && !config.apiKeys.kimi) {
|
|
190
|
+
config.apiKeys.kimi = process.env.KIMI_API_KEY;
|
|
191
|
+
config.enabledProviders.add("kimi");
|
|
192
|
+
}
|
|
193
|
+
if (process.env.LINEAR_API_KEY && !config.trackerKeys.linear) {
|
|
194
|
+
config.trackerKeys.linear = process.env.LINEAR_API_KEY;
|
|
195
|
+
}
|
|
196
|
+
if (process.env.GITHUB_TOKEN && !config.trackerKeys.github) {
|
|
197
|
+
config.trackerKeys.github = process.env.GITHUB_TOKEN;
|
|
198
|
+
}
|
|
199
|
+
if (process.env.GITLAB_TOKEN && !config.trackerKeys.gitlab) {
|
|
200
|
+
config.trackerKeys.gitlab = process.env.GITLAB_TOKEN;
|
|
201
|
+
}
|
|
202
|
+
if (process.env.RALLY_API_KEY && !config.trackerKeys.rally) {
|
|
203
|
+
config.trackerKeys.rally = process.env.RALLY_API_KEY;
|
|
204
|
+
}
|
|
205
|
+
if (process.env.SHADOW_MODE !== void 0) {
|
|
206
|
+
const envShadowMode = ["true", "1", "yes"].includes(process.env.SHADOW_MODE.toLowerCase());
|
|
207
|
+
config.shadow.enabled = envShadowMode;
|
|
208
|
+
}
|
|
209
|
+
return config;
|
|
210
|
+
}
|
|
211
|
+
var DEFAULT_CONFIG, GLOBAL_CONFIG_PATH;
|
|
212
|
+
var init_config_yaml = __esm({
|
|
213
|
+
"src/lib/config-yaml.ts"() {
|
|
214
|
+
"use strict";
|
|
215
|
+
init_esm_shims();
|
|
216
|
+
DEFAULT_CONFIG = {
|
|
217
|
+
enabledProviders: /* @__PURE__ */ new Set(["anthropic"]),
|
|
218
|
+
// Only Anthropic by default
|
|
219
|
+
apiKeys: {},
|
|
220
|
+
overrides: {},
|
|
221
|
+
geminiThinkingLevel: 3,
|
|
222
|
+
trackerKeys: {},
|
|
223
|
+
shadow: {
|
|
224
|
+
enabled: false,
|
|
225
|
+
trackers: {
|
|
226
|
+
linear: false,
|
|
227
|
+
github: false,
|
|
228
|
+
gitlab: false,
|
|
229
|
+
rally: false
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
};
|
|
233
|
+
GLOBAL_CONFIG_PATH = join(homedir(), ".panopticon", "config.yaml");
|
|
234
|
+
}
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
export {
|
|
238
|
+
loadConfig,
|
|
239
|
+
init_config_yaml
|
|
240
|
+
};
|
|
241
|
+
//# sourceMappingURL=chunk-BBCUK6N2.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/lib/config-yaml.ts"],"sourcesContent":["/**\n * YAML Configuration Loader\n *\n * Loads and merges configuration from:\n * 1. Global config: ~/.panopticon/config.yaml\n * 2. Per-project config: .panopticon.yaml (project root)\n *\n * Uses smart (capability-based) model selection - no legacy presets.\n */\n\nimport { readFileSync, existsSync } from 'fs';\nimport { join } from 'path';\nimport { homedir } from 'os';\nimport yaml from 'js-yaml';\nimport { WorkTypeId } from './work-types.js';\nimport { ModelId } from './settings.js';\nimport { ModelProvider } from './model-fallback.js';\n\n/**\n * Provider configuration (enable/disable + API keys)\n */\nexport interface ProviderConfig {\n /** Whether this provider is enabled */\n enabled: boolean;\n /** API key (optional, can use env var) */\n api_key?: string;\n}\n\n/**\n * Shadow mode configuration\n */\nexport interface ShadowConfig {\n /** Global shadow mode default */\n enabled?: boolean;\n\n /** Per-tracker overrides */\n trackers?: {\n linear?: boolean;\n github?: boolean;\n gitlab?: boolean;\n rally?: boolean;\n };\n}\n\n/**\n * Complete configuration structure (YAML schema)\n */\nexport interface YamlConfig {\n /** Model configuration */\n models?: {\n /** Provider enable/disable and API keys */\n providers?: {\n anthropic?: ProviderConfig | boolean;\n openai?: ProviderConfig | boolean;\n google?: ProviderConfig | boolean;\n zai?: ProviderConfig | boolean;\n kimi?: ProviderConfig | boolean;\n };\n\n /** Per-work-type overrides (explicit model for specific tasks) */\n overrides?: Partial<Record<WorkTypeId, ModelId>>;\n\n /** Gemini thinking level (1-4) */\n gemini_thinking_level?: 1 | 2 | 3 | 4;\n };\n\n /** Legacy API keys (for backward compatibility) */\n api_keys?: {\n openai?: string;\n google?: string;\n zai?: string;\n kimi?: string;\n };\n\n /** Tracker API keys (override environment variables) */\n tracker_keys?: {\n linear?: string;\n github?: string;\n gitlab?: string;\n rally?: string;\n };\n\n /** Shadow mode configuration */\n shadow?: ShadowConfig;\n}\n\n/**\n * Normalized shadow configuration\n */\nexport interface NormalizedShadowConfig {\n /** Global shadow mode enabled */\n enabled: boolean;\n\n /** Per-tracker overrides */\n trackers: {\n linear: boolean;\n github: boolean;\n gitlab: boolean;\n rally: boolean;\n };\n}\n\n/**\n * Normalized configuration (after loading and merging)\n */\nexport interface NormalizedConfig {\n /** Enabled providers */\n enabledProviders: Set<ModelProvider>;\n\n /** API keys by provider */\n apiKeys: {\n openai?: string;\n google?: string;\n zai?: string;\n kimi?: string;\n };\n\n /** Per-work-type overrides */\n overrides: Partial<Record<WorkTypeId, ModelId>>;\n\n /** Gemini thinking level */\n geminiThinkingLevel: 1 | 2 | 3 | 4;\n\n /** Tracker API keys */\n trackerKeys: {\n linear?: string;\n github?: string;\n gitlab?: string;\n rally?: string;\n };\n\n /** Shadow mode configuration */\n shadow: NormalizedShadowConfig;\n}\n\n/**\n * Default configuration (used when no config files exist)\n */\nconst DEFAULT_CONFIG: NormalizedConfig = {\n enabledProviders: new Set(['anthropic']), // Only Anthropic by default\n apiKeys: {},\n overrides: {},\n geminiThinkingLevel: 3,\n trackerKeys: {},\n shadow: {\n enabled: false,\n trackers: {\n linear: false,\n github: false,\n gitlab: false,\n rally: false,\n },\n },\n};\n\n/**\n * Path to global config file\n */\nconst GLOBAL_CONFIG_PATH = join(homedir(), '.panopticon', 'config.yaml');\n\n/**\n * Normalize a provider config (handle both boolean and object forms)\n */\nfunction normalizeProviderConfig(\n providerConfig: ProviderConfig | boolean | undefined,\n fallbackKey?: string\n): { enabled: boolean; api_key?: string } {\n if (providerConfig === undefined) {\n return { enabled: false };\n }\n\n if (typeof providerConfig === 'boolean') {\n return { enabled: providerConfig, api_key: fallbackKey };\n }\n\n return {\n enabled: providerConfig.enabled,\n api_key: providerConfig.api_key || fallbackKey,\n };\n}\n\n/**\n * Resolve environment variables in config values.\n * If the env var is not set, returns the original reference (e.g., \"$OPENAI_API_KEY\")\n * so the UI can show that it's configured via env var but not resolved.\n */\nfunction resolveEnvVar(value: string | undefined): string | undefined {\n if (!value) return undefined;\n\n // Replace $VAR_NAME or ${VAR_NAME} with environment variable\n // If env var is not set, keep the original reference\n return value.replace(/\\$\\{?([A-Z_][A-Z0-9_]*)\\}?/g, (match, varName) => {\n const envValue = process.env[varName];\n return envValue !== undefined ? envValue : match; // Keep $VAR_NAME if not set\n });\n}\n\n/**\n * Load and parse a YAML config file\n */\nfunction loadYamlFile(filePath: string): YamlConfig | null {\n if (!existsSync(filePath)) {\n return null;\n }\n\n try {\n const content = readFileSync(filePath, 'utf-8');\n const parsed = yaml.load(content) as YamlConfig;\n return parsed || {};\n } catch (error) {\n console.error(`Error loading YAML config from ${filePath}:`, error);\n return null;\n }\n}\n\n/**\n * Find project root by looking for .git directory\n */\nfunction findProjectRoot(startDir: string = process.cwd()): string | null {\n let currentDir = startDir;\n\n while (currentDir !== '/') {\n if (existsSync(join(currentDir, '.git'))) {\n return currentDir;\n }\n currentDir = join(currentDir, '..');\n }\n\n return null;\n}\n\n/**\n * Load per-project config (.panopticon.yaml in project root)\n */\nfunction loadProjectConfig(): YamlConfig | null {\n const projectRoot = findProjectRoot();\n if (!projectRoot) {\n return null;\n }\n\n const projectConfigPath = join(projectRoot, '.panopticon.yaml');\n return loadYamlFile(projectConfigPath);\n}\n\n/**\n * Load global config (~/.panopticon/config.yaml)\n */\nfunction loadGlobalConfig(): YamlConfig | null {\n return loadYamlFile(GLOBAL_CONFIG_PATH);\n}\n\n/**\n * Merge shadow configuration from multiple sources\n */\nfunction mergeShadowConfig(\n result: NormalizedShadowConfig,\n config: YamlConfig | null\n): void {\n if (!config?.shadow) return;\n\n // Merge global enabled flag\n if (config.shadow.enabled !== undefined) {\n result.enabled = config.shadow.enabled;\n }\n\n // Merge per-tracker overrides\n if (config.shadow.trackers) {\n if (config.shadow.trackers.linear !== undefined) {\n result.trackers.linear = config.shadow.trackers.linear;\n }\n if (config.shadow.trackers.github !== undefined) {\n result.trackers.github = config.shadow.trackers.github;\n }\n if (config.shadow.trackers.gitlab !== undefined) {\n result.trackers.gitlab = config.shadow.trackers.gitlab;\n }\n if (config.shadow.trackers.rally !== undefined) {\n result.trackers.rally = config.shadow.trackers.rally;\n }\n }\n}\n\n/**\n * Merge multiple configs with precedence: project > global > defaults\n */\nfunction mergeConfigs(...configs: (YamlConfig | null)[]): NormalizedConfig {\n const result: NormalizedConfig = {\n ...DEFAULT_CONFIG,\n enabledProviders: new Set(DEFAULT_CONFIG.enabledProviders),\n shadow: {\n enabled: DEFAULT_CONFIG.shadow.enabled,\n trackers: { ...DEFAULT_CONFIG.shadow.trackers },\n },\n };\n\n // Filter out null configs\n const validConfigs = configs.filter((c): c is YamlConfig => c !== null);\n\n // Merge in reverse order (lowest precedence first)\n for (const config of validConfigs.reverse()) {\n // Merge providers\n if (config.models?.providers) {\n const providers = config.models.providers;\n const legacyKeys = config.api_keys || {};\n\n // Anthropic (always enabled)\n result.enabledProviders.add('anthropic');\n\n // OpenAI\n const openai = normalizeProviderConfig(providers.openai, legacyKeys.openai);\n if (openai.enabled) {\n result.enabledProviders.add('openai');\n if (openai.api_key) {\n result.apiKeys.openai = resolveEnvVar(openai.api_key);\n }\n }\n\n // Google\n const google = normalizeProviderConfig(providers.google, legacyKeys.google);\n if (google.enabled) {\n result.enabledProviders.add('google');\n if (google.api_key) {\n result.apiKeys.google = resolveEnvVar(google.api_key);\n }\n }\n\n // Z.AI\n const zai = normalizeProviderConfig(providers.zai, legacyKeys.zai);\n if (zai.enabled) {\n result.enabledProviders.add('zai');\n if (zai.api_key) {\n result.apiKeys.zai = resolveEnvVar(zai.api_key);\n }\n }\n\n // Kimi\n const kimi = normalizeProviderConfig(providers.kimi, legacyKeys.kimi);\n if (kimi.enabled) {\n result.enabledProviders.add('kimi');\n if (kimi.api_key) {\n result.apiKeys.kimi = resolveEnvVar(kimi.api_key);\n }\n }\n }\n\n // Merge legacy API keys (for backward compatibility)\n if (config.api_keys) {\n if (config.api_keys.openai) {\n result.apiKeys.openai = resolveEnvVar(config.api_keys.openai);\n result.enabledProviders.add('openai');\n }\n if (config.api_keys.google) {\n result.apiKeys.google = resolveEnvVar(config.api_keys.google);\n result.enabledProviders.add('google');\n }\n if (config.api_keys.zai) {\n result.apiKeys.zai = resolveEnvVar(config.api_keys.zai);\n result.enabledProviders.add('zai');\n }\n if (config.api_keys.kimi) {\n result.apiKeys.kimi = resolveEnvVar(config.api_keys.kimi);\n result.enabledProviders.add('kimi');\n }\n }\n\n // Merge overrides\n if (config.models?.overrides) {\n result.overrides = {\n ...result.overrides,\n ...config.models.overrides,\n };\n }\n\n // Merge Gemini thinking level\n if (config.models?.gemini_thinking_level) {\n result.geminiThinkingLevel = config.models.gemini_thinking_level;\n }\n\n // Merge tracker keys\n if (config.tracker_keys) {\n if (config.tracker_keys.linear) {\n result.trackerKeys.linear = resolveEnvVar(config.tracker_keys.linear);\n }\n if (config.tracker_keys.github) {\n result.trackerKeys.github = resolveEnvVar(config.tracker_keys.github);\n }\n if (config.tracker_keys.gitlab) {\n result.trackerKeys.gitlab = resolveEnvVar(config.tracker_keys.gitlab);\n }\n if (config.tracker_keys.rally) {\n result.trackerKeys.rally = resolveEnvVar(config.tracker_keys.rally);\n }\n }\n\n // Merge shadow configuration\n mergeShadowConfig(result.shadow, config);\n }\n\n return result;\n}\n\n/**\n * Load complete configuration (global + project + defaults)\n * Also loads API keys from environment variables as fallback\n */\nexport function loadConfig(): NormalizedConfig {\n const globalConfig = loadGlobalConfig();\n const projectConfig = loadProjectConfig();\n const config = mergeConfigs(projectConfig, globalConfig);\n\n // Load API keys from environment variables as fallback\n // This allows using ~/.panopticon.env for API keys\n if (process.env.OPENAI_API_KEY && !config.apiKeys.openai) {\n config.apiKeys.openai = process.env.OPENAI_API_KEY;\n config.enabledProviders.add('openai');\n }\n if (process.env.GOOGLE_API_KEY && !config.apiKeys.google) {\n config.apiKeys.google = process.env.GOOGLE_API_KEY;\n config.enabledProviders.add('google');\n }\n if (process.env.ZAI_API_KEY && !config.apiKeys.zai) {\n config.apiKeys.zai = process.env.ZAI_API_KEY;\n config.enabledProviders.add('zai');\n }\n if (process.env.KIMI_API_KEY && !config.apiKeys.kimi) {\n config.apiKeys.kimi = process.env.KIMI_API_KEY;\n config.enabledProviders.add('kimi');\n }\n\n // Load tracker API keys from environment variables as fallback\n if (process.env.LINEAR_API_KEY && !config.trackerKeys.linear) {\n config.trackerKeys.linear = process.env.LINEAR_API_KEY;\n }\n if (process.env.GITHUB_TOKEN && !config.trackerKeys.github) {\n config.trackerKeys.github = process.env.GITHUB_TOKEN;\n }\n if (process.env.GITLAB_TOKEN && !config.trackerKeys.gitlab) {\n config.trackerKeys.gitlab = process.env.GITLAB_TOKEN;\n }\n if (process.env.RALLY_API_KEY && !config.trackerKeys.rally) {\n config.trackerKeys.rally = process.env.RALLY_API_KEY;\n }\n\n // Load shadow mode from environment as fallback\n // Environment variable takes precedence over config file\n if (process.env.SHADOW_MODE !== undefined) {\n const envShadowMode = ['true', '1', 'yes'].includes(process.env.SHADOW_MODE.toLowerCase());\n config.shadow.enabled = envShadowMode;\n }\n\n return config;\n}\n\n/**\n * Check if a project-level config exists\n */\nexport function hasProjectConfig(): boolean {\n const projectRoot = findProjectRoot();\n if (!projectRoot) return false;\n return existsSync(join(projectRoot, '.panopticon.yaml'));\n}\n\n/**\n * Check if global config exists\n */\nexport function hasGlobalConfig(): boolean {\n return existsSync(GLOBAL_CONFIG_PATH);\n}\n\n/**\n * Get path to global config file\n */\nexport function getGlobalConfigPath(): string {\n return GLOBAL_CONFIG_PATH;\n}\n\n/**\n * Get path to project config file (null if not in a project)\n */\nexport function getProjectConfigPath(): string | null {\n const projectRoot = findProjectRoot();\n if (!projectRoot) return null;\n return join(projectRoot, '.panopticon.yaml');\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
import {
|
|
2
|
+
init_config_yaml,
|
|
3
|
+
loadConfig
|
|
4
|
+
} from "./chunk-BBCUK6N2.js";
|
|
1
5
|
import {
|
|
2
6
|
AGENTS_DIR,
|
|
3
7
|
BACKUPS_DIR,
|
|
@@ -1296,24 +1300,35 @@ var RallyTracker = class {
|
|
|
1296
1300
|
};
|
|
1297
1301
|
|
|
1298
1302
|
// src/lib/tracker/factory.ts
|
|
1303
|
+
init_config_yaml();
|
|
1304
|
+
function getTrackerKeyFromConfig(trackerType) {
|
|
1305
|
+
try {
|
|
1306
|
+
const yamlConfig = loadConfig();
|
|
1307
|
+
return yamlConfig.trackerKeys[trackerType];
|
|
1308
|
+
} catch {
|
|
1309
|
+
return void 0;
|
|
1310
|
+
}
|
|
1311
|
+
}
|
|
1299
1312
|
function createTracker(config) {
|
|
1300
1313
|
switch (config.type) {
|
|
1301
1314
|
case "linear": {
|
|
1302
|
-
const
|
|
1315
|
+
const envKey = config.apiKeyEnv ? process.env[config.apiKeyEnv] : process.env.LINEAR_API_KEY;
|
|
1316
|
+
const apiKey = envKey || getTrackerKeyFromConfig("linear");
|
|
1303
1317
|
if (!apiKey) {
|
|
1304
1318
|
throw new TrackerAuthError(
|
|
1305
1319
|
"linear",
|
|
1306
|
-
`API key not found. Set ${config.apiKeyEnv ?? "LINEAR_API_KEY"} environment variable.`
|
|
1320
|
+
`API key not found. Set ${config.apiKeyEnv ?? "LINEAR_API_KEY"} environment variable or configure in Settings.`
|
|
1307
1321
|
);
|
|
1308
1322
|
}
|
|
1309
1323
|
return new LinearTracker(apiKey, { team: config.team });
|
|
1310
1324
|
}
|
|
1311
1325
|
case "github": {
|
|
1312
|
-
const
|
|
1326
|
+
const envToken = config.tokenEnv ? process.env[config.tokenEnv] : process.env.GITHUB_TOKEN;
|
|
1327
|
+
const token = envToken || getTrackerKeyFromConfig("github");
|
|
1313
1328
|
if (!token) {
|
|
1314
1329
|
throw new TrackerAuthError(
|
|
1315
1330
|
"github",
|
|
1316
|
-
`Token not found. Set ${config.tokenEnv ?? "GITHUB_TOKEN"} environment variable.`
|
|
1331
|
+
`Token not found. Set ${config.tokenEnv ?? "GITHUB_TOKEN"} environment variable or configure in Settings.`
|
|
1317
1332
|
);
|
|
1318
1333
|
}
|
|
1319
1334
|
if (!config.owner || !config.repo) {
|
|
@@ -1324,11 +1339,12 @@ function createTracker(config) {
|
|
|
1324
1339
|
return new GitHubTracker(token, config.owner, config.repo);
|
|
1325
1340
|
}
|
|
1326
1341
|
case "gitlab": {
|
|
1327
|
-
const
|
|
1342
|
+
const envToken = config.tokenEnv ? process.env[config.tokenEnv] : process.env.GITLAB_TOKEN;
|
|
1343
|
+
const token = envToken || getTrackerKeyFromConfig("gitlab");
|
|
1328
1344
|
if (!token) {
|
|
1329
1345
|
throw new TrackerAuthError(
|
|
1330
1346
|
"gitlab",
|
|
1331
|
-
`Token not found. Set ${config.tokenEnv ?? "GITLAB_TOKEN"} environment variable.`
|
|
1347
|
+
`Token not found. Set ${config.tokenEnv ?? "GITLAB_TOKEN"} environment variable or configure in Settings.`
|
|
1332
1348
|
);
|
|
1333
1349
|
}
|
|
1334
1350
|
if (!config.projectId) {
|
|
@@ -1337,11 +1353,12 @@ function createTracker(config) {
|
|
|
1337
1353
|
return new GitLabTracker(token, config.projectId);
|
|
1338
1354
|
}
|
|
1339
1355
|
case "rally": {
|
|
1340
|
-
const
|
|
1356
|
+
const envKey = config.apiKeyEnv ? process.env[config.apiKeyEnv] : process.env.RALLY_API_KEY;
|
|
1357
|
+
const apiKey = envKey || getTrackerKeyFromConfig("rally");
|
|
1341
1358
|
if (!apiKey) {
|
|
1342
1359
|
throw new TrackerAuthError(
|
|
1343
1360
|
"rally",
|
|
1344
|
-
`API key not found. Set ${config.apiKeyEnv ?? "RALLY_API_KEY"} environment variable.`
|
|
1361
|
+
`API key not found. Set ${config.apiKeyEnv ?? "RALLY_API_KEY"} environment variable or configure in Settings.`
|
|
1345
1362
|
);
|
|
1346
1363
|
}
|
|
1347
1364
|
return new RallyTracker({
|
|
@@ -1559,4 +1576,4 @@ export {
|
|
|
1559
1576
|
LinkManager,
|
|
1560
1577
|
getLinkManager
|
|
1561
1578
|
};
|
|
1562
|
-
//# sourceMappingURL=chunk-
|
|
1579
|
+
//# sourceMappingURL=chunk-NRPHRN6M.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/lib/shell.ts","../src/lib/backup.ts","../src/lib/sync.ts","../src/lib/tracker/interface.ts","../src/lib/tracker/linear.ts","../src/lib/tracker/github.ts","../src/lib/tracker/gitlab.ts","../src/lib/tracker/factory.ts","../src/lib/tracker/rally.ts","../src/lib/tracker/rally-api.ts","../src/lib/tracker/linking.ts","../src/lib/tracker/index.ts"],"sourcesContent":["import { existsSync, readFileSync, appendFileSync } from 'fs';\nimport { homedir } from 'os';\nimport { join } from 'path';\n\nexport type Shell = 'bash' | 'zsh' | 'fish' | 'unknown';\n\nexport function detectShell(): Shell {\n const shell = process.env.SHELL || '';\n\n if (shell.includes('zsh')) return 'zsh';\n if (shell.includes('bash')) return 'bash';\n if (shell.includes('fish')) return 'fish';\n\n return 'unknown';\n}\n\nexport function getShellRcFile(shell: Shell): string | null {\n const home = homedir();\n\n switch (shell) {\n case 'zsh':\n return join(home, '.zshrc');\n case 'bash':\n // Prefer .bashrc, fall back to .bash_profile\n const bashrc = join(home, '.bashrc');\n if (existsSync(bashrc)) return bashrc;\n return join(home, '.bash_profile');\n case 'fish':\n return join(home, '.config', 'fish', 'config.fish');\n default:\n return null;\n }\n}\n\nconst ALIAS_LINE = 'alias pan=\"panopticon\"';\nconst ALIAS_MARKER = '# Panopticon CLI alias';\n\nexport function hasAlias(rcFile: string): boolean {\n if (!existsSync(rcFile)) return false;\n\n const content = readFileSync(rcFile, 'utf8');\n return content.includes(ALIAS_MARKER) || content.includes(ALIAS_LINE);\n}\n\nexport function addAlias(rcFile: string): void {\n if (hasAlias(rcFile)) return;\n\n const aliasBlock = `\n${ALIAS_MARKER}\n${ALIAS_LINE}\n`;\n\n appendFileSync(rcFile, aliasBlock, 'utf8');\n}\n\nexport function getAliasInstructions(shell: Shell): string {\n const rcFile = getShellRcFile(shell);\n\n if (!rcFile) {\n return `Add this to your shell config:\\n ${ALIAS_LINE}`;\n }\n\n return `Alias added to ${rcFile}. Run:\\n source ${rcFile}`;\n}\n","import { existsSync, mkdirSync, readdirSync, cpSync, rmSync, lstatSync } from 'fs';\nimport { join, basename } from 'path';\nimport { BACKUPS_DIR } from './paths.js';\n\nexport interface BackupInfo {\n timestamp: string;\n path: string;\n targets: string[];\n}\n\nexport function createBackupTimestamp(): string {\n return new Date().toISOString().replace(/[:.]/g, '-');\n}\n\nexport function createBackup(sourceDirs: string[]): BackupInfo {\n const timestamp = createBackupTimestamp();\n const backupPath = join(BACKUPS_DIR, timestamp);\n\n mkdirSync(backupPath, { recursive: true });\n\n const targets: string[] = [];\n\n for (const sourceDir of sourceDirs) {\n if (!existsSync(sourceDir)) continue;\n\n const targetName = basename(sourceDir);\n const targetPath = join(backupPath, targetName);\n\n // Use filter to skip symlinks — sync targets (e.g. ~/.claude/skills/)\n // contain symlinks back into ~/.panopticon/skills/ which causes cpSync\n // to fail with \"cannot copy to a subdirectory of self\".\n cpSync(sourceDir, targetPath, {\n recursive: true,\n filter: (src) => !lstatSync(src).isSymbolicLink(),\n });\n targets.push(targetName);\n }\n\n return {\n timestamp,\n path: backupPath,\n targets,\n };\n}\n\nexport function listBackups(): BackupInfo[] {\n if (!existsSync(BACKUPS_DIR)) return [];\n\n const entries = readdirSync(BACKUPS_DIR, { withFileTypes: true });\n\n return entries\n .filter((e) => e.isDirectory())\n .map((e) => {\n const backupPath = join(BACKUPS_DIR, e.name);\n const contents = readdirSync(backupPath);\n\n return {\n timestamp: e.name,\n path: backupPath,\n targets: contents,\n };\n })\n .sort((a, b) => b.timestamp.localeCompare(a.timestamp));\n}\n\nexport function restoreBackup(timestamp: string, targetDirs: Record<string, string>): void {\n const backupPath = join(BACKUPS_DIR, timestamp);\n\n if (!existsSync(backupPath)) {\n throw new Error(`Backup not found: ${timestamp}`);\n }\n\n const contents = readdirSync(backupPath, { withFileTypes: true });\n\n for (const entry of contents) {\n if (!entry.isDirectory()) continue;\n\n const sourcePath = join(backupPath, entry.name);\n const targetPath = targetDirs[entry.name];\n\n if (!targetPath) continue;\n\n // Remove existing and restore from backup\n if (existsSync(targetPath)) {\n rmSync(targetPath, { recursive: true });\n }\n\n cpSync(sourcePath, targetPath, { recursive: true });\n }\n}\n\nexport function cleanOldBackups(keepCount: number = 10): number {\n const backups = listBackups();\n\n if (backups.length <= keepCount) return 0;\n\n const toRemove = backups.slice(keepCount);\n let removed = 0;\n\n for (const backup of toRemove) {\n rmSync(backup.path, { recursive: true });\n removed++;\n }\n\n return removed;\n}\n","import { existsSync, mkdirSync, readdirSync, symlinkSync, unlinkSync, lstatSync, readlinkSync, rmSync, copyFileSync, chmodSync } from 'fs';\nimport { join, basename } from 'path';\nimport { SKILLS_DIR, COMMANDS_DIR, AGENTS_DIR, BIN_DIR, SOURCE_SCRIPTS_DIR, SOURCE_DEV_SKILLS_DIR, SYNC_TARGETS, isDevMode, type Runtime } from './paths.js';\n\nexport interface SyncItem {\n name: string;\n sourcePath: string;\n targetPath: string;\n status: 'new' | 'exists' | 'conflict' | 'symlink';\n}\n\nexport interface SyncPlan {\n runtime: Runtime;\n skills: SyncItem[];\n commands: SyncItem[];\n agents: SyncItem[];\n devSkills: SyncItem[]; // Developer-only skills (only synced in dev mode)\n}\n\n/**\n * Remove a file, symlink, or directory safely\n */\nfunction removeTarget(targetPath: string): void {\n const stats = lstatSync(targetPath);\n if (stats.isDirectory() && !stats.isSymbolicLink()) {\n // It's a real directory, remove recursively\n rmSync(targetPath, { recursive: true, force: true });\n } else {\n // It's a file or symlink\n unlinkSync(targetPath);\n }\n}\n\n/**\n * Check if a path is a Panopticon-managed symlink\n */\nexport function isPanopticonSymlink(targetPath: string): boolean {\n if (!existsSync(targetPath)) return false;\n\n try {\n const stats = lstatSync(targetPath);\n if (!stats.isSymbolicLink()) return false;\n\n const linkTarget = readlinkSync(targetPath);\n // It's ours if it points to our skills/commands dir\n return linkTarget.includes('.panopticon');\n } catch {\n return false;\n }\n}\n\n/**\n * Plan what would be synced (dry run)\n */\nexport function planSync(runtime: Runtime): SyncPlan {\n const targets = SYNC_TARGETS[runtime];\n if (!targets) {\n throw new Error(`Unknown sync target \"${runtime}\". Valid targets: ${Object.keys(SYNC_TARGETS).join(', ')}`);\n }\n const plan: SyncPlan = {\n runtime,\n skills: [],\n commands: [],\n agents: [],\n devSkills: [],\n };\n\n // Plan skills sync\n if (existsSync(SKILLS_DIR)) {\n const skills = readdirSync(SKILLS_DIR, { withFileTypes: true })\n .filter((d) => d.isDirectory());\n\n for (const skill of skills) {\n const sourcePath = join(SKILLS_DIR, skill.name);\n const targetPath = join(targets.skills, skill.name);\n\n let status: SyncItem['status'] = 'new';\n\n if (existsSync(targetPath)) {\n if (isPanopticonSymlink(targetPath)) {\n status = 'symlink'; // Already managed by us\n } else {\n status = 'conflict'; // User content exists\n }\n }\n\n plan.skills.push({ name: skill.name, sourcePath, targetPath, status });\n }\n }\n\n // Plan dev-skills sync (only in dev mode)\n if (isDevMode() && existsSync(SOURCE_DEV_SKILLS_DIR)) {\n const devSkills = readdirSync(SOURCE_DEV_SKILLS_DIR, { withFileTypes: true })\n .filter((d) => d.isDirectory());\n\n for (const skill of devSkills) {\n const sourcePath = join(SOURCE_DEV_SKILLS_DIR, skill.name);\n const targetPath = join(targets.skills, skill.name);\n\n let status: SyncItem['status'] = 'new';\n\n if (existsSync(targetPath)) {\n if (isPanopticonSymlink(targetPath)) {\n status = 'symlink'; // Already managed by us\n } else {\n status = 'conflict'; // User content exists\n }\n }\n\n plan.devSkills.push({ name: skill.name, sourcePath, targetPath, status });\n }\n }\n\n // Plan commands sync\n if (existsSync(COMMANDS_DIR)) {\n const commands = readdirSync(COMMANDS_DIR, { withFileTypes: true })\n .filter((d) => d.isDirectory());\n\n for (const cmd of commands) {\n const sourcePath = join(COMMANDS_DIR, cmd.name);\n const targetPath = join(targets.commands, cmd.name);\n\n let status: SyncItem['status'] = 'new';\n\n if (existsSync(targetPath)) {\n if (isPanopticonSymlink(targetPath)) {\n status = 'symlink';\n } else {\n status = 'conflict';\n }\n }\n\n plan.commands.push({ name: cmd.name, sourcePath, targetPath, status });\n }\n }\n\n // Plan agents sync\n if (existsSync(AGENTS_DIR)) {\n const agents = readdirSync(AGENTS_DIR, { withFileTypes: true })\n .filter((entry) => entry.isFile() && entry.name.endsWith('.md'));\n\n for (const agent of agents) {\n const sourcePath = join(AGENTS_DIR, agent.name);\n const targetPath = join(targets.agents, agent.name);\n\n let status: SyncItem['status'] = 'new';\n\n if (existsSync(targetPath)) {\n if (isPanopticonSymlink(targetPath)) {\n status = 'symlink'; // Already managed by us\n } else {\n status = 'conflict'; // User content exists\n }\n }\n\n plan.agents.push({ name: agent.name, sourcePath, targetPath, status });\n }\n }\n\n return plan;\n}\n\nexport interface SyncOptions {\n force?: boolean;\n dryRun?: boolean;\n}\n\nexport interface SyncResult {\n created: string[];\n skipped: string[];\n conflicts: string[];\n}\n\n/**\n * Execute sync for a runtime\n */\nexport function executeSync(runtime: Runtime, options: SyncOptions = {}): SyncResult {\n const targets = SYNC_TARGETS[runtime];\n if (!targets) {\n throw new Error(`Unknown sync target \"${runtime}\". Valid targets: ${Object.keys(SYNC_TARGETS).join(', ')}`);\n }\n const plan = planSync(runtime);\n const result: SyncResult = {\n created: [],\n skipped: [],\n conflicts: [],\n };\n\n // Ensure target directories exist\n mkdirSync(targets.skills, { recursive: true });\n mkdirSync(targets.commands, { recursive: true });\n mkdirSync(targets.agents, { recursive: true });\n\n // Process skills\n for (const item of plan.skills) {\n if (options.dryRun) {\n if (item.status === 'new' || item.status === 'symlink') {\n result.created.push(item.name);\n } else {\n result.conflicts.push(item.name);\n }\n continue;\n }\n\n if (item.status === 'conflict' && !options.force) {\n result.conflicts.push(item.name);\n continue;\n }\n\n // Remove existing if force or if it's our symlink\n if (existsSync(item.targetPath)) {\n removeTarget(item.targetPath);\n }\n\n // Create symlink\n symlinkSync(item.sourcePath, item.targetPath);\n result.created.push(item.name);\n }\n\n // Process commands\n for (const item of plan.commands) {\n if (options.dryRun) {\n if (item.status === 'new' || item.status === 'symlink') {\n result.created.push(item.name);\n } else {\n result.conflicts.push(item.name);\n }\n continue;\n }\n\n if (item.status === 'conflict' && !options.force) {\n result.conflicts.push(item.name);\n continue;\n }\n\n if (existsSync(item.targetPath)) {\n removeTarget(item.targetPath);\n }\n\n symlinkSync(item.sourcePath, item.targetPath);\n result.created.push(item.name);\n }\n\n // Process agents\n for (const item of plan.agents) {\n if (options.dryRun) {\n if (item.status === 'new' || item.status === 'symlink') {\n result.created.push(item.name);\n } else {\n result.conflicts.push(item.name);\n }\n continue;\n }\n\n if (item.status === 'conflict' && !options.force) {\n result.conflicts.push(item.name);\n continue;\n }\n\n if (existsSync(item.targetPath)) {\n removeTarget(item.targetPath);\n }\n\n symlinkSync(item.sourcePath, item.targetPath);\n result.created.push(item.name);\n }\n\n // Process dev-skills (only in dev mode)\n for (const item of plan.devSkills) {\n if (options.dryRun) {\n if (item.status === 'new' || item.status === 'symlink') {\n result.created.push(`${item.name} (dev)`);\n } else {\n result.conflicts.push(`${item.name} (dev)`);\n }\n continue;\n }\n\n if (item.status === 'conflict' && !options.force) {\n result.conflicts.push(`${item.name} (dev)`);\n continue;\n }\n\n if (existsSync(item.targetPath)) {\n removeTarget(item.targetPath);\n }\n\n symlinkSync(item.sourcePath, item.targetPath);\n result.created.push(`${item.name} (dev)`);\n }\n\n return result;\n}\n\n/**\n * Hook item for sync planning\n */\nexport interface HookItem {\n name: string;\n sourcePath: string;\n targetPath: string;\n status: 'new' | 'updated' | 'current';\n}\n\n/**\n * Plan hooks sync (checks what would be updated)\n */\nexport function planHooksSync(): HookItem[] {\n const hooks: HookItem[] = [];\n\n if (!existsSync(SOURCE_SCRIPTS_DIR)) {\n return hooks;\n }\n\n // Only sync hook scripts (no extension) - skip helper scripts like .mjs, .sh\n const scripts = readdirSync(SOURCE_SCRIPTS_DIR, { withFileTypes: true })\n .filter((entry) => entry.isFile() && !entry.name.startsWith('.') && !entry.name.includes('.'));\n\n for (const script of scripts) {\n const sourcePath = join(SOURCE_SCRIPTS_DIR, script.name);\n const targetPath = join(BIN_DIR, script.name);\n\n let status: HookItem['status'] = 'new';\n\n if (existsSync(targetPath)) {\n // Could compare file contents/timestamps here for 'current' vs 'updated'\n // For now, always update to ensure latest version\n status = 'updated';\n }\n\n hooks.push({ name: script.name, sourcePath, targetPath, status });\n }\n\n return hooks;\n}\n\n/**\n * Sync hooks (copy scripts to ~/.panopticon/bin/)\n */\nexport function syncHooks(): { synced: string[]; errors: string[] } {\n const result = { synced: [] as string[], errors: [] as string[] };\n\n // Ensure bin directory exists\n mkdirSync(BIN_DIR, { recursive: true });\n\n const hooks = planHooksSync();\n\n for (const hook of hooks) {\n try {\n copyFileSync(hook.sourcePath, hook.targetPath);\n chmodSync(hook.targetPath, 0o755); // Make executable\n result.synced.push(hook.name);\n } catch (error) {\n result.errors.push(`${hook.name}: ${error}`);\n }\n }\n\n return result;\n}\n","/**\n * Issue Tracker Abstraction Layer\n *\n * Provides a unified interface for different issue tracking systems\n * (Linear, GitHub Issues, GitLab Issues, etc.)\n */\n\n// Supported tracker types\nexport type TrackerType = 'linear' | 'github' | 'gitlab' | 'rally';\n\n// Normalized issue state (lowest common denominator)\nexport type IssueState = 'open' | 'in_progress' | 'closed';\n\n// Normalized issue format\nexport interface Issue {\n /** Tracker-specific unique ID */\n id: string;\n\n /** Human-readable reference (e.g., MIN-630, #42) */\n ref: string;\n\n /** Issue title */\n title: string;\n\n /** Issue description/body (markdown) */\n description: string;\n\n /** Normalized state */\n state: IssueState;\n\n /** Labels/tags */\n labels: string[];\n\n /** Assignee username/name */\n assignee?: string;\n\n /** Web URL to the issue */\n url: string;\n\n /** Which tracker this issue came from */\n tracker: TrackerType;\n\n /** Cross-tracker linked issue references */\n linkedIssues?: string[];\n\n /** Priority (1=urgent, 2=high, 3=normal, 4=low) */\n priority?: number;\n\n /** Due date (ISO string) */\n dueDate?: string;\n\n /** Creation timestamp (ISO string) */\n createdAt: string;\n\n /** Last update timestamp (ISO string) */\n updatedAt: string;\n}\n\n// Comment on an issue\nexport interface Comment {\n id: string;\n issueId: string;\n body: string;\n author: string;\n createdAt: string;\n updatedAt: string;\n}\n\n// Filters for listing issues\nexport interface IssueFilters {\n /** Filter by state */\n state?: IssueState;\n\n /** Filter by labels (AND logic) */\n labels?: string[];\n\n /** Filter by assignee */\n assignee?: string;\n\n /** Filter by team/project (tracker-specific) */\n team?: string;\n\n /** Search query for title/description */\n query?: string;\n\n /** Maximum number of results */\n limit?: number;\n\n /** Include closed issues (default: false) */\n includeClosed?: boolean;\n}\n\n// Data for creating a new issue\nexport interface NewIssue {\n title: string;\n description?: string;\n labels?: string[];\n assignee?: string;\n team?: string;\n priority?: number;\n dueDate?: string;\n}\n\n// Data for updating an issue\nexport interface IssueUpdate {\n title?: string;\n description?: string;\n state?: IssueState;\n labels?: string[];\n assignee?: string;\n priority?: number;\n dueDate?: string;\n}\n\n/**\n * Abstract interface for issue trackers.\n * Implementations must handle normalization to/from tracker-specific formats.\n */\nexport interface IssueTracker {\n /** Tracker type identifier */\n readonly name: TrackerType;\n\n /**\n * List issues matching filters\n */\n listIssues(filters?: IssueFilters): Promise<Issue[]>;\n\n /**\n * Get a single issue by ID or ref\n * @param id - Issue ID or human-readable ref (e.g., \"MIN-630\", \"#42\")\n */\n getIssue(id: string): Promise<Issue>;\n\n /**\n * Update an existing issue\n */\n updateIssue(id: string, update: IssueUpdate): Promise<Issue>;\n\n /**\n * Create a new issue\n */\n createIssue(issue: NewIssue): Promise<Issue>;\n\n /**\n * Get comments on an issue\n */\n getComments(issueId: string): Promise<Comment[]>;\n\n /**\n * Add a comment to an issue\n */\n addComment(issueId: string, body: string): Promise<Comment>;\n\n /**\n * Transition issue to a new state\n */\n transitionIssue(id: string, state: IssueState): Promise<void>;\n\n /**\n * Link a PR/MR to an issue\n */\n linkPR(issueId: string, prUrl: string): Promise<void>;\n}\n\n/**\n * Error thrown when a tracker feature is not implemented\n */\nexport class NotImplementedError extends Error {\n constructor(feature: string) {\n super(`Not implemented: ${feature}`);\n this.name = 'NotImplementedError';\n }\n}\n\n/**\n * Error thrown when an issue is not found\n */\nexport class IssueNotFoundError extends Error {\n constructor(id: string, tracker: TrackerType) {\n super(`Issue not found: ${id} (tracker: ${tracker})`);\n this.name = 'IssueNotFoundError';\n }\n}\n\n/**\n * Error thrown when tracker authentication fails\n */\nexport class TrackerAuthError extends Error {\n constructor(tracker: TrackerType, message: string) {\n super(`Authentication failed for ${tracker}: ${message}`);\n this.name = 'TrackerAuthError';\n }\n}\n","/**\n * Linear Issue Tracker Adapter\n *\n * Implements IssueTracker interface for Linear.\n */\n\nimport { LinearClient } from '@linear/sdk';\nimport type {\n Issue,\n IssueFilters,\n IssueState,\n IssueTracker,\n IssueUpdate,\n NewIssue,\n Comment,\n TrackerType,\n} from './interface.js';\nimport { IssueNotFoundError, TrackerAuthError } from './interface.js';\n\n// Map Linear state types to our normalized states\nconst STATE_MAP: Record<string, IssueState> = {\n backlog: 'open',\n unstarted: 'open',\n started: 'in_progress',\n completed: 'closed',\n canceled: 'closed',\n};\n\nexport class LinearTracker implements IssueTracker {\n readonly name: TrackerType = 'linear';\n private client: LinearClient;\n private defaultTeam?: string;\n\n constructor(apiKey: string, options?: { team?: string }) {\n if (!apiKey) {\n throw new TrackerAuthError('linear', 'API key is required');\n }\n this.client = new LinearClient({ apiKey });\n this.defaultTeam = options?.team;\n }\n\n async listIssues(filters?: IssueFilters): Promise<Issue[]> {\n const team = filters?.team ?? this.defaultTeam;\n\n const result = await this.client.issues({\n first: filters?.limit ?? 50,\n filter: {\n team: team ? { key: { eq: team } } : undefined,\n state: filters?.state\n ? { type: { eq: this.reverseMapState(filters.state) } }\n : filters?.includeClosed\n ? undefined\n : { type: { neq: 'completed' } },\n labels: filters?.labels?.length\n ? { name: { in: filters.labels } }\n : undefined,\n assignee: filters?.assignee\n ? { name: { containsIgnoreCase: filters.assignee } }\n : undefined,\n },\n });\n\n const issues: Issue[] = [];\n for (const node of result.nodes) {\n issues.push(await this.normalizeIssue(node));\n }\n return issues;\n }\n\n async getIssue(id: string): Promise<Issue> {\n try {\n // Check if it's a UUID (36 chars with hyphens)\n const isUuid = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(id);\n\n if (isUuid) {\n // Fetch directly by UUID\n const issue = await this.client.issue(id);\n if (issue) {\n return this.normalizeIssue(issue);\n }\n } else {\n // Parse identifier (e.g., MIN-630) and search\n const match = id.match(/^([A-Z]+)-(\\d+)$/i);\n if (match) {\n const [, teamKey, number] = match;\n // Use searchIssues which supports identifier matching\n const results = await this.client.searchIssues(id, { first: 1 });\n if (results.nodes.length > 0) {\n return this.normalizeIssue(results.nodes[0]);\n }\n }\n }\n\n throw new IssueNotFoundError(id, 'linear');\n } catch (error) {\n if (error instanceof IssueNotFoundError) throw error;\n throw new IssueNotFoundError(id, 'linear');\n }\n }\n\n async updateIssue(id: string, update: IssueUpdate): Promise<Issue> {\n const issue = await this.getIssue(id);\n\n const updatePayload: Record<string, unknown> = {};\n\n if (update.title !== undefined) {\n updatePayload.title = update.title;\n }\n if (update.description !== undefined) {\n updatePayload.description = update.description;\n }\n if (update.priority !== undefined) {\n updatePayload.priority = update.priority;\n }\n if (update.dueDate !== undefined) {\n updatePayload.dueDate = update.dueDate;\n }\n if (update.state !== undefined) {\n // Need to find the state ID - this is complex in Linear\n // For now, we'll use the transition method\n await this.transitionIssue(id, update.state);\n }\n if (update.labels !== undefined) {\n // Need to look up label IDs - complex operation\n // TODO: Implement label updates\n }\n\n if (Object.keys(updatePayload).length > 0) {\n await this.client.updateIssue(issue.id, updatePayload);\n }\n\n return this.getIssue(id);\n }\n\n async createIssue(newIssue: NewIssue): Promise<Issue> {\n const team = newIssue.team ?? this.defaultTeam;\n\n if (!team) {\n throw new Error('Team is required to create an issue');\n }\n\n // Get team ID from key\n const teams = await this.client.teams({\n filter: { key: { eq: team } },\n });\n\n if (teams.nodes.length === 0) {\n throw new Error(`Team not found: ${team}`);\n }\n\n const teamId = teams.nodes[0].id;\n\n const result = await this.client.createIssue({\n teamId,\n title: newIssue.title,\n description: newIssue.description,\n priority: newIssue.priority,\n dueDate: newIssue.dueDate,\n });\n\n const created = await result.issue;\n if (!created) {\n throw new Error('Failed to create issue');\n }\n\n return this.normalizeIssue(created);\n }\n\n async getComments(issueId: string): Promise<Comment[]> {\n const issue = await this.client.issue(issueId);\n const comments = await issue.comments();\n\n return comments.nodes.map((c) => ({\n id: c.id,\n issueId,\n body: c.body,\n author: c.user?.then((u) => u?.name ?? 'Unknown') as unknown as string, // Simplified\n createdAt: c.createdAt.toISOString(),\n updatedAt: c.updatedAt.toISOString(),\n }));\n }\n\n async addComment(issueId: string, body: string): Promise<Comment> {\n const result = await this.client.createComment({\n issueId,\n body,\n });\n\n const comment = await result.comment;\n if (!comment) {\n throw new Error('Failed to create comment');\n }\n\n return {\n id: comment.id,\n issueId,\n body: comment.body,\n author: 'Panopticon', // Simplified\n createdAt: comment.createdAt.toISOString(),\n updatedAt: comment.updatedAt.toISOString(),\n };\n }\n\n async transitionIssue(id: string, state: IssueState): Promise<void> {\n const issue = await this.getIssue(id);\n\n // Get workflow states for the issue's team\n const linearIssue = await this.client.issue(issue.id);\n const team = await linearIssue.team;\n if (!team) {\n throw new Error('Could not determine issue team');\n }\n\n const states = await team.states();\n const targetStateType = this.reverseMapState(state);\n\n // Find a state matching the target type\n const targetState = states.nodes.find((s) => s.type === targetStateType);\n if (!targetState) {\n throw new Error(`No state found matching type: ${targetStateType}`);\n }\n\n await this.client.updateIssue(issue.id, {\n stateId: targetState.id,\n });\n }\n\n async linkPR(issueId: string, prUrl: string): Promise<void> {\n const issue = await this.getIssue(issueId);\n\n await this.client.createAttachment({\n issueId: issue.id,\n title: 'Pull Request',\n url: prUrl,\n });\n }\n\n private async normalizeIssue(linearIssue: any): Promise<Issue> {\n const state = await linearIssue.state;\n const assignee = await linearIssue.assignee;\n const labels = await linearIssue.labels();\n\n // Handle dueDate - can be Date, string, or undefined\n let dueDate: string | undefined;\n if (linearIssue.dueDate) {\n dueDate = linearIssue.dueDate instanceof Date\n ? linearIssue.dueDate.toISOString()\n : String(linearIssue.dueDate);\n }\n\n return {\n id: linearIssue.id,\n ref: linearIssue.identifier,\n title: linearIssue.title,\n description: linearIssue.description ?? '',\n state: this.mapState(state?.type ?? 'backlog'),\n labels: labels?.nodes?.map((l: any) => l.name) ?? [],\n assignee: assignee?.name,\n url: linearIssue.url,\n tracker: 'linear',\n priority: linearIssue.priority,\n dueDate,\n createdAt: linearIssue.createdAt instanceof Date\n ? linearIssue.createdAt.toISOString()\n : String(linearIssue.createdAt),\n updatedAt: linearIssue.updatedAt instanceof Date\n ? linearIssue.updatedAt.toISOString()\n : String(linearIssue.updatedAt),\n };\n }\n\n private mapState(linearState: string): IssueState {\n return STATE_MAP[linearState] ?? 'open';\n }\n\n private reverseMapState(state: IssueState): string {\n switch (state) {\n case 'open':\n return 'unstarted';\n case 'in_progress':\n return 'started';\n case 'closed':\n return 'completed';\n default:\n return 'unstarted';\n }\n }\n}\n","/**\n * GitHub Issues Tracker Adapter\n *\n * Implements IssueTracker interface for GitHub Issues.\n */\n\nimport { Octokit } from '@octokit/rest';\nimport type {\n Issue,\n IssueFilters,\n IssueState,\n IssueTracker,\n IssueUpdate,\n NewIssue,\n Comment,\n TrackerType,\n} from './interface.js';\nimport { IssueNotFoundError, TrackerAuthError } from './interface.js';\n\nexport class GitHubTracker implements IssueTracker {\n readonly name: TrackerType = 'github';\n private octokit: Octokit;\n private owner: string;\n private repo: string;\n\n constructor(token: string, owner: string, repo: string) {\n if (!token) {\n throw new TrackerAuthError('github', 'Token is required');\n }\n if (!owner || !repo) {\n throw new Error('GitHub owner and repo are required');\n }\n\n this.octokit = new Octokit({ auth: token });\n this.owner = owner;\n this.repo = repo;\n }\n\n async listIssues(filters?: IssueFilters): Promise<Issue[]> {\n const state = this.mapStateToGitHub(filters?.state);\n\n const response = await this.octokit.issues.listForRepo({\n owner: this.owner,\n repo: this.repo,\n state: filters?.includeClosed ? 'all' : state,\n labels: filters?.labels?.join(',') || undefined,\n assignee: filters?.assignee || undefined,\n per_page: filters?.limit ?? 50,\n });\n\n // Filter out pull requests (GitHub API returns both)\n const issues = response.data.filter((item) => !item.pull_request);\n\n return issues.map((issue) => this.normalizeIssue(issue));\n }\n\n async getIssue(id: string): Promise<Issue> {\n try {\n // Parse the issue number from refs like \"#42\" or just \"42\"\n const issueNumber = parseInt(id.replace(/^#/, ''), 10);\n\n if (isNaN(issueNumber)) {\n throw new IssueNotFoundError(id, 'github');\n }\n\n const { data: issue } = await this.octokit.issues.get({\n owner: this.owner,\n repo: this.repo,\n issue_number: issueNumber,\n });\n\n return this.normalizeIssue(issue);\n } catch (error: any) {\n if (error?.status === 404) {\n throw new IssueNotFoundError(id, 'github');\n }\n throw error;\n }\n }\n\n async updateIssue(id: string, update: IssueUpdate): Promise<Issue> {\n const issueNumber = parseInt(id.replace(/^#/, ''), 10);\n\n const updatePayload: Record<string, unknown> = {};\n\n if (update.title !== undefined) {\n updatePayload.title = update.title;\n }\n if (update.description !== undefined) {\n updatePayload.body = update.description;\n }\n if (update.state !== undefined) {\n updatePayload.state = update.state === 'closed' ? 'closed' : 'open';\n }\n if (update.labels !== undefined) {\n updatePayload.labels = update.labels;\n }\n if (update.assignee !== undefined) {\n updatePayload.assignees = update.assignee ? [update.assignee] : [];\n }\n\n await this.octokit.issues.update({\n owner: this.owner,\n repo: this.repo,\n issue_number: issueNumber,\n ...updatePayload,\n });\n\n return this.getIssue(id);\n }\n\n async createIssue(newIssue: NewIssue): Promise<Issue> {\n const { data: issue } = await this.octokit.issues.create({\n owner: this.owner,\n repo: this.repo,\n title: newIssue.title,\n body: newIssue.description,\n labels: newIssue.labels,\n assignees: newIssue.assignee ? [newIssue.assignee] : undefined,\n });\n\n return this.normalizeIssue(issue);\n }\n\n async getComments(issueId: string): Promise<Comment[]> {\n const issueNumber = parseInt(issueId.replace(/^#/, ''), 10);\n\n const { data: comments } = await this.octokit.issues.listComments({\n owner: this.owner,\n repo: this.repo,\n issue_number: issueNumber,\n });\n\n return comments.map((c) => ({\n id: String(c.id),\n issueId,\n body: c.body ?? '',\n author: c.user?.login ?? 'Unknown',\n createdAt: c.created_at,\n updatedAt: c.updated_at,\n }));\n }\n\n async addComment(issueId: string, body: string): Promise<Comment> {\n const issueNumber = parseInt(issueId.replace(/^#/, ''), 10);\n\n const { data: comment } = await this.octokit.issues.createComment({\n owner: this.owner,\n repo: this.repo,\n issue_number: issueNumber,\n body,\n });\n\n return {\n id: String(comment.id),\n issueId,\n body: comment.body ?? '',\n author: comment.user?.login ?? 'Unknown',\n createdAt: comment.created_at,\n updatedAt: comment.updated_at,\n };\n }\n\n async transitionIssue(id: string, state: IssueState): Promise<void> {\n await this.updateIssue(id, { state });\n }\n\n async linkPR(issueId: string, prUrl: string): Promise<void> {\n // GitHub auto-links PRs that mention issues\n // Add a comment with the PR link\n await this.addComment(\n issueId,\n `Linked Pull Request: ${prUrl}`\n );\n }\n\n private normalizeIssue(ghIssue: any): Issue {\n return {\n id: String(ghIssue.id),\n ref: `#${ghIssue.number}`,\n title: ghIssue.title,\n description: ghIssue.body ?? '',\n state: this.mapStateFromGitHub(ghIssue.state),\n labels: ghIssue.labels.map((l: any) =>\n typeof l === 'string' ? l : l.name\n ),\n assignee: ghIssue.assignee?.login,\n url: ghIssue.html_url,\n tracker: 'github',\n priority: undefined, // GitHub doesn't have priority\n dueDate: undefined, // GitHub doesn't have due dates on issues\n createdAt: ghIssue.created_at,\n updatedAt: ghIssue.updated_at,\n };\n }\n\n private mapStateFromGitHub(ghState: string): IssueState {\n // GitHub only has open and closed states\n // No way to distinguish \"in_progress\" without custom labels\n return ghState === 'closed' ? 'closed' : 'open';\n }\n\n private mapStateToGitHub(\n state?: IssueState\n ): 'open' | 'closed' | 'all' {\n if (!state) return 'open';\n if (state === 'closed') return 'closed';\n return 'open'; // Both 'open' and 'in_progress' map to 'open'\n }\n}\n","/**\n * GitLab Issues Tracker Adapter (Stub)\n *\n * Placeholder implementation for GitLab Issues support.\n * Full implementation will use @gitbeaker/rest.\n */\n\nimport type {\n Issue,\n IssueFilters,\n IssueState,\n IssueTracker,\n IssueUpdate,\n NewIssue,\n Comment,\n TrackerType,\n} from './interface.js';\nimport { NotImplementedError } from './interface.js';\n\nexport class GitLabTracker implements IssueTracker {\n readonly name: TrackerType = 'gitlab';\n\n constructor(\n private token: string,\n private projectId: string\n ) {\n // Stub - will initialize @gitbeaker client when implemented\n }\n\n async listIssues(_filters?: IssueFilters): Promise<Issue[]> {\n throw new NotImplementedError(\n 'GitLab tracker is not yet implemented. Coming soon!'\n );\n }\n\n async getIssue(_id: string): Promise<Issue> {\n throw new NotImplementedError(\n 'GitLab tracker is not yet implemented. Coming soon!'\n );\n }\n\n async updateIssue(_id: string, _update: IssueUpdate): Promise<Issue> {\n throw new NotImplementedError(\n 'GitLab tracker is not yet implemented. Coming soon!'\n );\n }\n\n async createIssue(_issue: NewIssue): Promise<Issue> {\n throw new NotImplementedError(\n 'GitLab tracker is not yet implemented. Coming soon!'\n );\n }\n\n async getComments(_issueId: string): Promise<Comment[]> {\n throw new NotImplementedError(\n 'GitLab tracker is not yet implemented. Coming soon!'\n );\n }\n\n async addComment(_issueId: string, _body: string): Promise<Comment> {\n throw new NotImplementedError(\n 'GitLab tracker is not yet implemented. Coming soon!'\n );\n }\n\n async transitionIssue(_id: string, _state: IssueState): Promise<void> {\n throw new NotImplementedError(\n 'GitLab tracker is not yet implemented. Coming soon!'\n );\n }\n\n async linkPR(_issueId: string, _prUrl: string): Promise<void> {\n throw new NotImplementedError(\n 'GitLab tracker is not yet implemented. Coming soon!'\n );\n }\n}\n","/**\n * Tracker Factory\n *\n * Creates appropriate tracker instances based on configuration.\n */\n\nimport type { IssueTracker, TrackerType } from './interface.js';\nimport { TrackerAuthError } from './interface.js';\nimport { LinearTracker } from './linear.js';\nimport { GitHubTracker } from './github.js';\nimport { GitLabTracker } from './gitlab.js';\nimport { RallyTracker } from './rally.js';\nimport type { TrackersConfig } from '../config.js';\nimport { loadConfig as loadYamlConfig } from '../config-yaml.js';\n\n// Configuration for a single tracker\nexport interface TrackerConfig {\n type: TrackerType;\n\n // Linear-specific\n apiKeyEnv?: string;\n team?: string;\n\n // GitHub-specific\n tokenEnv?: string;\n owner?: string;\n repo?: string;\n\n // GitLab-specific\n projectId?: string;\n\n // Rally-specific\n server?: string;\n workspace?: string;\n project?: string;\n}\n\n// Multi-tracker configuration (re-exported from config.ts)\n// Note: Use TrackersConfig from config.ts for full type with nested configs\n\n/**\n * Get tracker API key from config.yaml as fallback when env var is not set.\n */\nfunction getTrackerKeyFromConfig(trackerType: TrackerType): string | undefined {\n try {\n const yamlConfig = loadYamlConfig();\n return yamlConfig.trackerKeys[trackerType];\n } catch {\n return undefined;\n }\n}\n\n/**\n * Create a tracker instance from configuration\n */\nexport function createTracker(config: TrackerConfig): IssueTracker {\n switch (config.type) {\n case 'linear': {\n const envKey = config.apiKeyEnv\n ? process.env[config.apiKeyEnv]\n : process.env.LINEAR_API_KEY;\n const apiKey = envKey || getTrackerKeyFromConfig('linear');\n\n if (!apiKey) {\n throw new TrackerAuthError(\n 'linear',\n `API key not found. Set ${config.apiKeyEnv ?? 'LINEAR_API_KEY'} environment variable or configure in Settings.`\n );\n }\n\n return new LinearTracker(apiKey, { team: config.team });\n }\n\n case 'github': {\n const envToken = config.tokenEnv\n ? process.env[config.tokenEnv]\n : process.env.GITHUB_TOKEN;\n const token = envToken || getTrackerKeyFromConfig('github');\n\n if (!token) {\n throw new TrackerAuthError(\n 'github',\n `Token not found. Set ${config.tokenEnv ?? 'GITHUB_TOKEN'} environment variable or configure in Settings.`\n );\n }\n\n if (!config.owner || !config.repo) {\n throw new Error(\n 'GitHub tracker requires owner and repo configuration'\n );\n }\n\n return new GitHubTracker(token, config.owner, config.repo);\n }\n\n case 'gitlab': {\n const envToken = config.tokenEnv\n ? process.env[config.tokenEnv]\n : process.env.GITLAB_TOKEN;\n const token = envToken || getTrackerKeyFromConfig('gitlab');\n\n if (!token) {\n throw new TrackerAuthError(\n 'gitlab',\n `Token not found. Set ${config.tokenEnv ?? 'GITLAB_TOKEN'} environment variable or configure in Settings.`\n );\n }\n\n if (!config.projectId) {\n throw new Error('GitLab tracker requires projectId configuration');\n }\n\n return new GitLabTracker(token, config.projectId);\n }\n\n case 'rally': {\n const envKey = config.apiKeyEnv\n ? process.env[config.apiKeyEnv]\n : process.env.RALLY_API_KEY;\n const apiKey = envKey || getTrackerKeyFromConfig('rally');\n\n if (!apiKey) {\n throw new TrackerAuthError(\n 'rally',\n `API key not found. Set ${config.apiKeyEnv ?? 'RALLY_API_KEY'} environment variable or configure in Settings.`\n );\n }\n\n return new RallyTracker({\n apiKey,\n server: config.server,\n workspace: config.workspace,\n project: config.project,\n });\n }\n\n default:\n throw new Error(`Unknown tracker type: ${config.type}`);\n }\n}\n\n/**\n * Create tracker from trackers configuration section\n */\nexport function createTrackerFromConfig(\n trackersConfig: TrackersConfig,\n trackerType: TrackerType\n): IssueTracker {\n const config = trackersConfig[trackerType];\n\n if (!config) {\n throw new Error(\n `No configuration found for tracker: ${trackerType}. Add [trackers.${trackerType}] to config.`\n );\n }\n\n return createTracker({ ...config, type: trackerType });\n}\n\n/**\n * Get the primary tracker from configuration\n */\nexport function getPrimaryTracker(trackersConfig: TrackersConfig): IssueTracker {\n return createTrackerFromConfig(trackersConfig, trackersConfig.primary);\n}\n\n/**\n * Get the secondary tracker from configuration (if configured)\n */\nexport function getSecondaryTracker(\n trackersConfig: TrackersConfig\n): IssueTracker | null {\n if (!trackersConfig.secondary) {\n return null;\n }\n return createTrackerFromConfig(trackersConfig, trackersConfig.secondary);\n}\n\n/**\n * Get all configured trackers\n */\nexport function getAllTrackers(trackersConfig: TrackersConfig): IssueTracker[] {\n const trackers: IssueTracker[] = [getPrimaryTracker(trackersConfig)];\n\n const secondary = getSecondaryTracker(trackersConfig);\n if (secondary) {\n trackers.push(secondary);\n }\n\n return trackers;\n}\n","/**\n * Rally Tracker Adapter\n *\n * Implements IssueTracker interface for Broadcom Rally (formerly CA Agile Central).\n * Supports all Rally work item types: User Stories, Defects, Tasks, and Features.\n */\n\nimport { RallyRestApi } from './rally-api.js';\nimport type {\n Issue,\n IssueFilters,\n IssueState,\n IssueTracker,\n IssueUpdate,\n NewIssue,\n Comment,\n TrackerType,\n} from './interface.js';\nimport { IssueNotFoundError, TrackerAuthError, NotImplementedError } from './interface.js';\n\n// Map Rally ScheduleState to normalized IssueState\nconst STATE_MAP: Record<string, IssueState> = {\n Defined: 'open',\n 'In-Progress': 'in_progress',\n Completed: 'closed',\n Accepted: 'closed',\n};\n\n// Rally artifact types we support\ntype RallyArtifactType = 'HierarchicalRequirement' | 'Defect' | 'Task' | 'PortfolioItem/Feature';\n\n// Rally priority strings to numbers\nconst PRIORITY_MAP: Record<string, number> = {\n 'Resolve Immediately': 0,\n High: 1,\n Normal: 2,\n Low: 3,\n};\n\n// Reverse priority mapping\nconst REVERSE_PRIORITY_MAP: Record<number, string> = {\n 0: 'Resolve Immediately',\n 1: 'High',\n 2: 'Normal',\n 3: 'Low',\n 4: 'Low',\n};\n\nexport interface RallyConfig {\n apiKey: string;\n server?: string; // Default: rally1.rallydev.com\n workspace?: string; // Rally workspace OID (e.g., \"/workspace/12345\")\n project?: string; // Rally project OID (e.g., \"/project/67890\")\n}\n\nexport class RallyTracker implements IssueTracker {\n readonly name: TrackerType = 'rally' as TrackerType;\n private restApi: RallyRestApi;\n private workspace?: string;\n private project?: string;\n\n constructor(config: RallyConfig) {\n if (!config.apiKey) {\n throw new TrackerAuthError('rally' as TrackerType, 'API key is required');\n }\n\n this.restApi = new RallyRestApi({\n apiKey: config.apiKey,\n server: config.server || 'https://rally1.rallydev.com',\n requestOptions: {\n headers: {\n 'X-RallyIntegrationType': 'Panopticon',\n 'X-RallyIntegrationName': 'Panopticon CLI',\n 'X-RallyIntegrationVendor': 'Mind Your Now',\n 'X-RallyIntegrationVersion': '0.2.0',\n },\n },\n });\n\n this.workspace = config.workspace;\n this.project = config.project;\n }\n\n async listIssues(filters?: IssueFilters): Promise<Issue[]> {\n const query: any = {\n type: 'artifact', // Query all artifact types\n fetch: [\n 'FormattedID',\n 'Name',\n 'Description',\n 'ScheduleState',\n 'State', // For Defects\n 'Tags',\n 'Owner',\n 'Priority',\n 'DueDate',\n 'CreationDate',\n 'LastUpdateDate',\n 'Parent',\n '_type',\n ],\n limit: filters?.limit ?? 50,\n query: this.buildQueryString(filters),\n };\n\n if (this.workspace) {\n query.workspace = this.workspace;\n }\n if (this.project) {\n query.project = this.project;\n query.projectScopeDown = true;\n }\n\n try {\n const result = await this.queryRally(query);\n return result.Results.map((artifact: any) => this.normalizeIssue(artifact));\n } catch (error: any) {\n if (error.message?.includes('Unauthorized') || error.message?.includes('401')) {\n throw new TrackerAuthError('rally' as TrackerType, 'Invalid API key or insufficient permissions');\n }\n throw error;\n }\n }\n\n async getIssue(id: string): Promise<Issue> {\n try {\n // Rally FormattedIDs look like: US123, DE456, TA789, F012\n const query: any = {\n type: 'artifact',\n fetch: [\n 'FormattedID',\n 'Name',\n 'Description',\n 'ScheduleState',\n 'State',\n 'Tags',\n 'Owner',\n 'Priority',\n 'DueDate',\n 'CreationDate',\n 'LastUpdateDate',\n 'Parent',\n '_type',\n ],\n query: `(FormattedID = \"${id}\")`,\n };\n\n if (this.workspace) {\n query.workspace = this.workspace;\n }\n\n const result = await this.queryRally(query);\n\n if (!result.Results || result.Results.length === 0) {\n throw new IssueNotFoundError(id, 'rally' as TrackerType);\n }\n\n return this.normalizeIssue(result.Results[0]);\n } catch (error: any) {\n if (error instanceof IssueNotFoundError) throw error;\n throw new IssueNotFoundError(id, 'rally' as TrackerType);\n }\n }\n\n async updateIssue(id: string, update: IssueUpdate): Promise<Issue> {\n const issue = await this.getIssue(id);\n\n // Get the Rally object reference\n const query: any = {\n type: 'artifact',\n fetch: ['ObjectID', '_ref', '_type'],\n query: `(FormattedID = \"${id}\")`,\n };\n\n if (this.workspace) {\n query.workspace = this.workspace;\n }\n\n const result = await this.queryRally(query);\n if (!result.Results || result.Results.length === 0) {\n throw new IssueNotFoundError(id, 'rally' as TrackerType);\n }\n\n const artifact = result.Results[0];\n const updatePayload: Record<string, unknown> = {};\n\n if (update.title !== undefined) {\n updatePayload.Name = update.title;\n }\n if (update.description !== undefined) {\n updatePayload.Description = update.description;\n }\n if (update.state !== undefined) {\n const rallyState = this.reverseMapState(update.state);\n // Use ScheduleState for User Stories and Tasks, State for Defects\n if (artifact._type === 'Defect') {\n updatePayload.State = rallyState;\n } else {\n updatePayload.ScheduleState = rallyState;\n }\n }\n if (update.priority !== undefined) {\n updatePayload.Priority = REVERSE_PRIORITY_MAP[update.priority] || 'Normal';\n }\n if (update.dueDate !== undefined) {\n updatePayload.DueDate = update.dueDate;\n }\n\n if (Object.keys(updatePayload).length > 0) {\n await this.updateRally(artifact._type.toLowerCase(), artifact._ref, updatePayload);\n }\n\n return this.getIssue(id);\n }\n\n async createIssue(newIssue: NewIssue): Promise<Issue> {\n if (!this.project && !newIssue.team) {\n throw new Error('Project is required to create an issue. Set it in config or provide team field.');\n }\n\n const project = newIssue.team || this.project;\n\n // Default to HierarchicalRequirement (User Story) for new issues\n const createPayload: Record<string, unknown> = {\n Name: newIssue.title,\n Description: newIssue.description || '',\n Project: project,\n };\n\n if (newIssue.priority !== undefined) {\n createPayload.Priority = REVERSE_PRIORITY_MAP[newIssue.priority] || 'Normal';\n }\n if (newIssue.dueDate) {\n createPayload.DueDate = newIssue.dueDate;\n }\n if (this.workspace) {\n createPayload.Workspace = this.workspace;\n }\n\n const result = await this.createRally('hierarchicalrequirement', createPayload);\n\n // Fetch the created issue to return normalized format\n return this.getIssue(result.Object.FormattedID);\n }\n\n async getComments(issueId: string): Promise<Comment[]> {\n const issue = await this.getIssue(issueId);\n\n // Get the Rally object to find its Discussion\n const query: any = {\n type: 'artifact',\n fetch: ['ObjectID', '_ref', 'Discussion'],\n query: `(FormattedID = \"${issueId}\")`,\n };\n\n if (this.workspace) {\n query.workspace = this.workspace;\n }\n\n const result = await this.queryRally(query);\n if (!result.Results || result.Results.length === 0) {\n return [];\n }\n\n const artifact = result.Results[0];\n if (!artifact.Discussion) {\n return [];\n }\n\n // Query ConversationPosts for this Discussion\n const postsQuery: any = {\n type: 'conversationpost',\n fetch: ['ObjectID', 'Text', 'User', 'CreationDate', 'PostNumber'],\n query: `(Discussion = \"${artifact.Discussion._ref}\")`,\n order: 'PostNumber',\n };\n\n const postsResult = await this.queryRally(postsQuery);\n\n return (postsResult.Results || []).map((post: any) => ({\n id: post.ObjectID,\n issueId,\n body: post.Text || '',\n author: post.User?._refObjectName || 'Unknown',\n createdAt: post.CreationDate,\n updatedAt: post.CreationDate, // Rally doesn't track comment updates separately\n }));\n }\n\n async addComment(issueId: string, body: string): Promise<Comment> {\n // Get the Rally object to find its Discussion\n const query: any = {\n type: 'artifact',\n fetch: ['ObjectID', '_ref', 'Discussion'],\n query: `(FormattedID = \"${issueId}\")`,\n };\n\n if (this.workspace) {\n query.workspace = this.workspace;\n }\n\n const result = await this.queryRally(query);\n if (!result.Results || result.Results.length === 0) {\n throw new IssueNotFoundError(issueId, 'rally' as TrackerType);\n }\n\n const artifact = result.Results[0];\n\n // If no Discussion exists, create one\n let discussionRef = artifact.Discussion?._ref;\n if (!discussionRef) {\n const discussionResult = await this.createRally('conversationpost', {\n Artifact: artifact._ref,\n Text: body,\n });\n\n return {\n id: discussionResult.Object.ObjectID,\n issueId,\n body,\n author: 'Panopticon',\n createdAt: new Date().toISOString(),\n updatedAt: new Date().toISOString(),\n };\n }\n\n // Add a post to existing Discussion\n const postResult = await this.createRally('conversationpost', {\n Artifact: artifact._ref,\n Text: body,\n });\n\n return {\n id: postResult.Object.ObjectID,\n issueId,\n body,\n author: 'Panopticon',\n createdAt: new Date().toISOString(),\n updatedAt: new Date().toISOString(),\n };\n }\n\n async transitionIssue(id: string, state: IssueState): Promise<void> {\n await this.updateIssue(id, { state });\n }\n\n async linkPR(issueId: string, prUrl: string): Promise<void> {\n // Add a comment with the PR link\n await this.addComment(issueId, `Linked Pull Request: ${prUrl}`);\n }\n\n // Private helper methods\n\n private buildQueryString(filters?: IssueFilters): string {\n const conditions: string[] = [];\n\n if (filters?.state && !filters.includeClosed) {\n const rallyState = this.reverseMapState(filters.state);\n conditions.push(`((ScheduleState = \"${rallyState}\") OR (State = \"${rallyState}\"))`);\n }\n\n if (!filters?.includeClosed) {\n // Exclude completed/accepted items by default\n conditions.push('((ScheduleState != \"Completed\") AND (ScheduleState != \"Accepted\") AND (State != \"Closed\"))');\n }\n\n if (filters?.assignee) {\n conditions.push(`(Owner.Name contains \"${filters.assignee}\")`);\n }\n\n if (filters?.labels && filters.labels.length > 0) {\n const labelConditions = filters.labels.map(\n (label) => `(Tags.Name contains \"${label}\")`\n );\n conditions.push(`(${labelConditions.join(' AND ')})`);\n }\n\n if (filters?.query) {\n conditions.push(`((Name contains \"${filters.query}\") OR (Description contains \"${filters.query}\"))`);\n }\n\n return conditions.length > 0 ? conditions.join(' AND ') : '';\n }\n\n private normalizeIssue(rallyArtifact: any): Issue {\n // Determine state from ScheduleState (User Stories, Tasks) or State (Defects)\n const stateValue = rallyArtifact.ScheduleState || rallyArtifact.State || 'Defined';\n const state = this.mapState(stateValue);\n\n // Extract tags\n const labels: string[] = [];\n if (rallyArtifact.Tags && rallyArtifact.Tags._tagsNameArray) {\n labels.push(...rallyArtifact.Tags._tagsNameArray);\n }\n\n // Map priority\n const priority = rallyArtifact.Priority\n ? PRIORITY_MAP[rallyArtifact.Priority] ?? 2\n : undefined;\n\n // Build URL - Rally's web UI uses FormattedID\n const baseUrl = this.restApi.server.replace('/slm/webservice/', '');\n const url = `${baseUrl}/#/detail/${rallyArtifact._type.toLowerCase()}/${rallyArtifact.ObjectID}`;\n\n return {\n id: rallyArtifact.ObjectID,\n ref: rallyArtifact.FormattedID,\n title: rallyArtifact.Name || '',\n description: rallyArtifact.Description || '',\n state,\n labels,\n assignee: rallyArtifact.Owner?._refObjectName,\n url,\n tracker: 'rally' as TrackerType,\n priority,\n dueDate: rallyArtifact.DueDate,\n createdAt: rallyArtifact.CreationDate,\n updatedAt: rallyArtifact.LastUpdateDate,\n };\n }\n\n private mapState(rallyState: string): IssueState {\n return STATE_MAP[rallyState] ?? 'open';\n }\n\n private reverseMapState(state: IssueState): string {\n switch (state) {\n case 'open':\n return 'Defined';\n case 'in_progress':\n return 'In-Progress';\n case 'closed':\n return 'Completed';\n default:\n return 'Defined';\n }\n }\n\n // Rally API wrapper methods\n private async queryRally(queryConfig: any): Promise<any> {\n const result = await this.restApi.query(queryConfig);\n // Extract Results from WSAPI response format\n return {\n Results: result.QueryResult.Results,\n TotalResultCount: result.QueryResult.TotalResultCount,\n };\n }\n\n private async createRally(type: string, data: any): Promise<any> {\n const result = await this.restApi.create({\n type,\n data,\n fetch: ['FormattedID', 'ObjectID', '_ref'],\n });\n // Extract Object from WSAPI response format\n return {\n Object: result.CreateResult.Object,\n };\n }\n\n private async updateRally(type: string, ref: string, data: any): Promise<any> {\n const result = await this.restApi.update({\n type,\n ref,\n data,\n fetch: ['FormattedID', 'ObjectID'],\n });\n // Extract Object from WSAPI response format\n return {\n Object: result.OperationResult.Object,\n };\n }\n}\n","/**\n * Rally WSAPI REST Client\n *\n * Thin wrapper around native fetch for Rally Web Services API v2.0.\n * Provides typed methods for query, create, and update operations.\n */\n\nexport interface RallyQueryConfig {\n type: string;\n fetch?: string[];\n query?: string;\n limit?: number;\n workspace?: string;\n project?: string;\n projectScopeDown?: boolean;\n order?: string;\n}\n\nexport interface RallyQueryResult {\n QueryResult: {\n Results: any[];\n TotalResultCount: number;\n Errors: string[];\n Warnings: string[];\n };\n}\n\nexport interface RallyCreateConfig {\n type: string;\n data: any;\n fetch?: string[];\n}\n\nexport interface RallyCreateResult {\n CreateResult: {\n Object: any;\n Errors: string[];\n Warnings: string[];\n };\n}\n\nexport interface RallyUpdateConfig {\n type: string;\n ref: string;\n data: any;\n fetch?: string[];\n}\n\nexport interface RallyUpdateResult {\n OperationResult: {\n Object: any;\n Errors: string[];\n Warnings: string[];\n };\n}\n\nexport interface RallyApiConfig {\n apiKey: string;\n server?: string;\n requestOptions?: {\n headers?: Record<string, string>;\n };\n}\n\nexport class RallyRestApi {\n private apiKey: string;\n public server: string;\n private customHeaders: Record<string, string>;\n\n constructor(config: RallyApiConfig) {\n this.apiKey = config.apiKey;\n this.server = config.server || 'https://rally1.rallydev.com';\n this.customHeaders = config.requestOptions?.headers || {};\n }\n\n /**\n * Query Rally artifacts\n */\n async query(config: RallyQueryConfig): Promise<RallyQueryResult> {\n const params = new URLSearchParams();\n\n if (config.query) {\n params.set('query', config.query);\n }\n\n if (config.fetch && config.fetch.length > 0) {\n params.set('fetch', config.fetch.join(','));\n }\n\n if (config.limit !== undefined) {\n params.set('pagesize', String(config.limit));\n }\n\n if (config.workspace) {\n params.set('workspace', config.workspace);\n }\n\n if (config.project) {\n params.set('project', config.project);\n if (config.projectScopeDown) {\n params.set('projectScopeDown', 'true');\n }\n }\n\n if (config.order) {\n params.set('order', config.order);\n }\n\n const url = `${this.server}/slm/webservice/v2.0/${config.type}?${params.toString()}`;\n\n const response = await fetch(url, {\n method: 'GET',\n headers: {\n 'ZSESSIONID': this.apiKey,\n 'Content-Type': 'application/json',\n ...this.customHeaders,\n },\n });\n\n if (!response.ok) {\n if (response.status === 401) {\n throw new Error('Unauthorized: Invalid API key or insufficient permissions');\n }\n throw new Error(`Rally API query failed: ${response.status} ${response.statusText}`);\n }\n\n const result = await response.json() as RallyQueryResult;\n\n if (result.QueryResult.Errors && result.QueryResult.Errors.length > 0) {\n throw new Error(`Rally API query failed: ${result.QueryResult.Errors.join(', ')}`);\n }\n\n return result;\n }\n\n /**\n * Create a Rally object\n */\n async create(config: RallyCreateConfig): Promise<RallyCreateResult> {\n const url = `${this.server}/slm/webservice/v2.0/${config.type}/create`;\n\n const body: any = {\n [config.type]: config.data,\n };\n\n const params = new URLSearchParams();\n if (config.fetch && config.fetch.length > 0) {\n params.set('fetch', config.fetch.join(','));\n }\n\n const finalUrl = params.toString() ? `${url}?${params.toString()}` : url;\n\n const response = await fetch(finalUrl, {\n method: 'POST',\n headers: {\n 'ZSESSIONID': this.apiKey,\n 'Content-Type': 'application/json',\n ...this.customHeaders,\n },\n body: JSON.stringify(body),\n });\n\n if (!response.ok) {\n throw new Error(`Rally API create failed: ${response.status} ${response.statusText}`);\n }\n\n const result = await response.json() as RallyCreateResult;\n\n if (result.CreateResult.Errors && result.CreateResult.Errors.length > 0) {\n throw new Error(`Rally API create failed: ${result.CreateResult.Errors.join(', ')}`);\n }\n\n return result;\n }\n\n /**\n * Update a Rally object\n */\n async update(config: RallyUpdateConfig): Promise<RallyUpdateResult> {\n // Extract ObjectID from ref (e.g., \"/hierarchicalrequirement/12345\" -> \"12345\")\n const objectId = config.ref.split('/').pop();\n const url = `${this.server}/slm/webservice/v2.0/${config.type}/${objectId}`;\n\n const body: any = {\n [config.type]: config.data,\n };\n\n const params = new URLSearchParams();\n if (config.fetch && config.fetch.length > 0) {\n params.set('fetch', config.fetch.join(','));\n }\n\n const finalUrl = params.toString() ? `${url}?${params.toString()}` : url;\n\n const response = await fetch(finalUrl, {\n method: 'POST',\n headers: {\n 'ZSESSIONID': this.apiKey,\n 'Content-Type': 'application/json',\n ...this.customHeaders,\n },\n body: JSON.stringify(body),\n });\n\n if (!response.ok) {\n throw new Error(`Rally API update failed: ${response.status} ${response.statusText}`);\n }\n\n const result = await response.json() as RallyUpdateResult;\n\n if (result.OperationResult.Errors && result.OperationResult.Errors.length > 0) {\n throw new Error(`Rally API update failed: ${result.OperationResult.Errors.join(', ')}`);\n }\n\n return result;\n }\n}\n","/**\n * Cross-Tracker Linking\n *\n * Manages links between issues in different trackers.\n * Links are stored in a local JSON file for persistence.\n */\n\nimport { readFileSync, writeFileSync, existsSync, mkdirSync } from 'fs';\nimport { join } from 'path';\nimport { homedir } from 'os';\nimport type { TrackerType } from './interface.js';\n\n// Link direction types\nexport type LinkDirection = 'blocks' | 'blocked_by' | 'related' | 'duplicate_of';\n\n// A single link between two issues\nexport interface TrackerLink {\n sourceIssueRef: string; // e.g., \"MIN-630\"\n sourceTracker: TrackerType;\n targetIssueRef: string; // e.g., \"#42\"\n targetTracker: TrackerType;\n direction: LinkDirection;\n createdAt: string; // ISO timestamp\n}\n\n// Storage format\ninterface LinkStore {\n version: 1;\n links: TrackerLink[];\n}\n\n/**\n * Parse an issue reference to extract tracker and ID\n * Examples:\n * \"#42\" -> { tracker: \"github\", ref: \"#42\" }\n * \"github#42\" -> { tracker: \"github\", ref: \"#42\" }\n * \"MIN-630\" -> { tracker: \"linear\", ref: \"MIN-630\" }\n * \"gitlab#15\" -> { tracker: \"gitlab\", ref: \"#15\" }\n */\nexport function parseIssueRef(ref: string): { tracker: TrackerType; ref: string } | null {\n // Explicit tracker prefix\n if (ref.startsWith('github#')) {\n return { tracker: 'github', ref: `#${ref.slice(7)}` };\n }\n if (ref.startsWith('gitlab#')) {\n return { tracker: 'gitlab', ref: `#${ref.slice(7)}` };\n }\n if (ref.startsWith('linear:')) {\n return { tracker: 'linear', ref: ref.slice(7) };\n }\n\n // GitHub-style refs (#number)\n if (/^#\\d+$/.test(ref)) {\n return { tracker: 'github', ref };\n }\n\n // Linear-style refs (XXX-123)\n if (/^[A-Z]+-\\d+$/i.test(ref)) {\n return { tracker: 'linear', ref: ref.toUpperCase() };\n }\n\n return null;\n}\n\n/**\n * Format an issue ref with tracker prefix for display\n */\nexport function formatIssueRef(ref: string, tracker: TrackerType): string {\n if (tracker === 'github') {\n return ref.startsWith('#') ? `github${ref}` : `github#${ref}`;\n }\n if (tracker === 'gitlab') {\n return ref.startsWith('#') ? `gitlab${ref}` : `gitlab#${ref}`;\n }\n return ref; // Linear refs are already unique\n}\n\n/**\n * Link Manager for cross-tracker issue linking\n */\nexport class LinkManager {\n private storePath: string;\n private store: LinkStore;\n\n constructor(storePath?: string) {\n this.storePath = storePath ?? join(homedir(), '.panopticon', 'links.json');\n this.store = this.load();\n }\n\n private load(): LinkStore {\n if (existsSync(this.storePath)) {\n try {\n const data = JSON.parse(readFileSync(this.storePath, 'utf-8'));\n if (data.version === 1) {\n return data;\n }\n } catch {\n // Fall through to default\n }\n }\n return { version: 1, links: [] };\n }\n\n private save(): void {\n const dir = join(this.storePath, '..');\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true });\n }\n writeFileSync(this.storePath, JSON.stringify(this.store, null, 2));\n }\n\n /**\n * Add a link between two issues\n */\n addLink(\n source: { ref: string; tracker: TrackerType },\n target: { ref: string; tracker: TrackerType },\n direction: LinkDirection = 'related'\n ): TrackerLink {\n // Check if link already exists\n const existing = this.store.links.find(\n (l) =>\n l.sourceIssueRef === source.ref &&\n l.sourceTracker === source.tracker &&\n l.targetIssueRef === target.ref &&\n l.targetTracker === target.tracker\n );\n\n if (existing) {\n // Update direction if different\n if (existing.direction !== direction) {\n existing.direction = direction;\n this.save();\n }\n return existing;\n }\n\n const link: TrackerLink = {\n sourceIssueRef: source.ref,\n sourceTracker: source.tracker,\n targetIssueRef: target.ref,\n targetTracker: target.tracker,\n direction,\n createdAt: new Date().toISOString(),\n };\n\n this.store.links.push(link);\n this.save();\n return link;\n }\n\n /**\n * Remove a link between two issues\n */\n removeLink(\n source: { ref: string; tracker: TrackerType },\n target: { ref: string; tracker: TrackerType }\n ): boolean {\n const index = this.store.links.findIndex(\n (l) =>\n l.sourceIssueRef === source.ref &&\n l.sourceTracker === source.tracker &&\n l.targetIssueRef === target.ref &&\n l.targetTracker === target.tracker\n );\n\n if (index >= 0) {\n this.store.links.splice(index, 1);\n this.save();\n return true;\n }\n return false;\n }\n\n /**\n * Get all issues linked to a given issue\n */\n getLinkedIssues(ref: string, tracker: TrackerType): TrackerLink[] {\n return this.store.links.filter(\n (l) =>\n (l.sourceIssueRef === ref && l.sourceTracker === tracker) ||\n (l.targetIssueRef === ref && l.targetTracker === tracker)\n );\n }\n\n /**\n * Get all links (for debugging/admin)\n */\n getAllLinks(): TrackerLink[] {\n return [...this.store.links];\n }\n\n /**\n * Find linked issue in another tracker\n */\n findLinkedIssue(\n ref: string,\n sourceTracker: TrackerType,\n targetTracker: TrackerType\n ): string | null {\n // Check as source\n const asSource = this.store.links.find(\n (l) =>\n l.sourceIssueRef === ref &&\n l.sourceTracker === sourceTracker &&\n l.targetTracker === targetTracker\n );\n if (asSource) return asSource.targetIssueRef;\n\n // Check as target\n const asTarget = this.store.links.find(\n (l) =>\n l.targetIssueRef === ref &&\n l.targetTracker === sourceTracker &&\n l.sourceTracker === targetTracker\n );\n if (asTarget) return asTarget.sourceIssueRef;\n\n return null;\n }\n\n /**\n * Clear all links (for testing)\n */\n clear(): void {\n this.store.links = [];\n this.save();\n }\n}\n\n// Singleton instance\nlet _linkManager: LinkManager | null = null;\n\nexport function getLinkManager(): LinkManager {\n if (!_linkManager) {\n _linkManager = new LinkManager();\n }\n return _linkManager;\n}\n","/**\n * Issue Tracker Module\n *\n * Provides a unified interface for different issue tracking systems.\n */\n\n// Core interface and types\nexport type {\n IssueTracker,\n Issue,\n IssueFilters,\n IssueState,\n IssueUpdate,\n NewIssue,\n Comment,\n TrackerType,\n} from './interface.js';\n\nexport {\n NotImplementedError,\n IssueNotFoundError,\n TrackerAuthError,\n} from './interface.js';\n\n// Tracker implementations\nexport { LinearTracker } from './linear.js';\nexport { GitHubTracker } from './github.js';\nexport { GitLabTracker } from './gitlab.js';\n\n// Factory functions\nexport type { TrackerConfig } from './factory.js';\nexport {\n createTracker,\n createTrackerFromConfig,\n getPrimaryTracker,\n getSecondaryTracker,\n getAllTrackers,\n} from './factory.js';\n\n// Cross-tracker linking\nexport type { TrackerLink, LinkDirection } from './linking.js';\nexport {\n LinkManager,\n getLinkManager,\n parseIssueRef,\n formatIssueRef,\n} from './linking.js';\n"],"mappings":"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","names":["existsSync","join","existsSync","mkdirSync","readdirSync","lstatSync","rmSync","join","STATE_MAP","readFileSync","existsSync","mkdirSync","join","homedir"]}
|
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
killSession,
|
|
13
13
|
sendKeys,
|
|
14
14
|
sessionExists
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-65DGYSS4.js";
|
|
16
16
|
import {
|
|
17
17
|
getProviderEnv,
|
|
18
18
|
getProviderForModel,
|
|
@@ -913,4 +913,4 @@ export {
|
|
|
913
913
|
autoRecoverAgents,
|
|
914
914
|
init_agents
|
|
915
915
|
};
|
|
916
|
-
//# sourceMappingURL=chunk-
|
|
916
|
+
//# sourceMappingURL=chunk-XTXWSLT3.js.map
|