@skaile/workspaces 0.50.0 → 0.52.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 +226 -0
- package/dist/asset-feeds-OEGJ6NOF.js +205 -0
- package/dist/asset-feeds-OEGJ6NOF.js.map +1 -0
- package/dist/asset-manager/index.js +8 -8
- package/dist/asset-manager/installer.js +7 -7
- package/dist/asset-manager/src/index.d.ts +83 -7
- package/dist/asset-manager/src/index.d.ts.map +1 -1
- package/dist/asset-manager/src/installer.d.ts.map +1 -1
- package/dist/{chunk-P4BDTJMI.js → chunk-2D5YE3FL.js} +4 -4
- package/dist/{chunk-P4BDTJMI.js.map → chunk-2D5YE3FL.js.map} +1 -1
- package/dist/{chunk-4IGNQG6E.js → chunk-2ZK7M2SG.js} +3 -3
- package/dist/{chunk-4IGNQG6E.js.map → chunk-2ZK7M2SG.js.map} +1 -1
- package/dist/{chunk-SXT6BAQJ.js → chunk-3IHBGDCG.js} +2 -2
- package/dist/{chunk-SXT6BAQJ.js.map → chunk-3IHBGDCG.js.map} +1 -1
- package/dist/{chunk-SDAKQCOB.js → chunk-3KPNDTMR.js} +3 -3
- package/dist/{chunk-SDAKQCOB.js.map → chunk-3KPNDTMR.js.map} +1 -1
- package/dist/{chunk-H74X4TSR.js → chunk-6K4RVXAM.js} +6 -6
- package/dist/{chunk-H74X4TSR.js.map → chunk-6K4RVXAM.js.map} +1 -1
- package/dist/{chunk-2Y4HIITD.js → chunk-7ZWLZ5H3.js} +13 -9
- package/dist/chunk-7ZWLZ5H3.js.map +1 -0
- package/dist/{chunk-6IDBWPK2.js → chunk-BQCGFPHW.js} +4 -3
- package/dist/chunk-BQCGFPHW.js.map +1 -0
- package/dist/chunk-BXC5547R.js +377 -0
- package/dist/chunk-BXC5547R.js.map +1 -0
- package/dist/{chunk-3A3OACI2.js → chunk-EOINYN5T.js} +2 -2
- package/dist/{chunk-3A3OACI2.js.map → chunk-EOINYN5T.js.map} +1 -1
- package/dist/{chunk-XGCXFX7X.js → chunk-F3HNW354.js} +3 -3
- package/dist/{chunk-XGCXFX7X.js.map → chunk-F3HNW354.js.map} +1 -1
- package/dist/{chunk-33WB7VFV.js → chunk-LKOMH3QC.js} +3 -3
- package/dist/{chunk-33WB7VFV.js.map → chunk-LKOMH3QC.js.map} +1 -1
- package/dist/{chunk-O4JH3KUE.js → chunk-MENCWIHW.js} +11 -3
- package/dist/chunk-MENCWIHW.js.map +1 -0
- package/dist/{chunk-LV73DB4G.js → chunk-MGB657EG.js} +16 -21
- package/dist/chunk-MGB657EG.js.map +1 -0
- package/dist/{chunk-PBO6SCT2.js → chunk-NXC6IEL4.js} +37 -14
- package/dist/chunk-NXC6IEL4.js.map +1 -0
- package/dist/{chunk-EBSIZYM6.js → chunk-QLLFCQU5.js} +12 -12
- package/dist/chunk-QLLFCQU5.js.map +1 -0
- package/dist/{chunk-X46FY45B.js → chunk-SKADPHAM.js} +12 -8
- package/dist/chunk-SKADPHAM.js.map +1 -0
- package/dist/{chunk-C5RYGUF4.js → chunk-TCNYSHPM.js} +157 -31
- package/dist/chunk-TCNYSHPM.js.map +1 -0
- package/dist/{chunk-JXHULIOA.js → chunk-UTHEIPEY.js} +387 -42
- package/dist/chunk-UTHEIPEY.js.map +1 -0
- package/dist/{chunk-ZJ3VRPOI.js → chunk-VE2UIJ7Y.js} +11 -15
- package/dist/chunk-VE2UIJ7Y.js.map +1 -0
- package/dist/{chunk-WBF7JLTY.js → chunk-W53D5Q52.js} +4 -4
- package/dist/{chunk-WBF7JLTY.js.map → chunk-W53D5Q52.js.map} +1 -1
- package/dist/{chunk-HNORRENR.js → chunk-WD2NRI3T.js} +5 -5
- package/dist/{chunk-HNORRENR.js.map → chunk-WD2NRI3T.js.map} +1 -1
- package/dist/cli/index.js +679 -477
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/src/asset-feeds.d.ts +17 -3
- package/dist/cli/src/asset-feeds.d.ts.map +1 -1
- package/dist/cli/src/commands/catalog.d.ts +3 -2
- package/dist/cli/src/commands/catalog.d.ts.map +1 -1
- package/dist/cli/src/commands/manage.d.ts +47 -8
- package/dist/cli/src/commands/manage.d.ts.map +1 -1
- package/dist/cli/src/commands/project.d.ts.map +1 -1
- package/dist/cli/src/commands/source.d.ts +32 -0
- package/dist/cli/src/commands/source.d.ts.map +1 -1
- package/dist/cli/src/commands/update.d.ts +7 -0
- package/dist/cli/src/commands/update.d.ts.map +1 -1
- package/dist/connectors/config.js +7 -7
- package/dist/connectors/index.js +9 -9
- package/dist/connectors/src/config.d.ts +5 -13
- package/dist/connectors/src/config.d.ts.map +1 -1
- package/dist/connectors/src/index.d.ts +1 -1
- package/dist/connectors/src/index.d.ts.map +1 -1
- package/dist/core/driver-targets.js +1 -1
- package/dist/core/index.js +6 -6
- package/dist/core/manifest.js +1 -1
- package/dist/core/runtime-assets.js +4 -3
- package/dist/core/src/cache-paths.d.ts +6 -0
- package/dist/core/src/cache-paths.d.ts.map +1 -1
- package/dist/core/src/driver-targets.d.ts +12 -7
- package/dist/core/src/driver-targets.d.ts.map +1 -1
- package/dist/core/src/index.d.ts +3 -3
- package/dist/core/src/index.d.ts.map +1 -1
- package/dist/core/src/manifest.d.ts +6 -6
- package/dist/core/src/manifest.d.ts.map +1 -1
- package/dist/core/src/workspace-config.d.ts +36 -0
- package/dist/core/src/workspace-config.d.ts.map +1 -1
- package/dist/core/store.js +2 -2
- package/dist/core/workspace-config.js +3 -2
- package/dist/deploy/index.js +6 -6
- package/dist/discovery/index.js +2 -2
- package/dist/discovery/src/atomization-conventions.d.ts +30 -0
- package/dist/discovery/src/atomization-conventions.d.ts.map +1 -0
- package/dist/discovery/src/builtin-providers.d.ts.map +1 -1
- package/dist/discovery/src/discover-manifest.d.ts.map +1 -1
- package/dist/discovery/src/discover.d.ts +38 -0
- package/dist/discovery/src/discover.d.ts.map +1 -1
- package/dist/discovery/src/index.d.ts +5 -2
- package/dist/discovery/src/index.d.ts.map +1 -1
- package/dist/discovery/src/reference-lint.d.ts +112 -0
- package/dist/discovery/src/reference-lint.d.ts.map +1 -0
- package/dist/discovery/src/requires-graph.d.ts +1 -1
- package/dist/discovery/src/tree-entries.d.ts +9 -1
- package/dist/discovery/src/tree-entries.d.ts.map +1 -1
- package/dist/{ensure-sources-EE7Z2HKS.js → ensure-sources-GJOXWVWO.js} +8 -8
- package/dist/{ensure-sources-EE7Z2HKS.js.map → ensure-sources-GJOXWVWO.js.map} +1 -1
- package/dist/factory-assets/connectors/deploy.js +9 -9
- package/dist/factory-assets/connectors/devserver.js +9 -9
- package/dist/factory-assets/connectors/flow/adapter.js +9 -9
- package/dist/factory-assets/connectors/flow/engine/flow-kind-provider.d.ts +1 -1
- package/dist/factory-assets/connectors/flow/engine/flow-kind-provider.d.ts.map +1 -1
- package/dist/factory-assets/connectors/flow/engine.js +7 -7
- package/dist/factory-assets/connectors/flow/run-flow.js +10 -10
- package/dist/factory-assets/connectors/flow.js +9 -9
- package/dist/factory-assets/connectors/git.js +9 -9
- package/dist/factory-assets/connectors/gmail/adapter.d.ts.map +1 -1
- package/dist/factory-assets/connectors/gmail.js +9 -9
- package/dist/factory-assets/connectors/googledrive.js +9 -9
- package/dist/factory-assets/connectors/local.js +9 -9
- package/dist/factory-assets/connectors/mattermost/adapter.d.ts.map +1 -1
- package/dist/factory-assets/connectors/mattermost.js +9 -9
- package/dist/factory-assets/connectors/memory.js +9 -9
- package/dist/factory-assets/connectors/minio/adapter.d.ts.map +1 -1
- package/dist/factory-assets/connectors/minio.js +9 -9
- package/dist/factory-assets/connectors/postgres/adapter.d.ts.map +1 -1
- package/dist/factory-assets/connectors/postgres.js +9 -9
- package/dist/factory-assets/connectors/s3/driver.d.ts.map +1 -1
- package/dist/factory-assets/connectors/s3.js +9 -9
- package/dist/factory-assets/connectors/sharepoint.js +9 -9
- package/dist/factory-assets/connectors/sqlite/adapter.d.ts.map +1 -1
- package/dist/factory-assets/connectors/sqlite.js +9 -9
- package/dist/factory-assets/connectors/static-server.js +9 -9
- package/dist/factory-assets/connectors/tunnel.js +9 -9
- package/dist/factory-assets/connectors/webdav.js +9 -9
- package/dist/factory-assets/connectors/xstate-store.js +9 -9
- package/dist/factory-assets/connectors/xstate.js +9 -9
- package/dist/{flows-AAHXXXCH.js → flows-AGPIE6JM.js} +3 -3
- package/dist/{flows-AAHXXXCH.js.map → flows-AGPIE6JM.js.map} +1 -1
- package/dist/library/index.js +8 -8
- package/dist/library/install.js +6 -6
- package/dist/open-library-ERKRGH4B.js +23 -0
- package/dist/{open-library-TXJMFG34.js.map → open-library-ERKRGH4B.js.map} +1 -1
- package/dist/paths-D6RUQ522.js +15 -0
- package/dist/{paths-OMVC4UWY.js.map → paths-D6RUQ522.js.map} +1 -1
- package/dist/{plugin-store-JWJHIPUT.js → plugin-store-SGNJTBYS.js} +8 -8
- package/dist/{plugin-store-JWJHIPUT.js.map → plugin-store-SGNJTBYS.js.map} +1 -1
- package/dist/runner/index.js +11 -11
- package/dist/runner/src/serve.d.ts.map +1 -1
- package/dist/sdk/asset-manager.js +8 -8
- package/dist/sdk/core.js +6 -6
- package/dist/sdk/flow.js +7 -7
- package/dist/sdk/index.js +17 -11
- package/dist/sdk/index.js.map +1 -1
- package/dist/sdk/runner.js +11 -11
- package/dist/sdk/src/transport.d.ts +2 -0
- package/dist/sdk/src/transport.d.ts.map +1 -1
- package/dist/{setup-ETNBVZQA.js → setup-IV2JFW3T.js} +8 -8
- package/dist/{setup-ETNBVZQA.js.map → setup-IV2JFW3T.js.map} +1 -1
- package/dist/source-FGOMQMZT.js +24 -0
- package/dist/source-FGOMQMZT.js.map +1 -0
- package/dist/store-client-GJT2XQ5Z.js +15 -0
- package/dist/{store-client-SLFAAKSV.js.map → store-client-GJT2XQ5Z.js.map} +1 -1
- package/dist/tui/index.js +11 -11
- package/dist/types/src/transport.d.ts +12 -0
- package/dist/types/src/transport.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-O6R6J4RI.js +0 -128
- package/dist/asset-feeds-O6R6J4RI.js.map +0 -1
- package/dist/chunk-2Y4HIITD.js.map +0 -1
- package/dist/chunk-6IDBWPK2.js.map +0 -1
- package/dist/chunk-C5RYGUF4.js.map +0 -1
- package/dist/chunk-EBSIZYM6.js.map +0 -1
- package/dist/chunk-JXHULIOA.js.map +0 -1
- package/dist/chunk-LV73DB4G.js.map +0 -1
- package/dist/chunk-O4JH3KUE.js.map +0 -1
- package/dist/chunk-PBO6SCT2.js.map +0 -1
- package/dist/chunk-X46FY45B.js.map +0 -1
- package/dist/chunk-ZJ3VRPOI.js.map +0 -1
- package/dist/open-library-TXJMFG34.js +0 -23
- package/dist/paths-OMVC4UWY.js +0 -15
- package/dist/store-client-SLFAAKSV.js +0 -15
package/dist/cli/index.js
CHANGED
|
@@ -1,19 +1,20 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
2
|
+
import { AI_RESOURCES, aiResourceRoots } from '../chunk-LKOMH3QC.js';
|
|
3
|
+
import { makeSourceCommand, syncProjectSources } from '../chunk-BXC5547R.js';
|
|
4
|
+
import { openCatalogSource, openLibraryManager, createFullRegistry, openLibrary } from '../chunk-WD2NRI3T.js';
|
|
3
5
|
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-33WB7VFV.js';
|
|
6
|
+
import { getStoreConfig, storeFetch, saveStoreTokens, clearStoreTokens, isStoreAuthenticated } from '../chunk-2ZK7M2SG.js';
|
|
6
7
|
import { LocalSecretsProvider } from '../chunk-6BEGKO2Q.js';
|
|
7
|
-
import { resolveLibraryDir
|
|
8
|
-
import '../chunk-
|
|
8
|
+
import { resolveLibraryDir } from '../chunk-2D5YE3FL.js';
|
|
9
|
+
import '../chunk-UTHEIPEY.js';
|
|
9
10
|
import '../chunk-JXT46QFC.js';
|
|
10
11
|
import '../chunk-UKJMQZV6.js';
|
|
11
12
|
import '../chunk-R7FOF242.js';
|
|
12
|
-
import { runFlow, resumeFlow } from '../chunk-
|
|
13
|
+
import { runFlow, resumeFlow } from '../chunk-6K4RVXAM.js';
|
|
13
14
|
import '../chunk-4R6DROGN.js';
|
|
14
15
|
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-
|
|
16
|
+
import { runAgentChat, loadSessionById, loadSession, listSessions, setCurrentSession, deleteSession, clearSession, loadAgentManifest, compileComposition, MarkdownStreamer, resolveMixin } from '../chunk-MGB657EG.js';
|
|
17
|
+
import { buildClaudePluginFiles } from '../chunk-3IHBGDCG.js';
|
|
17
18
|
import '../chunk-X5YPJV4N.js';
|
|
18
19
|
import '../chunk-O7SG5PC2.js';
|
|
19
20
|
import '../chunk-7QBNJTTQ.js';
|
|
@@ -28,25 +29,25 @@ import '../chunk-BMQKMOQY.js';
|
|
|
28
29
|
import '../chunk-GAH4YRCI.js';
|
|
29
30
|
import '../chunk-N5AE5SOC.js';
|
|
30
31
|
import '../chunk-LV2HPH3C.js';
|
|
31
|
-
import '../chunk-
|
|
32
|
+
import '../chunk-QLLFCQU5.js';
|
|
32
33
|
import '../chunk-OVRSNIKJ.js';
|
|
33
|
-
import '../chunk-
|
|
34
|
+
import '../chunk-VE2UIJ7Y.js';
|
|
34
35
|
import '../chunk-RAIRWFAN.js';
|
|
35
36
|
import '../chunk-6E6PKKAD.js';
|
|
36
|
-
import { loadFlow, loadAllFlows } from '../chunk-
|
|
37
|
+
import { loadFlow, loadAllFlows } from '../chunk-SKADPHAM.js';
|
|
37
38
|
import '../chunk-DEYYRFQU.js';
|
|
38
39
|
import '../chunk-IFGTRL2I.js';
|
|
39
|
-
import { AssetManager, NON_DEPLOYABLE_KINDS, MissingManifestError } from '../chunk-
|
|
40
|
-
import '../chunk-
|
|
41
|
-
import { readLock, resolveSettings, globalSettingsPath, projectSettingsPath, loadSettings, saveSettings, portableSpawn, portableSpawnSync, WorkspaceYamlEditor, checkAgentSkillConformance } from '../chunk-
|
|
40
|
+
import { AssetManager, NON_DEPLOYABLE_KINDS, MissingManifestError } from '../chunk-TCNYSHPM.js';
|
|
41
|
+
import '../chunk-7ZWLZ5H3.js';
|
|
42
|
+
import { readLock, resolveSettings, globalSettingsPath, projectSettingsPath, loadSettings, saveSettings, portableSpawn, portableSpawnSync, WorkspaceYamlEditor, checkAgentSkillConformance } from '../chunk-3KPNDTMR.js';
|
|
42
43
|
import { assetSearchDirs, detectDomains } from '../chunk-ZAP2BDHG.js';
|
|
43
|
-
import '../chunk-
|
|
44
|
-
import { globalCacheRoot, sourceCacheKey, getGlobalCacheDir, resolveAgentDir,
|
|
44
|
+
import '../chunk-W53D5Q52.js';
|
|
45
|
+
import { globalCacheRoot, sourceCacheKey, getGlobalCacheDir, resolveAgentDir, resolveSkWorkspaceConfig } from '../chunk-NXC6IEL4.js';
|
|
45
46
|
import { SKAILE_MANIFEST_FILENAME, decodeSkaileManifest, loadSkPublishManifest, saveSkPublishManifest } from '../chunk-DZCK7GRW.js';
|
|
46
|
-
import { parseFrontmatter } from '../chunk-
|
|
47
|
+
import { parseFrontmatter } from '../chunk-BQCGFPHW.js';
|
|
47
48
|
import { parseAssetRef, ASSET_KINDS, isValidAssetName, slugifyAssetName, ASSET_NAME_HINT, assetRefToStr } from '../chunk-GEEW6SY2.js';
|
|
48
|
-
import '../chunk-
|
|
49
|
-
import { SUPPORTED_DRIVER_TARGETS } from '../chunk-
|
|
49
|
+
import '../chunk-F3HNW354.js';
|
|
50
|
+
import { SUPPORTED_DRIVER_TARGETS } from '../chunk-MENCWIHW.js';
|
|
50
51
|
import { DRIVER_DEFAULTS } from '../chunk-K5GBV4SA.js';
|
|
51
52
|
import { openSqlite } from '../chunk-JB35MVBN.js';
|
|
52
53
|
import '../chunk-KTBKW2FI.js';
|
|
@@ -70,7 +71,7 @@ import * as readline from 'readline';
|
|
|
70
71
|
import { createInterface } from 'readline';
|
|
71
72
|
import fs6 from 'fs/promises';
|
|
72
73
|
import { parse as parse$1, stringify as stringify$1 } from 'smol-toml';
|
|
73
|
-
import { execSync
|
|
74
|
+
import { execSync } from 'child_process';
|
|
74
75
|
import { createTRPCUntypedClient, httpLink, httpSubscriptionLink } from '@trpc/client';
|
|
75
76
|
|
|
76
77
|
async function runSearch(kind, query, opts) {
|
|
@@ -80,16 +81,24 @@ async function runSearch(kind, query, opts) {
|
|
|
80
81
|
}
|
|
81
82
|
const showLocal = !opts.store;
|
|
82
83
|
const showStore = !opts.local;
|
|
84
|
+
const { resolveConfig } = await import('../library/index.js');
|
|
85
|
+
const airGapped = resolveConfig({ projectDir: path14__default.resolve(opts.projectDir) }).catalog.cache_ttl === 0;
|
|
83
86
|
if (showLocal) {
|
|
84
|
-
searchLocal(query, kind, opts, showStore);
|
|
87
|
+
await searchLocal(query, kind, opts, showStore, airGapped);
|
|
85
88
|
}
|
|
86
89
|
if (showStore) {
|
|
87
|
-
await searchStore(query, kind, opts);
|
|
90
|
+
await searchStore(query, kind, opts, airGapped);
|
|
88
91
|
}
|
|
89
92
|
}
|
|
90
|
-
function searchLocal(query, kind, opts, showStore) {
|
|
91
|
-
const
|
|
92
|
-
|
|
93
|
+
async function searchLocal(query, kind, opts, showStore, airGapped) {
|
|
94
|
+
const projectDir = path14__default.resolve(opts.projectDir);
|
|
95
|
+
let entries = new AssetManager({ projectDir }).search(query, kind);
|
|
96
|
+
if (entries.length === 0 && !query && !kind && !airGapped) {
|
|
97
|
+
const { autoSyncForSearch } = await import('../source-FGOMQMZT.js');
|
|
98
|
+
if (await autoSyncForSearch(projectDir)) {
|
|
99
|
+
entries = new AssetManager({ projectDir }).search(query, kind);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
93
102
|
if (entries.length === 0) {
|
|
94
103
|
if (!showStore) {
|
|
95
104
|
logInfo(
|
|
@@ -126,9 +135,19 @@ function printLocalEntries(entries) {
|
|
|
126
135
|
${S.dim(`${entries.length} total`)}
|
|
127
136
|
`);
|
|
128
137
|
}
|
|
129
|
-
async function searchStore(query, kind, opts) {
|
|
138
|
+
async function searchStore(query, kind, opts, airGapped) {
|
|
139
|
+
if (airGapped) {
|
|
140
|
+
if (opts.store) {
|
|
141
|
+
logErr(
|
|
142
|
+
"air-gapped (catalog.cache_ttl: 0) \u2014 store search is disabled. Set catalog.cache_ttl > 0 to query the store."
|
|
143
|
+
);
|
|
144
|
+
process.exit(1);
|
|
145
|
+
}
|
|
146
|
+
logInfo("air-gapped (cache_ttl: 0) \u2014 local sources only");
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
130
149
|
try {
|
|
131
|
-
const { getStoreConfig: getStoreConfig2, storeFetch: storeFetch2 } = await import('../store-client-
|
|
150
|
+
const { getStoreConfig: getStoreConfig2, storeFetch: storeFetch2 } = await import('../store-client-GJT2XQ5Z.js');
|
|
132
151
|
const config = getStoreConfig2();
|
|
133
152
|
const params = {};
|
|
134
153
|
if (query) params.q = query;
|
|
@@ -149,6 +168,8 @@ async function searchStore(query, kind, opts) {
|
|
|
149
168
|
} catch (e) {
|
|
150
169
|
if (opts.store) {
|
|
151
170
|
logErr(`Store search failed: ${e.message}`);
|
|
171
|
+
} else {
|
|
172
|
+
logInfo("store unavailable \u2014 showing local results only (run with --store to see the error)");
|
|
152
173
|
}
|
|
153
174
|
}
|
|
154
175
|
}
|
|
@@ -157,14 +178,32 @@ function makeSearchCommand() {
|
|
|
157
178
|
await runSearch(kind, query, opts);
|
|
158
179
|
});
|
|
159
180
|
}
|
|
181
|
+
function parseBackendFilter(raw) {
|
|
182
|
+
if (!raw) return void 0;
|
|
183
|
+
const ids = raw.split(",").map((s) => s.trim()).filter(Boolean);
|
|
184
|
+
const out = [];
|
|
185
|
+
for (const id of ids) {
|
|
186
|
+
if (!SUPPORTED_DRIVER_TARGETS.includes(id)) {
|
|
187
|
+
logErr(`unknown backend '${id}' \u2014 expected one of: ${SUPPORTED_DRIVER_TARGETS.join(", ")}`);
|
|
188
|
+
process.exit(1);
|
|
189
|
+
}
|
|
190
|
+
out.push(id);
|
|
191
|
+
}
|
|
192
|
+
return out.length > 0 ? out : void 0;
|
|
193
|
+
}
|
|
160
194
|
function makeAddCommand() {
|
|
161
|
-
return new Command("add").description("Add to skaile.yaml + deploy").argument("<ref>", "Asset reference (kind:@<publisher>/name#<version>)").option("--project-dir <path>", "Project directory", process.cwd()).option("--global", "
|
|
195
|
+
return new Command("add").description("Add to skaile.yaml + deploy").argument("<ref>", "Asset reference (kind:@<publisher>/name#<version>)").option("--project-dir <path>", "Project directory", process.cwd()).option("--global", "Record in ~/.skaile/skaile.yaml + deploy to every global backend").option(
|
|
196
|
+
"--backend <ids>",
|
|
197
|
+
"Comma-separated global backends to deploy into (default: all resolved); implies --global"
|
|
198
|
+
).option("--target <agent>", "Driver target", "claude-code").option(
|
|
162
199
|
"--link",
|
|
163
200
|
"symlink local-path assets instead of copying (dev loop; machine-local, not for committing)"
|
|
164
201
|
).action(async (ref, opts) => {
|
|
202
|
+
const backends = parseBackendFilter(opts.backend);
|
|
165
203
|
const am2 = new AssetManager({
|
|
166
204
|
projectDir: path14__default.resolve(opts.projectDir),
|
|
167
|
-
global: opts.global,
|
|
205
|
+
global: opts.global || backends !== void 0,
|
|
206
|
+
backends,
|
|
168
207
|
driverTarget: opts.target
|
|
169
208
|
});
|
|
170
209
|
const spinner5 = p6.spinner();
|
|
@@ -188,10 +227,15 @@ function makeAddCommand() {
|
|
|
188
227
|
});
|
|
189
228
|
}
|
|
190
229
|
function makeRemoveCommand() {
|
|
191
|
-
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
|
|
230
|
+
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 ~/.skaile/skaile.yaml + undeploy from every global backend").option(
|
|
231
|
+
"--backend <ids>",
|
|
232
|
+
"Comma-separated global backends to undeploy from (default: all resolved); implies --global"
|
|
233
|
+
).option("--target <agent>", "Driver target", "claude-code").action((ref, opts) => {
|
|
234
|
+
const backends = parseBackendFilter(opts.backend);
|
|
192
235
|
const am2 = new AssetManager({
|
|
193
236
|
projectDir: path14__default.resolve(opts.projectDir),
|
|
194
|
-
global: opts.global,
|
|
237
|
+
global: opts.global || backends !== void 0,
|
|
238
|
+
backends,
|
|
195
239
|
driverTarget: opts.target
|
|
196
240
|
});
|
|
197
241
|
const ok = am2.remove(ref);
|
|
@@ -206,12 +250,19 @@ function stateLabel(s) {
|
|
|
206
250
|
return S.dim(s);
|
|
207
251
|
}
|
|
208
252
|
function makeListCommand() {
|
|
209
|
-
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(
|
|
253
|
+
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(
|
|
254
|
+
"-g, --global",
|
|
255
|
+
"Read the global SSOT (~/.skaile/skaile.yaml); report state per backend"
|
|
256
|
+
).option("--backend <ids>", "Comma-separated global backends to report (implies --global)").option("--json", "Output as JSON").addOption(
|
|
210
257
|
new Option("--target <agent>", "Driver target").default("claude-code").choices(SUPPORTED_DRIVER_TARGETS)
|
|
211
258
|
).action((kind, opts) => {
|
|
259
|
+
const backends = parseBackendFilter(opts.backend);
|
|
260
|
+
if (opts.global || backends) {
|
|
261
|
+
runGlobalList(kind, opts, backends);
|
|
262
|
+
return;
|
|
263
|
+
}
|
|
212
264
|
const am2 = new AssetManager({
|
|
213
265
|
projectDir: path14__default.resolve(opts.projectDir),
|
|
214
|
-
global: opts.global,
|
|
215
266
|
driverTarget: opts.target
|
|
216
267
|
});
|
|
217
268
|
let declared;
|
|
@@ -254,6 +305,47 @@ function makeListCommand() {
|
|
|
254
305
|
console.log();
|
|
255
306
|
});
|
|
256
307
|
}
|
|
308
|
+
function runGlobalList(kind, opts, backends) {
|
|
309
|
+
const am2 = new AssetManager({
|
|
310
|
+
projectDir: path14__default.resolve(opts.projectDir),
|
|
311
|
+
global: true,
|
|
312
|
+
backends
|
|
313
|
+
});
|
|
314
|
+
let rows;
|
|
315
|
+
try {
|
|
316
|
+
rows = am2.globalState({ kind });
|
|
317
|
+
} catch (err) {
|
|
318
|
+
logErr(err instanceof Error ? err.message : String(err));
|
|
319
|
+
process.exit(1);
|
|
320
|
+
}
|
|
321
|
+
if (opts.json) {
|
|
322
|
+
console.log(JSON.stringify(rows, null, 2));
|
|
323
|
+
return;
|
|
324
|
+
}
|
|
325
|
+
if (rows.length === 0) {
|
|
326
|
+
logInfo("No global dependencies declared in ~/.skaile/skaile.yaml.");
|
|
327
|
+
return;
|
|
328
|
+
}
|
|
329
|
+
const kindW = Math.max(4, ...rows.map((e) => e.kind.length));
|
|
330
|
+
const nameW = Math.max(4, ...rows.map((e) => e.name.length));
|
|
331
|
+
const beW = Math.max(7, ...rows.map((e) => e.backend.length));
|
|
332
|
+
console.log();
|
|
333
|
+
console.log(
|
|
334
|
+
` ${S.dim("KIND".padEnd(kindW))} ${S.dim("NAME".padEnd(nameW))} ${S.dim("BACKEND".padEnd(beW))} ${S.dim("STATE")}`
|
|
335
|
+
);
|
|
336
|
+
console.log(` ${S.rule(kindW + nameW + beW + 6 + "installed".length)}`);
|
|
337
|
+
for (const e of rows) {
|
|
338
|
+
console.log(
|
|
339
|
+
` ${kindColorPad(e.kind, kindW)} ${e.name.padEnd(nameW)} ${e.backend.padEnd(beW)} ${stateLabel(e.state)}`
|
|
340
|
+
);
|
|
341
|
+
}
|
|
342
|
+
console.log(`
|
|
343
|
+
${S.dim(`${rows.length} entries`)}`);
|
|
344
|
+
const drift = rows.filter((e) => e.state === "drift").length;
|
|
345
|
+
if (drift > 0)
|
|
346
|
+
logInfo(`${drift} with drift \u2014 run ${S.cmd("skaile install --global")} to materialize.`);
|
|
347
|
+
console.log();
|
|
348
|
+
}
|
|
257
349
|
function makeInfoCommand() {
|
|
258
350
|
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) => {
|
|
259
351
|
const am2 = new AssetManager({ projectDir: path14__default.resolve(opts.projectDir) });
|
|
@@ -515,9 +607,9 @@ function makeAssetCommand() {
|
|
|
515
607
|
});
|
|
516
608
|
logOk(`${up.added ? "Added" : "Updated"} manifest entry skill:${norm.name}`);
|
|
517
609
|
if (target.backend === "git" && opts.commit) {
|
|
518
|
-
const { spawnSync
|
|
519
|
-
|
|
520
|
-
const r =
|
|
610
|
+
const { spawnSync } = await import('child_process');
|
|
611
|
+
spawnSync("git", ["add", "--", destDir], { cwd: target.path, stdio: "inherit" });
|
|
612
|
+
const r = spawnSync("git", ["commit", "-m", `skaile: import ${norm.name}`], {
|
|
521
613
|
cwd: target.path,
|
|
522
614
|
stdio: "inherit"
|
|
523
615
|
});
|
|
@@ -585,9 +677,9 @@ function makeAssetCommand() {
|
|
|
585
677
|
break;
|
|
586
678
|
}
|
|
587
679
|
if (target.backend === "git" && opts.commit) {
|
|
588
|
-
const { spawnSync
|
|
589
|
-
|
|
590
|
-
const r =
|
|
680
|
+
const { spawnSync } = await import('child_process');
|
|
681
|
+
spawnSync("git", ["add", "--", destPath], { cwd: target.path, stdio: "inherit" });
|
|
682
|
+
const r = spawnSync("git", ["commit", "-m", `skaile: migrate ${basename2}`], {
|
|
591
683
|
cwd: target.path,
|
|
592
684
|
stdio: "inherit"
|
|
593
685
|
});
|
|
@@ -832,7 +924,7 @@ function makeCatalogCommand() {
|
|
|
832
924
|
return catalog;
|
|
833
925
|
}
|
|
834
926
|
async function runLocalCatalogTest(projectDir) {
|
|
835
|
-
const { resolveCatalogSource } = await import('../open-library-
|
|
927
|
+
const { resolveCatalogSource } = await import('../open-library-ERKRGH4B.js');
|
|
836
928
|
let resolved;
|
|
837
929
|
try {
|
|
838
930
|
resolved = await resolveCatalogSource({ projectDir });
|
|
@@ -1083,13 +1175,13 @@ function collectWorkspaceDefaults(projectDir) {
|
|
|
1083
1175
|
const wsDefaults = {};
|
|
1084
1176
|
try {
|
|
1085
1177
|
const ws = resolveSkWorkspaceConfig(projectDir);
|
|
1086
|
-
const
|
|
1087
|
-
if (
|
|
1088
|
-
if (
|
|
1089
|
-
if (
|
|
1090
|
-
if (
|
|
1091
|
-
if (
|
|
1092
|
-
if (
|
|
1178
|
+
const p8 = ws.agent_config?.default ?? {};
|
|
1179
|
+
if (p8.driver) wsDefaults.driver = p8.driver;
|
|
1180
|
+
if (p8.provider) wsDefaults.provider = p8.provider;
|
|
1181
|
+
if (p8.model) wsDefaults.model = p8.model;
|
|
1182
|
+
if (p8.skills_dir) wsDefaults.skills_dir = p8.skills_dir;
|
|
1183
|
+
if (p8.agents_dir) wsDefaults.agents_dir = p8.agents_dir;
|
|
1184
|
+
if (p8.prompts_dir) wsDefaults.prompts_dir = p8.prompts_dir;
|
|
1093
1185
|
} catch {
|
|
1094
1186
|
}
|
|
1095
1187
|
return wsDefaults;
|
|
@@ -1822,7 +1914,7 @@ async function ensureTargetsRegistered(projectDir) {
|
|
|
1822
1914
|
const { resolveSkWorkspaceConfig: resolveSkWorkspaceConfig2 } = await import('../core/index.js');
|
|
1823
1915
|
const config = resolveSkWorkspaceConfig2(projectDir);
|
|
1824
1916
|
if (config.plugins && config.plugins.length > 0) {
|
|
1825
|
-
const { ensurePluginsLoaded } = await import('../plugin-store-
|
|
1917
|
+
const { ensurePluginsLoaded } = await import('../plugin-store-SGNJTBYS.js');
|
|
1826
1918
|
const result = await ensurePluginsLoaded(projectDir, config.plugins, pluginRegistry);
|
|
1827
1919
|
for (const f of result.failed) logWarn(f.error);
|
|
1828
1920
|
}
|
|
@@ -2031,10 +2123,10 @@ var MCP_SERVER_ENTRY = {
|
|
|
2031
2123
|
function pluginDir(projectDir) {
|
|
2032
2124
|
return path14__default.join(projectDir, ".claude", "plugins", "skaile");
|
|
2033
2125
|
}
|
|
2034
|
-
async function readJsonStrict(
|
|
2126
|
+
async function readJsonStrict(p8) {
|
|
2035
2127
|
let raw;
|
|
2036
2128
|
try {
|
|
2037
|
-
raw = await fs6.readFile(
|
|
2129
|
+
raw = await fs6.readFile(p8, "utf-8");
|
|
2038
2130
|
} catch {
|
|
2039
2131
|
return null;
|
|
2040
2132
|
}
|
|
@@ -2042,13 +2134,13 @@ async function readJsonStrict(p9) {
|
|
|
2042
2134
|
return JSON.parse(raw);
|
|
2043
2135
|
} catch (e) {
|
|
2044
2136
|
throw new Error(
|
|
2045
|
-
`cannot parse ${
|
|
2137
|
+
`cannot parse ${p8}: ${e instanceof Error ? e.message : String(e)}; please fix or remove`
|
|
2046
2138
|
);
|
|
2047
2139
|
}
|
|
2048
2140
|
}
|
|
2049
|
-
async function writeJson(
|
|
2050
|
-
await fs6.mkdir(path14__default.dirname(
|
|
2051
|
-
await fs6.writeFile(
|
|
2141
|
+
async function writeJson(p8, value) {
|
|
2142
|
+
await fs6.mkdir(path14__default.dirname(p8), { recursive: true });
|
|
2143
|
+
await fs6.writeFile(p8, `${JSON.stringify(value, null, 2)}
|
|
2052
2144
|
`);
|
|
2053
2145
|
}
|
|
2054
2146
|
async function copyDir(src, dest) {
|
|
@@ -2103,7 +2195,7 @@ async function uninstall(projectDir) {
|
|
|
2103
2195
|
let changed = false;
|
|
2104
2196
|
const settings = await readJsonStrict(settingsPath);
|
|
2105
2197
|
if (settings && Array.isArray(settings.plugins)) {
|
|
2106
|
-
const next = settings.plugins.filter((
|
|
2198
|
+
const next = settings.plugins.filter((p8) => p8 !== dir);
|
|
2107
2199
|
if (next.length !== settings.plugins.length) {
|
|
2108
2200
|
changed = true;
|
|
2109
2201
|
const updated = { ...settings, plugins: next };
|
|
@@ -2150,7 +2242,7 @@ async function enable(projectDir) {
|
|
|
2150
2242
|
const settings = await readJsonStrict(settingsPath) ?? {};
|
|
2151
2243
|
if (detected.method === "plugin") {
|
|
2152
2244
|
const disabled2 = settings.disabledPlugins ?? [];
|
|
2153
|
-
const next2 = disabled2.filter((
|
|
2245
|
+
const next2 = disabled2.filter((p8) => p8 !== detected.pluginPath);
|
|
2154
2246
|
if (next2.length === disabled2.length) return { changed: false };
|
|
2155
2247
|
const updated2 = { ...settings, disabledPlugins: next2 };
|
|
2156
2248
|
if (next2.length === 0) delete updated2.disabledPlugins;
|
|
@@ -2231,10 +2323,10 @@ function buildEntry(projectDir) {
|
|
|
2231
2323
|
env: { SKAILE_PROJECT_DIR: projectDir }
|
|
2232
2324
|
};
|
|
2233
2325
|
}
|
|
2234
|
-
async function readConfig(
|
|
2326
|
+
async function readConfig(p8) {
|
|
2235
2327
|
let raw;
|
|
2236
2328
|
try {
|
|
2237
|
-
raw = await fs6.readFile(
|
|
2329
|
+
raw = await fs6.readFile(p8, "utf-8");
|
|
2238
2330
|
} catch {
|
|
2239
2331
|
return null;
|
|
2240
2332
|
}
|
|
@@ -2242,41 +2334,41 @@ async function readConfig(p9) {
|
|
|
2242
2334
|
return parse$1(raw);
|
|
2243
2335
|
} catch (e) {
|
|
2244
2336
|
throw new Error(
|
|
2245
|
-
`cannot parse ${
|
|
2337
|
+
`cannot parse ${p8}: ${e instanceof Error ? e.message : String(e)}; please fix or remove`
|
|
2246
2338
|
);
|
|
2247
2339
|
}
|
|
2248
2340
|
}
|
|
2249
|
-
async function writeConfig(
|
|
2250
|
-
await fs6.mkdir(path14__default.dirname(
|
|
2341
|
+
async function writeConfig(p8, value) {
|
|
2342
|
+
await fs6.mkdir(path14__default.dirname(p8), { recursive: true });
|
|
2251
2343
|
const cleaned = {};
|
|
2252
2344
|
for (const [k, v] of Object.entries(value)) {
|
|
2253
2345
|
if (v === void 0) continue;
|
|
2254
2346
|
cleaned[k] = v;
|
|
2255
2347
|
}
|
|
2256
|
-
await fs6.writeFile(
|
|
2348
|
+
await fs6.writeFile(p8, stringify$1(cleaned));
|
|
2257
2349
|
}
|
|
2258
2350
|
function configPath(projectDir) {
|
|
2259
2351
|
return path14__default.join(projectDir, ".codex", "config.toml");
|
|
2260
2352
|
}
|
|
2261
2353
|
async function install2(projectDir) {
|
|
2262
|
-
const
|
|
2263
|
-
const cfg = await readConfig(
|
|
2354
|
+
const p8 = configPath(projectDir);
|
|
2355
|
+
const cfg = await readConfig(p8) ?? {};
|
|
2264
2356
|
const next = buildEntry(projectDir);
|
|
2265
2357
|
const servers = { ...cfg.mcp_servers ?? {} };
|
|
2266
2358
|
const previous = servers[SKAILE_MCP_NAME2];
|
|
2267
2359
|
const matches = previous && JSON.stringify(previous) === JSON.stringify(next);
|
|
2268
2360
|
let warning;
|
|
2269
2361
|
if (previous && !matches) {
|
|
2270
|
-
warning = `overwrote existing ${SKAILE_MCP_NAME2} entry in ${path14__default.relative(projectDir,
|
|
2362
|
+
warning = `overwrote existing ${SKAILE_MCP_NAME2} entry in ${path14__default.relative(projectDir, p8)}`;
|
|
2271
2363
|
}
|
|
2272
2364
|
if (matches) return { changed: false, method: "toml" };
|
|
2273
2365
|
servers[SKAILE_MCP_NAME2] = next;
|
|
2274
|
-
await writeConfig(
|
|
2366
|
+
await writeConfig(p8, { ...cfg, mcp_servers: servers });
|
|
2275
2367
|
return { changed: true, method: "toml", warning };
|
|
2276
2368
|
}
|
|
2277
2369
|
async function uninstall2(projectDir) {
|
|
2278
|
-
const
|
|
2279
|
-
const cfg = await readConfig(
|
|
2370
|
+
const p8 = configPath(projectDir);
|
|
2371
|
+
const cfg = await readConfig(p8);
|
|
2280
2372
|
if (!cfg?.mcp_servers || !(SKAILE_MCP_NAME2 in cfg.mcp_servers)) {
|
|
2281
2373
|
return { changed: false };
|
|
2282
2374
|
}
|
|
@@ -2284,15 +2376,15 @@ async function uninstall2(projectDir) {
|
|
|
2284
2376
|
const updated = { ...cfg, mcp_servers: rest };
|
|
2285
2377
|
if (Object.keys(rest).length === 0) delete updated.mcp_servers;
|
|
2286
2378
|
if (Object.keys(updated).length === 0) {
|
|
2287
|
-
await fs6.unlink(
|
|
2379
|
+
await fs6.unlink(p8);
|
|
2288
2380
|
} else {
|
|
2289
|
-
await writeConfig(
|
|
2381
|
+
await writeConfig(p8, updated);
|
|
2290
2382
|
}
|
|
2291
2383
|
return { changed: true };
|
|
2292
2384
|
}
|
|
2293
2385
|
async function status2(projectDir) {
|
|
2294
|
-
const
|
|
2295
|
-
const cfg = await readConfig(
|
|
2386
|
+
const p8 = configPath(projectDir);
|
|
2387
|
+
const cfg = await readConfig(p8);
|
|
2296
2388
|
const installed = !!(cfg?.mcp_servers && SKAILE_MCP_NAME2 in cfg.mcp_servers);
|
|
2297
2389
|
if (!installed) {
|
|
2298
2390
|
return {
|
|
@@ -2308,7 +2400,7 @@ async function status2(projectDir) {
|
|
|
2308
2400
|
installed: "yes",
|
|
2309
2401
|
enabled: "n/a",
|
|
2310
2402
|
method: "mcp",
|
|
2311
|
-
location: path14__default.relative(projectDir,
|
|
2403
|
+
location: path14__default.relative(projectDir, p8)
|
|
2312
2404
|
};
|
|
2313
2405
|
}
|
|
2314
2406
|
async function install3(projectDir) {
|
|
@@ -2525,7 +2617,7 @@ function printStatusTable(rows) {
|
|
|
2525
2617
|
const widths = cols.map(
|
|
2526
2618
|
(c) => Math.max(c.header.length, ...rows.map((r) => String(r[c.key] ?? "").length))
|
|
2527
2619
|
);
|
|
2528
|
-
const fmtRow = (parts) => parts.map((
|
|
2620
|
+
const fmtRow = (parts) => parts.map((p8, i) => p8.padEnd(widths[i] ?? p8.length)).join(" ");
|
|
2529
2621
|
console.log();
|
|
2530
2622
|
console.log(` ${S.heading(fmtRow(cols.map((c) => c.header)))}`);
|
|
2531
2623
|
for (const r of rows) {
|
|
@@ -2980,9 +3072,9 @@ function makeLibraryCommand() {
|
|
|
2980
3072
|
logErr("`library commit` only applies to git-backed libraries.");
|
|
2981
3073
|
process.exit(1);
|
|
2982
3074
|
}
|
|
2983
|
-
const { spawnSync
|
|
2984
|
-
|
|
2985
|
-
const r =
|
|
3075
|
+
const { spawnSync } = await import('child_process');
|
|
3076
|
+
spawnSync("git", ["add", "-A"], { cwd: lib.path, stdio: "inherit" });
|
|
3077
|
+
const r = spawnSync("git", ["commit", "-m", opts.message], {
|
|
2986
3078
|
cwd: lib.path,
|
|
2987
3079
|
stdio: "inherit"
|
|
2988
3080
|
});
|
|
@@ -3000,8 +3092,8 @@ function makeLibraryCommand() {
|
|
|
3000
3092
|
const { manager, close } = await openLibraryManager();
|
|
3001
3093
|
try {
|
|
3002
3094
|
const lib = await manager.requireLibrary(name);
|
|
3003
|
-
const { spawnSync
|
|
3004
|
-
const r =
|
|
3095
|
+
const { spawnSync } = await import('child_process');
|
|
3096
|
+
const r = spawnSync("git", args, { cwd: lib.path, stdio: "inherit" });
|
|
3005
3097
|
process.exit(r.status ?? 0);
|
|
3006
3098
|
} finally {
|
|
3007
3099
|
close();
|
|
@@ -3264,6 +3356,8 @@ var ORIGIN_META = {
|
|
|
3264
3356
|
var ORIGIN_ORDER = ["library", "source", "factory", "store"];
|
|
3265
3357
|
var srcKey = (origin, publisher) => `${origin}:${publisher}`;
|
|
3266
3358
|
var domainKey = (origin, publisher, slug) => `${origin}:${publisher}:dom:${slug}`;
|
|
3359
|
+
var repoKey = (org, repo) => `${org}/${repo}`;
|
|
3360
|
+
var srcDomainKey = (org, repo, slug) => `${org}/${repo}:dom:${slug}`;
|
|
3267
3361
|
var NO_DOMAIN = "";
|
|
3268
3362
|
var domainRegistry = /* @__PURE__ */ new Map();
|
|
3269
3363
|
function relationBadge(relation) {
|
|
@@ -3292,12 +3386,20 @@ var state = {
|
|
|
3292
3386
|
sourceRows: [],
|
|
3293
3387
|
libraryRows: [],
|
|
3294
3388
|
visibleRows: [],
|
|
3389
|
+
sourceTreeRows: [],
|
|
3390
|
+
visibleSourceRows: [],
|
|
3295
3391
|
pendingAdds: /* @__PURE__ */ new Set(),
|
|
3296
3392
|
pendingRemoves: /* @__PURE__ */ new Set(),
|
|
3297
3393
|
collapsedOrigins: /* @__PURE__ */ new Set(),
|
|
3298
3394
|
collapsedSources: /* @__PURE__ */ new Set(),
|
|
3299
3395
|
collapsedDomains: /* @__PURE__ */ new Set(),
|
|
3300
3396
|
expandedDomainInfo: /* @__PURE__ */ new Set(),
|
|
3397
|
+
seenDomains: /* @__PURE__ */ new Set(),
|
|
3398
|
+
collapsedSourceOrgs: /* @__PURE__ */ new Set(),
|
|
3399
|
+
collapsedSourceRepos: /* @__PURE__ */ new Set(),
|
|
3400
|
+
collapsedSourceDomains: /* @__PURE__ */ new Set(),
|
|
3401
|
+
expandedSourceDomainInfo: /* @__PURE__ */ new Set(),
|
|
3402
|
+
seenSourceDomains: /* @__PURE__ */ new Set(),
|
|
3301
3403
|
seenOrigins: /* @__PURE__ */ new Set(),
|
|
3302
3404
|
originFilter: null,
|
|
3303
3405
|
message: "",
|
|
@@ -3311,13 +3413,13 @@ function buildVisibleRows(rows, collapsedOrigins, collapsedSources, collapsedDom
|
|
|
3311
3413
|
if (row.type === "origin-header") return true;
|
|
3312
3414
|
if (collapsedOrigins.has(origin)) return false;
|
|
3313
3415
|
if (row.type === "publisher-header") return true;
|
|
3314
|
-
if (collapsedSources.has(srcKey(origin,
|
|
3416
|
+
if (collapsedSources.has(srcKey(origin, rowGroup(row)))) return false;
|
|
3315
3417
|
if (row.type === "domain-header") return true;
|
|
3316
3418
|
if (row.type === "domain-info") {
|
|
3317
3419
|
return !collapsedDomains.has(domainKey(origin, row.source, row.domainSlug ?? NO_DOMAIN));
|
|
3318
3420
|
}
|
|
3319
3421
|
if (row.underDomain) {
|
|
3320
|
-
return !collapsedDomains.has(domainKey(origin,
|
|
3422
|
+
return !collapsedDomains.has(domainKey(origin, rowGroup(row), rowDomain(row)));
|
|
3321
3423
|
}
|
|
3322
3424
|
return true;
|
|
3323
3425
|
});
|
|
@@ -3331,6 +3433,80 @@ function domainAssetRefs(rows, origin, publisher, slug) {
|
|
|
3331
3433
|
function sourceAssetRefs(rows, origin, source) {
|
|
3332
3434
|
return refsOf(rows.filter((r) => isAsset(r) && inSource(r, origin, source)));
|
|
3333
3435
|
}
|
|
3436
|
+
function buildSourceTreeRows(assetRows, registered = []) {
|
|
3437
|
+
const byOrg = /* @__PURE__ */ new Map();
|
|
3438
|
+
const ensure = (org, repo) => {
|
|
3439
|
+
if (!byOrg.has(org)) byOrg.set(org, /* @__PURE__ */ new Map());
|
|
3440
|
+
const byRepo = byOrg.get(org);
|
|
3441
|
+
if (!byRepo.has(repo)) byRepo.set(repo, /* @__PURE__ */ new Map());
|
|
3442
|
+
return byRepo.get(repo);
|
|
3443
|
+
};
|
|
3444
|
+
for (const r of assetRows) {
|
|
3445
|
+
if (!isAsset(r) || rowOrigin(r) !== "source") continue;
|
|
3446
|
+
const org = rowOrg(r);
|
|
3447
|
+
const repo = rowGroup(r);
|
|
3448
|
+
const slug = rowDomain(r);
|
|
3449
|
+
const byDomain = ensure(org, repo);
|
|
3450
|
+
if (!byDomain.has(slug)) byDomain.set(slug, []);
|
|
3451
|
+
byDomain.get(slug).push(r);
|
|
3452
|
+
}
|
|
3453
|
+
for (const { org, repo } of registered) ensure(org, repo);
|
|
3454
|
+
if (byOrg.size === 0) return [];
|
|
3455
|
+
const rows = [{ type: "source-root" }];
|
|
3456
|
+
for (const org of [...byOrg.keys()].sort((a, b) => a.localeCompare(b))) {
|
|
3457
|
+
rows.push({ type: "org-header", origin: "source", org });
|
|
3458
|
+
const byRepo = byOrg.get(org);
|
|
3459
|
+
for (const repo of [...byRepo.keys()].sort((a, b) => a.localeCompare(b))) {
|
|
3460
|
+
rows.push({ type: "repo-header", origin: "source", org, source: repo });
|
|
3461
|
+
const byDomain = byRepo.get(repo);
|
|
3462
|
+
const loose = byDomain.get(NO_DOMAIN);
|
|
3463
|
+
if (loose) for (const a of loose) rows.push({ ...a, org });
|
|
3464
|
+
for (const slug of sortedDomainSlugs([...byDomain.keys()])) {
|
|
3465
|
+
const meta = domainRegistry.get(slug);
|
|
3466
|
+
rows.push({ type: "domain-header", origin: "source", org, source: repo, domainSlug: slug });
|
|
3467
|
+
if (meta?.description) {
|
|
3468
|
+
rows.push({ type: "domain-info", origin: "source", org, source: repo, domainSlug: slug });
|
|
3469
|
+
}
|
|
3470
|
+
for (const a of byDomain.get(slug)) rows.push({ ...a, org });
|
|
3471
|
+
}
|
|
3472
|
+
}
|
|
3473
|
+
}
|
|
3474
|
+
return rows;
|
|
3475
|
+
}
|
|
3476
|
+
function buildVisibleSourceRows(rows, collapsedOrgs, collapsedRepos, collapsedDomains) {
|
|
3477
|
+
return rows.filter((row) => {
|
|
3478
|
+
if (row.type === "source-root" || row.type === "org-header") return true;
|
|
3479
|
+
const org = row.org ?? UNKNOWN_ORG;
|
|
3480
|
+
if (collapsedOrgs.has(org)) return false;
|
|
3481
|
+
if (row.type === "repo-header") return true;
|
|
3482
|
+
if (collapsedRepos.has(repoKey(org, row.source))) return false;
|
|
3483
|
+
if (row.type === "domain-header") return true;
|
|
3484
|
+
if (row.type === "domain-info") {
|
|
3485
|
+
return !collapsedDomains.has(srcDomainKey(org, row.source, row.domainSlug ?? NO_DOMAIN));
|
|
3486
|
+
}
|
|
3487
|
+
if (row.underDomain) {
|
|
3488
|
+
return !collapsedDomains.has(srcDomainKey(org, rowGroup(row), rowDomain(row)));
|
|
3489
|
+
}
|
|
3490
|
+
return true;
|
|
3491
|
+
});
|
|
3492
|
+
}
|
|
3493
|
+
function sourceOrgRefs(rows, org) {
|
|
3494
|
+
return refsOf(rows.filter((r) => isAsset(r) && rowOrigin(r) === "source" && rowOrg(r) === org));
|
|
3495
|
+
}
|
|
3496
|
+
function sourceRepoRefs(rows, org, repo) {
|
|
3497
|
+
return refsOf(
|
|
3498
|
+
rows.filter(
|
|
3499
|
+
(r) => isAsset(r) && rowOrigin(r) === "source" && rowOrg(r) === org && rowGroup(r) === repo
|
|
3500
|
+
)
|
|
3501
|
+
);
|
|
3502
|
+
}
|
|
3503
|
+
function sourceDomainRefs(rows, org, repo, slug) {
|
|
3504
|
+
return refsOf(
|
|
3505
|
+
rows.filter(
|
|
3506
|
+
(r) => isAsset(r) && rowOrigin(r) === "source" && rowOrg(r) === org && rowGroup(r) === repo && rowDomain(r) === slug
|
|
3507
|
+
)
|
|
3508
|
+
);
|
|
3509
|
+
}
|
|
3334
3510
|
function isAsset(r) {
|
|
3335
3511
|
return r.type === "asset";
|
|
3336
3512
|
}
|
|
@@ -3340,14 +3516,24 @@ function rowOrigin(r) {
|
|
|
3340
3516
|
function rowPublisher(r) {
|
|
3341
3517
|
return r.entry?.publisher || "other";
|
|
3342
3518
|
}
|
|
3519
|
+
function rowGroup(r) {
|
|
3520
|
+
return r.source ?? rowPublisher(r);
|
|
3521
|
+
}
|
|
3343
3522
|
function rowDomain(r) {
|
|
3344
3523
|
return r.entry?.domainSlug || NO_DOMAIN;
|
|
3345
3524
|
}
|
|
3525
|
+
var UNKNOWN_ORG = "(unknown)";
|
|
3526
|
+
function rowOrg(r) {
|
|
3527
|
+
if (r.org) return r.org;
|
|
3528
|
+
const repo = r.entry?.repo;
|
|
3529
|
+
if (repo?.includes("/")) return repo.slice(0, repo.indexOf("/"));
|
|
3530
|
+
return UNKNOWN_ORG;
|
|
3531
|
+
}
|
|
3346
3532
|
function refsOf(rows) {
|
|
3347
3533
|
return rows.map((r) => assetRefOf(r)).filter((ref) => ref !== null);
|
|
3348
3534
|
}
|
|
3349
3535
|
function inSource(r, origin, source) {
|
|
3350
|
-
return rowOrigin(r) === origin &&
|
|
3536
|
+
return rowOrigin(r) === origin && rowGroup(r) === source;
|
|
3351
3537
|
}
|
|
3352
3538
|
function inDomain(r, origin, publisher, slug) {
|
|
3353
3539
|
if (!inSource(r, origin, publisher)) return false;
|
|
@@ -3408,7 +3594,7 @@ function actOnHeader(row, action3) {
|
|
|
3408
3594
|
return row.type === "domain-header" || row.type === "domain-info";
|
|
3409
3595
|
}
|
|
3410
3596
|
async function loadAssets() {
|
|
3411
|
-
const { gatherAssetFeeds } = await import('../asset-feeds-
|
|
3597
|
+
const { gatherAssetFeeds } = await import('../asset-feeds-OEGJ6NOF.js');
|
|
3412
3598
|
const { entries, domains, notes } = await gatherAssetFeeds(am, am.projectDir);
|
|
3413
3599
|
if (notes.length > 0) {
|
|
3414
3600
|
state.message = notes.map((n) => `[${n.feed}] ${n.message}`).join(" \u2022 ");
|
|
@@ -3420,11 +3606,60 @@ async function loadAssets() {
|
|
|
3420
3606
|
state.assetRows = rows;
|
|
3421
3607
|
reconcileCollapsedSets(rows);
|
|
3422
3608
|
rebuildVisible();
|
|
3609
|
+
rebuildSourceTree();
|
|
3610
|
+
}
|
|
3611
|
+
function rebuildSourceTree() {
|
|
3612
|
+
const registered = state.sourceRows.map((s) => sourceOrgRepo(s)).filter((x) => x !== null);
|
|
3613
|
+
state.sourceTreeRows = buildSourceTreeRows(state.assetRows, registered);
|
|
3614
|
+
reconcileSourceCollapsedSets(state.sourceTreeRows);
|
|
3615
|
+
rebuildVisibleSources();
|
|
3616
|
+
}
|
|
3617
|
+
function sourceOrgRepo(s) {
|
|
3618
|
+
const parts = s.path.split(path14__default.sep).filter(Boolean);
|
|
3619
|
+
if (parts.length < 2) return null;
|
|
3620
|
+
return { org: parts[parts.length - 2], repo: parts[parts.length - 1] };
|
|
3621
|
+
}
|
|
3622
|
+
function reconcileSourceCollapsedSets(rows) {
|
|
3623
|
+
const orgKeys = new Set(rows.filter((r) => r.type === "org-header").map((r) => r.org));
|
|
3624
|
+
const repoKeys = new Set(
|
|
3625
|
+
rows.filter((r) => r.type === "repo-header").map((r) => repoKey(r.org, r.source))
|
|
3626
|
+
);
|
|
3627
|
+
const domainKeys = new Set(
|
|
3628
|
+
rows.filter((r) => r.type === "domain-header").map((r) => srcDomainKey(r.org, r.source, r.domainSlug ?? NO_DOMAIN))
|
|
3629
|
+
);
|
|
3630
|
+
for (const k of state.collapsedSourceOrgs)
|
|
3631
|
+
if (!orgKeys.has(k)) state.collapsedSourceOrgs.delete(k);
|
|
3632
|
+
for (const k of state.collapsedSourceRepos) {
|
|
3633
|
+
if (!repoKeys.has(k)) state.collapsedSourceRepos.delete(k);
|
|
3634
|
+
}
|
|
3635
|
+
for (const k of domainKeys) {
|
|
3636
|
+
if (!state.seenSourceDomains.has(k)) {
|
|
3637
|
+
state.collapsedSourceDomains.add(k);
|
|
3638
|
+
state.seenSourceDomains.add(k);
|
|
3639
|
+
}
|
|
3640
|
+
}
|
|
3641
|
+
for (const k of state.collapsedSourceDomains) {
|
|
3642
|
+
if (!domainKeys.has(k)) state.collapsedSourceDomains.delete(k);
|
|
3643
|
+
}
|
|
3644
|
+
for (const k of state.expandedSourceDomainInfo) {
|
|
3645
|
+
if (!domainKeys.has(k)) state.expandedSourceDomainInfo.delete(k);
|
|
3646
|
+
}
|
|
3647
|
+
for (const k of state.seenSourceDomains)
|
|
3648
|
+
if (!domainKeys.has(k)) state.seenSourceDomains.delete(k);
|
|
3649
|
+
}
|
|
3650
|
+
function rebuildVisibleSources() {
|
|
3651
|
+
state.visibleSourceRows = buildVisibleSourceRows(
|
|
3652
|
+
state.sourceTreeRows,
|
|
3653
|
+
state.collapsedSourceOrgs,
|
|
3654
|
+
state.collapsedSourceRepos,
|
|
3655
|
+
state.collapsedSourceDomains
|
|
3656
|
+
);
|
|
3657
|
+
clampCursor();
|
|
3423
3658
|
}
|
|
3424
3659
|
function groupEntriesByOriginPublisherDomain(entries) {
|
|
3425
3660
|
const byOrigin = /* @__PURE__ */ new Map();
|
|
3426
|
-
for (const { origin, entry } of entries) {
|
|
3427
|
-
const publisher = entry.publisher || "other";
|
|
3661
|
+
for (const { origin, entry, group } of entries) {
|
|
3662
|
+
const publisher = group || entry.publisher || "other";
|
|
3428
3663
|
const slug = entry.domainSlug || NO_DOMAIN;
|
|
3429
3664
|
if (!byOrigin.has(origin)) byOrigin.set(origin, /* @__PURE__ */ new Map());
|
|
3430
3665
|
const byPublisher = byOrigin.get(origin);
|
|
@@ -3447,29 +3682,40 @@ function buildAssetRowsFromGroups(byOrigin, installed) {
|
|
|
3447
3682
|
const sortItems = (items) => items.sort(
|
|
3448
3683
|
(a, b) => a.kind !== b.kind ? a.kind.localeCompare(b.kind) : a.name.localeCompare(b.name)
|
|
3449
3684
|
);
|
|
3450
|
-
const pushAsset = (origin, entry, underDomain, seq) => {
|
|
3685
|
+
const pushAsset = (origin, group, entry, underDomain, seq) => {
|
|
3451
3686
|
const ref = `${entry.kind}:${entry.name}`;
|
|
3452
|
-
rows.push({
|
|
3687
|
+
rows.push({
|
|
3688
|
+
type: "asset",
|
|
3689
|
+
origin,
|
|
3690
|
+
source: group,
|
|
3691
|
+
org: entry.repo?.includes("/") ? entry.repo.slice(0, entry.repo.indexOf("/")) : void 0,
|
|
3692
|
+
entry,
|
|
3693
|
+
installed: installed.has(ref),
|
|
3694
|
+
underDomain,
|
|
3695
|
+
seq
|
|
3696
|
+
});
|
|
3453
3697
|
};
|
|
3454
3698
|
for (const origin of ORIGIN_ORDER) {
|
|
3455
|
-
const
|
|
3456
|
-
if (!
|
|
3699
|
+
const byGroup = byOrigin.get(origin);
|
|
3700
|
+
if (!byGroup || byGroup.size === 0) continue;
|
|
3457
3701
|
rows.push({ type: "origin-header", origin });
|
|
3458
|
-
for (const [
|
|
3702
|
+
for (const [group, byDomain] of [...byGroup.entries()].sort(
|
|
3459
3703
|
(a, b) => a[0].localeCompare(b[0])
|
|
3460
3704
|
)) {
|
|
3461
|
-
rows.push({ type: "publisher-header", origin, source:
|
|
3705
|
+
rows.push({ type: "publisher-header", origin, source: group });
|
|
3462
3706
|
const loose = byDomain.get(NO_DOMAIN);
|
|
3463
|
-
if (loose) for (const entry of sortItems(loose)) pushAsset(origin, entry, false);
|
|
3707
|
+
if (loose) for (const entry of sortItems(loose)) pushAsset(origin, group, entry, false);
|
|
3464
3708
|
for (const slug of sortedDomainSlugs([...byDomain.keys()])) {
|
|
3465
3709
|
const meta = domainRegistry.get(slug);
|
|
3466
|
-
rows.push({ type: "domain-header", origin, source:
|
|
3710
|
+
rows.push({ type: "domain-header", origin, source: group, domainSlug: slug });
|
|
3467
3711
|
if (meta?.description) {
|
|
3468
|
-
rows.push({ type: "domain-info", origin, source:
|
|
3712
|
+
rows.push({ type: "domain-info", origin, source: group, domainSlug: slug });
|
|
3469
3713
|
}
|
|
3470
3714
|
const items = sortItems(byDomain.get(slug));
|
|
3471
3715
|
const sequenced = meta?.relation === "sequence";
|
|
3472
|
-
items.forEach(
|
|
3716
|
+
items.forEach(
|
|
3717
|
+
(entry, i) => pushAsset(origin, group, entry, true, sequenced ? i + 1 : void 0)
|
|
3718
|
+
);
|
|
3473
3719
|
}
|
|
3474
3720
|
}
|
|
3475
3721
|
}
|
|
@@ -3496,17 +3742,26 @@ function reconcileCollapsedSets(rows) {
|
|
|
3496
3742
|
const newDomainKeys = new Set(
|
|
3497
3743
|
rows.filter((r) => r.type === "domain-header").map((r) => domainKey(rowOrigin(r), r.source, r.domainSlug ?? NO_DOMAIN))
|
|
3498
3744
|
);
|
|
3745
|
+
for (const k of newDomainKeys) {
|
|
3746
|
+
if (!state.seenDomains.has(k)) {
|
|
3747
|
+
state.collapsedDomains.add(k);
|
|
3748
|
+
state.seenDomains.add(k);
|
|
3749
|
+
}
|
|
3750
|
+
}
|
|
3499
3751
|
for (const d of state.collapsedDomains) {
|
|
3500
3752
|
if (!newDomainKeys.has(d)) state.collapsedDomains.delete(d);
|
|
3501
3753
|
}
|
|
3502
3754
|
for (const d of state.expandedDomainInfo) {
|
|
3503
3755
|
if (!newDomainKeys.has(d)) state.expandedDomainInfo.delete(d);
|
|
3504
3756
|
}
|
|
3757
|
+
for (const d of state.seenDomains) {
|
|
3758
|
+
if (!newDomainKeys.has(d)) state.seenDomains.delete(d);
|
|
3759
|
+
}
|
|
3505
3760
|
}
|
|
3506
3761
|
async function loadSourcesAndLibraries() {
|
|
3507
3762
|
try {
|
|
3508
3763
|
const [{ openLibraryManager: openLibraryManager2 }, { skaileHomeDir }, { getGlobalCacheDir: getGlobalCacheDir2 }] = await Promise.all([
|
|
3509
|
-
import('../open-library-
|
|
3764
|
+
import('../open-library-ERKRGH4B.js'),
|
|
3510
3765
|
import('../library/index.js'),
|
|
3511
3766
|
import('../core/index.js')
|
|
3512
3767
|
]);
|
|
@@ -3542,6 +3797,7 @@ async function loadSourcesAndLibraries() {
|
|
|
3542
3797
|
state.sourceRows = [];
|
|
3543
3798
|
state.libraryRows = [];
|
|
3544
3799
|
}
|
|
3800
|
+
rebuildSourceTree();
|
|
3545
3801
|
}
|
|
3546
3802
|
function rebuildVisible() {
|
|
3547
3803
|
state.visibleRows = buildVisibleRows(
|
|
@@ -3577,11 +3833,11 @@ var TABS = {
|
|
|
3577
3833
|
},
|
|
3578
3834
|
sources: {
|
|
3579
3835
|
label: "Sources",
|
|
3580
|
-
rowCount: () => state.
|
|
3581
|
-
selectableCount: () => state.
|
|
3836
|
+
rowCount: () => state.visibleSourceRows.length,
|
|
3837
|
+
selectableCount: () => state.sourceTreeRows.filter(isAsset).length,
|
|
3582
3838
|
emptyMsg: " No sources registered. Run `skaile source add <git-url>` from the shell to track a github repo.",
|
|
3583
|
-
renderRow: (i, sel) =>
|
|
3584
|
-
footer: " \u2191\u2193
|
|
3839
|
+
renderRow: (i, sel) => renderSourceTreeRow(state.visibleSourceRows[i], sel),
|
|
3840
|
+
footer: " \u2191\u2193/jk nav \u2190/\u2192 collapse/expand [space/+/-] select [a/\u21B5] apply [d] domain info [i] info Tab [q] quit"
|
|
3585
3841
|
},
|
|
3586
3842
|
libraries: {
|
|
3587
3843
|
label: "Libraries",
|
|
@@ -3645,8 +3901,9 @@ function groupStatus(refs) {
|
|
|
3645
3901
|
}
|
|
3646
3902
|
function renderHeaderLine(opts) {
|
|
3647
3903
|
const indicator = opts.collapsed ? "\u25B6" : "\u25BC";
|
|
3648
|
-
const
|
|
3649
|
-
const
|
|
3904
|
+
const countRows = opts.rows ?? state.assetRows;
|
|
3905
|
+
const total = countRows.filter(opts.match).length;
|
|
3906
|
+
const installed = countRows.filter((r) => opts.match(r) && r.installed).length;
|
|
3650
3907
|
const [add, remove] = pendingCountsFor(opts.match);
|
|
3651
3908
|
let count = String(installed);
|
|
3652
3909
|
if (add > 0) count += pc5.green(`+${add}`);
|
|
@@ -3685,8 +3942,8 @@ function renderAssetRow(row, selected) {
|
|
|
3685
3942
|
const slug = row.domainSlug ?? NO_DOMAIN;
|
|
3686
3943
|
const meta = domainRegistry.get(slug);
|
|
3687
3944
|
const title = meta?.title || slug || "(no domain)";
|
|
3688
|
-
const
|
|
3689
|
-
const label = `${pc5.magenta("\u25C8")} ${pc5.bold(title)}${
|
|
3945
|
+
const badge = relationBadge(meta?.relation);
|
|
3946
|
+
const label = `${pc5.magenta("\u25C8")} ${pc5.bold(title)}${badge ? ` ${badge}` : ""}`;
|
|
3690
3947
|
return renderHeaderLine({
|
|
3691
3948
|
indent: " ".repeat(5),
|
|
3692
3949
|
collapsed: state.collapsedDomains.has(domainKey(origin, row.source, slug)),
|
|
@@ -3700,15 +3957,18 @@ function renderAssetRow(row, selected) {
|
|
|
3700
3957
|
const origin = rowOrigin(row);
|
|
3701
3958
|
const slug = row.domainSlug ?? NO_DOMAIN;
|
|
3702
3959
|
const key = domainKey(origin, row.source, slug);
|
|
3703
|
-
const
|
|
3960
|
+
const line = renderDomainInfoLine(
|
|
3704
3961
|
domainRegistry.get(slug),
|
|
3705
3962
|
origin,
|
|
3706
3963
|
row.source,
|
|
3707
3964
|
slug,
|
|
3708
3965
|
state.expandedDomainInfo.has(key)
|
|
3709
3966
|
);
|
|
3710
|
-
return selected ? pc5.inverse(
|
|
3967
|
+
return selected ? pc5.inverse(line.padEnd(state.cols)) : line;
|
|
3711
3968
|
}
|
|
3969
|
+
return renderAssetLeaf(row, selected);
|
|
3970
|
+
}
|
|
3971
|
+
function renderAssetLeaf(row, selected, looseIndent = 5) {
|
|
3712
3972
|
const e = row.entry;
|
|
3713
3973
|
const ref = assetRefOf(row) ?? "";
|
|
3714
3974
|
let status4;
|
|
@@ -3730,10 +3990,86 @@ function renderAssetRow(row, selected) {
|
|
|
3730
3990
|
const repoBadge = repoBare ? pc5.dim(` \xB7${repoBare}`) : "";
|
|
3731
3991
|
const repoWidth = repoBare ? repoBare.length + 2 : 0;
|
|
3732
3992
|
const desc = e.description?.slice(0, Math.max(0, state.cols - 56 - badgeWidth - hintWidth - repoWidth)) ?? "";
|
|
3733
|
-
const indent = " ".repeat(row.underDomain ?
|
|
3993
|
+
const indent = " ".repeat(looseIndent + (row.underDomain ? 2 : 0));
|
|
3734
3994
|
const line = `${indent}${status4} ${hint}${kind} ${name} ${badge}${pc5.dim(desc)}${repoBadge}`;
|
|
3735
3995
|
return selected ? pc5.inverse(line.padEnd(state.cols)) : line;
|
|
3736
3996
|
}
|
|
3997
|
+
function renderSourceTreeRow(row, selected) {
|
|
3998
|
+
if (row.type === "source-root") {
|
|
3999
|
+
const total = state.sourceTreeRows.filter(isAsset).length;
|
|
4000
|
+
const meta = ORIGIN_META.source;
|
|
4001
|
+
const line = ` \u25BC ${meta.icon} ${pc5.bold(pc5.cyan(meta.label))} (${total} assets)`;
|
|
4002
|
+
return selected ? pc5.bgWhite(pc5.black(`${line} `.padEnd(state.cols))) : line;
|
|
4003
|
+
}
|
|
4004
|
+
if (row.type === "org-header") {
|
|
4005
|
+
const org = row.org;
|
|
4006
|
+
return renderHeaderLine({
|
|
4007
|
+
indent: " ".repeat(3),
|
|
4008
|
+
collapsed: state.collapsedSourceOrgs.has(org),
|
|
4009
|
+
match: (r) => isAsset(r) && rowOrigin(r) === "source" && rowOrg(r) === org,
|
|
4010
|
+
refs: sourceOrgRefs(state.sourceTreeRows, org),
|
|
4011
|
+
label: pc5.bold(pc5.cyan(org)),
|
|
4012
|
+
selected,
|
|
4013
|
+
rows: state.sourceTreeRows
|
|
4014
|
+
});
|
|
4015
|
+
}
|
|
4016
|
+
if (row.type === "repo-header") {
|
|
4017
|
+
const org = row.org;
|
|
4018
|
+
const repo = row.source;
|
|
4019
|
+
return renderHeaderLine({
|
|
4020
|
+
indent: " ".repeat(5),
|
|
4021
|
+
collapsed: state.collapsedSourceRepos.has(repoKey(org, repo)),
|
|
4022
|
+
match: (r) => isAsset(r) && rowOrigin(r) === "source" && rowOrg(r) === org && rowGroup(r) === repo,
|
|
4023
|
+
refs: sourceRepoRefs(state.sourceTreeRows, org, repo),
|
|
4024
|
+
label: pc5.bold(repo),
|
|
4025
|
+
selected,
|
|
4026
|
+
rows: state.sourceTreeRows
|
|
4027
|
+
});
|
|
4028
|
+
}
|
|
4029
|
+
if (row.type === "domain-header") {
|
|
4030
|
+
const org = row.org;
|
|
4031
|
+
const repo = row.source;
|
|
4032
|
+
const slug = row.domainSlug ?? NO_DOMAIN;
|
|
4033
|
+
const meta = domainRegistry.get(slug);
|
|
4034
|
+
const title = meta?.title || slug || "(no domain)";
|
|
4035
|
+
const badge = relationBadge(meta?.relation);
|
|
4036
|
+
const label = `${pc5.magenta("\u25C8")} ${pc5.bold(title)}${badge ? ` ${badge}` : ""}`;
|
|
4037
|
+
return renderHeaderLine({
|
|
4038
|
+
indent: " ".repeat(7),
|
|
4039
|
+
collapsed: state.collapsedSourceDomains.has(srcDomainKey(org, repo, slug)),
|
|
4040
|
+
match: (r) => isAsset(r) && rowOrigin(r) === "source" && rowOrg(r) === org && rowGroup(r) === repo && rowDomain(r) === slug,
|
|
4041
|
+
refs: sourceDomainRefs(state.sourceTreeRows, org, repo, slug),
|
|
4042
|
+
label,
|
|
4043
|
+
selected,
|
|
4044
|
+
rows: state.sourceTreeRows
|
|
4045
|
+
});
|
|
4046
|
+
}
|
|
4047
|
+
if (row.type === "domain-info") {
|
|
4048
|
+
const slug = row.domainSlug ?? NO_DOMAIN;
|
|
4049
|
+
const meta = domainRegistry.get(slug);
|
|
4050
|
+
const members = sourceDomainRefs(state.sourceTreeRows, row.org, row.source, slug).length;
|
|
4051
|
+
const key = srcDomainKey(row.org, row.source, slug);
|
|
4052
|
+
const line = renderSourceDomainInfoLine(meta, members, state.expandedSourceDomainInfo.has(key));
|
|
4053
|
+
return selected ? pc5.inverse(line.padEnd(state.cols)) : line;
|
|
4054
|
+
}
|
|
4055
|
+
return renderAssetLeaf(row, selected, 7);
|
|
4056
|
+
}
|
|
4057
|
+
function renderSourceDomainInfoLine(meta, members, expanded) {
|
|
4058
|
+
const indent = " ".repeat(9);
|
|
4059
|
+
const desc = meta?.description ?? "";
|
|
4060
|
+
if (!expanded) {
|
|
4061
|
+
const budget2 = Math.max(0, state.cols - indent.length - 12);
|
|
4062
|
+
const shown2 = desc.length > budget2 ? `${desc.slice(0, Math.max(0, budget2 - 1))}\u2026` : desc;
|
|
4063
|
+
return pc5.dim(`${indent}\u24D8 ${shown2} [d]`);
|
|
4064
|
+
}
|
|
4065
|
+
const parts = [desc, `${members} members`];
|
|
4066
|
+
if (meta?.recommendedRef) parts.push(`\u2605 ${meta.recommendedRef}`);
|
|
4067
|
+
if (meta?.sidecarSource) parts.push(`sidecar ${meta.sidecarSource}`);
|
|
4068
|
+
const full = parts.join(" \xB7 ");
|
|
4069
|
+
const budget = Math.max(0, state.cols - indent.length - 3);
|
|
4070
|
+
const shown = full.length > budget ? `${full.slice(0, Math.max(0, budget - 1))}\u2026` : full;
|
|
4071
|
+
return pc5.dim(`${indent}\u24D8 ${shown}`);
|
|
4072
|
+
}
|
|
3737
4073
|
function renderDomainInfoLine(meta, origin, publisher, slug, expanded) {
|
|
3738
4074
|
const indent = " ".repeat(7);
|
|
3739
4075
|
const desc = meta?.description ?? "";
|
|
@@ -3751,10 +4087,6 @@ function renderDomainInfoLine(meta, origin, publisher, slug, expanded) {
|
|
|
3751
4087
|
const shown = full.length > budget ? `${full.slice(0, Math.max(0, budget - 1))}\u2026` : full;
|
|
3752
4088
|
return pc5.dim(`${indent}\u24D8 ${shown}`);
|
|
3753
4089
|
}
|
|
3754
|
-
function renderSourceRow(row, selected) {
|
|
3755
|
-
const line = ` ${S.cmd(fitWidth(row.name, 20))} ${pc5.dim(row.ownership.padEnd(12))} ${pc5.dim(`${row.assetCount} assets`)} ${pc5.dim(row.path)}`;
|
|
3756
|
-
return selected ? pc5.inverse(line.padEnd(state.cols)) : line;
|
|
3757
|
-
}
|
|
3758
4090
|
function renderLibraryRow(row, selected) {
|
|
3759
4091
|
const mark = row.isDefault ? pc5.green("\u25B8") : " ";
|
|
3760
4092
|
const line = `${mark} ${S.cmd(fitWidth(row.name, 16))} ${pc5.dim(row.backend.padEnd(7))} ${pc5.dim(row.ownership.padEnd(12))} ${pc5.dim(`${row.assetCount} assets`)}`;
|
|
@@ -3858,19 +4190,15 @@ async function syncAll() {
|
|
|
3858
4190
|
"Sync is not yet driven from the manage TUI. Run `skaile source sync` (sources) or `skaile library sync <name>` (git-backed libraries) from the shell."
|
|
3859
4191
|
);
|
|
3860
4192
|
}
|
|
3861
|
-
function sourceShellHint(action3) {
|
|
3862
|
-
state.message = pc5.yellow(
|
|
3863
|
-
`${action3} is a shell command. Run \`skaile source \u2026\` from the shell.`
|
|
3864
|
-
);
|
|
3865
|
-
}
|
|
3866
4193
|
function libraryShellHint(action3) {
|
|
3867
4194
|
state.message = pc5.yellow(
|
|
3868
4195
|
`${action3} is a shell command. Run \`skaile library \u2026\` from the shell.`
|
|
3869
4196
|
);
|
|
3870
4197
|
}
|
|
3871
4198
|
async function showInfo() {
|
|
3872
|
-
|
|
3873
|
-
|
|
4199
|
+
const rows = state.tab === "sources" ? state.visibleSourceRows : state.visibleRows;
|
|
4200
|
+
if (state.tab !== "assets" && state.tab !== "sources") return;
|
|
4201
|
+
const row = rows[state.cursor];
|
|
3874
4202
|
if (row?.type !== "asset") return;
|
|
3875
4203
|
const e = row.entry;
|
|
3876
4204
|
clearScreen();
|
|
@@ -3998,6 +4326,115 @@ function toggleDomainInfoUnderCursor() {
|
|
|
3998
4326
|
else state.expandedDomainInfo.add(key);
|
|
3999
4327
|
rebuildVisible();
|
|
4000
4328
|
}
|
|
4329
|
+
function actOnSourceHeader(row, action3) {
|
|
4330
|
+
if (row.type === "org-header") {
|
|
4331
|
+
bulkSelection(sourceOrgRefs(state.sourceTreeRows, row.org), action3);
|
|
4332
|
+
return true;
|
|
4333
|
+
}
|
|
4334
|
+
if (row.type === "repo-header") {
|
|
4335
|
+
bulkSelection(sourceRepoRefs(state.sourceTreeRows, row.org, row.source), action3);
|
|
4336
|
+
return true;
|
|
4337
|
+
}
|
|
4338
|
+
return row.type === "source-root" || row.type === "domain-header" || row.type === "domain-info";
|
|
4339
|
+
}
|
|
4340
|
+
function selectSourceUnderCursor(action3) {
|
|
4341
|
+
const row = state.visibleSourceRows[state.cursor];
|
|
4342
|
+
if (!row) return;
|
|
4343
|
+
if (actOnSourceHeader(row, action3 === "toggle" ? "toggle" : action3)) return;
|
|
4344
|
+
const ref = assetRefOf(row);
|
|
4345
|
+
if (!ref) return;
|
|
4346
|
+
if (action3 === "toggle") {
|
|
4347
|
+
setSelection(ref, "toggle");
|
|
4348
|
+
} else if (action3 === "add") {
|
|
4349
|
+
setSelection(ref, state.pendingAdds.has(ref) ? "clear" : "add");
|
|
4350
|
+
} else {
|
|
4351
|
+
setSelection(ref, state.pendingRemoves.has(ref) ? "clear" : "remove");
|
|
4352
|
+
}
|
|
4353
|
+
}
|
|
4354
|
+
function expandSourceUnderCursor() {
|
|
4355
|
+
const row = state.visibleSourceRows[state.cursor];
|
|
4356
|
+
if (!row) return;
|
|
4357
|
+
if (row.type === "org-header" && state.collapsedSourceOrgs.has(row.org)) {
|
|
4358
|
+
state.collapsedSourceOrgs.delete(row.org);
|
|
4359
|
+
rebuildVisibleSources();
|
|
4360
|
+
} else if (row.type === "repo-header") {
|
|
4361
|
+
const k = repoKey(row.org, row.source);
|
|
4362
|
+
if (state.collapsedSourceRepos.has(k)) {
|
|
4363
|
+
state.collapsedSourceRepos.delete(k);
|
|
4364
|
+
rebuildVisibleSources();
|
|
4365
|
+
}
|
|
4366
|
+
} else if (row.type === "domain-header") {
|
|
4367
|
+
const k = srcDomainKey(row.org, row.source, row.domainSlug ?? NO_DOMAIN);
|
|
4368
|
+
if (state.collapsedSourceDomains.has(k)) {
|
|
4369
|
+
state.collapsedSourceDomains.delete(k);
|
|
4370
|
+
rebuildVisibleSources();
|
|
4371
|
+
}
|
|
4372
|
+
}
|
|
4373
|
+
}
|
|
4374
|
+
function collapseOrJumpSourceUnderCursor() {
|
|
4375
|
+
const row = state.visibleSourceRows[state.cursor];
|
|
4376
|
+
if (!row) return;
|
|
4377
|
+
if (row.type === "org-header") {
|
|
4378
|
+
if (!state.collapsedSourceOrgs.has(row.org)) {
|
|
4379
|
+
state.collapsedSourceOrgs.add(row.org);
|
|
4380
|
+
rebuildVisibleSources();
|
|
4381
|
+
}
|
|
4382
|
+
return;
|
|
4383
|
+
}
|
|
4384
|
+
if (row.type === "repo-header") {
|
|
4385
|
+
const k = repoKey(row.org, row.source);
|
|
4386
|
+
if (!state.collapsedSourceRepos.has(k)) {
|
|
4387
|
+
state.collapsedSourceRepos.add(k);
|
|
4388
|
+
rebuildVisibleSources();
|
|
4389
|
+
} else {
|
|
4390
|
+
const idx2 = findLastIndex(
|
|
4391
|
+
state.visibleSourceRows,
|
|
4392
|
+
state.cursor,
|
|
4393
|
+
(r) => r.type === "org-header"
|
|
4394
|
+
);
|
|
4395
|
+
if (idx2 >= 0) state.cursor = idx2;
|
|
4396
|
+
}
|
|
4397
|
+
return;
|
|
4398
|
+
}
|
|
4399
|
+
if (row.type === "domain-header") {
|
|
4400
|
+
const k = srcDomainKey(row.org, row.source, row.domainSlug ?? NO_DOMAIN);
|
|
4401
|
+
if (!state.collapsedSourceDomains.has(k)) {
|
|
4402
|
+
state.collapsedSourceDomains.add(k);
|
|
4403
|
+
rebuildVisibleSources();
|
|
4404
|
+
} else {
|
|
4405
|
+
const idx2 = findLastIndex(
|
|
4406
|
+
state.visibleSourceRows,
|
|
4407
|
+
state.cursor,
|
|
4408
|
+
(r) => r.type === "repo-header"
|
|
4409
|
+
);
|
|
4410
|
+
if (idx2 >= 0) state.cursor = idx2;
|
|
4411
|
+
}
|
|
4412
|
+
return;
|
|
4413
|
+
}
|
|
4414
|
+
const idx = findLastIndex(
|
|
4415
|
+
state.visibleSourceRows,
|
|
4416
|
+
state.cursor,
|
|
4417
|
+
(r) => r.type === "domain-header" || r.type === "repo-header" || r.type === "org-header"
|
|
4418
|
+
);
|
|
4419
|
+
if (idx >= 0) state.cursor = idx;
|
|
4420
|
+
}
|
|
4421
|
+
function toggleSourceDomainInfoUnderCursor() {
|
|
4422
|
+
const row = state.visibleSourceRows[state.cursor];
|
|
4423
|
+
if (!row) return;
|
|
4424
|
+
let key = null;
|
|
4425
|
+
if (row.type === "domain-header" || row.type === "domain-info") {
|
|
4426
|
+
key = srcDomainKey(row.org, row.source, row.domainSlug ?? NO_DOMAIN);
|
|
4427
|
+
} else if (row.type === "asset" && row.underDomain) {
|
|
4428
|
+
key = srcDomainKey(rowOrg(row), rowGroup(row), rowDomain(row));
|
|
4429
|
+
}
|
|
4430
|
+
if (!key) {
|
|
4431
|
+
state.message = pc5.dim("No domain here \u2014 [d] opens a domain's info region.");
|
|
4432
|
+
return;
|
|
4433
|
+
}
|
|
4434
|
+
if (state.expandedSourceDomainInfo.has(key)) state.expandedSourceDomainInfo.delete(key);
|
|
4435
|
+
else state.expandedSourceDomainInfo.add(key);
|
|
4436
|
+
rebuildVisibleSources();
|
|
4437
|
+
}
|
|
4001
4438
|
function findLastIndex(arr, endExclusive, pred) {
|
|
4002
4439
|
for (let i = Math.min(endExclusive, arr.length) - 1; i >= 0; i--) {
|
|
4003
4440
|
if (pred(arr[i])) return i;
|
|
@@ -4025,9 +4462,12 @@ var KEYMAP = [
|
|
|
4025
4462
|
{ keys: [" "], run: () => void nextTab() },
|
|
4026
4463
|
{ keys: ["\x1B[A", "k"], run: () => void moveCursor(-1) },
|
|
4027
4464
|
{ keys: ["\x1B[B", "j"], run: () => void moveCursor(1) },
|
|
4028
|
-
// Collapse / expand — assets tab
|
|
4465
|
+
// Collapse / expand — assets tab
|
|
4029
4466
|
{ keys: ["\x1B[C"], when: TAB_ASSETS, run: expandUnderCursor },
|
|
4030
4467
|
{ keys: ["\x1B[D"], when: TAB_ASSETS, run: collapseOrJumpUnderCursor },
|
|
4468
|
+
// Collapse / expand — sources tab
|
|
4469
|
+
{ keys: ["\x1B[C"], when: TAB_SOURCES, run: expandSourceUnderCursor },
|
|
4470
|
+
{ keys: ["\x1B[D"], when: TAB_SOURCES, run: collapseOrJumpSourceUnderCursor },
|
|
4031
4471
|
// + : assets → bulk-add or single-add toggle
|
|
4032
4472
|
{
|
|
4033
4473
|
keys: ["+"],
|
|
@@ -4041,10 +4481,13 @@ var KEYMAP = [
|
|
|
4041
4481
|
}
|
|
4042
4482
|
}
|
|
4043
4483
|
},
|
|
4044
|
-
// Sources tab:
|
|
4045
|
-
{ keys: ["+"
|
|
4046
|
-
{ keys: ["-"
|
|
4047
|
-
{ keys: ["
|
|
4484
|
+
// Sources tab: + / - / space select (asset leaf or org/repo bulk header).
|
|
4485
|
+
{ keys: ["+"], when: TAB_SOURCES, run: () => selectSourceUnderCursor("add") },
|
|
4486
|
+
{ keys: ["-"], when: TAB_SOURCES, run: () => selectSourceUnderCursor("remove") },
|
|
4487
|
+
{ keys: [" "], when: TAB_SOURCES, run: () => selectSourceUnderCursor("toggle") },
|
|
4488
|
+
{ keys: ["a", "\r", "\n"], when: TAB_SOURCES, run: applyChanges },
|
|
4489
|
+
{ keys: ["i"], when: TAB_SOURCES, run: showInfo },
|
|
4490
|
+
{ keys: ["d"], when: TAB_SOURCES, run: toggleSourceDomainInfoUnderCursor },
|
|
4048
4491
|
// Libraries tab: +/-/n/r/x/d/enter map to shell hints in the minimal scaffold.
|
|
4049
4492
|
{
|
|
4050
4493
|
keys: ["+", "n", "a"],
|
|
@@ -4154,8 +4597,8 @@ function makeManageCommand() {
|
|
|
4154
4597
|
}
|
|
4155
4598
|
function makeMcpServerCommand() {
|
|
4156
4599
|
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) => {
|
|
4157
|
-
const
|
|
4158
|
-
const projectDir =
|
|
4600
|
+
const path36 = await import('path');
|
|
4601
|
+
const projectDir = path36.default.resolve(opts.projectDir);
|
|
4159
4602
|
const { LogStore, StdoutSink, registerLogStore } = await import('../core/logging.js');
|
|
4160
4603
|
registerLogStore(
|
|
4161
4604
|
new LogStore({
|
|
@@ -4371,7 +4814,7 @@ function action2(fn) {
|
|
|
4371
4814
|
};
|
|
4372
4815
|
}
|
|
4373
4816
|
async function reconcileAndReport(projectDir, plugins) {
|
|
4374
|
-
const { reconcilePlugins } = await import('../plugin-store-
|
|
4817
|
+
const { reconcilePlugins } = await import('../plugin-store-SGNJTBYS.js');
|
|
4375
4818
|
if (plugins.length === 0) {
|
|
4376
4819
|
logInfo("No plugins declared \u2014 nothing to reconcile.");
|
|
4377
4820
|
return;
|
|
@@ -4387,7 +4830,7 @@ async function reconcileAndReport(projectDir, plugins) {
|
|
|
4387
4830
|
async function runInstall2(spec, opts) {
|
|
4388
4831
|
const projectDir = path14__default.resolve(opts.projectDir);
|
|
4389
4832
|
const { WorkspaceYamlEditor: WorkspaceYamlEditor2 } = await import('../core/index.js');
|
|
4390
|
-
const { specName } = await import('../plugin-store-
|
|
4833
|
+
const { specName } = await import('../plugin-store-SGNJTBYS.js');
|
|
4391
4834
|
const yamlPath = path14__default.join(projectDir, "skaile.yaml");
|
|
4392
4835
|
const editor = WorkspaceYamlEditor2.load(yamlPath);
|
|
4393
4836
|
const replaced = editor.addPlugin(spec, specName);
|
|
@@ -4399,7 +4842,7 @@ async function runInstall2(spec, opts) {
|
|
|
4399
4842
|
async function runRemove(name, opts) {
|
|
4400
4843
|
const projectDir = path14__default.resolve(opts.projectDir);
|
|
4401
4844
|
const { WorkspaceYamlEditor: WorkspaceYamlEditor2 } = await import('../core/index.js');
|
|
4402
|
-
const { specName } = await import('../plugin-store-
|
|
4845
|
+
const { specName } = await import('../plugin-store-SGNJTBYS.js');
|
|
4403
4846
|
const yamlPath = path14__default.join(projectDir, "skaile.yaml");
|
|
4404
4847
|
const editor = WorkspaceYamlEditor2.load(yamlPath);
|
|
4405
4848
|
const removed = editor.removePlugin(name, specName);
|
|
@@ -4427,7 +4870,7 @@ async function runList(opts) {
|
|
|
4427
4870
|
const registry = createPluginRegistry();
|
|
4428
4871
|
if (declared.length > 0) {
|
|
4429
4872
|
try {
|
|
4430
|
-
const { loadPlugins } = await import('../plugin-store-
|
|
4873
|
+
const { loadPlugins } = await import('../plugin-store-SGNJTBYS.js');
|
|
4431
4874
|
const result = await loadPlugins(projectDir, declared, registry);
|
|
4432
4875
|
for (const f of result.failed) logWarn(f.error);
|
|
4433
4876
|
} catch (err) {
|
|
@@ -4643,10 +5086,29 @@ async function runPointerOnlyInstall(ref, deps) {
|
|
|
4643
5086
|
}
|
|
4644
5087
|
function makeInstallCommand() {
|
|
4645
5088
|
return new Command("install").description(`Install dependencies from skaile.yaml, or a single asset by ref (${REF_HINT})`).argument("[ref]", `Asset ref to install from the Catalog (${REF_HINT})`).option("--locked", "Install from lock file (CI mode \u2014 fails on drift)").option("--project-dir <path>", "Project directory", process.cwd()).option("--target <agent>", "Agent framework", "claude-code").option(
|
|
5089
|
+
"--global",
|
|
5090
|
+
"Install the global SSOT (~/.skaile/skaile.yaml), fanning out to every global backend"
|
|
5091
|
+
).option(
|
|
5092
|
+
"--backend <ids>",
|
|
5093
|
+
"Comma-separated global backends to install into (default: all resolved); implies --global"
|
|
5094
|
+
).option(
|
|
4646
5095
|
"--link",
|
|
4647
5096
|
"symlink local-path assets instead of copying (dev loop; machine-local, not for committing)"
|
|
4648
5097
|
).action(runInstallCommand);
|
|
4649
5098
|
}
|
|
5099
|
+
function parseBackendFilter2(raw) {
|
|
5100
|
+
if (!raw) return void 0;
|
|
5101
|
+
const ids = raw.split(",").map((s) => s.trim()).filter(Boolean);
|
|
5102
|
+
const out = [];
|
|
5103
|
+
for (const id of ids) {
|
|
5104
|
+
if (!SUPPORTED_DRIVER_TARGETS.includes(id)) {
|
|
5105
|
+
logErr(`unknown backend '${id}' \u2014 expected one of: ${SUPPORTED_DRIVER_TARGETS.join(", ")}`);
|
|
5106
|
+
process.exit(1);
|
|
5107
|
+
}
|
|
5108
|
+
out.push(id);
|
|
5109
|
+
}
|
|
5110
|
+
return out.length > 0 ? out : void 0;
|
|
5111
|
+
}
|
|
4650
5112
|
async function runInstallCommand(ref, opts) {
|
|
4651
5113
|
if (ref !== void 0) {
|
|
4652
5114
|
await runRefInstall(ref, opts);
|
|
@@ -4662,7 +5124,7 @@ async function runRefInstall(ref, opts) {
|
|
|
4662
5124
|
const spinner5 = p6.spinner();
|
|
4663
5125
|
spinner5.start(`Installing ${ref}`);
|
|
4664
5126
|
try {
|
|
4665
|
-
const { openCatalogSource: openCatalogSource2, openLibrary: openLibrary2 } = await import('../open-library-
|
|
5127
|
+
const { openCatalogSource: openCatalogSource2, openLibrary: openLibrary2 } = await import('../open-library-ERKRGH4B.js');
|
|
4666
5128
|
const catalog = await openCatalogSource2({ projectDir: path14__default.resolve(opts.projectDir) });
|
|
4667
5129
|
if (!supportsInstallManifest(catalog)) {
|
|
4668
5130
|
throw new Error(
|
|
@@ -4693,8 +5155,13 @@ async function runRefInstall(ref, opts) {
|
|
|
4693
5155
|
}
|
|
4694
5156
|
async function runYamlInstall(opts) {
|
|
4695
5157
|
const projectDir = path14__default.resolve(opts.projectDir);
|
|
5158
|
+
const backends = parseBackendFilter2(opts.backend);
|
|
5159
|
+
if (opts.global || backends) {
|
|
5160
|
+
await runGlobalInstall(opts, backends);
|
|
5161
|
+
return;
|
|
5162
|
+
}
|
|
4696
5163
|
try {
|
|
4697
|
-
const { ensureSourcesCloned } = await import('../ensure-sources-
|
|
5164
|
+
const { ensureSourcesCloned } = await import('../ensure-sources-GJOXWVWO.js');
|
|
4698
5165
|
const hydrate = ensureSourcesCloned(projectDir, { quiet: true });
|
|
4699
5166
|
if (hydrate.cloned.length > 0) {
|
|
4700
5167
|
logOk(`Cloned source(s): ${hydrate.cloned.join(", ")}`);
|
|
@@ -4736,6 +5203,37 @@ async function runYamlInstall(opts) {
|
|
|
4736
5203
|
process.exit(1);
|
|
4737
5204
|
}
|
|
4738
5205
|
}
|
|
5206
|
+
async function runGlobalInstall(opts, backends) {
|
|
5207
|
+
const am2 = new AssetManager({
|
|
5208
|
+
projectDir: path14__default.resolve(opts.projectDir),
|
|
5209
|
+
global: true,
|
|
5210
|
+
backends
|
|
5211
|
+
});
|
|
5212
|
+
const spinner5 = p6.spinner();
|
|
5213
|
+
spinner5.start("Installing global dependencies");
|
|
5214
|
+
try {
|
|
5215
|
+
const result = await am2.install({ locked: opts.locked, link: opts.link });
|
|
5216
|
+
spinner5.stop("Done");
|
|
5217
|
+
if (result.deployed.length > 0) for (const d of result.deployed) logOk(d);
|
|
5218
|
+
if (result.removed.length > 0) for (const r of result.removed) logWarn(`Removed: ${r}`);
|
|
5219
|
+
if (result.deployed.length === 0 && result.removed.length === 0)
|
|
5220
|
+
logInfo("Nothing to install (already up to date).");
|
|
5221
|
+
if (result.missing.length > 0) {
|
|
5222
|
+
for (const m of result.missing) logErr(`Missing: ${m}`);
|
|
5223
|
+
process.exitCode = 1;
|
|
5224
|
+
}
|
|
5225
|
+
if (result.lockWritten) logInfo(`Global lock written: ${S.dim("~/.skaile/skaile.lock.yaml")}`);
|
|
5226
|
+
const state2 = am2.globalState({});
|
|
5227
|
+
const byBackend = /* @__PURE__ */ new Map();
|
|
5228
|
+
for (const s of state2)
|
|
5229
|
+
if (s.state === "installed") byBackend.set(s.backend, (byBackend.get(s.backend) ?? 0) + 1);
|
|
5230
|
+
for (const [backend, n] of byBackend) logInfo(`${backend}: ${n} installed`);
|
|
5231
|
+
} catch (err) {
|
|
5232
|
+
spinner5.stop("Failed");
|
|
5233
|
+
logErr(String(err));
|
|
5234
|
+
process.exit(1);
|
|
5235
|
+
}
|
|
5236
|
+
}
|
|
4739
5237
|
function makeCheckCommand() {
|
|
4740
5238
|
return new Command("check").description("Check for unmet requirements").option("--project-dir <path>", "Project directory", process.cwd()).action((opts) => {
|
|
4741
5239
|
const am2 = new AssetManager({ projectDir: path14__default.resolve(opts.projectDir) });
|
|
@@ -4782,8 +5280,8 @@ function makeCleanCommand() {
|
|
|
4782
5280
|
return;
|
|
4783
5281
|
}
|
|
4784
5282
|
if (!opts.yes) {
|
|
4785
|
-
const
|
|
4786
|
-
if (p6.isCancel(
|
|
5283
|
+
const confirm6 = await p6.confirm({ message: "Proceed?" });
|
|
5284
|
+
if (p6.isCancel(confirm6) || !confirm6) {
|
|
4787
5285
|
logInfo("Cancelled.");
|
|
4788
5286
|
return;
|
|
4789
5287
|
}
|
|
@@ -5050,11 +5548,11 @@ function makeClearCommand() {
|
|
|
5050
5548
|
}
|
|
5051
5549
|
function makeReplCommand() {
|
|
5052
5550
|
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) => {
|
|
5053
|
-
const { findWorkspaceRoot
|
|
5551
|
+
const { findWorkspaceRoot } = await import('../core/index.js');
|
|
5054
5552
|
const { startRepl } = await import('../tui/index.js');
|
|
5055
5553
|
const os2 = await import('os');
|
|
5056
5554
|
const userCwd = path14__default.resolve(opts.projectDir ?? process.cwd());
|
|
5057
|
-
const workspaceRoot =
|
|
5555
|
+
const workspaceRoot = findWorkspaceRoot(userCwd);
|
|
5058
5556
|
let projectDir;
|
|
5059
5557
|
let agentCwd;
|
|
5060
5558
|
let driverOverride = opts.driver;
|
|
@@ -5132,7 +5630,7 @@ async function ensurePluginsLoadedForServe(projectDir) {
|
|
|
5132
5630
|
const { resolveSkWorkspaceConfig: resolveSkWorkspaceConfig2 } = await import('../core/index.js');
|
|
5133
5631
|
const config = resolveSkWorkspaceConfig2(projectDir);
|
|
5134
5632
|
if (!config.plugins || config.plugins.length === 0) return;
|
|
5135
|
-
const { ensurePluginsLoaded } = await import('../plugin-store-
|
|
5633
|
+
const { ensurePluginsLoaded } = await import('../plugin-store-SGNJTBYS.js');
|
|
5136
5634
|
const { pluginRegistry } = await import('../plugin-registry/index.js');
|
|
5137
5635
|
const result = await ensurePluginsLoaded(projectDir, config.plugins, pluginRegistry);
|
|
5138
5636
|
if (result.loaded.length > 0) {
|
|
@@ -5148,21 +5646,21 @@ async function ensurePluginsLoadedForServe(projectDir) {
|
|
|
5148
5646
|
async function runCompileTest(opts) {
|
|
5149
5647
|
const { logOk: logOk2, logErr: logErr2, logInfo: logInfo2, S: S2 } = await import('../helpers-F4NZ66VD.js');
|
|
5150
5648
|
const { tmpdir } = await import('os');
|
|
5151
|
-
const { dirname:
|
|
5649
|
+
const { dirname: dirname4, join: join5, resolve: resolve5 } = await import('path');
|
|
5152
5650
|
const { fileURLToPath: fileURLToPath2 } = await import('url');
|
|
5153
|
-
const { unlinkSync, existsSync:
|
|
5651
|
+
const { unlinkSync, existsSync: existsSync13 } = await import('fs');
|
|
5154
5652
|
const { spawn } = await import('child_process');
|
|
5155
5653
|
const { portableSpawnSync: portableSpawnSync2 } = await import('../core/index.js');
|
|
5156
|
-
const { MONOREPO_ROOT } = await import('../paths-
|
|
5654
|
+
const { MONOREPO_ROOT } = await import('../paths-D6RUQ522.js');
|
|
5157
5655
|
if (MONOREPO_ROOT === null) {
|
|
5158
5656
|
logErr2("--compile-test is only available inside the skaile-dev workspace.");
|
|
5159
5657
|
logInfo2("Run it from a checkout of skaile-ai/skaile-dev (the monorepo shell).");
|
|
5160
5658
|
process.exitCode = 2;
|
|
5161
5659
|
return;
|
|
5162
5660
|
}
|
|
5163
|
-
const outfile =
|
|
5661
|
+
const outfile = join5(tmpdir(), `skaile-compile-test-${Date.now()}`);
|
|
5164
5662
|
const __thisFile = fileURLToPath2(import.meta.url);
|
|
5165
|
-
const entryPoint = resolve5(
|
|
5663
|
+
const entryPoint = resolve5(dirname4(__thisFile), "..", "index.ts");
|
|
5166
5664
|
logInfo2(`Building compiled binary...`);
|
|
5167
5665
|
logInfo2(`Entry: ${S2.dim(entryPoint)}`);
|
|
5168
5666
|
logInfo2(`Output: ${S2.dim(outfile)}`);
|
|
@@ -5212,7 +5710,7 @@ async function runCompileTest(opts) {
|
|
|
5212
5710
|
} catch {
|
|
5213
5711
|
}
|
|
5214
5712
|
try {
|
|
5215
|
-
if (
|
|
5713
|
+
if (existsSync13(outfile)) unlinkSync(outfile);
|
|
5216
5714
|
} catch {
|
|
5217
5715
|
}
|
|
5218
5716
|
}
|
|
@@ -5966,324 +6464,6 @@ function makeShowCommand() {
|
|
|
5966
6464
|
}
|
|
5967
6465
|
});
|
|
5968
6466
|
}
|
|
5969
|
-
|
|
5970
|
-
// cli/src/commands/source-manifest.ts
|
|
5971
|
-
var NOT_WIRED_MSG = "`skaile source manifest *` is scaffolded but not yet wired. Server-side endpoint (`POST /sources/<id>/manifest`) lands in a follow-up PR.";
|
|
5972
|
-
function notWired2(verb) {
|
|
5973
|
-
logErr(`${NOT_WIRED_MSG} (verb: source manifest ${verb})`);
|
|
5974
|
-
process.exit(2);
|
|
5975
|
-
}
|
|
5976
|
-
function addSourceManifestCommands(src) {
|
|
5977
|
-
const manifest = src.command("manifest").description("Sidecar manifest lifecycle for a source");
|
|
5978
|
-
manifest.command("init <src>").description("Start a sidecar manifest for a source").action(() => notWired2("init"));
|
|
5979
|
-
manifest.command("edit <src>").description("Open the sidecar manifest in $EDITOR").action(() => notWired2("edit"));
|
|
5980
|
-
manifest.command("rebuild <src>").description("Re-derive the manifest after an upstream change").option("--merge", "Merge with existing entries instead of overwriting", false).action(() => notWired2("rebuild"));
|
|
5981
|
-
manifest.command("verify <src>").description("Verify hashes, deps, and schema").option("--strict", "Fail on advisory checks", false).action(() => notWired2("verify"));
|
|
5982
|
-
manifest.command("publish <src>").description("Register the manifest in the store (provenance=curator)").action(() => notWired2("publish"));
|
|
5983
|
-
manifest.command("propose <src>").description("Open a PR to upstream with the sidecar manifest").action(() => notWired2("propose"));
|
|
5984
|
-
manifest.command("yank <src>").description("Retract a published manifest from the remote store").option("--version <v>", "Version to yank").action(() => notWired2("yank"));
|
|
5985
|
-
}
|
|
5986
|
-
|
|
5987
|
-
// cli/src/commands/source.ts
|
|
5988
|
-
function sourceClonePath(key) {
|
|
5989
|
-
return path14.join(getGlobalCacheDir(), key);
|
|
5990
|
-
}
|
|
5991
|
-
var SKAILE_MANIFEST_FILENAME2 = "skaile.manifest.yaml";
|
|
5992
|
-
var LEGACY_SOURCE_CONFIG_FILENAME = ".skaile-source.yaml";
|
|
5993
|
-
function indexingHadFailures(result) {
|
|
5994
|
-
return result.errors.length > 0;
|
|
5995
|
-
}
|
|
5996
|
-
function legacySourceConfigHint(dest) {
|
|
5997
|
-
const hasLegacy = existsSync(path14.join(dest, LEGACY_SOURCE_CONFIG_FILENAME));
|
|
5998
|
-
const hasManifest = existsSync(path14.join(dest, SKAILE_MANIFEST_FILENAME2));
|
|
5999
|
-
if (hasLegacy && !hasManifest) {
|
|
6000
|
-
return `This source ships a legacy ${LEGACY_SOURCE_CONFIG_FILENAME} but no ${SKAILE_MANIFEST_FILENAME2}; its declared publisher is ignored and assets are published under their first path segment. Add a ${SKAILE_MANIFEST_FILENAME2} (\`skaile source manifest init\`) to set the publisher and asset inventory.`;
|
|
6001
|
-
}
|
|
6002
|
-
return void 0;
|
|
6003
|
-
}
|
|
6004
|
-
function normalizeSourceUrl(input) {
|
|
6005
|
-
const s = input.trim();
|
|
6006
|
-
if (/^(?:https?|git|ssh|file):\/\//.test(s) || /^git@/.test(s)) return s;
|
|
6007
|
-
const repo = s.replace(/\.git$/, "");
|
|
6008
|
-
if (/^[\w.-]+\/[\w.-]+$/.test(repo)) return `git@github.com:${repo}.git`;
|
|
6009
|
-
if (/^[\w.-]+$/.test(repo)) return `git@github.com:skaile-ai/${repo}.git`;
|
|
6010
|
-
return s;
|
|
6011
|
-
}
|
|
6012
|
-
function sourceMatchesKey(entry, key) {
|
|
6013
|
-
if (entry.url === key) return true;
|
|
6014
|
-
if (sourceCacheKey(entry.url) === key || sourceShortName(entry.url) === key) return true;
|
|
6015
|
-
return entry.url === normalizeSourceUrl(key);
|
|
6016
|
-
}
|
|
6017
|
-
function findCacheKeyCollision(sources, url) {
|
|
6018
|
-
const key = sourceCacheKey(url);
|
|
6019
|
-
return sources.find((s) => s.url !== url && sourceCacheKey(s.url) === key);
|
|
6020
|
-
}
|
|
6021
|
-
function requireProjectYamlPath() {
|
|
6022
|
-
const root = findWorkspaceRoot(process.cwd());
|
|
6023
|
-
if (!root) {
|
|
6024
|
-
logErr(
|
|
6025
|
-
"No skaile.yaml found in the current directory or any parent. Run `skaile init` first."
|
|
6026
|
-
);
|
|
6027
|
-
process.exit(1);
|
|
6028
|
-
}
|
|
6029
|
-
return path14.join(root, workspaceConfigFilename());
|
|
6030
|
-
}
|
|
6031
|
-
function readProjectSources(yamlPath) {
|
|
6032
|
-
if (!existsSync(yamlPath)) return [];
|
|
6033
|
-
try {
|
|
6034
|
-
return WorkspaceYamlEditor.load(yamlPath).getSources();
|
|
6035
|
-
} catch (err) {
|
|
6036
|
-
logErr(`Could not read ${yamlPath}: ${err instanceof Error ? err.message : String(err)}`);
|
|
6037
|
-
process.exit(1);
|
|
6038
|
-
}
|
|
6039
|
-
}
|
|
6040
|
-
function ensureClone(entry, opts = {}) {
|
|
6041
|
-
const dest = sourceClonePath(sourceCacheKey(entry.url));
|
|
6042
|
-
if (existsSync(dest)) {
|
|
6043
|
-
if (!opts.force) return false;
|
|
6044
|
-
rmSync(dest, { recursive: true, force: true });
|
|
6045
|
-
}
|
|
6046
|
-
mkdirSync(path14.dirname(dest), { recursive: true });
|
|
6047
|
-
const args = ["clone", entry.url, dest];
|
|
6048
|
-
if (entry.pin) args.splice(1, 0, "--branch", entry.pin);
|
|
6049
|
-
const clone = spawnSync("git", args, { stdio: "inherit" });
|
|
6050
|
-
if (clone.status !== 0) {
|
|
6051
|
-
logErr(`git clone failed for ${entry.url}`);
|
|
6052
|
-
process.exit(1);
|
|
6053
|
-
}
|
|
6054
|
-
return true;
|
|
6055
|
-
}
|
|
6056
|
-
async function refreshManifestCache(entry, includeDev = false) {
|
|
6057
|
-
const { manager, library, close } = await openLibraryManager();
|
|
6058
|
-
try {
|
|
6059
|
-
const name = sourceShortName(entry.url);
|
|
6060
|
-
const dest = sourceClonePath(sourceCacheKey(entry.url));
|
|
6061
|
-
const existing = (await manager.listLibraries()).find((l) => l.name === name);
|
|
6062
|
-
const lib = existing ?? await manager.addLibrary({
|
|
6063
|
-
name,
|
|
6064
|
-
path: dest,
|
|
6065
|
-
backend: "git",
|
|
6066
|
-
backendConfig: { url: entry.url, branch: entry.pin ?? "main", authHint: "ssh" },
|
|
6067
|
-
ownership: "reader"
|
|
6068
|
-
});
|
|
6069
|
-
const catalog = new LocalCatalogSource(library, lib.id, dest, createFullRegistry());
|
|
6070
|
-
const result = await catalog.sync({ includeDev });
|
|
6071
|
-
await library.syncSource(lib.id);
|
|
6072
|
-
return result;
|
|
6073
|
-
} finally {
|
|
6074
|
-
close();
|
|
6075
|
-
}
|
|
6076
|
-
}
|
|
6077
|
-
async function dropManifestCache(url, purgeClone) {
|
|
6078
|
-
const name = sourceShortName(url);
|
|
6079
|
-
const { manager, close } = await openLibraryManager();
|
|
6080
|
-
try {
|
|
6081
|
-
const existing = (await manager.listLibraries()).find((l) => l.name === name);
|
|
6082
|
-
if (existing) {
|
|
6083
|
-
await manager.removeLibrary(name, { purge: false });
|
|
6084
|
-
}
|
|
6085
|
-
} finally {
|
|
6086
|
-
close();
|
|
6087
|
-
}
|
|
6088
|
-
if (purgeClone) {
|
|
6089
|
-
const dest = sourceClonePath(sourceCacheKey(url));
|
|
6090
|
-
if (existsSync(dest)) rmSync(dest, { recursive: true, force: true });
|
|
6091
|
-
}
|
|
6092
|
-
}
|
|
6093
|
-
function makeSourceCommand() {
|
|
6094
|
-
const cmd = new Command("source").description(
|
|
6095
|
-
"Manage github sources for the current project (recorded in skaile.yaml)"
|
|
6096
|
-
);
|
|
6097
|
-
cmd.command("add <source>").description(
|
|
6098
|
-
"Clone a github repo and register it in this project's skaile.yaml. <source> may be a full git URL, an owner/repo shorthand, or a bare name (\u2192 git@github.com:skaile-ai/<name>.git)."
|
|
6099
|
-
).option("--name <slug>", "[deprecated] no-op \u2014 the source entry stores only the URL").option("--pin <ref>", "Pin a branch, tag, or 40-char SHA").option("--branch <branch>", "[deprecated] alias for --pin").option("--force", "Remove an existing clone and re-clone", false).option("--dev", "Also index dev-only assets under the source's dev_paths", false).action(
|
|
6100
|
-
async (source, opts) => {
|
|
6101
|
-
const url = normalizeSourceUrl(source);
|
|
6102
|
-
const yamlPath = requireProjectYamlPath();
|
|
6103
|
-
const collision = findCacheKeyCollision(readProjectSources(yamlPath), url);
|
|
6104
|
-
if (collision) {
|
|
6105
|
-
logErr(
|
|
6106
|
-
`"${url}" maps to the same cache key (${sourceCacheKey(url)}) as already-registered "${collision.url}". Remove that source first (skaile source remove) or re-use its exact URL to update it.`
|
|
6107
|
-
);
|
|
6108
|
-
process.exitCode = 1;
|
|
6109
|
-
return;
|
|
6110
|
-
}
|
|
6111
|
-
if (opts.name) {
|
|
6112
|
-
logWarn(
|
|
6113
|
-
"the --name flag is deprecated; the source entry now stores only the URL (the cache slug is derived from it)."
|
|
6114
|
-
);
|
|
6115
|
-
}
|
|
6116
|
-
const pin = opts.pin ?? opts.branch;
|
|
6117
|
-
const slug = sourceShortName(url);
|
|
6118
|
-
const entry = { url };
|
|
6119
|
-
if (pin) entry.pin = pin;
|
|
6120
|
-
const editor = WorkspaceYamlEditor.load(yamlPath);
|
|
6121
|
-
editor.setSource(entry);
|
|
6122
|
-
editor.save();
|
|
6123
|
-
const dest = sourceClonePath(sourceCacheKey(url));
|
|
6124
|
-
const preexisting = existsSync(dest);
|
|
6125
|
-
const cloned = ensureClone(entry, { force: opts.force });
|
|
6126
|
-
if (!cloned) {
|
|
6127
|
-
logOk(`Reusing cached clone at ${dest}`);
|
|
6128
|
-
} else if (preexisting) {
|
|
6129
|
-
logOk(`Re-cloned ${url} \u2192 ${dest}`);
|
|
6130
|
-
} else {
|
|
6131
|
-
logOk(`Cloned ${url} \u2192 ${dest}`);
|
|
6132
|
-
}
|
|
6133
|
-
const result = await refreshManifestCache(entry, opts.dev);
|
|
6134
|
-
const failed = indexingHadFailures(result);
|
|
6135
|
-
const indexedMsg = `Indexed ${result.assetsUpdated} of ${result.assetsFound} asset(s) from "${slug}".`;
|
|
6136
|
-
if (failed) {
|
|
6137
|
-
logWarn(indexedMsg);
|
|
6138
|
-
} else {
|
|
6139
|
-
logOk(indexedMsg);
|
|
6140
|
-
}
|
|
6141
|
-
for (const err of result.errors) logWarn(err);
|
|
6142
|
-
const legacyHint = legacySourceConfigHint(dest);
|
|
6143
|
-
if (legacyHint) logWarn(legacyHint);
|
|
6144
|
-
const where = path14.relative(process.cwd(), yamlPath);
|
|
6145
|
-
if (failed) {
|
|
6146
|
-
logWarn(
|
|
6147
|
-
`Source "${slug}" registered in ${where}, but ${result.errors.length} asset(s) failed to index (see above). Fix the cause, then re-run \`skaile source sync ${slug}\`.`
|
|
6148
|
-
);
|
|
6149
|
-
process.exitCode = 1;
|
|
6150
|
-
} else {
|
|
6151
|
-
logOk(`Source "${slug}" registered in ${where}.`);
|
|
6152
|
-
}
|
|
6153
|
-
}
|
|
6154
|
-
);
|
|
6155
|
-
cmd.command("list").description("List sources registered in this project's skaile.yaml").option("--json", "Output as JSON").action(async (opts) => {
|
|
6156
|
-
const yamlPath = requireProjectYamlPath();
|
|
6157
|
-
const sources = readProjectSources(yamlPath);
|
|
6158
|
-
if (opts.json) return console.log(JSON.stringify(sources, null, 2));
|
|
6159
|
-
if (sources.length === 0) {
|
|
6160
|
-
logInfo("No sources in skaile.yaml. Run `skaile source add <git-url>` to register one.");
|
|
6161
|
-
return;
|
|
6162
|
-
}
|
|
6163
|
-
console.log();
|
|
6164
|
-
console.log(S.heading(" Sources"));
|
|
6165
|
-
for (const s of sources) {
|
|
6166
|
-
const slug = sourceShortName(s.url);
|
|
6167
|
-
const cached = existsSync(sourceClonePath(sourceCacheKey(s.url))) ? "" : S.warn(" (not cached)");
|
|
6168
|
-
console.log(` ${S.cmd(slug.padEnd(24))} ${S.dim(s.url)}${cached}`);
|
|
6169
|
-
}
|
|
6170
|
-
console.log(`
|
|
6171
|
-
${S.dim(`${sources.length} source(s)`)}
|
|
6172
|
-
`);
|
|
6173
|
-
});
|
|
6174
|
-
cmd.command("show <name-or-url>").description("Show details for a source (matched by URL or derived slug)").action(async (key) => {
|
|
6175
|
-
const yamlPath = requireProjectYamlPath();
|
|
6176
|
-
const entry = readProjectSources(yamlPath).find((s) => sourceMatchesKey(s, key));
|
|
6177
|
-
if (!entry) {
|
|
6178
|
-
logErr(`No source matching "${key}" in ${yamlPath}.`);
|
|
6179
|
-
process.exit(1);
|
|
6180
|
-
}
|
|
6181
|
-
const slug = sourceShortName(entry.url);
|
|
6182
|
-
const clonePath = sourceClonePath(sourceCacheKey(entry.url));
|
|
6183
|
-
console.log(
|
|
6184
|
-
JSON.stringify(
|
|
6185
|
-
{
|
|
6186
|
-
...entry,
|
|
6187
|
-
slug,
|
|
6188
|
-
clonePath,
|
|
6189
|
-
cached: existsSync(clonePath)
|
|
6190
|
-
},
|
|
6191
|
-
null,
|
|
6192
|
-
2
|
|
6193
|
-
)
|
|
6194
|
-
);
|
|
6195
|
-
});
|
|
6196
|
-
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) => {
|
|
6197
|
-
const yamlPath = requireProjectYamlPath();
|
|
6198
|
-
const editor = WorkspaceYamlEditor.load(yamlPath);
|
|
6199
|
-
const match = editor.getSources().find((s) => sourceMatchesKey(s, key));
|
|
6200
|
-
if (!match) {
|
|
6201
|
-
logErr(`No source matching "${key}" in ${yamlPath}.`);
|
|
6202
|
-
process.exit(1);
|
|
6203
|
-
}
|
|
6204
|
-
const slug = sourceShortName(match.url);
|
|
6205
|
-
editor.removeSource(match.url);
|
|
6206
|
-
editor.save();
|
|
6207
|
-
await dropManifestCache(match.url, opts.purge);
|
|
6208
|
-
logOk(
|
|
6209
|
-
opts.purge ? `Removed source "${slug}" and purged its clone.` : `Removed source "${slug}" from skaile.yaml (clone left in ~/.skaile/cache/sources/).`
|
|
6210
|
-
);
|
|
6211
|
-
});
|
|
6212
|
-
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) => {
|
|
6213
|
-
const yamlPath = requireProjectYamlPath();
|
|
6214
|
-
const sources = readProjectSources(yamlPath);
|
|
6215
|
-
if (sources.length === 0) {
|
|
6216
|
-
logInfo("No sources in skaile.yaml.");
|
|
6217
|
-
return;
|
|
6218
|
-
}
|
|
6219
|
-
let targets;
|
|
6220
|
-
if (key) {
|
|
6221
|
-
targets = sources.filter((s) => sourceMatchesKey(s, key));
|
|
6222
|
-
if (targets.length === 0) {
|
|
6223
|
-
logInfo(`No source matching "${key}".`);
|
|
6224
|
-
return;
|
|
6225
|
-
}
|
|
6226
|
-
} else if (opts.all || sources.length === 1 || !process.stdin.isTTY) {
|
|
6227
|
-
targets = sources;
|
|
6228
|
-
} else {
|
|
6229
|
-
const selected = await p6.multiselect({
|
|
6230
|
-
message: "Select sources to sync",
|
|
6231
|
-
options: sources.map((s) => ({
|
|
6232
|
-
value: s.url,
|
|
6233
|
-
label: sourceShortName(s.url),
|
|
6234
|
-
hint: s.url
|
|
6235
|
-
})),
|
|
6236
|
-
required: true
|
|
6237
|
-
});
|
|
6238
|
-
if (p6.isCancel(selected)) {
|
|
6239
|
-
p6.cancel("Cancelled.");
|
|
6240
|
-
return;
|
|
6241
|
-
}
|
|
6242
|
-
const picked = new Set(selected);
|
|
6243
|
-
targets = sources.filter((s) => picked.has(s.url));
|
|
6244
|
-
}
|
|
6245
|
-
for (const entry of targets) {
|
|
6246
|
-
const slug = sourceShortName(entry.url);
|
|
6247
|
-
const dest = sourceClonePath(sourceCacheKey(entry.url));
|
|
6248
|
-
if (!existsSync(dest)) {
|
|
6249
|
-
ensureClone(entry);
|
|
6250
|
-
logOk(`${slug}: cloned to ${dest}.`);
|
|
6251
|
-
} else {
|
|
6252
|
-
const pull = spawnSync("git", ["pull", "--ff-only"], { cwd: dest, stdio: "inherit" });
|
|
6253
|
-
if (pull.status !== 0) {
|
|
6254
|
-
logWarn(`${slug}: git pull failed, skipping manifest refresh.`);
|
|
6255
|
-
continue;
|
|
6256
|
-
}
|
|
6257
|
-
}
|
|
6258
|
-
const result = await refreshManifestCache(entry, opts.dev);
|
|
6259
|
-
const failed = indexingHadFailures(result);
|
|
6260
|
-
const indexedMsg = `${slug}: indexed ${result.assetsUpdated} of ${result.assetsFound} asset(s).`;
|
|
6261
|
-
if (failed) {
|
|
6262
|
-
logWarn(indexedMsg);
|
|
6263
|
-
process.exitCode = 1;
|
|
6264
|
-
} else {
|
|
6265
|
-
logOk(indexedMsg);
|
|
6266
|
-
}
|
|
6267
|
-
for (const err of result.errors) logWarn(`${slug}: ${err}`);
|
|
6268
|
-
const legacyHint = legacySourceConfigHint(dest);
|
|
6269
|
-
if (legacyHint) logWarn(`${slug}: ${legacyHint}`);
|
|
6270
|
-
}
|
|
6271
|
-
});
|
|
6272
|
-
cmd.command("patch <ref>").description("Extract an asset for editing against the source").action((_ref) => {
|
|
6273
|
-
logErr(
|
|
6274
|
-
"`skaile source patch` is scaffolded but not yet wired. The patch flow lands in a follow-up PR."
|
|
6275
|
-
);
|
|
6276
|
-
process.exit(2);
|
|
6277
|
-
});
|
|
6278
|
-
cmd.command("propose <ref>").description("Open a PR with the patch against the source upstream").action((_ref) => {
|
|
6279
|
-
logErr(
|
|
6280
|
-
"`skaile source propose` is scaffolded but not yet wired. The propose flow lands in a follow-up PR."
|
|
6281
|
-
);
|
|
6282
|
-
process.exit(2);
|
|
6283
|
-
});
|
|
6284
|
-
addSourceManifestCommands(cmd);
|
|
6285
|
-
return cmd;
|
|
6286
|
-
}
|
|
6287
6467
|
function makeStoreCommand() {
|
|
6288
6468
|
const store = new Command("store").description("Manage the AI Asset Store");
|
|
6289
6469
|
store.command("login").description("Authenticate with the store").option("--email <email>", "Login with email instead of GitHub").action(async (opts) => {
|
|
@@ -6461,7 +6641,7 @@ function makeTreeCommand() {
|
|
|
6461
6641
|
});
|
|
6462
6642
|
}
|
|
6463
6643
|
function makeUpdateCommand() {
|
|
6464
|
-
return new Command("update").description("Refresh the Catalog cache and re-deploy outdated assets in the current project").argument("[name]", "Update a specific asset (kind:name)").option("--project-dir <path>", "Project directory", process.cwd()).option("--no-catalog", "Skip refreshing the catalog cache").option("--catalog-only", "Refresh the catalog cache only; do not re-deploy assets").action(
|
|
6644
|
+
return new Command("update").description("Refresh the Catalog cache and re-deploy outdated assets in the current project").argument("[name]", "Update a specific asset (kind:name)").option("--project-dir <path>", "Project directory", process.cwd()).option("--no-catalog", "Skip refreshing the catalog cache").option("--catalog-only", "Refresh the catalog cache only; do not re-deploy assets").option("--no-sync", "Skip syncing sources from upstream before re-deploying").option("-y, --yes", "Sync sources without the confirmation prompt").action(
|
|
6465
6645
|
async (_name, opts) => {
|
|
6466
6646
|
if (opts.catalog !== false) {
|
|
6467
6647
|
try {
|
|
@@ -6479,7 +6659,16 @@ function makeUpdateCommand() {
|
|
|
6479
6659
|
}
|
|
6480
6660
|
}
|
|
6481
6661
|
if (opts.catalogOnly) return;
|
|
6482
|
-
const
|
|
6662
|
+
const projectDir = path14__default.resolve(opts.projectDir);
|
|
6663
|
+
if (await shouldSyncSources(opts)) {
|
|
6664
|
+
const syncSpinner = p6.spinner();
|
|
6665
|
+
syncSpinner.start("Syncing sources");
|
|
6666
|
+
const { total, synced, failed } = await syncProjectSources(projectDir);
|
|
6667
|
+
syncSpinner.stop(
|
|
6668
|
+
total === 0 ? "No sources to sync." : `Synced ${S.heading(`${synced}/${total}`)} source(s)` + (failed ? ` (${failed} failed)` : "")
|
|
6669
|
+
);
|
|
6670
|
+
}
|
|
6671
|
+
const am2 = new AssetManager({ projectDir });
|
|
6483
6672
|
const spinner5 = p6.spinner();
|
|
6484
6673
|
spinner5.start("Re-deploying assets");
|
|
6485
6674
|
const result = await am2.install();
|
|
@@ -6492,6 +6681,19 @@ function makeUpdateCommand() {
|
|
|
6492
6681
|
}
|
|
6493
6682
|
);
|
|
6494
6683
|
}
|
|
6684
|
+
async function shouldSyncSources(opts) {
|
|
6685
|
+
if (opts.sync === false) return false;
|
|
6686
|
+
if (opts.yes || !process.stdin.isTTY) return true;
|
|
6687
|
+
const answer = await p6.confirm({
|
|
6688
|
+
message: "Sync sources from upstream before re-deploying?",
|
|
6689
|
+
initialValue: true
|
|
6690
|
+
});
|
|
6691
|
+
if (p6.isCancel(answer)) {
|
|
6692
|
+
p6.cancel("Cancelled.");
|
|
6693
|
+
process.exit(130);
|
|
6694
|
+
}
|
|
6695
|
+
return answer;
|
|
6696
|
+
}
|
|
6495
6697
|
var MANIFEST_GLOBS = [
|
|
6496
6698
|
{ pattern: /\/SKILL\.md$/, kind: "skill" },
|
|
6497
6699
|
{ pattern: /\/agent\.yaml$/, kind: "agent" },
|
|
@@ -7221,7 +7423,7 @@ program.command("init [project-dir]").description("Initialize a project director
|
|
|
7221
7423
|
(projectDir, opts) => runInit(projectDir, opts)
|
|
7222
7424
|
);
|
|
7223
7425
|
async function runInit(projectDir, opts) {
|
|
7224
|
-
const { mkdirSync:
|
|
7426
|
+
const { mkdirSync: mkdirSync5, writeFileSync: writeFileSync4 } = await import('fs');
|
|
7225
7427
|
const { stringify } = await import('yaml');
|
|
7226
7428
|
const { DRIVER_TARGETS, SUPPORTED_DRIVER_TARGETS: SUPPORTED_DRIVER_TARGETS2 } = await import('../core/index.js');
|
|
7227
7429
|
const backend = opts.backend;
|
|
@@ -7233,30 +7435,30 @@ async function runInit(projectDir, opts) {
|
|
|
7233
7435
|
const resolved = path14__default.resolve(projectDir ?? ".");
|
|
7234
7436
|
const projectName = path14__default.basename(resolved);
|
|
7235
7437
|
const created = [];
|
|
7236
|
-
const { existsSync:
|
|
7237
|
-
if (!
|
|
7238
|
-
|
|
7438
|
+
const { existsSync: existsSync13 } = await import('fs');
|
|
7439
|
+
if (!existsSync13(resolved)) {
|
|
7440
|
+
mkdirSync5(resolved, { recursive: true });
|
|
7239
7441
|
created.push(".");
|
|
7240
7442
|
}
|
|
7241
7443
|
const skaileDir = path14__default.join(resolved, ".skaile");
|
|
7242
|
-
if (!
|
|
7243
|
-
|
|
7444
|
+
if (!existsSync13(skaileDir)) {
|
|
7445
|
+
mkdirSync5(path14__default.join(skaileDir, "sessions"), { recursive: true });
|
|
7244
7446
|
created.push(".skaile/");
|
|
7245
7447
|
}
|
|
7246
7448
|
const settingsPath = path14__default.join(skaileDir, "settings.json");
|
|
7247
|
-
if (!
|
|
7449
|
+
if (!existsSync13(settingsPath)) {
|
|
7248
7450
|
writeFileSync4(settingsPath, "{}\n");
|
|
7249
7451
|
created.push(".skaile/settings.json");
|
|
7250
7452
|
}
|
|
7251
7453
|
const wsConfigPath = path14__default.join(resolved, "skaile.yaml");
|
|
7252
|
-
if (!
|
|
7454
|
+
if (!existsSync13(wsConfigPath)) {
|
|
7253
7455
|
writeFileSync4(wsConfigPath, stringify(buildInitWorkspaceConfig(projectName, backend)));
|
|
7254
7456
|
created.push("skaile.yaml");
|
|
7255
7457
|
}
|
|
7256
7458
|
for (const dir of new Set(Object.values(DRIVER_TARGETS[backend].local))) {
|
|
7257
7459
|
const full = path14__default.join(resolved, dir);
|
|
7258
|
-
if (!
|
|
7259
|
-
|
|
7460
|
+
if (!existsSync13(full)) {
|
|
7461
|
+
mkdirSync5(full, { recursive: true });
|
|
7260
7462
|
created.push(`${dir}/`);
|
|
7261
7463
|
}
|
|
7262
7464
|
}
|
|
@@ -7286,7 +7488,7 @@ function buildInitWorkspaceConfig(projectName, backend) {
|
|
|
7286
7488
|
}
|
|
7287
7489
|
async function initGitScaffold(resolved, created) {
|
|
7288
7490
|
const { execSync: execSync3 } = await import('child_process');
|
|
7289
|
-
const { existsSync:
|
|
7491
|
+
const { existsSync: existsSync13, readFileSync: readFileSync8, writeFileSync: writeFileSync4 } = await import('fs');
|
|
7290
7492
|
const gitignorePath = path14__default.join(resolved, ".gitignore");
|
|
7291
7493
|
const entries = [
|
|
7292
7494
|
"node_modules/",
|
|
@@ -7302,7 +7504,7 @@ async function initGitScaffold(resolved, created) {
|
|
|
7302
7504
|
".env",
|
|
7303
7505
|
".env.local"
|
|
7304
7506
|
];
|
|
7305
|
-
const existing =
|
|
7507
|
+
const existing = existsSync13(gitignorePath) ? readFileSync8(gitignorePath, "utf-8") : "";
|
|
7306
7508
|
const have = new Set(existing.split("\n").map((l) => l.trim()));
|
|
7307
7509
|
const append = entries.filter((e) => !have.has(e));
|
|
7308
7510
|
if (append.length > 0) {
|
|
@@ -7311,7 +7513,7 @@ async function initGitScaffold(resolved, created) {
|
|
|
7311
7513
|
`);
|
|
7312
7514
|
if (!existing) created.push(".gitignore");
|
|
7313
7515
|
}
|
|
7314
|
-
if (!
|
|
7516
|
+
if (!existsSync13(path14__default.join(resolved, ".git"))) {
|
|
7315
7517
|
try {
|
|
7316
7518
|
execSync3("git init", { cwd: resolved, stdio: "pipe" });
|
|
7317
7519
|
created.push(".git/");
|
|
@@ -7341,7 +7543,7 @@ async function bootstrapUserConfig() {
|
|
|
7341
7543
|
}
|
|
7342
7544
|
async function hydrateInitSources(resolved, created) {
|
|
7343
7545
|
try {
|
|
7344
|
-
const { ensureSourcesCloned } = await import('../ensure-sources-
|
|
7546
|
+
const { ensureSourcesCloned } = await import('../ensure-sources-GJOXWVWO.js');
|
|
7345
7547
|
const hydrate = ensureSourcesCloned(resolved, { quiet: true });
|
|
7346
7548
|
for (const n of hydrate.cloned) created.push(`~/.skaile/cache/sources/${n}/`);
|
|
7347
7549
|
if (hydrate.failed.length > 0) {
|
|
@@ -7377,7 +7579,7 @@ function printInitSummary(resolved, projectDir, created) {
|
|
|
7377
7579
|
console.log();
|
|
7378
7580
|
}
|
|
7379
7581
|
program.command("setup").description("Interactive provider setup wizard").action(async () => {
|
|
7380
|
-
const { cmdSetup } = await import('../setup-
|
|
7582
|
+
const { cmdSetup } = await import('../setup-IV2JFW3T.js');
|
|
7381
7583
|
await cmdSetup([], { projectDir: process.cwd() });
|
|
7382
7584
|
});
|
|
7383
7585
|
program.addCommand(makeInstallCommand());
|