panopticon-cli 0.1.3 → 0.1.6
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/README.md +408 -9
- package/dist/chunk-RM3WGTFO.js +1058 -0
- package/dist/chunk-RM3WGTFO.js.map +1 -0
- package/dist/cli/index.js +1725 -717
- package/dist/cli/index.js.map +1 -1
- package/dist/index.d.ts +368 -5
- package/dist/index.js +43 -1
- package/package.json +2 -1
- package/templates/traefik/README.md +106 -0
- package/templates/traefik/docker-compose.yml +40 -0
- package/templates/traefik/dynamic/panopticon.yml +51 -0
- package/templates/traefik/dynamic/workspace.yml.template +34 -0
- package/templates/traefik/traefik.yml +45 -0
- package/dist/chunk-FR2P66GU.js +0 -352
- package/dist/chunk-FR2P66GU.js.map +0 -1
package/dist/index.d.ts
CHANGED
|
@@ -5,6 +5,10 @@ declare const COMMANDS_DIR: string;
|
|
|
5
5
|
declare const AGENTS_DIR: string;
|
|
6
6
|
declare const BACKUPS_DIR: string;
|
|
7
7
|
declare const COSTS_DIR: string;
|
|
8
|
+
declare const TRAEFIK_DIR: string;
|
|
9
|
+
declare const TRAEFIK_DYNAMIC_DIR: string;
|
|
10
|
+
declare const TRAEFIK_CERTS_DIR: string;
|
|
11
|
+
declare const CERTS_DIR: string;
|
|
8
12
|
declare const CONFIG_FILE: string;
|
|
9
13
|
declare const CLAUDE_DIR: string;
|
|
10
14
|
declare const CODEX_DIR: string;
|
|
@@ -31,8 +35,174 @@ declare const SYNC_TARGETS: {
|
|
|
31
35
|
type Runtime = keyof typeof SYNC_TARGETS;
|
|
32
36
|
declare const TEMPLATES_DIR: string;
|
|
33
37
|
declare const CLAUDE_MD_TEMPLATES: string;
|
|
38
|
+
declare const SOURCE_TEMPLATES_DIR: string;
|
|
39
|
+
declare const SOURCE_TRAEFIK_TEMPLATES: string;
|
|
34
40
|
declare const INIT_DIRS: string[];
|
|
35
41
|
|
|
42
|
+
/**
|
|
43
|
+
* Issue Tracker Abstraction Layer
|
|
44
|
+
*
|
|
45
|
+
* Provides a unified interface for different issue tracking systems
|
|
46
|
+
* (Linear, GitHub Issues, GitLab Issues, etc.)
|
|
47
|
+
*/
|
|
48
|
+
type TrackerType = 'linear' | 'github' | 'gitlab';
|
|
49
|
+
type IssueState = 'open' | 'in_progress' | 'closed';
|
|
50
|
+
interface Issue {
|
|
51
|
+
/** Tracker-specific unique ID */
|
|
52
|
+
id: string;
|
|
53
|
+
/** Human-readable reference (e.g., MIN-630, #42) */
|
|
54
|
+
ref: string;
|
|
55
|
+
/** Issue title */
|
|
56
|
+
title: string;
|
|
57
|
+
/** Issue description/body (markdown) */
|
|
58
|
+
description: string;
|
|
59
|
+
/** Normalized state */
|
|
60
|
+
state: IssueState;
|
|
61
|
+
/** Labels/tags */
|
|
62
|
+
labels: string[];
|
|
63
|
+
/** Assignee username/name */
|
|
64
|
+
assignee?: string;
|
|
65
|
+
/** Web URL to the issue */
|
|
66
|
+
url: string;
|
|
67
|
+
/** Which tracker this issue came from */
|
|
68
|
+
tracker: TrackerType;
|
|
69
|
+
/** Cross-tracker linked issue references */
|
|
70
|
+
linkedIssues?: string[];
|
|
71
|
+
/** Priority (1=urgent, 2=high, 3=normal, 4=low) */
|
|
72
|
+
priority?: number;
|
|
73
|
+
/** Due date (ISO string) */
|
|
74
|
+
dueDate?: string;
|
|
75
|
+
/** Creation timestamp (ISO string) */
|
|
76
|
+
createdAt: string;
|
|
77
|
+
/** Last update timestamp (ISO string) */
|
|
78
|
+
updatedAt: string;
|
|
79
|
+
}
|
|
80
|
+
interface Comment {
|
|
81
|
+
id: string;
|
|
82
|
+
issueId: string;
|
|
83
|
+
body: string;
|
|
84
|
+
author: string;
|
|
85
|
+
createdAt: string;
|
|
86
|
+
updatedAt: string;
|
|
87
|
+
}
|
|
88
|
+
interface IssueFilters {
|
|
89
|
+
/** Filter by state */
|
|
90
|
+
state?: IssueState;
|
|
91
|
+
/** Filter by labels (AND logic) */
|
|
92
|
+
labels?: string[];
|
|
93
|
+
/** Filter by assignee */
|
|
94
|
+
assignee?: string;
|
|
95
|
+
/** Filter by team/project (tracker-specific) */
|
|
96
|
+
team?: string;
|
|
97
|
+
/** Search query for title/description */
|
|
98
|
+
query?: string;
|
|
99
|
+
/** Maximum number of results */
|
|
100
|
+
limit?: number;
|
|
101
|
+
/** Include closed issues (default: false) */
|
|
102
|
+
includeClosed?: boolean;
|
|
103
|
+
}
|
|
104
|
+
interface NewIssue {
|
|
105
|
+
title: string;
|
|
106
|
+
description?: string;
|
|
107
|
+
labels?: string[];
|
|
108
|
+
assignee?: string;
|
|
109
|
+
team?: string;
|
|
110
|
+
priority?: number;
|
|
111
|
+
dueDate?: string;
|
|
112
|
+
}
|
|
113
|
+
interface IssueUpdate {
|
|
114
|
+
title?: string;
|
|
115
|
+
description?: string;
|
|
116
|
+
state?: IssueState;
|
|
117
|
+
labels?: string[];
|
|
118
|
+
assignee?: string;
|
|
119
|
+
priority?: number;
|
|
120
|
+
dueDate?: string;
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Abstract interface for issue trackers.
|
|
124
|
+
* Implementations must handle normalization to/from tracker-specific formats.
|
|
125
|
+
*/
|
|
126
|
+
interface IssueTracker {
|
|
127
|
+
/** Tracker type identifier */
|
|
128
|
+
readonly name: TrackerType;
|
|
129
|
+
/**
|
|
130
|
+
* List issues matching filters
|
|
131
|
+
*/
|
|
132
|
+
listIssues(filters?: IssueFilters): Promise<Issue[]>;
|
|
133
|
+
/**
|
|
134
|
+
* Get a single issue by ID or ref
|
|
135
|
+
* @param id - Issue ID or human-readable ref (e.g., "MIN-630", "#42")
|
|
136
|
+
*/
|
|
137
|
+
getIssue(id: string): Promise<Issue>;
|
|
138
|
+
/**
|
|
139
|
+
* Update an existing issue
|
|
140
|
+
*/
|
|
141
|
+
updateIssue(id: string, update: IssueUpdate): Promise<Issue>;
|
|
142
|
+
/**
|
|
143
|
+
* Create a new issue
|
|
144
|
+
*/
|
|
145
|
+
createIssue(issue: NewIssue): Promise<Issue>;
|
|
146
|
+
/**
|
|
147
|
+
* Get comments on an issue
|
|
148
|
+
*/
|
|
149
|
+
getComments(issueId: string): Promise<Comment[]>;
|
|
150
|
+
/**
|
|
151
|
+
* Add a comment to an issue
|
|
152
|
+
*/
|
|
153
|
+
addComment(issueId: string, body: string): Promise<Comment>;
|
|
154
|
+
/**
|
|
155
|
+
* Transition issue to a new state
|
|
156
|
+
*/
|
|
157
|
+
transitionIssue(id: string, state: IssueState): Promise<void>;
|
|
158
|
+
/**
|
|
159
|
+
* Link a PR/MR to an issue
|
|
160
|
+
*/
|
|
161
|
+
linkPR(issueId: string, prUrl: string): Promise<void>;
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Error thrown when a tracker feature is not implemented
|
|
165
|
+
*/
|
|
166
|
+
declare class NotImplementedError extends Error {
|
|
167
|
+
constructor(feature: string);
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Error thrown when an issue is not found
|
|
171
|
+
*/
|
|
172
|
+
declare class IssueNotFoundError extends Error {
|
|
173
|
+
constructor(id: string, tracker: TrackerType);
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Error thrown when tracker authentication fails
|
|
177
|
+
*/
|
|
178
|
+
declare class TrackerAuthError extends Error {
|
|
179
|
+
constructor(tracker: TrackerType, message: string);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
interface LinearConfig {
|
|
183
|
+
type: 'linear';
|
|
184
|
+
api_key_env?: string;
|
|
185
|
+
team?: string;
|
|
186
|
+
}
|
|
187
|
+
interface GitHubConfig {
|
|
188
|
+
type: 'github';
|
|
189
|
+
token_env?: string;
|
|
190
|
+
owner: string;
|
|
191
|
+
repo: string;
|
|
192
|
+
}
|
|
193
|
+
interface GitLabConfig {
|
|
194
|
+
type: 'gitlab';
|
|
195
|
+
token_env?: string;
|
|
196
|
+
project_id: string;
|
|
197
|
+
}
|
|
198
|
+
type TrackerConfigItem = LinearConfig | GitHubConfig | GitLabConfig;
|
|
199
|
+
interface TrackersConfig {
|
|
200
|
+
primary: TrackerType;
|
|
201
|
+
secondary?: TrackerType;
|
|
202
|
+
linear?: LinearConfig;
|
|
203
|
+
github?: GitHubConfig;
|
|
204
|
+
gitlab?: GitLabConfig;
|
|
205
|
+
}
|
|
36
206
|
interface PanopticonConfig {
|
|
37
207
|
panopticon: {
|
|
38
208
|
version: string;
|
|
@@ -40,15 +210,19 @@ interface PanopticonConfig {
|
|
|
40
210
|
sync: {
|
|
41
211
|
targets: string[];
|
|
42
212
|
backup_before_sync: boolean;
|
|
213
|
+
auto_sync?: boolean;
|
|
214
|
+
strategy?: 'symlink' | 'copy';
|
|
43
215
|
};
|
|
44
|
-
trackers:
|
|
45
|
-
primary: string;
|
|
46
|
-
secondary?: string;
|
|
47
|
-
};
|
|
216
|
+
trackers: TrackersConfig;
|
|
48
217
|
dashboard: {
|
|
49
218
|
port: number;
|
|
50
219
|
api_port: number;
|
|
51
220
|
};
|
|
221
|
+
traefik?: {
|
|
222
|
+
enabled: boolean;
|
|
223
|
+
dashboard_port?: number;
|
|
224
|
+
domain?: string;
|
|
225
|
+
};
|
|
52
226
|
}
|
|
53
227
|
declare function loadConfig(): PanopticonConfig;
|
|
54
228
|
declare function saveConfig(config: PanopticonConfig): void;
|
|
@@ -105,4 +279,193 @@ interface SyncResult {
|
|
|
105
279
|
*/
|
|
106
280
|
declare function executeSync(runtime: Runtime, options?: SyncOptions): SyncResult;
|
|
107
281
|
|
|
108
|
-
|
|
282
|
+
/**
|
|
283
|
+
* Linear Issue Tracker Adapter
|
|
284
|
+
*
|
|
285
|
+
* Implements IssueTracker interface for Linear.
|
|
286
|
+
*/
|
|
287
|
+
|
|
288
|
+
declare class LinearTracker implements IssueTracker {
|
|
289
|
+
readonly name: TrackerType;
|
|
290
|
+
private client;
|
|
291
|
+
private defaultTeam?;
|
|
292
|
+
constructor(apiKey: string, options?: {
|
|
293
|
+
team?: string;
|
|
294
|
+
});
|
|
295
|
+
listIssues(filters?: IssueFilters): Promise<Issue[]>;
|
|
296
|
+
getIssue(id: string): Promise<Issue>;
|
|
297
|
+
updateIssue(id: string, update: IssueUpdate): Promise<Issue>;
|
|
298
|
+
createIssue(newIssue: NewIssue): Promise<Issue>;
|
|
299
|
+
getComments(issueId: string): Promise<Comment[]>;
|
|
300
|
+
addComment(issueId: string, body: string): Promise<Comment>;
|
|
301
|
+
transitionIssue(id: string, state: IssueState): Promise<void>;
|
|
302
|
+
linkPR(issueId: string, prUrl: string): Promise<void>;
|
|
303
|
+
private normalizeIssue;
|
|
304
|
+
private mapState;
|
|
305
|
+
private reverseMapState;
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
/**
|
|
309
|
+
* GitHub Issues Tracker Adapter
|
|
310
|
+
*
|
|
311
|
+
* Implements IssueTracker interface for GitHub Issues.
|
|
312
|
+
*/
|
|
313
|
+
|
|
314
|
+
declare class GitHubTracker implements IssueTracker {
|
|
315
|
+
readonly name: TrackerType;
|
|
316
|
+
private octokit;
|
|
317
|
+
private owner;
|
|
318
|
+
private repo;
|
|
319
|
+
constructor(token: string, owner: string, repo: string);
|
|
320
|
+
listIssues(filters?: IssueFilters): Promise<Issue[]>;
|
|
321
|
+
getIssue(id: string): Promise<Issue>;
|
|
322
|
+
updateIssue(id: string, update: IssueUpdate): Promise<Issue>;
|
|
323
|
+
createIssue(newIssue: NewIssue): Promise<Issue>;
|
|
324
|
+
getComments(issueId: string): Promise<Comment[]>;
|
|
325
|
+
addComment(issueId: string, body: string): Promise<Comment>;
|
|
326
|
+
transitionIssue(id: string, state: IssueState): Promise<void>;
|
|
327
|
+
linkPR(issueId: string, prUrl: string): Promise<void>;
|
|
328
|
+
private normalizeIssue;
|
|
329
|
+
private mapStateFromGitHub;
|
|
330
|
+
private mapStateToGitHub;
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
/**
|
|
334
|
+
* GitLab Issues Tracker Adapter (Stub)
|
|
335
|
+
*
|
|
336
|
+
* Placeholder implementation for GitLab Issues support.
|
|
337
|
+
* Full implementation will use @gitbeaker/rest.
|
|
338
|
+
*/
|
|
339
|
+
|
|
340
|
+
declare class GitLabTracker implements IssueTracker {
|
|
341
|
+
private token;
|
|
342
|
+
private projectId;
|
|
343
|
+
readonly name: TrackerType;
|
|
344
|
+
constructor(token: string, projectId: string);
|
|
345
|
+
listIssues(_filters?: IssueFilters): Promise<Issue[]>;
|
|
346
|
+
getIssue(_id: string): Promise<Issue>;
|
|
347
|
+
updateIssue(_id: string, _update: IssueUpdate): Promise<Issue>;
|
|
348
|
+
createIssue(_issue: NewIssue): Promise<Issue>;
|
|
349
|
+
getComments(_issueId: string): Promise<Comment[]>;
|
|
350
|
+
addComment(_issueId: string, _body: string): Promise<Comment>;
|
|
351
|
+
transitionIssue(_id: string, _state: IssueState): Promise<void>;
|
|
352
|
+
linkPR(_issueId: string, _prUrl: string): Promise<void>;
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
/**
|
|
356
|
+
* Tracker Factory
|
|
357
|
+
*
|
|
358
|
+
* Creates appropriate tracker instances based on configuration.
|
|
359
|
+
*/
|
|
360
|
+
|
|
361
|
+
interface TrackerConfig {
|
|
362
|
+
type: TrackerType;
|
|
363
|
+
apiKeyEnv?: string;
|
|
364
|
+
team?: string;
|
|
365
|
+
tokenEnv?: string;
|
|
366
|
+
owner?: string;
|
|
367
|
+
repo?: string;
|
|
368
|
+
projectId?: string;
|
|
369
|
+
}
|
|
370
|
+
/**
|
|
371
|
+
* Create a tracker instance from configuration
|
|
372
|
+
*/
|
|
373
|
+
declare function createTracker(config: TrackerConfig): IssueTracker;
|
|
374
|
+
/**
|
|
375
|
+
* Create tracker from trackers configuration section
|
|
376
|
+
*/
|
|
377
|
+
declare function createTrackerFromConfig(trackersConfig: TrackersConfig, trackerType: TrackerType): IssueTracker;
|
|
378
|
+
/**
|
|
379
|
+
* Get the primary tracker from configuration
|
|
380
|
+
*/
|
|
381
|
+
declare function getPrimaryTracker(trackersConfig: TrackersConfig): IssueTracker;
|
|
382
|
+
/**
|
|
383
|
+
* Get the secondary tracker from configuration (if configured)
|
|
384
|
+
*/
|
|
385
|
+
declare function getSecondaryTracker(trackersConfig: TrackersConfig): IssueTracker | null;
|
|
386
|
+
/**
|
|
387
|
+
* Get all configured trackers
|
|
388
|
+
*/
|
|
389
|
+
declare function getAllTrackers(trackersConfig: TrackersConfig): IssueTracker[];
|
|
390
|
+
|
|
391
|
+
/**
|
|
392
|
+
* Cross-Tracker Linking
|
|
393
|
+
*
|
|
394
|
+
* Manages links between issues in different trackers.
|
|
395
|
+
* Links are stored in a local JSON file for persistence.
|
|
396
|
+
*/
|
|
397
|
+
|
|
398
|
+
type LinkDirection = 'blocks' | 'blocked_by' | 'related' | 'duplicate_of';
|
|
399
|
+
interface TrackerLink {
|
|
400
|
+
sourceIssueRef: string;
|
|
401
|
+
sourceTracker: TrackerType;
|
|
402
|
+
targetIssueRef: string;
|
|
403
|
+
targetTracker: TrackerType;
|
|
404
|
+
direction: LinkDirection;
|
|
405
|
+
createdAt: string;
|
|
406
|
+
}
|
|
407
|
+
/**
|
|
408
|
+
* Parse an issue reference to extract tracker and ID
|
|
409
|
+
* Examples:
|
|
410
|
+
* "#42" -> { tracker: "github", ref: "#42" }
|
|
411
|
+
* "github#42" -> { tracker: "github", ref: "#42" }
|
|
412
|
+
* "MIN-630" -> { tracker: "linear", ref: "MIN-630" }
|
|
413
|
+
* "gitlab#15" -> { tracker: "gitlab", ref: "#15" }
|
|
414
|
+
*/
|
|
415
|
+
declare function parseIssueRef(ref: string): {
|
|
416
|
+
tracker: TrackerType;
|
|
417
|
+
ref: string;
|
|
418
|
+
} | null;
|
|
419
|
+
/**
|
|
420
|
+
* Format an issue ref with tracker prefix for display
|
|
421
|
+
*/
|
|
422
|
+
declare function formatIssueRef(ref: string, tracker: TrackerType): string;
|
|
423
|
+
/**
|
|
424
|
+
* Link Manager for cross-tracker issue linking
|
|
425
|
+
*/
|
|
426
|
+
declare class LinkManager {
|
|
427
|
+
private storePath;
|
|
428
|
+
private store;
|
|
429
|
+
constructor(storePath?: string);
|
|
430
|
+
private load;
|
|
431
|
+
private save;
|
|
432
|
+
/**
|
|
433
|
+
* Add a link between two issues
|
|
434
|
+
*/
|
|
435
|
+
addLink(source: {
|
|
436
|
+
ref: string;
|
|
437
|
+
tracker: TrackerType;
|
|
438
|
+
}, target: {
|
|
439
|
+
ref: string;
|
|
440
|
+
tracker: TrackerType;
|
|
441
|
+
}, direction?: LinkDirection): TrackerLink;
|
|
442
|
+
/**
|
|
443
|
+
* Remove a link between two issues
|
|
444
|
+
*/
|
|
445
|
+
removeLink(source: {
|
|
446
|
+
ref: string;
|
|
447
|
+
tracker: TrackerType;
|
|
448
|
+
}, target: {
|
|
449
|
+
ref: string;
|
|
450
|
+
tracker: TrackerType;
|
|
451
|
+
}): boolean;
|
|
452
|
+
/**
|
|
453
|
+
* Get all issues linked to a given issue
|
|
454
|
+
*/
|
|
455
|
+
getLinkedIssues(ref: string, tracker: TrackerType): TrackerLink[];
|
|
456
|
+
/**
|
|
457
|
+
* Get all links (for debugging/admin)
|
|
458
|
+
*/
|
|
459
|
+
getAllLinks(): TrackerLink[];
|
|
460
|
+
/**
|
|
461
|
+
* Find linked issue in another tracker
|
|
462
|
+
*/
|
|
463
|
+
findLinkedIssue(ref: string, sourceTracker: TrackerType, targetTracker: TrackerType): string | null;
|
|
464
|
+
/**
|
|
465
|
+
* Clear all links (for testing)
|
|
466
|
+
*/
|
|
467
|
+
clear(): void;
|
|
468
|
+
}
|
|
469
|
+
declare function getLinkManager(): LinkManager;
|
|
470
|
+
|
|
471
|
+
export { AGENTS_DIR, BACKUPS_DIR, type BackupInfo, CERTS_DIR, CLAUDE_DIR, CLAUDE_MD_TEMPLATES, CODEX_DIR, COMMANDS_DIR, CONFIG_DIR, CONFIG_FILE, COSTS_DIR, CURSOR_DIR, type Comment, GEMINI_DIR, type GitHubConfig, GitHubTracker, type GitLabConfig, GitLabTracker, INIT_DIRS, type Issue, type IssueFilters, IssueNotFoundError, type IssueState, type IssueTracker, type IssueUpdate, type LinearConfig, LinearTracker, type LinkDirection, LinkManager, type NewIssue, NotImplementedError, PANOPTICON_HOME, type PanopticonConfig, type Runtime, SKILLS_DIR, SOURCE_TEMPLATES_DIR, SOURCE_TRAEFIK_TEMPLATES, SYNC_TARGETS, type Shell, type SyncItem, type SyncOptions, type SyncPlan, type SyncResult, TEMPLATES_DIR, TRAEFIK_CERTS_DIR, TRAEFIK_DIR, TRAEFIK_DYNAMIC_DIR, TrackerAuthError, type TrackerConfig, type TrackerConfigItem, type TrackerLink, type TrackerType, type TrackersConfig, addAlias, cleanOldBackups, createBackup, createBackupTimestamp, createTracker, createTrackerFromConfig, detectShell, executeSync, formatIssueRef, getAliasInstructions, getAllTrackers, getDefaultConfig, getLinkManager, getPrimaryTracker, getSecondaryTracker, getShellRcFile, hasAlias, isPanopticonSymlink, listBackups, loadConfig, parseIssueRef, planSync, restoreBackup, saveConfig };
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
AGENTS_DIR,
|
|
3
3
|
BACKUPS_DIR,
|
|
4
|
+
CERTS_DIR,
|
|
4
5
|
CLAUDE_DIR,
|
|
5
6
|
CLAUDE_MD_TEMPLATES,
|
|
6
7
|
CODEX_DIR,
|
|
@@ -10,31 +11,52 @@ import {
|
|
|
10
11
|
COSTS_DIR,
|
|
11
12
|
CURSOR_DIR,
|
|
12
13
|
GEMINI_DIR,
|
|
14
|
+
GitHubTracker,
|
|
15
|
+
GitLabTracker,
|
|
13
16
|
INIT_DIRS,
|
|
17
|
+
IssueNotFoundError,
|
|
18
|
+
LinearTracker,
|
|
19
|
+
LinkManager,
|
|
20
|
+
NotImplementedError,
|
|
14
21
|
PANOPTICON_HOME,
|
|
15
22
|
SKILLS_DIR,
|
|
23
|
+
SOURCE_TEMPLATES_DIR,
|
|
24
|
+
SOURCE_TRAEFIK_TEMPLATES,
|
|
16
25
|
SYNC_TARGETS,
|
|
17
26
|
TEMPLATES_DIR,
|
|
27
|
+
TRAEFIK_CERTS_DIR,
|
|
28
|
+
TRAEFIK_DIR,
|
|
29
|
+
TRAEFIK_DYNAMIC_DIR,
|
|
30
|
+
TrackerAuthError,
|
|
18
31
|
addAlias,
|
|
19
32
|
cleanOldBackups,
|
|
20
33
|
createBackup,
|
|
21
34
|
createBackupTimestamp,
|
|
35
|
+
createTracker,
|
|
36
|
+
createTrackerFromConfig,
|
|
22
37
|
detectShell,
|
|
23
38
|
executeSync,
|
|
39
|
+
formatIssueRef,
|
|
24
40
|
getAliasInstructions,
|
|
41
|
+
getAllTrackers,
|
|
25
42
|
getDefaultConfig,
|
|
43
|
+
getLinkManager,
|
|
44
|
+
getPrimaryTracker,
|
|
45
|
+
getSecondaryTracker,
|
|
26
46
|
getShellRcFile,
|
|
27
47
|
hasAlias,
|
|
28
48
|
isPanopticonSymlink,
|
|
29
49
|
listBackups,
|
|
30
50
|
loadConfig,
|
|
51
|
+
parseIssueRef,
|
|
31
52
|
planSync,
|
|
32
53
|
restoreBackup,
|
|
33
54
|
saveConfig
|
|
34
|
-
} from "./chunk-
|
|
55
|
+
} from "./chunk-RM3WGTFO.js";
|
|
35
56
|
export {
|
|
36
57
|
AGENTS_DIR,
|
|
37
58
|
BACKUPS_DIR,
|
|
59
|
+
CERTS_DIR,
|
|
38
60
|
CLAUDE_DIR,
|
|
39
61
|
CLAUDE_MD_TEMPLATES,
|
|
40
62
|
CODEX_DIR,
|
|
@@ -44,24 +66,44 @@ export {
|
|
|
44
66
|
COSTS_DIR,
|
|
45
67
|
CURSOR_DIR,
|
|
46
68
|
GEMINI_DIR,
|
|
69
|
+
GitHubTracker,
|
|
70
|
+
GitLabTracker,
|
|
47
71
|
INIT_DIRS,
|
|
72
|
+
IssueNotFoundError,
|
|
73
|
+
LinearTracker,
|
|
74
|
+
LinkManager,
|
|
75
|
+
NotImplementedError,
|
|
48
76
|
PANOPTICON_HOME,
|
|
49
77
|
SKILLS_DIR,
|
|
78
|
+
SOURCE_TEMPLATES_DIR,
|
|
79
|
+
SOURCE_TRAEFIK_TEMPLATES,
|
|
50
80
|
SYNC_TARGETS,
|
|
51
81
|
TEMPLATES_DIR,
|
|
82
|
+
TRAEFIK_CERTS_DIR,
|
|
83
|
+
TRAEFIK_DIR,
|
|
84
|
+
TRAEFIK_DYNAMIC_DIR,
|
|
85
|
+
TrackerAuthError,
|
|
52
86
|
addAlias,
|
|
53
87
|
cleanOldBackups,
|
|
54
88
|
createBackup,
|
|
55
89
|
createBackupTimestamp,
|
|
90
|
+
createTracker,
|
|
91
|
+
createTrackerFromConfig,
|
|
56
92
|
detectShell,
|
|
57
93
|
executeSync,
|
|
94
|
+
formatIssueRef,
|
|
58
95
|
getAliasInstructions,
|
|
96
|
+
getAllTrackers,
|
|
59
97
|
getDefaultConfig,
|
|
98
|
+
getLinkManager,
|
|
99
|
+
getPrimaryTracker,
|
|
100
|
+
getSecondaryTracker,
|
|
60
101
|
getShellRcFile,
|
|
61
102
|
hasAlias,
|
|
62
103
|
isPanopticonSymlink,
|
|
63
104
|
listBackups,
|
|
64
105
|
loadConfig,
|
|
106
|
+
parseIssueRef,
|
|
65
107
|
planSync,
|
|
66
108
|
restoreBackup,
|
|
67
109
|
saveConfig
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "panopticon-cli",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.6",
|
|
4
4
|
"description": "Multi-agent orchestration for AI coding assistants (Claude Code, Codex, Cursor, Gemini CLI)",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ai-agents",
|
|
@@ -50,6 +50,7 @@
|
|
|
50
50
|
"dependencies": {
|
|
51
51
|
"@iarna/toml": "^2.2.5",
|
|
52
52
|
"@linear/sdk": "^70.0.0",
|
|
53
|
+
"@octokit/rest": "^22.0.1",
|
|
53
54
|
"chalk": "^5.6.2",
|
|
54
55
|
"commander": "^12.1.0",
|
|
55
56
|
"conf": "^12.0.0",
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
# Panopticon Traefik Configuration
|
|
2
|
+
|
|
3
|
+
Traefik reverse proxy for local development with HTTPS.
|
|
4
|
+
|
|
5
|
+
## Directory Structure
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
~/.panopticon/traefik/
|
|
9
|
+
├── docker-compose.yml # Traefik container definition
|
|
10
|
+
├── traefik.yml # Static configuration
|
|
11
|
+
├── dynamic/ # Dynamic routing configs
|
|
12
|
+
│ └── panopticon.yml # Dashboard routing
|
|
13
|
+
├── certs/ # mkcert SSL certificates
|
|
14
|
+
│ ├── _wildcard.pan.localhost.pem
|
|
15
|
+
│ └── _wildcard.pan.localhost-key.pem
|
|
16
|
+
└── README.md # This file
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## URLs
|
|
20
|
+
|
|
21
|
+
| URL | Service |
|
|
22
|
+
|-----|---------|
|
|
23
|
+
| `https://pan.localhost` | Panopticon Dashboard (Frontend) |
|
|
24
|
+
| `https://pan.localhost/api/*` | Panopticon Dashboard (API) |
|
|
25
|
+
| `http://localhost:8080` | Traefik Dashboard |
|
|
26
|
+
|
|
27
|
+
## How It Works
|
|
28
|
+
|
|
29
|
+
### Static Configuration (`traefik.yml`)
|
|
30
|
+
- Defines entry points (HTTP:80, HTTPS:443)
|
|
31
|
+
- Enables Traefik dashboard on port 8080
|
|
32
|
+
- Configures file provider for dynamic configs
|
|
33
|
+
- Sets up TLS with wildcard certificates
|
|
34
|
+
|
|
35
|
+
### Dynamic Configuration (`dynamic/panopticon.yml`)
|
|
36
|
+
- Routes `https://pan.localhost` to dashboard frontend (port 3001)
|
|
37
|
+
- Routes `https://pan.localhost/api/*` to dashboard API (port 3002)
|
|
38
|
+
- Uses `host.docker.internal` to access host-based services
|
|
39
|
+
|
|
40
|
+
### Docker Compose
|
|
41
|
+
- Runs Traefik v3.0 in a container
|
|
42
|
+
- Exposes ports 80, 443, 8080
|
|
43
|
+
- Mounts configuration files and certificates
|
|
44
|
+
- Uses `panopticon` network for container communication
|
|
45
|
+
|
|
46
|
+
## Prerequisites
|
|
47
|
+
|
|
48
|
+
1. **mkcert certificates** must be generated first:
|
|
49
|
+
```bash
|
|
50
|
+
mkcert "*.pan.localhost" "*.localhost" localhost 127.0.0.1 ::1
|
|
51
|
+
```
|
|
52
|
+
Certificates should be in `~/.panopticon/traefik/certs/`
|
|
53
|
+
|
|
54
|
+
2. **DNS/Hosts configuration**:
|
|
55
|
+
- Add to `/etc/hosts`: `127.0.0.1 pan.localhost`
|
|
56
|
+
- Wildcard `*.localhost` resolves automatically on most systems
|
|
57
|
+
|
|
58
|
+
## Usage
|
|
59
|
+
|
|
60
|
+
Start Traefik:
|
|
61
|
+
```bash
|
|
62
|
+
cd ~/.panopticon/traefik
|
|
63
|
+
docker-compose up -d
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
Stop Traefik:
|
|
67
|
+
```bash
|
|
68
|
+
cd ~/.panopticon/traefik
|
|
69
|
+
docker-compose down
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
View logs:
|
|
73
|
+
```bash
|
|
74
|
+
docker logs -f panopticon-traefik
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## Managed by CLI
|
|
78
|
+
|
|
79
|
+
These commands are automated via `pan` CLI:
|
|
80
|
+
- `pan install` - Sets up Traefik (creates configs, generates certs)
|
|
81
|
+
- `pan up` - Starts Traefik container
|
|
82
|
+
- `pan down` - Stops Traefik container
|
|
83
|
+
|
|
84
|
+
## Adding Workspace Routes
|
|
85
|
+
|
|
86
|
+
Workspace-specific routes should be added as separate YAML files in `dynamic/`:
|
|
87
|
+
|
|
88
|
+
```yaml
|
|
89
|
+
# dynamic/feature-pan-4.yml
|
|
90
|
+
http:
|
|
91
|
+
routers:
|
|
92
|
+
workspace-feature-pan-4-frontend:
|
|
93
|
+
rule: "Host(`feature-pan-4.myn.localhost`)"
|
|
94
|
+
service: workspace-feature-pan-4-frontend
|
|
95
|
+
entryPoints:
|
|
96
|
+
- websecure
|
|
97
|
+
tls: {}
|
|
98
|
+
|
|
99
|
+
services:
|
|
100
|
+
workspace-feature-pan-4-frontend:
|
|
101
|
+
loadBalancer:
|
|
102
|
+
servers:
|
|
103
|
+
- url: "http://workspace-feature-pan-4-frontend:3000"
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
These are auto-generated by `pan workspace create` and `pan workspace start`.
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
services:
|
|
2
|
+
traefik:
|
|
3
|
+
image: traefik:v3.0
|
|
4
|
+
container_name: panopticon-traefik
|
|
5
|
+
restart: unless-stopped
|
|
6
|
+
ports:
|
|
7
|
+
- "8081:80" # HTTP (redirects to HTTPS)
|
|
8
|
+
- "8443:443" # HTTPS
|
|
9
|
+
- "8082:8080" # Traefik Dashboard
|
|
10
|
+
volumes:
|
|
11
|
+
# Traefik configuration
|
|
12
|
+
- ./traefik.yml:/etc/traefik/traefik.yml:ro
|
|
13
|
+
- ./dynamic:/etc/traefik/dynamic:ro
|
|
14
|
+
|
|
15
|
+
# TLS certificates (mkcert generated)
|
|
16
|
+
- ./certs:/etc/traefik/certs:ro
|
|
17
|
+
|
|
18
|
+
# Docker socket for service discovery
|
|
19
|
+
- /var/run/docker.sock:/var/run/docker.sock:ro
|
|
20
|
+
|
|
21
|
+
networks:
|
|
22
|
+
- panopticon
|
|
23
|
+
|
|
24
|
+
labels:
|
|
25
|
+
- "traefik.enable=true"
|
|
26
|
+
|
|
27
|
+
# Dashboard routing (traefik.pan.localhost:8080)
|
|
28
|
+
- "traefik.http.routers.traefik-dashboard.rule=Host(`traefik.pan.localhost`)"
|
|
29
|
+
- "traefik.http.routers.traefik-dashboard.entrypoints=websecure"
|
|
30
|
+
- "traefik.http.routers.traefik-dashboard.tls=true"
|
|
31
|
+
- "traefik.http.routers.traefik-dashboard.service=api@internal"
|
|
32
|
+
|
|
33
|
+
extra_hosts:
|
|
34
|
+
# Allow Traefik to reach host services (dashboard on ports 3001/3002)
|
|
35
|
+
- "host.docker.internal:host-gateway"
|
|
36
|
+
|
|
37
|
+
networks:
|
|
38
|
+
panopticon:
|
|
39
|
+
name: panopticon
|
|
40
|
+
driver: bridge
|