@skaile/workspaces 0.49.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 +248 -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 +94 -6
- package/dist/asset-manager/src/index.d.ts.map +1 -1
- package/dist/asset-manager/src/installer.d.ts +19 -8
- 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-XVDXGQ55.js → chunk-7X53KHQ4.js} +4 -2
- package/dist/{chunk-XVDXGQ55.js.map → chunk-7X53KHQ4.js.map} +1 -1
- package/dist/{chunk-LTUTK2Q3.js → chunk-7ZWLZ5H3.js} +35 -22
- 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-BWCGSGAC.js → chunk-TCNYSHPM.js} +165 -28
- 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 +688 -480
- 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/sdk/store.js +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/index.js +1 -1
- package/dist/store/src/store.d.ts.map +1 -1
- 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-6IDBWPK2.js.map +0 -1
- package/dist/chunk-BWCGSGAC.js.map +0 -1
- package/dist/chunk-EBSIZYM6.js.map +0 -1
- package/dist/chunk-JXHULIOA.js.map +0 -1
- package/dist/chunk-LTUTK2Q3.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,17 +178,38 @@ 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(
|
|
199
|
+
"--link",
|
|
200
|
+
"symlink local-path assets instead of copying (dev loop; machine-local, not for committing)"
|
|
201
|
+
).action(async (ref, opts) => {
|
|
202
|
+
const backends = parseBackendFilter(opts.backend);
|
|
162
203
|
const am2 = new AssetManager({
|
|
163
204
|
projectDir: path14__default.resolve(opts.projectDir),
|
|
164
|
-
global: opts.global,
|
|
205
|
+
global: opts.global || backends !== void 0,
|
|
206
|
+
backends,
|
|
165
207
|
driverTarget: opts.target
|
|
166
208
|
});
|
|
167
209
|
const spinner5 = p6.spinner();
|
|
168
210
|
spinner5.start(`Adding ${ref}`);
|
|
169
211
|
try {
|
|
170
|
-
const added = await am2.add(ref);
|
|
212
|
+
const added = await am2.add(ref, { link: opts.link });
|
|
171
213
|
spinner5.stop("Done");
|
|
172
214
|
if (added.length === 0) {
|
|
173
215
|
const kind = parseAssetRef(ref).kind;
|
|
@@ -185,10 +227,15 @@ function makeAddCommand() {
|
|
|
185
227
|
});
|
|
186
228
|
}
|
|
187
229
|
function makeRemoveCommand() {
|
|
188
|
-
return new Command("remove").description("Remove from skaile.yaml + undeploy").argument("<ref>", "Asset reference (kind:name)").option("--project-dir <path>", "Project directory", process.cwd()).option("--global", "Remove from
|
|
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);
|
|
189
235
|
const am2 = new AssetManager({
|
|
190
236
|
projectDir: path14__default.resolve(opts.projectDir),
|
|
191
|
-
global: opts.global,
|
|
237
|
+
global: opts.global || backends !== void 0,
|
|
238
|
+
backends,
|
|
192
239
|
driverTarget: opts.target
|
|
193
240
|
});
|
|
194
241
|
const ok = am2.remove(ref);
|
|
@@ -203,12 +250,19 @@ function stateLabel(s) {
|
|
|
203
250
|
return S.dim(s);
|
|
204
251
|
}
|
|
205
252
|
function makeListCommand() {
|
|
206
|
-
return new Command("list").description("List declared dependencies from skaile.yaml with state").argument("[kind]", "Filter by asset kind").option("--project-dir <path>", "Project directory", process.cwd()).option(
|
|
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(
|
|
207
257
|
new Option("--target <agent>", "Driver target").default("claude-code").choices(SUPPORTED_DRIVER_TARGETS)
|
|
208
258
|
).action((kind, opts) => {
|
|
259
|
+
const backends = parseBackendFilter(opts.backend);
|
|
260
|
+
if (opts.global || backends) {
|
|
261
|
+
runGlobalList(kind, opts, backends);
|
|
262
|
+
return;
|
|
263
|
+
}
|
|
209
264
|
const am2 = new AssetManager({
|
|
210
265
|
projectDir: path14__default.resolve(opts.projectDir),
|
|
211
|
-
global: opts.global,
|
|
212
266
|
driverTarget: opts.target
|
|
213
267
|
});
|
|
214
268
|
let declared;
|
|
@@ -251,6 +305,47 @@ function makeListCommand() {
|
|
|
251
305
|
console.log();
|
|
252
306
|
});
|
|
253
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
|
+
}
|
|
254
349
|
function makeInfoCommand() {
|
|
255
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) => {
|
|
256
351
|
const am2 = new AssetManager({ projectDir: path14__default.resolve(opts.projectDir) });
|
|
@@ -512,9 +607,9 @@ function makeAssetCommand() {
|
|
|
512
607
|
});
|
|
513
608
|
logOk(`${up.added ? "Added" : "Updated"} manifest entry skill:${norm.name}`);
|
|
514
609
|
if (target.backend === "git" && opts.commit) {
|
|
515
|
-
const { spawnSync
|
|
516
|
-
|
|
517
|
-
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}`], {
|
|
518
613
|
cwd: target.path,
|
|
519
614
|
stdio: "inherit"
|
|
520
615
|
});
|
|
@@ -582,9 +677,9 @@ function makeAssetCommand() {
|
|
|
582
677
|
break;
|
|
583
678
|
}
|
|
584
679
|
if (target.backend === "git" && opts.commit) {
|
|
585
|
-
const { spawnSync
|
|
586
|
-
|
|
587
|
-
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}`], {
|
|
588
683
|
cwd: target.path,
|
|
589
684
|
stdio: "inherit"
|
|
590
685
|
});
|
|
@@ -829,7 +924,7 @@ function makeCatalogCommand() {
|
|
|
829
924
|
return catalog;
|
|
830
925
|
}
|
|
831
926
|
async function runLocalCatalogTest(projectDir) {
|
|
832
|
-
const { resolveCatalogSource } = await import('../open-library-
|
|
927
|
+
const { resolveCatalogSource } = await import('../open-library-ERKRGH4B.js');
|
|
833
928
|
let resolved;
|
|
834
929
|
try {
|
|
835
930
|
resolved = await resolveCatalogSource({ projectDir });
|
|
@@ -1080,13 +1175,13 @@ function collectWorkspaceDefaults(projectDir) {
|
|
|
1080
1175
|
const wsDefaults = {};
|
|
1081
1176
|
try {
|
|
1082
1177
|
const ws = resolveSkWorkspaceConfig(projectDir);
|
|
1083
|
-
const
|
|
1084
|
-
if (
|
|
1085
|
-
if (
|
|
1086
|
-
if (
|
|
1087
|
-
if (
|
|
1088
|
-
if (
|
|
1089
|
-
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;
|
|
1090
1185
|
} catch {
|
|
1091
1186
|
}
|
|
1092
1187
|
return wsDefaults;
|
|
@@ -1819,7 +1914,7 @@ async function ensureTargetsRegistered(projectDir) {
|
|
|
1819
1914
|
const { resolveSkWorkspaceConfig: resolveSkWorkspaceConfig2 } = await import('../core/index.js');
|
|
1820
1915
|
const config = resolveSkWorkspaceConfig2(projectDir);
|
|
1821
1916
|
if (config.plugins && config.plugins.length > 0) {
|
|
1822
|
-
const { ensurePluginsLoaded } = await import('../plugin-store-
|
|
1917
|
+
const { ensurePluginsLoaded } = await import('../plugin-store-SGNJTBYS.js');
|
|
1823
1918
|
const result = await ensurePluginsLoaded(projectDir, config.plugins, pluginRegistry);
|
|
1824
1919
|
for (const f of result.failed) logWarn(f.error);
|
|
1825
1920
|
}
|
|
@@ -2028,10 +2123,10 @@ var MCP_SERVER_ENTRY = {
|
|
|
2028
2123
|
function pluginDir(projectDir) {
|
|
2029
2124
|
return path14__default.join(projectDir, ".claude", "plugins", "skaile");
|
|
2030
2125
|
}
|
|
2031
|
-
async function readJsonStrict(
|
|
2126
|
+
async function readJsonStrict(p8) {
|
|
2032
2127
|
let raw;
|
|
2033
2128
|
try {
|
|
2034
|
-
raw = await fs6.readFile(
|
|
2129
|
+
raw = await fs6.readFile(p8, "utf-8");
|
|
2035
2130
|
} catch {
|
|
2036
2131
|
return null;
|
|
2037
2132
|
}
|
|
@@ -2039,13 +2134,13 @@ async function readJsonStrict(p9) {
|
|
|
2039
2134
|
return JSON.parse(raw);
|
|
2040
2135
|
} catch (e) {
|
|
2041
2136
|
throw new Error(
|
|
2042
|
-
`cannot parse ${
|
|
2137
|
+
`cannot parse ${p8}: ${e instanceof Error ? e.message : String(e)}; please fix or remove`
|
|
2043
2138
|
);
|
|
2044
2139
|
}
|
|
2045
2140
|
}
|
|
2046
|
-
async function writeJson(
|
|
2047
|
-
await fs6.mkdir(path14__default.dirname(
|
|
2048
|
-
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)}
|
|
2049
2144
|
`);
|
|
2050
2145
|
}
|
|
2051
2146
|
async function copyDir(src, dest) {
|
|
@@ -2100,7 +2195,7 @@ async function uninstall(projectDir) {
|
|
|
2100
2195
|
let changed = false;
|
|
2101
2196
|
const settings = await readJsonStrict(settingsPath);
|
|
2102
2197
|
if (settings && Array.isArray(settings.plugins)) {
|
|
2103
|
-
const next = settings.plugins.filter((
|
|
2198
|
+
const next = settings.plugins.filter((p8) => p8 !== dir);
|
|
2104
2199
|
if (next.length !== settings.plugins.length) {
|
|
2105
2200
|
changed = true;
|
|
2106
2201
|
const updated = { ...settings, plugins: next };
|
|
@@ -2147,7 +2242,7 @@ async function enable(projectDir) {
|
|
|
2147
2242
|
const settings = await readJsonStrict(settingsPath) ?? {};
|
|
2148
2243
|
if (detected.method === "plugin") {
|
|
2149
2244
|
const disabled2 = settings.disabledPlugins ?? [];
|
|
2150
|
-
const next2 = disabled2.filter((
|
|
2245
|
+
const next2 = disabled2.filter((p8) => p8 !== detected.pluginPath);
|
|
2151
2246
|
if (next2.length === disabled2.length) return { changed: false };
|
|
2152
2247
|
const updated2 = { ...settings, disabledPlugins: next2 };
|
|
2153
2248
|
if (next2.length === 0) delete updated2.disabledPlugins;
|
|
@@ -2228,10 +2323,10 @@ function buildEntry(projectDir) {
|
|
|
2228
2323
|
env: { SKAILE_PROJECT_DIR: projectDir }
|
|
2229
2324
|
};
|
|
2230
2325
|
}
|
|
2231
|
-
async function readConfig(
|
|
2326
|
+
async function readConfig(p8) {
|
|
2232
2327
|
let raw;
|
|
2233
2328
|
try {
|
|
2234
|
-
raw = await fs6.readFile(
|
|
2329
|
+
raw = await fs6.readFile(p8, "utf-8");
|
|
2235
2330
|
} catch {
|
|
2236
2331
|
return null;
|
|
2237
2332
|
}
|
|
@@ -2239,41 +2334,41 @@ async function readConfig(p9) {
|
|
|
2239
2334
|
return parse$1(raw);
|
|
2240
2335
|
} catch (e) {
|
|
2241
2336
|
throw new Error(
|
|
2242
|
-
`cannot parse ${
|
|
2337
|
+
`cannot parse ${p8}: ${e instanceof Error ? e.message : String(e)}; please fix or remove`
|
|
2243
2338
|
);
|
|
2244
2339
|
}
|
|
2245
2340
|
}
|
|
2246
|
-
async function writeConfig(
|
|
2247
|
-
await fs6.mkdir(path14__default.dirname(
|
|
2341
|
+
async function writeConfig(p8, value) {
|
|
2342
|
+
await fs6.mkdir(path14__default.dirname(p8), { recursive: true });
|
|
2248
2343
|
const cleaned = {};
|
|
2249
2344
|
for (const [k, v] of Object.entries(value)) {
|
|
2250
2345
|
if (v === void 0) continue;
|
|
2251
2346
|
cleaned[k] = v;
|
|
2252
2347
|
}
|
|
2253
|
-
await fs6.writeFile(
|
|
2348
|
+
await fs6.writeFile(p8, stringify$1(cleaned));
|
|
2254
2349
|
}
|
|
2255
2350
|
function configPath(projectDir) {
|
|
2256
2351
|
return path14__default.join(projectDir, ".codex", "config.toml");
|
|
2257
2352
|
}
|
|
2258
2353
|
async function install2(projectDir) {
|
|
2259
|
-
const
|
|
2260
|
-
const cfg = await readConfig(
|
|
2354
|
+
const p8 = configPath(projectDir);
|
|
2355
|
+
const cfg = await readConfig(p8) ?? {};
|
|
2261
2356
|
const next = buildEntry(projectDir);
|
|
2262
2357
|
const servers = { ...cfg.mcp_servers ?? {} };
|
|
2263
2358
|
const previous = servers[SKAILE_MCP_NAME2];
|
|
2264
2359
|
const matches = previous && JSON.stringify(previous) === JSON.stringify(next);
|
|
2265
2360
|
let warning;
|
|
2266
2361
|
if (previous && !matches) {
|
|
2267
|
-
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)}`;
|
|
2268
2363
|
}
|
|
2269
2364
|
if (matches) return { changed: false, method: "toml" };
|
|
2270
2365
|
servers[SKAILE_MCP_NAME2] = next;
|
|
2271
|
-
await writeConfig(
|
|
2366
|
+
await writeConfig(p8, { ...cfg, mcp_servers: servers });
|
|
2272
2367
|
return { changed: true, method: "toml", warning };
|
|
2273
2368
|
}
|
|
2274
2369
|
async function uninstall2(projectDir) {
|
|
2275
|
-
const
|
|
2276
|
-
const cfg = await readConfig(
|
|
2370
|
+
const p8 = configPath(projectDir);
|
|
2371
|
+
const cfg = await readConfig(p8);
|
|
2277
2372
|
if (!cfg?.mcp_servers || !(SKAILE_MCP_NAME2 in cfg.mcp_servers)) {
|
|
2278
2373
|
return { changed: false };
|
|
2279
2374
|
}
|
|
@@ -2281,15 +2376,15 @@ async function uninstall2(projectDir) {
|
|
|
2281
2376
|
const updated = { ...cfg, mcp_servers: rest };
|
|
2282
2377
|
if (Object.keys(rest).length === 0) delete updated.mcp_servers;
|
|
2283
2378
|
if (Object.keys(updated).length === 0) {
|
|
2284
|
-
await fs6.unlink(
|
|
2379
|
+
await fs6.unlink(p8);
|
|
2285
2380
|
} else {
|
|
2286
|
-
await writeConfig(
|
|
2381
|
+
await writeConfig(p8, updated);
|
|
2287
2382
|
}
|
|
2288
2383
|
return { changed: true };
|
|
2289
2384
|
}
|
|
2290
2385
|
async function status2(projectDir) {
|
|
2291
|
-
const
|
|
2292
|
-
const cfg = await readConfig(
|
|
2386
|
+
const p8 = configPath(projectDir);
|
|
2387
|
+
const cfg = await readConfig(p8);
|
|
2293
2388
|
const installed = !!(cfg?.mcp_servers && SKAILE_MCP_NAME2 in cfg.mcp_servers);
|
|
2294
2389
|
if (!installed) {
|
|
2295
2390
|
return {
|
|
@@ -2305,7 +2400,7 @@ async function status2(projectDir) {
|
|
|
2305
2400
|
installed: "yes",
|
|
2306
2401
|
enabled: "n/a",
|
|
2307
2402
|
method: "mcp",
|
|
2308
|
-
location: path14__default.relative(projectDir,
|
|
2403
|
+
location: path14__default.relative(projectDir, p8)
|
|
2309
2404
|
};
|
|
2310
2405
|
}
|
|
2311
2406
|
async function install3(projectDir) {
|
|
@@ -2522,7 +2617,7 @@ function printStatusTable(rows) {
|
|
|
2522
2617
|
const widths = cols.map(
|
|
2523
2618
|
(c) => Math.max(c.header.length, ...rows.map((r) => String(r[c.key] ?? "").length))
|
|
2524
2619
|
);
|
|
2525
|
-
const fmtRow = (parts) => parts.map((
|
|
2620
|
+
const fmtRow = (parts) => parts.map((p8, i) => p8.padEnd(widths[i] ?? p8.length)).join(" ");
|
|
2526
2621
|
console.log();
|
|
2527
2622
|
console.log(` ${S.heading(fmtRow(cols.map((c) => c.header)))}`);
|
|
2528
2623
|
for (const r of rows) {
|
|
@@ -2977,9 +3072,9 @@ function makeLibraryCommand() {
|
|
|
2977
3072
|
logErr("`library commit` only applies to git-backed libraries.");
|
|
2978
3073
|
process.exit(1);
|
|
2979
3074
|
}
|
|
2980
|
-
const { spawnSync
|
|
2981
|
-
|
|
2982
|
-
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], {
|
|
2983
3078
|
cwd: lib.path,
|
|
2984
3079
|
stdio: "inherit"
|
|
2985
3080
|
});
|
|
@@ -2997,8 +3092,8 @@ function makeLibraryCommand() {
|
|
|
2997
3092
|
const { manager, close } = await openLibraryManager();
|
|
2998
3093
|
try {
|
|
2999
3094
|
const lib = await manager.requireLibrary(name);
|
|
3000
|
-
const { spawnSync
|
|
3001
|
-
const r =
|
|
3095
|
+
const { spawnSync } = await import('child_process');
|
|
3096
|
+
const r = spawnSync("git", args, { cwd: lib.path, stdio: "inherit" });
|
|
3002
3097
|
process.exit(r.status ?? 0);
|
|
3003
3098
|
} finally {
|
|
3004
3099
|
close();
|
|
@@ -3261,6 +3356,8 @@ var ORIGIN_META = {
|
|
|
3261
3356
|
var ORIGIN_ORDER = ["library", "source", "factory", "store"];
|
|
3262
3357
|
var srcKey = (origin, publisher) => `${origin}:${publisher}`;
|
|
3263
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}`;
|
|
3264
3361
|
var NO_DOMAIN = "";
|
|
3265
3362
|
var domainRegistry = /* @__PURE__ */ new Map();
|
|
3266
3363
|
function relationBadge(relation) {
|
|
@@ -3289,12 +3386,20 @@ var state = {
|
|
|
3289
3386
|
sourceRows: [],
|
|
3290
3387
|
libraryRows: [],
|
|
3291
3388
|
visibleRows: [],
|
|
3389
|
+
sourceTreeRows: [],
|
|
3390
|
+
visibleSourceRows: [],
|
|
3292
3391
|
pendingAdds: /* @__PURE__ */ new Set(),
|
|
3293
3392
|
pendingRemoves: /* @__PURE__ */ new Set(),
|
|
3294
3393
|
collapsedOrigins: /* @__PURE__ */ new Set(),
|
|
3295
3394
|
collapsedSources: /* @__PURE__ */ new Set(),
|
|
3296
3395
|
collapsedDomains: /* @__PURE__ */ new Set(),
|
|
3297
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(),
|
|
3298
3403
|
seenOrigins: /* @__PURE__ */ new Set(),
|
|
3299
3404
|
originFilter: null,
|
|
3300
3405
|
message: "",
|
|
@@ -3308,13 +3413,13 @@ function buildVisibleRows(rows, collapsedOrigins, collapsedSources, collapsedDom
|
|
|
3308
3413
|
if (row.type === "origin-header") return true;
|
|
3309
3414
|
if (collapsedOrigins.has(origin)) return false;
|
|
3310
3415
|
if (row.type === "publisher-header") return true;
|
|
3311
|
-
if (collapsedSources.has(srcKey(origin,
|
|
3416
|
+
if (collapsedSources.has(srcKey(origin, rowGroup(row)))) return false;
|
|
3312
3417
|
if (row.type === "domain-header") return true;
|
|
3313
3418
|
if (row.type === "domain-info") {
|
|
3314
3419
|
return !collapsedDomains.has(domainKey(origin, row.source, row.domainSlug ?? NO_DOMAIN));
|
|
3315
3420
|
}
|
|
3316
3421
|
if (row.underDomain) {
|
|
3317
|
-
return !collapsedDomains.has(domainKey(origin,
|
|
3422
|
+
return !collapsedDomains.has(domainKey(origin, rowGroup(row), rowDomain(row)));
|
|
3318
3423
|
}
|
|
3319
3424
|
return true;
|
|
3320
3425
|
});
|
|
@@ -3328,6 +3433,80 @@ function domainAssetRefs(rows, origin, publisher, slug) {
|
|
|
3328
3433
|
function sourceAssetRefs(rows, origin, source) {
|
|
3329
3434
|
return refsOf(rows.filter((r) => isAsset(r) && inSource(r, origin, source)));
|
|
3330
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
|
+
}
|
|
3331
3510
|
function isAsset(r) {
|
|
3332
3511
|
return r.type === "asset";
|
|
3333
3512
|
}
|
|
@@ -3337,14 +3516,24 @@ function rowOrigin(r) {
|
|
|
3337
3516
|
function rowPublisher(r) {
|
|
3338
3517
|
return r.entry?.publisher || "other";
|
|
3339
3518
|
}
|
|
3519
|
+
function rowGroup(r) {
|
|
3520
|
+
return r.source ?? rowPublisher(r);
|
|
3521
|
+
}
|
|
3340
3522
|
function rowDomain(r) {
|
|
3341
3523
|
return r.entry?.domainSlug || NO_DOMAIN;
|
|
3342
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
|
+
}
|
|
3343
3532
|
function refsOf(rows) {
|
|
3344
3533
|
return rows.map((r) => assetRefOf(r)).filter((ref) => ref !== null);
|
|
3345
3534
|
}
|
|
3346
3535
|
function inSource(r, origin, source) {
|
|
3347
|
-
return rowOrigin(r) === origin &&
|
|
3536
|
+
return rowOrigin(r) === origin && rowGroup(r) === source;
|
|
3348
3537
|
}
|
|
3349
3538
|
function inDomain(r, origin, publisher, slug) {
|
|
3350
3539
|
if (!inSource(r, origin, publisher)) return false;
|
|
@@ -3405,7 +3594,7 @@ function actOnHeader(row, action3) {
|
|
|
3405
3594
|
return row.type === "domain-header" || row.type === "domain-info";
|
|
3406
3595
|
}
|
|
3407
3596
|
async function loadAssets() {
|
|
3408
|
-
const { gatherAssetFeeds } = await import('../asset-feeds-
|
|
3597
|
+
const { gatherAssetFeeds } = await import('../asset-feeds-OEGJ6NOF.js');
|
|
3409
3598
|
const { entries, domains, notes } = await gatherAssetFeeds(am, am.projectDir);
|
|
3410
3599
|
if (notes.length > 0) {
|
|
3411
3600
|
state.message = notes.map((n) => `[${n.feed}] ${n.message}`).join(" \u2022 ");
|
|
@@ -3417,11 +3606,60 @@ async function loadAssets() {
|
|
|
3417
3606
|
state.assetRows = rows;
|
|
3418
3607
|
reconcileCollapsedSets(rows);
|
|
3419
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();
|
|
3420
3658
|
}
|
|
3421
3659
|
function groupEntriesByOriginPublisherDomain(entries) {
|
|
3422
3660
|
const byOrigin = /* @__PURE__ */ new Map();
|
|
3423
|
-
for (const { origin, entry } of entries) {
|
|
3424
|
-
const publisher = entry.publisher || "other";
|
|
3661
|
+
for (const { origin, entry, group } of entries) {
|
|
3662
|
+
const publisher = group || entry.publisher || "other";
|
|
3425
3663
|
const slug = entry.domainSlug || NO_DOMAIN;
|
|
3426
3664
|
if (!byOrigin.has(origin)) byOrigin.set(origin, /* @__PURE__ */ new Map());
|
|
3427
3665
|
const byPublisher = byOrigin.get(origin);
|
|
@@ -3444,29 +3682,40 @@ function buildAssetRowsFromGroups(byOrigin, installed) {
|
|
|
3444
3682
|
const sortItems = (items) => items.sort(
|
|
3445
3683
|
(a, b) => a.kind !== b.kind ? a.kind.localeCompare(b.kind) : a.name.localeCompare(b.name)
|
|
3446
3684
|
);
|
|
3447
|
-
const pushAsset = (origin, entry, underDomain, seq) => {
|
|
3685
|
+
const pushAsset = (origin, group, entry, underDomain, seq) => {
|
|
3448
3686
|
const ref = `${entry.kind}:${entry.name}`;
|
|
3449
|
-
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
|
+
});
|
|
3450
3697
|
};
|
|
3451
3698
|
for (const origin of ORIGIN_ORDER) {
|
|
3452
|
-
const
|
|
3453
|
-
if (!
|
|
3699
|
+
const byGroup = byOrigin.get(origin);
|
|
3700
|
+
if (!byGroup || byGroup.size === 0) continue;
|
|
3454
3701
|
rows.push({ type: "origin-header", origin });
|
|
3455
|
-
for (const [
|
|
3702
|
+
for (const [group, byDomain] of [...byGroup.entries()].sort(
|
|
3456
3703
|
(a, b) => a[0].localeCompare(b[0])
|
|
3457
3704
|
)) {
|
|
3458
|
-
rows.push({ type: "publisher-header", origin, source:
|
|
3705
|
+
rows.push({ type: "publisher-header", origin, source: group });
|
|
3459
3706
|
const loose = byDomain.get(NO_DOMAIN);
|
|
3460
|
-
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);
|
|
3461
3708
|
for (const slug of sortedDomainSlugs([...byDomain.keys()])) {
|
|
3462
3709
|
const meta = domainRegistry.get(slug);
|
|
3463
|
-
rows.push({ type: "domain-header", origin, source:
|
|
3710
|
+
rows.push({ type: "domain-header", origin, source: group, domainSlug: slug });
|
|
3464
3711
|
if (meta?.description) {
|
|
3465
|
-
rows.push({ type: "domain-info", origin, source:
|
|
3712
|
+
rows.push({ type: "domain-info", origin, source: group, domainSlug: slug });
|
|
3466
3713
|
}
|
|
3467
3714
|
const items = sortItems(byDomain.get(slug));
|
|
3468
3715
|
const sequenced = meta?.relation === "sequence";
|
|
3469
|
-
items.forEach(
|
|
3716
|
+
items.forEach(
|
|
3717
|
+
(entry, i) => pushAsset(origin, group, entry, true, sequenced ? i + 1 : void 0)
|
|
3718
|
+
);
|
|
3470
3719
|
}
|
|
3471
3720
|
}
|
|
3472
3721
|
}
|
|
@@ -3493,17 +3742,26 @@ function reconcileCollapsedSets(rows) {
|
|
|
3493
3742
|
const newDomainKeys = new Set(
|
|
3494
3743
|
rows.filter((r) => r.type === "domain-header").map((r) => domainKey(rowOrigin(r), r.source, r.domainSlug ?? NO_DOMAIN))
|
|
3495
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
|
+
}
|
|
3496
3751
|
for (const d of state.collapsedDomains) {
|
|
3497
3752
|
if (!newDomainKeys.has(d)) state.collapsedDomains.delete(d);
|
|
3498
3753
|
}
|
|
3499
3754
|
for (const d of state.expandedDomainInfo) {
|
|
3500
3755
|
if (!newDomainKeys.has(d)) state.expandedDomainInfo.delete(d);
|
|
3501
3756
|
}
|
|
3757
|
+
for (const d of state.seenDomains) {
|
|
3758
|
+
if (!newDomainKeys.has(d)) state.seenDomains.delete(d);
|
|
3759
|
+
}
|
|
3502
3760
|
}
|
|
3503
3761
|
async function loadSourcesAndLibraries() {
|
|
3504
3762
|
try {
|
|
3505
3763
|
const [{ openLibraryManager: openLibraryManager2 }, { skaileHomeDir }, { getGlobalCacheDir: getGlobalCacheDir2 }] = await Promise.all([
|
|
3506
|
-
import('../open-library-
|
|
3764
|
+
import('../open-library-ERKRGH4B.js'),
|
|
3507
3765
|
import('../library/index.js'),
|
|
3508
3766
|
import('../core/index.js')
|
|
3509
3767
|
]);
|
|
@@ -3539,6 +3797,7 @@ async function loadSourcesAndLibraries() {
|
|
|
3539
3797
|
state.sourceRows = [];
|
|
3540
3798
|
state.libraryRows = [];
|
|
3541
3799
|
}
|
|
3800
|
+
rebuildSourceTree();
|
|
3542
3801
|
}
|
|
3543
3802
|
function rebuildVisible() {
|
|
3544
3803
|
state.visibleRows = buildVisibleRows(
|
|
@@ -3574,11 +3833,11 @@ var TABS = {
|
|
|
3574
3833
|
},
|
|
3575
3834
|
sources: {
|
|
3576
3835
|
label: "Sources",
|
|
3577
|
-
rowCount: () => state.
|
|
3578
|
-
selectableCount: () => state.
|
|
3836
|
+
rowCount: () => state.visibleSourceRows.length,
|
|
3837
|
+
selectableCount: () => state.sourceTreeRows.filter(isAsset).length,
|
|
3579
3838
|
emptyMsg: " No sources registered. Run `skaile source add <git-url>` from the shell to track a github repo.",
|
|
3580
|
-
renderRow: (i, sel) =>
|
|
3581
|
-
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"
|
|
3582
3841
|
},
|
|
3583
3842
|
libraries: {
|
|
3584
3843
|
label: "Libraries",
|
|
@@ -3642,8 +3901,9 @@ function groupStatus(refs) {
|
|
|
3642
3901
|
}
|
|
3643
3902
|
function renderHeaderLine(opts) {
|
|
3644
3903
|
const indicator = opts.collapsed ? "\u25B6" : "\u25BC";
|
|
3645
|
-
const
|
|
3646
|
-
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;
|
|
3647
3907
|
const [add, remove] = pendingCountsFor(opts.match);
|
|
3648
3908
|
let count = String(installed);
|
|
3649
3909
|
if (add > 0) count += pc5.green(`+${add}`);
|
|
@@ -3682,8 +3942,8 @@ function renderAssetRow(row, selected) {
|
|
|
3682
3942
|
const slug = row.domainSlug ?? NO_DOMAIN;
|
|
3683
3943
|
const meta = domainRegistry.get(slug);
|
|
3684
3944
|
const title = meta?.title || slug || "(no domain)";
|
|
3685
|
-
const
|
|
3686
|
-
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}` : ""}`;
|
|
3687
3947
|
return renderHeaderLine({
|
|
3688
3948
|
indent: " ".repeat(5),
|
|
3689
3949
|
collapsed: state.collapsedDomains.has(domainKey(origin, row.source, slug)),
|
|
@@ -3697,15 +3957,18 @@ function renderAssetRow(row, selected) {
|
|
|
3697
3957
|
const origin = rowOrigin(row);
|
|
3698
3958
|
const slug = row.domainSlug ?? NO_DOMAIN;
|
|
3699
3959
|
const key = domainKey(origin, row.source, slug);
|
|
3700
|
-
const
|
|
3960
|
+
const line = renderDomainInfoLine(
|
|
3701
3961
|
domainRegistry.get(slug),
|
|
3702
3962
|
origin,
|
|
3703
3963
|
row.source,
|
|
3704
3964
|
slug,
|
|
3705
3965
|
state.expandedDomainInfo.has(key)
|
|
3706
3966
|
);
|
|
3707
|
-
return selected ? pc5.inverse(
|
|
3967
|
+
return selected ? pc5.inverse(line.padEnd(state.cols)) : line;
|
|
3708
3968
|
}
|
|
3969
|
+
return renderAssetLeaf(row, selected);
|
|
3970
|
+
}
|
|
3971
|
+
function renderAssetLeaf(row, selected, looseIndent = 5) {
|
|
3709
3972
|
const e = row.entry;
|
|
3710
3973
|
const ref = assetRefOf(row) ?? "";
|
|
3711
3974
|
let status4;
|
|
@@ -3727,10 +3990,86 @@ function renderAssetRow(row, selected) {
|
|
|
3727
3990
|
const repoBadge = repoBare ? pc5.dim(` \xB7${repoBare}`) : "";
|
|
3728
3991
|
const repoWidth = repoBare ? repoBare.length + 2 : 0;
|
|
3729
3992
|
const desc = e.description?.slice(0, Math.max(0, state.cols - 56 - badgeWidth - hintWidth - repoWidth)) ?? "";
|
|
3730
|
-
const indent = " ".repeat(row.underDomain ?
|
|
3993
|
+
const indent = " ".repeat(looseIndent + (row.underDomain ? 2 : 0));
|
|
3731
3994
|
const line = `${indent}${status4} ${hint}${kind} ${name} ${badge}${pc5.dim(desc)}${repoBadge}`;
|
|
3732
3995
|
return selected ? pc5.inverse(line.padEnd(state.cols)) : line;
|
|
3733
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
|
+
}
|
|
3734
4073
|
function renderDomainInfoLine(meta, origin, publisher, slug, expanded) {
|
|
3735
4074
|
const indent = " ".repeat(7);
|
|
3736
4075
|
const desc = meta?.description ?? "";
|
|
@@ -3748,10 +4087,6 @@ function renderDomainInfoLine(meta, origin, publisher, slug, expanded) {
|
|
|
3748
4087
|
const shown = full.length > budget ? `${full.slice(0, Math.max(0, budget - 1))}\u2026` : full;
|
|
3749
4088
|
return pc5.dim(`${indent}\u24D8 ${shown}`);
|
|
3750
4089
|
}
|
|
3751
|
-
function renderSourceRow(row, selected) {
|
|
3752
|
-
const line = ` ${S.cmd(fitWidth(row.name, 20))} ${pc5.dim(row.ownership.padEnd(12))} ${pc5.dim(`${row.assetCount} assets`)} ${pc5.dim(row.path)}`;
|
|
3753
|
-
return selected ? pc5.inverse(line.padEnd(state.cols)) : line;
|
|
3754
|
-
}
|
|
3755
4090
|
function renderLibraryRow(row, selected) {
|
|
3756
4091
|
const mark = row.isDefault ? pc5.green("\u25B8") : " ";
|
|
3757
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`)}`;
|
|
@@ -3855,19 +4190,15 @@ async function syncAll() {
|
|
|
3855
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."
|
|
3856
4191
|
);
|
|
3857
4192
|
}
|
|
3858
|
-
function sourceShellHint(action3) {
|
|
3859
|
-
state.message = pc5.yellow(
|
|
3860
|
-
`${action3} is a shell command. Run \`skaile source \u2026\` from the shell.`
|
|
3861
|
-
);
|
|
3862
|
-
}
|
|
3863
4193
|
function libraryShellHint(action3) {
|
|
3864
4194
|
state.message = pc5.yellow(
|
|
3865
4195
|
`${action3} is a shell command. Run \`skaile library \u2026\` from the shell.`
|
|
3866
4196
|
);
|
|
3867
4197
|
}
|
|
3868
4198
|
async function showInfo() {
|
|
3869
|
-
|
|
3870
|
-
|
|
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];
|
|
3871
4202
|
if (row?.type !== "asset") return;
|
|
3872
4203
|
const e = row.entry;
|
|
3873
4204
|
clearScreen();
|
|
@@ -3995,6 +4326,115 @@ function toggleDomainInfoUnderCursor() {
|
|
|
3995
4326
|
else state.expandedDomainInfo.add(key);
|
|
3996
4327
|
rebuildVisible();
|
|
3997
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
|
+
}
|
|
3998
4438
|
function findLastIndex(arr, endExclusive, pred) {
|
|
3999
4439
|
for (let i = Math.min(endExclusive, arr.length) - 1; i >= 0; i--) {
|
|
4000
4440
|
if (pred(arr[i])) return i;
|
|
@@ -4022,9 +4462,12 @@ var KEYMAP = [
|
|
|
4022
4462
|
{ keys: [" "], run: () => void nextTab() },
|
|
4023
4463
|
{ keys: ["\x1B[A", "k"], run: () => void moveCursor(-1) },
|
|
4024
4464
|
{ keys: ["\x1B[B", "j"], run: () => void moveCursor(1) },
|
|
4025
|
-
// Collapse / expand — assets tab
|
|
4465
|
+
// Collapse / expand — assets tab
|
|
4026
4466
|
{ keys: ["\x1B[C"], when: TAB_ASSETS, run: expandUnderCursor },
|
|
4027
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 },
|
|
4028
4471
|
// + : assets → bulk-add or single-add toggle
|
|
4029
4472
|
{
|
|
4030
4473
|
keys: ["+"],
|
|
@@ -4038,10 +4481,13 @@ var KEYMAP = [
|
|
|
4038
4481
|
}
|
|
4039
4482
|
}
|
|
4040
4483
|
},
|
|
4041
|
-
// Sources tab:
|
|
4042
|
-
{ keys: ["+"
|
|
4043
|
-
{ keys: ["-"
|
|
4044
|
-
{ 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 },
|
|
4045
4491
|
// Libraries tab: +/-/n/r/x/d/enter map to shell hints in the minimal scaffold.
|
|
4046
4492
|
{
|
|
4047
4493
|
keys: ["+", "n", "a"],
|
|
@@ -4151,8 +4597,8 @@ function makeManageCommand() {
|
|
|
4151
4597
|
}
|
|
4152
4598
|
function makeMcpServerCommand() {
|
|
4153
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) => {
|
|
4154
|
-
const
|
|
4155
|
-
const projectDir =
|
|
4600
|
+
const path36 = await import('path');
|
|
4601
|
+
const projectDir = path36.default.resolve(opts.projectDir);
|
|
4156
4602
|
const { LogStore, StdoutSink, registerLogStore } = await import('../core/logging.js');
|
|
4157
4603
|
registerLogStore(
|
|
4158
4604
|
new LogStore({
|
|
@@ -4368,7 +4814,7 @@ function action2(fn) {
|
|
|
4368
4814
|
};
|
|
4369
4815
|
}
|
|
4370
4816
|
async function reconcileAndReport(projectDir, plugins) {
|
|
4371
|
-
const { reconcilePlugins } = await import('../plugin-store-
|
|
4817
|
+
const { reconcilePlugins } = await import('../plugin-store-SGNJTBYS.js');
|
|
4372
4818
|
if (plugins.length === 0) {
|
|
4373
4819
|
logInfo("No plugins declared \u2014 nothing to reconcile.");
|
|
4374
4820
|
return;
|
|
@@ -4384,7 +4830,7 @@ async function reconcileAndReport(projectDir, plugins) {
|
|
|
4384
4830
|
async function runInstall2(spec, opts) {
|
|
4385
4831
|
const projectDir = path14__default.resolve(opts.projectDir);
|
|
4386
4832
|
const { WorkspaceYamlEditor: WorkspaceYamlEditor2 } = await import('../core/index.js');
|
|
4387
|
-
const { specName } = await import('../plugin-store-
|
|
4833
|
+
const { specName } = await import('../plugin-store-SGNJTBYS.js');
|
|
4388
4834
|
const yamlPath = path14__default.join(projectDir, "skaile.yaml");
|
|
4389
4835
|
const editor = WorkspaceYamlEditor2.load(yamlPath);
|
|
4390
4836
|
const replaced = editor.addPlugin(spec, specName);
|
|
@@ -4396,7 +4842,7 @@ async function runInstall2(spec, opts) {
|
|
|
4396
4842
|
async function runRemove(name, opts) {
|
|
4397
4843
|
const projectDir = path14__default.resolve(opts.projectDir);
|
|
4398
4844
|
const { WorkspaceYamlEditor: WorkspaceYamlEditor2 } = await import('../core/index.js');
|
|
4399
|
-
const { specName } = await import('../plugin-store-
|
|
4845
|
+
const { specName } = await import('../plugin-store-SGNJTBYS.js');
|
|
4400
4846
|
const yamlPath = path14__default.join(projectDir, "skaile.yaml");
|
|
4401
4847
|
const editor = WorkspaceYamlEditor2.load(yamlPath);
|
|
4402
4848
|
const removed = editor.removePlugin(name, specName);
|
|
@@ -4424,7 +4870,7 @@ async function runList(opts) {
|
|
|
4424
4870
|
const registry = createPluginRegistry();
|
|
4425
4871
|
if (declared.length > 0) {
|
|
4426
4872
|
try {
|
|
4427
|
-
const { loadPlugins } = await import('../plugin-store-
|
|
4873
|
+
const { loadPlugins } = await import('../plugin-store-SGNJTBYS.js');
|
|
4428
4874
|
const result = await loadPlugins(projectDir, declared, registry);
|
|
4429
4875
|
for (const f of result.failed) logWarn(f.error);
|
|
4430
4876
|
} catch (err) {
|
|
@@ -4639,7 +5085,29 @@ async function runPointerOnlyInstall(ref, deps) {
|
|
|
4639
5085
|
};
|
|
4640
5086
|
}
|
|
4641
5087
|
function makeInstallCommand() {
|
|
4642
|
-
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").
|
|
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(
|
|
5095
|
+
"--link",
|
|
5096
|
+
"symlink local-path assets instead of copying (dev loop; machine-local, not for committing)"
|
|
5097
|
+
).action(runInstallCommand);
|
|
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;
|
|
4643
5111
|
}
|
|
4644
5112
|
async function runInstallCommand(ref, opts) {
|
|
4645
5113
|
if (ref !== void 0) {
|
|
@@ -4656,7 +5124,7 @@ async function runRefInstall(ref, opts) {
|
|
|
4656
5124
|
const spinner5 = p6.spinner();
|
|
4657
5125
|
spinner5.start(`Installing ${ref}`);
|
|
4658
5126
|
try {
|
|
4659
|
-
const { openCatalogSource: openCatalogSource2, openLibrary: openLibrary2 } = await import('../open-library-
|
|
5127
|
+
const { openCatalogSource: openCatalogSource2, openLibrary: openLibrary2 } = await import('../open-library-ERKRGH4B.js');
|
|
4660
5128
|
const catalog = await openCatalogSource2({ projectDir: path14__default.resolve(opts.projectDir) });
|
|
4661
5129
|
if (!supportsInstallManifest(catalog)) {
|
|
4662
5130
|
throw new Error(
|
|
@@ -4687,8 +5155,13 @@ async function runRefInstall(ref, opts) {
|
|
|
4687
5155
|
}
|
|
4688
5156
|
async function runYamlInstall(opts) {
|
|
4689
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
|
+
}
|
|
4690
5163
|
try {
|
|
4691
|
-
const { ensureSourcesCloned } = await import('../ensure-sources-
|
|
5164
|
+
const { ensureSourcesCloned } = await import('../ensure-sources-GJOXWVWO.js');
|
|
4692
5165
|
const hydrate = ensureSourcesCloned(projectDir, { quiet: true });
|
|
4693
5166
|
if (hydrate.cloned.length > 0) {
|
|
4694
5167
|
logOk(`Cloned source(s): ${hydrate.cloned.join(", ")}`);
|
|
@@ -4706,7 +5179,7 @@ async function runYamlInstall(opts) {
|
|
|
4706
5179
|
const spinner5 = p6.spinner();
|
|
4707
5180
|
spinner5.start(opts.locked ? "Installing from lock file" : "Installing dependencies");
|
|
4708
5181
|
try {
|
|
4709
|
-
const result = await am2.install({ locked: opts.locked });
|
|
5182
|
+
const result = await am2.install({ locked: opts.locked, link: opts.link });
|
|
4710
5183
|
spinner5.stop("Done");
|
|
4711
5184
|
if (result.deployed.length > 0) {
|
|
4712
5185
|
for (const d of result.deployed) logOk(d);
|
|
@@ -4730,6 +5203,37 @@ async function runYamlInstall(opts) {
|
|
|
4730
5203
|
process.exit(1);
|
|
4731
5204
|
}
|
|
4732
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
|
+
}
|
|
4733
5237
|
function makeCheckCommand() {
|
|
4734
5238
|
return new Command("check").description("Check for unmet requirements").option("--project-dir <path>", "Project directory", process.cwd()).action((opts) => {
|
|
4735
5239
|
const am2 = new AssetManager({ projectDir: path14__default.resolve(opts.projectDir) });
|
|
@@ -4776,8 +5280,8 @@ function makeCleanCommand() {
|
|
|
4776
5280
|
return;
|
|
4777
5281
|
}
|
|
4778
5282
|
if (!opts.yes) {
|
|
4779
|
-
const
|
|
4780
|
-
if (p6.isCancel(
|
|
5283
|
+
const confirm6 = await p6.confirm({ message: "Proceed?" });
|
|
5284
|
+
if (p6.isCancel(confirm6) || !confirm6) {
|
|
4781
5285
|
logInfo("Cancelled.");
|
|
4782
5286
|
return;
|
|
4783
5287
|
}
|
|
@@ -5044,11 +5548,11 @@ function makeClearCommand() {
|
|
|
5044
5548
|
}
|
|
5045
5549
|
function makeReplCommand() {
|
|
5046
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) => {
|
|
5047
|
-
const { findWorkspaceRoot
|
|
5551
|
+
const { findWorkspaceRoot } = await import('../core/index.js');
|
|
5048
5552
|
const { startRepl } = await import('../tui/index.js');
|
|
5049
5553
|
const os2 = await import('os');
|
|
5050
5554
|
const userCwd = path14__default.resolve(opts.projectDir ?? process.cwd());
|
|
5051
|
-
const workspaceRoot =
|
|
5555
|
+
const workspaceRoot = findWorkspaceRoot(userCwd);
|
|
5052
5556
|
let projectDir;
|
|
5053
5557
|
let agentCwd;
|
|
5054
5558
|
let driverOverride = opts.driver;
|
|
@@ -5126,7 +5630,7 @@ async function ensurePluginsLoadedForServe(projectDir) {
|
|
|
5126
5630
|
const { resolveSkWorkspaceConfig: resolveSkWorkspaceConfig2 } = await import('../core/index.js');
|
|
5127
5631
|
const config = resolveSkWorkspaceConfig2(projectDir);
|
|
5128
5632
|
if (!config.plugins || config.plugins.length === 0) return;
|
|
5129
|
-
const { ensurePluginsLoaded } = await import('../plugin-store-
|
|
5633
|
+
const { ensurePluginsLoaded } = await import('../plugin-store-SGNJTBYS.js');
|
|
5130
5634
|
const { pluginRegistry } = await import('../plugin-registry/index.js');
|
|
5131
5635
|
const result = await ensurePluginsLoaded(projectDir, config.plugins, pluginRegistry);
|
|
5132
5636
|
if (result.loaded.length > 0) {
|
|
@@ -5142,21 +5646,21 @@ async function ensurePluginsLoadedForServe(projectDir) {
|
|
|
5142
5646
|
async function runCompileTest(opts) {
|
|
5143
5647
|
const { logOk: logOk2, logErr: logErr2, logInfo: logInfo2, S: S2 } = await import('../helpers-F4NZ66VD.js');
|
|
5144
5648
|
const { tmpdir } = await import('os');
|
|
5145
|
-
const { dirname:
|
|
5649
|
+
const { dirname: dirname4, join: join5, resolve: resolve5 } = await import('path');
|
|
5146
5650
|
const { fileURLToPath: fileURLToPath2 } = await import('url');
|
|
5147
|
-
const { unlinkSync, existsSync:
|
|
5651
|
+
const { unlinkSync, existsSync: existsSync13 } = await import('fs');
|
|
5148
5652
|
const { spawn } = await import('child_process');
|
|
5149
5653
|
const { portableSpawnSync: portableSpawnSync2 } = await import('../core/index.js');
|
|
5150
|
-
const { MONOREPO_ROOT } = await import('../paths-
|
|
5654
|
+
const { MONOREPO_ROOT } = await import('../paths-D6RUQ522.js');
|
|
5151
5655
|
if (MONOREPO_ROOT === null) {
|
|
5152
5656
|
logErr2("--compile-test is only available inside the skaile-dev workspace.");
|
|
5153
5657
|
logInfo2("Run it from a checkout of skaile-ai/skaile-dev (the monorepo shell).");
|
|
5154
5658
|
process.exitCode = 2;
|
|
5155
5659
|
return;
|
|
5156
5660
|
}
|
|
5157
|
-
const outfile =
|
|
5661
|
+
const outfile = join5(tmpdir(), `skaile-compile-test-${Date.now()}`);
|
|
5158
5662
|
const __thisFile = fileURLToPath2(import.meta.url);
|
|
5159
|
-
const entryPoint = resolve5(
|
|
5663
|
+
const entryPoint = resolve5(dirname4(__thisFile), "..", "index.ts");
|
|
5160
5664
|
logInfo2(`Building compiled binary...`);
|
|
5161
5665
|
logInfo2(`Entry: ${S2.dim(entryPoint)}`);
|
|
5162
5666
|
logInfo2(`Output: ${S2.dim(outfile)}`);
|
|
@@ -5206,7 +5710,7 @@ async function runCompileTest(opts) {
|
|
|
5206
5710
|
} catch {
|
|
5207
5711
|
}
|
|
5208
5712
|
try {
|
|
5209
|
-
if (
|
|
5713
|
+
if (existsSync13(outfile)) unlinkSync(outfile);
|
|
5210
5714
|
} catch {
|
|
5211
5715
|
}
|
|
5212
5716
|
}
|
|
@@ -5960,324 +6464,6 @@ function makeShowCommand() {
|
|
|
5960
6464
|
}
|
|
5961
6465
|
});
|
|
5962
6466
|
}
|
|
5963
|
-
|
|
5964
|
-
// cli/src/commands/source-manifest.ts
|
|
5965
|
-
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.";
|
|
5966
|
-
function notWired2(verb) {
|
|
5967
|
-
logErr(`${NOT_WIRED_MSG} (verb: source manifest ${verb})`);
|
|
5968
|
-
process.exit(2);
|
|
5969
|
-
}
|
|
5970
|
-
function addSourceManifestCommands(src) {
|
|
5971
|
-
const manifest = src.command("manifest").description("Sidecar manifest lifecycle for a source");
|
|
5972
|
-
manifest.command("init <src>").description("Start a sidecar manifest for a source").action(() => notWired2("init"));
|
|
5973
|
-
manifest.command("edit <src>").description("Open the sidecar manifest in $EDITOR").action(() => notWired2("edit"));
|
|
5974
|
-
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"));
|
|
5975
|
-
manifest.command("verify <src>").description("Verify hashes, deps, and schema").option("--strict", "Fail on advisory checks", false).action(() => notWired2("verify"));
|
|
5976
|
-
manifest.command("publish <src>").description("Register the manifest in the store (provenance=curator)").action(() => notWired2("publish"));
|
|
5977
|
-
manifest.command("propose <src>").description("Open a PR to upstream with the sidecar manifest").action(() => notWired2("propose"));
|
|
5978
|
-
manifest.command("yank <src>").description("Retract a published manifest from the remote store").option("--version <v>", "Version to yank").action(() => notWired2("yank"));
|
|
5979
|
-
}
|
|
5980
|
-
|
|
5981
|
-
// cli/src/commands/source.ts
|
|
5982
|
-
function sourceClonePath(key) {
|
|
5983
|
-
return path14.join(getGlobalCacheDir(), key);
|
|
5984
|
-
}
|
|
5985
|
-
var SKAILE_MANIFEST_FILENAME2 = "skaile.manifest.yaml";
|
|
5986
|
-
var LEGACY_SOURCE_CONFIG_FILENAME = ".skaile-source.yaml";
|
|
5987
|
-
function indexingHadFailures(result) {
|
|
5988
|
-
return result.errors.length > 0;
|
|
5989
|
-
}
|
|
5990
|
-
function legacySourceConfigHint(dest) {
|
|
5991
|
-
const hasLegacy = existsSync(path14.join(dest, LEGACY_SOURCE_CONFIG_FILENAME));
|
|
5992
|
-
const hasManifest = existsSync(path14.join(dest, SKAILE_MANIFEST_FILENAME2));
|
|
5993
|
-
if (hasLegacy && !hasManifest) {
|
|
5994
|
-
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.`;
|
|
5995
|
-
}
|
|
5996
|
-
return void 0;
|
|
5997
|
-
}
|
|
5998
|
-
function normalizeSourceUrl(input) {
|
|
5999
|
-
const s = input.trim();
|
|
6000
|
-
if (/^(?:https?|git|ssh|file):\/\//.test(s) || /^git@/.test(s)) return s;
|
|
6001
|
-
const repo = s.replace(/\.git$/, "");
|
|
6002
|
-
if (/^[\w.-]+\/[\w.-]+$/.test(repo)) return `git@github.com:${repo}.git`;
|
|
6003
|
-
if (/^[\w.-]+$/.test(repo)) return `git@github.com:skaile-ai/${repo}.git`;
|
|
6004
|
-
return s;
|
|
6005
|
-
}
|
|
6006
|
-
function sourceMatchesKey(entry, key) {
|
|
6007
|
-
if (entry.url === key) return true;
|
|
6008
|
-
if (sourceCacheKey(entry.url) === key || sourceShortName(entry.url) === key) return true;
|
|
6009
|
-
return entry.url === normalizeSourceUrl(key);
|
|
6010
|
-
}
|
|
6011
|
-
function findCacheKeyCollision(sources, url) {
|
|
6012
|
-
const key = sourceCacheKey(url);
|
|
6013
|
-
return sources.find((s) => s.url !== url && sourceCacheKey(s.url) === key);
|
|
6014
|
-
}
|
|
6015
|
-
function requireProjectYamlPath() {
|
|
6016
|
-
const root = findWorkspaceRoot(process.cwd());
|
|
6017
|
-
if (!root) {
|
|
6018
|
-
logErr(
|
|
6019
|
-
"No skaile.yaml found in the current directory or any parent. Run `skaile init` first."
|
|
6020
|
-
);
|
|
6021
|
-
process.exit(1);
|
|
6022
|
-
}
|
|
6023
|
-
return path14.join(root, workspaceConfigFilename());
|
|
6024
|
-
}
|
|
6025
|
-
function readProjectSources(yamlPath) {
|
|
6026
|
-
if (!existsSync(yamlPath)) return [];
|
|
6027
|
-
try {
|
|
6028
|
-
return WorkspaceYamlEditor.load(yamlPath).getSources();
|
|
6029
|
-
} catch (err) {
|
|
6030
|
-
logErr(`Could not read ${yamlPath}: ${err instanceof Error ? err.message : String(err)}`);
|
|
6031
|
-
process.exit(1);
|
|
6032
|
-
}
|
|
6033
|
-
}
|
|
6034
|
-
function ensureClone(entry, opts = {}) {
|
|
6035
|
-
const dest = sourceClonePath(sourceCacheKey(entry.url));
|
|
6036
|
-
if (existsSync(dest)) {
|
|
6037
|
-
if (!opts.force) return false;
|
|
6038
|
-
rmSync(dest, { recursive: true, force: true });
|
|
6039
|
-
}
|
|
6040
|
-
mkdirSync(path14.dirname(dest), { recursive: true });
|
|
6041
|
-
const args = ["clone", entry.url, dest];
|
|
6042
|
-
if (entry.pin) args.splice(1, 0, "--branch", entry.pin);
|
|
6043
|
-
const clone = spawnSync("git", args, { stdio: "inherit" });
|
|
6044
|
-
if (clone.status !== 0) {
|
|
6045
|
-
logErr(`git clone failed for ${entry.url}`);
|
|
6046
|
-
process.exit(1);
|
|
6047
|
-
}
|
|
6048
|
-
return true;
|
|
6049
|
-
}
|
|
6050
|
-
async function refreshManifestCache(entry, includeDev = false) {
|
|
6051
|
-
const { manager, library, close } = await openLibraryManager();
|
|
6052
|
-
try {
|
|
6053
|
-
const name = sourceShortName(entry.url);
|
|
6054
|
-
const dest = sourceClonePath(sourceCacheKey(entry.url));
|
|
6055
|
-
const existing = (await manager.listLibraries()).find((l) => l.name === name);
|
|
6056
|
-
const lib = existing ?? await manager.addLibrary({
|
|
6057
|
-
name,
|
|
6058
|
-
path: dest,
|
|
6059
|
-
backend: "git",
|
|
6060
|
-
backendConfig: { url: entry.url, branch: entry.pin ?? "main", authHint: "ssh" },
|
|
6061
|
-
ownership: "reader"
|
|
6062
|
-
});
|
|
6063
|
-
const catalog = new LocalCatalogSource(library, lib.id, dest, createFullRegistry());
|
|
6064
|
-
const result = await catalog.sync({ includeDev });
|
|
6065
|
-
await library.syncSource(lib.id);
|
|
6066
|
-
return result;
|
|
6067
|
-
} finally {
|
|
6068
|
-
close();
|
|
6069
|
-
}
|
|
6070
|
-
}
|
|
6071
|
-
async function dropManifestCache(url, purgeClone) {
|
|
6072
|
-
const name = sourceShortName(url);
|
|
6073
|
-
const { manager, close } = await openLibraryManager();
|
|
6074
|
-
try {
|
|
6075
|
-
const existing = (await manager.listLibraries()).find((l) => l.name === name);
|
|
6076
|
-
if (existing) {
|
|
6077
|
-
await manager.removeLibrary(name, { purge: false });
|
|
6078
|
-
}
|
|
6079
|
-
} finally {
|
|
6080
|
-
close();
|
|
6081
|
-
}
|
|
6082
|
-
if (purgeClone) {
|
|
6083
|
-
const dest = sourceClonePath(sourceCacheKey(url));
|
|
6084
|
-
if (existsSync(dest)) rmSync(dest, { recursive: true, force: true });
|
|
6085
|
-
}
|
|
6086
|
-
}
|
|
6087
|
-
function makeSourceCommand() {
|
|
6088
|
-
const cmd = new Command("source").description(
|
|
6089
|
-
"Manage github sources for the current project (recorded in skaile.yaml)"
|
|
6090
|
-
);
|
|
6091
|
-
cmd.command("add <source>").description(
|
|
6092
|
-
"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)."
|
|
6093
|
-
).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(
|
|
6094
|
-
async (source, opts) => {
|
|
6095
|
-
const url = normalizeSourceUrl(source);
|
|
6096
|
-
const yamlPath = requireProjectYamlPath();
|
|
6097
|
-
const collision = findCacheKeyCollision(readProjectSources(yamlPath), url);
|
|
6098
|
-
if (collision) {
|
|
6099
|
-
logErr(
|
|
6100
|
-
`"${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.`
|
|
6101
|
-
);
|
|
6102
|
-
process.exitCode = 1;
|
|
6103
|
-
return;
|
|
6104
|
-
}
|
|
6105
|
-
if (opts.name) {
|
|
6106
|
-
logWarn(
|
|
6107
|
-
"the --name flag is deprecated; the source entry now stores only the URL (the cache slug is derived from it)."
|
|
6108
|
-
);
|
|
6109
|
-
}
|
|
6110
|
-
const pin = opts.pin ?? opts.branch;
|
|
6111
|
-
const slug = sourceShortName(url);
|
|
6112
|
-
const entry = { url };
|
|
6113
|
-
if (pin) entry.pin = pin;
|
|
6114
|
-
const editor = WorkspaceYamlEditor.load(yamlPath);
|
|
6115
|
-
editor.setSource(entry);
|
|
6116
|
-
editor.save();
|
|
6117
|
-
const dest = sourceClonePath(sourceCacheKey(url));
|
|
6118
|
-
const preexisting = existsSync(dest);
|
|
6119
|
-
const cloned = ensureClone(entry, { force: opts.force });
|
|
6120
|
-
if (!cloned) {
|
|
6121
|
-
logOk(`Reusing cached clone at ${dest}`);
|
|
6122
|
-
} else if (preexisting) {
|
|
6123
|
-
logOk(`Re-cloned ${url} \u2192 ${dest}`);
|
|
6124
|
-
} else {
|
|
6125
|
-
logOk(`Cloned ${url} \u2192 ${dest}`);
|
|
6126
|
-
}
|
|
6127
|
-
const result = await refreshManifestCache(entry, opts.dev);
|
|
6128
|
-
const failed = indexingHadFailures(result);
|
|
6129
|
-
const indexedMsg = `Indexed ${result.assetsUpdated} of ${result.assetsFound} asset(s) from "${slug}".`;
|
|
6130
|
-
if (failed) {
|
|
6131
|
-
logWarn(indexedMsg);
|
|
6132
|
-
} else {
|
|
6133
|
-
logOk(indexedMsg);
|
|
6134
|
-
}
|
|
6135
|
-
for (const err of result.errors) logWarn(err);
|
|
6136
|
-
const legacyHint = legacySourceConfigHint(dest);
|
|
6137
|
-
if (legacyHint) logWarn(legacyHint);
|
|
6138
|
-
const where = path14.relative(process.cwd(), yamlPath);
|
|
6139
|
-
if (failed) {
|
|
6140
|
-
logWarn(
|
|
6141
|
-
`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}\`.`
|
|
6142
|
-
);
|
|
6143
|
-
process.exitCode = 1;
|
|
6144
|
-
} else {
|
|
6145
|
-
logOk(`Source "${slug}" registered in ${where}.`);
|
|
6146
|
-
}
|
|
6147
|
-
}
|
|
6148
|
-
);
|
|
6149
|
-
cmd.command("list").description("List sources registered in this project's skaile.yaml").option("--json", "Output as JSON").action(async (opts) => {
|
|
6150
|
-
const yamlPath = requireProjectYamlPath();
|
|
6151
|
-
const sources = readProjectSources(yamlPath);
|
|
6152
|
-
if (opts.json) return console.log(JSON.stringify(sources, null, 2));
|
|
6153
|
-
if (sources.length === 0) {
|
|
6154
|
-
logInfo("No sources in skaile.yaml. Run `skaile source add <git-url>` to register one.");
|
|
6155
|
-
return;
|
|
6156
|
-
}
|
|
6157
|
-
console.log();
|
|
6158
|
-
console.log(S.heading(" Sources"));
|
|
6159
|
-
for (const s of sources) {
|
|
6160
|
-
const slug = sourceShortName(s.url);
|
|
6161
|
-
const cached = existsSync(sourceClonePath(sourceCacheKey(s.url))) ? "" : S.warn(" (not cached)");
|
|
6162
|
-
console.log(` ${S.cmd(slug.padEnd(24))} ${S.dim(s.url)}${cached}`);
|
|
6163
|
-
}
|
|
6164
|
-
console.log(`
|
|
6165
|
-
${S.dim(`${sources.length} source(s)`)}
|
|
6166
|
-
`);
|
|
6167
|
-
});
|
|
6168
|
-
cmd.command("show <name-or-url>").description("Show details for a source (matched by URL or derived slug)").action(async (key) => {
|
|
6169
|
-
const yamlPath = requireProjectYamlPath();
|
|
6170
|
-
const entry = readProjectSources(yamlPath).find((s) => sourceMatchesKey(s, key));
|
|
6171
|
-
if (!entry) {
|
|
6172
|
-
logErr(`No source matching "${key}" in ${yamlPath}.`);
|
|
6173
|
-
process.exit(1);
|
|
6174
|
-
}
|
|
6175
|
-
const slug = sourceShortName(entry.url);
|
|
6176
|
-
const clonePath = sourceClonePath(sourceCacheKey(entry.url));
|
|
6177
|
-
console.log(
|
|
6178
|
-
JSON.stringify(
|
|
6179
|
-
{
|
|
6180
|
-
...entry,
|
|
6181
|
-
slug,
|
|
6182
|
-
clonePath,
|
|
6183
|
-
cached: existsSync(clonePath)
|
|
6184
|
-
},
|
|
6185
|
-
null,
|
|
6186
|
-
2
|
|
6187
|
-
)
|
|
6188
|
-
);
|
|
6189
|
-
});
|
|
6190
|
-
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) => {
|
|
6191
|
-
const yamlPath = requireProjectYamlPath();
|
|
6192
|
-
const editor = WorkspaceYamlEditor.load(yamlPath);
|
|
6193
|
-
const match = editor.getSources().find((s) => sourceMatchesKey(s, key));
|
|
6194
|
-
if (!match) {
|
|
6195
|
-
logErr(`No source matching "${key}" in ${yamlPath}.`);
|
|
6196
|
-
process.exit(1);
|
|
6197
|
-
}
|
|
6198
|
-
const slug = sourceShortName(match.url);
|
|
6199
|
-
editor.removeSource(match.url);
|
|
6200
|
-
editor.save();
|
|
6201
|
-
await dropManifestCache(match.url, opts.purge);
|
|
6202
|
-
logOk(
|
|
6203
|
-
opts.purge ? `Removed source "${slug}" and purged its clone.` : `Removed source "${slug}" from skaile.yaml (clone left in ~/.skaile/cache/sources/).`
|
|
6204
|
-
);
|
|
6205
|
-
});
|
|
6206
|
-
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) => {
|
|
6207
|
-
const yamlPath = requireProjectYamlPath();
|
|
6208
|
-
const sources = readProjectSources(yamlPath);
|
|
6209
|
-
if (sources.length === 0) {
|
|
6210
|
-
logInfo("No sources in skaile.yaml.");
|
|
6211
|
-
return;
|
|
6212
|
-
}
|
|
6213
|
-
let targets;
|
|
6214
|
-
if (key) {
|
|
6215
|
-
targets = sources.filter((s) => sourceMatchesKey(s, key));
|
|
6216
|
-
if (targets.length === 0) {
|
|
6217
|
-
logInfo(`No source matching "${key}".`);
|
|
6218
|
-
return;
|
|
6219
|
-
}
|
|
6220
|
-
} else if (opts.all || sources.length === 1 || !process.stdin.isTTY) {
|
|
6221
|
-
targets = sources;
|
|
6222
|
-
} else {
|
|
6223
|
-
const selected = await p6.multiselect({
|
|
6224
|
-
message: "Select sources to sync",
|
|
6225
|
-
options: sources.map((s) => ({
|
|
6226
|
-
value: s.url,
|
|
6227
|
-
label: sourceShortName(s.url),
|
|
6228
|
-
hint: s.url
|
|
6229
|
-
})),
|
|
6230
|
-
required: true
|
|
6231
|
-
});
|
|
6232
|
-
if (p6.isCancel(selected)) {
|
|
6233
|
-
p6.cancel("Cancelled.");
|
|
6234
|
-
return;
|
|
6235
|
-
}
|
|
6236
|
-
const picked = new Set(selected);
|
|
6237
|
-
targets = sources.filter((s) => picked.has(s.url));
|
|
6238
|
-
}
|
|
6239
|
-
for (const entry of targets) {
|
|
6240
|
-
const slug = sourceShortName(entry.url);
|
|
6241
|
-
const dest = sourceClonePath(sourceCacheKey(entry.url));
|
|
6242
|
-
if (!existsSync(dest)) {
|
|
6243
|
-
ensureClone(entry);
|
|
6244
|
-
logOk(`${slug}: cloned to ${dest}.`);
|
|
6245
|
-
} else {
|
|
6246
|
-
const pull = spawnSync("git", ["pull", "--ff-only"], { cwd: dest, stdio: "inherit" });
|
|
6247
|
-
if (pull.status !== 0) {
|
|
6248
|
-
logWarn(`${slug}: git pull failed, skipping manifest refresh.`);
|
|
6249
|
-
continue;
|
|
6250
|
-
}
|
|
6251
|
-
}
|
|
6252
|
-
const result = await refreshManifestCache(entry, opts.dev);
|
|
6253
|
-
const failed = indexingHadFailures(result);
|
|
6254
|
-
const indexedMsg = `${slug}: indexed ${result.assetsUpdated} of ${result.assetsFound} asset(s).`;
|
|
6255
|
-
if (failed) {
|
|
6256
|
-
logWarn(indexedMsg);
|
|
6257
|
-
process.exitCode = 1;
|
|
6258
|
-
} else {
|
|
6259
|
-
logOk(indexedMsg);
|
|
6260
|
-
}
|
|
6261
|
-
for (const err of result.errors) logWarn(`${slug}: ${err}`);
|
|
6262
|
-
const legacyHint = legacySourceConfigHint(dest);
|
|
6263
|
-
if (legacyHint) logWarn(`${slug}: ${legacyHint}`);
|
|
6264
|
-
}
|
|
6265
|
-
});
|
|
6266
|
-
cmd.command("patch <ref>").description("Extract an asset for editing against the source").action((_ref) => {
|
|
6267
|
-
logErr(
|
|
6268
|
-
"`skaile source patch` is scaffolded but not yet wired. The patch flow lands in a follow-up PR."
|
|
6269
|
-
);
|
|
6270
|
-
process.exit(2);
|
|
6271
|
-
});
|
|
6272
|
-
cmd.command("propose <ref>").description("Open a PR with the patch against the source upstream").action((_ref) => {
|
|
6273
|
-
logErr(
|
|
6274
|
-
"`skaile source propose` is scaffolded but not yet wired. The propose flow lands in a follow-up PR."
|
|
6275
|
-
);
|
|
6276
|
-
process.exit(2);
|
|
6277
|
-
});
|
|
6278
|
-
addSourceManifestCommands(cmd);
|
|
6279
|
-
return cmd;
|
|
6280
|
-
}
|
|
6281
6467
|
function makeStoreCommand() {
|
|
6282
6468
|
const store = new Command("store").description("Manage the AI Asset Store");
|
|
6283
6469
|
store.command("login").description("Authenticate with the store").option("--email <email>", "Login with email instead of GitHub").action(async (opts) => {
|
|
@@ -6455,7 +6641,7 @@ function makeTreeCommand() {
|
|
|
6455
6641
|
});
|
|
6456
6642
|
}
|
|
6457
6643
|
function makeUpdateCommand() {
|
|
6458
|
-
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(
|
|
6459
6645
|
async (_name, opts) => {
|
|
6460
6646
|
if (opts.catalog !== false) {
|
|
6461
6647
|
try {
|
|
@@ -6473,7 +6659,16 @@ function makeUpdateCommand() {
|
|
|
6473
6659
|
}
|
|
6474
6660
|
}
|
|
6475
6661
|
if (opts.catalogOnly) return;
|
|
6476
|
-
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 });
|
|
6477
6672
|
const spinner5 = p6.spinner();
|
|
6478
6673
|
spinner5.start("Re-deploying assets");
|
|
6479
6674
|
const result = await am2.install();
|
|
@@ -6486,6 +6681,19 @@ function makeUpdateCommand() {
|
|
|
6486
6681
|
}
|
|
6487
6682
|
);
|
|
6488
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
|
+
}
|
|
6489
6697
|
var MANIFEST_GLOBS = [
|
|
6490
6698
|
{ pattern: /\/SKILL\.md$/, kind: "skill" },
|
|
6491
6699
|
{ pattern: /\/agent\.yaml$/, kind: "agent" },
|
|
@@ -7215,7 +7423,7 @@ program.command("init [project-dir]").description("Initialize a project director
|
|
|
7215
7423
|
(projectDir, opts) => runInit(projectDir, opts)
|
|
7216
7424
|
);
|
|
7217
7425
|
async function runInit(projectDir, opts) {
|
|
7218
|
-
const { mkdirSync:
|
|
7426
|
+
const { mkdirSync: mkdirSync5, writeFileSync: writeFileSync4 } = await import('fs');
|
|
7219
7427
|
const { stringify } = await import('yaml');
|
|
7220
7428
|
const { DRIVER_TARGETS, SUPPORTED_DRIVER_TARGETS: SUPPORTED_DRIVER_TARGETS2 } = await import('../core/index.js');
|
|
7221
7429
|
const backend = opts.backend;
|
|
@@ -7227,30 +7435,30 @@ async function runInit(projectDir, opts) {
|
|
|
7227
7435
|
const resolved = path14__default.resolve(projectDir ?? ".");
|
|
7228
7436
|
const projectName = path14__default.basename(resolved);
|
|
7229
7437
|
const created = [];
|
|
7230
|
-
const { existsSync:
|
|
7231
|
-
if (!
|
|
7232
|
-
|
|
7438
|
+
const { existsSync: existsSync13 } = await import('fs');
|
|
7439
|
+
if (!existsSync13(resolved)) {
|
|
7440
|
+
mkdirSync5(resolved, { recursive: true });
|
|
7233
7441
|
created.push(".");
|
|
7234
7442
|
}
|
|
7235
7443
|
const skaileDir = path14__default.join(resolved, ".skaile");
|
|
7236
|
-
if (!
|
|
7237
|
-
|
|
7444
|
+
if (!existsSync13(skaileDir)) {
|
|
7445
|
+
mkdirSync5(path14__default.join(skaileDir, "sessions"), { recursive: true });
|
|
7238
7446
|
created.push(".skaile/");
|
|
7239
7447
|
}
|
|
7240
7448
|
const settingsPath = path14__default.join(skaileDir, "settings.json");
|
|
7241
|
-
if (!
|
|
7449
|
+
if (!existsSync13(settingsPath)) {
|
|
7242
7450
|
writeFileSync4(settingsPath, "{}\n");
|
|
7243
7451
|
created.push(".skaile/settings.json");
|
|
7244
7452
|
}
|
|
7245
7453
|
const wsConfigPath = path14__default.join(resolved, "skaile.yaml");
|
|
7246
|
-
if (!
|
|
7454
|
+
if (!existsSync13(wsConfigPath)) {
|
|
7247
7455
|
writeFileSync4(wsConfigPath, stringify(buildInitWorkspaceConfig(projectName, backend)));
|
|
7248
7456
|
created.push("skaile.yaml");
|
|
7249
7457
|
}
|
|
7250
7458
|
for (const dir of new Set(Object.values(DRIVER_TARGETS[backend].local))) {
|
|
7251
7459
|
const full = path14__default.join(resolved, dir);
|
|
7252
|
-
if (!
|
|
7253
|
-
|
|
7460
|
+
if (!existsSync13(full)) {
|
|
7461
|
+
mkdirSync5(full, { recursive: true });
|
|
7254
7462
|
created.push(`${dir}/`);
|
|
7255
7463
|
}
|
|
7256
7464
|
}
|
|
@@ -7280,7 +7488,7 @@ function buildInitWorkspaceConfig(projectName, backend) {
|
|
|
7280
7488
|
}
|
|
7281
7489
|
async function initGitScaffold(resolved, created) {
|
|
7282
7490
|
const { execSync: execSync3 } = await import('child_process');
|
|
7283
|
-
const { existsSync:
|
|
7491
|
+
const { existsSync: existsSync13, readFileSync: readFileSync8, writeFileSync: writeFileSync4 } = await import('fs');
|
|
7284
7492
|
const gitignorePath = path14__default.join(resolved, ".gitignore");
|
|
7285
7493
|
const entries = [
|
|
7286
7494
|
"node_modules/",
|
|
@@ -7296,7 +7504,7 @@ async function initGitScaffold(resolved, created) {
|
|
|
7296
7504
|
".env",
|
|
7297
7505
|
".env.local"
|
|
7298
7506
|
];
|
|
7299
|
-
const existing =
|
|
7507
|
+
const existing = existsSync13(gitignorePath) ? readFileSync8(gitignorePath, "utf-8") : "";
|
|
7300
7508
|
const have = new Set(existing.split("\n").map((l) => l.trim()));
|
|
7301
7509
|
const append = entries.filter((e) => !have.has(e));
|
|
7302
7510
|
if (append.length > 0) {
|
|
@@ -7305,7 +7513,7 @@ async function initGitScaffold(resolved, created) {
|
|
|
7305
7513
|
`);
|
|
7306
7514
|
if (!existing) created.push(".gitignore");
|
|
7307
7515
|
}
|
|
7308
|
-
if (!
|
|
7516
|
+
if (!existsSync13(path14__default.join(resolved, ".git"))) {
|
|
7309
7517
|
try {
|
|
7310
7518
|
execSync3("git init", { cwd: resolved, stdio: "pipe" });
|
|
7311
7519
|
created.push(".git/");
|
|
@@ -7335,7 +7543,7 @@ async function bootstrapUserConfig() {
|
|
|
7335
7543
|
}
|
|
7336
7544
|
async function hydrateInitSources(resolved, created) {
|
|
7337
7545
|
try {
|
|
7338
|
-
const { ensureSourcesCloned } = await import('../ensure-sources-
|
|
7546
|
+
const { ensureSourcesCloned } = await import('../ensure-sources-GJOXWVWO.js');
|
|
7339
7547
|
const hydrate = ensureSourcesCloned(resolved, { quiet: true });
|
|
7340
7548
|
for (const n of hydrate.cloned) created.push(`~/.skaile/cache/sources/${n}/`);
|
|
7341
7549
|
if (hydrate.failed.length > 0) {
|
|
@@ -7371,7 +7579,7 @@ function printInitSummary(resolved, projectDir, created) {
|
|
|
7371
7579
|
console.log();
|
|
7372
7580
|
}
|
|
7373
7581
|
program.command("setup").description("Interactive provider setup wizard").action(async () => {
|
|
7374
|
-
const { cmdSetup } = await import('../setup-
|
|
7582
|
+
const { cmdSetup } = await import('../setup-IV2JFW3T.js');
|
|
7375
7583
|
await cmdSetup([], { projectDir: process.cwd() });
|
|
7376
7584
|
});
|
|
7377
7585
|
program.addCommand(makeInstallCommand());
|