jfl 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +443 -145
- package/clawdbot-plugin/clawdbot.plugin.json +20 -0
- package/clawdbot-plugin/index.js +555 -0
- package/clawdbot-plugin/index.ts +582 -0
- package/clawdbot-skill/SKILL.md +33 -336
- package/clawdbot-skill/index.ts +491 -321
- package/clawdbot-skill/skill.json +4 -13
- package/dist/commands/clawdbot.d.ts +11 -0
- package/dist/commands/clawdbot.d.ts.map +1 -0
- package/dist/commands/clawdbot.js +215 -0
- package/dist/commands/clawdbot.js.map +1 -0
- package/dist/commands/context-hub.d.ts +5 -0
- package/dist/commands/context-hub.d.ts.map +1 -1
- package/dist/commands/context-hub.js +394 -28
- package/dist/commands/context-hub.js.map +1 -1
- package/dist/commands/gtm-process-update.d.ts +10 -0
- package/dist/commands/gtm-process-update.d.ts.map +1 -0
- package/dist/commands/gtm-process-update.js +101 -0
- package/dist/commands/gtm-process-update.js.map +1 -0
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +278 -4
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/login.d.ts.map +1 -1
- package/dist/commands/login.js +32 -33
- package/dist/commands/login.js.map +1 -1
- package/dist/commands/memory.d.ts +38 -0
- package/dist/commands/memory.d.ts.map +1 -0
- package/dist/commands/memory.js +229 -0
- package/dist/commands/memory.js.map +1 -0
- package/dist/commands/migrate-services.d.ts +8 -0
- package/dist/commands/migrate-services.d.ts.map +1 -0
- package/dist/commands/migrate-services.js +182 -0
- package/dist/commands/migrate-services.js.map +1 -0
- package/dist/commands/onboard.d.ts +24 -0
- package/dist/commands/onboard.d.ts.map +1 -0
- package/dist/commands/onboard.js +663 -0
- package/dist/commands/onboard.js.map +1 -0
- package/dist/commands/openclaw.d.ts +56 -0
- package/dist/commands/openclaw.d.ts.map +1 -0
- package/dist/commands/openclaw.js +700 -0
- package/dist/commands/openclaw.js.map +1 -0
- package/dist/commands/orchestrate.d.ts +14 -0
- package/dist/commands/orchestrate.d.ts.map +1 -0
- package/dist/commands/orchestrate.js +270 -0
- package/dist/commands/orchestrate.js.map +1 -0
- package/dist/commands/profile.d.ts +46 -0
- package/dist/commands/profile.d.ts.map +1 -0
- package/dist/commands/profile.js +498 -0
- package/dist/commands/profile.js.map +1 -0
- package/dist/commands/repair.d.ts.map +1 -1
- package/dist/commands/repair.js +37 -0
- package/dist/commands/repair.js.map +1 -1
- package/dist/commands/service-agent.d.ts +16 -0
- package/dist/commands/service-agent.d.ts.map +1 -0
- package/dist/commands/service-agent.js +375 -0
- package/dist/commands/service-agent.js.map +1 -0
- package/dist/commands/service-manager.d.ts +12 -0
- package/dist/commands/service-manager.d.ts.map +1 -0
- package/dist/commands/service-manager.js +967 -0
- package/dist/commands/service-manager.js.map +1 -0
- package/dist/commands/service-validate.d.ts +12 -0
- package/dist/commands/service-validate.d.ts.map +1 -0
- package/dist/commands/service-validate.js +611 -0
- package/dist/commands/service-validate.js.map +1 -0
- package/dist/commands/services-create.d.ts +15 -0
- package/dist/commands/services-create.d.ts.map +1 -0
- package/dist/commands/services-create.js +1452 -0
- package/dist/commands/services-create.js.map +1 -0
- package/dist/commands/services-scan.d.ts +13 -0
- package/dist/commands/services-scan.d.ts.map +1 -0
- package/dist/commands/services-scan.js +251 -0
- package/dist/commands/services-scan.js.map +1 -0
- package/dist/commands/services-sync-agents.d.ts +23 -0
- package/dist/commands/services-sync-agents.d.ts.map +1 -0
- package/dist/commands/services-sync-agents.js +207 -0
- package/dist/commands/services-sync-agents.js.map +1 -0
- package/dist/commands/services.d.ts +19 -0
- package/dist/commands/services.d.ts.map +1 -0
- package/dist/commands/services.js +742 -0
- package/dist/commands/services.js.map +1 -0
- package/dist/commands/session.d.ts +5 -1
- package/dist/commands/session.d.ts.map +1 -1
- package/dist/commands/session.js +68 -586
- package/dist/commands/session.js.map +1 -1
- package/dist/commands/status.d.ts.map +1 -1
- package/dist/commands/status.js +17 -0
- package/dist/commands/status.js.map +1 -1
- package/dist/commands/update.d.ts.map +1 -1
- package/dist/commands/update.js +75 -21
- package/dist/commands/update.js.map +1 -1
- package/dist/commands/validate-settings.d.ts +37 -0
- package/dist/commands/validate-settings.d.ts.map +1 -0
- package/dist/commands/validate-settings.js +197 -0
- package/dist/commands/validate-settings.js.map +1 -0
- package/dist/commands/voice.d.ts +0 -1
- package/dist/commands/voice.d.ts.map +1 -1
- package/dist/commands/voice.js +16 -15
- package/dist/commands/voice.js.map +1 -1
- package/dist/index.js +395 -141
- package/dist/index.js.map +1 -1
- package/dist/lib/agent-generator.d.ts +26 -0
- package/dist/lib/agent-generator.d.ts.map +1 -0
- package/dist/lib/agent-generator.js +331 -0
- package/dist/lib/agent-generator.js.map +1 -0
- package/dist/lib/memory-db.d.ts +102 -0
- package/dist/lib/memory-db.d.ts.map +1 -0
- package/dist/lib/memory-db.js +313 -0
- package/dist/lib/memory-db.js.map +1 -0
- package/dist/lib/memory-indexer.d.ts +47 -0
- package/dist/lib/memory-indexer.d.ts.map +1 -0
- package/dist/lib/memory-indexer.js +215 -0
- package/dist/lib/memory-indexer.js.map +1 -0
- package/dist/lib/memory-search.d.ts +41 -0
- package/dist/lib/memory-search.d.ts.map +1 -0
- package/dist/lib/memory-search.js +246 -0
- package/dist/lib/memory-search.js.map +1 -0
- package/dist/lib/openclaw-registry.d.ts +48 -0
- package/dist/lib/openclaw-registry.d.ts.map +1 -0
- package/dist/lib/openclaw-registry.js +181 -0
- package/dist/lib/openclaw-registry.js.map +1 -0
- package/dist/lib/openclaw-sdk.d.ts +107 -0
- package/dist/lib/openclaw-sdk.d.ts.map +1 -0
- package/dist/lib/openclaw-sdk.js +208 -0
- package/dist/lib/openclaw-sdk.js.map +1 -0
- package/dist/lib/peer-agent-generator.d.ts +44 -0
- package/dist/lib/peer-agent-generator.d.ts.map +1 -0
- package/dist/lib/peer-agent-generator.js +286 -0
- package/dist/lib/peer-agent-generator.js.map +1 -0
- package/dist/lib/service-dependencies.d.ts +44 -0
- package/dist/lib/service-dependencies.d.ts.map +1 -0
- package/dist/lib/service-dependencies.js +314 -0
- package/dist/lib/service-dependencies.js.map +1 -0
- package/dist/lib/service-detector.d.ts +61 -0
- package/dist/lib/service-detector.d.ts.map +1 -0
- package/dist/lib/service-detector.js +521 -0
- package/dist/lib/service-detector.js.map +1 -0
- package/dist/lib/service-gtm.d.ts +157 -0
- package/dist/lib/service-gtm.d.ts.map +1 -0
- package/dist/lib/service-gtm.js +786 -0
- package/dist/lib/service-gtm.js.map +1 -0
- package/dist/lib/service-mcp-base.d.ts +103 -0
- package/dist/lib/service-mcp-base.d.ts.map +1 -0
- package/dist/lib/service-mcp-base.js +263 -0
- package/dist/lib/service-mcp-base.js.map +1 -0
- package/dist/lib/service-utils.d.ts +103 -0
- package/dist/lib/service-utils.d.ts.map +1 -0
- package/dist/lib/service-utils.js +368 -0
- package/dist/lib/service-utils.js.map +1 -0
- package/dist/lib/skill-generator.d.ts +21 -0
- package/dist/lib/skill-generator.d.ts.map +1 -0
- package/dist/lib/skill-generator.js +253 -0
- package/dist/lib/skill-generator.js.map +1 -0
- package/dist/lib/stratus-client.d.ts +100 -0
- package/dist/lib/stratus-client.d.ts.map +1 -0
- package/dist/lib/stratus-client.js +255 -0
- package/dist/lib/stratus-client.js.map +1 -0
- package/dist/mcp/context-hub-mcp.js +135 -53
- package/dist/mcp/context-hub-mcp.js.map +1 -1
- package/dist/mcp/service-mcp-server.d.ts +12 -0
- package/dist/mcp/service-mcp-server.d.ts.map +1 -0
- package/dist/mcp/service-mcp-server.js +434 -0
- package/dist/mcp/service-mcp-server.js.map +1 -0
- package/dist/mcp/service-peer-mcp.d.ts +36 -0
- package/dist/mcp/service-peer-mcp.d.ts.map +1 -0
- package/dist/mcp/service-peer-mcp.js +220 -0
- package/dist/mcp/service-peer-mcp.js.map +1 -0
- package/dist/mcp/service-registry-mcp.d.ts +13 -0
- package/dist/mcp/service-registry-mcp.d.ts.map +1 -0
- package/dist/mcp/service-registry-mcp.js +330 -0
- package/dist/mcp/service-registry-mcp.js.map +1 -0
- package/dist/ui/banner.js +1 -1
- package/dist/ui/banner.js.map +1 -1
- package/dist/ui/context-hub-logs.d.ts +10 -0
- package/dist/ui/context-hub-logs.d.ts.map +1 -0
- package/dist/ui/context-hub-logs.js +175 -0
- package/dist/ui/context-hub-logs.js.map +1 -0
- package/dist/ui/service-dashboard.d.ts +11 -0
- package/dist/ui/service-dashboard.d.ts.map +1 -0
- package/dist/ui/service-dashboard.js +357 -0
- package/dist/ui/service-dashboard.js.map +1 -0
- package/dist/ui/services-manager.d.ts +11 -0
- package/dist/ui/services-manager.d.ts.map +1 -0
- package/dist/ui/services-manager.js +507 -0
- package/dist/ui/services-manager.js.map +1 -0
- package/dist/utils/auth-guard.d.ts.map +1 -1
- package/dist/utils/auth-guard.js +8 -9
- package/dist/utils/auth-guard.js.map +1 -1
- package/dist/utils/claude-md-generator.d.ts +10 -0
- package/dist/utils/claude-md-generator.d.ts.map +1 -0
- package/dist/utils/claude-md-generator.js +215 -0
- package/dist/utils/claude-md-generator.js.map +1 -0
- package/dist/utils/ensure-context-hub.d.ts +20 -0
- package/dist/utils/ensure-context-hub.d.ts.map +1 -0
- package/dist/utils/ensure-context-hub.js +65 -0
- package/dist/utils/ensure-context-hub.js.map +1 -0
- package/dist/utils/ensure-project.d.ts.map +1 -1
- package/dist/utils/ensure-project.js +3 -4
- package/dist/utils/ensure-project.js.map +1 -1
- package/dist/utils/jfl-config.d.ts +19 -0
- package/dist/utils/jfl-config.d.ts.map +1 -0
- package/dist/utils/jfl-config.js +112 -0
- package/dist/utils/jfl-config.js.map +1 -0
- package/dist/utils/jfl-migration.d.ts +29 -0
- package/dist/utils/jfl-migration.d.ts.map +1 -0
- package/dist/utils/jfl-migration.js +142 -0
- package/dist/utils/jfl-migration.js.map +1 -0
- package/dist/utils/jfl-paths.d.ts +55 -0
- package/dist/utils/jfl-paths.d.ts.map +1 -0
- package/dist/utils/jfl-paths.js +120 -0
- package/dist/utils/jfl-paths.js.map +1 -0
- package/dist/utils/settings-validator.d.ts +73 -0
- package/dist/utils/settings-validator.d.ts.map +1 -0
- package/dist/utils/settings-validator.js +222 -0
- package/dist/utils/settings-validator.js.map +1 -0
- package/package.json +19 -3
- package/scripts/commit-gtm.sh +56 -0
- package/scripts/commit-product.sh +68 -0
- package/scripts/context-query.sh +45 -0
- package/scripts/session/auto-commit.sh +297 -0
- package/scripts/session/jfl-doctor.sh +707 -0
- package/scripts/session/session-cleanup.sh +268 -0
- package/scripts/session/session-end.sh +198 -0
- package/scripts/session/session-init.sh +350 -0
- package/scripts/session/session-init.sh.backup +292 -0
- package/scripts/session/session-sync.sh +167 -0
- package/scripts/session/test-context-preservation.sh +160 -0
- package/scripts/session/test-critical-infrastructure.sh +293 -0
- package/scripts/session/test-experience-level.sh +336 -0
- package/scripts/session/test-session-cleanup.sh +268 -0
- package/scripts/session/test-session-sync.sh +320 -0
- package/scripts/voice-start.sh +36 -8
- package/scripts/where-am-i.sh +78 -0
- package/template/.claude/service-settings.json +32 -0
- package/template/.claude/settings.json +14 -1
- package/template/.claude/skills/end/SKILL.md +1780 -0
- package/template/.jfl/config.json +2 -1
- package/template/CLAUDE.md +1039 -134
- package/template/CLAUDE.md.bak +1187 -0
- package/template/scripts/commit-gtm.sh +56 -0
- package/template/scripts/commit-product.sh +68 -0
- package/template/scripts/migrate-to-branch-sessions.sh +201 -0
- package/template/scripts/session/auto-commit.sh +58 -6
- package/template/scripts/session/jfl-doctor.sh +137 -17
- package/template/scripts/session/session-cleanup.sh +268 -0
- package/template/scripts/session/session-end.sh +4 -0
- package/template/scripts/session/session-init.sh +253 -66
- package/template/scripts/session/test-critical-infrastructure.sh +293 -0
- package/template/scripts/session/test-experience-level.sh +336 -0
- package/template/scripts/session/test-session-cleanup.sh +268 -0
- package/template/scripts/session/test-session-sync.sh +320 -0
- package/template/scripts/where-am-i.sh +78 -0
- package/template/templates/service-agent/.claude/settings.json +32 -0
- package/template/templates/service-agent/CLAUDE.md +334 -0
- package/template/templates/service-agent/knowledge/ARCHITECTURE.md +115 -0
- package/template/templates/service-agent/knowledge/DEPLOYMENT.md +199 -0
- package/template/templates/service-agent/knowledge/RUNBOOK.md +412 -0
- package/template/templates/service-agent/knowledge/SERVICE_SPEC.md +77 -0
- package/dist/commands/session-mgmt.d.ts +0 -33
- package/dist/commands/session-mgmt.d.ts.map +0 -1
- package/dist/commands/session-mgmt.js +0 -404
- package/dist/commands/session-mgmt.js.map +0 -1
- package/template/scripts/session/auto-merge.sh +0 -325
|
@@ -0,0 +1,368 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Service Management Utilities
|
|
3
|
+
*
|
|
4
|
+
* Shared utilities for service lifecycle management across commands.
|
|
5
|
+
* Provides version tracking, health checks, and restart logic.
|
|
6
|
+
*
|
|
7
|
+
* @purpose Shared service management utilities for update flow
|
|
8
|
+
*/
|
|
9
|
+
import * as fs from "fs";
|
|
10
|
+
import * as path from "path";
|
|
11
|
+
import { execSync } from "child_process";
|
|
12
|
+
import chalk from "chalk";
|
|
13
|
+
import ora from "ora";
|
|
14
|
+
import { JFL_PATHS } from "../utils/jfl-paths.js";
|
|
15
|
+
// ============================================================================
|
|
16
|
+
// Version Tracking
|
|
17
|
+
// ============================================================================
|
|
18
|
+
const CLI_VERSION_FILE = path.join(JFL_PATHS.data, "cli-version.json");
|
|
19
|
+
/**
|
|
20
|
+
* Get current CLI version from package.json
|
|
21
|
+
*/
|
|
22
|
+
export function getCurrentCliVersion() {
|
|
23
|
+
try {
|
|
24
|
+
const packageJson = JSON.parse(fs.readFileSync(path.join(__dirname, "../../package.json"), "utf-8"));
|
|
25
|
+
return packageJson.version;
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
return "0.0.0";
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Read stored CLI version info
|
|
33
|
+
*/
|
|
34
|
+
export function readCliVersion() {
|
|
35
|
+
if (!fs.existsSync(CLI_VERSION_FILE)) {
|
|
36
|
+
return null;
|
|
37
|
+
}
|
|
38
|
+
try {
|
|
39
|
+
const content = fs.readFileSync(CLI_VERSION_FILE, "utf-8");
|
|
40
|
+
return JSON.parse(content);
|
|
41
|
+
}
|
|
42
|
+
catch {
|
|
43
|
+
return null;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Write CLI version info
|
|
48
|
+
*/
|
|
49
|
+
export function writeCliVersion(version, services) {
|
|
50
|
+
const dir = path.dirname(CLI_VERSION_FILE);
|
|
51
|
+
if (!fs.existsSync(dir)) {
|
|
52
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
53
|
+
}
|
|
54
|
+
const versionInfo = {
|
|
55
|
+
version,
|
|
56
|
+
updated_at: new Date().toISOString(),
|
|
57
|
+
services: services || {
|
|
58
|
+
"context-hub": { version, port: 4242 },
|
|
59
|
+
"service-manager": { version, port: 3402 }
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
fs.writeFileSync(CLI_VERSION_FILE, JSON.stringify(versionInfo, null, 2));
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Detect if services have changed (CLI version bump)
|
|
66
|
+
*/
|
|
67
|
+
export async function detectServiceChanges() {
|
|
68
|
+
const currentVersion = getCurrentCliVersion();
|
|
69
|
+
const storedInfo = readCliVersion();
|
|
70
|
+
if (!storedInfo) {
|
|
71
|
+
// First time - no stored version yet
|
|
72
|
+
return { changed: false, newVersion: currentVersion };
|
|
73
|
+
}
|
|
74
|
+
const changed = storedInfo.version !== currentVersion;
|
|
75
|
+
return {
|
|
76
|
+
changed,
|
|
77
|
+
oldVersion: storedInfo.version,
|
|
78
|
+
newVersion: currentVersion
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
// ============================================================================
|
|
82
|
+
// Service Health Checks
|
|
83
|
+
// ============================================================================
|
|
84
|
+
/**
|
|
85
|
+
* Check if a service is running via health endpoint
|
|
86
|
+
*/
|
|
87
|
+
export async function waitForHealthy(url, timeout = 5000) {
|
|
88
|
+
const startTime = Date.now();
|
|
89
|
+
while (Date.now() - startTime < timeout) {
|
|
90
|
+
try {
|
|
91
|
+
const controller = new AbortController();
|
|
92
|
+
const timeoutId = setTimeout(() => controller.abort(), 2000);
|
|
93
|
+
const response = await fetch(url, {
|
|
94
|
+
signal: controller.signal
|
|
95
|
+
});
|
|
96
|
+
clearTimeout(timeoutId);
|
|
97
|
+
if (response.ok) {
|
|
98
|
+
return true;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
catch {
|
|
102
|
+
// Health check failed, retry
|
|
103
|
+
}
|
|
104
|
+
// Wait 500ms before retry
|
|
105
|
+
await new Promise(resolve => setTimeout(resolve, 500));
|
|
106
|
+
}
|
|
107
|
+
return false;
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Check if a service is running via PID file
|
|
111
|
+
*/
|
|
112
|
+
export function isServiceRunningViaPid(pidFile) {
|
|
113
|
+
if (!fs.existsSync(pidFile)) {
|
|
114
|
+
return { running: false };
|
|
115
|
+
}
|
|
116
|
+
try {
|
|
117
|
+
const pid = parseInt(fs.readFileSync(pidFile, "utf-8").trim(), 10);
|
|
118
|
+
process.kill(pid, 0); // Check if process exists
|
|
119
|
+
return { running: true, pid };
|
|
120
|
+
}
|
|
121
|
+
catch {
|
|
122
|
+
// Process doesn't exist, clean up stale PID file
|
|
123
|
+
try {
|
|
124
|
+
fs.unlinkSync(pidFile);
|
|
125
|
+
}
|
|
126
|
+
catch {
|
|
127
|
+
// Ignore cleanup errors
|
|
128
|
+
}
|
|
129
|
+
return { running: false };
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Check health of a service
|
|
134
|
+
*/
|
|
135
|
+
export async function checkServiceHealth(serviceName, healthUrl, pidFile) {
|
|
136
|
+
// If health URL provided, check that
|
|
137
|
+
if (healthUrl) {
|
|
138
|
+
try {
|
|
139
|
+
const controller = new AbortController();
|
|
140
|
+
const timeoutId = setTimeout(() => controller.abort(), 3000);
|
|
141
|
+
const response = await fetch(healthUrl, {
|
|
142
|
+
signal: controller.signal
|
|
143
|
+
});
|
|
144
|
+
clearTimeout(timeoutId);
|
|
145
|
+
if (response.ok) {
|
|
146
|
+
const data = await response.json().catch(() => ({}));
|
|
147
|
+
return {
|
|
148
|
+
healthy: true,
|
|
149
|
+
message: `${serviceName} is healthy`,
|
|
150
|
+
port: data.port
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
return {
|
|
154
|
+
healthy: false,
|
|
155
|
+
message: `${serviceName} health check failed: HTTP ${response.status}`
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
catch (err) {
|
|
159
|
+
return {
|
|
160
|
+
healthy: false,
|
|
161
|
+
message: `${serviceName} health check failed: ${err.message}`
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
// Fallback to PID file check
|
|
166
|
+
if (pidFile) {
|
|
167
|
+
const status = isServiceRunningViaPid(pidFile);
|
|
168
|
+
return {
|
|
169
|
+
healthy: status.running,
|
|
170
|
+
message: status.running
|
|
171
|
+
? `${serviceName} is running (PID: ${status.pid})`
|
|
172
|
+
: `${serviceName} is not running`
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
return {
|
|
176
|
+
healthy: false,
|
|
177
|
+
message: `Cannot determine health for ${serviceName} (no health URL or PID file)`
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
// ============================================================================
|
|
181
|
+
// Service Control
|
|
182
|
+
// ============================================================================
|
|
183
|
+
/**
|
|
184
|
+
* Wait for a service to stop
|
|
185
|
+
*/
|
|
186
|
+
async function waitForStop(pidFile, timeout) {
|
|
187
|
+
const startTime = Date.now();
|
|
188
|
+
while (Date.now() - startTime < timeout) {
|
|
189
|
+
if (!fs.existsSync(pidFile)) {
|
|
190
|
+
return true;
|
|
191
|
+
}
|
|
192
|
+
try {
|
|
193
|
+
const pid = parseInt(fs.readFileSync(pidFile, "utf-8").trim(), 10);
|
|
194
|
+
process.kill(pid, 0); // Check if process exists
|
|
195
|
+
}
|
|
196
|
+
catch {
|
|
197
|
+
// Process is gone
|
|
198
|
+
return true;
|
|
199
|
+
}
|
|
200
|
+
await new Promise(resolve => setTimeout(resolve, 200));
|
|
201
|
+
}
|
|
202
|
+
return false;
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* Execute a command silently
|
|
206
|
+
*/
|
|
207
|
+
function execSilent(command) {
|
|
208
|
+
try {
|
|
209
|
+
execSync(command, { stdio: "pipe" });
|
|
210
|
+
return { success: true };
|
|
211
|
+
}
|
|
212
|
+
catch (err) {
|
|
213
|
+
return { success: false, error: err.message };
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* Restart a service with health validation
|
|
218
|
+
*/
|
|
219
|
+
export async function restartService(serviceName, opts) {
|
|
220
|
+
const spinner = ora(`Restarting ${serviceName}...`).start();
|
|
221
|
+
try {
|
|
222
|
+
// 1. Stop the service
|
|
223
|
+
const stopResult = execSilent(opts.stopCommand);
|
|
224
|
+
if (stopResult.success) {
|
|
225
|
+
spinner.text = `${serviceName} stopped, starting...`;
|
|
226
|
+
await new Promise(resolve => setTimeout(resolve, 500));
|
|
227
|
+
}
|
|
228
|
+
// 2. Start the service
|
|
229
|
+
const startResult = execSilent(opts.startCommand);
|
|
230
|
+
if (!startResult.success) {
|
|
231
|
+
spinner.fail(`${serviceName} failed to start`);
|
|
232
|
+
return {
|
|
233
|
+
success: false,
|
|
234
|
+
message: `Failed to start: ${startResult.error}`
|
|
235
|
+
};
|
|
236
|
+
}
|
|
237
|
+
// 3. Wait a moment for startup
|
|
238
|
+
await new Promise(resolve => setTimeout(resolve, 800));
|
|
239
|
+
// 4. Health check if URL provided
|
|
240
|
+
if (opts.healthCheck) {
|
|
241
|
+
spinner.text = `Checking ${serviceName} health...`;
|
|
242
|
+
const healthy = await waitForHealthy(opts.healthCheck, opts.timeout || 5000);
|
|
243
|
+
if (healthy) {
|
|
244
|
+
spinner.succeed(`${serviceName} restarted`);
|
|
245
|
+
return { success: true, message: "Service restarted and healthy" };
|
|
246
|
+
}
|
|
247
|
+
else {
|
|
248
|
+
spinner.warn(`${serviceName} started but health check failed`);
|
|
249
|
+
return {
|
|
250
|
+
success: false,
|
|
251
|
+
message: "Service started but not responding to health checks"
|
|
252
|
+
};
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
spinner.succeed(`${serviceName} restarted`);
|
|
256
|
+
return { success: true, message: "Service restarted" };
|
|
257
|
+
}
|
|
258
|
+
catch (error) {
|
|
259
|
+
spinner.fail(`${serviceName} restart failed`);
|
|
260
|
+
return {
|
|
261
|
+
success: false,
|
|
262
|
+
message: error.message
|
|
263
|
+
};
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
/**
|
|
267
|
+
* Ensure a service is running (start if not, validate if running)
|
|
268
|
+
*/
|
|
269
|
+
export async function ensureServiceRunning(serviceName, startCommand, healthCheck, pidFile) {
|
|
270
|
+
// Check if already running
|
|
271
|
+
if (pidFile) {
|
|
272
|
+
const status = isServiceRunningViaPid(pidFile);
|
|
273
|
+
if (status.running && healthCheck) {
|
|
274
|
+
// Verify health
|
|
275
|
+
const healthy = await waitForHealthy(healthCheck, 2000);
|
|
276
|
+
if (healthy) {
|
|
277
|
+
return { success: true, message: `${serviceName} already running` };
|
|
278
|
+
}
|
|
279
|
+
// Process exists but not healthy - fall through to restart
|
|
280
|
+
}
|
|
281
|
+
else if (status.running) {
|
|
282
|
+
return { success: true, message: `${serviceName} already running` };
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
// Start the service
|
|
286
|
+
const result = execSilent(startCommand);
|
|
287
|
+
if (!result.success) {
|
|
288
|
+
return {
|
|
289
|
+
success: false,
|
|
290
|
+
message: `Failed to start: ${result.error}`
|
|
291
|
+
};
|
|
292
|
+
}
|
|
293
|
+
// Wait for startup
|
|
294
|
+
await new Promise(resolve => setTimeout(resolve, 800));
|
|
295
|
+
// Validate health if URL provided
|
|
296
|
+
if (healthCheck) {
|
|
297
|
+
const healthy = await waitForHealthy(healthCheck, 5000);
|
|
298
|
+
if (healthy) {
|
|
299
|
+
return { success: true, message: `${serviceName} started successfully` };
|
|
300
|
+
}
|
|
301
|
+
else {
|
|
302
|
+
return {
|
|
303
|
+
success: false,
|
|
304
|
+
message: `${serviceName} started but health check failed`
|
|
305
|
+
};
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
return { success: true, message: `${serviceName} started` };
|
|
309
|
+
}
|
|
310
|
+
// ============================================================================
|
|
311
|
+
// Multi-Service Operations
|
|
312
|
+
// ============================================================================
|
|
313
|
+
/**
|
|
314
|
+
* Restart all core services (Context Hub + Service Manager)
|
|
315
|
+
*/
|
|
316
|
+
export async function restartCoreServices(options = {}) {
|
|
317
|
+
const results = {
|
|
318
|
+
contextHub: false,
|
|
319
|
+
serviceManager: false
|
|
320
|
+
};
|
|
321
|
+
console.log(chalk.cyan("\n📦 Restarting services...\n"));
|
|
322
|
+
// Restart Context Hub
|
|
323
|
+
const contextHubResult = await restartService("context-hub", {
|
|
324
|
+
stopCommand: "jfl context-hub stop",
|
|
325
|
+
startCommand: "jfl context-hub ensure",
|
|
326
|
+
healthCheck: "http://localhost:4242/health",
|
|
327
|
+
timeout: 5000
|
|
328
|
+
});
|
|
329
|
+
results.contextHub = contextHubResult.success;
|
|
330
|
+
// Restart Service Manager
|
|
331
|
+
const serviceManagerResult = await restartService("service-manager", {
|
|
332
|
+
stopCommand: "jfl service-manager stop",
|
|
333
|
+
startCommand: "jfl service-manager ensure",
|
|
334
|
+
healthCheck: "http://localhost:3402/health",
|
|
335
|
+
timeout: 5000
|
|
336
|
+
});
|
|
337
|
+
results.serviceManager = serviceManagerResult.success;
|
|
338
|
+
return results;
|
|
339
|
+
}
|
|
340
|
+
/**
|
|
341
|
+
* Validate all core services are healthy
|
|
342
|
+
*/
|
|
343
|
+
export async function validateCoreServices() {
|
|
344
|
+
const issues = [];
|
|
345
|
+
// Check Context Hub
|
|
346
|
+
const contextHubHealth = await checkServiceHealth("context-hub", "http://localhost:4242/health", ".jfl/context-hub.pid");
|
|
347
|
+
if (!contextHubHealth.healthy) {
|
|
348
|
+
issues.push({
|
|
349
|
+
service: "context-hub",
|
|
350
|
+
message: contextHubHealth.message,
|
|
351
|
+
remedy: "Run: jfl context-hub restart"
|
|
352
|
+
});
|
|
353
|
+
}
|
|
354
|
+
// Check Service Manager
|
|
355
|
+
const serviceManagerHealth = await checkServiceHealth("service-manager", "http://localhost:3402/health", path.join(JFL_PATHS.data, "services", "pids", "service-manager.pid"));
|
|
356
|
+
if (!serviceManagerHealth.healthy) {
|
|
357
|
+
issues.push({
|
|
358
|
+
service: "service-manager",
|
|
359
|
+
message: serviceManagerHealth.message,
|
|
360
|
+
remedy: "Run: jfl service-manager restart"
|
|
361
|
+
});
|
|
362
|
+
}
|
|
363
|
+
return {
|
|
364
|
+
healthy: issues.length === 0,
|
|
365
|
+
issues
|
|
366
|
+
};
|
|
367
|
+
}
|
|
368
|
+
//# sourceMappingURL=service-utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"service-utils.js","sourceRoot":"","sources":["../../src/lib/service-utils.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Skill Generator
|
|
3
|
+
*
|
|
4
|
+
* Generates service skill wrappers in GTM .claude/skills/ directory
|
|
5
|
+
*
|
|
6
|
+
* @purpose Generate skill wrappers for service agent invocation
|
|
7
|
+
*/
|
|
8
|
+
import type { ServiceMetadata } from "./service-detector.js";
|
|
9
|
+
/**
|
|
10
|
+
* Generate skill definition (SKILL.md)
|
|
11
|
+
*/
|
|
12
|
+
export declare function generateSkillDefinition(metadata: ServiceMetadata, servicePath: string): string;
|
|
13
|
+
/**
|
|
14
|
+
* Generate skill handler script
|
|
15
|
+
*/
|
|
16
|
+
export declare function generateSkillHandler(metadata: ServiceMetadata, servicePath: string, gtmPath: string): string;
|
|
17
|
+
/**
|
|
18
|
+
* Write skill files to GTM repo
|
|
19
|
+
*/
|
|
20
|
+
export declare function writeSkillFiles(metadata: ServiceMetadata, servicePath: string, gtmPath: string): string;
|
|
21
|
+
//# sourceMappingURL=skill-generator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skill-generator.d.ts","sourceRoot":"","sources":["../../src/lib/skill-generator.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAA;AAE5D;;GAEG;AACH,wBAAgB,uBAAuB,CACrC,QAAQ,EAAE,eAAe,EACzB,WAAW,EAAE,MAAM,GAClB,MAAM,CAmFR;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAClC,QAAQ,EAAE,eAAe,EACzB,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,MAAM,GACd,MAAM,CAsIR;AAED;;GAEG;AACH,wBAAgB,eAAe,CAC7B,QAAQ,EAAE,eAAe,EACzB,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,MAAM,GACd,MAAM,CAoBR"}
|
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Skill Generator
|
|
3
|
+
*
|
|
4
|
+
* Generates service skill wrappers in GTM .claude/skills/ directory
|
|
5
|
+
*
|
|
6
|
+
* @purpose Generate skill wrappers for service agent invocation
|
|
7
|
+
*/
|
|
8
|
+
import { writeFileSync, mkdirSync, existsSync } from "fs";
|
|
9
|
+
import { join } from "path";
|
|
10
|
+
/**
|
|
11
|
+
* Generate skill definition (SKILL.md)
|
|
12
|
+
*/
|
|
13
|
+
export function generateSkillDefinition(metadata, servicePath) {
|
|
14
|
+
const skillName = metadata.name;
|
|
15
|
+
return `---
|
|
16
|
+
name: ${skillName}
|
|
17
|
+
version: 1.0.0
|
|
18
|
+
type: service
|
|
19
|
+
description: ${metadata.description}
|
|
20
|
+
service_path: ${servicePath}
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
# ${skillName} - Service Agent Skill
|
|
24
|
+
|
|
25
|
+
Quick access to **${metadata.name}** service agent.
|
|
26
|
+
|
|
27
|
+
## Usage
|
|
28
|
+
|
|
29
|
+
\`\`\`
|
|
30
|
+
/${skillName} [command]
|
|
31
|
+
\`\`\`
|
|
32
|
+
|
|
33
|
+
## Commands
|
|
34
|
+
|
|
35
|
+
| Command | Description |
|
|
36
|
+
|---------|-------------|
|
|
37
|
+
| \`status\` | Show service status |
|
|
38
|
+
| \`logs\` | Show service logs |
|
|
39
|
+
| \`start\` | Start the service |
|
|
40
|
+
| \`stop\` | Stop the service |
|
|
41
|
+
| \`restart\` | Restart the service |
|
|
42
|
+
| \`health\` | Check service health |
|
|
43
|
+
| \`recent\` | Show recent changes |
|
|
44
|
+
| \`deploy\` | Deploy to production (requires approval) |
|
|
45
|
+
|
|
46
|
+
## Examples
|
|
47
|
+
|
|
48
|
+
\`\`\`
|
|
49
|
+
/${skillName} status
|
|
50
|
+
/${skillName} logs
|
|
51
|
+
/${skillName} restart
|
|
52
|
+
/${skillName} deploy
|
|
53
|
+
\`\`\`
|
|
54
|
+
|
|
55
|
+
## How It Works
|
|
56
|
+
|
|
57
|
+
This skill spawns the **service-${skillName}** agent with your request. The agent:
|
|
58
|
+
|
|
59
|
+
1. Reads service knowledge docs (SERVICE_SPEC, ARCHITECTURE, DEPLOYMENT, RUNBOOK)
|
|
60
|
+
2. Performs the requested operation
|
|
61
|
+
3. Updates service status
|
|
62
|
+
4. Emits event to GTM
|
|
63
|
+
5. Writes journal entry if significant
|
|
64
|
+
6. Returns the result
|
|
65
|
+
|
|
66
|
+
## Metadata
|
|
67
|
+
|
|
68
|
+
- **Type**: ${metadata.type}
|
|
69
|
+
- **Port**: ${metadata.port || "N/A"}
|
|
70
|
+
- **Version**: ${metadata.version}
|
|
71
|
+
- **Dependencies**: ${metadata.dependencies.join(", ") || "None"}
|
|
72
|
+
${metadata.healthcheck ? `- **Healthcheck**: \`${metadata.healthcheck}\`` : ""}
|
|
73
|
+
|
|
74
|
+
## Service Path
|
|
75
|
+
|
|
76
|
+
\`${servicePath}\`
|
|
77
|
+
|
|
78
|
+
## Knowledge Docs
|
|
79
|
+
|
|
80
|
+
- \`${servicePath}/knowledge/SERVICE_SPEC.md\`
|
|
81
|
+
- \`${servicePath}/knowledge/ARCHITECTURE.md\`
|
|
82
|
+
- \`${servicePath}/knowledge/DEPLOYMENT.md\`
|
|
83
|
+
- \`${servicePath}/knowledge/RUNBOOK.md\`
|
|
84
|
+
|
|
85
|
+
## Direct Invocation
|
|
86
|
+
|
|
87
|
+
You can also invoke via @-mention in conversation:
|
|
88
|
+
|
|
89
|
+
\`\`\`
|
|
90
|
+
@${skillName} what's your current status?
|
|
91
|
+
@${skillName} show me recent changes
|
|
92
|
+
@${skillName} deploy latest changes
|
|
93
|
+
\`\`\`
|
|
94
|
+
`;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Generate skill handler script
|
|
98
|
+
*/
|
|
99
|
+
export function generateSkillHandler(metadata, servicePath, gtmPath) {
|
|
100
|
+
const skillName = metadata.name;
|
|
101
|
+
return `#!/bin/bash
|
|
102
|
+
#
|
|
103
|
+
# Service Agent Skill Handler: ${skillName}
|
|
104
|
+
#
|
|
105
|
+
# Routes skill invocations to service agent
|
|
106
|
+
#
|
|
107
|
+
|
|
108
|
+
set -e
|
|
109
|
+
|
|
110
|
+
COMMAND="\${1:-status}"
|
|
111
|
+
GTM_PATH="${gtmPath}"
|
|
112
|
+
SERVICE_PATH="${servicePath}"
|
|
113
|
+
SERVICE_NAME="${skillName}"
|
|
114
|
+
|
|
115
|
+
# Validate command
|
|
116
|
+
case "$COMMAND" in
|
|
117
|
+
status|logs|start|stop|restart|health|recent|deploy|help)
|
|
118
|
+
# Valid command
|
|
119
|
+
;;
|
|
120
|
+
*)
|
|
121
|
+
echo "Unknown command: $COMMAND"
|
|
122
|
+
echo ""
|
|
123
|
+
echo "Available commands:"
|
|
124
|
+
echo " status - Show service status"
|
|
125
|
+
echo " logs - Show service logs"
|
|
126
|
+
echo " start - Start the service"
|
|
127
|
+
echo " stop - Stop the service"
|
|
128
|
+
echo " restart - Restart the service"
|
|
129
|
+
echo " health - Check service health"
|
|
130
|
+
echo " recent - Show recent changes"
|
|
131
|
+
echo " deploy - Deploy to production"
|
|
132
|
+
echo " help - Show this help"
|
|
133
|
+
exit 1
|
|
134
|
+
;;
|
|
135
|
+
esac
|
|
136
|
+
|
|
137
|
+
# For help, show skill documentation
|
|
138
|
+
if [[ "$COMMAND" == "help" ]]; then
|
|
139
|
+
cat << EOF
|
|
140
|
+
Service Agent Skill: ${skillName}
|
|
141
|
+
|
|
142
|
+
Commands:
|
|
143
|
+
/${skillName} status - Show service status
|
|
144
|
+
/${skillName} logs - Show service logs
|
|
145
|
+
/${skillName} start - Start the service
|
|
146
|
+
/${skillName} stop - Stop the service
|
|
147
|
+
/${skillName} restart - Restart the service
|
|
148
|
+
/${skillName} health - Check service health
|
|
149
|
+
/${skillName} recent - Show recent changes
|
|
150
|
+
/${skillName} deploy - Deploy to production
|
|
151
|
+
|
|
152
|
+
Metadata:
|
|
153
|
+
Type: ${metadata.type}
|
|
154
|
+
Port: ${metadata.port || "N/A"}
|
|
155
|
+
Version: ${metadata.version}
|
|
156
|
+
Path: ${servicePath}
|
|
157
|
+
|
|
158
|
+
You can also use @-mentions:
|
|
159
|
+
@${skillName} what's your status?
|
|
160
|
+
@${skillName} show recent changes
|
|
161
|
+
@${skillName} deploy latest version
|
|
162
|
+
EOF
|
|
163
|
+
exit 0
|
|
164
|
+
fi
|
|
165
|
+
|
|
166
|
+
# Quick status check (no agent spawn needed)
|
|
167
|
+
if [[ "$COMMAND" == "status" ]]; then
|
|
168
|
+
if [[ -f "$SERVICE_PATH/.jfl/status.json" ]]; then
|
|
169
|
+
echo "Service Status: ${skillName}"
|
|
170
|
+
echo ""
|
|
171
|
+
jq '.' "$SERVICE_PATH/.jfl/status.json"
|
|
172
|
+
else
|
|
173
|
+
echo "Status file not found. Service may not be onboarded yet."
|
|
174
|
+
exit 1
|
|
175
|
+
fi
|
|
176
|
+
exit 0
|
|
177
|
+
fi
|
|
178
|
+
|
|
179
|
+
# Quick health check (no agent spawn needed)
|
|
180
|
+
if [[ "$COMMAND" == "health" ]]; then
|
|
181
|
+
${metadata.healthcheck || 'echo "No healthcheck defined"'}
|
|
182
|
+
exit $?
|
|
183
|
+
fi
|
|
184
|
+
|
|
185
|
+
# Quick recent changes (no agent spawn needed)
|
|
186
|
+
if [[ "$COMMAND" == "recent" ]]; then
|
|
187
|
+
echo "Recent Changes: ${skillName}"
|
|
188
|
+
echo ""
|
|
189
|
+
if [[ -f "$SERVICE_PATH/.jfl/status.json" ]]; then
|
|
190
|
+
jq -r '.recent_changes[]' "$SERVICE_PATH/.jfl/status.json"
|
|
191
|
+
fi
|
|
192
|
+
echo ""
|
|
193
|
+
echo "Recent Journal Entries:"
|
|
194
|
+
cat "$SERVICE_PATH/.jfl/journal"/*.jsonl 2>/dev/null | tail -5 | jq -r '"\(.ts) - \(.title)"'
|
|
195
|
+
echo ""
|
|
196
|
+
echo "Recent Commits:"
|
|
197
|
+
cd "$SERVICE_PATH" && git log --oneline -5
|
|
198
|
+
exit 0
|
|
199
|
+
fi
|
|
200
|
+
|
|
201
|
+
# For other commands, this should spawn the service agent via Claude Code
|
|
202
|
+
# Since we're in a skill handler, we need to return instructions for Claude
|
|
203
|
+
cat << EOF
|
|
204
|
+
[SPAWN_SERVICE_AGENT]
|
|
205
|
+
Service: ${skillName}
|
|
206
|
+
Command: $COMMAND
|
|
207
|
+
Agent: service-${skillName}
|
|
208
|
+
Working Directory: ${servicePath}
|
|
209
|
+
|
|
210
|
+
Claude should:
|
|
211
|
+
1. Spawn Task tool with subagent_type="general-purpose"
|
|
212
|
+
2. Set working directory to: ${servicePath}
|
|
213
|
+
3. Pass this request to the agent:
|
|
214
|
+
|
|
215
|
+
"You are the service agent for ${skillName}.
|
|
216
|
+
|
|
217
|
+
Your working directory is: ${servicePath}
|
|
218
|
+
|
|
219
|
+
Read your knowledge docs to understand the service:
|
|
220
|
+
- knowledge/SERVICE_SPEC.md
|
|
221
|
+
- knowledge/ARCHITECTURE.md
|
|
222
|
+
- knowledge/DEPLOYMENT.md
|
|
223
|
+
- knowledge/RUNBOOK.md
|
|
224
|
+
|
|
225
|
+
User request: $COMMAND the service
|
|
226
|
+
|
|
227
|
+
Execute the operation, update status, emit event, write journal, and report outcome."
|
|
228
|
+
|
|
229
|
+
[/SPAWN_SERVICE_AGENT]
|
|
230
|
+
EOF
|
|
231
|
+
`;
|
|
232
|
+
}
|
|
233
|
+
/**
|
|
234
|
+
* Write skill files to GTM repo
|
|
235
|
+
*/
|
|
236
|
+
export function writeSkillFiles(metadata, servicePath, gtmPath) {
|
|
237
|
+
const skillName = metadata.name;
|
|
238
|
+
const skillDir = join(gtmPath, ".claude/skills", skillName);
|
|
239
|
+
// Ensure directory exists
|
|
240
|
+
if (!existsSync(skillDir)) {
|
|
241
|
+
mkdirSync(skillDir, { recursive: true });
|
|
242
|
+
}
|
|
243
|
+
// Write SKILL.md
|
|
244
|
+
const skillMd = generateSkillDefinition(metadata, servicePath);
|
|
245
|
+
const skillMdPath = join(skillDir, "SKILL.md");
|
|
246
|
+
writeFileSync(skillMdPath, skillMd);
|
|
247
|
+
// Write handler.sh
|
|
248
|
+
const handler = generateSkillHandler(metadata, servicePath, gtmPath);
|
|
249
|
+
const handlerPath = join(skillDir, "handler.sh");
|
|
250
|
+
writeFileSync(handlerPath, handler, { mode: 0o755 });
|
|
251
|
+
return skillDir;
|
|
252
|
+
}
|
|
253
|
+
//# sourceMappingURL=skill-generator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skill-generator.js","sourceRoot":"","sources":["../../src/lib/skill-generator.ts"],"names":[],"mappings":"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"}
|