@made-by-moonlight/athene-core 0.9.1
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/LICENSE +22 -0
- package/README.md +241 -0
- package/dist/activity-events.d.ts +42 -0
- package/dist/activity-events.d.ts.map +1 -0
- package/dist/activity-events.js +192 -0
- package/dist/activity-events.js.map +1 -0
- package/dist/activity-log.d.ts +71 -0
- package/dist/activity-log.d.ts.map +1 -0
- package/dist/activity-log.js +203 -0
- package/dist/activity-log.js.map +1 -0
- package/dist/activity-signal.d.ts +20 -0
- package/dist/activity-signal.d.ts.map +1 -0
- package/dist/activity-signal.js +91 -0
- package/dist/activity-signal.js.map +1 -0
- package/dist/agent-report.d.ts +148 -0
- package/dist/agent-report.d.ts.map +1 -0
- package/dist/agent-report.js +516 -0
- package/dist/agent-report.js.map +1 -0
- package/dist/agent-selection.d.ts +31 -0
- package/dist/agent-selection.d.ts.map +1 -0
- package/dist/agent-selection.js +69 -0
- package/dist/agent-selection.js.map +1 -0
- package/dist/agent-workspace-hooks.d.ts +74 -0
- package/dist/agent-workspace-hooks.d.ts.map +1 -0
- package/dist/agent-workspace-hooks.js +988 -0
- package/dist/agent-workspace-hooks.js.map +1 -0
- package/dist/atomic-write.d.ts +6 -0
- package/dist/atomic-write.d.ts.map +1 -0
- package/dist/atomic-write.js +49 -0
- package/dist/atomic-write.js.map +1 -0
- package/dist/cleanup-stack.d.ts +37 -0
- package/dist/cleanup-stack.d.ts.map +1 -0
- package/dist/cleanup-stack.js +45 -0
- package/dist/cleanup-stack.js.map +1 -0
- package/dist/code-review-manager.d.ts +118 -0
- package/dist/code-review-manager.d.ts.map +1 -0
- package/dist/code-review-manager.js +719 -0
- package/dist/code-review-manager.js.map +1 -0
- package/dist/code-review-store.d.ts +114 -0
- package/dist/code-review-store.d.ts.map +1 -0
- package/dist/code-review-store.js +346 -0
- package/dist/code-review-store.js.map +1 -0
- package/dist/config-generator.d.ts +84 -0
- package/dist/config-generator.d.ts.map +1 -0
- package/dist/config-generator.js +295 -0
- package/dist/config-generator.js.map +1 -0
- package/dist/config.d.ts +55 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +852 -0
- package/dist/config.js.map +1 -0
- package/dist/daemon-children.d.ts +55 -0
- package/dist/daemon-children.d.ts.map +1 -0
- package/dist/daemon-children.js +435 -0
- package/dist/daemon-children.js.map +1 -0
- package/dist/dashboard-notifications.d.ts +42 -0
- package/dist/dashboard-notifications.d.ts.map +1 -0
- package/dist/dashboard-notifications.js +123 -0
- package/dist/dashboard-notifications.js.map +1 -0
- package/dist/events-db.d.ts +39 -0
- package/dist/events-db.d.ts.map +1 -0
- package/dist/events-db.js +185 -0
- package/dist/events-db.js.map +1 -0
- package/dist/feature-flags.d.ts +2 -0
- package/dist/feature-flags.d.ts.map +1 -0
- package/dist/feature-flags.js +9 -0
- package/dist/feature-flags.js.map +1 -0
- package/dist/feedback-tools.d.ts +97 -0
- package/dist/feedback-tools.d.ts.map +1 -0
- package/dist/feedback-tools.js +161 -0
- package/dist/feedback-tools.js.map +1 -0
- package/dist/file-lock.d.ts +5 -0
- package/dist/file-lock.d.ts.map +1 -0
- package/dist/file-lock.js +59 -0
- package/dist/file-lock.js.map +1 -0
- package/dist/format-automated-comments.d.ts +18 -0
- package/dist/format-automated-comments.d.ts.map +1 -0
- package/dist/gh-trace.d.ts +57 -0
- package/dist/gh-trace.d.ts.map +1 -0
- package/dist/gh-trace.js +320 -0
- package/dist/gh-trace.js.map +1 -0
- package/dist/git-activity.d.ts +10 -0
- package/dist/git-activity.d.ts.map +1 -0
- package/dist/git-activity.js +30 -0
- package/dist/git-activity.js.map +1 -0
- package/dist/global-config.d.ts +1085 -0
- package/dist/global-config.d.ts.map +1 -0
- package/dist/global-config.js +1067 -0
- package/dist/global-config.js.map +1 -0
- package/dist/index.d.ts +91 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +59 -0
- package/dist/index.js.map +1 -0
- package/dist/key-value.d.ts +7 -0
- package/dist/key-value.d.ts.map +1 -0
- package/dist/key-value.js +24 -0
- package/dist/key-value.js.map +1 -0
- package/dist/lifecycle-manager.d.ts +22 -0
- package/dist/lifecycle-manager.d.ts.map +1 -0
- package/dist/lifecycle-manager.js +2813 -0
- package/dist/lifecycle-manager.js.map +1 -0
- package/dist/lifecycle-state.d.ts +28 -0
- package/dist/lifecycle-state.d.ts.map +1 -0
- package/dist/lifecycle-state.js +446 -0
- package/dist/lifecycle-state.js.map +1 -0
- package/dist/lifecycle-status-decisions.d.ts +85 -0
- package/dist/lifecycle-status-decisions.d.ts.map +1 -0
- package/dist/lifecycle-status-decisions.js +262 -0
- package/dist/lifecycle-status-decisions.js.map +1 -0
- package/dist/lifecycle-transition.d.ts +81 -0
- package/dist/lifecycle-transition.d.ts.map +1 -0
- package/dist/lifecycle-transition.js +207 -0
- package/dist/lifecycle-transition.js.map +1 -0
- package/dist/metadata.d.ts +54 -0
- package/dist/metadata.d.ts.map +1 -0
- package/dist/metadata.js +484 -0
- package/dist/metadata.js.map +1 -0
- package/dist/migration/storage-v2.d.ts +76 -0
- package/dist/migration/storage-v2.d.ts.map +1 -0
- package/dist/migration/storage-v2.js +1614 -0
- package/dist/migration/storage-v2.js.map +1 -0
- package/dist/notification-data.d.ts +135 -0
- package/dist/notification-data.d.ts.map +1 -0
- package/dist/notification-data.js +204 -0
- package/dist/notification-data.js.map +1 -0
- package/dist/notification-observability.d.ts +21 -0
- package/dist/notification-observability.d.ts.map +1 -0
- package/dist/notification-observability.js +154 -0
- package/dist/notification-observability.js.map +1 -0
- package/dist/notifier-resolution.d.ts +14 -0
- package/dist/notifier-resolution.d.ts.map +1 -0
- package/dist/notifier-resolution.js +23 -0
- package/dist/notifier-resolution.js.map +1 -0
- package/dist/observability.d.ts +100 -0
- package/dist/observability.d.ts.map +1 -0
- package/dist/observability.js +535 -0
- package/dist/observability.js.map +1 -0
- package/dist/opencode-agents-md.d.ts +3 -0
- package/dist/opencode-agents-md.d.ts.map +1 -0
- package/dist/opencode-agents-md.js +40 -0
- package/dist/opencode-agents-md.js.map +1 -0
- package/dist/opencode-config.d.ts +2 -0
- package/dist/opencode-config.d.ts.map +1 -0
- package/dist/opencode-config.js +17 -0
- package/dist/opencode-config.js.map +1 -0
- package/dist/opencode-session-id.d.ts +2 -0
- package/dist/opencode-session-id.d.ts.map +1 -0
- package/dist/opencode-session-id.js +12 -0
- package/dist/opencode-session-id.js.map +1 -0
- package/dist/opencode-shared.d.ts +80 -0
- package/dist/opencode-shared.d.ts.map +1 -0
- package/dist/opencode-shared.js +202 -0
- package/dist/opencode-shared.js.map +1 -0
- package/dist/orchestrator-prompt.d.ts +19 -0
- package/dist/orchestrator-prompt.d.ts.map +1 -0
- package/dist/orchestrator-prompt.js +130 -0
- package/dist/orchestrator-prompt.js.map +1 -0
- package/dist/orchestrator-session-strategy.d.ts +5 -0
- package/dist/orchestrator-session-strategy.d.ts.map +1 -0
- package/dist/orchestrator-session-strategy.js +13 -0
- package/dist/orchestrator-session-strategy.js.map +1 -0
- package/dist/paths.d.ts +145 -0
- package/dist/paths.d.ts.map +1 -0
- package/dist/paths.js +288 -0
- package/dist/paths.js.map +1 -0
- package/dist/platform.d.ts +32 -0
- package/dist/platform.d.ts.map +1 -0
- package/dist/platform.js +211 -0
- package/dist/platform.js.map +1 -0
- package/dist/plugin-registry.d.ts +15 -0
- package/dist/plugin-registry.d.ts.map +1 -0
- package/dist/plugin-registry.js +499 -0
- package/dist/plugin-registry.js.map +1 -0
- package/dist/portfolio-projects.d.ts +7 -0
- package/dist/portfolio-projects.d.ts.map +1 -0
- package/dist/portfolio-projects.js +65 -0
- package/dist/portfolio-projects.js.map +1 -0
- package/dist/portfolio-registry.d.ts +42 -0
- package/dist/portfolio-registry.d.ts.map +1 -0
- package/dist/portfolio-registry.js +311 -0
- package/dist/portfolio-registry.js.map +1 -0
- package/dist/portfolio-routing.d.ts +5 -0
- package/dist/portfolio-routing.d.ts.map +1 -0
- package/dist/portfolio-routing.js +24 -0
- package/dist/portfolio-routing.js.map +1 -0
- package/dist/portfolio-session-service.d.ts +15 -0
- package/dist/portfolio-session-service.d.ts.map +1 -0
- package/dist/portfolio-session-service.js +206 -0
- package/dist/portfolio-session-service.js.map +1 -0
- package/dist/process-cache.d.ts +32 -0
- package/dist/process-cache.d.ts.map +1 -0
- package/dist/process-cache.js +44 -0
- package/dist/process-cache.js.map +1 -0
- package/dist/project-resolver.d.ts +5 -0
- package/dist/project-resolver.d.ts.map +1 -0
- package/dist/project-resolver.js +20 -0
- package/dist/project-resolver.js.map +1 -0
- package/dist/prompt-builder.d.ts +42 -0
- package/dist/prompt-builder.d.ts.map +1 -0
- package/dist/prompt-builder.js +182 -0
- package/dist/prompt-builder.js.map +1 -0
- package/dist/prompts/orchestrator.md.js +4 -0
- package/dist/prompts/orchestrator.md.js.map +1 -0
- package/dist/query-activity-events.d.ts +42 -0
- package/dist/query-activity-events.d.ts.map +1 -0
- package/dist/query-activity-events.js +170 -0
- package/dist/query-activity-events.js.map +1 -0
- package/dist/recovery/actions.d.ts +7 -0
- package/dist/recovery/actions.d.ts.map +1 -0
- package/dist/recovery/index.d.ts +8 -0
- package/dist/recovery/index.d.ts.map +1 -0
- package/dist/recovery/logger.d.ts +12 -0
- package/dist/recovery/logger.d.ts.map +1 -0
- package/dist/recovery/manager.d.ts +24 -0
- package/dist/recovery/manager.d.ts.map +1 -0
- package/dist/recovery/scanner.d.ts +11 -0
- package/dist/recovery/scanner.d.ts.map +1 -0
- package/dist/recovery/types.d.ts +170 -0
- package/dist/recovery/types.d.ts.map +1 -0
- package/dist/recovery/validator.d.ts +8 -0
- package/dist/recovery/validator.d.ts.map +1 -0
- package/dist/report-watcher.d.ts +93 -0
- package/dist/report-watcher.d.ts.map +1 -0
- package/dist/report-watcher.js +182 -0
- package/dist/report-watcher.js.map +1 -0
- package/dist/scm-webhook-utils.d.ts +6 -0
- package/dist/scm-webhook-utils.d.ts.map +1 -0
- package/dist/scm-webhook-utils.js +36 -0
- package/dist/scm-webhook-utils.js.map +1 -0
- package/dist/session-manager.d.ts +22 -0
- package/dist/session-manager.d.ts.map +1 -0
- package/dist/session-manager.js +3077 -0
- package/dist/session-manager.js.map +1 -0
- package/dist/spawn-target.d.ts +23 -0
- package/dist/spawn-target.d.ts.map +1 -0
- package/dist/spawn-target.js +39 -0
- package/dist/spawn-target.js.map +1 -0
- package/dist/storage-key.d.ts +9 -0
- package/dist/storage-key.d.ts.map +1 -0
- package/dist/storage-key.js +59 -0
- package/dist/storage-key.js.map +1 -0
- package/dist/tmux.d.ts +39 -0
- package/dist/tmux.d.ts.map +1 -0
- package/dist/tmux.js +141 -0
- package/dist/tmux.js.map +1 -0
- package/dist/types.d.ts +1496 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +215 -0
- package/dist/types.js.map +1 -0
- package/dist/update-cache.d.ts +59 -0
- package/dist/update-cache.d.ts.map +1 -0
- package/dist/update-cache.js +77 -0
- package/dist/update-cache.js.map +1 -0
- package/dist/utils/metadata-flatten.d.ts +3 -0
- package/dist/utils/metadata-flatten.d.ts.map +1 -0
- package/dist/utils/metadata-flatten.js +18 -0
- package/dist/utils/metadata-flatten.js.map +1 -0
- package/dist/utils/pr.d.ts +7 -0
- package/dist/utils/pr.d.ts.map +1 -0
- package/dist/utils/pr.js +97 -0
- package/dist/utils/pr.js.map +1 -0
- package/dist/utils/session-from-metadata.d.ts +16 -0
- package/dist/utils/session-from-metadata.d.ts.map +1 -0
- package/dist/utils/session-from-metadata.js +87 -0
- package/dist/utils/session-from-metadata.js.map +1 -0
- package/dist/utils/session-id.d.ts +4 -0
- package/dist/utils/session-id.d.ts.map +1 -0
- package/dist/utils/session-id.js +9 -0
- package/dist/utils/session-id.js.map +1 -0
- package/dist/utils/validation.d.ts +9 -0
- package/dist/utils/validation.d.ts.map +1 -0
- package/dist/utils/validation.js +45 -0
- package/dist/utils/validation.js.map +1 -0
- package/dist/utils.d.ts +65 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/utils.js +189 -0
- package/dist/utils.js.map +1 -0
- package/dist/version-compare.d.ts +27 -0
- package/dist/version-compare.d.ts.map +1 -0
- package/dist/version-compare.js +121 -0
- package/dist/version-compare.js.map +1 -0
- package/dist/windows-pty-registry.d.ts +27 -0
- package/dist/windows-pty-registry.d.ts.map +1 -0
- package/dist/windows-pty-registry.js +109 -0
- package/dist/windows-pty-registry.js.map +1 -0
- package/package.json +110 -0
|
@@ -0,0 +1,499 @@
|
|
|
1
|
+
import { existsSync, statSync, readFileSync } from 'node:fs';
|
|
2
|
+
import { join, resolve, isAbsolute, dirname } from 'node:path';
|
|
3
|
+
import { pathToFileURL } from 'node:url';
|
|
4
|
+
import { recordActivityEvent } from './activity-events.js';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Plugin Registry — discovers and loads plugins.
|
|
8
|
+
*
|
|
9
|
+
* Plugins can be:
|
|
10
|
+
* 1. Built-in (packages/plugins/*)
|
|
11
|
+
* 2. npm packages (@made-by-moonlight/athene-plugin-*)
|
|
12
|
+
* 3. Local file paths specified in config
|
|
13
|
+
*/
|
|
14
|
+
const LOCAL_PLUGIN_ENTRY_CANDIDATES = ["dist/index.js", "index.js"];
|
|
15
|
+
function makeKey(slot, name) {
|
|
16
|
+
return `${slot}:${name}`;
|
|
17
|
+
}
|
|
18
|
+
/** Built-in plugin package names, mapped to their npm package */
|
|
19
|
+
const BUILTIN_PLUGINS = [
|
|
20
|
+
// Runtimes
|
|
21
|
+
{ slot: "runtime", name: "tmux", pkg: "@made-by-moonlight/athene-plugin-runtime-tmux" },
|
|
22
|
+
{ slot: "runtime", name: "process", pkg: "@made-by-moonlight/athene-plugin-runtime-process" },
|
|
23
|
+
// Agents
|
|
24
|
+
{ slot: "agent", name: "claude-code", pkg: "@made-by-moonlight/athene-plugin-agent-claude-code" },
|
|
25
|
+
{ slot: "agent", name: "codex", pkg: "@made-by-moonlight/athene-plugin-agent-codex" },
|
|
26
|
+
{ slot: "agent", name: "aider", pkg: "@made-by-moonlight/athene-plugin-agent-aider" },
|
|
27
|
+
{ slot: "agent", name: "cursor", pkg: "@made-by-moonlight/athene-plugin-agent-cursor" },
|
|
28
|
+
{ slot: "agent", name: "kimicode", pkg: "@made-by-moonlight/athene-plugin-agent-kimicode" },
|
|
29
|
+
{ slot: "agent", name: "grok", pkg: "@made-by-moonlight/athene-plugin-agent-grok" },
|
|
30
|
+
{ slot: "agent", name: "opencode", pkg: "@made-by-moonlight/athene-plugin-agent-opencode" },
|
|
31
|
+
// Workspaces
|
|
32
|
+
{ slot: "workspace", name: "worktree", pkg: "@made-by-moonlight/athene-plugin-workspace-worktree" },
|
|
33
|
+
{ slot: "workspace", name: "clone", pkg: "@made-by-moonlight/athene-plugin-workspace-clone" },
|
|
34
|
+
// Trackers
|
|
35
|
+
{ slot: "tracker", name: "github", pkg: "@made-by-moonlight/athene-plugin-tracker-github" },
|
|
36
|
+
{ slot: "tracker", name: "linear", pkg: "@made-by-moonlight/athene-plugin-tracker-linear" },
|
|
37
|
+
{ slot: "tracker", name: "gitlab", pkg: "@made-by-moonlight/athene-plugin-tracker-gitlab" },
|
|
38
|
+
// SCM
|
|
39
|
+
{ slot: "scm", name: "github", pkg: "@made-by-moonlight/athene-plugin-scm-github" },
|
|
40
|
+
{ slot: "scm", name: "gitlab", pkg: "@made-by-moonlight/athene-plugin-scm-gitlab" },
|
|
41
|
+
// Notifiers
|
|
42
|
+
{ slot: "notifier", name: "composio", pkg: "@made-by-moonlight/athene-plugin-notifier-composio" },
|
|
43
|
+
{ slot: "notifier", name: "dashboard", pkg: "@made-by-moonlight/athene-plugin-notifier-dashboard" },
|
|
44
|
+
{ slot: "notifier", name: "desktop", pkg: "@made-by-moonlight/athene-plugin-notifier-desktop" },
|
|
45
|
+
{ slot: "notifier", name: "discord", pkg: "@made-by-moonlight/athene-plugin-notifier-discord" },
|
|
46
|
+
{ slot: "notifier", name: "openclaw", pkg: "@made-by-moonlight/athene-plugin-notifier-openclaw" },
|
|
47
|
+
{ slot: "notifier", name: "slack", pkg: "@made-by-moonlight/athene-plugin-notifier-slack" },
|
|
48
|
+
{ slot: "notifier", name: "webhook", pkg: "@made-by-moonlight/athene-plugin-notifier-webhook" },
|
|
49
|
+
// Terminals
|
|
50
|
+
{ slot: "terminal", name: "iterm2", pkg: "@made-by-moonlight/athene-plugin-terminal-iterm2" },
|
|
51
|
+
{ slot: "terminal", name: "web", pkg: "@made-by-moonlight/athene-plugin-terminal-web" },
|
|
52
|
+
];
|
|
53
|
+
function matchesNotifierPlugin(pluginName, notifierId, notifierConfig) {
|
|
54
|
+
const configuredPlugin = notifierConfig["plugin"];
|
|
55
|
+
const hasExplicitPlugin = typeof configuredPlugin === "string" && configuredPlugin.length > 0;
|
|
56
|
+
return hasExplicitPlugin ? configuredPlugin === pluginName : notifierId === pluginName;
|
|
57
|
+
}
|
|
58
|
+
function hasExplicitConflictingNotifierEntry(pluginName, config) {
|
|
59
|
+
if (!Object.prototype.hasOwnProperty.call(config.notifiers ?? {}, pluginName))
|
|
60
|
+
return false;
|
|
61
|
+
const exactMatch = config.notifiers?.[pluginName];
|
|
62
|
+
return (!exactMatch ||
|
|
63
|
+
typeof exactMatch !== "object" ||
|
|
64
|
+
!matchesNotifierPlugin(pluginName, pluginName, exactMatch));
|
|
65
|
+
}
|
|
66
|
+
function collectNotifierRegistrations(pluginName, config, isExternalLoad = false) {
|
|
67
|
+
const orderedMatches = new Map();
|
|
68
|
+
const notifierEntries = Object.entries(config.notifiers ?? {});
|
|
69
|
+
const defaultNotifiers = Array.isArray(config.defaults?.notifiers)
|
|
70
|
+
? config.defaults.notifiers
|
|
71
|
+
: [];
|
|
72
|
+
const routingNotifiers = Object.values(config.notificationRouting ?? {}).flatMap((value) => Array.isArray(value) ? value : []);
|
|
73
|
+
const isReferencedByName = defaultNotifiers.includes(pluginName) || routingNotifiers.includes(pluginName);
|
|
74
|
+
const exactMatch = config.notifiers?.[pluginName];
|
|
75
|
+
if (exactMatch &&
|
|
76
|
+
typeof exactMatch === "object" &&
|
|
77
|
+
matchesNotifierPlugin(pluginName, pluginName, exactMatch)) {
|
|
78
|
+
orderedMatches.set(pluginName, exactMatch);
|
|
79
|
+
}
|
|
80
|
+
for (const [notifierId, notifierConfig] of notifierEntries) {
|
|
81
|
+
if (!notifierConfig || typeof notifierConfig !== "object")
|
|
82
|
+
continue;
|
|
83
|
+
if (matchesNotifierPlugin(pluginName, notifierId, notifierConfig)) {
|
|
84
|
+
orderedMatches.set(notifierId, notifierConfig);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
if (orderedMatches.size === 0 &&
|
|
88
|
+
isReferencedByName &&
|
|
89
|
+
!hasExplicitConflictingNotifierEntry(pluginName, config)) {
|
|
90
|
+
orderedMatches.set(pluginName, {});
|
|
91
|
+
}
|
|
92
|
+
return [...orderedMatches.entries()].map(([registrationName, rawConfig]) => ({
|
|
93
|
+
registrationName,
|
|
94
|
+
config: prepareConfig("notifier", pluginName, registrationName, rawConfig, config.configPath, isExternalLoad),
|
|
95
|
+
}));
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Internal helper to validate and strip loading metadata from a plugin configuration.
|
|
99
|
+
* Reserved fields (plugin, package, path) are used for plugin resolution and stripped.
|
|
100
|
+
*/
|
|
101
|
+
function prepareConfig(slot, name, sourceId, rawConfig, configPath, isExternalLoad = false) {
|
|
102
|
+
// Explicitly check for reserved fields to prevent silent stripping/collision.
|
|
103
|
+
// 'path' is reserved for local resolution; 'package' is reserved for npm resolution.
|
|
104
|
+
if ("package" in rawConfig && "path" in rawConfig) {
|
|
105
|
+
throw new Error(`In ${slot} "${sourceId}": both "package" and "path" are specified. ` +
|
|
106
|
+
`Use "package" for npm plugins or "path" for local plugins, not both.`);
|
|
107
|
+
}
|
|
108
|
+
// If loading via built-in name or npm package, having a 'path' field is ambiguous:
|
|
109
|
+
// it could be a local plugin path (for loading) or a plugin config value.
|
|
110
|
+
// We reject this to avoid silently stripping a config value the user intended to pass.
|
|
111
|
+
// Skip the built-in guard for external loads: when loading via `path`, the manifest.name
|
|
112
|
+
// may legitimately collide with a built-in (e.g. a forked "slack"), and the path field
|
|
113
|
+
// here IS the loading path, not a stray user config value.
|
|
114
|
+
const isBuiltin = !isExternalLoad && BUILTIN_PLUGINS.some((b) => b.slot === slot && b.name === name);
|
|
115
|
+
if ((rawConfig.package || isBuiltin) && "path" in rawConfig) {
|
|
116
|
+
const loadingMethod = rawConfig.package
|
|
117
|
+
? `npm package "${rawConfig.package}"`
|
|
118
|
+
: `built-in plugin "${name}"`;
|
|
119
|
+
throw new Error(`In ${slot} "${sourceId}": "path" field conflicts with reserved plugin loading field. ` +
|
|
120
|
+
`You're loading via ${loadingMethod}, but also have a "path" field which would be stripped. ` +
|
|
121
|
+
`Rename your configuration field to something else (e.g., "apiPath", "webhookPath").`);
|
|
122
|
+
}
|
|
123
|
+
// Strip loading metadata fields (plugin, package, path) from config passed to plugin.
|
|
124
|
+
const { plugin: _plugin, package: _package, path: _path, ...rest } = rawConfig;
|
|
125
|
+
return configPath ? { ...rest, configPath } : rest;
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Build an index of external plugin entries by package/path for O(1) lookups.
|
|
129
|
+
* Multiple entries can share the same package/path (e.g., multiple projects using same plugin).
|
|
130
|
+
*/
|
|
131
|
+
function buildExternalPluginIndex(externalEntries) {
|
|
132
|
+
const index = new Map();
|
|
133
|
+
if (!externalEntries)
|
|
134
|
+
return index;
|
|
135
|
+
for (const entry of externalEntries) {
|
|
136
|
+
const key = entry.package ? `package:${entry.package}` : `path:${entry.path}`;
|
|
137
|
+
const existing = index.get(key);
|
|
138
|
+
if (existing) {
|
|
139
|
+
existing.push(entry);
|
|
140
|
+
}
|
|
141
|
+
else {
|
|
142
|
+
index.set(key, [entry]);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
return index;
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Find ALL external plugin entries that match a given plugin config.
|
|
149
|
+
* Used for manifest.name validation when loading inline tracker/scm/notifier plugins.
|
|
150
|
+
*
|
|
151
|
+
* Returns all matching entries because multiple projects may share the same
|
|
152
|
+
* external plugin (same package/path), and all their configs need to be updated
|
|
153
|
+
* with the actual manifest.name.
|
|
154
|
+
*/
|
|
155
|
+
function findAllExternalPluginEntries(plugin, externalIndex) {
|
|
156
|
+
if (plugin.package) {
|
|
157
|
+
return externalIndex.get(`package:${plugin.package}`) ?? [];
|
|
158
|
+
}
|
|
159
|
+
if (plugin.path) {
|
|
160
|
+
return externalIndex.get(`path:${plugin.path}`) ?? [];
|
|
161
|
+
}
|
|
162
|
+
return [];
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Validate that a plugin's manifest.name matches the expected name (if specified).
|
|
166
|
+
* Throws an error if there's a mismatch.
|
|
167
|
+
*/
|
|
168
|
+
function validateManifestName(manifest, entry, specifier) {
|
|
169
|
+
// If the user specified an explicit plugin name, validate it matches the manifest
|
|
170
|
+
if (entry.expectedPluginName && entry.expectedPluginName !== manifest.name) {
|
|
171
|
+
const specifierType = entry.package ? "package" : "path";
|
|
172
|
+
throw new Error(`Plugin manifest.name mismatch at ${entry.source}: ` +
|
|
173
|
+
`expected "${entry.expectedPluginName}" but ${specifierType} "${specifier}" has manifest.name "${manifest.name}". ` +
|
|
174
|
+
`Either update the 'plugin' field to match the actual manifest.name, or remove it to auto-infer.`);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Update the config with the actual plugin name after loading an external plugin.
|
|
179
|
+
* This ensures resolvePlugins() can look up the plugin by its manifest.name.
|
|
180
|
+
*
|
|
181
|
+
* Uses structured location data to avoid ambiguity from parsing dotted strings
|
|
182
|
+
* (project/notifier keys can legally contain dots).
|
|
183
|
+
*/
|
|
184
|
+
function updateConfigWithManifestName(manifest, entry, config) {
|
|
185
|
+
const { location, slot, source } = entry;
|
|
186
|
+
// Use structured location to update the config
|
|
187
|
+
if (location.kind === "project") {
|
|
188
|
+
const { projectId, configType } = location;
|
|
189
|
+
const project = config.projects[projectId];
|
|
190
|
+
if (project?.[configType]) {
|
|
191
|
+
project[configType].plugin = manifest.name;
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
else if (location.kind === "notifier") {
|
|
195
|
+
const { notifierId } = location;
|
|
196
|
+
const notifierConfig = config.notifiers[notifierId];
|
|
197
|
+
if (notifierConfig) {
|
|
198
|
+
notifierConfig.plugin = manifest.name;
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
// Also validate slot matches
|
|
202
|
+
if (manifest.slot !== slot) {
|
|
203
|
+
process.stderr.write(`[plugin-registry] Plugin at ${source} has slot "${manifest.slot}" but was configured as "${slot}". ` +
|
|
204
|
+
`The plugin will be registered under its declared slot "${manifest.slot}".\n`);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
function isPluginModule(value) {
|
|
208
|
+
if (!value || typeof value !== "object")
|
|
209
|
+
return false;
|
|
210
|
+
const candidate = value;
|
|
211
|
+
return Boolean(candidate.manifest && typeof candidate.create === "function");
|
|
212
|
+
}
|
|
213
|
+
function normalizeImportedPluginModule(value) {
|
|
214
|
+
if (isPluginModule(value))
|
|
215
|
+
return value;
|
|
216
|
+
if (value && typeof value === "object" && "default" in value) {
|
|
217
|
+
const defaultExport = value.default;
|
|
218
|
+
if (isPluginModule(defaultExport))
|
|
219
|
+
return defaultExport;
|
|
220
|
+
}
|
|
221
|
+
return null;
|
|
222
|
+
}
|
|
223
|
+
function resolveConfigRelativePath(targetPath, configPath) {
|
|
224
|
+
if (isAbsolute(targetPath))
|
|
225
|
+
return targetPath;
|
|
226
|
+
const baseDir = configPath ? dirname(configPath) : process.cwd();
|
|
227
|
+
return resolve(baseDir, targetPath);
|
|
228
|
+
}
|
|
229
|
+
function resolvePackageExportsEntry(exportsField) {
|
|
230
|
+
if (typeof exportsField === "string")
|
|
231
|
+
return exportsField;
|
|
232
|
+
if (!exportsField || typeof exportsField !== "object")
|
|
233
|
+
return null;
|
|
234
|
+
const exportsRecord = exportsField;
|
|
235
|
+
const dotEntry = exportsRecord["."];
|
|
236
|
+
if (typeof dotEntry === "string")
|
|
237
|
+
return dotEntry;
|
|
238
|
+
if (dotEntry && typeof dotEntry === "object") {
|
|
239
|
+
const importEntry = dotEntry["import"];
|
|
240
|
+
if (typeof importEntry === "string")
|
|
241
|
+
return importEntry;
|
|
242
|
+
const defaultEntry = dotEntry["default"];
|
|
243
|
+
if (typeof defaultEntry === "string")
|
|
244
|
+
return defaultEntry;
|
|
245
|
+
}
|
|
246
|
+
const importEntry = exportsRecord["import"];
|
|
247
|
+
if (typeof importEntry === "string")
|
|
248
|
+
return importEntry;
|
|
249
|
+
const defaultEntry = exportsRecord["default"];
|
|
250
|
+
if (typeof defaultEntry === "string")
|
|
251
|
+
return defaultEntry;
|
|
252
|
+
return null;
|
|
253
|
+
}
|
|
254
|
+
function resolveLocalPluginEntrypoint(pluginPath) {
|
|
255
|
+
if (!existsSync(pluginPath))
|
|
256
|
+
return null;
|
|
257
|
+
let stat;
|
|
258
|
+
try {
|
|
259
|
+
stat = statSync(pluginPath);
|
|
260
|
+
}
|
|
261
|
+
catch {
|
|
262
|
+
return null;
|
|
263
|
+
}
|
|
264
|
+
if (stat.isFile())
|
|
265
|
+
return pluginPath;
|
|
266
|
+
if (!stat.isDirectory())
|
|
267
|
+
return null;
|
|
268
|
+
const packageJsonPath = join(pluginPath, "package.json");
|
|
269
|
+
if (existsSync(packageJsonPath)) {
|
|
270
|
+
try {
|
|
271
|
+
const raw = readFileSync(packageJsonPath, "utf-8");
|
|
272
|
+
const packageJson = JSON.parse(raw);
|
|
273
|
+
const exportsEntry = resolvePackageExportsEntry(packageJson.exports);
|
|
274
|
+
if (exportsEntry) {
|
|
275
|
+
const resolvedEntry = resolve(pluginPath, exportsEntry);
|
|
276
|
+
if (existsSync(resolvedEntry))
|
|
277
|
+
return resolvedEntry;
|
|
278
|
+
}
|
|
279
|
+
if (typeof packageJson.module === "string") {
|
|
280
|
+
const moduleEntry = resolve(pluginPath, packageJson.module);
|
|
281
|
+
if (existsSync(moduleEntry))
|
|
282
|
+
return moduleEntry;
|
|
283
|
+
}
|
|
284
|
+
if (typeof packageJson.main === "string") {
|
|
285
|
+
const mainEntry = resolve(pluginPath, packageJson.main);
|
|
286
|
+
if (existsSync(mainEntry))
|
|
287
|
+
return mainEntry;
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
catch {
|
|
291
|
+
// Fall through to common entrypoint guesses below.
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
for (const candidate of LOCAL_PLUGIN_ENTRY_CANDIDATES) {
|
|
295
|
+
const entry = join(pluginPath, candidate);
|
|
296
|
+
if (existsSync(entry))
|
|
297
|
+
return entry;
|
|
298
|
+
}
|
|
299
|
+
return null;
|
|
300
|
+
}
|
|
301
|
+
function inferPackageSpecifier(value) {
|
|
302
|
+
if (!value)
|
|
303
|
+
return null;
|
|
304
|
+
if (value.startsWith(".") || value.startsWith("/"))
|
|
305
|
+
return null;
|
|
306
|
+
return value.startsWith("@") || value.includes("/") ? value : null;
|
|
307
|
+
}
|
|
308
|
+
function resolvePluginSpecifier(plugin, config) {
|
|
309
|
+
switch (plugin.source) {
|
|
310
|
+
case "local": {
|
|
311
|
+
if (!plugin.path)
|
|
312
|
+
return null;
|
|
313
|
+
const absolutePath = resolveConfigRelativePath(plugin.path, config.configPath);
|
|
314
|
+
const entrypoint = resolveLocalPluginEntrypoint(absolutePath);
|
|
315
|
+
return entrypoint ? pathToFileURL(entrypoint).href : null;
|
|
316
|
+
}
|
|
317
|
+
case "registry":
|
|
318
|
+
case "npm":
|
|
319
|
+
return plugin.package ?? inferPackageSpecifier(plugin.name);
|
|
320
|
+
default:
|
|
321
|
+
return null;
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
function createPluginRegistry() {
|
|
325
|
+
const plugins = new Map();
|
|
326
|
+
function registerInstance(slot, name, manifest, instance) {
|
|
327
|
+
plugins.set(makeKey(slot, name), { manifest, instance });
|
|
328
|
+
}
|
|
329
|
+
function registerNotifier(plugin, config, isExternalLoad = false) {
|
|
330
|
+
const { manifest } = plugin;
|
|
331
|
+
const registrations = collectNotifierRegistrations(manifest.name, config, isExternalLoad);
|
|
332
|
+
if (registrations.length === 0) {
|
|
333
|
+
if (hasExplicitConflictingNotifierEntry(manifest.name, config))
|
|
334
|
+
return;
|
|
335
|
+
registerInstance(manifest.slot, manifest.name, manifest, plugin.create(undefined));
|
|
336
|
+
return;
|
|
337
|
+
}
|
|
338
|
+
for (const [index, registration] of registrations.entries()) {
|
|
339
|
+
const instance = plugin.create(registration.config);
|
|
340
|
+
registerInstance(manifest.slot, registration.registrationName, manifest, instance);
|
|
341
|
+
if (index === 0 && registration.registrationName !== manifest.name) {
|
|
342
|
+
registerInstance(manifest.slot, manifest.name, manifest, instance);
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
return {
|
|
347
|
+
register(plugin, config) {
|
|
348
|
+
const { manifest } = plugin;
|
|
349
|
+
const instance = plugin.create(config);
|
|
350
|
+
registerInstance(manifest.slot, manifest.name, manifest, instance);
|
|
351
|
+
},
|
|
352
|
+
get(slot, name) {
|
|
353
|
+
const entry = plugins.get(makeKey(slot, name));
|
|
354
|
+
return entry ? entry.instance : null;
|
|
355
|
+
},
|
|
356
|
+
list(slot) {
|
|
357
|
+
const result = new Map();
|
|
358
|
+
for (const [key, entry] of plugins) {
|
|
359
|
+
if (key.startsWith(`${slot}:`) && !result.has(entry.manifest.name)) {
|
|
360
|
+
result.set(entry.manifest.name, entry.manifest);
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
return [...result.values()];
|
|
364
|
+
},
|
|
365
|
+
async loadBuiltins(orchestratorConfig, importFn) {
|
|
366
|
+
const doImport = importFn ?? ((pkg) => import(/* webpackIgnore: true */ pkg));
|
|
367
|
+
for (const builtin of BUILTIN_PLUGINS) {
|
|
368
|
+
let mod;
|
|
369
|
+
try {
|
|
370
|
+
mod = normalizeImportedPluginModule(await doImport(builtin.pkg));
|
|
371
|
+
}
|
|
372
|
+
catch {
|
|
373
|
+
// Plugin not installed — that's fine, only load what's available
|
|
374
|
+
continue;
|
|
375
|
+
}
|
|
376
|
+
if (mod) {
|
|
377
|
+
try {
|
|
378
|
+
if (orchestratorConfig && mod.manifest.slot === "notifier") {
|
|
379
|
+
registerNotifier(mod, orchestratorConfig);
|
|
380
|
+
}
|
|
381
|
+
else {
|
|
382
|
+
this.register(mod);
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
catch (error) {
|
|
386
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
387
|
+
process.stderr.write(`[plugin-registry] Failed to load built-in plugin "${builtin.name}": ${error}\n`);
|
|
388
|
+
recordActivityEvent({
|
|
389
|
+
source: "plugin-registry",
|
|
390
|
+
kind: "plugin-registry.load_failed",
|
|
391
|
+
level: "error",
|
|
392
|
+
summary: `built-in plugin ${builtin.name} failed to load`,
|
|
393
|
+
data: {
|
|
394
|
+
plugin: builtin.name,
|
|
395
|
+
slot: builtin.slot,
|
|
396
|
+
pkg: builtin.pkg,
|
|
397
|
+
builtin: true,
|
|
398
|
+
error: message,
|
|
399
|
+
},
|
|
400
|
+
});
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
},
|
|
405
|
+
async loadFromConfig(config, importFn) {
|
|
406
|
+
// Load built-ins with orchestrator config so plugins receive their settings
|
|
407
|
+
await this.loadBuiltins(config, importFn);
|
|
408
|
+
const doImport = importFn ?? ((pkg) => import(/* webpackIgnore: true */ pkg));
|
|
409
|
+
// Build index once for O(1) lookups when matching plugins to external entries
|
|
410
|
+
const externalIndex = buildExternalPluginIndex(config._externalPluginEntries);
|
|
411
|
+
for (const plugin of config.plugins ?? []) {
|
|
412
|
+
if (plugin.enabled === false)
|
|
413
|
+
continue;
|
|
414
|
+
const specifier = resolvePluginSpecifier(plugin, config);
|
|
415
|
+
if (!specifier) {
|
|
416
|
+
process.stderr.write(`[plugin-registry] Could not resolve specifier for plugin "${plugin.name}" (source: ${plugin.source})\n`);
|
|
417
|
+
recordActivityEvent({
|
|
418
|
+
source: "plugin-registry",
|
|
419
|
+
kind: "plugin-registry.specifier_failed",
|
|
420
|
+
level: "error",
|
|
421
|
+
summary: `could not resolve specifier for plugin ${plugin.name}`,
|
|
422
|
+
data: {
|
|
423
|
+
plugin: plugin.name,
|
|
424
|
+
source: plugin.source ?? null,
|
|
425
|
+
},
|
|
426
|
+
});
|
|
427
|
+
continue;
|
|
428
|
+
}
|
|
429
|
+
try {
|
|
430
|
+
const mod = normalizeImportedPluginModule(await doImport(specifier));
|
|
431
|
+
if (!mod)
|
|
432
|
+
continue;
|
|
433
|
+
// Check if this plugin was auto-added from inline tracker/scm/notifier config.
|
|
434
|
+
// Multiple projects may share the same external plugin, so find ALL matching entries.
|
|
435
|
+
// We validate and update configs FIRST so notifier alias registration uses
|
|
436
|
+
// the final manifest.name instead of any temporary inferred plugin name.
|
|
437
|
+
const matchingEntries = findAllExternalPluginEntries(plugin, externalIndex);
|
|
438
|
+
for (const externalEntry of matchingEntries) {
|
|
439
|
+
try {
|
|
440
|
+
// Validate manifest.name matches expectedPluginName (if specified)
|
|
441
|
+
validateManifestName(mod.manifest, externalEntry, specifier);
|
|
442
|
+
// Update the config with the actual manifest.name
|
|
443
|
+
updateConfigWithManifestName(mod.manifest, externalEntry, config);
|
|
444
|
+
}
|
|
445
|
+
catch (validationError) {
|
|
446
|
+
// Log validation errors but don't abort - other projects can still use the plugin.
|
|
447
|
+
// The misconfigured project will fail later when it tries to use the plugin
|
|
448
|
+
// with the wrong name, giving a clearer error at point of use.
|
|
449
|
+
const message = validationError instanceof Error
|
|
450
|
+
? validationError.message
|
|
451
|
+
: String(validationError);
|
|
452
|
+
process.stderr.write(`[plugin-registry] Config validation failed for ${externalEntry.source}: ${validationError}\n`);
|
|
453
|
+
recordActivityEvent({
|
|
454
|
+
source: "plugin-registry",
|
|
455
|
+
kind: "plugin-registry.validation_failed",
|
|
456
|
+
level: "error",
|
|
457
|
+
summary: `plugin manifest validation failed for ${plugin.name}`,
|
|
458
|
+
data: {
|
|
459
|
+
plugin: plugin.name,
|
|
460
|
+
externalSource: externalEntry.source,
|
|
461
|
+
specifier,
|
|
462
|
+
manifestName: mod.manifest.name,
|
|
463
|
+
manifestSlot: mod.manifest.slot,
|
|
464
|
+
error: message,
|
|
465
|
+
},
|
|
466
|
+
});
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
if (mod.manifest.slot === "notifier") {
|
|
470
|
+
registerNotifier(mod, config, true);
|
|
471
|
+
}
|
|
472
|
+
else {
|
|
473
|
+
this.register(mod);
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
catch (error) {
|
|
477
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
478
|
+
process.stderr.write(`[plugin-registry] Failed to load plugin "${specifier}": ${error}\n`);
|
|
479
|
+
recordActivityEvent({
|
|
480
|
+
source: "plugin-registry",
|
|
481
|
+
kind: "plugin-registry.load_failed",
|
|
482
|
+
level: "error",
|
|
483
|
+
summary: `external plugin ${plugin.name} failed to load`,
|
|
484
|
+
data: {
|
|
485
|
+
plugin: plugin.name,
|
|
486
|
+
specifier,
|
|
487
|
+
source: plugin.source ?? null,
|
|
488
|
+
builtin: false,
|
|
489
|
+
error: message,
|
|
490
|
+
},
|
|
491
|
+
});
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
},
|
|
495
|
+
};
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
export { createPluginRegistry, isPluginModule, normalizeImportedPluginModule, resolveLocalPluginEntrypoint, resolvePackageExportsEntry };
|
|
499
|
+
//# sourceMappingURL=plugin-registry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin-registry.js","sources":["../src/plugin-registry.ts"],"sourcesContent":[null],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { LoadedConfig, PortfolioProject, ProjectConfig } from "./types.js";
|
|
2
|
+
export declare function resolveProjectConfig(entry: PortfolioProject): {
|
|
3
|
+
config: LoadedConfig;
|
|
4
|
+
project: ProjectConfig;
|
|
5
|
+
} | null;
|
|
6
|
+
export declare function clearConfigCache(): void;
|
|
7
|
+
//# sourceMappingURL=portfolio-projects.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"portfolio-projects.d.ts","sourceRoot":"","sources":["../src/portfolio-projects.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAWhF,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,gBAAgB,GACtB;IAAE,MAAM,EAAE,YAAY,CAAC;IAAC,OAAO,EAAE,aAAa,CAAA;CAAE,GAAG,IAAI,CAsDzD;AAED,wBAAgB,gBAAgB,IAAI,IAAI,CAEvC"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { validateConfig, loadConfig } from './config.js';
|
|
2
|
+
import { getGlobalConfigPath, loadGlobalConfig, buildEffectiveProjectConfig } from './global-config.js';
|
|
3
|
+
|
|
4
|
+
const CACHE_TTL_MS = 30_000;
|
|
5
|
+
const configCache = new Map();
|
|
6
|
+
function resolveProjectConfig(entry) {
|
|
7
|
+
try {
|
|
8
|
+
if (entry.configPath === getGlobalConfigPath()) {
|
|
9
|
+
const globalConfig = loadGlobalConfig(entry.configPath);
|
|
10
|
+
if (!globalConfig)
|
|
11
|
+
return null;
|
|
12
|
+
const effectiveProject = buildEffectiveProjectConfig(entry.configProjectKey, globalConfig);
|
|
13
|
+
if (!effectiveProject)
|
|
14
|
+
return null;
|
|
15
|
+
const config = validateConfig({
|
|
16
|
+
port: globalConfig.port,
|
|
17
|
+
terminalPort: globalConfig.terminalPort,
|
|
18
|
+
directTerminalPort: globalConfig.directTerminalPort,
|
|
19
|
+
readyThresholdMs: globalConfig.readyThresholdMs,
|
|
20
|
+
defaults: globalConfig.defaults,
|
|
21
|
+
notifiers: globalConfig.notifiers,
|
|
22
|
+
notificationRouting: globalConfig.notificationRouting,
|
|
23
|
+
reactions: globalConfig.reactions,
|
|
24
|
+
projects: {
|
|
25
|
+
[entry.configProjectKey]: {
|
|
26
|
+
...effectiveProject,
|
|
27
|
+
...(typeof effectiveProject["repo"] === "string"
|
|
28
|
+
? { repo: effectiveProject["repo"] }
|
|
29
|
+
: {}),
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
});
|
|
33
|
+
const loadedConfig = { ...config, degradedProjects: {} };
|
|
34
|
+
loadedConfig.configPath = entry.configPath;
|
|
35
|
+
const project = loadedConfig.projects[entry.configProjectKey];
|
|
36
|
+
if (!project) {
|
|
37
|
+
return null;
|
|
38
|
+
}
|
|
39
|
+
return { config: loadedConfig, project };
|
|
40
|
+
}
|
|
41
|
+
const cached = configCache.get(entry.configPath);
|
|
42
|
+
let config;
|
|
43
|
+
if (cached && Date.now() < cached.expiresAt) {
|
|
44
|
+
config = cached.config;
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
config = loadConfig(entry.configPath);
|
|
48
|
+
configCache.set(entry.configPath, { config, expiresAt: Date.now() + CACHE_TTL_MS });
|
|
49
|
+
}
|
|
50
|
+
const project = config.projects[entry.configProjectKey];
|
|
51
|
+
if (!project) {
|
|
52
|
+
return null;
|
|
53
|
+
}
|
|
54
|
+
return { config, project };
|
|
55
|
+
}
|
|
56
|
+
catch {
|
|
57
|
+
return null;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
function clearConfigCache() {
|
|
61
|
+
configCache.clear();
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export { clearConfigCache, resolveProjectConfig };
|
|
65
|
+
//# sourceMappingURL=portfolio-projects.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"portfolio-projects.js","sources":["../src/portfolio-projects.ts"],"sourcesContent":[null],"names":[],"mappings":";;;AAQA,MAAM,YAAY,GAAG,MAAM;AAC3B,MAAM,WAAW,GAAG,IAAI,GAAG,EAAuD;AAE5E,SAAU,oBAAoB,CAClC,KAAuB,EAAA;AAEvB,IAAA,IAAI;AACF,QAAA,IAAI,KAAK,CAAC,UAAU,KAAK,mBAAmB,EAAE,EAAE;YAC9C,MAAM,YAAY,GAAG,gBAAgB,CAAC,KAAK,CAAC,UAAU,CAAC;AACvD,YAAA,IAAI,CAAC,YAAY;AAAE,gBAAA,OAAO,IAAI;YAE9B,MAAM,gBAAgB,GAAG,2BAA2B,CAAC,KAAK,CAAC,gBAAgB,EAAE,YAAY,CAAC;AAC1F,YAAA,IAAI,CAAC,gBAAgB;AAAE,gBAAA,OAAO,IAAI;YAElC,MAAM,MAAM,GAAG,cAAc,CAAC;gBAC5B,IAAI,EAAE,YAAY,CAAC,IAAI;gBACvB,YAAY,EAAE,YAAY,CAAC,YAAY;gBACvC,kBAAkB,EAAE,YAAY,CAAC,kBAAkB;gBACnD,gBAAgB,EAAE,YAAY,CAAC,gBAAgB;gBAC/C,QAAQ,EAAE,YAAY,CAAC,QAAQ;gBAC/B,SAAS,EAAE,YAAY,CAAC,SAAS;gBACjC,mBAAmB,EAAE,YAAY,CAAC,mBAAmB;gBACrD,SAAS,EAAE,YAAY,CAAC,SAAS;AACjC,gBAAA,QAAQ,EAAE;AACR,oBAAA,CAAC,KAAK,CAAC,gBAAgB,GAAG;AACxB,wBAAA,GAAG,gBAAgB;AACnB,wBAAA,IAAI,OAAO,gBAAgB,CAAC,MAAM,CAAC,KAAK;8BACpC,EAAE,IAAI,EAAE,gBAAgB,CAAC,MAAM,CAAC;8BAChC,EAAE,CAAC;AACR,qBAAA;AACF,iBAAA;AACF,aAAA,CAAC;YACF,MAAM,YAAY,GAAiB,EAAE,GAAG,MAAM,EAAE,gBAAgB,EAAE,EAAE,EAAE;AACtE,YAAA,YAAY,CAAC,UAAU,GAAG,KAAK,CAAC,UAAU;YAE1C,MAAM,OAAO,GAAG,YAAY,CAAC,QAAQ,CAAC,KAAK,CAAC,gBAAgB,CAAC;YAC7D,IAAI,CAAC,OAAO,EAAE;AACZ,gBAAA,OAAO,IAAI;YACb;AACA,YAAA,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,OAAO,EAAE;QAC1C;QAEA,MAAM,MAAM,GAAG,WAAW,CAAC,GAAG,CAAC,KAAK,CAAC,UAAU,CAAC;AAChD,QAAA,IAAI,MAAoB;QACxB,IAAI,MAAM,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,MAAM,CAAC,SAAS,EAAE;AAC3C,YAAA,MAAM,GAAG,MAAM,CAAC,MAAM;QACxB;aAAO;AACL,YAAA,MAAM,GAAG,UAAU,CAAC,KAAK,CAAC,UAAU,CAAC;YACrC,WAAW,CAAC,GAAG,CAAC,KAAK,CAAC,UAAU,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,YAAY,EAAE,CAAC;QACrF;QAEA,MAAM,OAAO,GAAG,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,gBAAgB,CAAC;QACvD,IAAI,CAAC,OAAO,EAAE;AACZ,YAAA,OAAO,IAAI;QACb;AACA,QAAA,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE;IAC5B;AAAE,IAAA,MAAM;AACN,QAAA,OAAO,IAAI;IACb;AACF;SAEgB,gBAAgB,GAAA;IAC9B,WAAW,CAAC,KAAK,EAAE;AACrB;;;;"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Portfolio registry — global-config-backed project projection plus user preferences.
|
|
3
|
+
*
|
|
4
|
+
* The global config is the canonical source of truth for which projects exist.
|
|
5
|
+
* Preferences provide a lightweight UI overlay for ordering, pinning, visibility,
|
|
6
|
+
* and display names.
|
|
7
|
+
*/
|
|
8
|
+
import type { PortfolioProject, PortfolioPreferences, PortfolioRegistered } from "./types.js";
|
|
9
|
+
import { type RegisterProjectOptions } from "./global-config.js";
|
|
10
|
+
/** Load registered projects from registered.json (legacy compatibility only). */
|
|
11
|
+
export declare function loadRegistered(): PortfolioRegistered;
|
|
12
|
+
/** Save registered projects to registered.json (legacy compatibility only). */
|
|
13
|
+
export declare function saveRegistered(reg: PortfolioRegistered): void;
|
|
14
|
+
/** Load portfolio preferences from preferences.json */
|
|
15
|
+
export declare function loadPreferences(): PortfolioPreferences;
|
|
16
|
+
/** Save portfolio preferences to preferences.json */
|
|
17
|
+
export declare function savePreferences(prefs: PortfolioPreferences): void;
|
|
18
|
+
/**
|
|
19
|
+
* Atomically update preferences: reads the current state, applies the updater,
|
|
20
|
+
* and writes back in a single synchronous block. This prevents lost updates
|
|
21
|
+
* from concurrent async handlers that might interleave between read and write.
|
|
22
|
+
*/
|
|
23
|
+
export declare function updatePreferences(updater: (prefs: PortfolioPreferences) => void): void;
|
|
24
|
+
/**
|
|
25
|
+
* Backward-compatible alias for callers that previously treated "discovered"
|
|
26
|
+
* projects as the portfolio base. Projects are now projected from the
|
|
27
|
+
* canonical registry, so discovery simply returns that projection.
|
|
28
|
+
*/
|
|
29
|
+
export declare function discoverProjects(): PortfolioProject[];
|
|
30
|
+
/**
|
|
31
|
+
* Build the portfolio directly from the canonical global registry, with
|
|
32
|
+
* preferences layered on top. Falls back to the currently loaded config when
|
|
33
|
+
* no global config exists yet.
|
|
34
|
+
*/
|
|
35
|
+
export declare function getPortfolio(): PortfolioProject[];
|
|
36
|
+
/** Register a project into the canonical global config registry. Returns the effective registered project ID. */
|
|
37
|
+
export declare function registerProject(repoPath: string, configProjectKey?: string, displayName?: string, options?: RegisterProjectOptions): string;
|
|
38
|
+
/** Remove a project from the canonical global config registry. */
|
|
39
|
+
export declare function unregisterProject(projectId: string): void;
|
|
40
|
+
/** Refresh is a no-op for the global-registry-backed portfolio. */
|
|
41
|
+
export declare function refreshProject(_projectId: string, _configPath: string): void;
|
|
42
|
+
//# sourceMappingURL=portfolio-registry.d.ts.map
|