@skaile/workspaces 0.44.0 → 0.46.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/CHANGELOG.md +141 -0
- package/dist/{asset-feeds-EGSG4FUB.js → asset-feeds-DLRQWELS.js} +7 -7
- package/dist/{asset-feeds-EGSG4FUB.js.map → asset-feeds-DLRQWELS.js.map} +1 -1
- package/dist/asset-manager/index.js +7 -7
- package/dist/asset-manager/installer.js +6 -6
- package/dist/asset-manager/renderers.js +2 -2
- package/dist/asset-manager/src/index.d.ts +47 -0
- package/dist/asset-manager/src/index.d.ts.map +1 -1
- package/dist/{chunk-VPXV2Z5E.js → chunk-3VBQJZYL.js} +6 -6
- package/dist/chunk-3VBQJZYL.js.map +1 -0
- package/dist/{chunk-LMRO2QNF.js → chunk-3VT2I7IA.js} +72 -5
- package/dist/chunk-3VT2I7IA.js.map +1 -0
- package/dist/{chunk-CVWA4RIK.js → chunk-4VPRAG35.js} +5 -5
- package/dist/{chunk-CVWA4RIK.js.map → chunk-4VPRAG35.js.map} +1 -1
- package/dist/{chunk-JUZLVRI4.js → chunk-CNP2FHRM.js} +84 -19
- package/dist/chunk-CNP2FHRM.js.map +1 -0
- package/dist/{chunk-RGPBEGP2.js → chunk-CU5Z7GH3.js} +6 -2
- package/dist/chunk-CU5Z7GH3.js.map +1 -0
- package/dist/{chunk-CBZEIFU4.js → chunk-DDR4OSSM.js} +3 -3
- package/dist/{chunk-CBZEIFU4.js.map → chunk-DDR4OSSM.js.map} +1 -1
- package/dist/{chunk-PCXU2CVW.js → chunk-FAALG3QN.js} +4 -4
- package/dist/{chunk-PCXU2CVW.js.map → chunk-FAALG3QN.js.map} +1 -1
- package/dist/{chunk-5LHPKVGR.js → chunk-FX4BDEUN.js} +126 -9
- package/dist/chunk-FX4BDEUN.js.map +1 -0
- package/dist/{chunk-BLGHFVXE.js → chunk-G3GODNHM.js} +66 -4
- package/dist/chunk-G3GODNHM.js.map +1 -0
- package/dist/{chunk-ETDXTGDF.js → chunk-HOEP5CJQ.js} +3 -3
- package/dist/{chunk-ETDXTGDF.js.map → chunk-HOEP5CJQ.js.map} +1 -1
- package/dist/{chunk-5FVJXQDP.js → chunk-JXHULIOA.js} +3 -3
- package/dist/{chunk-5FVJXQDP.js.map → chunk-JXHULIOA.js.map} +1 -1
- package/dist/{chunk-ZAEJ33Y6.js → chunk-LLOXWWB6.js} +5 -5
- package/dist/{chunk-ZAEJ33Y6.js.map → chunk-LLOXWWB6.js.map} +1 -1
- package/dist/{chunk-GM3BV6JK.js → chunk-P6HRQPXC.js} +2 -2
- package/dist/{chunk-GM3BV6JK.js.map → chunk-P6HRQPXC.js.map} +1 -1
- package/dist/{chunk-NHLXS2CH.js → chunk-PPSRBFYE.js} +2 -2
- package/dist/{chunk-NHLXS2CH.js.map → chunk-PPSRBFYE.js.map} +1 -1
- package/dist/{chunk-7NQXVBCQ.js → chunk-TKTXIAG5.js} +5 -5
- package/dist/{chunk-7NQXVBCQ.js.map → chunk-TKTXIAG5.js.map} +1 -1
- package/dist/{chunk-XUXVH3JK.js → chunk-WRBF34YE.js} +3 -3
- package/dist/{chunk-XUXVH3JK.js.map → chunk-WRBF34YE.js.map} +1 -1
- package/dist/{chunk-COSTF7QW.js → chunk-WTFJFW7F.js} +50 -12
- package/dist/chunk-WTFJFW7F.js.map +1 -0
- package/dist/{chunk-XF2BBX6P.js → chunk-Z3ZRI2AE.js} +3 -3
- package/dist/{chunk-XF2BBX6P.js.map → chunk-Z3ZRI2AE.js.map} +1 -1
- package/dist/cli/index.js +1039 -704
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/src/commands/asset-cmd.d.ts +1 -1
- package/dist/cli/src/commands/asset-cmd.d.ts.map +1 -1
- package/dist/cli/src/commands/catalog.d.ts +11 -4
- package/dist/cli/src/commands/catalog.d.ts.map +1 -1
- package/dist/cli/src/commands/library-cmd.d.ts.map +1 -1
- package/dist/cli/src/commands/npx.d.ts.map +1 -1
- package/dist/cli/src/commands/project.d.ts.map +1 -1
- package/dist/cli/src/commands/skailify-lib.d.ts +108 -0
- package/dist/cli/src/commands/skailify-lib.d.ts.map +1 -0
- package/dist/cli/src/commands/source.d.ts +17 -4
- package/dist/cli/src/commands/source.d.ts.map +1 -1
- package/dist/cli/src/commands/validate.d.ts.map +1 -1
- package/dist/cli/src/ensure-sources.d.ts.map +1 -1
- package/dist/connectors/config.js +4 -4
- package/dist/connectors/index.js +5 -5
- package/dist/core/index.js +3 -3
- package/dist/core/runtime-assets.js +2 -2
- package/dist/core/src/conformance.d.ts +33 -0
- package/dist/core/src/conformance.d.ts.map +1 -0
- package/dist/core/src/index.d.ts +3 -2
- package/dist/core/src/index.d.ts.map +1 -1
- package/dist/core/src/repo-manager.d.ts +24 -0
- package/dist/core/src/repo-manager.d.ts.map +1 -1
- package/dist/core/src/runtime-assets.d.ts.map +1 -1
- package/dist/core/src/workspace-config.d.ts.map +1 -1
- package/dist/core/workspace-config.js +1 -1
- package/dist/deploy/index.js +3 -3
- package/dist/discovery/index.js +2 -2
- package/dist/{ensure-sources-NSDMTAWN.js → ensure-sources-KLCGXVE6.js} +12 -13
- package/dist/ensure-sources-KLCGXVE6.js.map +1 -0
- package/dist/factory-assets/connectors/deploy.js +5 -5
- package/dist/factory-assets/connectors/devserver.js +5 -5
- package/dist/factory-assets/connectors/flow/adapter.js +5 -5
- package/dist/factory-assets/connectors/flow/engine.js +3 -3
- package/dist/factory-assets/connectors/flow/run-flow.js +6 -6
- package/dist/factory-assets/connectors/flow.js +5 -5
- package/dist/factory-assets/connectors/git/CONNECTOR.md +8 -0
- package/dist/factory-assets/connectors/git/driver.d.ts +33 -1
- package/dist/factory-assets/connectors/git/driver.d.ts.map +1 -1
- package/dist/factory-assets/connectors/git.js +5 -5
- package/dist/factory-assets/connectors/gmail.js +5 -5
- package/dist/factory-assets/connectors/googledrive.js +5 -5
- package/dist/factory-assets/connectors/local.js +5 -5
- package/dist/factory-assets/connectors/mattermost.js +5 -5
- package/dist/factory-assets/connectors/memory.js +5 -5
- package/dist/factory-assets/connectors/minio.js +5 -5
- package/dist/factory-assets/connectors/postgres.js +5 -5
- package/dist/factory-assets/connectors/s3.js +5 -5
- package/dist/factory-assets/connectors/sharepoint.js +5 -5
- package/dist/factory-assets/connectors/sqlite.js +5 -5
- package/dist/factory-assets/connectors/static-server.js +5 -5
- package/dist/factory-assets/connectors/tunnel.js +5 -5
- package/dist/factory-assets/connectors/webdav.js +5 -5
- package/dist/factory-assets/connectors/xstate-store.js +5 -5
- package/dist/factory-assets/connectors/xstate.js +5 -5
- package/dist/factory-assets/skaile.manifest.yaml +3 -0
- package/dist/factory-assets/skills/skailify/SKILL.md +84 -0
- package/dist/{flows-WELXQ7IG.js → flows-PNDUCOJR.js} +3 -3
- package/dist/{flows-WELXQ7IG.js.map → flows-PNDUCOJR.js.map} +1 -1
- package/dist/library/index.js +6 -6
- package/dist/library/install.js +3 -3
- package/dist/{open-library-362BZ6OW.js → open-library-COHFCT4N.js} +9 -9
- package/dist/{open-library-362BZ6OW.js.map → open-library-COHFCT4N.js.map} +1 -1
- package/dist/{paths-4SSFMX5Z.js → paths-2SYXGTZJ.js} +6 -6
- package/dist/{paths-4SSFMX5Z.js.map → paths-2SYXGTZJ.js.map} +1 -1
- package/dist/{plugin-store-RBCDBO7K.js → plugin-store-UNENLB56.js} +5 -5
- package/dist/{plugin-store-RBCDBO7K.js.map → plugin-store-UNENLB56.js.map} +1 -1
- package/dist/runner/index.js +7 -7
- package/dist/runner/src/file-changed-coalescer.d.ts +48 -0
- package/dist/runner/src/file-changed-coalescer.d.ts.map +1 -0
- package/dist/runner/src/resources.d.ts.map +1 -1
- package/dist/sdk/asset-manager.js +7 -7
- package/dist/sdk/core.js +3 -3
- package/dist/sdk/flow.js +3 -3
- package/dist/sdk/index.js +7 -7
- package/dist/sdk/runner.js +7 -7
- package/dist/{setup-VGZTFQ32.js → setup-AYH6SR4U.js} +5 -5
- package/dist/{setup-VGZTFQ32.js.map → setup-AYH6SR4U.js.map} +1 -1
- package/dist/{store-client-XFZFKY3W.js → store-client-U4FMAIWX.js} +6 -6
- package/dist/{store-client-XFZFKY3W.js.map → store-client-U4FMAIWX.js.map} +1 -1
- package/dist/tui/index.js +7 -7
- package/dist/types/manifests.js +1 -1
- package/dist/types/src/manifests/skill.d.ts +1 -0
- package/dist/types/src/manifests/skill.d.ts.map +1 -1
- package/dist/workspace-plugin/adapters/mcp.js +1 -1
- package/dist/workspace-plugin/adapters/omp.js +3 -3
- package/dist/workspace-plugin/index.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-5LHPKVGR.js.map +0 -1
- package/dist/chunk-BLGHFVXE.js.map +0 -1
- package/dist/chunk-COSTF7QW.js.map +0 -1
- package/dist/chunk-JUZLVRI4.js.map +0 -1
- package/dist/chunk-LMRO2QNF.js.map +0 -1
- package/dist/chunk-RGPBEGP2.js.map +0 -1
- package/dist/chunk-VPXV2Z5E.js.map +0 -1
- package/dist/ensure-sources-NSDMTAWN.js.map +0 -1
package/dist/cli/index.js
CHANGED
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { openCatalogSource, openLibraryManager, createFullRegistry, openLibrary } from '../chunk-
|
|
2
|
+
import { openCatalogSource, openLibraryManager, createFullRegistry, openLibrary } from '../chunk-FAALG3QN.js';
|
|
3
3
|
import { logErr, S, logOk, logInfo, colorRef, logWarn, kindColorPad, kindColor, formatRelativeTime, fitWidth } from '../chunk-GYPA2Q7F.js';
|
|
4
|
-
import { getStoreConfig, storeFetch, saveStoreTokens, clearStoreTokens, isStoreAuthenticated } from '../chunk-
|
|
5
|
-
import { AI_RESOURCES, aiResourceRoots } from '../chunk-
|
|
4
|
+
import { getStoreConfig, storeFetch, saveStoreTokens, clearStoreTokens, isStoreAuthenticated } from '../chunk-Z3ZRI2AE.js';
|
|
5
|
+
import { AI_RESOURCES, aiResourceRoots } from '../chunk-HOEP5CJQ.js';
|
|
6
6
|
import { LocalSecretsProvider } from '../chunk-6BEGKO2Q.js';
|
|
7
|
-
import { resolveLibraryDir, LocalCatalogSource } from '../chunk-
|
|
8
|
-
import '../chunk-
|
|
7
|
+
import { resolveLibraryDir, LocalCatalogSource } from '../chunk-LLOXWWB6.js';
|
|
8
|
+
import '../chunk-JXHULIOA.js';
|
|
9
9
|
import '../chunk-JXT46QFC.js';
|
|
10
10
|
import '../chunk-UKJMQZV6.js';
|
|
11
11
|
import '../chunk-R7FOF242.js';
|
|
12
|
-
import { runFlow, resumeFlow } from '../chunk-
|
|
12
|
+
import { runFlow, resumeFlow } from '../chunk-TKTXIAG5.js';
|
|
13
13
|
import '../chunk-4R6DROGN.js';
|
|
14
14
|
import { validateFlowVersions, parseSkillFrontmatter } from '../chunk-GXC3TYMQ.js';
|
|
15
|
-
import { runAgentChat, loadSessionById, loadSession, listSessions, setCurrentSession, deleteSession, clearSession, loadAgentManifest, compileComposition, MarkdownStreamer, resolveMixin } from '../chunk-
|
|
16
|
-
import { buildClaudePluginFiles } from '../chunk-
|
|
15
|
+
import { runAgentChat, loadSessionById, loadSession, listSessions, setCurrentSession, deleteSession, clearSession, loadAgentManifest, compileComposition, MarkdownStreamer, resolveMixin } from '../chunk-FX4BDEUN.js';
|
|
16
|
+
import { buildClaudePluginFiles } from '../chunk-PPSRBFYE.js';
|
|
17
17
|
import '../chunk-X5YPJV4N.js';
|
|
18
18
|
import '../chunk-O7SG5PC2.js';
|
|
19
19
|
import '../chunk-7QBNJTTQ.js';
|
|
@@ -28,59 +28,514 @@ import '../chunk-BMQKMOQY.js';
|
|
|
28
28
|
import '../chunk-GAH4YRCI.js';
|
|
29
29
|
import '../chunk-OCAQH66V.js';
|
|
30
30
|
import '../chunk-LV2HPH3C.js';
|
|
31
|
-
import '../chunk-
|
|
31
|
+
import '../chunk-3VT2I7IA.js';
|
|
32
32
|
import '../chunk-OVRSNIKJ.js';
|
|
33
|
-
import '../chunk-
|
|
33
|
+
import '../chunk-DDR4OSSM.js';
|
|
34
34
|
import '../chunk-FYLIR4AV.js';
|
|
35
35
|
import '../chunk-6E6PKKAD.js';
|
|
36
36
|
import { loadFlow, loadAllFlows } from '../chunk-X46FY45B.js';
|
|
37
37
|
import '../chunk-DEYYRFQU.js';
|
|
38
38
|
import '../chunk-IFGTRL2I.js';
|
|
39
|
-
import { AssetManager, NON_DEPLOYABLE_KINDS } from '../chunk-
|
|
40
|
-
import '../chunk-
|
|
41
|
-
import { readLock, resolveSettings, globalSettingsPath, projectSettingsPath, loadSettings, saveSettings, portableSpawn, portableSpawnSync, WorkspaceYamlEditor } from '../chunk-
|
|
39
|
+
import { AssetManager, NON_DEPLOYABLE_KINDS, MissingManifestError } from '../chunk-CNP2FHRM.js';
|
|
40
|
+
import '../chunk-4VPRAG35.js';
|
|
41
|
+
import { readLock, resolveSettings, globalSettingsPath, projectSettingsPath, loadSettings, saveSettings, portableSpawn, portableSpawnSync, WorkspaceYamlEditor, checkAgentSkillConformance } from '../chunk-G3GODNHM.js';
|
|
42
42
|
import { assetSearchDirs, detectDomains } from '../chunk-ZAP2BDHG.js';
|
|
43
|
-
import '../chunk-
|
|
44
|
-
import { globalCacheRoot, getGlobalCacheDir, resolveAgentDir, findWorkspaceRoot, workspaceConfigFilename, resolveSkWorkspaceConfig } from '../chunk-
|
|
45
|
-
import { SKAILE_MANIFEST_FILENAME, decodeSkaileManifest } from '../chunk-DZCK7GRW.js';
|
|
43
|
+
import '../chunk-3VBQJZYL.js';
|
|
44
|
+
import { globalCacheRoot, sourceCacheKey, getGlobalCacheDir, resolveAgentDir, sourceShortName, findWorkspaceRoot, workspaceConfigFilename, resolveSkWorkspaceConfig } from '../chunk-WTFJFW7F.js';
|
|
45
|
+
import { SKAILE_MANIFEST_FILENAME, decodeSkaileManifest, loadSkPublishManifest, saveSkPublishManifest } from '../chunk-DZCK7GRW.js';
|
|
46
46
|
import { parseFrontmatter } from '../chunk-6IDBWPK2.js';
|
|
47
|
-
import { parseAssetRef, ASSET_KINDS, isValidAssetName, ASSET_NAME_HINT, assetRefToStr } from '../chunk-GEEW6SY2.js';
|
|
47
|
+
import { parseAssetRef, ASSET_KINDS, isValidAssetName, slugifyAssetName, ASSET_NAME_HINT, assetRefToStr } from '../chunk-GEEW6SY2.js';
|
|
48
48
|
import '../chunk-XGCXFX7X.js';
|
|
49
49
|
import { SUPPORTED_DRIVER_TARGETS } from '../chunk-O4JH3KUE.js';
|
|
50
50
|
import { DRIVER_DEFAULTS } from '../chunk-K5GBV4SA.js';
|
|
51
51
|
import { openSqlite } from '../chunk-JB35MVBN.js';
|
|
52
52
|
import '../chunk-KTBKW2FI.js';
|
|
53
53
|
import '../chunk-UQ6LFBPZ.js';
|
|
54
|
-
import '../chunk-
|
|
55
|
-
import '../chunk-
|
|
54
|
+
import '../chunk-WRBF34YE.js';
|
|
55
|
+
import '../chunk-CU5Z7GH3.js';
|
|
56
56
|
import '../chunk-CGYEHQOX.js';
|
|
57
57
|
import '../chunk-NSBPE2FW.js';
|
|
58
|
-
import * as
|
|
59
|
-
import
|
|
60
|
-
import * as
|
|
61
|
-
import
|
|
58
|
+
import * as fs12 from 'fs';
|
|
59
|
+
import fs12__default, { readFileSync, existsSync, mkdirSync, writeFileSync, lstatSync, rmSync, readdirSync, statSync } from 'fs';
|
|
60
|
+
import * as path14 from 'path';
|
|
61
|
+
import path14__default, { resolve, join } from 'path';
|
|
62
62
|
import { fileURLToPath } from 'url';
|
|
63
63
|
import { Help, Command, Option } from 'commander';
|
|
64
|
-
import { homedir } from 'os';
|
|
65
64
|
import * as p6 from '@clack/prompts';
|
|
66
65
|
import pc5 from 'picocolors';
|
|
66
|
+
import * as os from 'os';
|
|
67
|
+
import { homedir } from 'os';
|
|
68
|
+
import { parse, stringify } from 'yaml';
|
|
67
69
|
import * as readline from 'readline';
|
|
68
70
|
import { createInterface } from 'readline';
|
|
69
|
-
import
|
|
70
|
-
import { parse as parse$1, stringify } from 'smol-toml';
|
|
71
|
+
import fs6 from 'fs/promises';
|
|
72
|
+
import { parse as parse$1, stringify as stringify$1 } from 'smol-toml';
|
|
71
73
|
import { execSync, spawnSync } from 'child_process';
|
|
72
74
|
import { createTRPCUntypedClient, httpLink, httpSubscriptionLink } from '@trpc/client';
|
|
73
|
-
import { parse } from 'yaml';
|
|
74
75
|
|
|
76
|
+
async function runSearch(kind, query, opts) {
|
|
77
|
+
if (kind?.includes(":")) {
|
|
78
|
+
query = kind;
|
|
79
|
+
kind = void 0;
|
|
80
|
+
}
|
|
81
|
+
const showLocal = !opts.store;
|
|
82
|
+
const showStore = !opts.local;
|
|
83
|
+
if (showLocal) {
|
|
84
|
+
searchLocal(query, kind, opts, showStore);
|
|
85
|
+
}
|
|
86
|
+
if (showStore) {
|
|
87
|
+
await searchStore(query, kind, opts);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
function searchLocal(query, kind, opts, showStore) {
|
|
91
|
+
const am2 = new AssetManager({ projectDir: path14__default.resolve(opts.projectDir) });
|
|
92
|
+
const entries = am2.search(query, kind);
|
|
93
|
+
if (entries.length === 0) {
|
|
94
|
+
if (!showStore) {
|
|
95
|
+
logInfo(
|
|
96
|
+
query ? `No entries matching "${query}".` : "No assets found. Run `skaile source sync` first."
|
|
97
|
+
);
|
|
98
|
+
}
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
if (showStore) {
|
|
102
|
+
console.log(`
|
|
103
|
+
${S.heading("Local:")}`);
|
|
104
|
+
}
|
|
105
|
+
printLocalEntries(entries);
|
|
106
|
+
}
|
|
107
|
+
function printLocalEntries(entries) {
|
|
108
|
+
const byKind = /* @__PURE__ */ new Map();
|
|
109
|
+
for (const e of entries) {
|
|
110
|
+
if (!byKind.has(e.kind)) byKind.set(e.kind, []);
|
|
111
|
+
byKind.get(e.kind).push(e);
|
|
112
|
+
}
|
|
113
|
+
for (const [k, items] of byKind) {
|
|
114
|
+
const nameW = Math.max(4, ...items.map((e) => e.name.length));
|
|
115
|
+
console.log();
|
|
116
|
+
console.log(
|
|
117
|
+
` ${kindColor(k)} ${S.heading(`${k.toUpperCase()}S`)} ${S.dim(`(${items.length})`)}`
|
|
118
|
+
);
|
|
119
|
+
console.log(` ${S.rule(nameW + 62)}`);
|
|
120
|
+
for (const e of items) {
|
|
121
|
+
const ver = e.version ? S.dim(` v${e.version}`) : "";
|
|
122
|
+
console.log(` ${S.cmd(e.name.padEnd(nameW))} ${e.description.slice(0, 60)}${ver}`);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
console.log(`
|
|
126
|
+
${S.dim(`${entries.length} total`)}
|
|
127
|
+
`);
|
|
128
|
+
}
|
|
129
|
+
async function searchStore(query, kind, opts) {
|
|
130
|
+
try {
|
|
131
|
+
const { getStoreConfig: getStoreConfig2, storeFetch: storeFetch2 } = await import('../store-client-U4FMAIWX.js');
|
|
132
|
+
const config = getStoreConfig2();
|
|
133
|
+
const params = {};
|
|
134
|
+
if (query) params.q = query;
|
|
135
|
+
if (kind) params.kind = kind;
|
|
136
|
+
const storeRes = await storeFetch2(config, "/api/assets", { params });
|
|
137
|
+
if (storeRes.results.length > 0) {
|
|
138
|
+
console.log(`
|
|
139
|
+
${S.heading("Store:")}`);
|
|
140
|
+
for (const asset of storeRes.results) {
|
|
141
|
+
const ref = `${asset.kind}:@${asset.publisher}/${asset.slug}`;
|
|
142
|
+
console.log(
|
|
143
|
+
` \u2B21 ${kindColorPad(asset.kind)} ${colorRef(ref).padEnd(40)} ${S.dim(asset.description?.slice(0, 50) || "")} ${S.dim(`\u2193${asset.downloads}`)}`
|
|
144
|
+
);
|
|
145
|
+
}
|
|
146
|
+
} else if (opts.store) {
|
|
147
|
+
logInfo("No results in store");
|
|
148
|
+
}
|
|
149
|
+
} catch (e) {
|
|
150
|
+
if (opts.store) {
|
|
151
|
+
logErr(`Store search failed: ${e.message}`);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
function makeSearchCommand() {
|
|
156
|
+
return new Command("search").description("Search across all repos").argument("[kind]", "Filter by asset kind").argument("[query]", "Search query").option("--project-dir <path>", "Project directory", process.cwd()).option("--store", "Search only the store").option("--local", "Search only local repos").action(async (kind, query, opts) => {
|
|
157
|
+
await runSearch(kind, query, opts);
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
function makeAddCommand() {
|
|
161
|
+
return new Command("add").description("Add to skaile.yaml + deploy").argument("<ref>", "Asset reference (kind:@<publisher>/name#<version>)").option("--project-dir <path>", "Project directory", process.cwd()).option("--global", "Deploy to global dir (~/.claude)").option("--target <agent>", "Driver target", "claude-code").action(async (ref, opts) => {
|
|
162
|
+
const am2 = new AssetManager({
|
|
163
|
+
projectDir: path14__default.resolve(opts.projectDir),
|
|
164
|
+
global: opts.global,
|
|
165
|
+
driverTarget: opts.target
|
|
166
|
+
});
|
|
167
|
+
const spinner5 = p6.spinner();
|
|
168
|
+
spinner5.start(`Adding ${ref}`);
|
|
169
|
+
try {
|
|
170
|
+
const added = await am2.add(ref);
|
|
171
|
+
spinner5.stop("Done");
|
|
172
|
+
if (added.length === 0) {
|
|
173
|
+
const kind = parseAssetRef(ref).kind;
|
|
174
|
+
if (NON_DEPLOYABLE_KINDS.has(kind))
|
|
175
|
+
logInfo(
|
|
176
|
+
`Recorded in skaile.yaml. ${kind} assets are not deployed into the driver target \u2014 they are wired when skaile runs the agent.`
|
|
177
|
+
);
|
|
178
|
+
else logInfo("Nothing to deploy (already up to date).");
|
|
179
|
+
} else for (const a of added) logOk(a);
|
|
180
|
+
} catch (err) {
|
|
181
|
+
spinner5.stop("Failed");
|
|
182
|
+
logErr(String(err));
|
|
183
|
+
process.exit(1);
|
|
184
|
+
}
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
function makeRemoveCommand() {
|
|
188
|
+
return new Command("remove").description("Remove from skaile.yaml + undeploy").argument("<ref>", "Asset reference (kind:name)").option("--project-dir <path>", "Project directory", process.cwd()).option("--global", "Remove from global dir").option("--target <agent>", "Driver target", "claude-code").action((ref, opts) => {
|
|
189
|
+
const am2 = new AssetManager({
|
|
190
|
+
projectDir: path14__default.resolve(opts.projectDir),
|
|
191
|
+
global: opts.global,
|
|
192
|
+
driverTarget: opts.target
|
|
193
|
+
});
|
|
194
|
+
const ok = am2.remove(ref);
|
|
195
|
+
if (ok) logOk(`Removed ${ref}`);
|
|
196
|
+
else logErr(`Not deployed: ${ref}`);
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
function stateLabel(s) {
|
|
200
|
+
if (s === "installed") return S.ok(s);
|
|
201
|
+
if (s === "drift") return S.warn(s);
|
|
202
|
+
if (s === "invalid") return S.err(s);
|
|
203
|
+
return S.dim(s);
|
|
204
|
+
}
|
|
205
|
+
function makeListCommand() {
|
|
206
|
+
return new Command("list").description("List declared dependencies from skaile.yaml with state").argument("[kind]", "Filter by asset kind").option("--project-dir <path>", "Project directory", process.cwd()).option("-g, --global", "Inspect the global deployment dir for state").option("--json", "Output as JSON").addOption(
|
|
207
|
+
new Option("--target <agent>", "Driver target").default("claude-code").choices(SUPPORTED_DRIVER_TARGETS)
|
|
208
|
+
).action((kind, opts) => {
|
|
209
|
+
const am2 = new AssetManager({
|
|
210
|
+
projectDir: path14__default.resolve(opts.projectDir),
|
|
211
|
+
global: opts.global,
|
|
212
|
+
driverTarget: opts.target
|
|
213
|
+
});
|
|
214
|
+
let declared;
|
|
215
|
+
try {
|
|
216
|
+
declared = am2.listDeclared(kind);
|
|
217
|
+
} catch (err) {
|
|
218
|
+
if (err instanceof MissingManifestError)
|
|
219
|
+
logErr(`No ${S.cmd("skaile.yaml")} found. Run ${S.cmd("skaile init")} to create one.`);
|
|
220
|
+
else logErr(err instanceof Error ? err.message : String(err));
|
|
221
|
+
process.exit(1);
|
|
222
|
+
}
|
|
223
|
+
if (opts.json) {
|
|
224
|
+
console.log(JSON.stringify(declared, null, 2));
|
|
225
|
+
return;
|
|
226
|
+
}
|
|
227
|
+
if (declared.length === 0) {
|
|
228
|
+
logInfo("No dependencies declared in skaile.yaml.");
|
|
229
|
+
return;
|
|
230
|
+
}
|
|
231
|
+
const kindW = Math.max(4, ...declared.map((e) => e.kind.length));
|
|
232
|
+
const nameW = Math.max(4, ...declared.map((e) => e.name.length));
|
|
233
|
+
console.log();
|
|
234
|
+
console.log(
|
|
235
|
+
` ${S.dim("KIND".padEnd(kindW))} ${S.dim("NAME".padEnd(nameW))} ${S.dim("STATE")}`
|
|
236
|
+
);
|
|
237
|
+
console.log(` ${S.rule(kindW + nameW + 4 + "installed".length)}`);
|
|
238
|
+
for (const e of declared) {
|
|
239
|
+
console.log(
|
|
240
|
+
` ${kindColorPad(e.kind, kindW)} ${e.name.padEnd(nameW)} ${stateLabel(e.state)}`
|
|
241
|
+
);
|
|
242
|
+
}
|
|
243
|
+
console.log(`
|
|
244
|
+
${S.dim(`${declared.length} declared`)}`);
|
|
245
|
+
const drift = declared.filter((e) => e.state === "drift").length;
|
|
246
|
+
if (drift > 0)
|
|
247
|
+
logInfo(`${drift} with drift \u2014 run ${S.cmd("skaile install")} to materialize.`);
|
|
248
|
+
const invalid = declared.filter((e) => e.state === "invalid").length;
|
|
249
|
+
if (invalid > 0)
|
|
250
|
+
logInfo(`${invalid} invalid \u2014 fix the ${S.cmd("skaile.yaml")} dependencies entry.`);
|
|
251
|
+
console.log();
|
|
252
|
+
});
|
|
253
|
+
}
|
|
254
|
+
function makeInfoCommand() {
|
|
255
|
+
return new Command("info").description("Show asset metadata, deps, deploy status").argument("<ref>", "Asset reference (kind:name)").option("--project-dir <path>", "Project directory", process.cwd()).action((ref, opts) => {
|
|
256
|
+
const am2 = new AssetManager({ projectDir: path14__default.resolve(opts.projectDir) });
|
|
257
|
+
const entry = am2.info(ref);
|
|
258
|
+
if (!entry) {
|
|
259
|
+
logErr(
|
|
260
|
+
`'${ref}' not found. Run ${S.cmd("skaile source sync")} then ${S.cmd("skaile search")}.`
|
|
261
|
+
);
|
|
262
|
+
process.exit(1);
|
|
263
|
+
}
|
|
264
|
+
console.log();
|
|
265
|
+
console.log(` ${S.heading(entry.name)}`);
|
|
266
|
+
console.log(` ${S.rule(40)}`);
|
|
267
|
+
console.log(` kind: ${kindColor(entry.kind)}`);
|
|
268
|
+
if (entry.version) console.log(` version: ${entry.version}`);
|
|
269
|
+
if (entry.description) console.log(` description: ${entry.description}`);
|
|
270
|
+
if (entry.publisher) console.log(` repository: ${S.dim(entry.publisher)}`);
|
|
271
|
+
console.log(` source: ${S.dim(entry.source)}`);
|
|
272
|
+
if (entry.requires.length) {
|
|
273
|
+
console.log(` requires:`);
|
|
274
|
+
for (const d of entry.requires)
|
|
275
|
+
console.log(` ${S.dim("\xB7")} ${kindColor(d.kind)}:${d.name}`);
|
|
276
|
+
}
|
|
277
|
+
if (entry.dependencies.length) {
|
|
278
|
+
console.log(` dependencies:`);
|
|
279
|
+
for (const s of entry.dependencies) console.log(` ${S.dim("\xB7")} ${colorRef(s)}`);
|
|
280
|
+
}
|
|
281
|
+
console.log();
|
|
282
|
+
});
|
|
283
|
+
}
|
|
284
|
+
function makeCreateCommand() {
|
|
285
|
+
return new Command("create").description("Scaffold a new asset").argument("<name>", "Asset name").addOption(
|
|
286
|
+
new Option("-k, --kind <kind>", "Asset kind").default("skill").choices([...ASSET_KINDS])
|
|
287
|
+
).option("-d, --dir <dir>", "Target directory (default: cwd)").action((name, opts) => {
|
|
288
|
+
const am2 = new AssetManager({ projectDir: process.cwd() });
|
|
289
|
+
const destDir = opts.dir ? path14__default.resolve(opts.dir) : process.cwd();
|
|
290
|
+
const result = am2.create(name, opts.kind, destDir);
|
|
291
|
+
if (result.ok) logOk(`Created ${kindColor(opts.kind)}: ${pc5.dim(result.path)}`);
|
|
292
|
+
else {
|
|
293
|
+
logErr(result.path);
|
|
294
|
+
process.exit(1);
|
|
295
|
+
}
|
|
296
|
+
});
|
|
297
|
+
}
|
|
298
|
+
function makeDoctorCommand() {
|
|
299
|
+
return new Command("doctor").description("Scan for missing dependency chains").argument("[name]", "Check a specific asset (kind:name)").option("--project-dir <path>", "Project directory", process.cwd()).action((name, opts) => {
|
|
300
|
+
const am2 = new AssetManager({ projectDir: path14__default.resolve(opts.projectDir) });
|
|
301
|
+
const issues = am2.doctor();
|
|
302
|
+
if (issues.length === 0) {
|
|
303
|
+
logOk("No missing dependencies.");
|
|
304
|
+
return;
|
|
305
|
+
}
|
|
306
|
+
const assetW = Math.max(5, ...issues.map((i) => `${i.assetKind}:${i.assetName}`.length));
|
|
307
|
+
const depW = Math.max(11, ...issues.map((i) => `${i.depKind}:${i.depName}`.length));
|
|
308
|
+
console.log();
|
|
309
|
+
console.log(
|
|
310
|
+
` ${S.dim("ASSET".padEnd(assetW))} ${S.dim("MISSING DEP".padEnd(depW))} ${S.dim("IN REPOS")}`
|
|
311
|
+
);
|
|
312
|
+
console.log(` ${S.rule(assetW + depW + 15)}`);
|
|
313
|
+
for (const i of issues) {
|
|
314
|
+
const asset = `${i.assetKind}:${i.assetName}`;
|
|
315
|
+
const dep = `${i.depKind}:${i.depName}`;
|
|
316
|
+
const status4 = i.inRepos ? S.warn("fixable") : S.err("not found");
|
|
317
|
+
console.log(` ${asset.padEnd(assetW)} ${dep.padEnd(depW)} ${status4}`);
|
|
318
|
+
}
|
|
319
|
+
console.log();
|
|
320
|
+
});
|
|
321
|
+
}
|
|
322
|
+
var DEFAULT_IMPORT_VERSION = "0.1.0";
|
|
323
|
+
var DEFAULT_IMPORT_STAGE = "alpha";
|
|
324
|
+
function claudeSkillRoots() {
|
|
325
|
+
const roots = [];
|
|
326
|
+
const override = process.env.SKAILE_CLAUDE_SKILLS_DIR;
|
|
327
|
+
if (override) roots.push(override);
|
|
328
|
+
roots.push(path14.join(os.homedir(), ".claude", "skills"));
|
|
329
|
+
return roots;
|
|
330
|
+
}
|
|
331
|
+
function resolveImportSource(nameOrPath) {
|
|
332
|
+
const asPath = path14.resolve(nameOrPath);
|
|
333
|
+
if (fs12.existsSync(asPath)) {
|
|
334
|
+
const dir = fs12.statSync(asPath).isDirectory() ? asPath : path14.dirname(asPath);
|
|
335
|
+
const skillFile = path14.join(dir, "SKILL.md");
|
|
336
|
+
if (fs12.existsSync(skillFile)) return { dir, skillFile, via: "path" };
|
|
337
|
+
}
|
|
338
|
+
if (!nameOrPath.includes(path14.sep) && !nameOrPath.startsWith(".")) {
|
|
339
|
+
for (const root of claudeSkillRoots()) {
|
|
340
|
+
const dir = path14.join(root, nameOrPath);
|
|
341
|
+
const skillFile = path14.join(dir, "SKILL.md");
|
|
342
|
+
if (fs12.existsSync(skillFile)) return { dir, skillFile, via: "claude-skills" };
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
return null;
|
|
346
|
+
}
|
|
347
|
+
function normalizeSkillContent(raw, opts = {}) {
|
|
348
|
+
const notes = [];
|
|
349
|
+
const { data, body } = parseFrontmatter(raw);
|
|
350
|
+
const rawName = typeof data.name === "string" && data.name.trim() ? data.name.trim() : void 0;
|
|
351
|
+
const sourceName = rawName ?? opts.fallbackName ?? "";
|
|
352
|
+
let name = sourceName;
|
|
353
|
+
let originalName;
|
|
354
|
+
if (!sourceName) {
|
|
355
|
+
throw new Error("skill has no `name` in frontmatter and no fallback was provided");
|
|
356
|
+
}
|
|
357
|
+
if (!isValidAssetName(sourceName)) {
|
|
358
|
+
name = slugifyAssetName(sourceName);
|
|
359
|
+
originalName = sourceName;
|
|
360
|
+
notes.push(`renamed "${sourceName}" \u2192 "${name}" (canonical kebab-case)`);
|
|
361
|
+
}
|
|
362
|
+
const existingMeta = data.metadata && typeof data.metadata === "object" && !Array.isArray(data.metadata) ? { ...data.metadata } : {};
|
|
363
|
+
if (existingMeta.version == null) {
|
|
364
|
+
existingMeta.version = opts.version ?? DEFAULT_IMPORT_VERSION;
|
|
365
|
+
notes.push(`stamped metadata.version: ${existingMeta.version}`);
|
|
366
|
+
}
|
|
367
|
+
if (existingMeta.stage == null) {
|
|
368
|
+
existingMeta.stage = opts.stage ?? DEFAULT_IMPORT_STAGE;
|
|
369
|
+
notes.push(`stamped metadata.stage: ${existingMeta.stage}`);
|
|
370
|
+
}
|
|
371
|
+
if (existingMeta.tags == null) {
|
|
372
|
+
const keywords = Array.isArray(data.keywords) ? data.keywords : [];
|
|
373
|
+
existingMeta.tags = keywords.filter((k) => typeof k === "string");
|
|
374
|
+
if (existingMeta.tags.length > 0) {
|
|
375
|
+
notes.push("promoted top-level keywords \u2192 metadata.tags");
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
const ordered = { name };
|
|
379
|
+
if (data.description != null) ordered.description = data.description;
|
|
380
|
+
ordered.metadata = existingMeta;
|
|
381
|
+
for (const [k, v] of Object.entries(data)) {
|
|
382
|
+
if (k === "name" || k === "description" || k === "metadata" || k === "keywords") continue;
|
|
383
|
+
ordered[k] = v;
|
|
384
|
+
}
|
|
385
|
+
const fm = stringify(ordered).trimEnd();
|
|
386
|
+
const content = `---
|
|
387
|
+
${fm}
|
|
388
|
+
---
|
|
389
|
+
|
|
390
|
+
${body}
|
|
391
|
+
`;
|
|
392
|
+
const changed = notes.length > 0;
|
|
393
|
+
return { content, name, originalName, changed, notes };
|
|
394
|
+
}
|
|
395
|
+
var DOMAIN_TEMPLATE = (name, publisher, description) => {
|
|
396
|
+
const fm = stringify({ name, publisher, description }).trimEnd();
|
|
397
|
+
return `---
|
|
398
|
+
${fm}
|
|
399
|
+
---
|
|
400
|
+
|
|
401
|
+
# ${name}
|
|
402
|
+
|
|
403
|
+
${description}
|
|
404
|
+
`;
|
|
405
|
+
};
|
|
406
|
+
function ensureDomain(libraryPath, domain, opts = {}) {
|
|
407
|
+
const dir = path14.join(libraryPath, domain);
|
|
408
|
+
const domainFile = path14.join(dir, "DOMAIN.md");
|
|
409
|
+
const publisher = opts.publisher ?? slugifyAssetName(domain);
|
|
410
|
+
if (fs12.existsSync(domainFile)) {
|
|
411
|
+
return { dir, publisher, created: false };
|
|
412
|
+
}
|
|
413
|
+
fs12.mkdirSync(dir, { recursive: true });
|
|
414
|
+
const description = opts.description ?? `The ${domain} domain.`;
|
|
415
|
+
fs12.writeFileSync(domainFile, DOMAIN_TEMPLATE(domain, publisher, description), "utf8");
|
|
416
|
+
return { dir, publisher, created: true };
|
|
417
|
+
}
|
|
418
|
+
function listDomains(libraryPath) {
|
|
419
|
+
if (!fs12.existsSync(libraryPath)) return [];
|
|
420
|
+
return fs12.readdirSync(libraryPath, { withFileTypes: true }).filter((e) => e.isDirectory() && fs12.existsSync(path14.join(libraryPath, e.name, "DOMAIN.md"))).map((e) => e.name).sort();
|
|
421
|
+
}
|
|
422
|
+
function upsertManifestAsset(libraryPath, input) {
|
|
423
|
+
const manifest = loadSkPublishManifest(libraryPath) ?? { assets: [] };
|
|
424
|
+
const assets = Array.isArray(manifest.assets) ? [...manifest.assets] : [];
|
|
425
|
+
const entry = { kind: input.kind, name: input.name, root: input.root };
|
|
426
|
+
if (input.version) entry.version = input.version;
|
|
427
|
+
if (input.publisher) entry.publisher = input.publisher;
|
|
428
|
+
if (input.description) entry.description = input.description;
|
|
429
|
+
if (input.keywords && input.keywords.length > 0) entry.keywords = input.keywords;
|
|
430
|
+
const idx = assets.findIndex((a) => a.kind === input.kind && a.name === input.name);
|
|
431
|
+
const added = idx < 0;
|
|
432
|
+
if (added) {
|
|
433
|
+
assets.push(entry);
|
|
434
|
+
} else {
|
|
435
|
+
assets[idx] = { ...assets[idx], ...entry };
|
|
436
|
+
}
|
|
437
|
+
const manifestPath = saveSkPublishManifest(libraryPath, { ...manifest, assets });
|
|
438
|
+
return { manifestPath, added };
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
// cli/src/commands/asset-cmd.ts
|
|
75
442
|
function makeAssetCommand() {
|
|
76
443
|
const cmd = new Command("asset").description("Author and install AI assets");
|
|
444
|
+
cmd.command("import <name-or-path>").description("Import + skailify an existing coding-agent skill into a library").option("--to <library>", "Target library (default: auto / personal)").option("--domain <name>", "Place under this domain's skills/ (created if missing)").option("--version <semver>", "Version to stamp when the skill ships none").option("--stage <stage>", "Lifecycle stage to stamp (default: alpha)").option("--no-normalize", "Copy verbatim \u2014 skip frontmatter normalization").option("--commit", "Auto-commit in git-backed libraries", false).action(
|
|
445
|
+
async (nameOrPath, opts) => {
|
|
446
|
+
const src = resolveImportSource(nameOrPath);
|
|
447
|
+
if (!src) {
|
|
448
|
+
logErr(
|
|
449
|
+
`No skill found for "${nameOrPath}". Pass a path to a SKILL.md dir, or a bare name present under ~/.claude/skills/.`
|
|
450
|
+
);
|
|
451
|
+
process.exit(1);
|
|
452
|
+
}
|
|
453
|
+
logInfo(`Source: ${S.dim(src.dir)} (${src.via})`);
|
|
454
|
+
const { manager, close } = await openLibraryManager();
|
|
455
|
+
try {
|
|
456
|
+
let target;
|
|
457
|
+
if (opts.to) {
|
|
458
|
+
target = await manager.requireLibrary(opts.to);
|
|
459
|
+
} else {
|
|
460
|
+
const all = await manager.listLibraries();
|
|
461
|
+
const def = all.find(
|
|
462
|
+
(l) => l.isDefault && (l.ownership === "owner" || l.ownership === "contributor")
|
|
463
|
+
);
|
|
464
|
+
target = def ?? (await manager.ensurePersonalLibrary(resolveLibraryDir())).library;
|
|
465
|
+
}
|
|
466
|
+
if (target.ownership === "reader") {
|
|
467
|
+
logErr(`Library "${target.name}" is read-only (ownership=reader). Choose --to.`);
|
|
468
|
+
process.exit(1);
|
|
469
|
+
}
|
|
470
|
+
const rawSkill = fs12.readFileSync(src.skillFile, "utf8");
|
|
471
|
+
const norm = opts.normalize ? normalizeSkillContent(rawSkill, {
|
|
472
|
+
fallbackName: path14.basename(src.dir),
|
|
473
|
+
version: opts.version,
|
|
474
|
+
stage: opts.stage
|
|
475
|
+
}) : { content: rawSkill, name: path14.basename(src.dir), changed: false, notes: [] };
|
|
476
|
+
if (!opts.normalize && !isValidAssetName(norm.name)) {
|
|
477
|
+
logWarn(
|
|
478
|
+
`Name "${norm.name}" is not canonical (kebab-case); \`skaile validate\` will reject this manifest entry. Drop --no-normalize to slugify it.`
|
|
479
|
+
);
|
|
480
|
+
}
|
|
481
|
+
let destParent = target.path;
|
|
482
|
+
let publisher;
|
|
483
|
+
if (opts.domain) {
|
|
484
|
+
const dom = ensureDomain(target.path, opts.domain);
|
|
485
|
+
if (dom.created) logOk(`Scaffolded domain ${S.cmd(opts.domain)} \u2192 ${dom.dir}`);
|
|
486
|
+
destParent = path14.join(dom.dir, "skills");
|
|
487
|
+
publisher = dom.publisher;
|
|
488
|
+
}
|
|
489
|
+
fs12.mkdirSync(destParent, { recursive: true });
|
|
490
|
+
const destDir = path14.join(destParent, norm.name);
|
|
491
|
+
if (fs12.existsSync(destDir)) {
|
|
492
|
+
logErr(`Destination already exists: ${destDir}`);
|
|
493
|
+
process.exit(1);
|
|
494
|
+
}
|
|
495
|
+
fs12.cpSync(src.dir, destDir, { recursive: true });
|
|
496
|
+
fs12.writeFileSync(path14.join(destDir, "SKILL.md"), norm.content, "utf8");
|
|
497
|
+
for (const note of norm.notes) logInfo(` \u2022 ${note}`);
|
|
498
|
+
const fm = parseFrontmatter(norm.content).data;
|
|
499
|
+
const descRaw = fm.description;
|
|
500
|
+
const description = typeof descRaw === "string" ? descRaw.trim() : void 0;
|
|
501
|
+
for (const f of checkAgentSkillConformance(fm, { dirName: norm.name })) {
|
|
502
|
+
logWarn(`conformance: ${f.field} \u2014 ${f.message}`);
|
|
503
|
+
}
|
|
504
|
+
const root = path14.relative(target.path, destDir);
|
|
505
|
+
const up = upsertManifestAsset(target.path, {
|
|
506
|
+
kind: "skill",
|
|
507
|
+
name: norm.name,
|
|
508
|
+
root,
|
|
509
|
+
version: opts.version,
|
|
510
|
+
publisher,
|
|
511
|
+
description
|
|
512
|
+
});
|
|
513
|
+
logOk(`${up.added ? "Added" : "Updated"} manifest entry skill:${norm.name}`);
|
|
514
|
+
if (target.backend === "git" && opts.commit) {
|
|
515
|
+
const { spawnSync: spawnSync2 } = await import('child_process');
|
|
516
|
+
spawnSync2("git", ["add", "--", destDir], { cwd: target.path, stdio: "inherit" });
|
|
517
|
+
const r = spawnSync2("git", ["commit", "-m", `skaile: import ${norm.name}`], {
|
|
518
|
+
cwd: target.path,
|
|
519
|
+
stdio: "inherit"
|
|
520
|
+
});
|
|
521
|
+
if (r.status !== 0) {
|
|
522
|
+
logWarn("Nothing committed (working tree clean or commit aborted).");
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
logOk(`Imported ${S.cmd(norm.name)} \u2192 ${target.name}`);
|
|
526
|
+
logInfo(`Verify: ${S.cmd(`skaile validate ${target.path}`)}`);
|
|
527
|
+
} finally {
|
|
528
|
+
close();
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
);
|
|
77
532
|
cmd.command("migrate <path>").description("Move/copy/link a workspace asset into a library").option("--to <library>", "Target library (default: auto)").option("--domain <name>", "Place inside this domain (domain-structured libs)").option("--mode <mode>", "copy | move | link", "copy").option("--commit", "Auto-commit in git-backed libraries", false).action(
|
|
78
533
|
async (srcPath, opts) => {
|
|
79
534
|
if (!["copy", "move", "link"].includes(opts.mode)) {
|
|
80
535
|
logErr(`Invalid --mode "${opts.mode}". Expected: copy | move | link.`);
|
|
81
536
|
process.exit(1);
|
|
82
537
|
}
|
|
83
|
-
if (!
|
|
538
|
+
if (!fs12.existsSync(srcPath)) {
|
|
84
539
|
logErr(`Source path does not exist: ${srcPath}`);
|
|
85
540
|
process.exit(1);
|
|
86
541
|
}
|
|
@@ -107,32 +562,35 @@ function makeAssetCommand() {
|
|
|
107
562
|
);
|
|
108
563
|
process.exit(1);
|
|
109
564
|
}
|
|
110
|
-
const basename2 =
|
|
111
|
-
const destDir = target.structure === "domain" && opts.domain ?
|
|
112
|
-
|
|
113
|
-
const destPath =
|
|
114
|
-
if (
|
|
565
|
+
const basename2 = path14.basename(srcPath);
|
|
566
|
+
const destDir = target.structure === "domain" && opts.domain ? path14.join(target.path, opts.domain) : target.path;
|
|
567
|
+
fs12.mkdirSync(destDir, { recursive: true });
|
|
568
|
+
const destPath = path14.join(destDir, basename2);
|
|
569
|
+
if (fs12.existsSync(destPath)) {
|
|
115
570
|
logErr(`Destination already exists: ${destPath}`);
|
|
116
571
|
process.exit(1);
|
|
117
572
|
}
|
|
118
573
|
switch (opts.mode) {
|
|
119
574
|
case "copy":
|
|
120
|
-
|
|
575
|
+
fs12.cpSync(srcPath, destPath, { recursive: true });
|
|
121
576
|
break;
|
|
122
577
|
case "move":
|
|
123
|
-
|
|
578
|
+
fs12.renameSync(srcPath, destPath);
|
|
124
579
|
break;
|
|
125
580
|
case "link":
|
|
126
|
-
|
|
581
|
+
fs12.symlinkSync(path14.resolve(srcPath), destPath);
|
|
127
582
|
break;
|
|
128
583
|
}
|
|
129
584
|
if (target.backend === "git" && opts.commit) {
|
|
130
585
|
const { spawnSync: spawnSync2 } = await import('child_process');
|
|
131
|
-
spawnSync2("git", ["add", "
|
|
132
|
-
spawnSync2("git", ["commit", "-m", `skaile: migrate ${basename2}`], {
|
|
586
|
+
spawnSync2("git", ["add", "--", destPath], { cwd: target.path, stdio: "inherit" });
|
|
587
|
+
const r = spawnSync2("git", ["commit", "-m", `skaile: migrate ${basename2}`], {
|
|
133
588
|
cwd: target.path,
|
|
134
|
-
stdio: "
|
|
589
|
+
stdio: "inherit"
|
|
135
590
|
});
|
|
591
|
+
if (r.status !== 0) {
|
|
592
|
+
logWarn("Nothing committed (working tree clean or commit aborted).");
|
|
593
|
+
}
|
|
136
594
|
}
|
|
137
595
|
logOk(`Migrated ${basename2} \u2192 ${target.name} (${opts.mode})`);
|
|
138
596
|
if (opts.mode === "move") {
|
|
@@ -157,7 +615,7 @@ function makeAssetCommand() {
|
|
|
157
615
|
try {
|
|
158
616
|
const def = await library.getAssetDef(ref);
|
|
159
617
|
if (!def) {
|
|
160
|
-
logErr(`No asset found for ref "${ref}". Try \`skaile
|
|
618
|
+
logErr(`No asset found for ref "${ref}". Try \`skaile search\`.`);
|
|
161
619
|
process.exit(1);
|
|
162
620
|
}
|
|
163
621
|
const target = opts.target ?? process.cwd();
|
|
@@ -171,17 +629,17 @@ function makeAssetCommand() {
|
|
|
171
629
|
}
|
|
172
630
|
const manifestPath = def.manifest.path;
|
|
173
631
|
const candidateSubpath = typeof manifestPath === "string" && manifestPath.length > 0 ? manifestPath : def.name;
|
|
174
|
-
const srcPath =
|
|
175
|
-
if (!
|
|
632
|
+
const srcPath = path14.join(lib.path, candidateSubpath);
|
|
633
|
+
if (!fs12.existsSync(srcPath)) {
|
|
176
634
|
logErr(`Asset path not found: ${srcPath}`);
|
|
177
635
|
process.exit(1);
|
|
178
636
|
}
|
|
179
|
-
const destPath =
|
|
180
|
-
|
|
637
|
+
const destPath = path14.join(target, candidateSubpath);
|
|
638
|
+
fs12.mkdirSync(path14.dirname(destPath), { recursive: true });
|
|
181
639
|
if (opts.mode === "copy") {
|
|
182
|
-
|
|
640
|
+
fs12.cpSync(srcPath, destPath, { recursive: true });
|
|
183
641
|
} else {
|
|
184
|
-
|
|
642
|
+
fs12.symlinkSync(path14.resolve(srcPath), destPath);
|
|
185
643
|
}
|
|
186
644
|
logOk(`Installed ${ref} \u2192 ${destPath} (${opts.mode})`);
|
|
187
645
|
} finally {
|
|
@@ -189,29 +647,7 @@ function makeAssetCommand() {
|
|
|
189
647
|
}
|
|
190
648
|
}
|
|
191
649
|
);
|
|
192
|
-
cmd.
|
|
193
|
-
const { manager, library, close } = await openLibraryManager();
|
|
194
|
-
try {
|
|
195
|
-
let defs = await library.listAssetDefs(opts.kind ? { kind: opts.kind } : void 0);
|
|
196
|
-
if (opts.library) {
|
|
197
|
-
const lib = await manager.requireLibrary(opts.library);
|
|
198
|
-
defs = defs.filter((d) => d.libraryId === lib.id);
|
|
199
|
-
}
|
|
200
|
-
if (opts.json) return console.log(JSON.stringify(defs, null, 2));
|
|
201
|
-
if (defs.length === 0) {
|
|
202
|
-
logInfo("No assets cached. Run `skaile library sync <name>` first.");
|
|
203
|
-
return;
|
|
204
|
-
}
|
|
205
|
-
for (const d of defs) {
|
|
206
|
-
console.log(` ${S.cmd(d.id.padEnd(40))} ${d.kind.padEnd(10)} ${d.description ?? ""}`);
|
|
207
|
-
}
|
|
208
|
-
console.log(`
|
|
209
|
-
${S.dim(`${defs.length} asset(s)`)}
|
|
210
|
-
`);
|
|
211
|
-
} finally {
|
|
212
|
-
close();
|
|
213
|
-
}
|
|
214
|
-
});
|
|
650
|
+
cmd.addCommand(makeListCommand());
|
|
215
651
|
cmd.command("show <ref>").description("Show details for an asset by canonical ref").action(async (ref) => {
|
|
216
652
|
const { library, close } = await openLibraryManager();
|
|
217
653
|
try {
|
|
@@ -237,354 +673,136 @@ function makeAuthCommand() {
|
|
|
237
673
|
const health = await provider.testConnection();
|
|
238
674
|
if (health.ok) {
|
|
239
675
|
logOk(`Local provider: healthy (${health.latencyMs}ms)`);
|
|
240
|
-
} else {
|
|
241
|
-
logErr(`Local provider: ${health.error ?? "unhealthy"}`);
|
|
242
|
-
}
|
|
243
|
-
});
|
|
244
|
-
cmd.command("set-key-strategy").description("Set the master key strategy (keychain, passphrase, or machine)").argument("<strategy>", `One of: ${VALID_STRATEGIES.join(", ")}`).option(
|
|
245
|
-
"--passphrase <value>",
|
|
246
|
-
"Passphrase value (required for passphrase strategy; alternative to SKAILE_SECRETS_PASSPHRASE env var)"
|
|
247
|
-
).action(async (strategy, opts) => {
|
|
248
|
-
if (!VALID_STRATEGIES.includes(strategy)) {
|
|
249
|
-
logErr(`Invalid strategy "${strategy}". Must be one of: ${VALID_STRATEGIES.join(", ")}`);
|
|
250
|
-
process.exit(1);
|
|
251
|
-
}
|
|
252
|
-
if (strategy === "passphrase" && !opts.passphrase && !process.env.SKAILE_SECRETS_PASSPHRASE) {
|
|
253
|
-
logErr(
|
|
254
|
-
"Passphrase required. Provide via --passphrase or set SKAILE_SECRETS_PASSPHRASE:\n export SKAILE_SECRETS_PASSPHRASE='...'\n skaile auth set-key-strategy passphrase"
|
|
255
|
-
);
|
|
256
|
-
process.exit(1);
|
|
257
|
-
}
|
|
258
|
-
const provider = new LocalSecretsProvider();
|
|
259
|
-
try {
|
|
260
|
-
await provider.setKeyStrategy(strategy, opts.passphrase);
|
|
261
|
-
logOk(`Key strategy set to: ${strategy}`);
|
|
262
|
-
} catch (e) {
|
|
263
|
-
logErr(`Failed to set strategy: ${e instanceof Error ? e.message : String(e)}`);
|
|
264
|
-
process.exit(1);
|
|
265
|
-
}
|
|
266
|
-
});
|
|
267
|
-
return cmd;
|
|
268
|
-
}
|
|
269
|
-
function collectCacheTargets(scope) {
|
|
270
|
-
const out = [];
|
|
271
|
-
out.push(path13__default.join(scope.projectDir, ".skaile", "cache"));
|
|
272
|
-
out.push(path13__default.join(scope.projectDir, ".skaile", "store-cache"));
|
|
273
|
-
out.push(path13__default.join(scope.projectDir, ".skaile", "repos"));
|
|
274
|
-
if (scope.global) {
|
|
275
|
-
out.push(globalCacheRoot());
|
|
276
|
-
const home = process.env.SKAILE_HOME ?? path13__default.join(homedir(), ".skaile");
|
|
277
|
-
out.push(path13__default.join(home, "repos"));
|
|
278
|
-
out.push(path13__default.join(home, "catalog-cache"));
|
|
279
|
-
}
|
|
280
|
-
return out;
|
|
281
|
-
}
|
|
282
|
-
function dirSize(target) {
|
|
283
|
-
if (!existsSync(target)) return 0;
|
|
284
|
-
const st = lstatSync(target);
|
|
285
|
-
if (st.isSymbolicLink()) return 0;
|
|
286
|
-
if (!st.isDirectory()) return st.size;
|
|
287
|
-
return dirSizeOfDir(target);
|
|
288
|
-
}
|
|
289
|
-
function dirSizeOfDir(dir) {
|
|
290
|
-
let total = 0;
|
|
291
|
-
for (const ent of readdirSync(dir, { withFileTypes: true })) {
|
|
292
|
-
const child = path13__default.join(dir, ent.name);
|
|
293
|
-
if (ent.isSymbolicLink()) continue;
|
|
294
|
-
if (ent.isDirectory()) total += dirSizeOfDir(child);
|
|
295
|
-
else if (ent.isFile()) total += statSync(child).size;
|
|
296
|
-
}
|
|
297
|
-
return total;
|
|
298
|
-
}
|
|
299
|
-
function removeCacheTargets(targets, opts) {
|
|
300
|
-
const present = targets.filter((t) => existsSync(t));
|
|
301
|
-
for (const t of present) rmSync(t, { recursive: true, force: true });
|
|
302
|
-
return present;
|
|
303
|
-
}
|
|
304
|
-
function fmtBytes(n) {
|
|
305
|
-
const u = ["B", "KB", "MB", "GB"];
|
|
306
|
-
let i = 0;
|
|
307
|
-
let v = n;
|
|
308
|
-
while (v >= 1024 && i < u.length - 1) {
|
|
309
|
-
v /= 1024;
|
|
310
|
-
i++;
|
|
311
|
-
}
|
|
312
|
-
return `${v.toFixed(i === 0 ? 0 : 1)} ${u[i]}`;
|
|
313
|
-
}
|
|
314
|
-
function makeCacheCommand() {
|
|
315
|
-
const cmd = new Command("cache").description("Inspect and reclaim the re-derivable cache");
|
|
316
|
-
cmd.command("clean").description("Remove the project cache (.skaile/cache); --global also clears ~/.skaile/cache").option("--global", "Also clear the global cache (sources + catalog) and legacy dirs").option("--dry-run", "Show what would be removed without doing it").option("-y, --yes", "Skip confirmation prompt").option("--project-dir <path>", "Project directory", process.cwd()).action(async (opts) => {
|
|
317
|
-
const targets = collectCacheTargets({
|
|
318
|
-
projectDir: path13__default.resolve(opts.projectDir),
|
|
319
|
-
global: opts.global
|
|
320
|
-
}).filter((t) => existsSync(t));
|
|
321
|
-
if (targets.length === 0) {
|
|
322
|
-
logInfo("Cache is already empty.");
|
|
323
|
-
return;
|
|
324
|
-
}
|
|
325
|
-
console.log();
|
|
326
|
-
console.log(` ${S.heading("Will remove:")}`);
|
|
327
|
-
for (const t of targets)
|
|
328
|
-
console.log(` ${S.dim(t)} ${S.dim(`(${fmtBytes(dirSize(t))})`)}`);
|
|
329
|
-
if (opts.dryRun) {
|
|
330
|
-
console.log();
|
|
331
|
-
logInfo("Dry run \u2014 no changes made.");
|
|
332
|
-
return;
|
|
333
|
-
}
|
|
334
|
-
if (!opts.yes) {
|
|
335
|
-
const ok = await p6.confirm({
|
|
336
|
-
message: opts.global ? "Clear project AND global cache?" : "Clear project cache?"
|
|
337
|
-
});
|
|
338
|
-
if (p6.isCancel(ok) || !ok) {
|
|
339
|
-
logInfo("Cancelled.");
|
|
340
|
-
return;
|
|
341
|
-
}
|
|
342
|
-
}
|
|
343
|
-
const removed = removeCacheTargets(targets);
|
|
344
|
-
console.log();
|
|
345
|
-
for (const r of removed) logOk(`Removed ${r}`);
|
|
346
|
-
});
|
|
347
|
-
cmd.command("dir").description("Print the resolved cache roots").option("--global", "Include the global cache root").option("--project-dir <path>", "Project directory", process.cwd()).action((opts) => {
|
|
348
|
-
console.log(path13__default.join(path13__default.resolve(opts.projectDir), ".skaile", "cache"));
|
|
349
|
-
if (opts.global) console.log(globalCacheRoot());
|
|
350
|
-
});
|
|
351
|
-
cmd.command("size").description("Show cache disk usage per directory").option("--global", "Include the global cache").option("--project-dir <path>", "Project directory", process.cwd()).action((opts) => {
|
|
352
|
-
const targets = collectCacheTargets({
|
|
353
|
-
projectDir: path13__default.resolve(opts.projectDir),
|
|
354
|
-
global: opts.global
|
|
355
|
-
});
|
|
356
|
-
console.log();
|
|
357
|
-
for (const t of targets) {
|
|
358
|
-
if (!existsSync(t)) continue;
|
|
359
|
-
console.log(` ${S.dim(fmtBytes(dirSize(t)).padStart(9))} ${t}`);
|
|
360
|
-
}
|
|
361
|
-
console.log();
|
|
362
|
-
});
|
|
363
|
-
return cmd;
|
|
364
|
-
}
|
|
365
|
-
async function runSearch(kind, query, opts) {
|
|
366
|
-
if (kind?.includes(":")) {
|
|
367
|
-
query = kind;
|
|
368
|
-
kind = void 0;
|
|
369
|
-
}
|
|
370
|
-
const showLocal = !opts.store;
|
|
371
|
-
const showStore = !opts.local;
|
|
372
|
-
if (showLocal) {
|
|
373
|
-
searchLocal(query, kind, opts, showStore);
|
|
374
|
-
}
|
|
375
|
-
if (showStore) {
|
|
376
|
-
await searchStore(query, kind, opts);
|
|
377
|
-
}
|
|
378
|
-
}
|
|
379
|
-
function searchLocal(query, kind, opts, showStore) {
|
|
380
|
-
const am2 = new AssetManager({ projectDir: path13__default.resolve(opts.projectDir) });
|
|
381
|
-
const entries = am2.search(query, kind);
|
|
382
|
-
if (entries.length === 0) {
|
|
383
|
-
if (!showStore) {
|
|
384
|
-
logInfo(
|
|
385
|
-
query ? `No entries matching "${query}".` : "No assets found. Run `skaile source sync` first."
|
|
386
|
-
);
|
|
387
|
-
}
|
|
388
|
-
return;
|
|
389
|
-
}
|
|
390
|
-
if (showStore) {
|
|
391
|
-
console.log(`
|
|
392
|
-
${S.heading("Local:")}`);
|
|
393
|
-
}
|
|
394
|
-
printLocalEntries(entries);
|
|
395
|
-
}
|
|
396
|
-
function printLocalEntries(entries) {
|
|
397
|
-
const byKind = /* @__PURE__ */ new Map();
|
|
398
|
-
for (const e of entries) {
|
|
399
|
-
if (!byKind.has(e.kind)) byKind.set(e.kind, []);
|
|
400
|
-
byKind.get(e.kind).push(e);
|
|
401
|
-
}
|
|
402
|
-
for (const [k, items] of byKind) {
|
|
403
|
-
const nameW = Math.max(4, ...items.map((e) => e.name.length));
|
|
404
|
-
console.log();
|
|
405
|
-
console.log(
|
|
406
|
-
` ${kindColor(k)} ${S.heading(`${k.toUpperCase()}S`)} ${S.dim(`(${items.length})`)}`
|
|
407
|
-
);
|
|
408
|
-
console.log(` ${S.rule(nameW + 62)}`);
|
|
409
|
-
for (const e of items) {
|
|
410
|
-
const ver = e.version ? S.dim(` v${e.version}`) : "";
|
|
411
|
-
console.log(` ${S.cmd(e.name.padEnd(nameW))} ${e.description.slice(0, 60)}${ver}`);
|
|
412
|
-
}
|
|
413
|
-
}
|
|
414
|
-
console.log(`
|
|
415
|
-
${S.dim(`${entries.length} total`)}
|
|
416
|
-
`);
|
|
417
|
-
}
|
|
418
|
-
async function searchStore(query, kind, opts) {
|
|
419
|
-
try {
|
|
420
|
-
const { getStoreConfig: getStoreConfig2, storeFetch: storeFetch2 } = await import('../store-client-XFZFKY3W.js');
|
|
421
|
-
const config = getStoreConfig2();
|
|
422
|
-
const params = {};
|
|
423
|
-
if (query) params.q = query;
|
|
424
|
-
if (kind) params.kind = kind;
|
|
425
|
-
const storeRes = await storeFetch2(config, "/api/assets", { params });
|
|
426
|
-
if (storeRes.results.length > 0) {
|
|
427
|
-
console.log(`
|
|
428
|
-
${S.heading("Store:")}`);
|
|
429
|
-
for (const asset of storeRes.results) {
|
|
430
|
-
const ref = `${asset.kind}:@${asset.publisher}/${asset.slug}`;
|
|
431
|
-
console.log(
|
|
432
|
-
` \u2B21 ${kindColorPad(asset.kind)} ${colorRef(ref).padEnd(40)} ${S.dim(asset.description?.slice(0, 50) || "")} ${S.dim(`\u2193${asset.downloads}`)}`
|
|
433
|
-
);
|
|
434
|
-
}
|
|
435
|
-
} else if (opts.store) {
|
|
436
|
-
logInfo("No results in store");
|
|
437
|
-
}
|
|
438
|
-
} catch (e) {
|
|
439
|
-
if (opts.store) {
|
|
440
|
-
logErr(`Store search failed: ${e.message}`);
|
|
676
|
+
} else {
|
|
677
|
+
logErr(`Local provider: ${health.error ?? "unhealthy"}`);
|
|
441
678
|
}
|
|
442
|
-
}
|
|
443
|
-
}
|
|
444
|
-
function makeSearchCommand() {
|
|
445
|
-
return new Command("search").description("Search across all repos").argument("[kind]", "Filter by asset kind").argument("[query]", "Search query").option("--project-dir <path>", "Project directory", process.cwd()).option("--store", "Search only the store").option("--local", "Search only local repos").action(async (kind, query, opts) => {
|
|
446
|
-
await runSearch(kind, query, opts);
|
|
447
679
|
});
|
|
448
|
-
}
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
}
|
|
456
|
-
|
|
457
|
-
|
|
680
|
+
cmd.command("set-key-strategy").description("Set the master key strategy (keychain, passphrase, or machine)").argument("<strategy>", `One of: ${VALID_STRATEGIES.join(", ")}`).option(
|
|
681
|
+
"--passphrase <value>",
|
|
682
|
+
"Passphrase value (required for passphrase strategy; alternative to SKAILE_SECRETS_PASSPHRASE env var)"
|
|
683
|
+
).action(async (strategy, opts) => {
|
|
684
|
+
if (!VALID_STRATEGIES.includes(strategy)) {
|
|
685
|
+
logErr(`Invalid strategy "${strategy}". Must be one of: ${VALID_STRATEGIES.join(", ")}`);
|
|
686
|
+
process.exit(1);
|
|
687
|
+
}
|
|
688
|
+
if (strategy === "passphrase" && !opts.passphrase && !process.env.SKAILE_SECRETS_PASSPHRASE) {
|
|
689
|
+
logErr(
|
|
690
|
+
"Passphrase required. Provide via --passphrase or set SKAILE_SECRETS_PASSPHRASE:\n export SKAILE_SECRETS_PASSPHRASE='...'\n skaile auth set-key-strategy passphrase"
|
|
691
|
+
);
|
|
692
|
+
process.exit(1);
|
|
693
|
+
}
|
|
694
|
+
const provider = new LocalSecretsProvider();
|
|
458
695
|
try {
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
if (NON_DEPLOYABLE_KINDS.has(kind))
|
|
464
|
-
logInfo(
|
|
465
|
-
`Recorded in skaile.yaml. ${kind} assets are not deployed into the driver target \u2014 they are wired when skaile runs the agent.`
|
|
466
|
-
);
|
|
467
|
-
else logInfo("Nothing to deploy (already up to date).");
|
|
468
|
-
} else for (const a of added) logOk(a);
|
|
469
|
-
} catch (err) {
|
|
470
|
-
spinner5.stop("Failed");
|
|
471
|
-
logErr(String(err));
|
|
696
|
+
await provider.setKeyStrategy(strategy, opts.passphrase);
|
|
697
|
+
logOk(`Key strategy set to: ${strategy}`);
|
|
698
|
+
} catch (e) {
|
|
699
|
+
logErr(`Failed to set strategy: ${e instanceof Error ? e.message : String(e)}`);
|
|
472
700
|
process.exit(1);
|
|
473
701
|
}
|
|
474
702
|
});
|
|
703
|
+
return cmd;
|
|
475
704
|
}
|
|
476
|
-
function
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
const
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
}
|
|
705
|
+
function collectCacheTargets(scope) {
|
|
706
|
+
const out = [];
|
|
707
|
+
out.push(path14__default.join(scope.projectDir, ".skaile", "cache"));
|
|
708
|
+
out.push(path14__default.join(scope.projectDir, ".skaile", "store-cache"));
|
|
709
|
+
out.push(path14__default.join(scope.projectDir, ".skaile", "repos"));
|
|
710
|
+
if (scope.global) {
|
|
711
|
+
out.push(globalCacheRoot());
|
|
712
|
+
const home = process.env.SKAILE_HOME ?? path14__default.join(homedir(), ".skaile");
|
|
713
|
+
out.push(path14__default.join(home, "repos"));
|
|
714
|
+
out.push(path14__default.join(home, "catalog-cache"));
|
|
715
|
+
}
|
|
716
|
+
return out;
|
|
487
717
|
}
|
|
488
|
-
function
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
global: opts.global,
|
|
495
|
-
driverTarget: opts.target
|
|
496
|
-
});
|
|
497
|
-
const deployed = am2.listDeployed(kind);
|
|
498
|
-
if (deployed.length === 0) {
|
|
499
|
-
logInfo("Nothing deployed.");
|
|
500
|
-
return;
|
|
501
|
-
}
|
|
502
|
-
const kindW = Math.max(5, ...deployed.map((e) => e.kind.length));
|
|
503
|
-
const nameW = Math.max(4, ...deployed.map((e) => e.name.length));
|
|
504
|
-
console.log();
|
|
505
|
-
console.log(` ${S.dim("KIND".padEnd(kindW))} ${S.dim("NAME".padEnd(nameW))}`);
|
|
506
|
-
console.log(` ${S.rule(kindW + nameW + 4)}`);
|
|
507
|
-
for (const e of deployed) {
|
|
508
|
-
console.log(` ${kindColorPad(e.kind, kindW)} ${e.name.padEnd(nameW)}`);
|
|
509
|
-
}
|
|
510
|
-
console.log(`
|
|
511
|
-
${S.dim(`${deployed.length} deployed`)}
|
|
512
|
-
`);
|
|
513
|
-
});
|
|
718
|
+
function dirSize(target) {
|
|
719
|
+
if (!existsSync(target)) return 0;
|
|
720
|
+
const st = lstatSync(target);
|
|
721
|
+
if (st.isSymbolicLink()) return 0;
|
|
722
|
+
if (!st.isDirectory()) return st.size;
|
|
723
|
+
return dirSizeOfDir(target);
|
|
514
724
|
}
|
|
515
|
-
function
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
const
|
|
519
|
-
if (
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
725
|
+
function dirSizeOfDir(dir) {
|
|
726
|
+
let total = 0;
|
|
727
|
+
for (const ent of readdirSync(dir, { withFileTypes: true })) {
|
|
728
|
+
const child = path14__default.join(dir, ent.name);
|
|
729
|
+
if (ent.isSymbolicLink()) continue;
|
|
730
|
+
if (ent.isDirectory()) total += dirSizeOfDir(child);
|
|
731
|
+
else if (ent.isFile()) total += statSync(child).size;
|
|
732
|
+
}
|
|
733
|
+
return total;
|
|
734
|
+
}
|
|
735
|
+
function removeCacheTargets(targets, opts) {
|
|
736
|
+
const present = targets.filter((t) => existsSync(t));
|
|
737
|
+
for (const t of present) rmSync(t, { recursive: true, force: true });
|
|
738
|
+
return present;
|
|
739
|
+
}
|
|
740
|
+
function fmtBytes(n) {
|
|
741
|
+
const u = ["B", "KB", "MB", "GB"];
|
|
742
|
+
let i = 0;
|
|
743
|
+
let v = n;
|
|
744
|
+
while (v >= 1024 && i < u.length - 1) {
|
|
745
|
+
v /= 1024;
|
|
746
|
+
i++;
|
|
747
|
+
}
|
|
748
|
+
return `${v.toFixed(i === 0 ? 0 : 1)} ${u[i]}`;
|
|
749
|
+
}
|
|
750
|
+
function makeCacheCommand() {
|
|
751
|
+
const cmd = new Command("cache").description("Inspect and reclaim the re-derivable cache");
|
|
752
|
+
cmd.command("clean").description("Remove the project cache (.skaile/cache); --global also clears ~/.skaile/cache").option("--global", "Also clear the global cache (sources + catalog) and legacy dirs").option("--dry-run", "Show what would be removed without doing it").option("-y, --yes", "Skip confirmation prompt").option("--project-dir <path>", "Project directory", process.cwd()).action(async (opts) => {
|
|
753
|
+
const targets = collectCacheTargets({
|
|
754
|
+
projectDir: path14__default.resolve(opts.projectDir),
|
|
755
|
+
global: opts.global
|
|
756
|
+
}).filter((t) => existsSync(t));
|
|
757
|
+
if (targets.length === 0) {
|
|
758
|
+
logInfo("Cache is already empty.");
|
|
759
|
+
return;
|
|
524
760
|
}
|
|
525
761
|
console.log();
|
|
526
|
-
console.log(` ${S.heading(
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
if (
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
if (entry.requires.length) {
|
|
534
|
-
console.log(` requires:`);
|
|
535
|
-
for (const d of entry.requires)
|
|
536
|
-
console.log(` ${S.dim("\xB7")} ${kindColor(d.kind)}:${d.name}`);
|
|
762
|
+
console.log(` ${S.heading("Will remove:")}`);
|
|
763
|
+
for (const t of targets)
|
|
764
|
+
console.log(` ${S.dim(t)} ${S.dim(`(${fmtBytes(dirSize(t))})`)}`);
|
|
765
|
+
if (opts.dryRun) {
|
|
766
|
+
console.log();
|
|
767
|
+
logInfo("Dry run \u2014 no changes made.");
|
|
768
|
+
return;
|
|
537
769
|
}
|
|
538
|
-
if (
|
|
539
|
-
|
|
540
|
-
|
|
770
|
+
if (!opts.yes) {
|
|
771
|
+
const ok = await p6.confirm({
|
|
772
|
+
message: opts.global ? "Clear project AND global cache?" : "Clear project cache?"
|
|
773
|
+
});
|
|
774
|
+
if (p6.isCancel(ok) || !ok) {
|
|
775
|
+
logInfo("Cancelled.");
|
|
776
|
+
return;
|
|
777
|
+
}
|
|
541
778
|
}
|
|
779
|
+
const removed = removeCacheTargets(targets);
|
|
542
780
|
console.log();
|
|
781
|
+
for (const r of removed) logOk(`Removed ${r}`);
|
|
543
782
|
});
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
new Option("-k, --kind <kind>", "Asset kind").default("skill").choices([...ASSET_KINDS])
|
|
548
|
-
).option("-d, --dir <dir>", "Target directory (default: cwd)").action((name, opts) => {
|
|
549
|
-
const am2 = new AssetManager({ projectDir: process.cwd() });
|
|
550
|
-
const destDir = opts.dir ? path13__default.resolve(opts.dir) : process.cwd();
|
|
551
|
-
const result = am2.create(name, opts.kind, destDir);
|
|
552
|
-
if (result.ok) logOk(`Created ${kindColor(opts.kind)}: ${pc5.dim(result.path)}`);
|
|
553
|
-
else {
|
|
554
|
-
logErr(result.path);
|
|
555
|
-
process.exit(1);
|
|
556
|
-
}
|
|
783
|
+
cmd.command("dir").description("Print the resolved cache roots").option("--global", "Include the global cache root").option("--project-dir <path>", "Project directory", process.cwd()).action((opts) => {
|
|
784
|
+
console.log(path14__default.join(path14__default.resolve(opts.projectDir), ".skaile", "cache"));
|
|
785
|
+
if (opts.global) console.log(globalCacheRoot());
|
|
557
786
|
});
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
if (issues.length === 0) {
|
|
564
|
-
logOk("No missing dependencies.");
|
|
565
|
-
return;
|
|
566
|
-
}
|
|
567
|
-
const assetW = Math.max(5, ...issues.map((i) => `${i.assetKind}:${i.assetName}`.length));
|
|
568
|
-
const depW = Math.max(11, ...issues.map((i) => `${i.depKind}:${i.depName}`.length));
|
|
787
|
+
cmd.command("size").description("Show cache disk usage per directory").option("--global", "Include the global cache").option("--project-dir <path>", "Project directory", process.cwd()).action((opts) => {
|
|
788
|
+
const targets = collectCacheTargets({
|
|
789
|
+
projectDir: path14__default.resolve(opts.projectDir),
|
|
790
|
+
global: opts.global
|
|
791
|
+
});
|
|
569
792
|
console.log();
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
console.log(` ${S.rule(assetW + depW + 15)}`);
|
|
574
|
-
for (const i of issues) {
|
|
575
|
-
const asset = `${i.assetKind}:${i.assetName}`;
|
|
576
|
-
const dep = `${i.depKind}:${i.depName}`;
|
|
577
|
-
const status4 = i.inRepos ? S.warn("fixable") : S.err("not found");
|
|
578
|
-
console.log(` ${asset.padEnd(assetW)} ${dep.padEnd(depW)} ${status4}`);
|
|
793
|
+
for (const t of targets) {
|
|
794
|
+
if (!existsSync(t)) continue;
|
|
795
|
+
console.log(` ${S.dim(fmtBytes(dirSize(t)).padStart(9))} ${t}`);
|
|
579
796
|
}
|
|
580
797
|
console.log();
|
|
581
798
|
});
|
|
799
|
+
return cmd;
|
|
582
800
|
}
|
|
583
801
|
function makeCatalogCommand() {
|
|
584
802
|
const catalog = new Command("catalog").description("Catalog source health and configuration");
|
|
585
803
|
catalog.command("test").description("Probe the configured catalog source and report status").option("--project-dir <path>", "Project directory (for project-level config overlay)").option("--url <url>", "Override the catalog URL for this probe").option("--force", "Probe the network even in air-gapped mode (cache_ttl: 0)").action(async (opts) => {
|
|
586
804
|
const { resolveConfig, isLocalCatalogUrl, trpcGetUrl } = await import('../library/index.js');
|
|
587
|
-
const projectDir = opts.projectDir ?
|
|
805
|
+
const projectDir = opts.projectDir ? path14__default.resolve(opts.projectDir) : void 0;
|
|
588
806
|
const cfg = resolveConfig({ projectDir });
|
|
589
807
|
const baseUrl = opts.url ?? cfg.catalog.url;
|
|
590
808
|
if (isLocalCatalogUrl(baseUrl)) {
|
|
@@ -602,7 +820,7 @@ function makeCatalogCommand() {
|
|
|
602
820
|
});
|
|
603
821
|
catalog.command("info").description("Print the resolved catalog configuration (url, framing, cacheTtlMs)").option("--project-dir <path>", "Project directory (for project-level config overlay)").action(async (opts) => {
|
|
604
822
|
const { resolveConfig } = await import('../library/index.js');
|
|
605
|
-
const projectDir = opts.projectDir ?
|
|
823
|
+
const projectDir = opts.projectDir ? path14__default.resolve(opts.projectDir) : void 0;
|
|
606
824
|
const cfg = resolveConfig({ projectDir });
|
|
607
825
|
console.log(`url: ${cfg.catalog.url}`);
|
|
608
826
|
console.log(`framing: ${cfg.catalog.framing}`);
|
|
@@ -611,7 +829,7 @@ function makeCatalogCommand() {
|
|
|
611
829
|
return catalog;
|
|
612
830
|
}
|
|
613
831
|
async function runLocalCatalogTest(projectDir) {
|
|
614
|
-
const { resolveCatalogSource } = await import('../open-library-
|
|
832
|
+
const { resolveCatalogSource } = await import('../open-library-COHFCT4N.js');
|
|
615
833
|
let resolved;
|
|
616
834
|
try {
|
|
617
835
|
resolved = await resolveCatalogSource({ projectDir });
|
|
@@ -744,8 +962,8 @@ function findFlowFile(flowId, priorityRoots = []) {
|
|
|
744
962
|
for (const root of [...priorityRoots, ...aiResourceRoots()]) {
|
|
745
963
|
for (const { dir } of assetSearchDirs(root, "flows")) {
|
|
746
964
|
for (const ext of [".flow.yaml", ".flow.json", ".json"]) {
|
|
747
|
-
const candidate =
|
|
748
|
-
if (
|
|
965
|
+
const candidate = path14__default.join(dir, `${flowId}${ext}`);
|
|
966
|
+
if (fs12__default.existsSync(candidate)) return candidate;
|
|
749
967
|
}
|
|
750
968
|
}
|
|
751
969
|
}
|
|
@@ -755,7 +973,7 @@ function findSkills(domain) {
|
|
|
755
973
|
const found = [];
|
|
756
974
|
for (const root of aiResourceRoots()) {
|
|
757
975
|
for (const { dir, domain: dirDomain } of assetSearchDirs(root, "skills")) {
|
|
758
|
-
if (
|
|
976
|
+
if (fs12__default.existsSync(dir)) walkSkills(dir, dirDomain, found);
|
|
759
977
|
}
|
|
760
978
|
}
|
|
761
979
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -768,11 +986,11 @@ function findSkills(domain) {
|
|
|
768
986
|
return deduped;
|
|
769
987
|
}
|
|
770
988
|
function walkSkills(dir, domain, out) {
|
|
771
|
-
for (const entry of
|
|
772
|
-
const full =
|
|
989
|
+
for (const entry of fs12__default.readdirSync(dir, { withFileTypes: true })) {
|
|
990
|
+
const full = path14__default.join(dir, entry.name);
|
|
773
991
|
if (entry.isDirectory()) {
|
|
774
|
-
const skillMd =
|
|
775
|
-
if (
|
|
992
|
+
const skillMd = path14__default.join(full, "SKILL.md");
|
|
993
|
+
if (fs12__default.existsSync(skillMd)) {
|
|
776
994
|
out.push({ name: entry.name, path: full, skillPath: skillMd, domain });
|
|
777
995
|
} else {
|
|
778
996
|
walkSkills(full, domain, out);
|
|
@@ -800,10 +1018,10 @@ function resolveFlowIds() {
|
|
|
800
1018
|
}
|
|
801
1019
|
}
|
|
802
1020
|
function resolveSessionIds(projectDir) {
|
|
803
|
-
const sessionsDir =
|
|
804
|
-
if (!
|
|
1021
|
+
const sessionsDir = path14__default.join(projectDir, ".skaile", "sessions");
|
|
1022
|
+
if (!fs12__default.existsSync(sessionsDir)) return [];
|
|
805
1023
|
try {
|
|
806
|
-
return
|
|
1024
|
+
return fs12__default.readdirSync(sessionsDir).filter((f) => f.endsWith(".json")).map((f) => f.slice(0, -".json".length));
|
|
807
1025
|
} catch {
|
|
808
1026
|
return [];
|
|
809
1027
|
}
|
|
@@ -919,7 +1137,7 @@ function printResolvedPathsSection(config) {
|
|
|
919
1137
|
console.log(` ${S.label("prompts:".padEnd(16))} ${config.promptsDir ?? paths.promptsDir}`);
|
|
920
1138
|
}
|
|
921
1139
|
async function showConfig(opts) {
|
|
922
|
-
const projectDir = opts.projectDir ?
|
|
1140
|
+
const projectDir = opts.projectDir ? path14__default.resolve(opts.projectDir) : process.cwd();
|
|
923
1141
|
const config = await resolveSettings(projectDir);
|
|
924
1142
|
const wsDefaults = collectWorkspaceDefaults(projectDir);
|
|
925
1143
|
printEffectiveSection(config);
|
|
@@ -932,13 +1150,13 @@ function makeConfigCommand() {
|
|
|
932
1150
|
const cmd = new Command("config").description("Manage personal config (.skaile/settings.json)");
|
|
933
1151
|
cmd.command("show").description("Show effective config with sources").option("--project-dir <path>", "Project directory").action((opts) => showConfig(opts));
|
|
934
1152
|
cmd.command("get <key>").description("Get an effective config value").option("--project-dir <path>", "Project directory").action(async (key, opts) => {
|
|
935
|
-
const projectDir = opts.projectDir ?
|
|
1153
|
+
const projectDir = opts.projectDir ? path14__default.resolve(opts.projectDir) : process.cwd();
|
|
936
1154
|
const config = await resolveSettings(projectDir);
|
|
937
1155
|
const value = config[key];
|
|
938
1156
|
console.log(value ?? S.dim("(not set)"));
|
|
939
1157
|
});
|
|
940
1158
|
cmd.command("set <key> <value>").description("Set a personal config value (driver, model, provider, apiKey.<provider>)").option("--project-dir <path>", "Project directory").option("--global", "Write to ~/.skaile/settings.json instead of project-local").action(async (key, value, opts) => {
|
|
941
|
-
const projectDir = opts.projectDir ?
|
|
1159
|
+
const projectDir = opts.projectDir ? path14__default.resolve(opts.projectDir) : process.cwd();
|
|
942
1160
|
const isApiKey = key.startsWith(API_KEY_PREFIX);
|
|
943
1161
|
if (!PERSONAL_KEYS.has(key) && !isApiKey) {
|
|
944
1162
|
logErr(
|
|
@@ -1053,11 +1271,11 @@ function makeConnectCommand() {
|
|
|
1053
1271
|
process.exitCode = 1;
|
|
1054
1272
|
return;
|
|
1055
1273
|
}
|
|
1056
|
-
await new Promise((
|
|
1274
|
+
await new Promise((resolve5) => {
|
|
1057
1275
|
client.onMessage((event) => {
|
|
1058
1276
|
console.log(formatEvent(event));
|
|
1059
1277
|
if (event.type === "finished" || event.type === "debug_result") {
|
|
1060
|
-
|
|
1278
|
+
resolve5();
|
|
1061
1279
|
}
|
|
1062
1280
|
});
|
|
1063
1281
|
client.send(parsed);
|
|
@@ -1101,12 +1319,12 @@ function makeConnectCommand() {
|
|
|
1101
1319
|
client.send(cmd);
|
|
1102
1320
|
rl.prompt();
|
|
1103
1321
|
});
|
|
1104
|
-
await new Promise((
|
|
1105
|
-
rl.on("close",
|
|
1322
|
+
await new Promise((resolve5) => {
|
|
1323
|
+
rl.on("close", resolve5);
|
|
1106
1324
|
client.onDisconnect(() => {
|
|
1107
1325
|
logErr("Server disconnected");
|
|
1108
1326
|
rl.close();
|
|
1109
|
-
|
|
1327
|
+
resolve5();
|
|
1110
1328
|
});
|
|
1111
1329
|
});
|
|
1112
1330
|
await client.disconnect();
|
|
@@ -1188,15 +1406,15 @@ function parseOpArgs(args) {
|
|
|
1188
1406
|
async function promptText(label, defaultVal) {
|
|
1189
1407
|
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
1190
1408
|
const hint = defaultVal ? ` [${defaultVal}]` : "";
|
|
1191
|
-
return new Promise((
|
|
1409
|
+
return new Promise((resolve5) => {
|
|
1192
1410
|
rl.question(` ${label}${hint}: `, (answer) => {
|
|
1193
1411
|
rl.close();
|
|
1194
|
-
|
|
1412
|
+
resolve5(answer.trim() || defaultVal || "");
|
|
1195
1413
|
});
|
|
1196
1414
|
});
|
|
1197
1415
|
}
|
|
1198
1416
|
async function promptSecret(label) {
|
|
1199
|
-
return new Promise((
|
|
1417
|
+
return new Promise((resolve5) => {
|
|
1200
1418
|
process.stdout.write(` ${label} (hidden): `);
|
|
1201
1419
|
const stdin = process.stdin;
|
|
1202
1420
|
stdin.setRawMode?.(true);
|
|
@@ -1209,7 +1427,7 @@ async function promptSecret(label) {
|
|
|
1209
1427
|
stdin.pause();
|
|
1210
1428
|
stdin.removeListener("data", onData);
|
|
1211
1429
|
process.stdout.write("\n");
|
|
1212
|
-
|
|
1430
|
+
resolve5(value);
|
|
1213
1431
|
} else if (char === "") {
|
|
1214
1432
|
process.exit(1);
|
|
1215
1433
|
} else if (char === "\x7F") {
|
|
@@ -1256,8 +1474,8 @@ function makeConnectorCommand() {
|
|
|
1256
1474
|
async (driver, opts) => {
|
|
1257
1475
|
const { installNpmPackages } = await import('../connectors/index.js');
|
|
1258
1476
|
const { scanDirectory, factoryAssetRoots, WorkspaceYamlEditor: WorkspaceYamlEditor2 } = await import('../core/index.js');
|
|
1259
|
-
const projectDir =
|
|
1260
|
-
const yamlPath =
|
|
1477
|
+
const projectDir = path14__default.resolve(opts.projectDir);
|
|
1478
|
+
const yamlPath = path14__default.join(projectDir, "skaile.yaml");
|
|
1261
1479
|
if (!existsSync(yamlPath)) {
|
|
1262
1480
|
logErr("No skaile.yaml found in current directory. Run 'skaile init' first.");
|
|
1263
1481
|
process.exit(1);
|
|
@@ -1317,8 +1535,8 @@ ${installResult.output}`);
|
|
|
1317
1535
|
);
|
|
1318
1536
|
cmd.command("remove <id>").option("--project-dir <path>", "Workspace directory", process.cwd()).description("Remove a connector from skaile.yaml by its instance ID").action(async (id, opts) => {
|
|
1319
1537
|
const { WorkspaceYamlEditor: WorkspaceYamlEditor2 } = await import('../core/index.js');
|
|
1320
|
-
const projectDir =
|
|
1321
|
-
const yamlPath =
|
|
1538
|
+
const projectDir = path14__default.resolve(opts.projectDir);
|
|
1539
|
+
const yamlPath = path14__default.join(projectDir, "skaile.yaml");
|
|
1322
1540
|
if (!existsSync(yamlPath)) {
|
|
1323
1541
|
logErr("No skaile.yaml found in current directory.");
|
|
1324
1542
|
process.exit(1);
|
|
@@ -1335,7 +1553,7 @@ ${installResult.output}`);
|
|
|
1335
1553
|
cmd.command("status [id]").option("--project-dir <path>", "Workspace directory", process.cwd()).description("Connect and report health status for one or all connectors").action(async (id, opts) => {
|
|
1336
1554
|
const res = await import('../connectors/index.js');
|
|
1337
1555
|
res.registerBuiltinConnectors();
|
|
1338
|
-
const projectDir =
|
|
1556
|
+
const projectDir = path14__default.resolve(opts.projectDir);
|
|
1339
1557
|
const declarations = res.loadConnectorDeclarations(projectDir);
|
|
1340
1558
|
if (declarations.length === 0) {
|
|
1341
1559
|
console.log("No connectors configured in skaile.yaml.");
|
|
@@ -1359,7 +1577,7 @@ ${installResult.output}`);
|
|
|
1359
1577
|
await manager.disconnectAll();
|
|
1360
1578
|
});
|
|
1361
1579
|
cmd.command("list").description("List all configured connectors").option("--project-dir <path>", "Workspace directory", process.cwd()).action(async (opts) => {
|
|
1362
|
-
const projectDir =
|
|
1580
|
+
const projectDir = path14__default.resolve(opts.projectDir);
|
|
1363
1581
|
const manager = await connectConnectors(projectDir);
|
|
1364
1582
|
try {
|
|
1365
1583
|
console.log(JSON.stringify(manager.listConnectors(), null, 2));
|
|
@@ -1368,7 +1586,7 @@ ${installResult.output}`);
|
|
|
1368
1586
|
}
|
|
1369
1587
|
});
|
|
1370
1588
|
cmd.command("sync [id]").description("Re-sync a filesystem-face connector or all of them (git pull, S3 refresh, etc.)").option("--all", "Sync all connectors").option("--project-dir <path>", "Workspace directory", process.cwd()).action(async (id, opts) => {
|
|
1371
|
-
const projectDir =
|
|
1589
|
+
const projectDir = path14__default.resolve(opts.projectDir);
|
|
1372
1590
|
const manager = await connectConnectors(projectDir);
|
|
1373
1591
|
try {
|
|
1374
1592
|
if (opts.all) {
|
|
@@ -1392,7 +1610,7 @@ ${installResult.output}`);
|
|
|
1392
1610
|
}
|
|
1393
1611
|
});
|
|
1394
1612
|
cmd.command("ops <id>").description("List available operations for a connector").option("--project-dir <path>", "Workspace directory", process.cwd()).action(async (id, opts) => {
|
|
1395
|
-
const projectDir =
|
|
1613
|
+
const projectDir = path14__default.resolve(opts.projectDir);
|
|
1396
1614
|
const manager = await connectConnectors(projectDir);
|
|
1397
1615
|
try {
|
|
1398
1616
|
if (!manager.has(id)) {
|
|
@@ -1407,7 +1625,7 @@ ${installResult.output}`);
|
|
|
1407
1625
|
}
|
|
1408
1626
|
});
|
|
1409
1627
|
cmd.command("read <id> <resource-path>").description("Read content from a connector").option("--project-dir <path>", "Workspace directory", process.cwd()).action(async (id, resourcePath, opts) => {
|
|
1410
|
-
const projectDir =
|
|
1628
|
+
const projectDir = path14__default.resolve(opts.projectDir);
|
|
1411
1629
|
const manager = await connectConnectors(projectDir);
|
|
1412
1630
|
try {
|
|
1413
1631
|
const content = await manager.read(id, resourcePath);
|
|
@@ -1417,7 +1635,7 @@ ${installResult.output}`);
|
|
|
1417
1635
|
}
|
|
1418
1636
|
});
|
|
1419
1637
|
cmd.command("write <id> <resource-path> <content>").description("Write content to a connector at a path").option("--project-dir <path>", "Workspace directory", process.cwd()).action(async (id, resourcePath, content, opts) => {
|
|
1420
|
-
const projectDir =
|
|
1638
|
+
const projectDir = path14__default.resolve(opts.projectDir);
|
|
1421
1639
|
const manager = await connectConnectors(projectDir);
|
|
1422
1640
|
try {
|
|
1423
1641
|
await manager.write(id, resourcePath, { data: content });
|
|
@@ -1427,7 +1645,7 @@ ${installResult.output}`);
|
|
|
1427
1645
|
}
|
|
1428
1646
|
});
|
|
1429
1647
|
cmd.command("entries <id> [resource-path]").description("List entries in a connector (files, keys, rows, etc)").option("--project-dir <path>", "Workspace directory", process.cwd()).option("--recursive", "Include nested entries").option("--limit <n>", "Maximum entries to return", parsePositiveIntOption).action(async (id, resourcePath, opts) => {
|
|
1430
|
-
const projectDir =
|
|
1648
|
+
const projectDir = path14__default.resolve(opts.projectDir);
|
|
1431
1649
|
const manager = await connectConnectors(projectDir);
|
|
1432
1650
|
try {
|
|
1433
1651
|
const entries = await manager.list(id, resourcePath, {
|
|
@@ -1440,7 +1658,7 @@ ${installResult.output}`);
|
|
|
1440
1658
|
}
|
|
1441
1659
|
});
|
|
1442
1660
|
cmd.command("search <id> <query>").description("Search within a connector for matching content").option("--project-dir <path>", "Workspace directory", process.cwd()).action(async (id, query, opts) => {
|
|
1443
|
-
const projectDir =
|
|
1661
|
+
const projectDir = path14__default.resolve(opts.projectDir);
|
|
1444
1662
|
const manager = await connectConnectors(projectDir);
|
|
1445
1663
|
try {
|
|
1446
1664
|
const results = await manager.search(id, query);
|
|
@@ -1450,7 +1668,7 @@ ${installResult.output}`);
|
|
|
1450
1668
|
}
|
|
1451
1669
|
});
|
|
1452
1670
|
cmd.command("delete <id> <resource-path>").description("Delete an entry from a connector").option("--project-dir <path>", "Workspace directory", process.cwd()).action(async (id, resourcePath, opts) => {
|
|
1453
|
-
const projectDir =
|
|
1671
|
+
const projectDir = path14__default.resolve(opts.projectDir);
|
|
1454
1672
|
const manager = await connectConnectors(projectDir);
|
|
1455
1673
|
try {
|
|
1456
1674
|
const ok = await manager.delete(id, resourcePath);
|
|
@@ -1460,7 +1678,7 @@ ${installResult.output}`);
|
|
|
1460
1678
|
}
|
|
1461
1679
|
});
|
|
1462
1680
|
cmd.command("run <id> <op> [args...]").description("Run a custom adapter operation (e.g. git log, sqlite query)").option("--project-dir <path>", "Workspace directory", process.cwd()).allowUnknownOption().action(async (id, op, args, opts) => {
|
|
1463
|
-
const projectDir =
|
|
1681
|
+
const projectDir = path14__default.resolve(opts.projectDir);
|
|
1464
1682
|
const manager = await connectConnectors(projectDir);
|
|
1465
1683
|
try {
|
|
1466
1684
|
if (!manager.has(id)) {
|
|
@@ -1495,17 +1713,17 @@ async function runDebugQuery(query, parentOpts, args) {
|
|
|
1495
1713
|
process.exitCode = 1;
|
|
1496
1714
|
return;
|
|
1497
1715
|
}
|
|
1498
|
-
await new Promise((
|
|
1716
|
+
await new Promise((resolve5) => {
|
|
1499
1717
|
const timeout = setTimeout(() => {
|
|
1500
1718
|
logErr("Timeout: no debug_result received within 5s");
|
|
1501
1719
|
process.exitCode = 1;
|
|
1502
|
-
|
|
1720
|
+
resolve5();
|
|
1503
1721
|
}, 5e3);
|
|
1504
1722
|
client.onMessage((event) => {
|
|
1505
1723
|
if (event.type !== "debug_result") return;
|
|
1506
1724
|
clearTimeout(timeout);
|
|
1507
1725
|
printDebugResult(query, event.data);
|
|
1508
|
-
|
|
1726
|
+
resolve5();
|
|
1509
1727
|
});
|
|
1510
1728
|
client.send({ type: "debug", query, args });
|
|
1511
1729
|
});
|
|
@@ -1569,7 +1787,7 @@ function envRecord() {
|
|
|
1569
1787
|
async function buildDeployContext(projectDir) {
|
|
1570
1788
|
const { resolveSkWorkspaceConfig: resolveSkWorkspaceConfig2 } = await import('../core/index.js');
|
|
1571
1789
|
const config = resolveSkWorkspaceConfig2(projectDir);
|
|
1572
|
-
const workspaceId = config.name ??
|
|
1790
|
+
const workspaceId = config.name ?? path14__default.basename(projectDir);
|
|
1573
1791
|
let log;
|
|
1574
1792
|
try {
|
|
1575
1793
|
const { createLogger } = await import('../core/logging.js');
|
|
@@ -1601,13 +1819,13 @@ async function ensureTargetsRegistered(projectDir) {
|
|
|
1601
1819
|
const { resolveSkWorkspaceConfig: resolveSkWorkspaceConfig2 } = await import('../core/index.js');
|
|
1602
1820
|
const config = resolveSkWorkspaceConfig2(projectDir);
|
|
1603
1821
|
if (config.plugins && config.plugins.length > 0) {
|
|
1604
|
-
const { ensurePluginsLoaded } = await import('../plugin-store-
|
|
1822
|
+
const { ensurePluginsLoaded } = await import('../plugin-store-UNENLB56.js');
|
|
1605
1823
|
const result = await ensurePluginsLoaded(projectDir, config.plugins, pluginRegistry);
|
|
1606
1824
|
for (const f of result.failed) logWarn(f.error);
|
|
1607
1825
|
}
|
|
1608
1826
|
}
|
|
1609
1827
|
async function runUp(opts) {
|
|
1610
|
-
const projectDir =
|
|
1828
|
+
const projectDir = path14__default.resolve(opts.projectDir);
|
|
1611
1829
|
await ensureTargetsRegistered(projectDir);
|
|
1612
1830
|
const { resolveSkWorkspaceConfig: resolveSkWorkspaceConfig2 } = await import('../core/index.js');
|
|
1613
1831
|
const { resolveDeployTarget, pluginRegistry } = await import('../plugin-registry/index.js');
|
|
@@ -1639,12 +1857,12 @@ async function runUp(opts) {
|
|
|
1639
1857
|
await holdUntilSignal(handle, controller);
|
|
1640
1858
|
}
|
|
1641
1859
|
function holdUntilSignal(handle, controller) {
|
|
1642
|
-
return new Promise((
|
|
1860
|
+
return new Promise((resolve5) => {
|
|
1643
1861
|
const onSig = () => {
|
|
1644
1862
|
process.removeListener("SIGINT", onSig);
|
|
1645
1863
|
controller.abort();
|
|
1646
1864
|
logInfo("Stopping\u2026");
|
|
1647
|
-
handle.stop().then(() => logOk("Stopped.")).catch((e) => logErr(`stop failed: ${e instanceof Error ? e.message : String(e)}`)).finally(() =>
|
|
1865
|
+
handle.stop().then(() => logOk("Stopped.")).catch((e) => logErr(`stop failed: ${e instanceof Error ? e.message : String(e)}`)).finally(() => resolve5());
|
|
1648
1866
|
};
|
|
1649
1867
|
process.on("SIGINT", onSig);
|
|
1650
1868
|
});
|
|
@@ -1675,7 +1893,7 @@ async function restoreFromHandle(projectDir) {
|
|
|
1675
1893
|
return { target, handle, ctx };
|
|
1676
1894
|
}
|
|
1677
1895
|
async function runDown(opts) {
|
|
1678
|
-
const projectDir =
|
|
1896
|
+
const projectDir = path14__default.resolve(opts.projectDir);
|
|
1679
1897
|
const restored = await restoreFromHandle(projectDir);
|
|
1680
1898
|
if (!restored) return;
|
|
1681
1899
|
await restored.handle.stop();
|
|
@@ -1684,7 +1902,7 @@ async function runDown(opts) {
|
|
|
1684
1902
|
logOk(`Stopped ${S.cmd(restored.target.id)} and cleared the handle.`);
|
|
1685
1903
|
}
|
|
1686
1904
|
async function runStatus(opts) {
|
|
1687
|
-
const projectDir =
|
|
1905
|
+
const projectDir = path14__default.resolve(opts.projectDir);
|
|
1688
1906
|
const restored = await restoreFromHandle(projectDir);
|
|
1689
1907
|
if (!restored) return;
|
|
1690
1908
|
const health = await restored.handle.health();
|
|
@@ -1698,7 +1916,7 @@ async function runStatus(opts) {
|
|
|
1698
1916
|
console.log();
|
|
1699
1917
|
}
|
|
1700
1918
|
async function runLogs(opts) {
|
|
1701
|
-
const projectDir =
|
|
1919
|
+
const projectDir = path14__default.resolve(opts.projectDir);
|
|
1702
1920
|
const restored = await restoreFromHandle(projectDir);
|
|
1703
1921
|
if (!restored) return;
|
|
1704
1922
|
if (!restored.handle.logs) {
|
|
@@ -1722,7 +1940,7 @@ function makeDeployCommand() {
|
|
|
1722
1940
|
}
|
|
1723
1941
|
function makeDiffCommand() {
|
|
1724
1942
|
return new Command("diff").description("Show changes between deployed and source versions").argument("<ref>", "Asset reference (kind:name)").option("--project-dir <path>", "Project directory", process.cwd()).action((ref, opts) => {
|
|
1725
|
-
const am2 = new AssetManager({ projectDir:
|
|
1943
|
+
const am2 = new AssetManager({ projectDir: path14__default.resolve(opts.projectDir) });
|
|
1726
1944
|
const result = am2.diff(ref);
|
|
1727
1945
|
if (result === null) {
|
|
1728
1946
|
logInfo("No differences (or asset not found).");
|
|
@@ -1775,7 +1993,7 @@ function makeFlowCommand() {
|
|
|
1775
1993
|
function makeHistoryCommand() {
|
|
1776
1994
|
const cmd = new Command("history").description("Show recent add/remove/update actions");
|
|
1777
1995
|
cmd.argument("[limit]", "Number of entries to show", "20").option("--project-dir <path>", "Project directory", process.cwd()).action((limitStr, opts) => {
|
|
1778
|
-
const am2 = new AssetManager({ projectDir:
|
|
1996
|
+
const am2 = new AssetManager({ projectDir: path14__default.resolve(opts.projectDir) });
|
|
1779
1997
|
const limit = parseInt(limitStr, 10) || 20;
|
|
1780
1998
|
const entries = am2.history(limit);
|
|
1781
1999
|
if (entries.length === 0) {
|
|
@@ -1795,7 +2013,7 @@ function makeHistoryCommand() {
|
|
|
1795
2013
|
console.log();
|
|
1796
2014
|
});
|
|
1797
2015
|
cmd.command("clear").description("Clear action history").option("--project-dir <path>", "Project directory", process.cwd()).action((opts) => {
|
|
1798
|
-
const am2 = new AssetManager({ projectDir:
|
|
2016
|
+
const am2 = new AssetManager({ projectDir: path14__default.resolve(opts.projectDir) });
|
|
1799
2017
|
am2.clearHistory();
|
|
1800
2018
|
logOk("History cleared.");
|
|
1801
2019
|
});
|
|
@@ -1808,12 +2026,12 @@ var MCP_SERVER_ENTRY = {
|
|
|
1808
2026
|
env: {}
|
|
1809
2027
|
};
|
|
1810
2028
|
function pluginDir(projectDir) {
|
|
1811
|
-
return
|
|
2029
|
+
return path14__default.join(projectDir, ".claude", "plugins", "skaile");
|
|
1812
2030
|
}
|
|
1813
2031
|
async function readJsonStrict(p9) {
|
|
1814
2032
|
let raw;
|
|
1815
2033
|
try {
|
|
1816
|
-
raw = await
|
|
2034
|
+
raw = await fs6.readFile(p9, "utf-8");
|
|
1817
2035
|
} catch {
|
|
1818
2036
|
return null;
|
|
1819
2037
|
}
|
|
@@ -1826,32 +2044,32 @@ async function readJsonStrict(p9) {
|
|
|
1826
2044
|
}
|
|
1827
2045
|
}
|
|
1828
2046
|
async function writeJson(p9, value) {
|
|
1829
|
-
await
|
|
1830
|
-
await
|
|
2047
|
+
await fs6.mkdir(path14__default.dirname(p9), { recursive: true });
|
|
2048
|
+
await fs6.writeFile(p9, `${JSON.stringify(value, null, 2)}
|
|
1831
2049
|
`);
|
|
1832
2050
|
}
|
|
1833
2051
|
async function copyDir(src, dest) {
|
|
1834
|
-
await
|
|
1835
|
-
const entries = await
|
|
2052
|
+
await fs6.mkdir(dest, { recursive: true });
|
|
2053
|
+
const entries = await fs6.readdir(src, { withFileTypes: true });
|
|
1836
2054
|
for (const entry of entries) {
|
|
1837
|
-
const srcPath =
|
|
1838
|
-
const destPath =
|
|
2055
|
+
const srcPath = path14__default.join(src, entry.name);
|
|
2056
|
+
const destPath = path14__default.join(dest, entry.name);
|
|
1839
2057
|
if (entry.isDirectory()) await copyDir(srcPath, destPath);
|
|
1840
|
-
else await
|
|
2058
|
+
else await fs6.copyFile(srcPath, destPath);
|
|
1841
2059
|
}
|
|
1842
2060
|
}
|
|
1843
2061
|
async function install(projectDir, opts) {
|
|
1844
2062
|
return opts?.full ? installFullPlugin(projectDir) : installMcp(projectDir);
|
|
1845
2063
|
}
|
|
1846
2064
|
async function installMcp(projectDir) {
|
|
1847
|
-
const mcpPath =
|
|
2065
|
+
const mcpPath = path14__default.join(projectDir, ".claude", "mcp.json");
|
|
1848
2066
|
const existing = await readJsonStrict(mcpPath) ?? {};
|
|
1849
2067
|
const mcpServers = { ...existing.mcpServers ?? {} };
|
|
1850
2068
|
const previous = mcpServers[SKAILE_MCP_NAME];
|
|
1851
2069
|
const matches = previous && JSON.stringify(previous) === JSON.stringify(MCP_SERVER_ENTRY);
|
|
1852
2070
|
let warning;
|
|
1853
2071
|
if (previous && !matches) {
|
|
1854
|
-
warning = `overwrote existing ${SKAILE_MCP_NAME} entry in ${
|
|
2072
|
+
warning = `overwrote existing ${SKAILE_MCP_NAME} entry in ${path14__default.relative(projectDir, mcpPath)}`;
|
|
1855
2073
|
}
|
|
1856
2074
|
mcpServers[SKAILE_MCP_NAME] = MCP_SERVER_ENTRY;
|
|
1857
2075
|
await writeJson(mcpPath, { ...existing, mcpServers });
|
|
@@ -1860,15 +2078,15 @@ async function installMcp(projectDir) {
|
|
|
1860
2078
|
async function installFullPlugin(projectDir) {
|
|
1861
2079
|
const dir = pluginDir(projectDir);
|
|
1862
2080
|
for (const [rel, content] of Object.entries(buildClaudePluginFiles())) {
|
|
1863
|
-
const dest =
|
|
1864
|
-
await
|
|
1865
|
-
await
|
|
2081
|
+
const dest = path14__default.join(dir, rel);
|
|
2082
|
+
await fs6.mkdir(path14__default.dirname(dest), { recursive: true });
|
|
2083
|
+
await fs6.writeFile(dest, content);
|
|
1866
2084
|
}
|
|
1867
|
-
const projectSkillsDir =
|
|
2085
|
+
const projectSkillsDir = path14__default.join(projectDir, ".skaile", "skills");
|
|
1868
2086
|
if (existsSync(projectSkillsDir)) {
|
|
1869
|
-
await copyDir(projectSkillsDir,
|
|
2087
|
+
await copyDir(projectSkillsDir, path14__default.join(dir, "skills"));
|
|
1870
2088
|
}
|
|
1871
|
-
const settingsPath =
|
|
2089
|
+
const settingsPath = path14__default.join(projectDir, ".claude", "settings.json");
|
|
1872
2090
|
const settings = await readJsonStrict(settingsPath) ?? {};
|
|
1873
2091
|
const plugins = settings.plugins ?? [];
|
|
1874
2092
|
if (!plugins.includes(dir)) plugins.push(dir);
|
|
@@ -1876,8 +2094,8 @@ async function installFullPlugin(projectDir) {
|
|
|
1876
2094
|
return { changed: true, method: "plugin" };
|
|
1877
2095
|
}
|
|
1878
2096
|
async function uninstall(projectDir) {
|
|
1879
|
-
const settingsPath =
|
|
1880
|
-
const mcpPath =
|
|
2097
|
+
const settingsPath = path14__default.join(projectDir, ".claude", "settings.json");
|
|
2098
|
+
const mcpPath = path14__default.join(projectDir, ".claude", "mcp.json");
|
|
1881
2099
|
const dir = pluginDir(projectDir);
|
|
1882
2100
|
let changed = false;
|
|
1883
2101
|
const settings = await readJsonStrict(settingsPath);
|
|
@@ -1891,7 +2109,7 @@ async function uninstall(projectDir) {
|
|
|
1891
2109
|
}
|
|
1892
2110
|
}
|
|
1893
2111
|
if (existsSync(dir)) {
|
|
1894
|
-
await
|
|
2112
|
+
await fs6.rm(dir, { recursive: true, force: true });
|
|
1895
2113
|
changed = true;
|
|
1896
2114
|
}
|
|
1897
2115
|
const mcp = await readJsonStrict(mcpPath);
|
|
@@ -1901,7 +2119,7 @@ async function uninstall(projectDir) {
|
|
|
1901
2119
|
const updated = { ...mcp, mcpServers: rest };
|
|
1902
2120
|
if (Object.keys(rest).length === 0) delete updated.mcpServers;
|
|
1903
2121
|
if (Object.keys(updated).length === 0) {
|
|
1904
|
-
await
|
|
2122
|
+
await fs6.unlink(mcpPath);
|
|
1905
2123
|
} else {
|
|
1906
2124
|
await writeJson(mcpPath, updated);
|
|
1907
2125
|
}
|
|
@@ -1911,12 +2129,12 @@ async function uninstall(projectDir) {
|
|
|
1911
2129
|
async function detectInstall(projectDir) {
|
|
1912
2130
|
const dir = pluginDir(projectDir);
|
|
1913
2131
|
const settings = await readJsonStrict(
|
|
1914
|
-
|
|
2132
|
+
path14__default.join(projectDir, ".claude", "settings.json")
|
|
1915
2133
|
);
|
|
1916
|
-
if (existsSync(
|
|
2134
|
+
if (existsSync(path14__default.join(dir, ".claude-plugin", "plugin.json")) && settings?.plugins?.includes(dir)) {
|
|
1917
2135
|
return { method: "plugin", pluginPath: dir };
|
|
1918
2136
|
}
|
|
1919
|
-
const mcp = await readJsonStrict(
|
|
2137
|
+
const mcp = await readJsonStrict(path14__default.join(projectDir, ".claude", "mcp.json"));
|
|
1920
2138
|
if (mcp?.mcpServers && SKAILE_MCP_NAME in mcp.mcpServers) {
|
|
1921
2139
|
return { method: "mcp" };
|
|
1922
2140
|
}
|
|
@@ -1925,7 +2143,7 @@ async function detectInstall(projectDir) {
|
|
|
1925
2143
|
async function enable(projectDir) {
|
|
1926
2144
|
const detected = await detectInstall(projectDir);
|
|
1927
2145
|
if (!detected) throw new Error("plugin not installed for claude-code");
|
|
1928
|
-
const settingsPath =
|
|
2146
|
+
const settingsPath = path14__default.join(projectDir, ".claude", "settings.json");
|
|
1929
2147
|
const settings = await readJsonStrict(settingsPath) ?? {};
|
|
1930
2148
|
if (detected.method === "plugin") {
|
|
1931
2149
|
const disabled2 = settings.disabledPlugins ?? [];
|
|
@@ -1947,7 +2165,7 @@ async function enable(projectDir) {
|
|
|
1947
2165
|
async function disable(projectDir) {
|
|
1948
2166
|
const detected = await detectInstall(projectDir);
|
|
1949
2167
|
if (!detected) throw new Error("plugin not installed for claude-code");
|
|
1950
|
-
const settingsPath =
|
|
2168
|
+
const settingsPath = path14__default.join(projectDir, ".claude", "settings.json");
|
|
1951
2169
|
const settings = await readJsonStrict(settingsPath) ?? {};
|
|
1952
2170
|
if (detected.method === "plugin") {
|
|
1953
2171
|
const list2 = settings.disabledPlugins ?? [];
|
|
@@ -1967,12 +2185,12 @@ async function disable(projectDir) {
|
|
|
1967
2185
|
return { changed: true };
|
|
1968
2186
|
}
|
|
1969
2187
|
async function status(projectDir) {
|
|
1970
|
-
const settingsPath =
|
|
1971
|
-
const mcpPath =
|
|
2188
|
+
const settingsPath = path14__default.join(projectDir, ".claude", "settings.json");
|
|
2189
|
+
const mcpPath = path14__default.join(projectDir, ".claude", "mcp.json");
|
|
1972
2190
|
const dir = pluginDir(projectDir);
|
|
1973
2191
|
const settings = await readJsonStrict(settingsPath);
|
|
1974
2192
|
const mcp = await readJsonStrict(mcpPath);
|
|
1975
|
-
const pluginInstalled = !!(existsSync(
|
|
2193
|
+
const pluginInstalled = !!(existsSync(path14__default.join(dir, ".claude-plugin", "plugin.json")) && settings?.plugins?.includes(dir));
|
|
1976
2194
|
const mcpInstalled = !!(mcp?.mcpServers && SKAILE_MCP_NAME in mcp.mcpServers);
|
|
1977
2195
|
if (!pluginInstalled && !mcpInstalled) {
|
|
1978
2196
|
return {
|
|
@@ -1990,7 +2208,7 @@ async function status(projectDir) {
|
|
|
1990
2208
|
installed: "yes",
|
|
1991
2209
|
enabled: disabled2 ? "no" : "yes",
|
|
1992
2210
|
method: "plugin",
|
|
1993
|
-
location:
|
|
2211
|
+
location: path14__default.relative(projectDir, dir)
|
|
1994
2212
|
};
|
|
1995
2213
|
}
|
|
1996
2214
|
const disabled = settings?.disabledMcpjsonServers?.includes(SKAILE_MCP_NAME) ?? false;
|
|
@@ -1999,7 +2217,7 @@ async function status(projectDir) {
|
|
|
1999
2217
|
installed: "yes",
|
|
2000
2218
|
enabled: disabled ? "no" : "yes",
|
|
2001
2219
|
method: "mcp",
|
|
2002
|
-
location:
|
|
2220
|
+
location: path14__default.relative(projectDir, mcpPath)
|
|
2003
2221
|
};
|
|
2004
2222
|
}
|
|
2005
2223
|
var SKAILE_MCP_NAME2 = "skaile-workspace";
|
|
@@ -2013,7 +2231,7 @@ function buildEntry(projectDir) {
|
|
|
2013
2231
|
async function readConfig(p9) {
|
|
2014
2232
|
let raw;
|
|
2015
2233
|
try {
|
|
2016
|
-
raw = await
|
|
2234
|
+
raw = await fs6.readFile(p9, "utf-8");
|
|
2017
2235
|
} catch {
|
|
2018
2236
|
return null;
|
|
2019
2237
|
}
|
|
@@ -2026,16 +2244,16 @@ async function readConfig(p9) {
|
|
|
2026
2244
|
}
|
|
2027
2245
|
}
|
|
2028
2246
|
async function writeConfig(p9, value) {
|
|
2029
|
-
await
|
|
2247
|
+
await fs6.mkdir(path14__default.dirname(p9), { recursive: true });
|
|
2030
2248
|
const cleaned = {};
|
|
2031
2249
|
for (const [k, v] of Object.entries(value)) {
|
|
2032
2250
|
if (v === void 0) continue;
|
|
2033
2251
|
cleaned[k] = v;
|
|
2034
2252
|
}
|
|
2035
|
-
await
|
|
2253
|
+
await fs6.writeFile(p9, stringify$1(cleaned));
|
|
2036
2254
|
}
|
|
2037
2255
|
function configPath(projectDir) {
|
|
2038
|
-
return
|
|
2256
|
+
return path14__default.join(projectDir, ".codex", "config.toml");
|
|
2039
2257
|
}
|
|
2040
2258
|
async function install2(projectDir) {
|
|
2041
2259
|
const p9 = configPath(projectDir);
|
|
@@ -2046,7 +2264,7 @@ async function install2(projectDir) {
|
|
|
2046
2264
|
const matches = previous && JSON.stringify(previous) === JSON.stringify(next);
|
|
2047
2265
|
let warning;
|
|
2048
2266
|
if (previous && !matches) {
|
|
2049
|
-
warning = `overwrote existing ${SKAILE_MCP_NAME2} entry in ${
|
|
2267
|
+
warning = `overwrote existing ${SKAILE_MCP_NAME2} entry in ${path14__default.relative(projectDir, p9)}`;
|
|
2050
2268
|
}
|
|
2051
2269
|
if (matches) return { changed: false, method: "toml" };
|
|
2052
2270
|
servers[SKAILE_MCP_NAME2] = next;
|
|
@@ -2063,7 +2281,7 @@ async function uninstall2(projectDir) {
|
|
|
2063
2281
|
const updated = { ...cfg, mcp_servers: rest };
|
|
2064
2282
|
if (Object.keys(rest).length === 0) delete updated.mcp_servers;
|
|
2065
2283
|
if (Object.keys(updated).length === 0) {
|
|
2066
|
-
await
|
|
2284
|
+
await fs6.unlink(p9);
|
|
2067
2285
|
} else {
|
|
2068
2286
|
await writeConfig(p9, updated);
|
|
2069
2287
|
}
|
|
@@ -2087,43 +2305,43 @@ async function status2(projectDir) {
|
|
|
2087
2305
|
installed: "yes",
|
|
2088
2306
|
enabled: "n/a",
|
|
2089
2307
|
method: "mcp",
|
|
2090
|
-
location:
|
|
2308
|
+
location: path14__default.relative(projectDir, p9)
|
|
2091
2309
|
};
|
|
2092
2310
|
}
|
|
2093
2311
|
async function install3(projectDir) {
|
|
2094
|
-
const extDir =
|
|
2095
|
-
const extPath =
|
|
2096
|
-
await
|
|
2312
|
+
const extDir = path14__default.join(projectDir, ".omp", "extensions");
|
|
2313
|
+
const extPath = path14__default.join(extDir, "skaile.ts");
|
|
2314
|
+
await fs6.mkdir(extDir, { recursive: true });
|
|
2097
2315
|
const { WorkspacePlugin } = await import('../workspace-plugin/index.js');
|
|
2098
2316
|
const plugin = new WorkspacePlugin({ projectDir });
|
|
2099
2317
|
const nextSrc = await plugin.buildOmpExtensionSource();
|
|
2100
2318
|
let prevSrc = null;
|
|
2101
2319
|
try {
|
|
2102
|
-
prevSrc = await
|
|
2320
|
+
prevSrc = await fs6.readFile(extPath, "utf-8");
|
|
2103
2321
|
} catch {
|
|
2104
2322
|
}
|
|
2105
2323
|
if (prevSrc === nextSrc) return { changed: false, method: "generated" };
|
|
2106
|
-
await
|
|
2324
|
+
await fs6.writeFile(extPath, nextSrc);
|
|
2107
2325
|
return { changed: true, method: "generated" };
|
|
2108
2326
|
}
|
|
2109
2327
|
async function uninstall3(projectDir) {
|
|
2110
|
-
const extPath =
|
|
2328
|
+
const extPath = path14__default.join(projectDir, ".omp", "extensions", "skaile.ts");
|
|
2111
2329
|
try {
|
|
2112
|
-
await
|
|
2330
|
+
await fs6.unlink(extPath);
|
|
2113
2331
|
return { changed: true };
|
|
2114
2332
|
} catch {
|
|
2115
2333
|
return { changed: false };
|
|
2116
2334
|
}
|
|
2117
2335
|
}
|
|
2118
2336
|
async function status3(projectDir) {
|
|
2119
|
-
const extPath =
|
|
2337
|
+
const extPath = path14__default.join(projectDir, ".omp", "extensions", "skaile.ts");
|
|
2120
2338
|
if (existsSync(extPath)) {
|
|
2121
2339
|
return {
|
|
2122
2340
|
backend: "omp",
|
|
2123
2341
|
installed: "yes",
|
|
2124
2342
|
enabled: "n/a",
|
|
2125
2343
|
method: "extension",
|
|
2126
|
-
location:
|
|
2344
|
+
location: path14__default.relative(projectDir, extPath)
|
|
2127
2345
|
};
|
|
2128
2346
|
}
|
|
2129
2347
|
return {
|
|
@@ -2186,7 +2404,7 @@ async function installCodex(projectDir) {
|
|
|
2186
2404
|
console.log(` ${S.dim("\u2192")} Restart Codex CLI to pick up the change.`);
|
|
2187
2405
|
}
|
|
2188
2406
|
async function runInstall(opts) {
|
|
2189
|
-
const projectDir =
|
|
2407
|
+
const projectDir = path14__default.resolve(opts.projectDir);
|
|
2190
2408
|
const targets = resolveDriver(opts.driver);
|
|
2191
2409
|
let exitCode = 0;
|
|
2192
2410
|
if (targets.includes("claude-code")) {
|
|
@@ -2220,7 +2438,7 @@ async function uninstallCodex(projectDir) {
|
|
|
2220
2438
|
else logInfo(`codex: not installed`);
|
|
2221
2439
|
}
|
|
2222
2440
|
async function runUninstall(opts) {
|
|
2223
|
-
const projectDir =
|
|
2441
|
+
const projectDir = path14__default.resolve(opts.projectDir);
|
|
2224
2442
|
const targets = resolveDriver(opts.driver);
|
|
2225
2443
|
let exitCode = 0;
|
|
2226
2444
|
if (targets.includes("claude-code")) {
|
|
@@ -2263,7 +2481,7 @@ async function toggleTarget(t, projectDir, action3) {
|
|
|
2263
2481
|
});
|
|
2264
2482
|
}
|
|
2265
2483
|
async function runToggle(opts, action3) {
|
|
2266
|
-
const projectDir =
|
|
2484
|
+
const projectDir = path14__default.resolve(opts.projectDir);
|
|
2267
2485
|
const requestedAll = opts.driver === "all";
|
|
2268
2486
|
const targets = resolveDriver(opts.driver);
|
|
2269
2487
|
const usageError = checkToggleSupported(targets, requestedAll, action3);
|
|
@@ -2275,7 +2493,7 @@ async function runToggle(opts, action3) {
|
|
|
2275
2493
|
return exitCode;
|
|
2276
2494
|
}
|
|
2277
2495
|
async function runStatus2(opts) {
|
|
2278
|
-
const projectDir =
|
|
2496
|
+
const projectDir = path14__default.resolve(opts.projectDir);
|
|
2279
2497
|
const targets = resolveDriver(opts.driver);
|
|
2280
2498
|
const rows = [];
|
|
2281
2499
|
let exitCode = 0;
|
|
@@ -2346,7 +2564,7 @@ async function runHook(event) {
|
|
|
2346
2564
|
await plugin.shutdown();
|
|
2347
2565
|
return;
|
|
2348
2566
|
}
|
|
2349
|
-
const store = new PluginStore(
|
|
2567
|
+
const store = new PluginStore(path14__default.join(projectDir, ".skaile", "plugin-state.json"));
|
|
2350
2568
|
await store.load();
|
|
2351
2569
|
const status4 = store.get("connector:status");
|
|
2352
2570
|
if (status4 && typeof status4 === "object" && Object.keys(status4).length > 0) {
|
|
@@ -2468,12 +2686,12 @@ function makeLibraryCommand() {
|
|
|
2468
2686
|
cmd.command("init <name>").description("Create a new local library at ~/.skaile/libraries/<name>").option("--git <url>", "Initialize as a git library tracking <url>").option("--owner", "Mark as owner (default for local)").option("--contributor", "Mark as contributor").option("--reader", "Mark as reader").action(
|
|
2469
2687
|
async (name, opts) => {
|
|
2470
2688
|
const libDir = resolveLibraryDir();
|
|
2471
|
-
const libPath =
|
|
2689
|
+
const libPath = path14.join(libDir, name);
|
|
2472
2690
|
const ownership = opts.contributor ? "contributor" : opts.reader ? "reader" : "owner";
|
|
2473
2691
|
const { manager, close } = await openLibraryManager();
|
|
2474
2692
|
try {
|
|
2475
2693
|
if (opts.git) {
|
|
2476
|
-
|
|
2694
|
+
fs12.mkdirSync(libPath, { recursive: true });
|
|
2477
2695
|
await manager.addLibrary({
|
|
2478
2696
|
name,
|
|
2479
2697
|
path: libPath,
|
|
@@ -2482,7 +2700,7 @@ function makeLibraryCommand() {
|
|
|
2482
2700
|
ownership
|
|
2483
2701
|
});
|
|
2484
2702
|
} else {
|
|
2485
|
-
|
|
2703
|
+
fs12.mkdirSync(libPath, { recursive: true });
|
|
2486
2704
|
await manager.addLibrary({
|
|
2487
2705
|
name,
|
|
2488
2706
|
path: libPath,
|
|
@@ -2539,7 +2757,7 @@ function makeLibraryCommand() {
|
|
|
2539
2757
|
target = def;
|
|
2540
2758
|
}
|
|
2541
2759
|
const am2 = new AssetManager({ projectDir: process.cwd() });
|
|
2542
|
-
const destDir = opts.dir ?
|
|
2760
|
+
const destDir = opts.dir ? path14.join(target.path, opts.dir) : target.path;
|
|
2543
2761
|
const res = am2.create(name, opts.kind ?? kind, destDir);
|
|
2544
2762
|
if (res.ok) {
|
|
2545
2763
|
logOk(`Created ${opts.kind ?? kind}: ${pc5.dim(res.path)}`);
|
|
@@ -2552,6 +2770,80 @@ function makeLibraryCommand() {
|
|
|
2552
2770
|
}
|
|
2553
2771
|
}
|
|
2554
2772
|
);
|
|
2773
|
+
const domain = cmd.command("domain").description("Manage domains (publisher namespaces) inside a library");
|
|
2774
|
+
async function resolveTargetLibrary(manager, libraryName) {
|
|
2775
|
+
if (libraryName) return manager.requireLibrary(libraryName);
|
|
2776
|
+
const all = await manager.listLibraries();
|
|
2777
|
+
const def = all.find((l) => l.isDefault);
|
|
2778
|
+
if (def) return def;
|
|
2779
|
+
if (all.length === 1) return all[0];
|
|
2780
|
+
if (all.length === 0) {
|
|
2781
|
+
logErr("No libraries registered. Run `skaile library init <name>` first.");
|
|
2782
|
+
process.exit(1);
|
|
2783
|
+
}
|
|
2784
|
+
logErr("No default library set. Run `skaile library default <name>` or pass --library.");
|
|
2785
|
+
process.exit(1);
|
|
2786
|
+
}
|
|
2787
|
+
domain.command("create <name>").description("Scaffold a domain dir + DOMAIN.md inside a library").option("--library <name>", "Target library (default: the default-marked one)").option("--publisher <p>", "Publisher slug (default: the domain name kebab-cased)").option("--description <text>", "Domain description for DOMAIN.md").action(
|
|
2788
|
+
async (name, opts) => {
|
|
2789
|
+
const { manager, close } = await openLibraryManager();
|
|
2790
|
+
try {
|
|
2791
|
+
const target = await resolveTargetLibrary(manager, opts.library);
|
|
2792
|
+
if (target.ownership === "reader") {
|
|
2793
|
+
logErr(`Library "${target.name}" is read-only (ownership=reader).`);
|
|
2794
|
+
process.exit(1);
|
|
2795
|
+
}
|
|
2796
|
+
const res = ensureDomain(target.path, name, {
|
|
2797
|
+
publisher: opts.publisher,
|
|
2798
|
+
description: opts.description
|
|
2799
|
+
});
|
|
2800
|
+
if (target.structure !== "domain") {
|
|
2801
|
+
await manager.updateLibrary(target.id, { structure: "domain" });
|
|
2802
|
+
}
|
|
2803
|
+
if (res.created) {
|
|
2804
|
+
logOk(`Created domain ${S.cmd(name)} (publisher @${res.publisher}) \u2192 ${res.dir}`);
|
|
2805
|
+
} else {
|
|
2806
|
+
logInfo(`Domain ${S.cmd(name)} already exists at ${res.dir}`);
|
|
2807
|
+
}
|
|
2808
|
+
} finally {
|
|
2809
|
+
close();
|
|
2810
|
+
}
|
|
2811
|
+
}
|
|
2812
|
+
);
|
|
2813
|
+
domain.command("list").description("List domains in a library").option("--library <name>", "Target library (default: the default-marked one)").option("--json", "Output as JSON").action(async (opts) => {
|
|
2814
|
+
const { manager, close } = await openLibraryManager();
|
|
2815
|
+
try {
|
|
2816
|
+
const target = await resolveTargetLibrary(manager, opts.library);
|
|
2817
|
+
const domains = listDomains(target.path);
|
|
2818
|
+
if (opts.json) return console.log(JSON.stringify(domains, null, 2));
|
|
2819
|
+
if (domains.length === 0) {
|
|
2820
|
+
logInfo(
|
|
2821
|
+
`No domains in "${target.name}". Create one: \`skaile library domain create <name>\`.`
|
|
2822
|
+
);
|
|
2823
|
+
return;
|
|
2824
|
+
}
|
|
2825
|
+
for (const d of domains) console.log(` ${S.cmd(d)}`);
|
|
2826
|
+
console.log(`
|
|
2827
|
+
${S.dim(`${domains.length} domain(s) in ${target.name}`)}
|
|
2828
|
+
`);
|
|
2829
|
+
} finally {
|
|
2830
|
+
close();
|
|
2831
|
+
}
|
|
2832
|
+
});
|
|
2833
|
+
domain.command("show <name>").description("Print a domain's DOMAIN.md").option("--library <name>", "Target library (default: the default-marked one)").action(async (name, opts) => {
|
|
2834
|
+
const { manager, close } = await openLibraryManager();
|
|
2835
|
+
try {
|
|
2836
|
+
const target = await resolveTargetLibrary(manager, opts.library);
|
|
2837
|
+
const domainFile = path14.join(target.path, name, "DOMAIN.md");
|
|
2838
|
+
if (!existsSync(domainFile)) {
|
|
2839
|
+
logErr(`Domain "${name}" not found in "${target.name}" (no ${domainFile}).`);
|
|
2840
|
+
process.exit(1);
|
|
2841
|
+
}
|
|
2842
|
+
console.log(fs12.readFileSync(domainFile, "utf8"));
|
|
2843
|
+
} finally {
|
|
2844
|
+
close();
|
|
2845
|
+
}
|
|
2846
|
+
});
|
|
2555
2847
|
cmd.command("default <name>").description("Set <name> as the default library").action(async (name) => {
|
|
2556
2848
|
const { manager, close } = await openLibraryManager();
|
|
2557
2849
|
try {
|
|
@@ -2565,13 +2857,13 @@ function makeLibraryCommand() {
|
|
|
2565
2857
|
const { manager, close } = await openLibraryManager();
|
|
2566
2858
|
try {
|
|
2567
2859
|
const lib = await manager.requireLibrary(oldName);
|
|
2568
|
-
const parent =
|
|
2569
|
-
const newPath =
|
|
2570
|
-
if (
|
|
2860
|
+
const parent = path14.dirname(lib.path);
|
|
2861
|
+
const newPath = path14.join(parent, newName);
|
|
2862
|
+
if (fs12.existsSync(newPath)) {
|
|
2571
2863
|
logErr(`Target directory already exists: ${newPath}`);
|
|
2572
2864
|
process.exit(1);
|
|
2573
2865
|
}
|
|
2574
|
-
|
|
2866
|
+
fs12.renameSync(lib.path, newPath);
|
|
2575
2867
|
await manager.updateLibrary(lib.id, { name: newName, path: newPath });
|
|
2576
2868
|
logOk(`Renamed ${oldName} \u2192 ${newName}`);
|
|
2577
2869
|
} finally {
|
|
@@ -2755,9 +3047,9 @@ async function printOverallStatus(projectDir, asJson) {
|
|
|
2755
3047
|
} catch {
|
|
2756
3048
|
secretsStrategy = "unavailable";
|
|
2757
3049
|
}
|
|
2758
|
-
const resolvedProjectDir =
|
|
2759
|
-
const hasWorkspaceConfig = existsSync(
|
|
2760
|
-
const hasLockFile = existsSync(
|
|
3050
|
+
const resolvedProjectDir = path14.resolve(projectDir);
|
|
3051
|
+
const hasWorkspaceConfig = existsSync(path14.join(resolvedProjectDir, "skaile.yaml"));
|
|
3052
|
+
const hasLockFile = existsSync(path14.join(resolvedProjectDir, "skaile.lock.yaml"));
|
|
2761
3053
|
let assignments = [];
|
|
2762
3054
|
if (hasWorkspaceConfig) {
|
|
2763
3055
|
try {
|
|
@@ -3113,7 +3405,7 @@ function actOnHeader(row, action3) {
|
|
|
3113
3405
|
return row.type === "domain-header" || row.type === "domain-info";
|
|
3114
3406
|
}
|
|
3115
3407
|
async function loadAssets() {
|
|
3116
|
-
const { gatherAssetFeeds } = await import('../asset-feeds-
|
|
3408
|
+
const { gatherAssetFeeds } = await import('../asset-feeds-DLRQWELS.js');
|
|
3117
3409
|
const { entries, domains, notes } = await gatherAssetFeeds(am, am.projectDir);
|
|
3118
3410
|
if (notes.length > 0) {
|
|
3119
3411
|
state.message = notes.map((n) => `[${n.feed}] ${n.message}`).join(" \u2022 ");
|
|
@@ -3211,14 +3503,14 @@ function reconcileCollapsedSets(rows) {
|
|
|
3211
3503
|
async function loadSourcesAndLibraries() {
|
|
3212
3504
|
try {
|
|
3213
3505
|
const [{ openLibraryManager: openLibraryManager2 }, { skaileHomeDir }, { getGlobalCacheDir: getGlobalCacheDir2 }] = await Promise.all([
|
|
3214
|
-
import('../open-library-
|
|
3506
|
+
import('../open-library-COHFCT4N.js'),
|
|
3215
3507
|
import('../library/index.js'),
|
|
3216
3508
|
import('../core/index.js')
|
|
3217
3509
|
]);
|
|
3218
3510
|
const { manager, library, close } = await openLibraryManager2();
|
|
3219
3511
|
try {
|
|
3220
3512
|
const newRoot = getGlobalCacheDir2();
|
|
3221
|
-
const legacyRoot =
|
|
3513
|
+
const legacyRoot = path14__default.join(skaileHomeDir(), "sources");
|
|
3222
3514
|
const isSourceRow = (l) => l.path.startsWith(newRoot) || l.path.startsWith(legacyRoot);
|
|
3223
3515
|
const libs = await manager.listLibraries();
|
|
3224
3516
|
const defs = await library.listAssetDefs();
|
|
@@ -3598,10 +3890,10 @@ async function showInfo() {
|
|
|
3598
3890
|
}
|
|
3599
3891
|
console.log();
|
|
3600
3892
|
console.log(pc5.dim(" Press any key to return..."));
|
|
3601
|
-
await new Promise((
|
|
3893
|
+
await new Promise((resolve5) => {
|
|
3602
3894
|
const onData = () => {
|
|
3603
3895
|
process.stdin.removeListener("data", onData);
|
|
3604
|
-
|
|
3896
|
+
resolve5();
|
|
3605
3897
|
};
|
|
3606
3898
|
process.stdin.once("data", onData);
|
|
3607
3899
|
});
|
|
@@ -3854,13 +4146,13 @@ async function run(projectDir) {
|
|
|
3854
4146
|
}
|
|
3855
4147
|
function makeManageCommand() {
|
|
3856
4148
|
return new Command("manage").description("Interactive TUI for managing assets, sources, and libraries").option("--project-dir <path>", "Project directory", process.cwd()).action(async (opts) => {
|
|
3857
|
-
await run(
|
|
4149
|
+
await run(path14__default.resolve(opts.projectDir));
|
|
3858
4150
|
});
|
|
3859
4151
|
}
|
|
3860
4152
|
function makeMcpServerCommand() {
|
|
3861
4153
|
return new Command("mcp-server").description("Start skaile workspace MCP server (stdio transport)").option("--project-dir <path>", "Project directory (default: cwd)", process.cwd()).action(async (opts) => {
|
|
3862
|
-
const
|
|
3863
|
-
const projectDir =
|
|
4154
|
+
const path37 = await import('path');
|
|
4155
|
+
const projectDir = path37.default.resolve(opts.projectDir);
|
|
3864
4156
|
const { LogStore, StdoutSink, registerLogStore } = await import('../core/logging.js');
|
|
3865
4157
|
registerLogStore(
|
|
3866
4158
|
new LogStore({
|
|
@@ -3897,8 +4189,8 @@ function makeNpxCommand() {
|
|
|
3897
4189
|
skills.command("add <url>").description(
|
|
3898
4190
|
"Clone a repo, register it in the project's skaile.yaml sources[], and install a skill from it"
|
|
3899
4191
|
).requiredOption("--skill <name>", "Skill name to install from the repo").option("--project-dir <path>", "Project directory", process.cwd()).option("--target <agent>", "Agent framework", "claude-code").option("--global", "Deploy globally").action(async (url, opts) => {
|
|
3900
|
-
const projectDir =
|
|
3901
|
-
const projYaml =
|
|
4192
|
+
const projectDir = path14__default.resolve(opts.projectDir);
|
|
4193
|
+
const projYaml = path14__default.join(projectDir, "skaile.yaml");
|
|
3902
4194
|
if (!existsSync(projYaml)) {
|
|
3903
4195
|
logErr(`No skaile.yaml in ${projectDir} \u2014 run \`skaile init\` first.`);
|
|
3904
4196
|
process.exit(1);
|
|
@@ -3910,14 +4202,15 @@ function makeNpxCommand() {
|
|
|
3910
4202
|
process.exit(1);
|
|
3911
4203
|
}
|
|
3912
4204
|
const spinner5 = p6.spinner();
|
|
3913
|
-
const
|
|
3914
|
-
const clonePath =
|
|
4205
|
+
const key = sourceCacheKey(url);
|
|
4206
|
+
const clonePath = path14__default.join(getGlobalCacheDir(), key);
|
|
3915
4207
|
spinner5.start(`Cloning ${url}`);
|
|
3916
4208
|
try {
|
|
3917
4209
|
if (!existsSync(clonePath)) {
|
|
4210
|
+
mkdirSync(path14__default.dirname(clonePath), { recursive: true });
|
|
3918
4211
|
execSync(`git clone ${url} ${clonePath}`, { stdio: "ignore" });
|
|
3919
4212
|
}
|
|
3920
|
-
spinner5.stop(`Cloned to ${
|
|
4213
|
+
spinner5.stop(`Cloned to ${key}`);
|
|
3921
4214
|
} catch (err) {
|
|
3922
4215
|
spinner5.stop("Clone failed");
|
|
3923
4216
|
logErr(err instanceof Error ? err.message : String(err));
|
|
@@ -3960,7 +4253,7 @@ function makeNpxCommand() {
|
|
|
3960
4253
|
return npx;
|
|
3961
4254
|
}
|
|
3962
4255
|
function resolvePublisher(clonePath, url) {
|
|
3963
|
-
const manifestPath =
|
|
4256
|
+
const manifestPath = path14__default.join(clonePath, SKAILE_MANIFEST_FILENAME);
|
|
3964
4257
|
if (existsSync(manifestPath)) {
|
|
3965
4258
|
try {
|
|
3966
4259
|
const { manifest } = decodeSkaileManifest(readFileSync(manifestPath, "utf8"));
|
|
@@ -3973,12 +4266,12 @@ function resolvePublisher(clonePath, url) {
|
|
|
3973
4266
|
return url.match(/github\.com[/:]([^/]+)\/[^/]+/)?.[1];
|
|
3974
4267
|
}
|
|
3975
4268
|
function resolveSkillName(clonePath, requested) {
|
|
3976
|
-
const skillsDir =
|
|
3977
|
-
if (existsSync(
|
|
4269
|
+
const skillsDir = path14__default.join(clonePath, "skills");
|
|
4270
|
+
if (existsSync(path14__default.join(skillsDir, requested, "SKILL.md"))) return requested;
|
|
3978
4271
|
if (!existsSync(skillsDir)) return requested;
|
|
3979
4272
|
for (const entry of readdirSync(skillsDir, { withFileTypes: true })) {
|
|
3980
4273
|
if (!entry.isDirectory()) continue;
|
|
3981
|
-
const md =
|
|
4274
|
+
const md = path14__default.join(skillsDir, entry.name, "SKILL.md");
|
|
3982
4275
|
if (!existsSync(md)) continue;
|
|
3983
4276
|
try {
|
|
3984
4277
|
const { data } = parseFrontmatter(readFileSync(md, "utf8"));
|
|
@@ -3988,15 +4281,12 @@ function resolveSkillName(clonePath, requested) {
|
|
|
3988
4281
|
}
|
|
3989
4282
|
return requested;
|
|
3990
4283
|
}
|
|
3991
|
-
function sourceSlug(url) {
|
|
3992
|
-
return url.replace(/\.git$/, "").split(/[/:]/).pop() ?? "source";
|
|
3993
|
-
}
|
|
3994
4284
|
function makeOutdatedCommand() {
|
|
3995
4285
|
return new Command("outdated").description("Check for assets behind their repo").argument("[name]", "Check a specific asset (kind:name)").option("--project-dir <path>", "Project directory", process.cwd()).addOption(
|
|
3996
4286
|
new Option("--target <agent>", "Driver target").default("claude-code").choices(SUPPORTED_DRIVER_TARGETS)
|
|
3997
4287
|
).action((name, opts) => {
|
|
3998
4288
|
const am2 = new AssetManager({
|
|
3999
|
-
projectDir:
|
|
4289
|
+
projectDir: path14__default.resolve(opts.projectDir),
|
|
4000
4290
|
driverTarget: opts.target
|
|
4001
4291
|
});
|
|
4002
4292
|
const entries = am2.outdated();
|
|
@@ -4025,7 +4315,7 @@ function makeOutdatedCommand() {
|
|
|
4025
4315
|
function makePatchCommand() {
|
|
4026
4316
|
const cmd = new Command("patch").description("Patch workflow for skill improvement");
|
|
4027
4317
|
cmd.command("extract <ref>").alias("start").description("Extract asset for local editing").option("--project-dir <path>", "Project directory", process.cwd()).action((ref, opts) => {
|
|
4028
|
-
const am2 = new AssetManager({ projectDir:
|
|
4318
|
+
const am2 = new AssetManager({ projectDir: path14__default.resolve(opts.projectDir) });
|
|
4029
4319
|
try {
|
|
4030
4320
|
const dest = am2.patch(ref);
|
|
4031
4321
|
logOk(`Extracted to ${S.dim(dest)}`);
|
|
@@ -4036,7 +4326,7 @@ function makePatchCommand() {
|
|
|
4036
4326
|
}
|
|
4037
4327
|
});
|
|
4038
4328
|
cmd.command("commit <ref>").description("Generate .patch file from edits").option("--project-dir <path>", "Project directory", process.cwd()).action((ref, opts) => {
|
|
4039
|
-
const am2 = new AssetManager({ projectDir:
|
|
4329
|
+
const am2 = new AssetManager({ projectDir: path14__default.resolve(opts.projectDir) });
|
|
4040
4330
|
try {
|
|
4041
4331
|
const patchFile = am2.patchCommit(ref);
|
|
4042
4332
|
logOk(`Patch saved to ${S.dim(patchFile)}`);
|
|
@@ -4047,7 +4337,7 @@ function makePatchCommand() {
|
|
|
4047
4337
|
}
|
|
4048
4338
|
});
|
|
4049
4339
|
cmd.command("submit <ref>").description("Apply patch to repo clone and prepare for PR").option("--project-dir <path>", "Project directory", process.cwd()).action((ref, opts) => {
|
|
4050
|
-
const am2 = new AssetManager({ projectDir:
|
|
4340
|
+
const am2 = new AssetManager({ projectDir: path14__default.resolve(opts.projectDir) });
|
|
4051
4341
|
try {
|
|
4052
4342
|
am2.patchSubmit(ref);
|
|
4053
4343
|
logOk("Patch applied to repo clone and committed.");
|
|
@@ -4060,7 +4350,7 @@ function makePatchCommand() {
|
|
|
4060
4350
|
}
|
|
4061
4351
|
});
|
|
4062
4352
|
cmd.command("remove <ref>").description("Remove local patch after upstream merge").option("--project-dir <path>", "Project directory", process.cwd()).action((ref, opts) => {
|
|
4063
|
-
const am2 = new AssetManager({ projectDir:
|
|
4353
|
+
const am2 = new AssetManager({ projectDir: path14__default.resolve(opts.projectDir) });
|
|
4064
4354
|
am2.patchRemove(ref);
|
|
4065
4355
|
logOk(`Patch removed for ${ref}`);
|
|
4066
4356
|
});
|
|
@@ -4078,7 +4368,7 @@ function action2(fn) {
|
|
|
4078
4368
|
};
|
|
4079
4369
|
}
|
|
4080
4370
|
async function reconcileAndReport(projectDir, plugins) {
|
|
4081
|
-
const { reconcilePlugins } = await import('../plugin-store-
|
|
4371
|
+
const { reconcilePlugins } = await import('../plugin-store-UNENLB56.js');
|
|
4082
4372
|
if (plugins.length === 0) {
|
|
4083
4373
|
logInfo("No plugins declared \u2014 nothing to reconcile.");
|
|
4084
4374
|
return;
|
|
@@ -4092,10 +4382,10 @@ async function reconcileAndReport(projectDir, plugins) {
|
|
|
4092
4382
|
}
|
|
4093
4383
|
}
|
|
4094
4384
|
async function runInstall2(spec, opts) {
|
|
4095
|
-
const projectDir =
|
|
4385
|
+
const projectDir = path14__default.resolve(opts.projectDir);
|
|
4096
4386
|
const { WorkspaceYamlEditor: WorkspaceYamlEditor2 } = await import('../core/index.js');
|
|
4097
|
-
const { specName } = await import('../plugin-store-
|
|
4098
|
-
const yamlPath =
|
|
4387
|
+
const { specName } = await import('../plugin-store-UNENLB56.js');
|
|
4388
|
+
const yamlPath = path14__default.join(projectDir, "skaile.yaml");
|
|
4099
4389
|
const editor = WorkspaceYamlEditor2.load(yamlPath);
|
|
4100
4390
|
const replaced = editor.addPlugin(spec, specName);
|
|
4101
4391
|
editor.save();
|
|
@@ -4104,10 +4394,10 @@ async function runInstall2(spec, opts) {
|
|
|
4104
4394
|
await reconcileAndReport(projectDir, editor.getPlugins());
|
|
4105
4395
|
}
|
|
4106
4396
|
async function runRemove(name, opts) {
|
|
4107
|
-
const projectDir =
|
|
4397
|
+
const projectDir = path14__default.resolve(opts.projectDir);
|
|
4108
4398
|
const { WorkspaceYamlEditor: WorkspaceYamlEditor2 } = await import('../core/index.js');
|
|
4109
|
-
const { specName } = await import('../plugin-store-
|
|
4110
|
-
const yamlPath =
|
|
4399
|
+
const { specName } = await import('../plugin-store-UNENLB56.js');
|
|
4400
|
+
const yamlPath = path14__default.join(projectDir, "skaile.yaml");
|
|
4111
4401
|
const editor = WorkspaceYamlEditor2.load(yamlPath);
|
|
4112
4402
|
const removed = editor.removePlugin(name, specName);
|
|
4113
4403
|
if (!removed) {
|
|
@@ -4119,7 +4409,7 @@ async function runRemove(name, opts) {
|
|
|
4119
4409
|
await reconcileAndReport(projectDir, editor.getPlugins());
|
|
4120
4410
|
}
|
|
4121
4411
|
async function runList(opts) {
|
|
4122
|
-
const projectDir =
|
|
4412
|
+
const projectDir = path14__default.resolve(opts.projectDir);
|
|
4123
4413
|
const { resolveSkWorkspaceConfig: resolveSkWorkspaceConfig2 } = await import('../core/index.js');
|
|
4124
4414
|
const config = resolveSkWorkspaceConfig2(projectDir);
|
|
4125
4415
|
const declared = config.plugins ?? [];
|
|
@@ -4134,7 +4424,7 @@ async function runList(opts) {
|
|
|
4134
4424
|
const registry = createPluginRegistry();
|
|
4135
4425
|
if (declared.length > 0) {
|
|
4136
4426
|
try {
|
|
4137
|
-
const { loadPlugins } = await import('../plugin-store-
|
|
4427
|
+
const { loadPlugins } = await import('../plugin-store-UNENLB56.js');
|
|
4138
4428
|
const result = await loadPlugins(projectDir, declared, registry);
|
|
4139
4429
|
for (const f of result.failed) logWarn(f.error);
|
|
4140
4430
|
} catch (err) {
|
|
@@ -4173,7 +4463,7 @@ function makePresetCommand() {
|
|
|
4173
4463
|
cmd.command("init [name]").description("Scaffold a new .preset.yaml file").option("--dir <path>", "Output directory", process.cwd()).action(async (name, opts) => {
|
|
4174
4464
|
const presetName = name ?? "my-preset";
|
|
4175
4465
|
const filename = `${presetName}.preset.yaml`;
|
|
4176
|
-
const outPath =
|
|
4466
|
+
const outPath = path14__default.join(path14__default.resolve(opts.dir), filename);
|
|
4177
4467
|
if (existsSync(outPath)) {
|
|
4178
4468
|
logErr(`File already exists: ${outPath}`);
|
|
4179
4469
|
logInfo("Choose a different name or remove the existing file.");
|
|
@@ -4221,7 +4511,7 @@ async function reportNestedPresetRefs(preset) {
|
|
|
4221
4511
|
}
|
|
4222
4512
|
async function checkPresetCycles(preset, resolved) {
|
|
4223
4513
|
const { detectCycles } = await import('../discovery/index.js');
|
|
4224
|
-
const presetRef =
|
|
4514
|
+
const presetRef = path14__default.basename(resolved, ".preset.yaml");
|
|
4225
4515
|
const edges = [];
|
|
4226
4516
|
for (const item of preset.items) {
|
|
4227
4517
|
if (item.ref) {
|
|
@@ -4272,7 +4562,7 @@ function printPresetSummary(preset, placeholderCount, hasWarnings) {
|
|
|
4272
4562
|
}
|
|
4273
4563
|
}
|
|
4274
4564
|
async function runPresetValidate(filePath) {
|
|
4275
|
-
const resolved =
|
|
4565
|
+
const resolved = path14__default.resolve(filePath);
|
|
4276
4566
|
const preset = await loadPresetForValidation(resolved);
|
|
4277
4567
|
await reportNestedPresetRefs(preset);
|
|
4278
4568
|
await checkPresetCycles(preset, resolved);
|
|
@@ -4366,8 +4656,8 @@ async function runRefInstall(ref, opts) {
|
|
|
4366
4656
|
const spinner5 = p6.spinner();
|
|
4367
4657
|
spinner5.start(`Installing ${ref}`);
|
|
4368
4658
|
try {
|
|
4369
|
-
const { openCatalogSource: openCatalogSource2, openLibrary: openLibrary2 } = await import('../open-library-
|
|
4370
|
-
const catalog = await openCatalogSource2({ projectDir:
|
|
4659
|
+
const { openCatalogSource: openCatalogSource2, openLibrary: openLibrary2 } = await import('../open-library-COHFCT4N.js');
|
|
4660
|
+
const catalog = await openCatalogSource2({ projectDir: path14__default.resolve(opts.projectDir) });
|
|
4371
4661
|
if (!supportsInstallManifest(catalog)) {
|
|
4372
4662
|
throw new Error(
|
|
4373
4663
|
"pointer-only install (skaile install <ref>) requires a tRPC-framed Catalog. The configured catalog uses REST framing, which does not serve install manifests. Set catalog.url to https://skaile.store, or catalog.framing: trpc, in ~/.skaile/config.yaml."
|
|
@@ -4396,9 +4686,9 @@ async function runRefInstall(ref, opts) {
|
|
|
4396
4686
|
}
|
|
4397
4687
|
}
|
|
4398
4688
|
async function runYamlInstall(opts) {
|
|
4399
|
-
const projectDir =
|
|
4689
|
+
const projectDir = path14__default.resolve(opts.projectDir);
|
|
4400
4690
|
try {
|
|
4401
|
-
const { ensureSourcesCloned } = await import('../ensure-sources-
|
|
4691
|
+
const { ensureSourcesCloned } = await import('../ensure-sources-KLCGXVE6.js');
|
|
4402
4692
|
const hydrate = ensureSourcesCloned(projectDir, { quiet: true });
|
|
4403
4693
|
if (hydrate.cloned.length > 0) {
|
|
4404
4694
|
logOk(`Cloned source(s): ${hydrate.cloned.join(", ")}`);
|
|
@@ -4429,6 +4719,7 @@ async function runYamlInstall(opts) {
|
|
|
4429
4719
|
}
|
|
4430
4720
|
if (result.missing.length > 0) {
|
|
4431
4721
|
for (const m of result.missing) logErr(`Missing: ${m}`);
|
|
4722
|
+
process.exitCode = 1;
|
|
4432
4723
|
}
|
|
4433
4724
|
if (result.lockWritten) {
|
|
4434
4725
|
logInfo(`Lock file written: ${S.dim("skaile.lock.yaml")}`);
|
|
@@ -4441,7 +4732,7 @@ async function runYamlInstall(opts) {
|
|
|
4441
4732
|
}
|
|
4442
4733
|
function makeCheckCommand() {
|
|
4443
4734
|
return new Command("check").description("Check for unmet requirements").option("--project-dir <path>", "Project directory", process.cwd()).action((opts) => {
|
|
4444
|
-
const am2 = new AssetManager({ projectDir:
|
|
4735
|
+
const am2 = new AssetManager({ projectDir: path14__default.resolve(opts.projectDir) });
|
|
4445
4736
|
const issues = am2.doctor();
|
|
4446
4737
|
if (issues.length === 0) {
|
|
4447
4738
|
logOk("All dependencies satisfied.");
|
|
@@ -4458,10 +4749,10 @@ function makeCheckCommand() {
|
|
|
4458
4749
|
function makeCleanCommand() {
|
|
4459
4750
|
return new Command("clean").description("Remove all skaile-managed assets from the workspace").option("--all", "Full reset: also remove history, patches, repos, and lock file").option("--dry-run", "Show what would be removed without doing it").option("-y, --yes", "Skip confirmation prompt").option("--project-dir <path>", "Project directory", process.cwd()).option("--target <agent>", "Agent framework", "claude-code").action(async (opts) => {
|
|
4460
4751
|
const am2 = new AssetManager({
|
|
4461
|
-
projectDir:
|
|
4752
|
+
projectDir: path14__default.resolve(opts.projectDir),
|
|
4462
4753
|
driverTarget: opts.target
|
|
4463
4754
|
});
|
|
4464
|
-
const lock = readLock(
|
|
4755
|
+
const lock = readLock(path14__default.resolve(opts.projectDir, "skaile.lock.yaml"));
|
|
4465
4756
|
if (!lock || Object.keys(lock.assets).length === 0) {
|
|
4466
4757
|
logInfo("Nothing to clean (no skaile-managed assets found).");
|
|
4467
4758
|
return;
|
|
@@ -4514,14 +4805,14 @@ function makeCleanCommand() {
|
|
|
4514
4805
|
}
|
|
4515
4806
|
function makeRebuildCommand() {
|
|
4516
4807
|
return new Command("rebuild").description("Re-snapshot inline-snapshot composition items and bump prompt version").argument("[agent]", "Agent name or path (defaults to current project agent)").option("--project-dir <dir>", "Project directory", process.cwd()).action(async (agentArg, opts) => {
|
|
4517
|
-
const projectDir =
|
|
4808
|
+
const projectDir = path14__default.resolve(opts.projectDir);
|
|
4518
4809
|
let agentDir;
|
|
4519
4810
|
if (agentArg) {
|
|
4520
4811
|
if (agentArg.includes("/") || agentArg.includes("\\")) {
|
|
4521
|
-
agentDir =
|
|
4812
|
+
agentDir = path14__default.resolve(projectDir, agentArg);
|
|
4522
4813
|
} else {
|
|
4523
4814
|
const resolved = resolveAgentDir(projectDir);
|
|
4524
|
-
agentDir = resolved ??
|
|
4815
|
+
agentDir = resolved ?? path14__default.resolve(projectDir, agentArg);
|
|
4525
4816
|
}
|
|
4526
4817
|
} else {
|
|
4527
4818
|
const resolved = resolveAgentDir(projectDir);
|
|
@@ -4599,7 +4890,7 @@ function makeFlowEventHandler() {
|
|
|
4599
4890
|
}
|
|
4600
4891
|
function makeRunCommand() {
|
|
4601
4892
|
const cmd = new Command("run").description("Start a flow or run a single-shot text prompt").argument("[flow-id-or-text...]", "Flow ID or text prompt").option("--project-dir <path>", "Project directory", process.cwd()).option("--driver <name>", "Driver backend (claude-sdk, codex, omp)").option("--provider <name>", "LLM provider").option("--model <name>", "Model override").option("--label <label>", "Human-readable session label").option("--dry-run", "Print plan without executing").option("--skill <name>", "Skill name (for single-shot mode)").action(async (positional, opts) => {
|
|
4602
|
-
const projectDir =
|
|
4893
|
+
const projectDir = path14__default.resolve(opts.projectDir);
|
|
4603
4894
|
const cliDriver = opts.driver;
|
|
4604
4895
|
const dryRun = opts.dryRun ?? false;
|
|
4605
4896
|
let flowId = positional[0];
|
|
@@ -4634,12 +4925,12 @@ function makeRunCommand() {
|
|
|
4634
4925
|
const priorityRoots = [];
|
|
4635
4926
|
let dir = projectDir;
|
|
4636
4927
|
for (let i = 0; i < 6; i++) {
|
|
4637
|
-
const candidate =
|
|
4638
|
-
if (
|
|
4928
|
+
const candidate = path14__default.join(dir, "ai-assets");
|
|
4929
|
+
if (fs12__default.existsSync(candidate)) {
|
|
4639
4930
|
priorityRoots.push(candidate);
|
|
4640
4931
|
break;
|
|
4641
4932
|
}
|
|
4642
|
-
dir =
|
|
4933
|
+
dir = path14__default.dirname(dir);
|
|
4643
4934
|
}
|
|
4644
4935
|
const flowPath = findFlowFile(flowId, priorityRoots);
|
|
4645
4936
|
if (!flowPath) {
|
|
@@ -4694,7 +4985,7 @@ function makeRunCommand() {
|
|
|
4694
4985
|
}
|
|
4695
4986
|
function makeResumeCommand() {
|
|
4696
4987
|
const cmd = new Command("resume").description("Resume current session").option("--project-dir <path>", "Project directory", process.cwd()).option("--session <run-id>", "Target session by runId").option("--dry-run", "Print plan without executing").action(async (opts) => {
|
|
4697
|
-
const projectDir =
|
|
4988
|
+
const projectDir = path14__default.resolve(opts.projectDir);
|
|
4698
4989
|
const sessionId = opts.session;
|
|
4699
4990
|
const dryRun = opts.dryRun ?? false;
|
|
4700
4991
|
const session = sessionId ? await loadSessionById(projectDir, sessionId) : await loadSession(projectDir);
|
|
@@ -4721,7 +5012,7 @@ function makeResumeCommand() {
|
|
|
4721
5012
|
}
|
|
4722
5013
|
function makeStatusCommand() {
|
|
4723
5014
|
return new Command("status").description("Show current session state").option("--project-dir <path>", "Project directory", process.cwd()).action(async (opts) => {
|
|
4724
|
-
const projectDir =
|
|
5015
|
+
const projectDir = path14__default.resolve(opts.projectDir);
|
|
4725
5016
|
const session = await loadSession(projectDir);
|
|
4726
5017
|
if (!session) {
|
|
4727
5018
|
logInfo("No active session.");
|
|
@@ -4746,7 +5037,7 @@ function makeStatusCommand() {
|
|
|
4746
5037
|
}
|
|
4747
5038
|
function makeClearCommand() {
|
|
4748
5039
|
return new Command("clear").description("Unset current session pointer").option("--project-dir <path>", "Project directory", process.cwd()).action(async (opts) => {
|
|
4749
|
-
const projectDir =
|
|
5040
|
+
const projectDir = path14__default.resolve(opts.projectDir);
|
|
4750
5041
|
await clearSession(projectDir);
|
|
4751
5042
|
logOk("Session cleared.");
|
|
4752
5043
|
});
|
|
@@ -4755,8 +5046,8 @@ function makeReplCommand() {
|
|
|
4755
5046
|
return new Command("repl").description("Start an interactive agent session").option("--project-dir <path>", "Project directory").option("--driver <name>", "Driver backend (claude-sdk, omp)").option("--provider <name>", "LLM provider").option("--model <name>", "Model override").option("--resume", "Resume last session").option("--resume-session <id>", "Resume specific session").action(async (opts) => {
|
|
4756
5047
|
const { findWorkspaceRoot: findWorkspaceRoot2 } = await import('../core/index.js');
|
|
4757
5048
|
const { startRepl } = await import('../tui/index.js');
|
|
4758
|
-
const
|
|
4759
|
-
const userCwd =
|
|
5049
|
+
const os2 = await import('os');
|
|
5050
|
+
const userCwd = path14__default.resolve(opts.projectDir ?? process.cwd());
|
|
4760
5051
|
const workspaceRoot = findWorkspaceRoot2(userCwd);
|
|
4761
5052
|
let projectDir;
|
|
4762
5053
|
let agentCwd;
|
|
@@ -4778,13 +5069,13 @@ function makeReplCommand() {
|
|
|
4778
5069
|
p6.cancel("Cancelled.");
|
|
4779
5070
|
process.exit(0);
|
|
4780
5071
|
}
|
|
4781
|
-
const tmpDir =
|
|
5072
|
+
const tmpDir = fs12__default.mkdtempSync(path14__default.join(os2.tmpdir(), "skaile-repl-"));
|
|
4782
5073
|
projectDir = tmpDir;
|
|
4783
5074
|
agentCwd = userCwd;
|
|
4784
5075
|
logOk(`Temporary workspace: ${S.cmd(tmpDir)}`);
|
|
4785
5076
|
if (!driverOverride) {
|
|
4786
|
-
const claudeDir =
|
|
4787
|
-
if (
|
|
5077
|
+
const claudeDir = path14__default.join(os2.homedir(), ".claude");
|
|
5078
|
+
if (fs12__default.existsSync(claudeDir)) {
|
|
4788
5079
|
driverOverride = "claude-sdk";
|
|
4789
5080
|
logInfo(`Detected ${S.cmd("~/.claude")} \u2192 using ${S.cmd("claude-sdk")} backend`);
|
|
4790
5081
|
} else {
|
|
@@ -4835,7 +5126,7 @@ async function ensurePluginsLoadedForServe(projectDir) {
|
|
|
4835
5126
|
const { resolveSkWorkspaceConfig: resolveSkWorkspaceConfig2 } = await import('../core/index.js');
|
|
4836
5127
|
const config = resolveSkWorkspaceConfig2(projectDir);
|
|
4837
5128
|
if (!config.plugins || config.plugins.length === 0) return;
|
|
4838
|
-
const { ensurePluginsLoaded } = await import('../plugin-store-
|
|
5129
|
+
const { ensurePluginsLoaded } = await import('../plugin-store-UNENLB56.js');
|
|
4839
5130
|
const { pluginRegistry } = await import('../plugin-registry/index.js');
|
|
4840
5131
|
const result = await ensurePluginsLoaded(projectDir, config.plugins, pluginRegistry);
|
|
4841
5132
|
if (result.loaded.length > 0) {
|
|
@@ -4851,21 +5142,21 @@ async function ensurePluginsLoadedForServe(projectDir) {
|
|
|
4851
5142
|
async function runCompileTest(opts) {
|
|
4852
5143
|
const { logOk: logOk2, logErr: logErr2, logInfo: logInfo2, S: S2 } = await import('../helpers-F4NZ66VD.js');
|
|
4853
5144
|
const { tmpdir } = await import('os');
|
|
4854
|
-
const { dirname:
|
|
5145
|
+
const { dirname: dirname5, join: join6, resolve: resolve5 } = await import('path');
|
|
4855
5146
|
const { fileURLToPath: fileURLToPath2 } = await import('url');
|
|
4856
|
-
const { unlinkSync, existsSync:
|
|
5147
|
+
const { unlinkSync, existsSync: existsSync14 } = await import('fs');
|
|
4857
5148
|
const { spawn } = await import('child_process');
|
|
4858
5149
|
const { portableSpawnSync: portableSpawnSync2 } = await import('../core/index.js');
|
|
4859
|
-
const { MONOREPO_ROOT } = await import('../paths-
|
|
5150
|
+
const { MONOREPO_ROOT } = await import('../paths-2SYXGTZJ.js');
|
|
4860
5151
|
if (MONOREPO_ROOT === null) {
|
|
4861
5152
|
logErr2("--compile-test is only available inside the skaile-dev workspace.");
|
|
4862
5153
|
logInfo2("Run it from a checkout of skaile-ai/skaile-dev (the monorepo shell).");
|
|
4863
5154
|
process.exitCode = 2;
|
|
4864
5155
|
return;
|
|
4865
5156
|
}
|
|
4866
|
-
const outfile =
|
|
5157
|
+
const outfile = join6(tmpdir(), `skaile-compile-test-${Date.now()}`);
|
|
4867
5158
|
const __thisFile = fileURLToPath2(import.meta.url);
|
|
4868
|
-
const entryPoint =
|
|
5159
|
+
const entryPoint = resolve5(dirname5(__thisFile), "..", "index.ts");
|
|
4869
5160
|
logInfo2(`Building compiled binary...`);
|
|
4870
5161
|
logInfo2(`Entry: ${S2.dim(entryPoint)}`);
|
|
4871
5162
|
logInfo2(`Output: ${S2.dim(outfile)}`);
|
|
@@ -4915,7 +5206,7 @@ async function runCompileTest(opts) {
|
|
|
4915
5206
|
} catch {
|
|
4916
5207
|
}
|
|
4917
5208
|
try {
|
|
4918
|
-
if (
|
|
5209
|
+
if (existsSync14(outfile)) unlinkSync(outfile);
|
|
4919
5210
|
} catch {
|
|
4920
5211
|
}
|
|
4921
5212
|
}
|
|
@@ -5168,19 +5459,19 @@ function buildTailSelect(q) {
|
|
|
5168
5459
|
return { sql, params };
|
|
5169
5460
|
}
|
|
5170
5461
|
function sleepUnlessAborted(ms, signal) {
|
|
5171
|
-
return new Promise((
|
|
5462
|
+
return new Promise((resolve5) => {
|
|
5172
5463
|
if (signal?.aborted) {
|
|
5173
|
-
|
|
5464
|
+
resolve5();
|
|
5174
5465
|
return;
|
|
5175
5466
|
}
|
|
5176
5467
|
const timer = setTimeout(() => {
|
|
5177
5468
|
signal?.removeEventListener("abort", onAbort);
|
|
5178
|
-
|
|
5469
|
+
resolve5();
|
|
5179
5470
|
}, ms);
|
|
5180
5471
|
const onAbort = () => {
|
|
5181
5472
|
clearTimeout(timer);
|
|
5182
5473
|
signal?.removeEventListener("abort", onAbort);
|
|
5183
|
-
|
|
5474
|
+
resolve5();
|
|
5184
5475
|
};
|
|
5185
5476
|
signal?.addEventListener("abort", onAbort, { once: true });
|
|
5186
5477
|
});
|
|
@@ -5257,7 +5548,7 @@ async function remoteTail(opts) {
|
|
|
5257
5548
|
]
|
|
5258
5549
|
});
|
|
5259
5550
|
const filter = makeFilter(opts.query);
|
|
5260
|
-
return new Promise((
|
|
5551
|
+
return new Promise((resolve5, reject) => {
|
|
5261
5552
|
let settled = false;
|
|
5262
5553
|
const finish = (err) => {
|
|
5263
5554
|
if (settled) return;
|
|
@@ -5268,11 +5559,11 @@ async function remoteTail(opts) {
|
|
|
5268
5559
|
}
|
|
5269
5560
|
opts.signal?.removeEventListener("abort", onAbort);
|
|
5270
5561
|
if (err) reject(err);
|
|
5271
|
-
else
|
|
5562
|
+
else resolve5();
|
|
5272
5563
|
};
|
|
5273
5564
|
const onAbort = () => finish();
|
|
5274
5565
|
if (opts.signal?.aborted) {
|
|
5275
|
-
|
|
5566
|
+
resolve5();
|
|
5276
5567
|
return;
|
|
5277
5568
|
}
|
|
5278
5569
|
opts.signal?.addEventListener("abort", onAbort, { once: true });
|
|
@@ -5326,7 +5617,7 @@ function resolveMode(opts) {
|
|
|
5326
5617
|
if (opts.forceLocal && opts.forceRemote) {
|
|
5327
5618
|
throw new Error("Cannot use both --local and --remote");
|
|
5328
5619
|
}
|
|
5329
|
-
const startDir =
|
|
5620
|
+
const startDir = path14__default.resolve(opts.projectDir ?? process.cwd());
|
|
5330
5621
|
const localDb = findLogsDb(startDir);
|
|
5331
5622
|
if (opts.forceLocal) {
|
|
5332
5623
|
if (!localDb) {
|
|
@@ -5359,14 +5650,14 @@ function resolveMode(opts) {
|
|
|
5359
5650
|
function findLogsDb(startDir) {
|
|
5360
5651
|
let dir = startDir;
|
|
5361
5652
|
for (let i = 0; i < MAX_WALK_LEVELS; i++) {
|
|
5362
|
-
const candidate =
|
|
5653
|
+
const candidate = path14__default.join(dir, ".skaile", "logs.db");
|
|
5363
5654
|
if (existsSync(candidate)) {
|
|
5364
5655
|
try {
|
|
5365
5656
|
if (statSync(candidate).isFile()) return candidate;
|
|
5366
5657
|
} catch {
|
|
5367
5658
|
}
|
|
5368
5659
|
}
|
|
5369
|
-
const parent =
|
|
5660
|
+
const parent = path14__default.dirname(dir);
|
|
5370
5661
|
if (parent === dir) return void 0;
|
|
5371
5662
|
dir = parent;
|
|
5372
5663
|
}
|
|
@@ -5392,7 +5683,7 @@ function readApiToken() {
|
|
|
5392
5683
|
}
|
|
5393
5684
|
function readGlobalSettings() {
|
|
5394
5685
|
try {
|
|
5395
|
-
const settingsPath =
|
|
5686
|
+
const settingsPath = path14__default.join(homedir(), ".skaile", "settings.json");
|
|
5396
5687
|
if (!existsSync(settingsPath)) return {};
|
|
5397
5688
|
return JSON.parse(readFileSync(settingsPath, "utf8"));
|
|
5398
5689
|
} catch {
|
|
@@ -5541,7 +5832,7 @@ function parsePositiveInt(value, flag) {
|
|
|
5541
5832
|
function makeSessionCommand() {
|
|
5542
5833
|
const cmd = new Command("session").description("Manage sessions");
|
|
5543
5834
|
cmd.command("list").description("List all sessions for a project").option("--project-dir <path>", "Project directory", process.cwd()).action(async (opts) => {
|
|
5544
|
-
const projectDir =
|
|
5835
|
+
const projectDir = path14__default.resolve(opts.projectDir);
|
|
5545
5836
|
const sessions = await listSessions(projectDir);
|
|
5546
5837
|
const current = await loadSession(projectDir);
|
|
5547
5838
|
if (sessions.length === 0) {
|
|
@@ -5569,7 +5860,7 @@ function makeSessionCommand() {
|
|
|
5569
5860
|
console.log();
|
|
5570
5861
|
});
|
|
5571
5862
|
cmd.command("show <run-id>").description("Show a specific session").option("--project-dir <path>", "Project directory", process.cwd()).action(async (runId, opts) => {
|
|
5572
|
-
const projectDir =
|
|
5863
|
+
const projectDir = path14__default.resolve(opts.projectDir);
|
|
5573
5864
|
const session = await loadSessionById(projectDir, runId);
|
|
5574
5865
|
if (!session) {
|
|
5575
5866
|
logErr(`Session not found: ${runId}`);
|
|
@@ -5578,12 +5869,12 @@ function makeSessionCommand() {
|
|
|
5578
5869
|
console.log(JSON.stringify(session, null, 2));
|
|
5579
5870
|
});
|
|
5580
5871
|
cmd.command("switch <run-id>").description("Switch the current session").option("--project-dir <path>", "Project directory", process.cwd()).action(async (runId, opts) => {
|
|
5581
|
-
const projectDir =
|
|
5872
|
+
const projectDir = path14__default.resolve(opts.projectDir);
|
|
5582
5873
|
await setCurrentSession(projectDir, runId);
|
|
5583
5874
|
logOk(`Switched to session: ${S.dim(runId.slice(0, 8))}`);
|
|
5584
5875
|
});
|
|
5585
5876
|
cmd.command("delete <run-id>").description("Delete a session").option("--project-dir <path>", "Project directory", process.cwd()).action(async (runId, opts) => {
|
|
5586
|
-
const projectDir =
|
|
5877
|
+
const projectDir = path14__default.resolve(opts.projectDir);
|
|
5587
5878
|
await deleteSession(projectDir, runId);
|
|
5588
5879
|
logOk(`Deleted session: ${S.dim(runId.slice(0, 8))}`);
|
|
5589
5880
|
});
|
|
@@ -5637,12 +5928,12 @@ function showOverview(am2) {
|
|
|
5637
5928
|
}
|
|
5638
5929
|
function showAsset(am2, kind, name) {
|
|
5639
5930
|
const entry = am2.info(`${kind}:${name}`);
|
|
5640
|
-
if (entry?.source &&
|
|
5931
|
+
if (entry?.source && fs12__default.existsSync(entry.source)) {
|
|
5641
5932
|
console.log();
|
|
5642
5933
|
console.log(` ${kindColor(entry.kind)} ${S.heading(entry.name)}`);
|
|
5643
5934
|
console.log(` ${S.rule(40)}`);
|
|
5644
5935
|
console.log();
|
|
5645
|
-
console.log(
|
|
5936
|
+
console.log(fs12__default.readFileSync(entry.source, "utf-8"));
|
|
5646
5937
|
return;
|
|
5647
5938
|
}
|
|
5648
5939
|
logErr(`Asset not found: ${kind}:${name}`);
|
|
@@ -5651,7 +5942,7 @@ function showAsset(am2, kind, name) {
|
|
|
5651
5942
|
function makeShowCommand() {
|
|
5652
5943
|
return new Command("show").description("Show deployed assets overview, or print asset content").argument("[kind]", "Asset kind (skill, agent, prompt, flow, bundle, contract)").argument("[name]", "Asset name").option("--project-dir <path>", "Project directory", process.cwd()).option("--target <agent>", "Agent framework", "claude-code").action((kind, name, opts) => {
|
|
5653
5944
|
const am2 = new AssetManager({
|
|
5654
|
-
projectDir:
|
|
5945
|
+
projectDir: path14__default.resolve(opts.projectDir),
|
|
5655
5946
|
driverTarget: opts.target
|
|
5656
5947
|
});
|
|
5657
5948
|
if (!kind) {
|
|
@@ -5688,11 +5979,8 @@ function addSourceManifestCommands(src) {
|
|
|
5688
5979
|
}
|
|
5689
5980
|
|
|
5690
5981
|
// cli/src/commands/source.ts
|
|
5691
|
-
function sourceClonePath(
|
|
5692
|
-
return
|
|
5693
|
-
}
|
|
5694
|
-
function deriveSlug(url) {
|
|
5695
|
-
return url.replace(/\.git$/, "").split(/[/:]/).pop() ?? "source";
|
|
5982
|
+
function sourceClonePath(key) {
|
|
5983
|
+
return path14.join(getGlobalCacheDir(), key);
|
|
5696
5984
|
}
|
|
5697
5985
|
function normalizeSourceUrl(input) {
|
|
5698
5986
|
const s = input.trim();
|
|
@@ -5703,9 +5991,14 @@ function normalizeSourceUrl(input) {
|
|
|
5703
5991
|
return s;
|
|
5704
5992
|
}
|
|
5705
5993
|
function sourceMatchesKey(entry, key) {
|
|
5706
|
-
if (entry.url === key
|
|
5994
|
+
if (entry.url === key) return true;
|
|
5995
|
+
if (sourceCacheKey(entry.url) === key || sourceShortName(entry.url) === key) return true;
|
|
5707
5996
|
return entry.url === normalizeSourceUrl(key);
|
|
5708
5997
|
}
|
|
5998
|
+
function findCacheKeyCollision(sources, url) {
|
|
5999
|
+
const key = sourceCacheKey(url);
|
|
6000
|
+
return sources.find((s) => s.url !== url && sourceCacheKey(s.url) === key);
|
|
6001
|
+
}
|
|
5709
6002
|
function requireProjectYamlPath() {
|
|
5710
6003
|
const root = findWorkspaceRoot(process.cwd());
|
|
5711
6004
|
if (!root) {
|
|
@@ -5714,7 +6007,7 @@ function requireProjectYamlPath() {
|
|
|
5714
6007
|
);
|
|
5715
6008
|
process.exit(1);
|
|
5716
6009
|
}
|
|
5717
|
-
return
|
|
6010
|
+
return path14.join(root, workspaceConfigFilename());
|
|
5718
6011
|
}
|
|
5719
6012
|
function readProjectSources(yamlPath) {
|
|
5720
6013
|
if (!existsSync(yamlPath)) return [];
|
|
@@ -5726,12 +6019,12 @@ function readProjectSources(yamlPath) {
|
|
|
5726
6019
|
}
|
|
5727
6020
|
}
|
|
5728
6021
|
function ensureClone(entry, opts = {}) {
|
|
5729
|
-
const
|
|
5730
|
-
const dest = sourceClonePath(slug);
|
|
6022
|
+
const dest = sourceClonePath(sourceCacheKey(entry.url));
|
|
5731
6023
|
if (existsSync(dest)) {
|
|
5732
6024
|
if (!opts.force) return false;
|
|
5733
6025
|
rmSync(dest, { recursive: true, force: true });
|
|
5734
6026
|
}
|
|
6027
|
+
mkdirSync(path14.dirname(dest), { recursive: true });
|
|
5735
6028
|
const args = ["clone", entry.url, dest];
|
|
5736
6029
|
if (entry.pin) args.splice(1, 0, "--branch", entry.pin);
|
|
5737
6030
|
const clone = spawnSync("git", args, { stdio: "inherit" });
|
|
@@ -5744,11 +6037,11 @@ function ensureClone(entry, opts = {}) {
|
|
|
5744
6037
|
async function refreshManifestCache(entry, includeDev = false) {
|
|
5745
6038
|
const { manager, library, close } = await openLibraryManager();
|
|
5746
6039
|
try {
|
|
5747
|
-
const
|
|
5748
|
-
const dest = sourceClonePath(
|
|
5749
|
-
const existing = (await manager.listLibraries()).find((l) => l.name ===
|
|
6040
|
+
const name = sourceShortName(entry.url);
|
|
6041
|
+
const dest = sourceClonePath(sourceCacheKey(entry.url));
|
|
6042
|
+
const existing = (await manager.listLibraries()).find((l) => l.name === name);
|
|
5750
6043
|
const lib = existing ?? await manager.addLibrary({
|
|
5751
|
-
name
|
|
6044
|
+
name,
|
|
5752
6045
|
path: dest,
|
|
5753
6046
|
backend: "git",
|
|
5754
6047
|
backendConfig: { url: entry.url, branch: entry.pin ?? "main", authHint: "ssh" },
|
|
@@ -5762,7 +6055,8 @@ async function refreshManifestCache(entry, includeDev = false) {
|
|
|
5762
6055
|
close();
|
|
5763
6056
|
}
|
|
5764
6057
|
}
|
|
5765
|
-
async function dropManifestCache(
|
|
6058
|
+
async function dropManifestCache(url, purgeClone) {
|
|
6059
|
+
const name = sourceShortName(url);
|
|
5766
6060
|
const { manager, close } = await openLibraryManager();
|
|
5767
6061
|
try {
|
|
5768
6062
|
const existing = (await manager.listLibraries()).find((l) => l.name === name);
|
|
@@ -5773,7 +6067,7 @@ async function dropManifestCache(name, purgeClone) {
|
|
|
5773
6067
|
close();
|
|
5774
6068
|
}
|
|
5775
6069
|
if (purgeClone) {
|
|
5776
|
-
const dest = sourceClonePath(
|
|
6070
|
+
const dest = sourceClonePath(sourceCacheKey(url));
|
|
5777
6071
|
if (existsSync(dest)) rmSync(dest, { recursive: true, force: true });
|
|
5778
6072
|
}
|
|
5779
6073
|
}
|
|
@@ -5787,19 +6081,27 @@ function makeSourceCommand() {
|
|
|
5787
6081
|
async (source, opts) => {
|
|
5788
6082
|
const url = normalizeSourceUrl(source);
|
|
5789
6083
|
const yamlPath = requireProjectYamlPath();
|
|
6084
|
+
const collision = findCacheKeyCollision(readProjectSources(yamlPath), url);
|
|
6085
|
+
if (collision) {
|
|
6086
|
+
logErr(
|
|
6087
|
+
`"${url}" maps to the same cache key (${sourceCacheKey(url)}) as already-registered "${collision.url}". Remove that source first (skaile source remove) or re-use its exact URL to update it.`
|
|
6088
|
+
);
|
|
6089
|
+
process.exitCode = 1;
|
|
6090
|
+
return;
|
|
6091
|
+
}
|
|
5790
6092
|
if (opts.name) {
|
|
5791
6093
|
logWarn(
|
|
5792
6094
|
"the --name flag is deprecated; the source entry now stores only the URL (the cache slug is derived from it)."
|
|
5793
6095
|
);
|
|
5794
6096
|
}
|
|
5795
6097
|
const pin = opts.pin ?? opts.branch;
|
|
5796
|
-
const slug =
|
|
6098
|
+
const slug = sourceShortName(url);
|
|
5797
6099
|
const entry = { url };
|
|
5798
6100
|
if (pin) entry.pin = pin;
|
|
5799
6101
|
const editor = WorkspaceYamlEditor.load(yamlPath);
|
|
5800
6102
|
editor.setSource(entry);
|
|
5801
6103
|
editor.save();
|
|
5802
|
-
const dest = sourceClonePath(
|
|
6104
|
+
const dest = sourceClonePath(sourceCacheKey(url));
|
|
5803
6105
|
const preexisting = existsSync(dest);
|
|
5804
6106
|
const cloned = ensureClone(entry, { force: opts.force });
|
|
5805
6107
|
if (!cloned) {
|
|
@@ -5812,7 +6114,7 @@ function makeSourceCommand() {
|
|
|
5812
6114
|
const result = await refreshManifestCache(entry, opts.dev);
|
|
5813
6115
|
logOk(`Indexed ${result.assetsUpdated} of ${result.assetsFound} asset(s) from "${slug}".`);
|
|
5814
6116
|
for (const err of result.errors) logWarn(err);
|
|
5815
|
-
logOk(`Source "${slug}" registered in ${
|
|
6117
|
+
logOk(`Source "${slug}" registered in ${path14.relative(process.cwd(), yamlPath)}.`);
|
|
5816
6118
|
}
|
|
5817
6119
|
);
|
|
5818
6120
|
cmd.command("list").description("List sources registered in this project's skaile.yaml").option("--json", "Output as JSON").action(async (opts) => {
|
|
@@ -5826,8 +6128,8 @@ function makeSourceCommand() {
|
|
|
5826
6128
|
console.log();
|
|
5827
6129
|
console.log(S.heading(" Sources"));
|
|
5828
6130
|
for (const s of sources) {
|
|
5829
|
-
const slug =
|
|
5830
|
-
const cached = existsSync(sourceClonePath(
|
|
6131
|
+
const slug = sourceShortName(s.url);
|
|
6132
|
+
const cached = existsSync(sourceClonePath(sourceCacheKey(s.url))) ? "" : S.warn(" (not cached)");
|
|
5831
6133
|
console.log(` ${S.cmd(slug.padEnd(24))} ${S.dim(s.url)}${cached}`);
|
|
5832
6134
|
}
|
|
5833
6135
|
console.log(`
|
|
@@ -5841,14 +6143,15 @@ function makeSourceCommand() {
|
|
|
5841
6143
|
logErr(`No source matching "${key}" in ${yamlPath}.`);
|
|
5842
6144
|
process.exit(1);
|
|
5843
6145
|
}
|
|
5844
|
-
const slug =
|
|
6146
|
+
const slug = sourceShortName(entry.url);
|
|
6147
|
+
const clonePath = sourceClonePath(sourceCacheKey(entry.url));
|
|
5845
6148
|
console.log(
|
|
5846
6149
|
JSON.stringify(
|
|
5847
6150
|
{
|
|
5848
6151
|
...entry,
|
|
5849
6152
|
slug,
|
|
5850
|
-
clonePath
|
|
5851
|
-
cached: existsSync(
|
|
6153
|
+
clonePath,
|
|
6154
|
+
cached: existsSync(clonePath)
|
|
5852
6155
|
},
|
|
5853
6156
|
null,
|
|
5854
6157
|
2
|
|
@@ -5863,10 +6166,10 @@ function makeSourceCommand() {
|
|
|
5863
6166
|
logErr(`No source matching "${key}" in ${yamlPath}.`);
|
|
5864
6167
|
process.exit(1);
|
|
5865
6168
|
}
|
|
5866
|
-
const slug =
|
|
6169
|
+
const slug = sourceShortName(match.url);
|
|
5867
6170
|
editor.removeSource(match.url);
|
|
5868
6171
|
editor.save();
|
|
5869
|
-
await dropManifestCache(
|
|
6172
|
+
await dropManifestCache(match.url, opts.purge);
|
|
5870
6173
|
logOk(
|
|
5871
6174
|
opts.purge ? `Removed source "${slug}" and purged its clone.` : `Removed source "${slug}" from skaile.yaml (clone left in ~/.skaile/cache/sources/).`
|
|
5872
6175
|
);
|
|
@@ -5890,7 +6193,11 @@ function makeSourceCommand() {
|
|
|
5890
6193
|
} else {
|
|
5891
6194
|
const selected = await p6.multiselect({
|
|
5892
6195
|
message: "Select sources to sync",
|
|
5893
|
-
options: sources.map((s) => ({
|
|
6196
|
+
options: sources.map((s) => ({
|
|
6197
|
+
value: s.url,
|
|
6198
|
+
label: sourceShortName(s.url),
|
|
6199
|
+
hint: s.url
|
|
6200
|
+
})),
|
|
5894
6201
|
required: true
|
|
5895
6202
|
});
|
|
5896
6203
|
if (p6.isCancel(selected)) {
|
|
@@ -5901,8 +6208,8 @@ function makeSourceCommand() {
|
|
|
5901
6208
|
targets = sources.filter((s) => picked.has(s.url));
|
|
5902
6209
|
}
|
|
5903
6210
|
for (const entry of targets) {
|
|
5904
|
-
const slug =
|
|
5905
|
-
const dest = sourceClonePath(
|
|
6211
|
+
const slug = sourceShortName(entry.url);
|
|
6212
|
+
const dest = sourceClonePath(sourceCacheKey(entry.url));
|
|
5906
6213
|
if (!existsSync(dest)) {
|
|
5907
6214
|
ensureClone(entry);
|
|
5908
6215
|
logOk(`${slug}: cloned to ${dest}.`);
|
|
@@ -5940,10 +6247,10 @@ function makeStoreCommand() {
|
|
|
5940
6247
|
if (opts.email) {
|
|
5941
6248
|
const readline2 = await import('readline');
|
|
5942
6249
|
const rl = readline2.createInterface({ input: process.stdin, output: process.stdout });
|
|
5943
|
-
const password = await new Promise((
|
|
6250
|
+
const password = await new Promise((resolve5) => {
|
|
5944
6251
|
rl.question("Password: ", (answer) => {
|
|
5945
6252
|
rl.close();
|
|
5946
|
-
|
|
6253
|
+
resolve5(answer);
|
|
5947
6254
|
});
|
|
5948
6255
|
});
|
|
5949
6256
|
try {
|
|
@@ -6098,7 +6405,7 @@ function printTree(node, prefix = "", isLast = true) {
|
|
|
6098
6405
|
}
|
|
6099
6406
|
function makeTreeCommand() {
|
|
6100
6407
|
return new Command("tree").description("Show full dependency tree").option("--project-dir <path>", "Project directory", process.cwd()).action((opts) => {
|
|
6101
|
-
const am2 = new AssetManager({ projectDir:
|
|
6408
|
+
const am2 = new AssetManager({ projectDir: path14__default.resolve(opts.projectDir) });
|
|
6102
6409
|
const root = am2.tree();
|
|
6103
6410
|
if (root.children.length === 0) {
|
|
6104
6411
|
logInfo("No dependencies in lock file. Run `skaile install` first.");
|
|
@@ -6116,7 +6423,7 @@ function makeUpdateCommand() {
|
|
|
6116
6423
|
try {
|
|
6117
6424
|
const catalogSpinner = p6.spinner();
|
|
6118
6425
|
catalogSpinner.start("Refreshing catalog cache");
|
|
6119
|
-
const remote = await openCatalogSource({ projectDir:
|
|
6426
|
+
const remote = await openCatalogSource({ projectDir: path14__default.resolve(opts.projectDir) });
|
|
6120
6427
|
const result2 = await remote.refresh();
|
|
6121
6428
|
catalogSpinner.stop(
|
|
6122
6429
|
`Catalog refreshed: ${S.heading(String(result2.assetsCached))} assets cached`
|
|
@@ -6128,7 +6435,7 @@ function makeUpdateCommand() {
|
|
|
6128
6435
|
}
|
|
6129
6436
|
}
|
|
6130
6437
|
if (opts.catalogOnly) return;
|
|
6131
|
-
const am2 = new AssetManager({ projectDir:
|
|
6438
|
+
const am2 = new AssetManager({ projectDir: path14__default.resolve(opts.projectDir) });
|
|
6132
6439
|
const spinner5 = p6.spinner();
|
|
6133
6440
|
spinner5.start("Re-deploying assets");
|
|
6134
6441
|
const result = await am2.install();
|
|
@@ -6162,12 +6469,12 @@ function findManifestCandidates(rootPath) {
|
|
|
6162
6469
|
function walk(dir) {
|
|
6163
6470
|
let entries;
|
|
6164
6471
|
try {
|
|
6165
|
-
entries =
|
|
6472
|
+
entries = fs12__default.readdirSync(dir, { withFileTypes: true });
|
|
6166
6473
|
} catch {
|
|
6167
6474
|
return;
|
|
6168
6475
|
}
|
|
6169
6476
|
for (const entry of entries) {
|
|
6170
|
-
const fullPath =
|
|
6477
|
+
const fullPath = path14__default.join(dir, entry.name);
|
|
6171
6478
|
if (entry.isDirectory()) {
|
|
6172
6479
|
if (!SKIP_DIRS.has(entry.name)) walk(fullPath);
|
|
6173
6480
|
} else if (entry.isFile()) {
|
|
@@ -6208,7 +6515,7 @@ function checkManifestIdentity(kind, parsed) {
|
|
|
6208
6515
|
return null;
|
|
6209
6516
|
}
|
|
6210
6517
|
function parseManifestCandidate(c, absRoot) {
|
|
6211
|
-
const content =
|
|
6518
|
+
const content = fs12__default.readFileSync(c.filePath, "utf-8");
|
|
6212
6519
|
if (c.filePath.endsWith(".md")) {
|
|
6213
6520
|
const parsed = parseMdFrontmatter(content);
|
|
6214
6521
|
if (parsed === null) {
|
|
@@ -6220,23 +6527,38 @@ function parseManifestCandidate(c, absRoot) {
|
|
|
6220
6527
|
const parsed = c.filePath.endsWith(".json") ? JSON.parse(content) : parse(content);
|
|
6221
6528
|
return { kind: "value", parsed };
|
|
6222
6529
|
} catch (e) {
|
|
6223
|
-
const relPath =
|
|
6530
|
+
const relPath = path14__default.relative(absRoot, c.filePath);
|
|
6224
6531
|
logErr(`${relPath} \u2014 parse error: ${e instanceof Error ? e.message : String(e)}`);
|
|
6225
6532
|
return { kind: "error" };
|
|
6226
6533
|
}
|
|
6227
6534
|
}
|
|
6228
|
-
function validateManifestCandidate(c, parsed, absRoot, registry) {
|
|
6229
|
-
const relPath =
|
|
6535
|
+
function validateManifestCandidate(c, parsed, absRoot, registry, strictConformance) {
|
|
6536
|
+
const relPath = path14__default.relative(absRoot, c.filePath);
|
|
6230
6537
|
let errors = 0;
|
|
6538
|
+
let warnings = 0;
|
|
6231
6539
|
const identityError = checkManifestIdentity(c.kind, parsed);
|
|
6232
6540
|
if (identityError) {
|
|
6233
6541
|
logErr(`${relPath} [${c.kind}] \u2014 ${identityError}`);
|
|
6234
6542
|
errors++;
|
|
6235
6543
|
}
|
|
6544
|
+
if (c.kind === "skill" && parsed && typeof parsed === "object") {
|
|
6545
|
+
const dirName = path14__default.basename(path14__default.dirname(c.filePath));
|
|
6546
|
+
const findings = checkAgentSkillConformance(parsed, { dirName });
|
|
6547
|
+
for (const f of findings) {
|
|
6548
|
+
const line = `${relPath} [skill conformance] \u2014 ${f.field}: ${f.message}`;
|
|
6549
|
+
if (strictConformance) {
|
|
6550
|
+
logErr(line);
|
|
6551
|
+
errors++;
|
|
6552
|
+
} else {
|
|
6553
|
+
logWarn(line);
|
|
6554
|
+
warnings++;
|
|
6555
|
+
}
|
|
6556
|
+
}
|
|
6557
|
+
}
|
|
6236
6558
|
const provider = registry.getProvider(c.kind);
|
|
6237
6559
|
if (!provider) {
|
|
6238
6560
|
logWarn(`${relPath} [${c.kind}] \u2014 kind "${c.kind}" is not registered, skipping validation`);
|
|
6239
|
-
return { errors, warnings: 1 };
|
|
6561
|
+
return { errors, warnings: warnings + 1 };
|
|
6240
6562
|
}
|
|
6241
6563
|
const result = provider.validateManifest(parsed);
|
|
6242
6564
|
if (!result.ok) {
|
|
@@ -6245,11 +6567,11 @@ function validateManifestCandidate(c, parsed, absRoot, registry) {
|
|
|
6245
6567
|
}
|
|
6246
6568
|
errors += result.errors.length;
|
|
6247
6569
|
}
|
|
6248
|
-
return { errors, warnings
|
|
6570
|
+
return { errors, warnings };
|
|
6249
6571
|
}
|
|
6250
|
-
function validateManifests(rootPath) {
|
|
6251
|
-
const absRoot =
|
|
6252
|
-
if (!
|
|
6572
|
+
function validateManifests(rootPath, strictConformance) {
|
|
6573
|
+
const absRoot = path14__default.resolve(rootPath);
|
|
6574
|
+
if (!fs12__default.existsSync(absRoot)) {
|
|
6253
6575
|
logErr(`Path does not exist: ${absRoot}`);
|
|
6254
6576
|
return { total: 0, errors: 1, warnings: 0 };
|
|
6255
6577
|
}
|
|
@@ -6264,7 +6586,13 @@ function validateManifests(rootPath) {
|
|
|
6264
6586
|
errors++;
|
|
6265
6587
|
continue;
|
|
6266
6588
|
}
|
|
6267
|
-
const delta = validateManifestCandidate(
|
|
6589
|
+
const delta = validateManifestCandidate(
|
|
6590
|
+
c,
|
|
6591
|
+
parseResult.parsed,
|
|
6592
|
+
absRoot,
|
|
6593
|
+
registry,
|
|
6594
|
+
strictConformance
|
|
6595
|
+
);
|
|
6268
6596
|
errors += delta.errors;
|
|
6269
6597
|
warnings += delta.warnings;
|
|
6270
6598
|
}
|
|
@@ -6275,12 +6603,12 @@ function findWorkspaceManifests(rootPath) {
|
|
|
6275
6603
|
function walk(dir) {
|
|
6276
6604
|
let entries;
|
|
6277
6605
|
try {
|
|
6278
|
-
entries =
|
|
6606
|
+
entries = fs12__default.readdirSync(dir, { withFileTypes: true });
|
|
6279
6607
|
} catch {
|
|
6280
6608
|
return;
|
|
6281
6609
|
}
|
|
6282
6610
|
for (const entry of entries) {
|
|
6283
|
-
const full =
|
|
6611
|
+
const full = path14__default.join(dir, entry.name);
|
|
6284
6612
|
if (entry.isDirectory()) {
|
|
6285
6613
|
if (!SKIP_DIRS.has(entry.name)) walk(full);
|
|
6286
6614
|
} else if (entry.isFile() && /(^|\.)skaile\.yaml$/.test(entry.name)) {
|
|
@@ -6343,14 +6671,14 @@ function validateWorkspaceAssets(parsed, relPath) {
|
|
|
6343
6671
|
return errors;
|
|
6344
6672
|
}
|
|
6345
6673
|
function validateWorkspaceManifests(rootPath) {
|
|
6346
|
-
const absRoot =
|
|
6674
|
+
const absRoot = path14__default.resolve(rootPath);
|
|
6347
6675
|
const files = findWorkspaceManifests(absRoot);
|
|
6348
6676
|
let errors = 0;
|
|
6349
6677
|
for (const file of files) {
|
|
6350
|
-
const relPath =
|
|
6678
|
+
const relPath = path14__default.relative(absRoot, file);
|
|
6351
6679
|
let parsed;
|
|
6352
6680
|
try {
|
|
6353
|
-
parsed = parse(
|
|
6681
|
+
parsed = parse(fs12__default.readFileSync(file, "utf-8")) ?? {};
|
|
6354
6682
|
} catch (e) {
|
|
6355
6683
|
logErr(`${relPath} \u2014 parse error: ${e instanceof Error ? e.message : String(e)}`);
|
|
6356
6684
|
errors++;
|
|
@@ -6364,34 +6692,34 @@ function validateWorkspaceManifests(rootPath) {
|
|
|
6364
6692
|
var EXCLUDED_DOMAINS = /* @__PURE__ */ new Set(["skaileup-shared", "external", "docs"]);
|
|
6365
6693
|
function collectAssetVersions() {
|
|
6366
6694
|
const assets = [];
|
|
6367
|
-
if (!
|
|
6368
|
-
const domains =
|
|
6695
|
+
if (!fs12__default.existsSync(AI_RESOURCES)) return assets;
|
|
6696
|
+
const domains = fs12__default.readdirSync(AI_RESOURCES, { withFileTypes: true }).filter((d) => d.isDirectory() && !EXCLUDED_DOMAINS.has(d.name));
|
|
6369
6697
|
for (const d of domains) {
|
|
6370
|
-
const domainDir =
|
|
6371
|
-
const skillsDir =
|
|
6372
|
-
if (
|
|
6698
|
+
const domainDir = path14__default.join(AI_RESOURCES, d.name);
|
|
6699
|
+
const skillsDir = path14__default.join(domainDir, "skills");
|
|
6700
|
+
if (fs12__default.existsSync(skillsDir)) {
|
|
6373
6701
|
collectSkillVersions(skillsDir, d.name, assets);
|
|
6374
6702
|
}
|
|
6375
|
-
const agentsDir =
|
|
6376
|
-
if (
|
|
6703
|
+
const agentsDir = path14__default.join(domainDir, "agents");
|
|
6704
|
+
if (fs12__default.existsSync(agentsDir)) {
|
|
6377
6705
|
collectAgentVersions(agentsDir, d.name, assets);
|
|
6378
6706
|
}
|
|
6379
|
-
const flowsDir =
|
|
6380
|
-
if (
|
|
6707
|
+
const flowsDir = path14__default.join(domainDir, "flows");
|
|
6708
|
+
if (fs12__default.existsSync(flowsDir)) {
|
|
6381
6709
|
collectFlowVersions(flowsDir, d.name, assets);
|
|
6382
6710
|
}
|
|
6383
|
-
const promptsDir =
|
|
6384
|
-
if (
|
|
6711
|
+
const promptsDir = path14__default.join(domainDir, "prompts");
|
|
6712
|
+
if (fs12__default.existsSync(promptsDir)) {
|
|
6385
6713
|
collectPromptVersions(promptsDir, d.name, assets);
|
|
6386
6714
|
}
|
|
6387
6715
|
}
|
|
6388
6716
|
return assets;
|
|
6389
6717
|
}
|
|
6390
6718
|
function collectFlowVersions(dir, domain, out) {
|
|
6391
|
-
for (const f of
|
|
6719
|
+
for (const f of fs12__default.readdirSync(dir)) {
|
|
6392
6720
|
if (!f.endsWith(".flow.yaml")) continue;
|
|
6393
|
-
const fp =
|
|
6394
|
-
const content =
|
|
6721
|
+
const fp = path14__default.join(dir, f);
|
|
6722
|
+
const content = fs12__default.readFileSync(fp, "utf-8");
|
|
6395
6723
|
const parsed = parse(content);
|
|
6396
6724
|
out.push({
|
|
6397
6725
|
kind: "flow",
|
|
@@ -6403,10 +6731,10 @@ function collectFlowVersions(dir, domain, out) {
|
|
|
6403
6731
|
}
|
|
6404
6732
|
}
|
|
6405
6733
|
function collectPromptVersions(dir, domain, out) {
|
|
6406
|
-
for (const f of
|
|
6734
|
+
for (const f of fs12__default.readdirSync(dir)) {
|
|
6407
6735
|
if (!f.endsWith(".prompt.md")) continue;
|
|
6408
|
-
const fp =
|
|
6409
|
-
const content =
|
|
6736
|
+
const fp = path14__default.join(dir, f);
|
|
6737
|
+
const content = fs12__default.readFileSync(fp, "utf-8");
|
|
6410
6738
|
const fm = parseSkillFrontmatter(content);
|
|
6411
6739
|
out.push({
|
|
6412
6740
|
kind: "prompt",
|
|
@@ -6418,12 +6746,12 @@ function collectPromptVersions(dir, domain, out) {
|
|
|
6418
6746
|
}
|
|
6419
6747
|
}
|
|
6420
6748
|
function collectSkillVersions(dir, domain, out) {
|
|
6421
|
-
for (const entry of
|
|
6749
|
+
for (const entry of fs12__default.readdirSync(dir, { withFileTypes: true })) {
|
|
6422
6750
|
if (!entry.isDirectory()) continue;
|
|
6423
|
-
const full =
|
|
6424
|
-
const skillMd =
|
|
6425
|
-
if (
|
|
6426
|
-
const content =
|
|
6751
|
+
const full = path14__default.join(dir, entry.name);
|
|
6752
|
+
const skillMd = path14__default.join(full, "SKILL.md");
|
|
6753
|
+
if (fs12__default.existsSync(skillMd)) {
|
|
6754
|
+
const content = fs12__default.readFileSync(skillMd, "utf-8");
|
|
6427
6755
|
const fm = parseSkillFrontmatter(content);
|
|
6428
6756
|
out.push({
|
|
6429
6757
|
kind: "skill",
|
|
@@ -6438,11 +6766,11 @@ function collectSkillVersions(dir, domain, out) {
|
|
|
6438
6766
|
}
|
|
6439
6767
|
}
|
|
6440
6768
|
function collectAgentVersions(dir, domain, out) {
|
|
6441
|
-
for (const entry of
|
|
6769
|
+
for (const entry of fs12__default.readdirSync(dir, { withFileTypes: true })) {
|
|
6442
6770
|
if (!entry.isDirectory()) continue;
|
|
6443
|
-
const agentYaml =
|
|
6444
|
-
if (!
|
|
6445
|
-
const content =
|
|
6771
|
+
const agentYaml = path14__default.join(dir, entry.name, "agent.yaml");
|
|
6772
|
+
if (!fs12__default.existsSync(agentYaml)) continue;
|
|
6773
|
+
const content = fs12__default.readFileSync(agentYaml, "utf-8");
|
|
6446
6774
|
const parsed = parse(content);
|
|
6447
6775
|
out.push({
|
|
6448
6776
|
kind: "agent",
|
|
@@ -6473,7 +6801,7 @@ function filterToChangedAssets(assets) {
|
|
|
6473
6801
|
encoding: "utf-8"
|
|
6474
6802
|
});
|
|
6475
6803
|
const changedFiles = new Set(
|
|
6476
|
-
diffOutput.trim().split("\n").filter(Boolean).map((f) =>
|
|
6804
|
+
diffOutput.trim().split("\n").filter(Boolean).map((f) => path14__default.resolve(AI_RESOURCES, f))
|
|
6477
6805
|
);
|
|
6478
6806
|
return assets.filter((a) => changedFiles.has(a.filePath));
|
|
6479
6807
|
} catch {
|
|
@@ -6499,7 +6827,7 @@ function checkVersionBumps(assets) {
|
|
|
6499
6827
|
let warnings = 0;
|
|
6500
6828
|
for (const a of assets) {
|
|
6501
6829
|
if (!a.version) continue;
|
|
6502
|
-
const relPath =
|
|
6830
|
+
const relPath = path14__default.relative(AI_RESOURCES, a.filePath);
|
|
6503
6831
|
try {
|
|
6504
6832
|
const headContent = execSync(`git show HEAD:${relPath}`, {
|
|
6505
6833
|
cwd: AI_RESOURCES,
|
|
@@ -6525,7 +6853,7 @@ function checkFlowVersionPins(assets) {
|
|
|
6525
6853
|
}
|
|
6526
6854
|
let errors = 0;
|
|
6527
6855
|
for (const f of flows) {
|
|
6528
|
-
const content =
|
|
6856
|
+
const content = fs12__default.readFileSync(f.filePath, "utf-8");
|
|
6529
6857
|
const parsed = parse(content);
|
|
6530
6858
|
const nodes = (parsed?.nodes ?? []).filter((n) => n.type === "skill" && n.data?.version).map((n) => ({
|
|
6531
6859
|
nodeId: n.id,
|
|
@@ -6571,14 +6899,21 @@ function makeValidateCommand() {
|
|
|
6571
6899
|
const cmd = new Command("validate").description(
|
|
6572
6900
|
"Validate asset manifests, versions, and changelogs"
|
|
6573
6901
|
);
|
|
6574
|
-
cmd.argument("[path]", "Path to asset repo or directory to validate", ".").
|
|
6575
|
-
|
|
6902
|
+
cmd.argument("[path]", "Path to asset repo or directory to validate", ".").option(
|
|
6903
|
+
"--strict-conformance",
|
|
6904
|
+
"Treat Agent Skills (agentskills.io) standard findings as errors"
|
|
6905
|
+
).action((targetPath, opts) => {
|
|
6906
|
+
const absPath = path14__default.resolve(targetPath);
|
|
6576
6907
|
logInfo(`Validating manifests in ${absPath}`);
|
|
6577
|
-
const { total, errors } = validateManifests(
|
|
6908
|
+
const { total, errors, warnings } = validateManifests(
|
|
6909
|
+
absPath,
|
|
6910
|
+
opts.strictConformance ?? false
|
|
6911
|
+
);
|
|
6578
6912
|
const ws = validateWorkspaceManifests(absPath);
|
|
6579
6913
|
const totalErrors = errors + ws.errors;
|
|
6580
6914
|
console.log();
|
|
6581
6915
|
logInfo(`Scanned ${total} asset manifest(s) and ${ws.total} skaile.yaml file(s)`);
|
|
6916
|
+
if (warnings > 0) logWarn(`${warnings} conformance warning(s)`);
|
|
6582
6917
|
if (totalErrors === 0) {
|
|
6583
6918
|
logOk("All manifests valid");
|
|
6584
6919
|
} else {
|
|
@@ -6618,7 +6953,7 @@ function makeValidateCommand() {
|
|
|
6618
6953
|
let errors = 0;
|
|
6619
6954
|
for (const domain of modifiedDomains) {
|
|
6620
6955
|
const changelogModified = modifiedFiles.some(
|
|
6621
|
-
(f) => f === `${domain}/CHANGELOG.md` || f ===
|
|
6956
|
+
(f) => f === `${domain}/CHANGELOG.md` || f === path14__default.join(domain, "CHANGELOG.md")
|
|
6622
6957
|
);
|
|
6623
6958
|
if (changelogModified) {
|
|
6624
6959
|
logOk(`${domain}/CHANGELOG.md updated`);
|
|
@@ -6700,7 +7035,7 @@ function makeVerifyCommand() {
|
|
|
6700
7035
|
}
|
|
6701
7036
|
function makeWhyCommand() {
|
|
6702
7037
|
return new Command("why").description("Show why an asset is installed (dependency chain)").argument("<ref>", "Asset reference (kind:name)").option("--project-dir <path>", "Project directory", process.cwd()).action((ref, opts) => {
|
|
6703
|
-
const am2 = new AssetManager({ projectDir:
|
|
7038
|
+
const am2 = new AssetManager({ projectDir: path14__default.resolve(opts.projectDir) });
|
|
6704
7039
|
const chain = am2.why(ref);
|
|
6705
7040
|
if (chain.length === 0) {
|
|
6706
7041
|
logErr(`${ref} not found in lock file. Run \`skaile install\` first.`);
|
|
@@ -6721,7 +7056,7 @@ function makeWhyCommand() {
|
|
|
6721
7056
|
var _defaultFormatHelp = Help.prototype.formatHelp;
|
|
6722
7057
|
var pkg = JSON.parse(
|
|
6723
7058
|
readFileSync(
|
|
6724
|
-
|
|
7059
|
+
path14__default.resolve(path14__default.dirname(fileURLToPath(import.meta.url)), "../../package.json"),
|
|
6725
7060
|
"utf-8"
|
|
6726
7061
|
)
|
|
6727
7062
|
);
|
|
@@ -6842,7 +7177,7 @@ program.command("init [project-dir]").description("Initialize a project director
|
|
|
6842
7177
|
(projectDir, opts) => runInit(projectDir, opts)
|
|
6843
7178
|
);
|
|
6844
7179
|
async function runInit(projectDir, opts) {
|
|
6845
|
-
const { mkdirSync:
|
|
7180
|
+
const { mkdirSync: mkdirSync6, writeFileSync: writeFileSync4 } = await import('fs');
|
|
6846
7181
|
const { stringify } = await import('yaml');
|
|
6847
7182
|
const { DRIVER_TARGETS, SUPPORTED_DRIVER_TARGETS: SUPPORTED_DRIVER_TARGETS2 } = await import('../core/index.js');
|
|
6848
7183
|
const backend = opts.backend;
|
|
@@ -6851,33 +7186,33 @@ async function runInit(projectDir, opts) {
|
|
|
6851
7186
|
process.exitCode = 1;
|
|
6852
7187
|
return;
|
|
6853
7188
|
}
|
|
6854
|
-
const resolved =
|
|
6855
|
-
const projectName =
|
|
7189
|
+
const resolved = path14__default.resolve(projectDir ?? ".");
|
|
7190
|
+
const projectName = path14__default.basename(resolved);
|
|
6856
7191
|
const created = [];
|
|
6857
|
-
const { existsSync:
|
|
6858
|
-
if (!
|
|
6859
|
-
|
|
7192
|
+
const { existsSync: existsSync14 } = await import('fs');
|
|
7193
|
+
if (!existsSync14(resolved)) {
|
|
7194
|
+
mkdirSync6(resolved, { recursive: true });
|
|
6860
7195
|
created.push(".");
|
|
6861
7196
|
}
|
|
6862
|
-
const skaileDir =
|
|
6863
|
-
if (!
|
|
6864
|
-
|
|
7197
|
+
const skaileDir = path14__default.join(resolved, ".skaile");
|
|
7198
|
+
if (!existsSync14(skaileDir)) {
|
|
7199
|
+
mkdirSync6(path14__default.join(skaileDir, "sessions"), { recursive: true });
|
|
6865
7200
|
created.push(".skaile/");
|
|
6866
7201
|
}
|
|
6867
|
-
const settingsPath =
|
|
6868
|
-
if (!
|
|
6869
|
-
|
|
7202
|
+
const settingsPath = path14__default.join(skaileDir, "settings.json");
|
|
7203
|
+
if (!existsSync14(settingsPath)) {
|
|
7204
|
+
writeFileSync4(settingsPath, "{}\n");
|
|
6870
7205
|
created.push(".skaile/settings.json");
|
|
6871
7206
|
}
|
|
6872
|
-
const wsConfigPath =
|
|
6873
|
-
if (!
|
|
6874
|
-
|
|
7207
|
+
const wsConfigPath = path14__default.join(resolved, "skaile.yaml");
|
|
7208
|
+
if (!existsSync14(wsConfigPath)) {
|
|
7209
|
+
writeFileSync4(wsConfigPath, stringify(buildInitWorkspaceConfig(projectName, backend)));
|
|
6875
7210
|
created.push("skaile.yaml");
|
|
6876
7211
|
}
|
|
6877
7212
|
for (const dir of new Set(Object.values(DRIVER_TARGETS[backend].local))) {
|
|
6878
|
-
const full =
|
|
6879
|
-
if (!
|
|
6880
|
-
|
|
7213
|
+
const full = path14__default.join(resolved, dir);
|
|
7214
|
+
if (!existsSync14(full)) {
|
|
7215
|
+
mkdirSync6(full, { recursive: true });
|
|
6881
7216
|
created.push(`${dir}/`);
|
|
6882
7217
|
}
|
|
6883
7218
|
}
|
|
@@ -6907,8 +7242,8 @@ function buildInitWorkspaceConfig(projectName, backend) {
|
|
|
6907
7242
|
}
|
|
6908
7243
|
async function initGitScaffold(resolved, created) {
|
|
6909
7244
|
const { execSync: execSync3 } = await import('child_process');
|
|
6910
|
-
const { existsSync:
|
|
6911
|
-
const gitignorePath =
|
|
7245
|
+
const { existsSync: existsSync14, readFileSync: readFileSync8, writeFileSync: writeFileSync4 } = await import('fs');
|
|
7246
|
+
const gitignorePath = path14__default.join(resolved, ".gitignore");
|
|
6912
7247
|
const entries = [
|
|
6913
7248
|
"node_modules/",
|
|
6914
7249
|
".skaile/sessions/",
|
|
@@ -6917,16 +7252,16 @@ async function initGitScaffold(resolved, created) {
|
|
|
6917
7252
|
".env",
|
|
6918
7253
|
".env.local"
|
|
6919
7254
|
];
|
|
6920
|
-
const existing =
|
|
7255
|
+
const existing = existsSync14(gitignorePath) ? readFileSync8(gitignorePath, "utf-8") : "";
|
|
6921
7256
|
const have = new Set(existing.split("\n").map((l) => l.trim()));
|
|
6922
7257
|
const append = entries.filter((e) => !have.has(e));
|
|
6923
7258
|
if (append.length > 0) {
|
|
6924
7259
|
const prefix = existing && !existing.endsWith("\n") ? "\n" : "";
|
|
6925
|
-
|
|
7260
|
+
writeFileSync4(gitignorePath, `${existing + prefix}${append.join("\n")}
|
|
6926
7261
|
`);
|
|
6927
7262
|
if (!existing) created.push(".gitignore");
|
|
6928
7263
|
}
|
|
6929
|
-
if (!
|
|
7264
|
+
if (!existsSync14(path14__default.join(resolved, ".git"))) {
|
|
6930
7265
|
try {
|
|
6931
7266
|
execSync3("git init", { cwd: resolved, stdio: "pipe" });
|
|
6932
7267
|
created.push(".git/");
|
|
@@ -6938,10 +7273,10 @@ async function initGitScaffold(resolved, created) {
|
|
|
6938
7273
|
}
|
|
6939
7274
|
async function bootstrapUserConfig() {
|
|
6940
7275
|
try {
|
|
6941
|
-
const
|
|
7276
|
+
const fs13 = await import('fs');
|
|
6942
7277
|
const { userConfigPath, saveConfig, getConfigDefaults } = await import('../library/index.js');
|
|
6943
7278
|
const userCfgPath = userConfigPath();
|
|
6944
|
-
if (!
|
|
7279
|
+
if (!fs13.existsSync(userCfgPath)) {
|
|
6945
7280
|
const defaults = getConfigDefaults();
|
|
6946
7281
|
saveConfig(userCfgPath, {
|
|
6947
7282
|
catalog: { url: defaults.catalog.url, cache_ttl: defaults.catalog.cache_ttl }
|
|
@@ -6956,7 +7291,7 @@ async function bootstrapUserConfig() {
|
|
|
6956
7291
|
}
|
|
6957
7292
|
async function hydrateInitSources(resolved, created) {
|
|
6958
7293
|
try {
|
|
6959
|
-
const { ensureSourcesCloned } = await import('../ensure-sources-
|
|
7294
|
+
const { ensureSourcesCloned } = await import('../ensure-sources-KLCGXVE6.js');
|
|
6960
7295
|
const hydrate = ensureSourcesCloned(resolved, { quiet: true });
|
|
6961
7296
|
for (const n of hydrate.cloned) created.push(`~/.skaile/cache/sources/${n}/`);
|
|
6962
7297
|
if (hydrate.failed.length > 0) {
|
|
@@ -6972,7 +7307,7 @@ function printInitSummary(resolved, projectDir, created) {
|
|
|
6972
7307
|
logOk(`Initialized project at ${S.heading(resolved)}`);
|
|
6973
7308
|
console.log();
|
|
6974
7309
|
console.log(S.heading(" Next steps:"));
|
|
6975
|
-
const isCurrentDir = resolved ===
|
|
7310
|
+
const isCurrentDir = resolved === path14__default.resolve(".");
|
|
6976
7311
|
let step = 1;
|
|
6977
7312
|
if (!isCurrentDir) {
|
|
6978
7313
|
console.log(` ${S.dim(`${step}.`)} ${S.cmd(`cd ${projectDir}`)}`);
|
|
@@ -6984,7 +7319,7 @@ function printInitSummary(resolved, projectDir, created) {
|
|
|
6984
7319
|
console.log();
|
|
6985
7320
|
}
|
|
6986
7321
|
program.command("setup").description("Interactive provider setup wizard").action(async () => {
|
|
6987
|
-
const { cmdSetup } = await import('../setup-
|
|
7322
|
+
const { cmdSetup } = await import('../setup-AYH6SR4U.js');
|
|
6988
7323
|
await cmdSetup([], { projectDir: process.cwd() });
|
|
6989
7324
|
});
|
|
6990
7325
|
program.addCommand(makeInstallCommand());
|