@skaile/workspaces 0.43.1 → 0.45.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 +101 -0
- package/dist/{asset-feeds-3PSV57NT.js → asset-feeds-AOZLZMDV.js} +15 -11
- package/dist/asset-feeds-AOZLZMDV.js.map +1 -0
- package/dist/asset-manager/index.js +5 -5
- package/dist/asset-manager/installer.js +4 -4
- package/dist/asset-manager/src/index.d.ts +149 -4
- package/dist/asset-manager/src/index.d.ts.map +1 -1
- package/dist/{chunk-KYQNWFJV.js → chunk-BLGHFVXE.js} +3 -3
- package/dist/{chunk-KYQNWFJV.js.map → chunk-BLGHFVXE.js.map} +1 -1
- package/dist/{chunk-R4H6EJW5.js → chunk-CBZEIFU4.js} +3 -3
- package/dist/{chunk-R4H6EJW5.js.map → chunk-CBZEIFU4.js.map} +1 -1
- package/dist/{chunk-GJI6FZ56.js → chunk-COSTF7QW.js} +60 -8
- package/dist/chunk-COSTF7QW.js.map +1 -0
- package/dist/{chunk-NYMRKIOR.js → chunk-CVWA4RIK.js} +4 -4
- package/dist/{chunk-NYMRKIOR.js.map → chunk-CVWA4RIK.js.map} +1 -1
- package/dist/{chunk-BXYMGZCI.js → chunk-ETDXTGDF.js} +3 -3
- package/dist/{chunk-BXYMGZCI.js.map → chunk-ETDXTGDF.js.map} +1 -1
- package/dist/{chunk-TDSRLMDB.js → chunk-EVZKWY5J.js} +2 -2
- package/dist/chunk-EVZKWY5J.js.map +1 -0
- package/dist/{chunk-3HUUP3JC.js → chunk-FYLIR4AV.js} +107 -7
- package/dist/chunk-FYLIR4AV.js.map +1 -0
- package/dist/{chunk-G6FJZG4C.js → chunk-GM3BV6JK.js} +2 -2
- package/dist/{chunk-G6FJZG4C.js.map → chunk-GM3BV6JK.js.map} +1 -1
- package/dist/{chunk-R4YUZRGF.js → chunk-JUZGLINM.js} +2 -2
- package/dist/{chunk-R4YUZRGF.js.map → chunk-JUZGLINM.js.map} +1 -1
- package/dist/{chunk-WKZ5R4NP.js → chunk-L6BKSTAX.js} +332 -38
- package/dist/chunk-L6BKSTAX.js.map +1 -0
- package/dist/{chunk-WRDHUTOK.js → chunk-LHUCCPH4.js} +5 -5
- package/dist/{chunk-WRDHUTOK.js.map → chunk-LHUCCPH4.js.map} +1 -1
- package/dist/{chunk-U2XHHLE3.js → chunk-LMRO2QNF.js} +5 -5
- package/dist/{chunk-U2XHHLE3.js.map → chunk-LMRO2QNF.js.map} +1 -1
- package/dist/{chunk-N4FSBCLV.js → chunk-N2KV5RK3.js} +127 -10
- package/dist/chunk-N2KV5RK3.js.map +1 -0
- package/dist/{chunk-CIEKKLMG.js → chunk-PCXU2CVW.js} +3 -3
- package/dist/{chunk-CIEKKLMG.js.map → chunk-PCXU2CVW.js.map} +1 -1
- package/dist/{chunk-HVCZLD5Z.js → chunk-VPXV2Z5E.js} +5 -7
- package/dist/chunk-VPXV2Z5E.js.map +1 -0
- package/dist/{chunk-2BEDUMTA.js → chunk-XF2BBX6P.js} +3 -3
- package/dist/{chunk-2BEDUMTA.js.map → chunk-XF2BBX6P.js.map} +1 -1
- package/dist/{chunk-3K2CYDBT.js → chunk-Z5Z3MYDL.js} +8 -4
- package/dist/chunk-Z5Z3MYDL.js.map +1 -0
- package/dist/{chunk-M54RYUXY.js → chunk-ZAEJ33Y6.js} +19 -7
- package/dist/chunk-ZAEJ33Y6.js.map +1 -0
- package/dist/cli/index.js +969 -572
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/src/asset-feeds.d.ts.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/cache.d.ts +27 -0
- package/dist/cli/src/commands/cache.d.ts.map +1 -0
- package/dist/cli/src/commands/catalog.d.ts +9 -3
- 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/manage.d.ts.map +1 -1
- package/dist/cli/src/commands/npx.d.ts +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 +3 -1
- package/dist/cli/src/commands/source.d.ts.map +1 -1
- package/dist/cli/src/commands/update.d.ts +1 -1
- package/dist/cli/src/ensure-sources.d.ts +2 -2
- package/dist/cli/src/ensure-sources.d.ts.map +1 -1
- package/dist/connectors/config.js +4 -4
- package/dist/connectors/index.js +6 -6
- package/dist/connectors/rclone.js +1 -1
- package/dist/connectors/src/rclone-process-manager.d.ts +57 -2
- package/dist/connectors/src/rclone-process-manager.d.ts.map +1 -1
- package/dist/core/index.js +3 -3
- package/dist/core/runtime-assets.js +2 -2
- package/dist/core/src/cache-paths.d.ts +25 -0
- package/dist/core/src/cache-paths.d.ts.map +1 -0
- package/dist/core/src/index.d.ts +2 -1
- package/dist/core/src/index.d.ts.map +1 -1
- package/dist/core/src/repo-manager.d.ts +11 -8
- 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 +2 -2
- 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/{ensure-sources-VQDZB7NT.js → ensure-sources-NSDMTAWN.js} +6 -12
- package/dist/ensure-sources-NSDMTAWN.js.map +1 -0
- package/dist/factory-assets/connectors/deploy.js +6 -6
- package/dist/factory-assets/connectors/devserver.js +6 -6
- package/dist/factory-assets/connectors/flow/adapter.js +6 -6
- package/dist/factory-assets/connectors/flow/engine.js +3 -3
- package/dist/factory-assets/connectors/flow/run-flow.js +7 -7
- package/dist/factory-assets/connectors/flow.js +6 -6
- package/dist/factory-assets/connectors/git.js +6 -6
- package/dist/factory-assets/connectors/gmail.js +6 -6
- package/dist/factory-assets/connectors/googledrive.js +6 -6
- package/dist/factory-assets/connectors/local.js +6 -6
- package/dist/factory-assets/connectors/mattermost.js +6 -6
- package/dist/factory-assets/connectors/memory.js +6 -6
- package/dist/factory-assets/connectors/minio.js +6 -6
- package/dist/factory-assets/connectors/postgres.js +6 -6
- package/dist/factory-assets/connectors/s3.js +6 -6
- package/dist/factory-assets/connectors/sharepoint.js +6 -6
- package/dist/factory-assets/connectors/sqlite.js +6 -6
- package/dist/factory-assets/connectors/static-server.js +6 -6
- package/dist/factory-assets/connectors/tunnel.js +6 -6
- package/dist/factory-assets/connectors/webdav.js +6 -6
- package/dist/factory-assets/connectors/xstate-store.js +6 -6
- package/dist/factory-assets/connectors/xstate.js +6 -6
- package/dist/factory-assets/skaile.manifest.yaml +3 -0
- package/dist/factory-assets/skills/skailify/SKILL.md +84 -0
- package/dist/{flows-KTBCZ5GQ.js → flows-WELXQ7IG.js} +3 -3
- package/dist/{flows-KTBCZ5GQ.js.map → flows-WELXQ7IG.js.map} +1 -1
- package/dist/library/index.js +4 -4
- package/dist/library/install.js +3 -3
- package/dist/library/src/local/local-catalog-source.d.ts +1 -1
- package/dist/library/src/local/sidecar-git.d.ts +2 -2
- package/dist/library/src/local/sidecar-paths.d.ts +12 -10
- package/dist/library/src/local/sidecar-paths.d.ts.map +1 -1
- package/dist/library/src/local/store-paths.d.ts +2 -2
- package/dist/library/src/remote/cache.d.ts +8 -2
- package/dist/library/src/remote/cache.d.ts.map +1 -1
- package/dist/library/src/remote/remote-catalog-source.d.ts +1 -1
- package/dist/library/src/remote/rest-catalog-source.d.ts +1 -1
- package/dist/{open-library-FHUXOCN7.js → open-library-362BZ6OW.js} +7 -7
- package/dist/{open-library-FHUXOCN7.js.map → open-library-362BZ6OW.js.map} +1 -1
- package/dist/{paths-7H5CSBLQ.js → paths-4SSFMX5Z.js} +6 -6
- package/dist/{paths-7H5CSBLQ.js.map → paths-4SSFMX5Z.js.map} +1 -1
- package/dist/{plugin-store-LGLN2QUX.js → plugin-store-2X2YXJVG.js} +5 -5
- package/dist/{plugin-store-LGLN2QUX.js.map → plugin-store-2X2YXJVG.js.map} +1 -1
- package/dist/runner/index.js +9 -9
- 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 +5 -5
- package/dist/sdk/core.js +3 -3
- package/dist/sdk/flow.js +3 -3
- package/dist/sdk/index.js +9 -9
- package/dist/sdk/runner.js +9 -9
- package/dist/sdk/session.js +2 -2
- package/dist/sdk/types.js +1 -1
- package/dist/session/index.js +2 -2
- package/dist/session/src/index.d.ts +1 -1
- package/dist/session/src/index.d.ts.map +1 -1
- package/dist/session/src/mentions.d.ts +11 -0
- package/dist/session/src/mentions.d.ts.map +1 -1
- package/dist/{setup-EVNPECSY.js → setup-VGZTFQ32.js} +5 -5
- package/dist/{setup-EVNPECSY.js.map → setup-VGZTFQ32.js.map} +1 -1
- package/dist/{store-client-4XN7IB3R.js → store-client-XFZFKY3W.js} +6 -6
- package/dist/{store-client-4XN7IB3R.js.map → store-client-XFZFKY3W.js.map} +1 -1
- package/dist/tui/index.js +9 -9
- package/dist/types/index.js +1 -1
- package/dist/types/src/mentions.d.ts +12 -0
- package/dist/types/src/mentions.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/asset-feeds-3PSV57NT.js.map +0 -1
- package/dist/chunk-3HUUP3JC.js.map +0 -1
- package/dist/chunk-3K2CYDBT.js.map +0 -1
- package/dist/chunk-GJI6FZ56.js.map +0 -1
- package/dist/chunk-HVCZLD5Z.js.map +0 -1
- package/dist/chunk-M54RYUXY.js.map +0 -1
- package/dist/chunk-N4FSBCLV.js.map +0 -1
- package/dist/chunk-TDSRLMDB.js.map +0 -1
- package/dist/chunk-WKZ5R4NP.js.map +0 -1
- package/dist/ensure-sources-VQDZB7NT.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-PCXU2CVW.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-XF2BBX6P.js';
|
|
5
|
+
import { AI_RESOURCES, aiResourceRoots } from '../chunk-ETDXTGDF.js';
|
|
6
6
|
import { LocalSecretsProvider } from '../chunk-6BEGKO2Q.js';
|
|
7
|
-
import { resolveLibraryDir, LocalCatalogSource
|
|
7
|
+
import { resolveLibraryDir, LocalCatalogSource } from '../chunk-ZAEJ33Y6.js';
|
|
8
8
|
import '../chunk-5FVJXQDP.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-LHUCCPH4.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-N2KV5RK3.js';
|
|
16
|
+
import { buildClaudePluginFiles } from '../chunk-JUZGLINM.js';
|
|
17
17
|
import '../chunk-X5YPJV4N.js';
|
|
18
18
|
import '../chunk-O7SG5PC2.js';
|
|
19
19
|
import '../chunk-7QBNJTTQ.js';
|
|
@@ -21,30 +21,30 @@ import '../chunk-GTS2FODO.js';
|
|
|
21
21
|
import '../chunk-WQ7DE5UC.js';
|
|
22
22
|
import '../chunk-32NA4TVC.js';
|
|
23
23
|
import '../chunk-W3UDISS2.js';
|
|
24
|
-
import '../chunk-
|
|
24
|
+
import '../chunk-EVZKWY5J.js';
|
|
25
25
|
import '../chunk-5C3QJSOD.js';
|
|
26
26
|
import '../chunk-RRVQAE5D.js';
|
|
27
27
|
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-LMRO2QNF.js';
|
|
32
32
|
import '../chunk-OVRSNIKJ.js';
|
|
33
|
-
import '../chunk-
|
|
34
|
-
import '../chunk-
|
|
33
|
+
import '../chunk-CBZEIFU4.js';
|
|
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 } 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-L6BKSTAX.js';
|
|
40
|
+
import '../chunk-CVWA4RIK.js';
|
|
41
|
+
import { readLock, resolveSettings, globalSettingsPath, projectSettingsPath, loadSettings, saveSettings, portableSpawn, portableSpawnSync, WorkspaceYamlEditor } from '../chunk-BLGHFVXE.js';
|
|
42
42
|
import { assetSearchDirs, detectDomains } from '../chunk-ZAP2BDHG.js';
|
|
43
|
-
import '../chunk-
|
|
44
|
-
import { resolveAgentDir, findWorkspaceRoot, workspaceConfigFilename, resolveSkWorkspaceConfig } from '../chunk-
|
|
45
|
-
import { SKAILE_MANIFEST_FILENAME, decodeSkaileManifest } from '../chunk-DZCK7GRW.js';
|
|
43
|
+
import '../chunk-VPXV2Z5E.js';
|
|
44
|
+
import { globalCacheRoot, getGlobalCacheDir, resolveAgentDir, findWorkspaceRoot, workspaceConfigFilename, resolveSkWorkspaceConfig } from '../chunk-COSTF7QW.js';
|
|
45
|
+
import { SKAILE_MANIFEST_FILENAME, decodeSkaileManifest, loadSkPublishManifest, saveSkPublishManifest } from '../chunk-DZCK7GRW.js';
|
|
46
46
|
import { parseFrontmatter } from '../chunk-6IDBWPK2.js';
|
|
47
|
-
import {
|
|
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';
|
|
@@ -55,217 +55,24 @@ import '../chunk-XUXVH3JK.js';
|
|
|
55
55
|
import '../chunk-RGPBEGP2.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, 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 * as
|
|
64
|
+
import * as p6 from '@clack/prompts';
|
|
65
65
|
import pc5 from 'picocolors';
|
|
66
|
+
import * as os from 'os';
|
|
67
|
+
import { homedir } from 'os';
|
|
68
|
+
import { parse, stringify } from 'yaml';
|
|
66
69
|
import * as readline from 'readline';
|
|
67
70
|
import { createInterface } from 'readline';
|
|
68
|
-
import
|
|
69
|
-
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';
|
|
70
73
|
import { execSync, spawnSync } from 'child_process';
|
|
71
|
-
import { homedir } from 'os';
|
|
72
74
|
import { createTRPCUntypedClient, httpLink, httpSubscriptionLink } from '@trpc/client';
|
|
73
|
-
import { parse } from 'yaml';
|
|
74
75
|
|
|
75
|
-
function makeAssetCommand() {
|
|
76
|
-
const cmd = new Command("asset").description("Author and install AI assets");
|
|
77
|
-
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
|
-
async (srcPath, opts) => {
|
|
79
|
-
if (!["copy", "move", "link"].includes(opts.mode)) {
|
|
80
|
-
logErr(`Invalid --mode "${opts.mode}". Expected: copy | move | link.`);
|
|
81
|
-
process.exit(1);
|
|
82
|
-
}
|
|
83
|
-
if (!fs11.existsSync(srcPath)) {
|
|
84
|
-
logErr(`Source path does not exist: ${srcPath}`);
|
|
85
|
-
process.exit(1);
|
|
86
|
-
}
|
|
87
|
-
const { manager, close } = await openLibraryManager();
|
|
88
|
-
try {
|
|
89
|
-
let target;
|
|
90
|
-
if (opts.to) {
|
|
91
|
-
target = await manager.requireLibrary(opts.to);
|
|
92
|
-
} else {
|
|
93
|
-
const all = await manager.listLibraries();
|
|
94
|
-
const def = all.find(
|
|
95
|
-
(l) => l.isDefault && (l.ownership === "owner" || l.ownership === "contributor")
|
|
96
|
-
);
|
|
97
|
-
if (def) {
|
|
98
|
-
target = def;
|
|
99
|
-
} else {
|
|
100
|
-
const res = await manager.ensurePersonalLibrary(resolveLibraryDir());
|
|
101
|
-
target = res.library;
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
if (target.ownership === "reader") {
|
|
105
|
-
logErr(
|
|
106
|
-
`Library "${target.name}" is read-only (ownership=reader). Choose another with --to.`
|
|
107
|
-
);
|
|
108
|
-
process.exit(1);
|
|
109
|
-
}
|
|
110
|
-
const basename2 = path12.basename(srcPath);
|
|
111
|
-
const destDir = target.structure === "domain" && opts.domain ? path12.join(target.path, opts.domain) : target.path;
|
|
112
|
-
fs11.mkdirSync(destDir, { recursive: true });
|
|
113
|
-
const destPath = path12.join(destDir, basename2);
|
|
114
|
-
if (fs11.existsSync(destPath)) {
|
|
115
|
-
logErr(`Destination already exists: ${destPath}`);
|
|
116
|
-
process.exit(1);
|
|
117
|
-
}
|
|
118
|
-
switch (opts.mode) {
|
|
119
|
-
case "copy":
|
|
120
|
-
fs11.cpSync(srcPath, destPath, { recursive: true });
|
|
121
|
-
break;
|
|
122
|
-
case "move":
|
|
123
|
-
fs11.renameSync(srcPath, destPath);
|
|
124
|
-
break;
|
|
125
|
-
case "link":
|
|
126
|
-
fs11.symlinkSync(path12.resolve(srcPath), destPath);
|
|
127
|
-
break;
|
|
128
|
-
}
|
|
129
|
-
if (target.backend === "git" && opts.commit) {
|
|
130
|
-
const { spawnSync: spawnSync2 } = await import('child_process');
|
|
131
|
-
spawnSync2("git", ["add", "-A"], { cwd: target.path, stdio: "ignore" });
|
|
132
|
-
spawnSync2("git", ["commit", "-m", `skaile: migrate ${basename2}`], {
|
|
133
|
-
cwd: target.path,
|
|
134
|
-
stdio: "ignore"
|
|
135
|
-
});
|
|
136
|
-
}
|
|
137
|
-
logOk(`Migrated ${basename2} \u2192 ${target.name} (${opts.mode})`);
|
|
138
|
-
if (opts.mode === "move") {
|
|
139
|
-
logInfo("Source moved into the library \u2014 future edits modify the library copy.");
|
|
140
|
-
} else if (opts.mode === "copy") {
|
|
141
|
-
logInfo("Original kept; workspace edits will NOT reach the library.");
|
|
142
|
-
} else {
|
|
143
|
-
logInfo("Symlinked \u2014 workspace edits propagate to the library immediately.");
|
|
144
|
-
}
|
|
145
|
-
} finally {
|
|
146
|
-
close();
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
);
|
|
150
|
-
cmd.command("install <ref>").description("Install an asset from a library into a workspace").option("--target <dir>", "Workspace target (default: cwd)").option("--mode <mode>", "copy | link", "copy").option("--from <library>", "Library to install from (default: any)").action(
|
|
151
|
-
async (ref, opts) => {
|
|
152
|
-
if (!["copy", "link"].includes(opts.mode)) {
|
|
153
|
-
logErr(`Invalid --mode "${opts.mode}". Expected: copy | link.`);
|
|
154
|
-
process.exit(1);
|
|
155
|
-
}
|
|
156
|
-
const { manager, library, close } = await openLibraryManager();
|
|
157
|
-
try {
|
|
158
|
-
const def = await library.getAssetDef(ref);
|
|
159
|
-
if (!def) {
|
|
160
|
-
logErr(`No asset found for ref "${ref}". Try \`skaile asset list\`.`);
|
|
161
|
-
process.exit(1);
|
|
162
|
-
}
|
|
163
|
-
const target = opts.target ?? process.cwd();
|
|
164
|
-
const lib = def.libraryId ? (await manager.listLibraries()).find((l) => l.id === def.libraryId) : void 0;
|
|
165
|
-
if (!lib) {
|
|
166
|
-
logErr(`Asset has no associated library; install path unknown.`);
|
|
167
|
-
process.exit(1);
|
|
168
|
-
}
|
|
169
|
-
if (opts.from && lib.name !== opts.from) {
|
|
170
|
-
logWarn(`Asset belongs to "${lib.name}", but --from=${opts.from} was specified.`);
|
|
171
|
-
}
|
|
172
|
-
const manifestPath = def.manifest.path;
|
|
173
|
-
const candidateSubpath = typeof manifestPath === "string" && manifestPath.length > 0 ? manifestPath : def.name;
|
|
174
|
-
const srcPath = path12.join(lib.path, candidateSubpath);
|
|
175
|
-
if (!fs11.existsSync(srcPath)) {
|
|
176
|
-
logErr(`Asset path not found: ${srcPath}`);
|
|
177
|
-
process.exit(1);
|
|
178
|
-
}
|
|
179
|
-
const destPath = path12.join(target, candidateSubpath);
|
|
180
|
-
fs11.mkdirSync(path12.dirname(destPath), { recursive: true });
|
|
181
|
-
if (opts.mode === "copy") {
|
|
182
|
-
fs11.cpSync(srcPath, destPath, { recursive: true });
|
|
183
|
-
} else {
|
|
184
|
-
fs11.symlinkSync(path12.resolve(srcPath), destPath);
|
|
185
|
-
}
|
|
186
|
-
logOk(`Installed ${ref} \u2192 ${destPath} (${opts.mode})`);
|
|
187
|
-
} finally {
|
|
188
|
-
close();
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
);
|
|
192
|
-
cmd.command("list").description("List asset definitions across libraries").option("--library <name>", "Filter by library").option("--domain <name>", "Filter by domain").option("--kind <kind>", "Filter by kind").option("--json", "Output as JSON").action(async (opts) => {
|
|
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
|
-
});
|
|
215
|
-
cmd.command("show <ref>").description("Show details for an asset by canonical ref").action(async (ref) => {
|
|
216
|
-
const { library, close } = await openLibraryManager();
|
|
217
|
-
try {
|
|
218
|
-
const def = await library.getAssetDef(ref);
|
|
219
|
-
if (!def) {
|
|
220
|
-
logErr(`Not found: ${ref}`);
|
|
221
|
-
process.exit(1);
|
|
222
|
-
}
|
|
223
|
-
console.log(JSON.stringify(def, null, 2));
|
|
224
|
-
} finally {
|
|
225
|
-
close();
|
|
226
|
-
}
|
|
227
|
-
});
|
|
228
|
-
return cmd;
|
|
229
|
-
}
|
|
230
|
-
var VALID_STRATEGIES = ["keychain", "passphrase", "machine"];
|
|
231
|
-
function makeAuthCommand() {
|
|
232
|
-
const cmd = new Command("auth").description("Manage secret key strategy and provider status");
|
|
233
|
-
cmd.command("status").description("Show current key strategy and provider health").action(async () => {
|
|
234
|
-
const provider = new LocalSecretsProvider();
|
|
235
|
-
const strategy = provider.getKeyStrategy();
|
|
236
|
-
logInfo(`Key strategy: ${strategy}`);
|
|
237
|
-
const health = await provider.testConnection();
|
|
238
|
-
if (health.ok) {
|
|
239
|
-
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
76
|
async function runSearch(kind, query, opts) {
|
|
270
77
|
if (kind?.includes(":")) {
|
|
271
78
|
query = kind;
|
|
@@ -281,7 +88,7 @@ async function runSearch(kind, query, opts) {
|
|
|
281
88
|
}
|
|
282
89
|
}
|
|
283
90
|
function searchLocal(query, kind, opts, showStore) {
|
|
284
|
-
const am2 = new AssetManager({ projectDir:
|
|
91
|
+
const am2 = new AssetManager({ projectDir: path14__default.resolve(opts.projectDir) });
|
|
285
92
|
const entries = am2.search(query, kind);
|
|
286
93
|
if (entries.length === 0) {
|
|
287
94
|
if (!showStore) {
|
|
@@ -321,7 +128,7 @@ function printLocalEntries(entries) {
|
|
|
321
128
|
}
|
|
322
129
|
async function searchStore(query, kind, opts) {
|
|
323
130
|
try {
|
|
324
|
-
const { getStoreConfig: getStoreConfig2, storeFetch: storeFetch2 } = await import('../store-client-
|
|
131
|
+
const { getStoreConfig: getStoreConfig2, storeFetch: storeFetch2 } = await import('../store-client-XFZFKY3W.js');
|
|
325
132
|
const config = getStoreConfig2();
|
|
326
133
|
const params = {};
|
|
327
134
|
if (query) params.q = query;
|
|
@@ -353,17 +160,23 @@ function makeSearchCommand() {
|
|
|
353
160
|
function makeAddCommand() {
|
|
354
161
|
return new Command("add").description("Add to skaile.yaml + deploy").argument("<ref>", "Asset reference (kind:name[@repo])").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) => {
|
|
355
162
|
const am2 = new AssetManager({
|
|
356
|
-
projectDir:
|
|
163
|
+
projectDir: path14__default.resolve(opts.projectDir),
|
|
357
164
|
global: opts.global,
|
|
358
165
|
driverTarget: opts.target
|
|
359
166
|
});
|
|
360
|
-
const spinner5 =
|
|
167
|
+
const spinner5 = p6.spinner();
|
|
361
168
|
spinner5.start(`Adding ${ref}`);
|
|
362
169
|
try {
|
|
363
170
|
const added = await am2.add(ref);
|
|
364
171
|
spinner5.stop("Done");
|
|
365
|
-
if (added.length === 0)
|
|
366
|
-
|
|
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);
|
|
367
180
|
} catch (err) {
|
|
368
181
|
spinner5.stop("Failed");
|
|
369
182
|
logErr(String(err));
|
|
@@ -374,7 +187,7 @@ function makeAddCommand() {
|
|
|
374
187
|
function makeRemoveCommand() {
|
|
375
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) => {
|
|
376
189
|
const am2 = new AssetManager({
|
|
377
|
-
projectDir:
|
|
190
|
+
projectDir: path14__default.resolve(opts.projectDir),
|
|
378
191
|
global: opts.global,
|
|
379
192
|
driverTarget: opts.target
|
|
380
193
|
});
|
|
@@ -383,36 +196,64 @@ function makeRemoveCommand() {
|
|
|
383
196
|
else logErr(`Not deployed: ${ref}`);
|
|
384
197
|
});
|
|
385
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
|
+
}
|
|
386
205
|
function makeListCommand() {
|
|
387
|
-
return new Command("list").description("List
|
|
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(
|
|
388
207
|
new Option("--target <agent>", "Driver target").default("claude-code").choices(SUPPORTED_DRIVER_TARGETS)
|
|
389
208
|
).action((kind, opts) => {
|
|
390
209
|
const am2 = new AssetManager({
|
|
391
|
-
projectDir:
|
|
210
|
+
projectDir: path14__default.resolve(opts.projectDir),
|
|
392
211
|
global: opts.global,
|
|
393
212
|
driverTarget: opts.target
|
|
394
213
|
});
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
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.");
|
|
398
229
|
return;
|
|
399
230
|
}
|
|
400
|
-
const kindW = Math.max(
|
|
401
|
-
const nameW = Math.max(4, ...
|
|
231
|
+
const kindW = Math.max(4, ...declared.map((e) => e.kind.length));
|
|
232
|
+
const nameW = Math.max(4, ...declared.map((e) => e.name.length));
|
|
402
233
|
console.log();
|
|
403
|
-
console.log(
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
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
|
+
);
|
|
407
242
|
}
|
|
408
243
|
console.log(`
|
|
409
|
-
${S.dim(`${
|
|
410
|
-
|
|
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();
|
|
411
252
|
});
|
|
412
253
|
}
|
|
413
254
|
function makeInfoCommand() {
|
|
414
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) => {
|
|
415
|
-
const am2 = new AssetManager({ projectDir:
|
|
256
|
+
const am2 = new AssetManager({ projectDir: path14__default.resolve(opts.projectDir) });
|
|
416
257
|
const entry = am2.info(ref);
|
|
417
258
|
if (!entry) {
|
|
418
259
|
logErr(
|
|
@@ -445,7 +286,7 @@ function makeCreateCommand() {
|
|
|
445
286
|
new Option("-k, --kind <kind>", "Asset kind").default("skill").choices([...ASSET_KINDS])
|
|
446
287
|
).option("-d, --dir <dir>", "Target directory (default: cwd)").action((name, opts) => {
|
|
447
288
|
const am2 = new AssetManager({ projectDir: process.cwd() });
|
|
448
|
-
const destDir = opts.dir ?
|
|
289
|
+
const destDir = opts.dir ? path14__default.resolve(opts.dir) : process.cwd();
|
|
449
290
|
const result = am2.create(name, opts.kind, destDir);
|
|
450
291
|
if (result.ok) logOk(`Created ${kindColor(opts.kind)}: ${pc5.dim(result.path)}`);
|
|
451
292
|
else {
|
|
@@ -456,7 +297,7 @@ function makeCreateCommand() {
|
|
|
456
297
|
}
|
|
457
298
|
function makeDoctorCommand() {
|
|
458
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) => {
|
|
459
|
-
const am2 = new AssetManager({ projectDir:
|
|
300
|
+
const am2 = new AssetManager({ projectDir: path14__default.resolve(opts.projectDir) });
|
|
460
301
|
const issues = am2.doctor();
|
|
461
302
|
if (issues.length === 0) {
|
|
462
303
|
logOk("No missing dependencies.");
|
|
@@ -478,11 +319,486 @@ function makeDoctorCommand() {
|
|
|
478
319
|
console.log();
|
|
479
320
|
});
|
|
480
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
|
|
442
|
+
function makeAssetCommand() {
|
|
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 descRaw = parseFrontmatter(norm.content).data.description;
|
|
499
|
+
const description = typeof descRaw === "string" ? descRaw.trim() : void 0;
|
|
500
|
+
const root = path14.relative(target.path, destDir);
|
|
501
|
+
const up = upsertManifestAsset(target.path, {
|
|
502
|
+
kind: "skill",
|
|
503
|
+
name: norm.name,
|
|
504
|
+
root,
|
|
505
|
+
version: opts.version,
|
|
506
|
+
publisher,
|
|
507
|
+
description
|
|
508
|
+
});
|
|
509
|
+
logOk(`${up.added ? "Added" : "Updated"} manifest entry skill:${norm.name}`);
|
|
510
|
+
if (target.backend === "git" && opts.commit) {
|
|
511
|
+
const { spawnSync: spawnSync2 } = await import('child_process');
|
|
512
|
+
spawnSync2("git", ["add", "--", destDir], { cwd: target.path, stdio: "inherit" });
|
|
513
|
+
const r = spawnSync2("git", ["commit", "-m", `skaile: import ${norm.name}`], {
|
|
514
|
+
cwd: target.path,
|
|
515
|
+
stdio: "inherit"
|
|
516
|
+
});
|
|
517
|
+
if (r.status !== 0) {
|
|
518
|
+
logWarn("Nothing committed (working tree clean or commit aborted).");
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
logOk(`Imported ${S.cmd(norm.name)} \u2192 ${target.name}`);
|
|
522
|
+
logInfo(`Verify: ${S.cmd(`skaile validate ${target.path}`)}`);
|
|
523
|
+
} finally {
|
|
524
|
+
close();
|
|
525
|
+
}
|
|
526
|
+
}
|
|
527
|
+
);
|
|
528
|
+
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(
|
|
529
|
+
async (srcPath, opts) => {
|
|
530
|
+
if (!["copy", "move", "link"].includes(opts.mode)) {
|
|
531
|
+
logErr(`Invalid --mode "${opts.mode}". Expected: copy | move | link.`);
|
|
532
|
+
process.exit(1);
|
|
533
|
+
}
|
|
534
|
+
if (!fs12.existsSync(srcPath)) {
|
|
535
|
+
logErr(`Source path does not exist: ${srcPath}`);
|
|
536
|
+
process.exit(1);
|
|
537
|
+
}
|
|
538
|
+
const { manager, close } = await openLibraryManager();
|
|
539
|
+
try {
|
|
540
|
+
let target;
|
|
541
|
+
if (opts.to) {
|
|
542
|
+
target = await manager.requireLibrary(opts.to);
|
|
543
|
+
} else {
|
|
544
|
+
const all = await manager.listLibraries();
|
|
545
|
+
const def = all.find(
|
|
546
|
+
(l) => l.isDefault && (l.ownership === "owner" || l.ownership === "contributor")
|
|
547
|
+
);
|
|
548
|
+
if (def) {
|
|
549
|
+
target = def;
|
|
550
|
+
} else {
|
|
551
|
+
const res = await manager.ensurePersonalLibrary(resolveLibraryDir());
|
|
552
|
+
target = res.library;
|
|
553
|
+
}
|
|
554
|
+
}
|
|
555
|
+
if (target.ownership === "reader") {
|
|
556
|
+
logErr(
|
|
557
|
+
`Library "${target.name}" is read-only (ownership=reader). Choose another with --to.`
|
|
558
|
+
);
|
|
559
|
+
process.exit(1);
|
|
560
|
+
}
|
|
561
|
+
const basename2 = path14.basename(srcPath);
|
|
562
|
+
const destDir = target.structure === "domain" && opts.domain ? path14.join(target.path, opts.domain) : target.path;
|
|
563
|
+
fs12.mkdirSync(destDir, { recursive: true });
|
|
564
|
+
const destPath = path14.join(destDir, basename2);
|
|
565
|
+
if (fs12.existsSync(destPath)) {
|
|
566
|
+
logErr(`Destination already exists: ${destPath}`);
|
|
567
|
+
process.exit(1);
|
|
568
|
+
}
|
|
569
|
+
switch (opts.mode) {
|
|
570
|
+
case "copy":
|
|
571
|
+
fs12.cpSync(srcPath, destPath, { recursive: true });
|
|
572
|
+
break;
|
|
573
|
+
case "move":
|
|
574
|
+
fs12.renameSync(srcPath, destPath);
|
|
575
|
+
break;
|
|
576
|
+
case "link":
|
|
577
|
+
fs12.symlinkSync(path14.resolve(srcPath), destPath);
|
|
578
|
+
break;
|
|
579
|
+
}
|
|
580
|
+
if (target.backend === "git" && opts.commit) {
|
|
581
|
+
const { spawnSync: spawnSync2 } = await import('child_process');
|
|
582
|
+
spawnSync2("git", ["add", "--", destPath], { cwd: target.path, stdio: "inherit" });
|
|
583
|
+
const r = spawnSync2("git", ["commit", "-m", `skaile: migrate ${basename2}`], {
|
|
584
|
+
cwd: target.path,
|
|
585
|
+
stdio: "inherit"
|
|
586
|
+
});
|
|
587
|
+
if (r.status !== 0) {
|
|
588
|
+
logWarn("Nothing committed (working tree clean or commit aborted).");
|
|
589
|
+
}
|
|
590
|
+
}
|
|
591
|
+
logOk(`Migrated ${basename2} \u2192 ${target.name} (${opts.mode})`);
|
|
592
|
+
if (opts.mode === "move") {
|
|
593
|
+
logInfo("Source moved into the library \u2014 future edits modify the library copy.");
|
|
594
|
+
} else if (opts.mode === "copy") {
|
|
595
|
+
logInfo("Original kept; workspace edits will NOT reach the library.");
|
|
596
|
+
} else {
|
|
597
|
+
logInfo("Symlinked \u2014 workspace edits propagate to the library immediately.");
|
|
598
|
+
}
|
|
599
|
+
} finally {
|
|
600
|
+
close();
|
|
601
|
+
}
|
|
602
|
+
}
|
|
603
|
+
);
|
|
604
|
+
cmd.command("install <ref>").description("Install an asset from a library into a workspace").option("--target <dir>", "Workspace target (default: cwd)").option("--mode <mode>", "copy | link", "copy").option("--from <library>", "Library to install from (default: any)").action(
|
|
605
|
+
async (ref, opts) => {
|
|
606
|
+
if (!["copy", "link"].includes(opts.mode)) {
|
|
607
|
+
logErr(`Invalid --mode "${opts.mode}". Expected: copy | link.`);
|
|
608
|
+
process.exit(1);
|
|
609
|
+
}
|
|
610
|
+
const { manager, library, close } = await openLibraryManager();
|
|
611
|
+
try {
|
|
612
|
+
const def = await library.getAssetDef(ref);
|
|
613
|
+
if (!def) {
|
|
614
|
+
logErr(`No asset found for ref "${ref}". Try \`skaile search\`.`);
|
|
615
|
+
process.exit(1);
|
|
616
|
+
}
|
|
617
|
+
const target = opts.target ?? process.cwd();
|
|
618
|
+
const lib = def.libraryId ? (await manager.listLibraries()).find((l) => l.id === def.libraryId) : void 0;
|
|
619
|
+
if (!lib) {
|
|
620
|
+
logErr(`Asset has no associated library; install path unknown.`);
|
|
621
|
+
process.exit(1);
|
|
622
|
+
}
|
|
623
|
+
if (opts.from && lib.name !== opts.from) {
|
|
624
|
+
logWarn(`Asset belongs to "${lib.name}", but --from=${opts.from} was specified.`);
|
|
625
|
+
}
|
|
626
|
+
const manifestPath = def.manifest.path;
|
|
627
|
+
const candidateSubpath = typeof manifestPath === "string" && manifestPath.length > 0 ? manifestPath : def.name;
|
|
628
|
+
const srcPath = path14.join(lib.path, candidateSubpath);
|
|
629
|
+
if (!fs12.existsSync(srcPath)) {
|
|
630
|
+
logErr(`Asset path not found: ${srcPath}`);
|
|
631
|
+
process.exit(1);
|
|
632
|
+
}
|
|
633
|
+
const destPath = path14.join(target, candidateSubpath);
|
|
634
|
+
fs12.mkdirSync(path14.dirname(destPath), { recursive: true });
|
|
635
|
+
if (opts.mode === "copy") {
|
|
636
|
+
fs12.cpSync(srcPath, destPath, { recursive: true });
|
|
637
|
+
} else {
|
|
638
|
+
fs12.symlinkSync(path14.resolve(srcPath), destPath);
|
|
639
|
+
}
|
|
640
|
+
logOk(`Installed ${ref} \u2192 ${destPath} (${opts.mode})`);
|
|
641
|
+
} finally {
|
|
642
|
+
close();
|
|
643
|
+
}
|
|
644
|
+
}
|
|
645
|
+
);
|
|
646
|
+
cmd.addCommand(makeListCommand());
|
|
647
|
+
cmd.command("show <ref>").description("Show details for an asset by canonical ref").action(async (ref) => {
|
|
648
|
+
const { library, close } = await openLibraryManager();
|
|
649
|
+
try {
|
|
650
|
+
const def = await library.getAssetDef(ref);
|
|
651
|
+
if (!def) {
|
|
652
|
+
logErr(`Not found: ${ref}`);
|
|
653
|
+
process.exit(1);
|
|
654
|
+
}
|
|
655
|
+
console.log(JSON.stringify(def, null, 2));
|
|
656
|
+
} finally {
|
|
657
|
+
close();
|
|
658
|
+
}
|
|
659
|
+
});
|
|
660
|
+
return cmd;
|
|
661
|
+
}
|
|
662
|
+
var VALID_STRATEGIES = ["keychain", "passphrase", "machine"];
|
|
663
|
+
function makeAuthCommand() {
|
|
664
|
+
const cmd = new Command("auth").description("Manage secret key strategy and provider status");
|
|
665
|
+
cmd.command("status").description("Show current key strategy and provider health").action(async () => {
|
|
666
|
+
const provider = new LocalSecretsProvider();
|
|
667
|
+
const strategy = provider.getKeyStrategy();
|
|
668
|
+
logInfo(`Key strategy: ${strategy}`);
|
|
669
|
+
const health = await provider.testConnection();
|
|
670
|
+
if (health.ok) {
|
|
671
|
+
logOk(`Local provider: healthy (${health.latencyMs}ms)`);
|
|
672
|
+
} else {
|
|
673
|
+
logErr(`Local provider: ${health.error ?? "unhealthy"}`);
|
|
674
|
+
}
|
|
675
|
+
});
|
|
676
|
+
cmd.command("set-key-strategy").description("Set the master key strategy (keychain, passphrase, or machine)").argument("<strategy>", `One of: ${VALID_STRATEGIES.join(", ")}`).option(
|
|
677
|
+
"--passphrase <value>",
|
|
678
|
+
"Passphrase value (required for passphrase strategy; alternative to SKAILE_SECRETS_PASSPHRASE env var)"
|
|
679
|
+
).action(async (strategy, opts) => {
|
|
680
|
+
if (!VALID_STRATEGIES.includes(strategy)) {
|
|
681
|
+
logErr(`Invalid strategy "${strategy}". Must be one of: ${VALID_STRATEGIES.join(", ")}`);
|
|
682
|
+
process.exit(1);
|
|
683
|
+
}
|
|
684
|
+
if (strategy === "passphrase" && !opts.passphrase && !process.env.SKAILE_SECRETS_PASSPHRASE) {
|
|
685
|
+
logErr(
|
|
686
|
+
"Passphrase required. Provide via --passphrase or set SKAILE_SECRETS_PASSPHRASE:\n export SKAILE_SECRETS_PASSPHRASE='...'\n skaile auth set-key-strategy passphrase"
|
|
687
|
+
);
|
|
688
|
+
process.exit(1);
|
|
689
|
+
}
|
|
690
|
+
const provider = new LocalSecretsProvider();
|
|
691
|
+
try {
|
|
692
|
+
await provider.setKeyStrategy(strategy, opts.passphrase);
|
|
693
|
+
logOk(`Key strategy set to: ${strategy}`);
|
|
694
|
+
} catch (e) {
|
|
695
|
+
logErr(`Failed to set strategy: ${e instanceof Error ? e.message : String(e)}`);
|
|
696
|
+
process.exit(1);
|
|
697
|
+
}
|
|
698
|
+
});
|
|
699
|
+
return cmd;
|
|
700
|
+
}
|
|
701
|
+
function collectCacheTargets(scope) {
|
|
702
|
+
const out = [];
|
|
703
|
+
out.push(path14__default.join(scope.projectDir, ".skaile", "cache"));
|
|
704
|
+
out.push(path14__default.join(scope.projectDir, ".skaile", "store-cache"));
|
|
705
|
+
out.push(path14__default.join(scope.projectDir, ".skaile", "repos"));
|
|
706
|
+
if (scope.global) {
|
|
707
|
+
out.push(globalCacheRoot());
|
|
708
|
+
const home = process.env.SKAILE_HOME ?? path14__default.join(homedir(), ".skaile");
|
|
709
|
+
out.push(path14__default.join(home, "repos"));
|
|
710
|
+
out.push(path14__default.join(home, "catalog-cache"));
|
|
711
|
+
}
|
|
712
|
+
return out;
|
|
713
|
+
}
|
|
714
|
+
function dirSize(target) {
|
|
715
|
+
if (!existsSync(target)) return 0;
|
|
716
|
+
const st = lstatSync(target);
|
|
717
|
+
if (st.isSymbolicLink()) return 0;
|
|
718
|
+
if (!st.isDirectory()) return st.size;
|
|
719
|
+
return dirSizeOfDir(target);
|
|
720
|
+
}
|
|
721
|
+
function dirSizeOfDir(dir) {
|
|
722
|
+
let total = 0;
|
|
723
|
+
for (const ent of readdirSync(dir, { withFileTypes: true })) {
|
|
724
|
+
const child = path14__default.join(dir, ent.name);
|
|
725
|
+
if (ent.isSymbolicLink()) continue;
|
|
726
|
+
if (ent.isDirectory()) total += dirSizeOfDir(child);
|
|
727
|
+
else if (ent.isFile()) total += statSync(child).size;
|
|
728
|
+
}
|
|
729
|
+
return total;
|
|
730
|
+
}
|
|
731
|
+
function removeCacheTargets(targets, opts) {
|
|
732
|
+
const present = targets.filter((t) => existsSync(t));
|
|
733
|
+
for (const t of present) rmSync(t, { recursive: true, force: true });
|
|
734
|
+
return present;
|
|
735
|
+
}
|
|
736
|
+
function fmtBytes(n) {
|
|
737
|
+
const u = ["B", "KB", "MB", "GB"];
|
|
738
|
+
let i = 0;
|
|
739
|
+
let v = n;
|
|
740
|
+
while (v >= 1024 && i < u.length - 1) {
|
|
741
|
+
v /= 1024;
|
|
742
|
+
i++;
|
|
743
|
+
}
|
|
744
|
+
return `${v.toFixed(i === 0 ? 0 : 1)} ${u[i]}`;
|
|
745
|
+
}
|
|
746
|
+
function makeCacheCommand() {
|
|
747
|
+
const cmd = new Command("cache").description("Inspect and reclaim the re-derivable cache");
|
|
748
|
+
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) => {
|
|
749
|
+
const targets = collectCacheTargets({
|
|
750
|
+
projectDir: path14__default.resolve(opts.projectDir),
|
|
751
|
+
global: opts.global
|
|
752
|
+
}).filter((t) => existsSync(t));
|
|
753
|
+
if (targets.length === 0) {
|
|
754
|
+
logInfo("Cache is already empty.");
|
|
755
|
+
return;
|
|
756
|
+
}
|
|
757
|
+
console.log();
|
|
758
|
+
console.log(` ${S.heading("Will remove:")}`);
|
|
759
|
+
for (const t of targets)
|
|
760
|
+
console.log(` ${S.dim(t)} ${S.dim(`(${fmtBytes(dirSize(t))})`)}`);
|
|
761
|
+
if (opts.dryRun) {
|
|
762
|
+
console.log();
|
|
763
|
+
logInfo("Dry run \u2014 no changes made.");
|
|
764
|
+
return;
|
|
765
|
+
}
|
|
766
|
+
if (!opts.yes) {
|
|
767
|
+
const ok = await p6.confirm({
|
|
768
|
+
message: opts.global ? "Clear project AND global cache?" : "Clear project cache?"
|
|
769
|
+
});
|
|
770
|
+
if (p6.isCancel(ok) || !ok) {
|
|
771
|
+
logInfo("Cancelled.");
|
|
772
|
+
return;
|
|
773
|
+
}
|
|
774
|
+
}
|
|
775
|
+
const removed = removeCacheTargets(targets);
|
|
776
|
+
console.log();
|
|
777
|
+
for (const r of removed) logOk(`Removed ${r}`);
|
|
778
|
+
});
|
|
779
|
+
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) => {
|
|
780
|
+
console.log(path14__default.join(path14__default.resolve(opts.projectDir), ".skaile", "cache"));
|
|
781
|
+
if (opts.global) console.log(globalCacheRoot());
|
|
782
|
+
});
|
|
783
|
+
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) => {
|
|
784
|
+
const targets = collectCacheTargets({
|
|
785
|
+
projectDir: path14__default.resolve(opts.projectDir),
|
|
786
|
+
global: opts.global
|
|
787
|
+
});
|
|
788
|
+
console.log();
|
|
789
|
+
for (const t of targets) {
|
|
790
|
+
if (!existsSync(t)) continue;
|
|
791
|
+
console.log(` ${S.dim(fmtBytes(dirSize(t)).padStart(9))} ${t}`);
|
|
792
|
+
}
|
|
793
|
+
console.log();
|
|
794
|
+
});
|
|
795
|
+
return cmd;
|
|
796
|
+
}
|
|
481
797
|
function makeCatalogCommand() {
|
|
482
798
|
const catalog = new Command("catalog").description("Catalog source health and configuration");
|
|
483
799
|
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) => {
|
|
484
800
|
const { resolveConfig, isLocalCatalogUrl, trpcGetUrl } = await import('../library/index.js');
|
|
485
|
-
const projectDir = opts.projectDir ?
|
|
801
|
+
const projectDir = opts.projectDir ? path14__default.resolve(opts.projectDir) : void 0;
|
|
486
802
|
const cfg = resolveConfig({ projectDir });
|
|
487
803
|
const baseUrl = opts.url ?? cfg.catalog.url;
|
|
488
804
|
if (isLocalCatalogUrl(baseUrl)) {
|
|
@@ -500,7 +816,7 @@ function makeCatalogCommand() {
|
|
|
500
816
|
});
|
|
501
817
|
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) => {
|
|
502
818
|
const { resolveConfig } = await import('../library/index.js');
|
|
503
|
-
const projectDir = opts.projectDir ?
|
|
819
|
+
const projectDir = opts.projectDir ? path14__default.resolve(opts.projectDir) : void 0;
|
|
504
820
|
const cfg = resolveConfig({ projectDir });
|
|
505
821
|
console.log(`url: ${cfg.catalog.url}`);
|
|
506
822
|
console.log(`framing: ${cfg.catalog.framing}`);
|
|
@@ -509,7 +825,7 @@ function makeCatalogCommand() {
|
|
|
509
825
|
return catalog;
|
|
510
826
|
}
|
|
511
827
|
async function runLocalCatalogTest(projectDir) {
|
|
512
|
-
const { resolveCatalogSource } = await import('../open-library-
|
|
828
|
+
const { resolveCatalogSource } = await import('../open-library-362BZ6OW.js');
|
|
513
829
|
let resolved;
|
|
514
830
|
try {
|
|
515
831
|
resolved = await resolveCatalogSource({ projectDir });
|
|
@@ -642,8 +958,8 @@ function findFlowFile(flowId, priorityRoots = []) {
|
|
|
642
958
|
for (const root of [...priorityRoots, ...aiResourceRoots()]) {
|
|
643
959
|
for (const { dir } of assetSearchDirs(root, "flows")) {
|
|
644
960
|
for (const ext of [".flow.yaml", ".flow.json", ".json"]) {
|
|
645
|
-
const candidate =
|
|
646
|
-
if (
|
|
961
|
+
const candidate = path14__default.join(dir, `${flowId}${ext}`);
|
|
962
|
+
if (fs12__default.existsSync(candidate)) return candidate;
|
|
647
963
|
}
|
|
648
964
|
}
|
|
649
965
|
}
|
|
@@ -653,7 +969,7 @@ function findSkills(domain) {
|
|
|
653
969
|
const found = [];
|
|
654
970
|
for (const root of aiResourceRoots()) {
|
|
655
971
|
for (const { dir, domain: dirDomain } of assetSearchDirs(root, "skills")) {
|
|
656
|
-
if (
|
|
972
|
+
if (fs12__default.existsSync(dir)) walkSkills(dir, dirDomain, found);
|
|
657
973
|
}
|
|
658
974
|
}
|
|
659
975
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -666,11 +982,11 @@ function findSkills(domain) {
|
|
|
666
982
|
return deduped;
|
|
667
983
|
}
|
|
668
984
|
function walkSkills(dir, domain, out) {
|
|
669
|
-
for (const entry of
|
|
670
|
-
const full =
|
|
985
|
+
for (const entry of fs12__default.readdirSync(dir, { withFileTypes: true })) {
|
|
986
|
+
const full = path14__default.join(dir, entry.name);
|
|
671
987
|
if (entry.isDirectory()) {
|
|
672
|
-
const skillMd =
|
|
673
|
-
if (
|
|
988
|
+
const skillMd = path14__default.join(full, "SKILL.md");
|
|
989
|
+
if (fs12__default.existsSync(skillMd)) {
|
|
674
990
|
out.push({ name: entry.name, path: full, skillPath: skillMd, domain });
|
|
675
991
|
} else {
|
|
676
992
|
walkSkills(full, domain, out);
|
|
@@ -698,10 +1014,10 @@ function resolveFlowIds() {
|
|
|
698
1014
|
}
|
|
699
1015
|
}
|
|
700
1016
|
function resolveSessionIds(projectDir) {
|
|
701
|
-
const sessionsDir =
|
|
702
|
-
if (!
|
|
1017
|
+
const sessionsDir = path14__default.join(projectDir, ".skaile", "sessions");
|
|
1018
|
+
if (!fs12__default.existsSync(sessionsDir)) return [];
|
|
703
1019
|
try {
|
|
704
|
-
return
|
|
1020
|
+
return fs12__default.readdirSync(sessionsDir).filter((f) => f.endsWith(".json")).map((f) => f.slice(0, -".json".length));
|
|
705
1021
|
} catch {
|
|
706
1022
|
return [];
|
|
707
1023
|
}
|
|
@@ -760,13 +1076,13 @@ function collectWorkspaceDefaults(projectDir) {
|
|
|
760
1076
|
const wsDefaults = {};
|
|
761
1077
|
try {
|
|
762
1078
|
const ws = resolveSkWorkspaceConfig(projectDir);
|
|
763
|
-
const
|
|
764
|
-
if (
|
|
765
|
-
if (
|
|
766
|
-
if (
|
|
767
|
-
if (
|
|
768
|
-
if (
|
|
769
|
-
if (
|
|
1079
|
+
const p9 = ws.agent_config?.default ?? {};
|
|
1080
|
+
if (p9.driver) wsDefaults.driver = p9.driver;
|
|
1081
|
+
if (p9.provider) wsDefaults.provider = p9.provider;
|
|
1082
|
+
if (p9.model) wsDefaults.model = p9.model;
|
|
1083
|
+
if (p9.skills_dir) wsDefaults.skills_dir = p9.skills_dir;
|
|
1084
|
+
if (p9.agents_dir) wsDefaults.agents_dir = p9.agents_dir;
|
|
1085
|
+
if (p9.prompts_dir) wsDefaults.prompts_dir = p9.prompts_dir;
|
|
770
1086
|
} catch {
|
|
771
1087
|
}
|
|
772
1088
|
return wsDefaults;
|
|
@@ -817,7 +1133,7 @@ function printResolvedPathsSection(config) {
|
|
|
817
1133
|
console.log(` ${S.label("prompts:".padEnd(16))} ${config.promptsDir ?? paths.promptsDir}`);
|
|
818
1134
|
}
|
|
819
1135
|
async function showConfig(opts) {
|
|
820
|
-
const projectDir = opts.projectDir ?
|
|
1136
|
+
const projectDir = opts.projectDir ? path14__default.resolve(opts.projectDir) : process.cwd();
|
|
821
1137
|
const config = await resolveSettings(projectDir);
|
|
822
1138
|
const wsDefaults = collectWorkspaceDefaults(projectDir);
|
|
823
1139
|
printEffectiveSection(config);
|
|
@@ -830,13 +1146,13 @@ function makeConfigCommand() {
|
|
|
830
1146
|
const cmd = new Command("config").description("Manage personal config (.skaile/settings.json)");
|
|
831
1147
|
cmd.command("show").description("Show effective config with sources").option("--project-dir <path>", "Project directory").action((opts) => showConfig(opts));
|
|
832
1148
|
cmd.command("get <key>").description("Get an effective config value").option("--project-dir <path>", "Project directory").action(async (key, opts) => {
|
|
833
|
-
const projectDir = opts.projectDir ?
|
|
1149
|
+
const projectDir = opts.projectDir ? path14__default.resolve(opts.projectDir) : process.cwd();
|
|
834
1150
|
const config = await resolveSettings(projectDir);
|
|
835
1151
|
const value = config[key];
|
|
836
1152
|
console.log(value ?? S.dim("(not set)"));
|
|
837
1153
|
});
|
|
838
1154
|
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) => {
|
|
839
|
-
const projectDir = opts.projectDir ?
|
|
1155
|
+
const projectDir = opts.projectDir ? path14__default.resolve(opts.projectDir) : process.cwd();
|
|
840
1156
|
const isApiKey = key.startsWith(API_KEY_PREFIX);
|
|
841
1157
|
if (!PERSONAL_KEYS.has(key) && !isApiKey) {
|
|
842
1158
|
logErr(
|
|
@@ -951,11 +1267,11 @@ function makeConnectCommand() {
|
|
|
951
1267
|
process.exitCode = 1;
|
|
952
1268
|
return;
|
|
953
1269
|
}
|
|
954
|
-
await new Promise((
|
|
1270
|
+
await new Promise((resolve5) => {
|
|
955
1271
|
client.onMessage((event) => {
|
|
956
1272
|
console.log(formatEvent(event));
|
|
957
1273
|
if (event.type === "finished" || event.type === "debug_result") {
|
|
958
|
-
|
|
1274
|
+
resolve5();
|
|
959
1275
|
}
|
|
960
1276
|
});
|
|
961
1277
|
client.send(parsed);
|
|
@@ -999,12 +1315,12 @@ function makeConnectCommand() {
|
|
|
999
1315
|
client.send(cmd);
|
|
1000
1316
|
rl.prompt();
|
|
1001
1317
|
});
|
|
1002
|
-
await new Promise((
|
|
1003
|
-
rl.on("close",
|
|
1318
|
+
await new Promise((resolve5) => {
|
|
1319
|
+
rl.on("close", resolve5);
|
|
1004
1320
|
client.onDisconnect(() => {
|
|
1005
1321
|
logErr("Server disconnected");
|
|
1006
1322
|
rl.close();
|
|
1007
|
-
|
|
1323
|
+
resolve5();
|
|
1008
1324
|
});
|
|
1009
1325
|
});
|
|
1010
1326
|
await client.disconnect();
|
|
@@ -1086,15 +1402,15 @@ function parseOpArgs(args) {
|
|
|
1086
1402
|
async function promptText(label, defaultVal) {
|
|
1087
1403
|
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
1088
1404
|
const hint = defaultVal ? ` [${defaultVal}]` : "";
|
|
1089
|
-
return new Promise((
|
|
1405
|
+
return new Promise((resolve5) => {
|
|
1090
1406
|
rl.question(` ${label}${hint}: `, (answer) => {
|
|
1091
1407
|
rl.close();
|
|
1092
|
-
|
|
1408
|
+
resolve5(answer.trim() || defaultVal || "");
|
|
1093
1409
|
});
|
|
1094
1410
|
});
|
|
1095
1411
|
}
|
|
1096
1412
|
async function promptSecret(label) {
|
|
1097
|
-
return new Promise((
|
|
1413
|
+
return new Promise((resolve5) => {
|
|
1098
1414
|
process.stdout.write(` ${label} (hidden): `);
|
|
1099
1415
|
const stdin = process.stdin;
|
|
1100
1416
|
stdin.setRawMode?.(true);
|
|
@@ -1107,7 +1423,7 @@ async function promptSecret(label) {
|
|
|
1107
1423
|
stdin.pause();
|
|
1108
1424
|
stdin.removeListener("data", onData);
|
|
1109
1425
|
process.stdout.write("\n");
|
|
1110
|
-
|
|
1426
|
+
resolve5(value);
|
|
1111
1427
|
} else if (char === "") {
|
|
1112
1428
|
process.exit(1);
|
|
1113
1429
|
} else if (char === "\x7F") {
|
|
@@ -1154,8 +1470,8 @@ function makeConnectorCommand() {
|
|
|
1154
1470
|
async (driver, opts) => {
|
|
1155
1471
|
const { installNpmPackages } = await import('../connectors/index.js');
|
|
1156
1472
|
const { scanDirectory, factoryAssetRoots, WorkspaceYamlEditor: WorkspaceYamlEditor2 } = await import('../core/index.js');
|
|
1157
|
-
const projectDir =
|
|
1158
|
-
const yamlPath =
|
|
1473
|
+
const projectDir = path14__default.resolve(opts.projectDir);
|
|
1474
|
+
const yamlPath = path14__default.join(projectDir, "skaile.yaml");
|
|
1159
1475
|
if (!existsSync(yamlPath)) {
|
|
1160
1476
|
logErr("No skaile.yaml found in current directory. Run 'skaile init' first.");
|
|
1161
1477
|
process.exit(1);
|
|
@@ -1215,8 +1531,8 @@ ${installResult.output}`);
|
|
|
1215
1531
|
);
|
|
1216
1532
|
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) => {
|
|
1217
1533
|
const { WorkspaceYamlEditor: WorkspaceYamlEditor2 } = await import('../core/index.js');
|
|
1218
|
-
const projectDir =
|
|
1219
|
-
const yamlPath =
|
|
1534
|
+
const projectDir = path14__default.resolve(opts.projectDir);
|
|
1535
|
+
const yamlPath = path14__default.join(projectDir, "skaile.yaml");
|
|
1220
1536
|
if (!existsSync(yamlPath)) {
|
|
1221
1537
|
logErr("No skaile.yaml found in current directory.");
|
|
1222
1538
|
process.exit(1);
|
|
@@ -1233,7 +1549,7 @@ ${installResult.output}`);
|
|
|
1233
1549
|
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) => {
|
|
1234
1550
|
const res = await import('../connectors/index.js');
|
|
1235
1551
|
res.registerBuiltinConnectors();
|
|
1236
|
-
const projectDir =
|
|
1552
|
+
const projectDir = path14__default.resolve(opts.projectDir);
|
|
1237
1553
|
const declarations = res.loadConnectorDeclarations(projectDir);
|
|
1238
1554
|
if (declarations.length === 0) {
|
|
1239
1555
|
console.log("No connectors configured in skaile.yaml.");
|
|
@@ -1257,7 +1573,7 @@ ${installResult.output}`);
|
|
|
1257
1573
|
await manager.disconnectAll();
|
|
1258
1574
|
});
|
|
1259
1575
|
cmd.command("list").description("List all configured connectors").option("--project-dir <path>", "Workspace directory", process.cwd()).action(async (opts) => {
|
|
1260
|
-
const projectDir =
|
|
1576
|
+
const projectDir = path14__default.resolve(opts.projectDir);
|
|
1261
1577
|
const manager = await connectConnectors(projectDir);
|
|
1262
1578
|
try {
|
|
1263
1579
|
console.log(JSON.stringify(manager.listConnectors(), null, 2));
|
|
@@ -1266,7 +1582,7 @@ ${installResult.output}`);
|
|
|
1266
1582
|
}
|
|
1267
1583
|
});
|
|
1268
1584
|
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) => {
|
|
1269
|
-
const projectDir =
|
|
1585
|
+
const projectDir = path14__default.resolve(opts.projectDir);
|
|
1270
1586
|
const manager = await connectConnectors(projectDir);
|
|
1271
1587
|
try {
|
|
1272
1588
|
if (opts.all) {
|
|
@@ -1290,7 +1606,7 @@ ${installResult.output}`);
|
|
|
1290
1606
|
}
|
|
1291
1607
|
});
|
|
1292
1608
|
cmd.command("ops <id>").description("List available operations for a connector").option("--project-dir <path>", "Workspace directory", process.cwd()).action(async (id, opts) => {
|
|
1293
|
-
const projectDir =
|
|
1609
|
+
const projectDir = path14__default.resolve(opts.projectDir);
|
|
1294
1610
|
const manager = await connectConnectors(projectDir);
|
|
1295
1611
|
try {
|
|
1296
1612
|
if (!manager.has(id)) {
|
|
@@ -1305,7 +1621,7 @@ ${installResult.output}`);
|
|
|
1305
1621
|
}
|
|
1306
1622
|
});
|
|
1307
1623
|
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) => {
|
|
1308
|
-
const projectDir =
|
|
1624
|
+
const projectDir = path14__default.resolve(opts.projectDir);
|
|
1309
1625
|
const manager = await connectConnectors(projectDir);
|
|
1310
1626
|
try {
|
|
1311
1627
|
const content = await manager.read(id, resourcePath);
|
|
@@ -1315,7 +1631,7 @@ ${installResult.output}`);
|
|
|
1315
1631
|
}
|
|
1316
1632
|
});
|
|
1317
1633
|
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) => {
|
|
1318
|
-
const projectDir =
|
|
1634
|
+
const projectDir = path14__default.resolve(opts.projectDir);
|
|
1319
1635
|
const manager = await connectConnectors(projectDir);
|
|
1320
1636
|
try {
|
|
1321
1637
|
await manager.write(id, resourcePath, { data: content });
|
|
@@ -1325,7 +1641,7 @@ ${installResult.output}`);
|
|
|
1325
1641
|
}
|
|
1326
1642
|
});
|
|
1327
1643
|
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) => {
|
|
1328
|
-
const projectDir =
|
|
1644
|
+
const projectDir = path14__default.resolve(opts.projectDir);
|
|
1329
1645
|
const manager = await connectConnectors(projectDir);
|
|
1330
1646
|
try {
|
|
1331
1647
|
const entries = await manager.list(id, resourcePath, {
|
|
@@ -1338,7 +1654,7 @@ ${installResult.output}`);
|
|
|
1338
1654
|
}
|
|
1339
1655
|
});
|
|
1340
1656
|
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) => {
|
|
1341
|
-
const projectDir =
|
|
1657
|
+
const projectDir = path14__default.resolve(opts.projectDir);
|
|
1342
1658
|
const manager = await connectConnectors(projectDir);
|
|
1343
1659
|
try {
|
|
1344
1660
|
const results = await manager.search(id, query);
|
|
@@ -1348,7 +1664,7 @@ ${installResult.output}`);
|
|
|
1348
1664
|
}
|
|
1349
1665
|
});
|
|
1350
1666
|
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) => {
|
|
1351
|
-
const projectDir =
|
|
1667
|
+
const projectDir = path14__default.resolve(opts.projectDir);
|
|
1352
1668
|
const manager = await connectConnectors(projectDir);
|
|
1353
1669
|
try {
|
|
1354
1670
|
const ok = await manager.delete(id, resourcePath);
|
|
@@ -1358,7 +1674,7 @@ ${installResult.output}`);
|
|
|
1358
1674
|
}
|
|
1359
1675
|
});
|
|
1360
1676
|
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) => {
|
|
1361
|
-
const projectDir =
|
|
1677
|
+
const projectDir = path14__default.resolve(opts.projectDir);
|
|
1362
1678
|
const manager = await connectConnectors(projectDir);
|
|
1363
1679
|
try {
|
|
1364
1680
|
if (!manager.has(id)) {
|
|
@@ -1393,17 +1709,17 @@ async function runDebugQuery(query, parentOpts, args) {
|
|
|
1393
1709
|
process.exitCode = 1;
|
|
1394
1710
|
return;
|
|
1395
1711
|
}
|
|
1396
|
-
await new Promise((
|
|
1712
|
+
await new Promise((resolve5) => {
|
|
1397
1713
|
const timeout = setTimeout(() => {
|
|
1398
1714
|
logErr("Timeout: no debug_result received within 5s");
|
|
1399
1715
|
process.exitCode = 1;
|
|
1400
|
-
|
|
1716
|
+
resolve5();
|
|
1401
1717
|
}, 5e3);
|
|
1402
1718
|
client.onMessage((event) => {
|
|
1403
1719
|
if (event.type !== "debug_result") return;
|
|
1404
1720
|
clearTimeout(timeout);
|
|
1405
1721
|
printDebugResult(query, event.data);
|
|
1406
|
-
|
|
1722
|
+
resolve5();
|
|
1407
1723
|
});
|
|
1408
1724
|
client.send({ type: "debug", query, args });
|
|
1409
1725
|
});
|
|
@@ -1467,7 +1783,7 @@ function envRecord() {
|
|
|
1467
1783
|
async function buildDeployContext(projectDir) {
|
|
1468
1784
|
const { resolveSkWorkspaceConfig: resolveSkWorkspaceConfig2 } = await import('../core/index.js');
|
|
1469
1785
|
const config = resolveSkWorkspaceConfig2(projectDir);
|
|
1470
|
-
const workspaceId = config.name ??
|
|
1786
|
+
const workspaceId = config.name ?? path14__default.basename(projectDir);
|
|
1471
1787
|
let log;
|
|
1472
1788
|
try {
|
|
1473
1789
|
const { createLogger } = await import('../core/logging.js');
|
|
@@ -1499,13 +1815,13 @@ async function ensureTargetsRegistered(projectDir) {
|
|
|
1499
1815
|
const { resolveSkWorkspaceConfig: resolveSkWorkspaceConfig2 } = await import('../core/index.js');
|
|
1500
1816
|
const config = resolveSkWorkspaceConfig2(projectDir);
|
|
1501
1817
|
if (config.plugins && config.plugins.length > 0) {
|
|
1502
|
-
const { ensurePluginsLoaded } = await import('../plugin-store-
|
|
1818
|
+
const { ensurePluginsLoaded } = await import('../plugin-store-2X2YXJVG.js');
|
|
1503
1819
|
const result = await ensurePluginsLoaded(projectDir, config.plugins, pluginRegistry);
|
|
1504
1820
|
for (const f of result.failed) logWarn(f.error);
|
|
1505
1821
|
}
|
|
1506
1822
|
}
|
|
1507
1823
|
async function runUp(opts) {
|
|
1508
|
-
const projectDir =
|
|
1824
|
+
const projectDir = path14__default.resolve(opts.projectDir);
|
|
1509
1825
|
await ensureTargetsRegistered(projectDir);
|
|
1510
1826
|
const { resolveSkWorkspaceConfig: resolveSkWorkspaceConfig2 } = await import('../core/index.js');
|
|
1511
1827
|
const { resolveDeployTarget, pluginRegistry } = await import('../plugin-registry/index.js');
|
|
@@ -1537,12 +1853,12 @@ async function runUp(opts) {
|
|
|
1537
1853
|
await holdUntilSignal(handle, controller);
|
|
1538
1854
|
}
|
|
1539
1855
|
function holdUntilSignal(handle, controller) {
|
|
1540
|
-
return new Promise((
|
|
1856
|
+
return new Promise((resolve5) => {
|
|
1541
1857
|
const onSig = () => {
|
|
1542
1858
|
process.removeListener("SIGINT", onSig);
|
|
1543
1859
|
controller.abort();
|
|
1544
1860
|
logInfo("Stopping\u2026");
|
|
1545
|
-
handle.stop().then(() => logOk("Stopped.")).catch((e) => logErr(`stop failed: ${e instanceof Error ? e.message : String(e)}`)).finally(() =>
|
|
1861
|
+
handle.stop().then(() => logOk("Stopped.")).catch((e) => logErr(`stop failed: ${e instanceof Error ? e.message : String(e)}`)).finally(() => resolve5());
|
|
1546
1862
|
};
|
|
1547
1863
|
process.on("SIGINT", onSig);
|
|
1548
1864
|
});
|
|
@@ -1573,7 +1889,7 @@ async function restoreFromHandle(projectDir) {
|
|
|
1573
1889
|
return { target, handle, ctx };
|
|
1574
1890
|
}
|
|
1575
1891
|
async function runDown(opts) {
|
|
1576
|
-
const projectDir =
|
|
1892
|
+
const projectDir = path14__default.resolve(opts.projectDir);
|
|
1577
1893
|
const restored = await restoreFromHandle(projectDir);
|
|
1578
1894
|
if (!restored) return;
|
|
1579
1895
|
await restored.handle.stop();
|
|
@@ -1582,7 +1898,7 @@ async function runDown(opts) {
|
|
|
1582
1898
|
logOk(`Stopped ${S.cmd(restored.target.id)} and cleared the handle.`);
|
|
1583
1899
|
}
|
|
1584
1900
|
async function runStatus(opts) {
|
|
1585
|
-
const projectDir =
|
|
1901
|
+
const projectDir = path14__default.resolve(opts.projectDir);
|
|
1586
1902
|
const restored = await restoreFromHandle(projectDir);
|
|
1587
1903
|
if (!restored) return;
|
|
1588
1904
|
const health = await restored.handle.health();
|
|
@@ -1596,7 +1912,7 @@ async function runStatus(opts) {
|
|
|
1596
1912
|
console.log();
|
|
1597
1913
|
}
|
|
1598
1914
|
async function runLogs(opts) {
|
|
1599
|
-
const projectDir =
|
|
1915
|
+
const projectDir = path14__default.resolve(opts.projectDir);
|
|
1600
1916
|
const restored = await restoreFromHandle(projectDir);
|
|
1601
1917
|
if (!restored) return;
|
|
1602
1918
|
if (!restored.handle.logs) {
|
|
@@ -1620,7 +1936,7 @@ function makeDeployCommand() {
|
|
|
1620
1936
|
}
|
|
1621
1937
|
function makeDiffCommand() {
|
|
1622
1938
|
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) => {
|
|
1623
|
-
const am2 = new AssetManager({ projectDir:
|
|
1939
|
+
const am2 = new AssetManager({ projectDir: path14__default.resolve(opts.projectDir) });
|
|
1624
1940
|
const result = am2.diff(ref);
|
|
1625
1941
|
if (result === null) {
|
|
1626
1942
|
logInfo("No differences (or asset not found).");
|
|
@@ -1673,7 +1989,7 @@ function makeFlowCommand() {
|
|
|
1673
1989
|
function makeHistoryCommand() {
|
|
1674
1990
|
const cmd = new Command("history").description("Show recent add/remove/update actions");
|
|
1675
1991
|
cmd.argument("[limit]", "Number of entries to show", "20").option("--project-dir <path>", "Project directory", process.cwd()).action((limitStr, opts) => {
|
|
1676
|
-
const am2 = new AssetManager({ projectDir:
|
|
1992
|
+
const am2 = new AssetManager({ projectDir: path14__default.resolve(opts.projectDir) });
|
|
1677
1993
|
const limit = parseInt(limitStr, 10) || 20;
|
|
1678
1994
|
const entries = am2.history(limit);
|
|
1679
1995
|
if (entries.length === 0) {
|
|
@@ -1693,7 +2009,7 @@ function makeHistoryCommand() {
|
|
|
1693
2009
|
console.log();
|
|
1694
2010
|
});
|
|
1695
2011
|
cmd.command("clear").description("Clear action history").option("--project-dir <path>", "Project directory", process.cwd()).action((opts) => {
|
|
1696
|
-
const am2 = new AssetManager({ projectDir:
|
|
2012
|
+
const am2 = new AssetManager({ projectDir: path14__default.resolve(opts.projectDir) });
|
|
1697
2013
|
am2.clearHistory();
|
|
1698
2014
|
logOk("History cleared.");
|
|
1699
2015
|
});
|
|
@@ -1706,12 +2022,12 @@ var MCP_SERVER_ENTRY = {
|
|
|
1706
2022
|
env: {}
|
|
1707
2023
|
};
|
|
1708
2024
|
function pluginDir(projectDir) {
|
|
1709
|
-
return
|
|
2025
|
+
return path14__default.join(projectDir, ".claude", "plugins", "skaile");
|
|
1710
2026
|
}
|
|
1711
|
-
async function readJsonStrict(
|
|
2027
|
+
async function readJsonStrict(p9) {
|
|
1712
2028
|
let raw;
|
|
1713
2029
|
try {
|
|
1714
|
-
raw = await
|
|
2030
|
+
raw = await fs6.readFile(p9, "utf-8");
|
|
1715
2031
|
} catch {
|
|
1716
2032
|
return null;
|
|
1717
2033
|
}
|
|
@@ -1719,37 +2035,37 @@ async function readJsonStrict(p8) {
|
|
|
1719
2035
|
return JSON.parse(raw);
|
|
1720
2036
|
} catch (e) {
|
|
1721
2037
|
throw new Error(
|
|
1722
|
-
`cannot parse ${
|
|
2038
|
+
`cannot parse ${p9}: ${e instanceof Error ? e.message : String(e)}; please fix or remove`
|
|
1723
2039
|
);
|
|
1724
2040
|
}
|
|
1725
2041
|
}
|
|
1726
|
-
async function writeJson(
|
|
1727
|
-
await
|
|
1728
|
-
await
|
|
2042
|
+
async function writeJson(p9, value) {
|
|
2043
|
+
await fs6.mkdir(path14__default.dirname(p9), { recursive: true });
|
|
2044
|
+
await fs6.writeFile(p9, `${JSON.stringify(value, null, 2)}
|
|
1729
2045
|
`);
|
|
1730
2046
|
}
|
|
1731
2047
|
async function copyDir(src, dest) {
|
|
1732
|
-
await
|
|
1733
|
-
const entries = await
|
|
2048
|
+
await fs6.mkdir(dest, { recursive: true });
|
|
2049
|
+
const entries = await fs6.readdir(src, { withFileTypes: true });
|
|
1734
2050
|
for (const entry of entries) {
|
|
1735
|
-
const srcPath =
|
|
1736
|
-
const destPath =
|
|
2051
|
+
const srcPath = path14__default.join(src, entry.name);
|
|
2052
|
+
const destPath = path14__default.join(dest, entry.name);
|
|
1737
2053
|
if (entry.isDirectory()) await copyDir(srcPath, destPath);
|
|
1738
|
-
else await
|
|
2054
|
+
else await fs6.copyFile(srcPath, destPath);
|
|
1739
2055
|
}
|
|
1740
2056
|
}
|
|
1741
2057
|
async function install(projectDir, opts) {
|
|
1742
2058
|
return opts?.full ? installFullPlugin(projectDir) : installMcp(projectDir);
|
|
1743
2059
|
}
|
|
1744
2060
|
async function installMcp(projectDir) {
|
|
1745
|
-
const mcpPath =
|
|
2061
|
+
const mcpPath = path14__default.join(projectDir, ".claude", "mcp.json");
|
|
1746
2062
|
const existing = await readJsonStrict(mcpPath) ?? {};
|
|
1747
2063
|
const mcpServers = { ...existing.mcpServers ?? {} };
|
|
1748
2064
|
const previous = mcpServers[SKAILE_MCP_NAME];
|
|
1749
2065
|
const matches = previous && JSON.stringify(previous) === JSON.stringify(MCP_SERVER_ENTRY);
|
|
1750
2066
|
let warning;
|
|
1751
2067
|
if (previous && !matches) {
|
|
1752
|
-
warning = `overwrote existing ${SKAILE_MCP_NAME} entry in ${
|
|
2068
|
+
warning = `overwrote existing ${SKAILE_MCP_NAME} entry in ${path14__default.relative(projectDir, mcpPath)}`;
|
|
1753
2069
|
}
|
|
1754
2070
|
mcpServers[SKAILE_MCP_NAME] = MCP_SERVER_ENTRY;
|
|
1755
2071
|
await writeJson(mcpPath, { ...existing, mcpServers });
|
|
@@ -1758,15 +2074,15 @@ async function installMcp(projectDir) {
|
|
|
1758
2074
|
async function installFullPlugin(projectDir) {
|
|
1759
2075
|
const dir = pluginDir(projectDir);
|
|
1760
2076
|
for (const [rel, content] of Object.entries(buildClaudePluginFiles())) {
|
|
1761
|
-
const dest =
|
|
1762
|
-
await
|
|
1763
|
-
await
|
|
2077
|
+
const dest = path14__default.join(dir, rel);
|
|
2078
|
+
await fs6.mkdir(path14__default.dirname(dest), { recursive: true });
|
|
2079
|
+
await fs6.writeFile(dest, content);
|
|
1764
2080
|
}
|
|
1765
|
-
const projectSkillsDir =
|
|
2081
|
+
const projectSkillsDir = path14__default.join(projectDir, ".skaile", "skills");
|
|
1766
2082
|
if (existsSync(projectSkillsDir)) {
|
|
1767
|
-
await copyDir(projectSkillsDir,
|
|
2083
|
+
await copyDir(projectSkillsDir, path14__default.join(dir, "skills"));
|
|
1768
2084
|
}
|
|
1769
|
-
const settingsPath =
|
|
2085
|
+
const settingsPath = path14__default.join(projectDir, ".claude", "settings.json");
|
|
1770
2086
|
const settings = await readJsonStrict(settingsPath) ?? {};
|
|
1771
2087
|
const plugins = settings.plugins ?? [];
|
|
1772
2088
|
if (!plugins.includes(dir)) plugins.push(dir);
|
|
@@ -1774,13 +2090,13 @@ async function installFullPlugin(projectDir) {
|
|
|
1774
2090
|
return { changed: true, method: "plugin" };
|
|
1775
2091
|
}
|
|
1776
2092
|
async function uninstall(projectDir) {
|
|
1777
|
-
const settingsPath =
|
|
1778
|
-
const mcpPath =
|
|
2093
|
+
const settingsPath = path14__default.join(projectDir, ".claude", "settings.json");
|
|
2094
|
+
const mcpPath = path14__default.join(projectDir, ".claude", "mcp.json");
|
|
1779
2095
|
const dir = pluginDir(projectDir);
|
|
1780
2096
|
let changed = false;
|
|
1781
2097
|
const settings = await readJsonStrict(settingsPath);
|
|
1782
2098
|
if (settings && Array.isArray(settings.plugins)) {
|
|
1783
|
-
const next = settings.plugins.filter((
|
|
2099
|
+
const next = settings.plugins.filter((p9) => p9 !== dir);
|
|
1784
2100
|
if (next.length !== settings.plugins.length) {
|
|
1785
2101
|
changed = true;
|
|
1786
2102
|
const updated = { ...settings, plugins: next };
|
|
@@ -1789,7 +2105,7 @@ async function uninstall(projectDir) {
|
|
|
1789
2105
|
}
|
|
1790
2106
|
}
|
|
1791
2107
|
if (existsSync(dir)) {
|
|
1792
|
-
await
|
|
2108
|
+
await fs6.rm(dir, { recursive: true, force: true });
|
|
1793
2109
|
changed = true;
|
|
1794
2110
|
}
|
|
1795
2111
|
const mcp = await readJsonStrict(mcpPath);
|
|
@@ -1799,7 +2115,7 @@ async function uninstall(projectDir) {
|
|
|
1799
2115
|
const updated = { ...mcp, mcpServers: rest };
|
|
1800
2116
|
if (Object.keys(rest).length === 0) delete updated.mcpServers;
|
|
1801
2117
|
if (Object.keys(updated).length === 0) {
|
|
1802
|
-
await
|
|
2118
|
+
await fs6.unlink(mcpPath);
|
|
1803
2119
|
} else {
|
|
1804
2120
|
await writeJson(mcpPath, updated);
|
|
1805
2121
|
}
|
|
@@ -1809,12 +2125,12 @@ async function uninstall(projectDir) {
|
|
|
1809
2125
|
async function detectInstall(projectDir) {
|
|
1810
2126
|
const dir = pluginDir(projectDir);
|
|
1811
2127
|
const settings = await readJsonStrict(
|
|
1812
|
-
|
|
2128
|
+
path14__default.join(projectDir, ".claude", "settings.json")
|
|
1813
2129
|
);
|
|
1814
|
-
if (existsSync(
|
|
2130
|
+
if (existsSync(path14__default.join(dir, ".claude-plugin", "plugin.json")) && settings?.plugins?.includes(dir)) {
|
|
1815
2131
|
return { method: "plugin", pluginPath: dir };
|
|
1816
2132
|
}
|
|
1817
|
-
const mcp = await readJsonStrict(
|
|
2133
|
+
const mcp = await readJsonStrict(path14__default.join(projectDir, ".claude", "mcp.json"));
|
|
1818
2134
|
if (mcp?.mcpServers && SKAILE_MCP_NAME in mcp.mcpServers) {
|
|
1819
2135
|
return { method: "mcp" };
|
|
1820
2136
|
}
|
|
@@ -1823,11 +2139,11 @@ async function detectInstall(projectDir) {
|
|
|
1823
2139
|
async function enable(projectDir) {
|
|
1824
2140
|
const detected = await detectInstall(projectDir);
|
|
1825
2141
|
if (!detected) throw new Error("plugin not installed for claude-code");
|
|
1826
|
-
const settingsPath =
|
|
2142
|
+
const settingsPath = path14__default.join(projectDir, ".claude", "settings.json");
|
|
1827
2143
|
const settings = await readJsonStrict(settingsPath) ?? {};
|
|
1828
2144
|
if (detected.method === "plugin") {
|
|
1829
2145
|
const disabled2 = settings.disabledPlugins ?? [];
|
|
1830
|
-
const next2 = disabled2.filter((
|
|
2146
|
+
const next2 = disabled2.filter((p9) => p9 !== detected.pluginPath);
|
|
1831
2147
|
if (next2.length === disabled2.length) return { changed: false };
|
|
1832
2148
|
const updated2 = { ...settings, disabledPlugins: next2 };
|
|
1833
2149
|
if (next2.length === 0) delete updated2.disabledPlugins;
|
|
@@ -1845,7 +2161,7 @@ async function enable(projectDir) {
|
|
|
1845
2161
|
async function disable(projectDir) {
|
|
1846
2162
|
const detected = await detectInstall(projectDir);
|
|
1847
2163
|
if (!detected) throw new Error("plugin not installed for claude-code");
|
|
1848
|
-
const settingsPath =
|
|
2164
|
+
const settingsPath = path14__default.join(projectDir, ".claude", "settings.json");
|
|
1849
2165
|
const settings = await readJsonStrict(settingsPath) ?? {};
|
|
1850
2166
|
if (detected.method === "plugin") {
|
|
1851
2167
|
const list2 = settings.disabledPlugins ?? [];
|
|
@@ -1865,12 +2181,12 @@ async function disable(projectDir) {
|
|
|
1865
2181
|
return { changed: true };
|
|
1866
2182
|
}
|
|
1867
2183
|
async function status(projectDir) {
|
|
1868
|
-
const settingsPath =
|
|
1869
|
-
const mcpPath =
|
|
2184
|
+
const settingsPath = path14__default.join(projectDir, ".claude", "settings.json");
|
|
2185
|
+
const mcpPath = path14__default.join(projectDir, ".claude", "mcp.json");
|
|
1870
2186
|
const dir = pluginDir(projectDir);
|
|
1871
2187
|
const settings = await readJsonStrict(settingsPath);
|
|
1872
2188
|
const mcp = await readJsonStrict(mcpPath);
|
|
1873
|
-
const pluginInstalled = !!(existsSync(
|
|
2189
|
+
const pluginInstalled = !!(existsSync(path14__default.join(dir, ".claude-plugin", "plugin.json")) && settings?.plugins?.includes(dir));
|
|
1874
2190
|
const mcpInstalled = !!(mcp?.mcpServers && SKAILE_MCP_NAME in mcp.mcpServers);
|
|
1875
2191
|
if (!pluginInstalled && !mcpInstalled) {
|
|
1876
2192
|
return {
|
|
@@ -1888,7 +2204,7 @@ async function status(projectDir) {
|
|
|
1888
2204
|
installed: "yes",
|
|
1889
2205
|
enabled: disabled2 ? "no" : "yes",
|
|
1890
2206
|
method: "plugin",
|
|
1891
|
-
location:
|
|
2207
|
+
location: path14__default.relative(projectDir, dir)
|
|
1892
2208
|
};
|
|
1893
2209
|
}
|
|
1894
2210
|
const disabled = settings?.disabledMcpjsonServers?.includes(SKAILE_MCP_NAME) ?? false;
|
|
@@ -1897,7 +2213,7 @@ async function status(projectDir) {
|
|
|
1897
2213
|
installed: "yes",
|
|
1898
2214
|
enabled: disabled ? "no" : "yes",
|
|
1899
2215
|
method: "mcp",
|
|
1900
|
-
location:
|
|
2216
|
+
location: path14__default.relative(projectDir, mcpPath)
|
|
1901
2217
|
};
|
|
1902
2218
|
}
|
|
1903
2219
|
var SKAILE_MCP_NAME2 = "skaile-workspace";
|
|
@@ -1908,10 +2224,10 @@ function buildEntry(projectDir) {
|
|
|
1908
2224
|
env: { SKAILE_PROJECT_DIR: projectDir }
|
|
1909
2225
|
};
|
|
1910
2226
|
}
|
|
1911
|
-
async function readConfig(
|
|
2227
|
+
async function readConfig(p9) {
|
|
1912
2228
|
let raw;
|
|
1913
2229
|
try {
|
|
1914
|
-
raw = await
|
|
2230
|
+
raw = await fs6.readFile(p9, "utf-8");
|
|
1915
2231
|
} catch {
|
|
1916
2232
|
return null;
|
|
1917
2233
|
}
|
|
@@ -1919,41 +2235,41 @@ async function readConfig(p8) {
|
|
|
1919
2235
|
return parse$1(raw);
|
|
1920
2236
|
} catch (e) {
|
|
1921
2237
|
throw new Error(
|
|
1922
|
-
`cannot parse ${
|
|
2238
|
+
`cannot parse ${p9}: ${e instanceof Error ? e.message : String(e)}; please fix or remove`
|
|
1923
2239
|
);
|
|
1924
2240
|
}
|
|
1925
2241
|
}
|
|
1926
|
-
async function writeConfig(
|
|
1927
|
-
await
|
|
2242
|
+
async function writeConfig(p9, value) {
|
|
2243
|
+
await fs6.mkdir(path14__default.dirname(p9), { recursive: true });
|
|
1928
2244
|
const cleaned = {};
|
|
1929
2245
|
for (const [k, v] of Object.entries(value)) {
|
|
1930
2246
|
if (v === void 0) continue;
|
|
1931
2247
|
cleaned[k] = v;
|
|
1932
2248
|
}
|
|
1933
|
-
await
|
|
2249
|
+
await fs6.writeFile(p9, stringify$1(cleaned));
|
|
1934
2250
|
}
|
|
1935
2251
|
function configPath(projectDir) {
|
|
1936
|
-
return
|
|
2252
|
+
return path14__default.join(projectDir, ".codex", "config.toml");
|
|
1937
2253
|
}
|
|
1938
2254
|
async function install2(projectDir) {
|
|
1939
|
-
const
|
|
1940
|
-
const cfg = await readConfig(
|
|
2255
|
+
const p9 = configPath(projectDir);
|
|
2256
|
+
const cfg = await readConfig(p9) ?? {};
|
|
1941
2257
|
const next = buildEntry(projectDir);
|
|
1942
2258
|
const servers = { ...cfg.mcp_servers ?? {} };
|
|
1943
2259
|
const previous = servers[SKAILE_MCP_NAME2];
|
|
1944
2260
|
const matches = previous && JSON.stringify(previous) === JSON.stringify(next);
|
|
1945
2261
|
let warning;
|
|
1946
2262
|
if (previous && !matches) {
|
|
1947
|
-
warning = `overwrote existing ${SKAILE_MCP_NAME2} entry in ${
|
|
2263
|
+
warning = `overwrote existing ${SKAILE_MCP_NAME2} entry in ${path14__default.relative(projectDir, p9)}`;
|
|
1948
2264
|
}
|
|
1949
2265
|
if (matches) return { changed: false, method: "toml" };
|
|
1950
2266
|
servers[SKAILE_MCP_NAME2] = next;
|
|
1951
|
-
await writeConfig(
|
|
2267
|
+
await writeConfig(p9, { ...cfg, mcp_servers: servers });
|
|
1952
2268
|
return { changed: true, method: "toml", warning };
|
|
1953
2269
|
}
|
|
1954
2270
|
async function uninstall2(projectDir) {
|
|
1955
|
-
const
|
|
1956
|
-
const cfg = await readConfig(
|
|
2271
|
+
const p9 = configPath(projectDir);
|
|
2272
|
+
const cfg = await readConfig(p9);
|
|
1957
2273
|
if (!cfg?.mcp_servers || !(SKAILE_MCP_NAME2 in cfg.mcp_servers)) {
|
|
1958
2274
|
return { changed: false };
|
|
1959
2275
|
}
|
|
@@ -1961,15 +2277,15 @@ async function uninstall2(projectDir) {
|
|
|
1961
2277
|
const updated = { ...cfg, mcp_servers: rest };
|
|
1962
2278
|
if (Object.keys(rest).length === 0) delete updated.mcp_servers;
|
|
1963
2279
|
if (Object.keys(updated).length === 0) {
|
|
1964
|
-
await
|
|
2280
|
+
await fs6.unlink(p9);
|
|
1965
2281
|
} else {
|
|
1966
|
-
await writeConfig(
|
|
2282
|
+
await writeConfig(p9, updated);
|
|
1967
2283
|
}
|
|
1968
2284
|
return { changed: true };
|
|
1969
2285
|
}
|
|
1970
2286
|
async function status2(projectDir) {
|
|
1971
|
-
const
|
|
1972
|
-
const cfg = await readConfig(
|
|
2287
|
+
const p9 = configPath(projectDir);
|
|
2288
|
+
const cfg = await readConfig(p9);
|
|
1973
2289
|
const installed = !!(cfg?.mcp_servers && SKAILE_MCP_NAME2 in cfg.mcp_servers);
|
|
1974
2290
|
if (!installed) {
|
|
1975
2291
|
return {
|
|
@@ -1985,43 +2301,43 @@ async function status2(projectDir) {
|
|
|
1985
2301
|
installed: "yes",
|
|
1986
2302
|
enabled: "n/a",
|
|
1987
2303
|
method: "mcp",
|
|
1988
|
-
location:
|
|
2304
|
+
location: path14__default.relative(projectDir, p9)
|
|
1989
2305
|
};
|
|
1990
2306
|
}
|
|
1991
2307
|
async function install3(projectDir) {
|
|
1992
|
-
const extDir =
|
|
1993
|
-
const extPath =
|
|
1994
|
-
await
|
|
2308
|
+
const extDir = path14__default.join(projectDir, ".omp", "extensions");
|
|
2309
|
+
const extPath = path14__default.join(extDir, "skaile.ts");
|
|
2310
|
+
await fs6.mkdir(extDir, { recursive: true });
|
|
1995
2311
|
const { WorkspacePlugin } = await import('../workspace-plugin/index.js');
|
|
1996
2312
|
const plugin = new WorkspacePlugin({ projectDir });
|
|
1997
2313
|
const nextSrc = await plugin.buildOmpExtensionSource();
|
|
1998
2314
|
let prevSrc = null;
|
|
1999
2315
|
try {
|
|
2000
|
-
prevSrc = await
|
|
2316
|
+
prevSrc = await fs6.readFile(extPath, "utf-8");
|
|
2001
2317
|
} catch {
|
|
2002
2318
|
}
|
|
2003
2319
|
if (prevSrc === nextSrc) return { changed: false, method: "generated" };
|
|
2004
|
-
await
|
|
2320
|
+
await fs6.writeFile(extPath, nextSrc);
|
|
2005
2321
|
return { changed: true, method: "generated" };
|
|
2006
2322
|
}
|
|
2007
2323
|
async function uninstall3(projectDir) {
|
|
2008
|
-
const extPath =
|
|
2324
|
+
const extPath = path14__default.join(projectDir, ".omp", "extensions", "skaile.ts");
|
|
2009
2325
|
try {
|
|
2010
|
-
await
|
|
2326
|
+
await fs6.unlink(extPath);
|
|
2011
2327
|
return { changed: true };
|
|
2012
2328
|
} catch {
|
|
2013
2329
|
return { changed: false };
|
|
2014
2330
|
}
|
|
2015
2331
|
}
|
|
2016
2332
|
async function status3(projectDir) {
|
|
2017
|
-
const extPath =
|
|
2333
|
+
const extPath = path14__default.join(projectDir, ".omp", "extensions", "skaile.ts");
|
|
2018
2334
|
if (existsSync(extPath)) {
|
|
2019
2335
|
return {
|
|
2020
2336
|
backend: "omp",
|
|
2021
2337
|
installed: "yes",
|
|
2022
2338
|
enabled: "n/a",
|
|
2023
2339
|
method: "extension",
|
|
2024
|
-
location:
|
|
2340
|
+
location: path14__default.relative(projectDir, extPath)
|
|
2025
2341
|
};
|
|
2026
2342
|
}
|
|
2027
2343
|
return {
|
|
@@ -2084,7 +2400,7 @@ async function installCodex(projectDir) {
|
|
|
2084
2400
|
console.log(` ${S.dim("\u2192")} Restart Codex CLI to pick up the change.`);
|
|
2085
2401
|
}
|
|
2086
2402
|
async function runInstall(opts) {
|
|
2087
|
-
const projectDir =
|
|
2403
|
+
const projectDir = path14__default.resolve(opts.projectDir);
|
|
2088
2404
|
const targets = resolveDriver(opts.driver);
|
|
2089
2405
|
let exitCode = 0;
|
|
2090
2406
|
if (targets.includes("claude-code")) {
|
|
@@ -2118,7 +2434,7 @@ async function uninstallCodex(projectDir) {
|
|
|
2118
2434
|
else logInfo(`codex: not installed`);
|
|
2119
2435
|
}
|
|
2120
2436
|
async function runUninstall(opts) {
|
|
2121
|
-
const projectDir =
|
|
2437
|
+
const projectDir = path14__default.resolve(opts.projectDir);
|
|
2122
2438
|
const targets = resolveDriver(opts.driver);
|
|
2123
2439
|
let exitCode = 0;
|
|
2124
2440
|
if (targets.includes("claude-code")) {
|
|
@@ -2161,7 +2477,7 @@ async function toggleTarget(t, projectDir, action3) {
|
|
|
2161
2477
|
});
|
|
2162
2478
|
}
|
|
2163
2479
|
async function runToggle(opts, action3) {
|
|
2164
|
-
const projectDir =
|
|
2480
|
+
const projectDir = path14__default.resolve(opts.projectDir);
|
|
2165
2481
|
const requestedAll = opts.driver === "all";
|
|
2166
2482
|
const targets = resolveDriver(opts.driver);
|
|
2167
2483
|
const usageError = checkToggleSupported(targets, requestedAll, action3);
|
|
@@ -2173,7 +2489,7 @@ async function runToggle(opts, action3) {
|
|
|
2173
2489
|
return exitCode;
|
|
2174
2490
|
}
|
|
2175
2491
|
async function runStatus2(opts) {
|
|
2176
|
-
const projectDir =
|
|
2492
|
+
const projectDir = path14__default.resolve(opts.projectDir);
|
|
2177
2493
|
const targets = resolveDriver(opts.driver);
|
|
2178
2494
|
const rows = [];
|
|
2179
2495
|
let exitCode = 0;
|
|
@@ -2202,7 +2518,7 @@ function printStatusTable(rows) {
|
|
|
2202
2518
|
const widths = cols.map(
|
|
2203
2519
|
(c) => Math.max(c.header.length, ...rows.map((r) => String(r[c.key] ?? "").length))
|
|
2204
2520
|
);
|
|
2205
|
-
const fmtRow = (parts) => parts.map((
|
|
2521
|
+
const fmtRow = (parts) => parts.map((p9, i) => p9.padEnd(widths[i] ?? p9.length)).join(" ");
|
|
2206
2522
|
console.log();
|
|
2207
2523
|
console.log(` ${S.heading(fmtRow(cols.map((c) => c.header)))}`);
|
|
2208
2524
|
for (const r of rows) {
|
|
@@ -2244,7 +2560,7 @@ async function runHook(event) {
|
|
|
2244
2560
|
await plugin.shutdown();
|
|
2245
2561
|
return;
|
|
2246
2562
|
}
|
|
2247
|
-
const store = new PluginStore(
|
|
2563
|
+
const store = new PluginStore(path14__default.join(projectDir, ".skaile", "plugin-state.json"));
|
|
2248
2564
|
await store.load();
|
|
2249
2565
|
const status4 = store.get("connector:status");
|
|
2250
2566
|
if (status4 && typeof status4 === "object" && Object.keys(status4).length > 0) {
|
|
@@ -2366,12 +2682,12 @@ function makeLibraryCommand() {
|
|
|
2366
2682
|
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(
|
|
2367
2683
|
async (name, opts) => {
|
|
2368
2684
|
const libDir = resolveLibraryDir();
|
|
2369
|
-
const libPath =
|
|
2685
|
+
const libPath = path14.join(libDir, name);
|
|
2370
2686
|
const ownership = opts.contributor ? "contributor" : opts.reader ? "reader" : "owner";
|
|
2371
2687
|
const { manager, close } = await openLibraryManager();
|
|
2372
2688
|
try {
|
|
2373
2689
|
if (opts.git) {
|
|
2374
|
-
|
|
2690
|
+
fs12.mkdirSync(libPath, { recursive: true });
|
|
2375
2691
|
await manager.addLibrary({
|
|
2376
2692
|
name,
|
|
2377
2693
|
path: libPath,
|
|
@@ -2380,7 +2696,7 @@ function makeLibraryCommand() {
|
|
|
2380
2696
|
ownership
|
|
2381
2697
|
});
|
|
2382
2698
|
} else {
|
|
2383
|
-
|
|
2699
|
+
fs12.mkdirSync(libPath, { recursive: true });
|
|
2384
2700
|
await manager.addLibrary({
|
|
2385
2701
|
name,
|
|
2386
2702
|
path: libPath,
|
|
@@ -2437,7 +2753,7 @@ function makeLibraryCommand() {
|
|
|
2437
2753
|
target = def;
|
|
2438
2754
|
}
|
|
2439
2755
|
const am2 = new AssetManager({ projectDir: process.cwd() });
|
|
2440
|
-
const destDir = opts.dir ?
|
|
2756
|
+
const destDir = opts.dir ? path14.join(target.path, opts.dir) : target.path;
|
|
2441
2757
|
const res = am2.create(name, opts.kind ?? kind, destDir);
|
|
2442
2758
|
if (res.ok) {
|
|
2443
2759
|
logOk(`Created ${opts.kind ?? kind}: ${pc5.dim(res.path)}`);
|
|
@@ -2450,6 +2766,80 @@ function makeLibraryCommand() {
|
|
|
2450
2766
|
}
|
|
2451
2767
|
}
|
|
2452
2768
|
);
|
|
2769
|
+
const domain = cmd.command("domain").description("Manage domains (publisher namespaces) inside a library");
|
|
2770
|
+
async function resolveTargetLibrary(manager, libraryName) {
|
|
2771
|
+
if (libraryName) return manager.requireLibrary(libraryName);
|
|
2772
|
+
const all = await manager.listLibraries();
|
|
2773
|
+
const def = all.find((l) => l.isDefault);
|
|
2774
|
+
if (def) return def;
|
|
2775
|
+
if (all.length === 1) return all[0];
|
|
2776
|
+
if (all.length === 0) {
|
|
2777
|
+
logErr("No libraries registered. Run `skaile library init <name>` first.");
|
|
2778
|
+
process.exit(1);
|
|
2779
|
+
}
|
|
2780
|
+
logErr("No default library set. Run `skaile library default <name>` or pass --library.");
|
|
2781
|
+
process.exit(1);
|
|
2782
|
+
}
|
|
2783
|
+
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(
|
|
2784
|
+
async (name, opts) => {
|
|
2785
|
+
const { manager, close } = await openLibraryManager();
|
|
2786
|
+
try {
|
|
2787
|
+
const target = await resolveTargetLibrary(manager, opts.library);
|
|
2788
|
+
if (target.ownership === "reader") {
|
|
2789
|
+
logErr(`Library "${target.name}" is read-only (ownership=reader).`);
|
|
2790
|
+
process.exit(1);
|
|
2791
|
+
}
|
|
2792
|
+
const res = ensureDomain(target.path, name, {
|
|
2793
|
+
publisher: opts.publisher,
|
|
2794
|
+
description: opts.description
|
|
2795
|
+
});
|
|
2796
|
+
if (target.structure !== "domain") {
|
|
2797
|
+
await manager.updateLibrary(target.id, { structure: "domain" });
|
|
2798
|
+
}
|
|
2799
|
+
if (res.created) {
|
|
2800
|
+
logOk(`Created domain ${S.cmd(name)} (publisher @${res.publisher}) \u2192 ${res.dir}`);
|
|
2801
|
+
} else {
|
|
2802
|
+
logInfo(`Domain ${S.cmd(name)} already exists at ${res.dir}`);
|
|
2803
|
+
}
|
|
2804
|
+
} finally {
|
|
2805
|
+
close();
|
|
2806
|
+
}
|
|
2807
|
+
}
|
|
2808
|
+
);
|
|
2809
|
+
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) => {
|
|
2810
|
+
const { manager, close } = await openLibraryManager();
|
|
2811
|
+
try {
|
|
2812
|
+
const target = await resolveTargetLibrary(manager, opts.library);
|
|
2813
|
+
const domains = listDomains(target.path);
|
|
2814
|
+
if (opts.json) return console.log(JSON.stringify(domains, null, 2));
|
|
2815
|
+
if (domains.length === 0) {
|
|
2816
|
+
logInfo(
|
|
2817
|
+
`No domains in "${target.name}". Create one: \`skaile library domain create <name>\`.`
|
|
2818
|
+
);
|
|
2819
|
+
return;
|
|
2820
|
+
}
|
|
2821
|
+
for (const d of domains) console.log(` ${S.cmd(d)}`);
|
|
2822
|
+
console.log(`
|
|
2823
|
+
${S.dim(`${domains.length} domain(s) in ${target.name}`)}
|
|
2824
|
+
`);
|
|
2825
|
+
} finally {
|
|
2826
|
+
close();
|
|
2827
|
+
}
|
|
2828
|
+
});
|
|
2829
|
+
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) => {
|
|
2830
|
+
const { manager, close } = await openLibraryManager();
|
|
2831
|
+
try {
|
|
2832
|
+
const target = await resolveTargetLibrary(manager, opts.library);
|
|
2833
|
+
const domainFile = path14.join(target.path, name, "DOMAIN.md");
|
|
2834
|
+
if (!existsSync(domainFile)) {
|
|
2835
|
+
logErr(`Domain "${name}" not found in "${target.name}" (no ${domainFile}).`);
|
|
2836
|
+
process.exit(1);
|
|
2837
|
+
}
|
|
2838
|
+
console.log(fs12.readFileSync(domainFile, "utf8"));
|
|
2839
|
+
} finally {
|
|
2840
|
+
close();
|
|
2841
|
+
}
|
|
2842
|
+
});
|
|
2453
2843
|
cmd.command("default <name>").description("Set <name> as the default library").action(async (name) => {
|
|
2454
2844
|
const { manager, close } = await openLibraryManager();
|
|
2455
2845
|
try {
|
|
@@ -2463,13 +2853,13 @@ function makeLibraryCommand() {
|
|
|
2463
2853
|
const { manager, close } = await openLibraryManager();
|
|
2464
2854
|
try {
|
|
2465
2855
|
const lib = await manager.requireLibrary(oldName);
|
|
2466
|
-
const parent =
|
|
2467
|
-
const newPath =
|
|
2468
|
-
if (
|
|
2856
|
+
const parent = path14.dirname(lib.path);
|
|
2857
|
+
const newPath = path14.join(parent, newName);
|
|
2858
|
+
if (fs12.existsSync(newPath)) {
|
|
2469
2859
|
logErr(`Target directory already exists: ${newPath}`);
|
|
2470
2860
|
process.exit(1);
|
|
2471
2861
|
}
|
|
2472
|
-
|
|
2862
|
+
fs12.renameSync(lib.path, newPath);
|
|
2473
2863
|
await manager.updateLibrary(lib.id, { name: newName, path: newPath });
|
|
2474
2864
|
logOk(`Renamed ${oldName} \u2192 ${newName}`);
|
|
2475
2865
|
} finally {
|
|
@@ -2503,11 +2893,11 @@ function makeLibraryCommand() {
|
|
|
2503
2893
|
const { manager, close } = await openLibraryManager();
|
|
2504
2894
|
try {
|
|
2505
2895
|
if (!opts.yes) {
|
|
2506
|
-
const confirmed = await
|
|
2896
|
+
const confirmed = await p6.confirm({
|
|
2507
2897
|
message: `Remove library "${name}"${opts.purge ? " AND delete its directory" : ""}?`,
|
|
2508
2898
|
initialValue: false
|
|
2509
2899
|
});
|
|
2510
|
-
if (!confirmed ||
|
|
2900
|
+
if (!confirmed || p6.isCancel(confirmed)) {
|
|
2511
2901
|
logInfo("Cancelled.");
|
|
2512
2902
|
return;
|
|
2513
2903
|
}
|
|
@@ -2653,9 +3043,9 @@ async function printOverallStatus(projectDir, asJson) {
|
|
|
2653
3043
|
} catch {
|
|
2654
3044
|
secretsStrategy = "unavailable";
|
|
2655
3045
|
}
|
|
2656
|
-
const resolvedProjectDir =
|
|
2657
|
-
const hasWorkspaceConfig = existsSync(
|
|
2658
|
-
const hasLockFile = existsSync(
|
|
3046
|
+
const resolvedProjectDir = path14.resolve(projectDir);
|
|
3047
|
+
const hasWorkspaceConfig = existsSync(path14.join(resolvedProjectDir, "skaile.yaml"));
|
|
3048
|
+
const hasLockFile = existsSync(path14.join(resolvedProjectDir, "skaile.lock.yaml"));
|
|
2659
3049
|
let assignments = [];
|
|
2660
3050
|
if (hasWorkspaceConfig) {
|
|
2661
3051
|
try {
|
|
@@ -3011,7 +3401,7 @@ function actOnHeader(row, action3) {
|
|
|
3011
3401
|
return row.type === "domain-header" || row.type === "domain-info";
|
|
3012
3402
|
}
|
|
3013
3403
|
async function loadAssets() {
|
|
3014
|
-
const { gatherAssetFeeds } = await import('../asset-feeds-
|
|
3404
|
+
const { gatherAssetFeeds } = await import('../asset-feeds-AOZLZMDV.js');
|
|
3015
3405
|
const { entries, domains, notes } = await gatherAssetFeeds(am, am.projectDir);
|
|
3016
3406
|
if (notes.length > 0) {
|
|
3017
3407
|
state.message = notes.map((n) => `[${n.feed}] ${n.message}`).join(" \u2022 ");
|
|
@@ -3108,14 +3498,16 @@ function reconcileCollapsedSets(rows) {
|
|
|
3108
3498
|
}
|
|
3109
3499
|
async function loadSourcesAndLibraries() {
|
|
3110
3500
|
try {
|
|
3111
|
-
const [{ openLibraryManager: openLibraryManager2 }, { skaileHomeDir:
|
|
3112
|
-
import('../open-library-
|
|
3113
|
-
import('../library/index.js')
|
|
3501
|
+
const [{ openLibraryManager: openLibraryManager2 }, { skaileHomeDir }, { getGlobalCacheDir: getGlobalCacheDir2 }] = await Promise.all([
|
|
3502
|
+
import('../open-library-362BZ6OW.js'),
|
|
3503
|
+
import('../library/index.js'),
|
|
3504
|
+
import('../core/index.js')
|
|
3114
3505
|
]);
|
|
3115
3506
|
const { manager, library, close } = await openLibraryManager2();
|
|
3116
3507
|
try {
|
|
3117
|
-
const
|
|
3118
|
-
const
|
|
3508
|
+
const newRoot = getGlobalCacheDir2();
|
|
3509
|
+
const legacyRoot = path14__default.join(skaileHomeDir(), "sources");
|
|
3510
|
+
const isSourceRow = (l) => l.path.startsWith(newRoot) || l.path.startsWith(legacyRoot);
|
|
3119
3511
|
const libs = await manager.listLibraries();
|
|
3120
3512
|
const defs = await library.listAssetDefs();
|
|
3121
3513
|
const counts = /* @__PURE__ */ new Map();
|
|
@@ -3494,10 +3886,10 @@ async function showInfo() {
|
|
|
3494
3886
|
}
|
|
3495
3887
|
console.log();
|
|
3496
3888
|
console.log(pc5.dim(" Press any key to return..."));
|
|
3497
|
-
await new Promise((
|
|
3889
|
+
await new Promise((resolve5) => {
|
|
3498
3890
|
const onData = () => {
|
|
3499
3891
|
process.stdin.removeListener("data", onData);
|
|
3500
|
-
|
|
3892
|
+
resolve5();
|
|
3501
3893
|
};
|
|
3502
3894
|
process.stdin.once("data", onData);
|
|
3503
3895
|
});
|
|
@@ -3750,13 +4142,13 @@ async function run(projectDir) {
|
|
|
3750
4142
|
}
|
|
3751
4143
|
function makeManageCommand() {
|
|
3752
4144
|
return new Command("manage").description("Interactive TUI for managing assets, sources, and libraries").option("--project-dir <path>", "Project directory", process.cwd()).action(async (opts) => {
|
|
3753
|
-
await run(
|
|
4145
|
+
await run(path14__default.resolve(opts.projectDir));
|
|
3754
4146
|
});
|
|
3755
4147
|
}
|
|
3756
4148
|
function makeMcpServerCommand() {
|
|
3757
4149
|
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) => {
|
|
3758
|
-
const
|
|
3759
|
-
const projectDir =
|
|
4150
|
+
const path37 = await import('path');
|
|
4151
|
+
const projectDir = path37.default.resolve(opts.projectDir);
|
|
3760
4152
|
const { LogStore, StdoutSink, registerLogStore } = await import('../core/logging.js');
|
|
3761
4153
|
registerLogStore(
|
|
3762
4154
|
new LogStore({
|
|
@@ -3793,8 +4185,8 @@ function makeNpxCommand() {
|
|
|
3793
4185
|
skills.command("add <url>").description(
|
|
3794
4186
|
"Clone a repo, register it in the project's skaile.yaml sources[], and install a skill from it"
|
|
3795
4187
|
).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) => {
|
|
3796
|
-
const projectDir =
|
|
3797
|
-
const projYaml =
|
|
4188
|
+
const projectDir = path14__default.resolve(opts.projectDir);
|
|
4189
|
+
const projYaml = path14__default.join(projectDir, "skaile.yaml");
|
|
3798
4190
|
if (!existsSync(projYaml)) {
|
|
3799
4191
|
logErr(`No skaile.yaml in ${projectDir} \u2014 run \`skaile init\` first.`);
|
|
3800
4192
|
process.exit(1);
|
|
@@ -3805,9 +4197,9 @@ function makeNpxCommand() {
|
|
|
3805
4197
|
);
|
|
3806
4198
|
process.exit(1);
|
|
3807
4199
|
}
|
|
3808
|
-
const spinner5 =
|
|
4200
|
+
const spinner5 = p6.spinner();
|
|
3809
4201
|
const slug = sourceSlug(url);
|
|
3810
|
-
const clonePath =
|
|
4202
|
+
const clonePath = path14__default.join(getGlobalCacheDir(), slug);
|
|
3811
4203
|
spinner5.start(`Cloning ${url}`);
|
|
3812
4204
|
try {
|
|
3813
4205
|
if (!existsSync(clonePath)) {
|
|
@@ -3856,7 +4248,7 @@ function makeNpxCommand() {
|
|
|
3856
4248
|
return npx;
|
|
3857
4249
|
}
|
|
3858
4250
|
function resolvePublisher(clonePath, url) {
|
|
3859
|
-
const manifestPath =
|
|
4251
|
+
const manifestPath = path14__default.join(clonePath, SKAILE_MANIFEST_FILENAME);
|
|
3860
4252
|
if (existsSync(manifestPath)) {
|
|
3861
4253
|
try {
|
|
3862
4254
|
const { manifest } = decodeSkaileManifest(readFileSync(manifestPath, "utf8"));
|
|
@@ -3869,12 +4261,12 @@ function resolvePublisher(clonePath, url) {
|
|
|
3869
4261
|
return url.match(/github\.com[/:]([^/]+)\/[^/]+/)?.[1];
|
|
3870
4262
|
}
|
|
3871
4263
|
function resolveSkillName(clonePath, requested) {
|
|
3872
|
-
const skillsDir =
|
|
3873
|
-
if (existsSync(
|
|
4264
|
+
const skillsDir = path14__default.join(clonePath, "skills");
|
|
4265
|
+
if (existsSync(path14__default.join(skillsDir, requested, "SKILL.md"))) return requested;
|
|
3874
4266
|
if (!existsSync(skillsDir)) return requested;
|
|
3875
4267
|
for (const entry of readdirSync(skillsDir, { withFileTypes: true })) {
|
|
3876
4268
|
if (!entry.isDirectory()) continue;
|
|
3877
|
-
const md =
|
|
4269
|
+
const md = path14__default.join(skillsDir, entry.name, "SKILL.md");
|
|
3878
4270
|
if (!existsSync(md)) continue;
|
|
3879
4271
|
try {
|
|
3880
4272
|
const { data } = parseFrontmatter(readFileSync(md, "utf8"));
|
|
@@ -3892,7 +4284,7 @@ function makeOutdatedCommand() {
|
|
|
3892
4284
|
new Option("--target <agent>", "Driver target").default("claude-code").choices(SUPPORTED_DRIVER_TARGETS)
|
|
3893
4285
|
).action((name, opts) => {
|
|
3894
4286
|
const am2 = new AssetManager({
|
|
3895
|
-
projectDir:
|
|
4287
|
+
projectDir: path14__default.resolve(opts.projectDir),
|
|
3896
4288
|
driverTarget: opts.target
|
|
3897
4289
|
});
|
|
3898
4290
|
const entries = am2.outdated();
|
|
@@ -3921,7 +4313,7 @@ function makeOutdatedCommand() {
|
|
|
3921
4313
|
function makePatchCommand() {
|
|
3922
4314
|
const cmd = new Command("patch").description("Patch workflow for skill improvement");
|
|
3923
4315
|
cmd.command("extract <ref>").alias("start").description("Extract asset for local editing").option("--project-dir <path>", "Project directory", process.cwd()).action((ref, opts) => {
|
|
3924
|
-
const am2 = new AssetManager({ projectDir:
|
|
4316
|
+
const am2 = new AssetManager({ projectDir: path14__default.resolve(opts.projectDir) });
|
|
3925
4317
|
try {
|
|
3926
4318
|
const dest = am2.patch(ref);
|
|
3927
4319
|
logOk(`Extracted to ${S.dim(dest)}`);
|
|
@@ -3932,7 +4324,7 @@ function makePatchCommand() {
|
|
|
3932
4324
|
}
|
|
3933
4325
|
});
|
|
3934
4326
|
cmd.command("commit <ref>").description("Generate .patch file from edits").option("--project-dir <path>", "Project directory", process.cwd()).action((ref, opts) => {
|
|
3935
|
-
const am2 = new AssetManager({ projectDir:
|
|
4327
|
+
const am2 = new AssetManager({ projectDir: path14__default.resolve(opts.projectDir) });
|
|
3936
4328
|
try {
|
|
3937
4329
|
const patchFile = am2.patchCommit(ref);
|
|
3938
4330
|
logOk(`Patch saved to ${S.dim(patchFile)}`);
|
|
@@ -3943,7 +4335,7 @@ function makePatchCommand() {
|
|
|
3943
4335
|
}
|
|
3944
4336
|
});
|
|
3945
4337
|
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) => {
|
|
3946
|
-
const am2 = new AssetManager({ projectDir:
|
|
4338
|
+
const am2 = new AssetManager({ projectDir: path14__default.resolve(opts.projectDir) });
|
|
3947
4339
|
try {
|
|
3948
4340
|
am2.patchSubmit(ref);
|
|
3949
4341
|
logOk("Patch applied to repo clone and committed.");
|
|
@@ -3956,7 +4348,7 @@ function makePatchCommand() {
|
|
|
3956
4348
|
}
|
|
3957
4349
|
});
|
|
3958
4350
|
cmd.command("remove <ref>").description("Remove local patch after upstream merge").option("--project-dir <path>", "Project directory", process.cwd()).action((ref, opts) => {
|
|
3959
|
-
const am2 = new AssetManager({ projectDir:
|
|
4351
|
+
const am2 = new AssetManager({ projectDir: path14__default.resolve(opts.projectDir) });
|
|
3960
4352
|
am2.patchRemove(ref);
|
|
3961
4353
|
logOk(`Patch removed for ${ref}`);
|
|
3962
4354
|
});
|
|
@@ -3974,7 +4366,7 @@ function action2(fn) {
|
|
|
3974
4366
|
};
|
|
3975
4367
|
}
|
|
3976
4368
|
async function reconcileAndReport(projectDir, plugins) {
|
|
3977
|
-
const { reconcilePlugins } = await import('../plugin-store-
|
|
4369
|
+
const { reconcilePlugins } = await import('../plugin-store-2X2YXJVG.js');
|
|
3978
4370
|
if (plugins.length === 0) {
|
|
3979
4371
|
logInfo("No plugins declared \u2014 nothing to reconcile.");
|
|
3980
4372
|
return;
|
|
@@ -3988,10 +4380,10 @@ async function reconcileAndReport(projectDir, plugins) {
|
|
|
3988
4380
|
}
|
|
3989
4381
|
}
|
|
3990
4382
|
async function runInstall2(spec, opts) {
|
|
3991
|
-
const projectDir =
|
|
4383
|
+
const projectDir = path14__default.resolve(opts.projectDir);
|
|
3992
4384
|
const { WorkspaceYamlEditor: WorkspaceYamlEditor2 } = await import('../core/index.js');
|
|
3993
|
-
const { specName } = await import('../plugin-store-
|
|
3994
|
-
const yamlPath =
|
|
4385
|
+
const { specName } = await import('../plugin-store-2X2YXJVG.js');
|
|
4386
|
+
const yamlPath = path14__default.join(projectDir, "skaile.yaml");
|
|
3995
4387
|
const editor = WorkspaceYamlEditor2.load(yamlPath);
|
|
3996
4388
|
const replaced = editor.addPlugin(spec, specName);
|
|
3997
4389
|
editor.save();
|
|
@@ -4000,10 +4392,10 @@ async function runInstall2(spec, opts) {
|
|
|
4000
4392
|
await reconcileAndReport(projectDir, editor.getPlugins());
|
|
4001
4393
|
}
|
|
4002
4394
|
async function runRemove(name, opts) {
|
|
4003
|
-
const projectDir =
|
|
4395
|
+
const projectDir = path14__default.resolve(opts.projectDir);
|
|
4004
4396
|
const { WorkspaceYamlEditor: WorkspaceYamlEditor2 } = await import('../core/index.js');
|
|
4005
|
-
const { specName } = await import('../plugin-store-
|
|
4006
|
-
const yamlPath =
|
|
4397
|
+
const { specName } = await import('../plugin-store-2X2YXJVG.js');
|
|
4398
|
+
const yamlPath = path14__default.join(projectDir, "skaile.yaml");
|
|
4007
4399
|
const editor = WorkspaceYamlEditor2.load(yamlPath);
|
|
4008
4400
|
const removed = editor.removePlugin(name, specName);
|
|
4009
4401
|
if (!removed) {
|
|
@@ -4015,7 +4407,7 @@ async function runRemove(name, opts) {
|
|
|
4015
4407
|
await reconcileAndReport(projectDir, editor.getPlugins());
|
|
4016
4408
|
}
|
|
4017
4409
|
async function runList(opts) {
|
|
4018
|
-
const projectDir =
|
|
4410
|
+
const projectDir = path14__default.resolve(opts.projectDir);
|
|
4019
4411
|
const { resolveSkWorkspaceConfig: resolveSkWorkspaceConfig2 } = await import('../core/index.js');
|
|
4020
4412
|
const config = resolveSkWorkspaceConfig2(projectDir);
|
|
4021
4413
|
const declared = config.plugins ?? [];
|
|
@@ -4030,7 +4422,7 @@ async function runList(opts) {
|
|
|
4030
4422
|
const registry = createPluginRegistry();
|
|
4031
4423
|
if (declared.length > 0) {
|
|
4032
4424
|
try {
|
|
4033
|
-
const { loadPlugins } = await import('../plugin-store-
|
|
4425
|
+
const { loadPlugins } = await import('../plugin-store-2X2YXJVG.js');
|
|
4034
4426
|
const result = await loadPlugins(projectDir, declared, registry);
|
|
4035
4427
|
for (const f of result.failed) logWarn(f.error);
|
|
4036
4428
|
} catch (err) {
|
|
@@ -4069,7 +4461,7 @@ function makePresetCommand() {
|
|
|
4069
4461
|
cmd.command("init [name]").description("Scaffold a new .preset.yaml file").option("--dir <path>", "Output directory", process.cwd()).action(async (name, opts) => {
|
|
4070
4462
|
const presetName = name ?? "my-preset";
|
|
4071
4463
|
const filename = `${presetName}.preset.yaml`;
|
|
4072
|
-
const outPath =
|
|
4464
|
+
const outPath = path14__default.join(path14__default.resolve(opts.dir), filename);
|
|
4073
4465
|
if (existsSync(outPath)) {
|
|
4074
4466
|
logErr(`File already exists: ${outPath}`);
|
|
4075
4467
|
logInfo("Choose a different name or remove the existing file.");
|
|
@@ -4117,7 +4509,7 @@ async function reportNestedPresetRefs(preset) {
|
|
|
4117
4509
|
}
|
|
4118
4510
|
async function checkPresetCycles(preset, resolved) {
|
|
4119
4511
|
const { detectCycles } = await import('../discovery/index.js');
|
|
4120
|
-
const presetRef =
|
|
4512
|
+
const presetRef = path14__default.basename(resolved, ".preset.yaml");
|
|
4121
4513
|
const edges = [];
|
|
4122
4514
|
for (const item of preset.items) {
|
|
4123
4515
|
if (item.ref) {
|
|
@@ -4168,7 +4560,7 @@ function printPresetSummary(preset, placeholderCount, hasWarnings) {
|
|
|
4168
4560
|
}
|
|
4169
4561
|
}
|
|
4170
4562
|
async function runPresetValidate(filePath) {
|
|
4171
|
-
const resolved =
|
|
4563
|
+
const resolved = path14__default.resolve(filePath);
|
|
4172
4564
|
const preset = await loadPresetForValidation(resolved);
|
|
4173
4565
|
await reportNestedPresetRefs(preset);
|
|
4174
4566
|
await checkPresetCycles(preset, resolved);
|
|
@@ -4259,11 +4651,11 @@ async function runRefInstall(ref, opts) {
|
|
|
4259
4651
|
logErr(`malformed asset ref '${ref}' \u2014 expected ${REF_HINT}`);
|
|
4260
4652
|
process.exit(1);
|
|
4261
4653
|
}
|
|
4262
|
-
const spinner5 =
|
|
4654
|
+
const spinner5 = p6.spinner();
|
|
4263
4655
|
spinner5.start(`Installing ${ref}`);
|
|
4264
4656
|
try {
|
|
4265
|
-
const { openCatalogSource: openCatalogSource2, openLibrary: openLibrary2 } = await import('../open-library-
|
|
4266
|
-
const catalog = await openCatalogSource2({ projectDir:
|
|
4657
|
+
const { openCatalogSource: openCatalogSource2, openLibrary: openLibrary2 } = await import('../open-library-362BZ6OW.js');
|
|
4658
|
+
const catalog = await openCatalogSource2({ projectDir: path14__default.resolve(opts.projectDir) });
|
|
4267
4659
|
if (!supportsInstallManifest(catalog)) {
|
|
4268
4660
|
throw new Error(
|
|
4269
4661
|
"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."
|
|
@@ -4292,9 +4684,9 @@ async function runRefInstall(ref, opts) {
|
|
|
4292
4684
|
}
|
|
4293
4685
|
}
|
|
4294
4686
|
async function runYamlInstall(opts) {
|
|
4295
|
-
const projectDir =
|
|
4687
|
+
const projectDir = path14__default.resolve(opts.projectDir);
|
|
4296
4688
|
try {
|
|
4297
|
-
const { ensureSourcesCloned } = await import('../ensure-sources-
|
|
4689
|
+
const { ensureSourcesCloned } = await import('../ensure-sources-NSDMTAWN.js');
|
|
4298
4690
|
const hydrate = ensureSourcesCloned(projectDir, { quiet: true });
|
|
4299
4691
|
if (hydrate.cloned.length > 0) {
|
|
4300
4692
|
logOk(`Cloned source(s): ${hydrate.cloned.join(", ")}`);
|
|
@@ -4309,7 +4701,7 @@ async function runYamlInstall(opts) {
|
|
|
4309
4701
|
projectDir,
|
|
4310
4702
|
driverTarget: opts.target
|
|
4311
4703
|
});
|
|
4312
|
-
const spinner5 =
|
|
4704
|
+
const spinner5 = p6.spinner();
|
|
4313
4705
|
spinner5.start(opts.locked ? "Installing from lock file" : "Installing dependencies");
|
|
4314
4706
|
try {
|
|
4315
4707
|
const result = await am2.install({ locked: opts.locked });
|
|
@@ -4337,7 +4729,7 @@ async function runYamlInstall(opts) {
|
|
|
4337
4729
|
}
|
|
4338
4730
|
function makeCheckCommand() {
|
|
4339
4731
|
return new Command("check").description("Check for unmet requirements").option("--project-dir <path>", "Project directory", process.cwd()).action((opts) => {
|
|
4340
|
-
const am2 = new AssetManager({ projectDir:
|
|
4732
|
+
const am2 = new AssetManager({ projectDir: path14__default.resolve(opts.projectDir) });
|
|
4341
4733
|
const issues = am2.doctor();
|
|
4342
4734
|
if (issues.length === 0) {
|
|
4343
4735
|
logOk("All dependencies satisfied.");
|
|
@@ -4354,10 +4746,10 @@ function makeCheckCommand() {
|
|
|
4354
4746
|
function makeCleanCommand() {
|
|
4355
4747
|
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) => {
|
|
4356
4748
|
const am2 = new AssetManager({
|
|
4357
|
-
projectDir:
|
|
4749
|
+
projectDir: path14__default.resolve(opts.projectDir),
|
|
4358
4750
|
driverTarget: opts.target
|
|
4359
4751
|
});
|
|
4360
|
-
const lock = readLock(
|
|
4752
|
+
const lock = readLock(path14__default.resolve(opts.projectDir, "skaile.lock.yaml"));
|
|
4361
4753
|
if (!lock || Object.keys(lock.assets).length === 0) {
|
|
4362
4754
|
logInfo("Nothing to clean (no skaile-managed assets found).");
|
|
4363
4755
|
return;
|
|
@@ -4381,8 +4773,8 @@ function makeCleanCommand() {
|
|
|
4381
4773
|
return;
|
|
4382
4774
|
}
|
|
4383
4775
|
if (!opts.yes) {
|
|
4384
|
-
const
|
|
4385
|
-
if (
|
|
4776
|
+
const confirm5 = await p6.confirm({ message: "Proceed?" });
|
|
4777
|
+
if (p6.isCancel(confirm5) || !confirm5) {
|
|
4386
4778
|
logInfo("Cancelled.");
|
|
4387
4779
|
return;
|
|
4388
4780
|
}
|
|
@@ -4410,14 +4802,14 @@ function makeCleanCommand() {
|
|
|
4410
4802
|
}
|
|
4411
4803
|
function makeRebuildCommand() {
|
|
4412
4804
|
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) => {
|
|
4413
|
-
const projectDir =
|
|
4805
|
+
const projectDir = path14__default.resolve(opts.projectDir);
|
|
4414
4806
|
let agentDir;
|
|
4415
4807
|
if (agentArg) {
|
|
4416
4808
|
if (agentArg.includes("/") || agentArg.includes("\\")) {
|
|
4417
|
-
agentDir =
|
|
4809
|
+
agentDir = path14__default.resolve(projectDir, agentArg);
|
|
4418
4810
|
} else {
|
|
4419
4811
|
const resolved = resolveAgentDir(projectDir);
|
|
4420
|
-
agentDir = resolved ??
|
|
4812
|
+
agentDir = resolved ?? path14__default.resolve(projectDir, agentArg);
|
|
4421
4813
|
}
|
|
4422
4814
|
} else {
|
|
4423
4815
|
const resolved = resolveAgentDir(projectDir);
|
|
@@ -4495,7 +4887,7 @@ function makeFlowEventHandler() {
|
|
|
4495
4887
|
}
|
|
4496
4888
|
function makeRunCommand() {
|
|
4497
4889
|
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) => {
|
|
4498
|
-
const projectDir =
|
|
4890
|
+
const projectDir = path14__default.resolve(opts.projectDir);
|
|
4499
4891
|
const cliDriver = opts.driver;
|
|
4500
4892
|
const dryRun = opts.dryRun ?? false;
|
|
4501
4893
|
let flowId = positional[0];
|
|
@@ -4505,7 +4897,7 @@ function makeRunCommand() {
|
|
|
4505
4897
|
logErr("No flows available.");
|
|
4506
4898
|
process.exit(1);
|
|
4507
4899
|
}
|
|
4508
|
-
const selected = await
|
|
4900
|
+
const selected = await p6.select({
|
|
4509
4901
|
message: "Select a flow to run",
|
|
4510
4902
|
options: flows.map((f) => ({
|
|
4511
4903
|
value: f.id,
|
|
@@ -4513,8 +4905,8 @@ function makeRunCommand() {
|
|
|
4513
4905
|
hint: f.description
|
|
4514
4906
|
}))
|
|
4515
4907
|
});
|
|
4516
|
-
if (
|
|
4517
|
-
|
|
4908
|
+
if (p6.isCancel(selected)) {
|
|
4909
|
+
p6.cancel("Cancelled.");
|
|
4518
4910
|
process.exit(0);
|
|
4519
4911
|
}
|
|
4520
4912
|
flowId = selected;
|
|
@@ -4530,12 +4922,12 @@ function makeRunCommand() {
|
|
|
4530
4922
|
const priorityRoots = [];
|
|
4531
4923
|
let dir = projectDir;
|
|
4532
4924
|
for (let i = 0; i < 6; i++) {
|
|
4533
|
-
const candidate =
|
|
4534
|
-
if (
|
|
4925
|
+
const candidate = path14__default.join(dir, "ai-assets");
|
|
4926
|
+
if (fs12__default.existsSync(candidate)) {
|
|
4535
4927
|
priorityRoots.push(candidate);
|
|
4536
4928
|
break;
|
|
4537
4929
|
}
|
|
4538
|
-
dir =
|
|
4930
|
+
dir = path14__default.dirname(dir);
|
|
4539
4931
|
}
|
|
4540
4932
|
const flowPath = findFlowFile(flowId, priorityRoots);
|
|
4541
4933
|
if (!flowPath) {
|
|
@@ -4590,7 +4982,7 @@ function makeRunCommand() {
|
|
|
4590
4982
|
}
|
|
4591
4983
|
function makeResumeCommand() {
|
|
4592
4984
|
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) => {
|
|
4593
|
-
const projectDir =
|
|
4985
|
+
const projectDir = path14__default.resolve(opts.projectDir);
|
|
4594
4986
|
const sessionId = opts.session;
|
|
4595
4987
|
const dryRun = opts.dryRun ?? false;
|
|
4596
4988
|
const session = sessionId ? await loadSessionById(projectDir, sessionId) : await loadSession(projectDir);
|
|
@@ -4617,7 +5009,7 @@ function makeResumeCommand() {
|
|
|
4617
5009
|
}
|
|
4618
5010
|
function makeStatusCommand() {
|
|
4619
5011
|
return new Command("status").description("Show current session state").option("--project-dir <path>", "Project directory", process.cwd()).action(async (opts) => {
|
|
4620
|
-
const projectDir =
|
|
5012
|
+
const projectDir = path14__default.resolve(opts.projectDir);
|
|
4621
5013
|
const session = await loadSession(projectDir);
|
|
4622
5014
|
if (!session) {
|
|
4623
5015
|
logInfo("No active session.");
|
|
@@ -4642,7 +5034,7 @@ function makeStatusCommand() {
|
|
|
4642
5034
|
}
|
|
4643
5035
|
function makeClearCommand() {
|
|
4644
5036
|
return new Command("clear").description("Unset current session pointer").option("--project-dir <path>", "Project directory", process.cwd()).action(async (opts) => {
|
|
4645
|
-
const projectDir =
|
|
5037
|
+
const projectDir = path14__default.resolve(opts.projectDir);
|
|
4646
5038
|
await clearSession(projectDir);
|
|
4647
5039
|
logOk("Session cleared.");
|
|
4648
5040
|
});
|
|
@@ -4651,8 +5043,8 @@ function makeReplCommand() {
|
|
|
4651
5043
|
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) => {
|
|
4652
5044
|
const { findWorkspaceRoot: findWorkspaceRoot2 } = await import('../core/index.js');
|
|
4653
5045
|
const { startRepl } = await import('../tui/index.js');
|
|
4654
|
-
const
|
|
4655
|
-
const userCwd =
|
|
5046
|
+
const os2 = await import('os');
|
|
5047
|
+
const userCwd = path14__default.resolve(opts.projectDir ?? process.cwd());
|
|
4656
5048
|
const workspaceRoot = findWorkspaceRoot2(userCwd);
|
|
4657
5049
|
let projectDir;
|
|
4658
5050
|
let agentCwd;
|
|
@@ -4667,20 +5059,20 @@ function makeReplCommand() {
|
|
|
4667
5059
|
console.log();
|
|
4668
5060
|
logWarn(`No skaile.yaml found in ${S.cmd(userCwd)} or any parent directory.`);
|
|
4669
5061
|
console.log();
|
|
4670
|
-
const shouldCreate = await
|
|
5062
|
+
const shouldCreate = await p6.confirm({
|
|
4671
5063
|
message: "Create a temporary workspace? (session state in /tmp/)"
|
|
4672
5064
|
});
|
|
4673
|
-
if (
|
|
4674
|
-
|
|
5065
|
+
if (p6.isCancel(shouldCreate) || !shouldCreate) {
|
|
5066
|
+
p6.cancel("Cancelled.");
|
|
4675
5067
|
process.exit(0);
|
|
4676
5068
|
}
|
|
4677
|
-
const tmpDir =
|
|
5069
|
+
const tmpDir = fs12__default.mkdtempSync(path14__default.join(os2.tmpdir(), "skaile-repl-"));
|
|
4678
5070
|
projectDir = tmpDir;
|
|
4679
5071
|
agentCwd = userCwd;
|
|
4680
5072
|
logOk(`Temporary workspace: ${S.cmd(tmpDir)}`);
|
|
4681
5073
|
if (!driverOverride) {
|
|
4682
|
-
const claudeDir =
|
|
4683
|
-
if (
|
|
5074
|
+
const claudeDir = path14__default.join(os2.homedir(), ".claude");
|
|
5075
|
+
if (fs12__default.existsSync(claudeDir)) {
|
|
4684
5076
|
driverOverride = "claude-sdk";
|
|
4685
5077
|
logInfo(`Detected ${S.cmd("~/.claude")} \u2192 using ${S.cmd("claude-sdk")} backend`);
|
|
4686
5078
|
} else {
|
|
@@ -4731,7 +5123,7 @@ async function ensurePluginsLoadedForServe(projectDir) {
|
|
|
4731
5123
|
const { resolveSkWorkspaceConfig: resolveSkWorkspaceConfig2 } = await import('../core/index.js');
|
|
4732
5124
|
const config = resolveSkWorkspaceConfig2(projectDir);
|
|
4733
5125
|
if (!config.plugins || config.plugins.length === 0) return;
|
|
4734
|
-
const { ensurePluginsLoaded } = await import('../plugin-store-
|
|
5126
|
+
const { ensurePluginsLoaded } = await import('../plugin-store-2X2YXJVG.js');
|
|
4735
5127
|
const { pluginRegistry } = await import('../plugin-registry/index.js');
|
|
4736
5128
|
const result = await ensurePluginsLoaded(projectDir, config.plugins, pluginRegistry);
|
|
4737
5129
|
if (result.loaded.length > 0) {
|
|
@@ -4747,21 +5139,21 @@ async function ensurePluginsLoadedForServe(projectDir) {
|
|
|
4747
5139
|
async function runCompileTest(opts) {
|
|
4748
5140
|
const { logOk: logOk2, logErr: logErr2, logInfo: logInfo2, S: S2 } = await import('../helpers-F4NZ66VD.js');
|
|
4749
5141
|
const { tmpdir } = await import('os');
|
|
4750
|
-
const { dirname:
|
|
5142
|
+
const { dirname: dirname4, join: join6, resolve: resolve5 } = await import('path');
|
|
4751
5143
|
const { fileURLToPath: fileURLToPath2 } = await import('url');
|
|
4752
|
-
const { unlinkSync, existsSync:
|
|
5144
|
+
const { unlinkSync, existsSync: existsSync14 } = await import('fs');
|
|
4753
5145
|
const { spawn } = await import('child_process');
|
|
4754
5146
|
const { portableSpawnSync: portableSpawnSync2 } = await import('../core/index.js');
|
|
4755
|
-
const { MONOREPO_ROOT } = await import('../paths-
|
|
5147
|
+
const { MONOREPO_ROOT } = await import('../paths-4SSFMX5Z.js');
|
|
4756
5148
|
if (MONOREPO_ROOT === null) {
|
|
4757
5149
|
logErr2("--compile-test is only available inside the skaile-dev workspace.");
|
|
4758
5150
|
logInfo2("Run it from a checkout of skaile-ai/skaile-dev (the monorepo shell).");
|
|
4759
5151
|
process.exitCode = 2;
|
|
4760
5152
|
return;
|
|
4761
5153
|
}
|
|
4762
|
-
const outfile =
|
|
5154
|
+
const outfile = join6(tmpdir(), `skaile-compile-test-${Date.now()}`);
|
|
4763
5155
|
const __thisFile = fileURLToPath2(import.meta.url);
|
|
4764
|
-
const entryPoint =
|
|
5156
|
+
const entryPoint = resolve5(dirname4(__thisFile), "..", "index.ts");
|
|
4765
5157
|
logInfo2(`Building compiled binary...`);
|
|
4766
5158
|
logInfo2(`Entry: ${S2.dim(entryPoint)}`);
|
|
4767
5159
|
logInfo2(`Output: ${S2.dim(outfile)}`);
|
|
@@ -4811,7 +5203,7 @@ async function runCompileTest(opts) {
|
|
|
4811
5203
|
} catch {
|
|
4812
5204
|
}
|
|
4813
5205
|
try {
|
|
4814
|
-
if (
|
|
5206
|
+
if (existsSync14(outfile)) unlinkSync(outfile);
|
|
4815
5207
|
} catch {
|
|
4816
5208
|
}
|
|
4817
5209
|
}
|
|
@@ -5064,19 +5456,19 @@ function buildTailSelect(q) {
|
|
|
5064
5456
|
return { sql, params };
|
|
5065
5457
|
}
|
|
5066
5458
|
function sleepUnlessAborted(ms, signal) {
|
|
5067
|
-
return new Promise((
|
|
5459
|
+
return new Promise((resolve5) => {
|
|
5068
5460
|
if (signal?.aborted) {
|
|
5069
|
-
|
|
5461
|
+
resolve5();
|
|
5070
5462
|
return;
|
|
5071
5463
|
}
|
|
5072
5464
|
const timer = setTimeout(() => {
|
|
5073
5465
|
signal?.removeEventListener("abort", onAbort);
|
|
5074
|
-
|
|
5466
|
+
resolve5();
|
|
5075
5467
|
}, ms);
|
|
5076
5468
|
const onAbort = () => {
|
|
5077
5469
|
clearTimeout(timer);
|
|
5078
5470
|
signal?.removeEventListener("abort", onAbort);
|
|
5079
|
-
|
|
5471
|
+
resolve5();
|
|
5080
5472
|
};
|
|
5081
5473
|
signal?.addEventListener("abort", onAbort, { once: true });
|
|
5082
5474
|
});
|
|
@@ -5153,7 +5545,7 @@ async function remoteTail(opts) {
|
|
|
5153
5545
|
]
|
|
5154
5546
|
});
|
|
5155
5547
|
const filter = makeFilter(opts.query);
|
|
5156
|
-
return new Promise((
|
|
5548
|
+
return new Promise((resolve5, reject) => {
|
|
5157
5549
|
let settled = false;
|
|
5158
5550
|
const finish = (err) => {
|
|
5159
5551
|
if (settled) return;
|
|
@@ -5164,11 +5556,11 @@ async function remoteTail(opts) {
|
|
|
5164
5556
|
}
|
|
5165
5557
|
opts.signal?.removeEventListener("abort", onAbort);
|
|
5166
5558
|
if (err) reject(err);
|
|
5167
|
-
else
|
|
5559
|
+
else resolve5();
|
|
5168
5560
|
};
|
|
5169
5561
|
const onAbort = () => finish();
|
|
5170
5562
|
if (opts.signal?.aborted) {
|
|
5171
|
-
|
|
5563
|
+
resolve5();
|
|
5172
5564
|
return;
|
|
5173
5565
|
}
|
|
5174
5566
|
opts.signal?.addEventListener("abort", onAbort, { once: true });
|
|
@@ -5222,7 +5614,7 @@ function resolveMode(opts) {
|
|
|
5222
5614
|
if (opts.forceLocal && opts.forceRemote) {
|
|
5223
5615
|
throw new Error("Cannot use both --local and --remote");
|
|
5224
5616
|
}
|
|
5225
|
-
const startDir =
|
|
5617
|
+
const startDir = path14__default.resolve(opts.projectDir ?? process.cwd());
|
|
5226
5618
|
const localDb = findLogsDb(startDir);
|
|
5227
5619
|
if (opts.forceLocal) {
|
|
5228
5620
|
if (!localDb) {
|
|
@@ -5255,14 +5647,14 @@ function resolveMode(opts) {
|
|
|
5255
5647
|
function findLogsDb(startDir) {
|
|
5256
5648
|
let dir = startDir;
|
|
5257
5649
|
for (let i = 0; i < MAX_WALK_LEVELS; i++) {
|
|
5258
|
-
const candidate =
|
|
5650
|
+
const candidate = path14__default.join(dir, ".skaile", "logs.db");
|
|
5259
5651
|
if (existsSync(candidate)) {
|
|
5260
5652
|
try {
|
|
5261
5653
|
if (statSync(candidate).isFile()) return candidate;
|
|
5262
5654
|
} catch {
|
|
5263
5655
|
}
|
|
5264
5656
|
}
|
|
5265
|
-
const parent =
|
|
5657
|
+
const parent = path14__default.dirname(dir);
|
|
5266
5658
|
if (parent === dir) return void 0;
|
|
5267
5659
|
dir = parent;
|
|
5268
5660
|
}
|
|
@@ -5288,7 +5680,7 @@ function readApiToken() {
|
|
|
5288
5680
|
}
|
|
5289
5681
|
function readGlobalSettings() {
|
|
5290
5682
|
try {
|
|
5291
|
-
const settingsPath =
|
|
5683
|
+
const settingsPath = path14__default.join(homedir(), ".skaile", "settings.json");
|
|
5292
5684
|
if (!existsSync(settingsPath)) return {};
|
|
5293
5685
|
return JSON.parse(readFileSync(settingsPath, "utf8"));
|
|
5294
5686
|
} catch {
|
|
@@ -5437,7 +5829,7 @@ function parsePositiveInt(value, flag) {
|
|
|
5437
5829
|
function makeSessionCommand() {
|
|
5438
5830
|
const cmd = new Command("session").description("Manage sessions");
|
|
5439
5831
|
cmd.command("list").description("List all sessions for a project").option("--project-dir <path>", "Project directory", process.cwd()).action(async (opts) => {
|
|
5440
|
-
const projectDir =
|
|
5832
|
+
const projectDir = path14__default.resolve(opts.projectDir);
|
|
5441
5833
|
const sessions = await listSessions(projectDir);
|
|
5442
5834
|
const current = await loadSession(projectDir);
|
|
5443
5835
|
if (sessions.length === 0) {
|
|
@@ -5465,7 +5857,7 @@ function makeSessionCommand() {
|
|
|
5465
5857
|
console.log();
|
|
5466
5858
|
});
|
|
5467
5859
|
cmd.command("show <run-id>").description("Show a specific session").option("--project-dir <path>", "Project directory", process.cwd()).action(async (runId, opts) => {
|
|
5468
|
-
const projectDir =
|
|
5860
|
+
const projectDir = path14__default.resolve(opts.projectDir);
|
|
5469
5861
|
const session = await loadSessionById(projectDir, runId);
|
|
5470
5862
|
if (!session) {
|
|
5471
5863
|
logErr(`Session not found: ${runId}`);
|
|
@@ -5474,12 +5866,12 @@ function makeSessionCommand() {
|
|
|
5474
5866
|
console.log(JSON.stringify(session, null, 2));
|
|
5475
5867
|
});
|
|
5476
5868
|
cmd.command("switch <run-id>").description("Switch the current session").option("--project-dir <path>", "Project directory", process.cwd()).action(async (runId, opts) => {
|
|
5477
|
-
const projectDir =
|
|
5869
|
+
const projectDir = path14__default.resolve(opts.projectDir);
|
|
5478
5870
|
await setCurrentSession(projectDir, runId);
|
|
5479
5871
|
logOk(`Switched to session: ${S.dim(runId.slice(0, 8))}`);
|
|
5480
5872
|
});
|
|
5481
5873
|
cmd.command("delete <run-id>").description("Delete a session").option("--project-dir <path>", "Project directory", process.cwd()).action(async (runId, opts) => {
|
|
5482
|
-
const projectDir =
|
|
5874
|
+
const projectDir = path14__default.resolve(opts.projectDir);
|
|
5483
5875
|
await deleteSession(projectDir, runId);
|
|
5484
5876
|
logOk(`Deleted session: ${S.dim(runId.slice(0, 8))}`);
|
|
5485
5877
|
});
|
|
@@ -5533,12 +5925,12 @@ function showOverview(am2) {
|
|
|
5533
5925
|
}
|
|
5534
5926
|
function showAsset(am2, kind, name) {
|
|
5535
5927
|
const entry = am2.info(`${kind}:${name}`);
|
|
5536
|
-
if (entry?.source &&
|
|
5928
|
+
if (entry?.source && fs12__default.existsSync(entry.source)) {
|
|
5537
5929
|
console.log();
|
|
5538
5930
|
console.log(` ${kindColor(entry.kind)} ${S.heading(entry.name)}`);
|
|
5539
5931
|
console.log(` ${S.rule(40)}`);
|
|
5540
5932
|
console.log();
|
|
5541
|
-
console.log(
|
|
5933
|
+
console.log(fs12__default.readFileSync(entry.source, "utf-8"));
|
|
5542
5934
|
return;
|
|
5543
5935
|
}
|
|
5544
5936
|
logErr(`Asset not found: ${kind}:${name}`);
|
|
@@ -5547,7 +5939,7 @@ function showAsset(am2, kind, name) {
|
|
|
5547
5939
|
function makeShowCommand() {
|
|
5548
5940
|
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) => {
|
|
5549
5941
|
const am2 = new AssetManager({
|
|
5550
|
-
projectDir:
|
|
5942
|
+
projectDir: path14__default.resolve(opts.projectDir),
|
|
5551
5943
|
driverTarget: opts.target
|
|
5552
5944
|
});
|
|
5553
5945
|
if (!kind) {
|
|
@@ -5584,11 +5976,8 @@ function addSourceManifestCommands(src) {
|
|
|
5584
5976
|
}
|
|
5585
5977
|
|
|
5586
5978
|
// cli/src/commands/source.ts
|
|
5587
|
-
function sourcesDir() {
|
|
5588
|
-
return path12.join(skaileHomeDir(), "sources");
|
|
5589
|
-
}
|
|
5590
5979
|
function sourceClonePath(name) {
|
|
5591
|
-
return
|
|
5980
|
+
return path14.join(getGlobalCacheDir(), name);
|
|
5592
5981
|
}
|
|
5593
5982
|
function deriveSlug(url) {
|
|
5594
5983
|
return url.replace(/\.git$/, "").split(/[/:]/).pop() ?? "source";
|
|
@@ -5613,7 +6002,7 @@ function requireProjectYamlPath() {
|
|
|
5613
6002
|
);
|
|
5614
6003
|
process.exit(1);
|
|
5615
6004
|
}
|
|
5616
|
-
return
|
|
6005
|
+
return path14.join(root, workspaceConfigFilename());
|
|
5617
6006
|
}
|
|
5618
6007
|
function readProjectSources(yamlPath) {
|
|
5619
6008
|
if (!existsSync(yamlPath)) return [];
|
|
@@ -5711,7 +6100,7 @@ function makeSourceCommand() {
|
|
|
5711
6100
|
const result = await refreshManifestCache(entry, opts.dev);
|
|
5712
6101
|
logOk(`Indexed ${result.assetsUpdated} of ${result.assetsFound} asset(s) from "${slug}".`);
|
|
5713
6102
|
for (const err of result.errors) logWarn(err);
|
|
5714
|
-
logOk(`Source "${slug}" registered in ${
|
|
6103
|
+
logOk(`Source "${slug}" registered in ${path14.relative(process.cwd(), yamlPath)}.`);
|
|
5715
6104
|
}
|
|
5716
6105
|
);
|
|
5717
6106
|
cmd.command("list").description("List sources registered in this project's skaile.yaml").option("--json", "Output as JSON").action(async (opts) => {
|
|
@@ -5754,7 +6143,7 @@ function makeSourceCommand() {
|
|
|
5754
6143
|
)
|
|
5755
6144
|
);
|
|
5756
6145
|
});
|
|
5757
|
-
cmd.command("remove <name-or-url>").description("Remove a source from this project's skaile.yaml (matched by URL or slug)").option("--purge", "Also delete the cached clone from ~/.skaile/sources/", false).action(async (key, opts) => {
|
|
6146
|
+
cmd.command("remove <name-or-url>").description("Remove a source from this project's skaile.yaml (matched by URL or slug)").option("--purge", "Also delete the cached clone from ~/.skaile/cache/sources/", false).action(async (key, opts) => {
|
|
5758
6147
|
const yamlPath = requireProjectYamlPath();
|
|
5759
6148
|
const editor = WorkspaceYamlEditor.load(yamlPath);
|
|
5760
6149
|
const match = editor.getSources().find((s) => sourceMatchesKey(s, key));
|
|
@@ -5767,7 +6156,7 @@ function makeSourceCommand() {
|
|
|
5767
6156
|
editor.save();
|
|
5768
6157
|
await dropManifestCache(slug, opts.purge);
|
|
5769
6158
|
logOk(
|
|
5770
|
-
opts.purge ? `Removed source "${slug}" and purged its clone.` : `Removed source "${slug}" from skaile.yaml (clone left in ~/.skaile/sources/).`
|
|
6159
|
+
opts.purge ? `Removed source "${slug}" and purged its clone.` : `Removed source "${slug}" from skaile.yaml (clone left in ~/.skaile/cache/sources/).`
|
|
5771
6160
|
);
|
|
5772
6161
|
});
|
|
5773
6162
|
cmd.command("sync [name]").description("Pull upstream changes and refresh the manifest cache").option("--dev", "Also index dev-only assets under each source's dev_paths", false).option("--all", "Sync every source without prompting", false).action(async (key, opts) => {
|
|
@@ -5787,13 +6176,13 @@ function makeSourceCommand() {
|
|
|
5787
6176
|
} else if (opts.all || sources.length === 1 || !process.stdin.isTTY) {
|
|
5788
6177
|
targets = sources;
|
|
5789
6178
|
} else {
|
|
5790
|
-
const selected = await
|
|
6179
|
+
const selected = await p6.multiselect({
|
|
5791
6180
|
message: "Select sources to sync",
|
|
5792
6181
|
options: sources.map((s) => ({ value: s.url, label: deriveSlug(s.url), hint: s.url })),
|
|
5793
6182
|
required: true
|
|
5794
6183
|
});
|
|
5795
|
-
if (
|
|
5796
|
-
|
|
6184
|
+
if (p6.isCancel(selected)) {
|
|
6185
|
+
p6.cancel("Cancelled.");
|
|
5797
6186
|
return;
|
|
5798
6187
|
}
|
|
5799
6188
|
const picked = new Set(selected);
|
|
@@ -5839,10 +6228,10 @@ function makeStoreCommand() {
|
|
|
5839
6228
|
if (opts.email) {
|
|
5840
6229
|
const readline2 = await import('readline');
|
|
5841
6230
|
const rl = readline2.createInterface({ input: process.stdin, output: process.stdout });
|
|
5842
|
-
const password = await new Promise((
|
|
6231
|
+
const password = await new Promise((resolve5) => {
|
|
5843
6232
|
rl.question("Password: ", (answer) => {
|
|
5844
6233
|
rl.close();
|
|
5845
|
-
|
|
6234
|
+
resolve5(answer);
|
|
5846
6235
|
});
|
|
5847
6236
|
});
|
|
5848
6237
|
try {
|
|
@@ -5997,7 +6386,7 @@ function printTree(node, prefix = "", isLast = true) {
|
|
|
5997
6386
|
}
|
|
5998
6387
|
function makeTreeCommand() {
|
|
5999
6388
|
return new Command("tree").description("Show full dependency tree").option("--project-dir <path>", "Project directory", process.cwd()).action((opts) => {
|
|
6000
|
-
const am2 = new AssetManager({ projectDir:
|
|
6389
|
+
const am2 = new AssetManager({ projectDir: path14__default.resolve(opts.projectDir) });
|
|
6001
6390
|
const root = am2.tree();
|
|
6002
6391
|
if (root.children.length === 0) {
|
|
6003
6392
|
logInfo("No dependencies in lock file. Run `skaile install` first.");
|
|
@@ -6013,9 +6402,9 @@ function makeUpdateCommand() {
|
|
|
6013
6402
|
async (_name, opts) => {
|
|
6014
6403
|
if (opts.catalog !== false) {
|
|
6015
6404
|
try {
|
|
6016
|
-
const catalogSpinner =
|
|
6405
|
+
const catalogSpinner = p6.spinner();
|
|
6017
6406
|
catalogSpinner.start("Refreshing catalog cache");
|
|
6018
|
-
const remote = await openCatalogSource({ projectDir:
|
|
6407
|
+
const remote = await openCatalogSource({ projectDir: path14__default.resolve(opts.projectDir) });
|
|
6019
6408
|
const result2 = await remote.refresh();
|
|
6020
6409
|
catalogSpinner.stop(
|
|
6021
6410
|
`Catalog refreshed: ${S.heading(String(result2.assetsCached))} assets cached`
|
|
@@ -6027,8 +6416,8 @@ function makeUpdateCommand() {
|
|
|
6027
6416
|
}
|
|
6028
6417
|
}
|
|
6029
6418
|
if (opts.catalogOnly) return;
|
|
6030
|
-
const am2 = new AssetManager({ projectDir:
|
|
6031
|
-
const spinner5 =
|
|
6419
|
+
const am2 = new AssetManager({ projectDir: path14__default.resolve(opts.projectDir) });
|
|
6420
|
+
const spinner5 = p6.spinner();
|
|
6032
6421
|
spinner5.start("Re-deploying assets");
|
|
6033
6422
|
const result = await am2.install();
|
|
6034
6423
|
spinner5.stop("Done");
|
|
@@ -6061,12 +6450,12 @@ function findManifestCandidates(rootPath) {
|
|
|
6061
6450
|
function walk(dir) {
|
|
6062
6451
|
let entries;
|
|
6063
6452
|
try {
|
|
6064
|
-
entries =
|
|
6453
|
+
entries = fs12__default.readdirSync(dir, { withFileTypes: true });
|
|
6065
6454
|
} catch {
|
|
6066
6455
|
return;
|
|
6067
6456
|
}
|
|
6068
6457
|
for (const entry of entries) {
|
|
6069
|
-
const fullPath =
|
|
6458
|
+
const fullPath = path14__default.join(dir, entry.name);
|
|
6070
6459
|
if (entry.isDirectory()) {
|
|
6071
6460
|
if (!SKIP_DIRS.has(entry.name)) walk(fullPath);
|
|
6072
6461
|
} else if (entry.isFile()) {
|
|
@@ -6107,7 +6496,7 @@ function checkManifestIdentity(kind, parsed) {
|
|
|
6107
6496
|
return null;
|
|
6108
6497
|
}
|
|
6109
6498
|
function parseManifestCandidate(c, absRoot) {
|
|
6110
|
-
const content =
|
|
6499
|
+
const content = fs12__default.readFileSync(c.filePath, "utf-8");
|
|
6111
6500
|
if (c.filePath.endsWith(".md")) {
|
|
6112
6501
|
const parsed = parseMdFrontmatter(content);
|
|
6113
6502
|
if (parsed === null) {
|
|
@@ -6119,13 +6508,13 @@ function parseManifestCandidate(c, absRoot) {
|
|
|
6119
6508
|
const parsed = c.filePath.endsWith(".json") ? JSON.parse(content) : parse(content);
|
|
6120
6509
|
return { kind: "value", parsed };
|
|
6121
6510
|
} catch (e) {
|
|
6122
|
-
const relPath =
|
|
6511
|
+
const relPath = path14__default.relative(absRoot, c.filePath);
|
|
6123
6512
|
logErr(`${relPath} \u2014 parse error: ${e instanceof Error ? e.message : String(e)}`);
|
|
6124
6513
|
return { kind: "error" };
|
|
6125
6514
|
}
|
|
6126
6515
|
}
|
|
6127
6516
|
function validateManifestCandidate(c, parsed, absRoot, registry) {
|
|
6128
|
-
const relPath =
|
|
6517
|
+
const relPath = path14__default.relative(absRoot, c.filePath);
|
|
6129
6518
|
let errors = 0;
|
|
6130
6519
|
const identityError = checkManifestIdentity(c.kind, parsed);
|
|
6131
6520
|
if (identityError) {
|
|
@@ -6147,8 +6536,8 @@ function validateManifestCandidate(c, parsed, absRoot, registry) {
|
|
|
6147
6536
|
return { errors, warnings: 0 };
|
|
6148
6537
|
}
|
|
6149
6538
|
function validateManifests(rootPath) {
|
|
6150
|
-
const absRoot =
|
|
6151
|
-
if (!
|
|
6539
|
+
const absRoot = path14__default.resolve(rootPath);
|
|
6540
|
+
if (!fs12__default.existsSync(absRoot)) {
|
|
6152
6541
|
logErr(`Path does not exist: ${absRoot}`);
|
|
6153
6542
|
return { total: 0, errors: 1, warnings: 0 };
|
|
6154
6543
|
}
|
|
@@ -6174,12 +6563,12 @@ function findWorkspaceManifests(rootPath) {
|
|
|
6174
6563
|
function walk(dir) {
|
|
6175
6564
|
let entries;
|
|
6176
6565
|
try {
|
|
6177
|
-
entries =
|
|
6566
|
+
entries = fs12__default.readdirSync(dir, { withFileTypes: true });
|
|
6178
6567
|
} catch {
|
|
6179
6568
|
return;
|
|
6180
6569
|
}
|
|
6181
6570
|
for (const entry of entries) {
|
|
6182
|
-
const full =
|
|
6571
|
+
const full = path14__default.join(dir, entry.name);
|
|
6183
6572
|
if (entry.isDirectory()) {
|
|
6184
6573
|
if (!SKIP_DIRS.has(entry.name)) walk(full);
|
|
6185
6574
|
} else if (entry.isFile() && /(^|\.)skaile\.yaml$/.test(entry.name)) {
|
|
@@ -6242,14 +6631,14 @@ function validateWorkspaceAssets(parsed, relPath) {
|
|
|
6242
6631
|
return errors;
|
|
6243
6632
|
}
|
|
6244
6633
|
function validateWorkspaceManifests(rootPath) {
|
|
6245
|
-
const absRoot =
|
|
6634
|
+
const absRoot = path14__default.resolve(rootPath);
|
|
6246
6635
|
const files = findWorkspaceManifests(absRoot);
|
|
6247
6636
|
let errors = 0;
|
|
6248
6637
|
for (const file of files) {
|
|
6249
|
-
const relPath =
|
|
6638
|
+
const relPath = path14__default.relative(absRoot, file);
|
|
6250
6639
|
let parsed;
|
|
6251
6640
|
try {
|
|
6252
|
-
parsed = parse(
|
|
6641
|
+
parsed = parse(fs12__default.readFileSync(file, "utf-8")) ?? {};
|
|
6253
6642
|
} catch (e) {
|
|
6254
6643
|
logErr(`${relPath} \u2014 parse error: ${e instanceof Error ? e.message : String(e)}`);
|
|
6255
6644
|
errors++;
|
|
@@ -6263,34 +6652,34 @@ function validateWorkspaceManifests(rootPath) {
|
|
|
6263
6652
|
var EXCLUDED_DOMAINS = /* @__PURE__ */ new Set(["skaileup-shared", "external", "docs"]);
|
|
6264
6653
|
function collectAssetVersions() {
|
|
6265
6654
|
const assets = [];
|
|
6266
|
-
if (!
|
|
6267
|
-
const domains =
|
|
6655
|
+
if (!fs12__default.existsSync(AI_RESOURCES)) return assets;
|
|
6656
|
+
const domains = fs12__default.readdirSync(AI_RESOURCES, { withFileTypes: true }).filter((d) => d.isDirectory() && !EXCLUDED_DOMAINS.has(d.name));
|
|
6268
6657
|
for (const d of domains) {
|
|
6269
|
-
const domainDir =
|
|
6270
|
-
const skillsDir =
|
|
6271
|
-
if (
|
|
6658
|
+
const domainDir = path14__default.join(AI_RESOURCES, d.name);
|
|
6659
|
+
const skillsDir = path14__default.join(domainDir, "skills");
|
|
6660
|
+
if (fs12__default.existsSync(skillsDir)) {
|
|
6272
6661
|
collectSkillVersions(skillsDir, d.name, assets);
|
|
6273
6662
|
}
|
|
6274
|
-
const agentsDir =
|
|
6275
|
-
if (
|
|
6663
|
+
const agentsDir = path14__default.join(domainDir, "agents");
|
|
6664
|
+
if (fs12__default.existsSync(agentsDir)) {
|
|
6276
6665
|
collectAgentVersions(agentsDir, d.name, assets);
|
|
6277
6666
|
}
|
|
6278
|
-
const flowsDir =
|
|
6279
|
-
if (
|
|
6667
|
+
const flowsDir = path14__default.join(domainDir, "flows");
|
|
6668
|
+
if (fs12__default.existsSync(flowsDir)) {
|
|
6280
6669
|
collectFlowVersions(flowsDir, d.name, assets);
|
|
6281
6670
|
}
|
|
6282
|
-
const promptsDir =
|
|
6283
|
-
if (
|
|
6671
|
+
const promptsDir = path14__default.join(domainDir, "prompts");
|
|
6672
|
+
if (fs12__default.existsSync(promptsDir)) {
|
|
6284
6673
|
collectPromptVersions(promptsDir, d.name, assets);
|
|
6285
6674
|
}
|
|
6286
6675
|
}
|
|
6287
6676
|
return assets;
|
|
6288
6677
|
}
|
|
6289
6678
|
function collectFlowVersions(dir, domain, out) {
|
|
6290
|
-
for (const f of
|
|
6679
|
+
for (const f of fs12__default.readdirSync(dir)) {
|
|
6291
6680
|
if (!f.endsWith(".flow.yaml")) continue;
|
|
6292
|
-
const fp =
|
|
6293
|
-
const content =
|
|
6681
|
+
const fp = path14__default.join(dir, f);
|
|
6682
|
+
const content = fs12__default.readFileSync(fp, "utf-8");
|
|
6294
6683
|
const parsed = parse(content);
|
|
6295
6684
|
out.push({
|
|
6296
6685
|
kind: "flow",
|
|
@@ -6302,10 +6691,10 @@ function collectFlowVersions(dir, domain, out) {
|
|
|
6302
6691
|
}
|
|
6303
6692
|
}
|
|
6304
6693
|
function collectPromptVersions(dir, domain, out) {
|
|
6305
|
-
for (const f of
|
|
6694
|
+
for (const f of fs12__default.readdirSync(dir)) {
|
|
6306
6695
|
if (!f.endsWith(".prompt.md")) continue;
|
|
6307
|
-
const fp =
|
|
6308
|
-
const content =
|
|
6696
|
+
const fp = path14__default.join(dir, f);
|
|
6697
|
+
const content = fs12__default.readFileSync(fp, "utf-8");
|
|
6309
6698
|
const fm = parseSkillFrontmatter(content);
|
|
6310
6699
|
out.push({
|
|
6311
6700
|
kind: "prompt",
|
|
@@ -6317,12 +6706,12 @@ function collectPromptVersions(dir, domain, out) {
|
|
|
6317
6706
|
}
|
|
6318
6707
|
}
|
|
6319
6708
|
function collectSkillVersions(dir, domain, out) {
|
|
6320
|
-
for (const entry of
|
|
6709
|
+
for (const entry of fs12__default.readdirSync(dir, { withFileTypes: true })) {
|
|
6321
6710
|
if (!entry.isDirectory()) continue;
|
|
6322
|
-
const full =
|
|
6323
|
-
const skillMd =
|
|
6324
|
-
if (
|
|
6325
|
-
const content =
|
|
6711
|
+
const full = path14__default.join(dir, entry.name);
|
|
6712
|
+
const skillMd = path14__default.join(full, "SKILL.md");
|
|
6713
|
+
if (fs12__default.existsSync(skillMd)) {
|
|
6714
|
+
const content = fs12__default.readFileSync(skillMd, "utf-8");
|
|
6326
6715
|
const fm = parseSkillFrontmatter(content);
|
|
6327
6716
|
out.push({
|
|
6328
6717
|
kind: "skill",
|
|
@@ -6337,11 +6726,11 @@ function collectSkillVersions(dir, domain, out) {
|
|
|
6337
6726
|
}
|
|
6338
6727
|
}
|
|
6339
6728
|
function collectAgentVersions(dir, domain, out) {
|
|
6340
|
-
for (const entry of
|
|
6729
|
+
for (const entry of fs12__default.readdirSync(dir, { withFileTypes: true })) {
|
|
6341
6730
|
if (!entry.isDirectory()) continue;
|
|
6342
|
-
const agentYaml =
|
|
6343
|
-
if (!
|
|
6344
|
-
const content =
|
|
6731
|
+
const agentYaml = path14__default.join(dir, entry.name, "agent.yaml");
|
|
6732
|
+
if (!fs12__default.existsSync(agentYaml)) continue;
|
|
6733
|
+
const content = fs12__default.readFileSync(agentYaml, "utf-8");
|
|
6345
6734
|
const parsed = parse(content);
|
|
6346
6735
|
out.push({
|
|
6347
6736
|
kind: "agent",
|
|
@@ -6372,7 +6761,7 @@ function filterToChangedAssets(assets) {
|
|
|
6372
6761
|
encoding: "utf-8"
|
|
6373
6762
|
});
|
|
6374
6763
|
const changedFiles = new Set(
|
|
6375
|
-
diffOutput.trim().split("\n").filter(Boolean).map((f) =>
|
|
6764
|
+
diffOutput.trim().split("\n").filter(Boolean).map((f) => path14__default.resolve(AI_RESOURCES, f))
|
|
6376
6765
|
);
|
|
6377
6766
|
return assets.filter((a) => changedFiles.has(a.filePath));
|
|
6378
6767
|
} catch {
|
|
@@ -6398,7 +6787,7 @@ function checkVersionBumps(assets) {
|
|
|
6398
6787
|
let warnings = 0;
|
|
6399
6788
|
for (const a of assets) {
|
|
6400
6789
|
if (!a.version) continue;
|
|
6401
|
-
const relPath =
|
|
6790
|
+
const relPath = path14__default.relative(AI_RESOURCES, a.filePath);
|
|
6402
6791
|
try {
|
|
6403
6792
|
const headContent = execSync(`git show HEAD:${relPath}`, {
|
|
6404
6793
|
cwd: AI_RESOURCES,
|
|
@@ -6424,7 +6813,7 @@ function checkFlowVersionPins(assets) {
|
|
|
6424
6813
|
}
|
|
6425
6814
|
let errors = 0;
|
|
6426
6815
|
for (const f of flows) {
|
|
6427
|
-
const content =
|
|
6816
|
+
const content = fs12__default.readFileSync(f.filePath, "utf-8");
|
|
6428
6817
|
const parsed = parse(content);
|
|
6429
6818
|
const nodes = (parsed?.nodes ?? []).filter((n) => n.type === "skill" && n.data?.version).map((n) => ({
|
|
6430
6819
|
nodeId: n.id,
|
|
@@ -6471,7 +6860,7 @@ function makeValidateCommand() {
|
|
|
6471
6860
|
"Validate asset manifests, versions, and changelogs"
|
|
6472
6861
|
);
|
|
6473
6862
|
cmd.argument("[path]", "Path to asset repo or directory to validate", ".").action((targetPath) => {
|
|
6474
|
-
const absPath =
|
|
6863
|
+
const absPath = path14__default.resolve(targetPath);
|
|
6475
6864
|
logInfo(`Validating manifests in ${absPath}`);
|
|
6476
6865
|
const { total, errors } = validateManifests(absPath);
|
|
6477
6866
|
const ws = validateWorkspaceManifests(absPath);
|
|
@@ -6517,7 +6906,7 @@ function makeValidateCommand() {
|
|
|
6517
6906
|
let errors = 0;
|
|
6518
6907
|
for (const domain of modifiedDomains) {
|
|
6519
6908
|
const changelogModified = modifiedFiles.some(
|
|
6520
|
-
(f) => f === `${domain}/CHANGELOG.md` || f ===
|
|
6909
|
+
(f) => f === `${domain}/CHANGELOG.md` || f === path14__default.join(domain, "CHANGELOG.md")
|
|
6521
6910
|
);
|
|
6522
6911
|
if (changelogModified) {
|
|
6523
6912
|
logOk(`${domain}/CHANGELOG.md updated`);
|
|
@@ -6599,7 +6988,7 @@ function makeVerifyCommand() {
|
|
|
6599
6988
|
}
|
|
6600
6989
|
function makeWhyCommand() {
|
|
6601
6990
|
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) => {
|
|
6602
|
-
const am2 = new AssetManager({ projectDir:
|
|
6991
|
+
const am2 = new AssetManager({ projectDir: path14__default.resolve(opts.projectDir) });
|
|
6603
6992
|
const chain = am2.why(ref);
|
|
6604
6993
|
if (chain.length === 0) {
|
|
6605
6994
|
logErr(`${ref} not found in lock file. Run \`skaile install\` first.`);
|
|
@@ -6620,7 +7009,7 @@ function makeWhyCommand() {
|
|
|
6620
7009
|
var _defaultFormatHelp = Help.prototype.formatHelp;
|
|
6621
7010
|
var pkg = JSON.parse(
|
|
6622
7011
|
readFileSync(
|
|
6623
|
-
|
|
7012
|
+
path14__default.resolve(path14__default.dirname(fileURLToPath(import.meta.url)), "../../package.json"),
|
|
6624
7013
|
"utf-8"
|
|
6625
7014
|
)
|
|
6626
7015
|
);
|
|
@@ -6741,7 +7130,7 @@ program.command("init [project-dir]").description("Initialize a project director
|
|
|
6741
7130
|
(projectDir, opts) => runInit(projectDir, opts)
|
|
6742
7131
|
);
|
|
6743
7132
|
async function runInit(projectDir, opts) {
|
|
6744
|
-
const { mkdirSync:
|
|
7133
|
+
const { mkdirSync: mkdirSync4, writeFileSync: writeFileSync4 } = await import('fs');
|
|
6745
7134
|
const { stringify } = await import('yaml');
|
|
6746
7135
|
const { DRIVER_TARGETS, SUPPORTED_DRIVER_TARGETS: SUPPORTED_DRIVER_TARGETS2 } = await import('../core/index.js');
|
|
6747
7136
|
const backend = opts.backend;
|
|
@@ -6750,33 +7139,33 @@ async function runInit(projectDir, opts) {
|
|
|
6750
7139
|
process.exitCode = 1;
|
|
6751
7140
|
return;
|
|
6752
7141
|
}
|
|
6753
|
-
const resolved =
|
|
6754
|
-
const projectName =
|
|
7142
|
+
const resolved = path14__default.resolve(projectDir ?? ".");
|
|
7143
|
+
const projectName = path14__default.basename(resolved);
|
|
6755
7144
|
const created = [];
|
|
6756
|
-
const { existsSync:
|
|
6757
|
-
if (!
|
|
6758
|
-
|
|
7145
|
+
const { existsSync: existsSync14 } = await import('fs');
|
|
7146
|
+
if (!existsSync14(resolved)) {
|
|
7147
|
+
mkdirSync4(resolved, { recursive: true });
|
|
6759
7148
|
created.push(".");
|
|
6760
7149
|
}
|
|
6761
|
-
const skaileDir =
|
|
6762
|
-
if (!
|
|
6763
|
-
|
|
7150
|
+
const skaileDir = path14__default.join(resolved, ".skaile");
|
|
7151
|
+
if (!existsSync14(skaileDir)) {
|
|
7152
|
+
mkdirSync4(path14__default.join(skaileDir, "sessions"), { recursive: true });
|
|
6764
7153
|
created.push(".skaile/");
|
|
6765
7154
|
}
|
|
6766
|
-
const settingsPath =
|
|
6767
|
-
if (!
|
|
6768
|
-
|
|
7155
|
+
const settingsPath = path14__default.join(skaileDir, "settings.json");
|
|
7156
|
+
if (!existsSync14(settingsPath)) {
|
|
7157
|
+
writeFileSync4(settingsPath, "{}\n");
|
|
6769
7158
|
created.push(".skaile/settings.json");
|
|
6770
7159
|
}
|
|
6771
|
-
const wsConfigPath =
|
|
6772
|
-
if (!
|
|
6773
|
-
|
|
7160
|
+
const wsConfigPath = path14__default.join(resolved, "skaile.yaml");
|
|
7161
|
+
if (!existsSync14(wsConfigPath)) {
|
|
7162
|
+
writeFileSync4(wsConfigPath, stringify(buildInitWorkspaceConfig(projectName, backend)));
|
|
6774
7163
|
created.push("skaile.yaml");
|
|
6775
7164
|
}
|
|
6776
7165
|
for (const dir of new Set(Object.values(DRIVER_TARGETS[backend].local))) {
|
|
6777
|
-
const full =
|
|
6778
|
-
if (!
|
|
6779
|
-
|
|
7166
|
+
const full = path14__default.join(resolved, dir);
|
|
7167
|
+
if (!existsSync14(full)) {
|
|
7168
|
+
mkdirSync4(full, { recursive: true });
|
|
6780
7169
|
created.push(`${dir}/`);
|
|
6781
7170
|
}
|
|
6782
7171
|
}
|
|
@@ -6806,19 +7195,26 @@ function buildInitWorkspaceConfig(projectName, backend) {
|
|
|
6806
7195
|
}
|
|
6807
7196
|
async function initGitScaffold(resolved, created) {
|
|
6808
7197
|
const { execSync: execSync3 } = await import('child_process');
|
|
6809
|
-
const { existsSync:
|
|
6810
|
-
const gitignorePath =
|
|
6811
|
-
const entries = [
|
|
6812
|
-
|
|
7198
|
+
const { existsSync: existsSync14, readFileSync: readFileSync8, writeFileSync: writeFileSync4 } = await import('fs');
|
|
7199
|
+
const gitignorePath = path14__default.join(resolved, ".gitignore");
|
|
7200
|
+
const entries = [
|
|
7201
|
+
"node_modules/",
|
|
7202
|
+
".skaile/sessions/",
|
|
7203
|
+
".skaile/cache/",
|
|
7204
|
+
"*.log",
|
|
7205
|
+
".env",
|
|
7206
|
+
".env.local"
|
|
7207
|
+
];
|
|
7208
|
+
const existing = existsSync14(gitignorePath) ? readFileSync8(gitignorePath, "utf-8") : "";
|
|
6813
7209
|
const have = new Set(existing.split("\n").map((l) => l.trim()));
|
|
6814
7210
|
const append = entries.filter((e) => !have.has(e));
|
|
6815
7211
|
if (append.length > 0) {
|
|
6816
7212
|
const prefix = existing && !existing.endsWith("\n") ? "\n" : "";
|
|
6817
|
-
|
|
7213
|
+
writeFileSync4(gitignorePath, `${existing + prefix}${append.join("\n")}
|
|
6818
7214
|
`);
|
|
6819
7215
|
if (!existing) created.push(".gitignore");
|
|
6820
7216
|
}
|
|
6821
|
-
if (!
|
|
7217
|
+
if (!existsSync14(path14__default.join(resolved, ".git"))) {
|
|
6822
7218
|
try {
|
|
6823
7219
|
execSync3("git init", { cwd: resolved, stdio: "pipe" });
|
|
6824
7220
|
created.push(".git/");
|
|
@@ -6830,10 +7226,10 @@ async function initGitScaffold(resolved, created) {
|
|
|
6830
7226
|
}
|
|
6831
7227
|
async function bootstrapUserConfig() {
|
|
6832
7228
|
try {
|
|
6833
|
-
const
|
|
7229
|
+
const fs13 = await import('fs');
|
|
6834
7230
|
const { userConfigPath, saveConfig, getConfigDefaults } = await import('../library/index.js');
|
|
6835
7231
|
const userCfgPath = userConfigPath();
|
|
6836
|
-
if (!
|
|
7232
|
+
if (!fs13.existsSync(userCfgPath)) {
|
|
6837
7233
|
const defaults = getConfigDefaults();
|
|
6838
7234
|
saveConfig(userCfgPath, {
|
|
6839
7235
|
catalog: { url: defaults.catalog.url, cache_ttl: defaults.catalog.cache_ttl }
|
|
@@ -6848,9 +7244,9 @@ async function bootstrapUserConfig() {
|
|
|
6848
7244
|
}
|
|
6849
7245
|
async function hydrateInitSources(resolved, created) {
|
|
6850
7246
|
try {
|
|
6851
|
-
const { ensureSourcesCloned } = await import('../ensure-sources-
|
|
7247
|
+
const { ensureSourcesCloned } = await import('../ensure-sources-NSDMTAWN.js');
|
|
6852
7248
|
const hydrate = ensureSourcesCloned(resolved, { quiet: true });
|
|
6853
|
-
for (const n of hydrate.cloned) created.push(`~/.skaile/sources/${n}/`);
|
|
7249
|
+
for (const n of hydrate.cloned) created.push(`~/.skaile/cache/sources/${n}/`);
|
|
6854
7250
|
if (hydrate.failed.length > 0) {
|
|
6855
7251
|
logErr(`Failed to clone source(s): ${hydrate.failed.join(", ")}`);
|
|
6856
7252
|
}
|
|
@@ -6864,7 +7260,7 @@ function printInitSummary(resolved, projectDir, created) {
|
|
|
6864
7260
|
logOk(`Initialized project at ${S.heading(resolved)}`);
|
|
6865
7261
|
console.log();
|
|
6866
7262
|
console.log(S.heading(" Next steps:"));
|
|
6867
|
-
const isCurrentDir = resolved ===
|
|
7263
|
+
const isCurrentDir = resolved === path14__default.resolve(".");
|
|
6868
7264
|
let step = 1;
|
|
6869
7265
|
if (!isCurrentDir) {
|
|
6870
7266
|
console.log(` ${S.dim(`${step}.`)} ${S.cmd(`cd ${projectDir}`)}`);
|
|
@@ -6876,12 +7272,13 @@ function printInitSummary(resolved, projectDir, created) {
|
|
|
6876
7272
|
console.log();
|
|
6877
7273
|
}
|
|
6878
7274
|
program.command("setup").description("Interactive provider setup wizard").action(async () => {
|
|
6879
|
-
const { cmdSetup } = await import('../setup-
|
|
7275
|
+
const { cmdSetup } = await import('../setup-VGZTFQ32.js');
|
|
6880
7276
|
await cmdSetup([], { projectDir: process.cwd() });
|
|
6881
7277
|
});
|
|
6882
7278
|
program.addCommand(makeInstallCommand());
|
|
6883
7279
|
program.addCommand(makeCheckCommand());
|
|
6884
7280
|
program.addCommand(makeCleanCommand());
|
|
7281
|
+
program.addCommand(makeCacheCommand());
|
|
6885
7282
|
program.addCommand(makeConfigCommand());
|
|
6886
7283
|
program.addCommand(makeAddCommand());
|
|
6887
7284
|
program.addCommand(makeRemoveCommand());
|