@skaile/workspaces 0.43.1 → 0.45.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +101 -0
- package/dist/{asset-feeds-3PSV57NT.js → asset-feeds-AOZLZMDV.js} +15 -11
- package/dist/asset-feeds-AOZLZMDV.js.map +1 -0
- package/dist/asset-manager/index.js +5 -5
- package/dist/asset-manager/installer.js +4 -4
- package/dist/asset-manager/src/index.d.ts +149 -4
- package/dist/asset-manager/src/index.d.ts.map +1 -1
- package/dist/{chunk-KYQNWFJV.js → chunk-BLGHFVXE.js} +3 -3
- package/dist/{chunk-KYQNWFJV.js.map → chunk-BLGHFVXE.js.map} +1 -1
- package/dist/{chunk-R4H6EJW5.js → chunk-CBZEIFU4.js} +3 -3
- package/dist/{chunk-R4H6EJW5.js.map → chunk-CBZEIFU4.js.map} +1 -1
- package/dist/{chunk-GJI6FZ56.js → chunk-COSTF7QW.js} +60 -8
- package/dist/chunk-COSTF7QW.js.map +1 -0
- package/dist/{chunk-NYMRKIOR.js → chunk-CVWA4RIK.js} +4 -4
- package/dist/{chunk-NYMRKIOR.js.map → chunk-CVWA4RIK.js.map} +1 -1
- package/dist/{chunk-BXYMGZCI.js → chunk-ETDXTGDF.js} +3 -3
- package/dist/{chunk-BXYMGZCI.js.map → chunk-ETDXTGDF.js.map} +1 -1
- package/dist/{chunk-TDSRLMDB.js → chunk-EVZKWY5J.js} +2 -2
- package/dist/chunk-EVZKWY5J.js.map +1 -0
- package/dist/{chunk-3HUUP3JC.js → chunk-FYLIR4AV.js} +107 -7
- package/dist/chunk-FYLIR4AV.js.map +1 -0
- package/dist/{chunk-G6FJZG4C.js → chunk-GM3BV6JK.js} +2 -2
- package/dist/{chunk-G6FJZG4C.js.map → chunk-GM3BV6JK.js.map} +1 -1
- package/dist/{chunk-R4YUZRGF.js → chunk-JUZGLINM.js} +2 -2
- package/dist/{chunk-R4YUZRGF.js.map → chunk-JUZGLINM.js.map} +1 -1
- package/dist/{chunk-WKZ5R4NP.js → chunk-L6BKSTAX.js} +332 -38
- package/dist/chunk-L6BKSTAX.js.map +1 -0
- package/dist/{chunk-WRDHUTOK.js → chunk-LHUCCPH4.js} +5 -5
- package/dist/{chunk-WRDHUTOK.js.map → chunk-LHUCCPH4.js.map} +1 -1
- package/dist/{chunk-U2XHHLE3.js → chunk-LMRO2QNF.js} +5 -5
- package/dist/{chunk-U2XHHLE3.js.map → chunk-LMRO2QNF.js.map} +1 -1
- package/dist/{chunk-N4FSBCLV.js → chunk-N2KV5RK3.js} +127 -10
- package/dist/chunk-N2KV5RK3.js.map +1 -0
- package/dist/{chunk-CIEKKLMG.js → chunk-PCXU2CVW.js} +3 -3
- package/dist/{chunk-CIEKKLMG.js.map → chunk-PCXU2CVW.js.map} +1 -1
- package/dist/{chunk-HVCZLD5Z.js → chunk-VPXV2Z5E.js} +5 -7
- package/dist/chunk-VPXV2Z5E.js.map +1 -0
- package/dist/{chunk-2BEDUMTA.js → chunk-XF2BBX6P.js} +3 -3
- package/dist/{chunk-2BEDUMTA.js.map → chunk-XF2BBX6P.js.map} +1 -1
- package/dist/{chunk-3K2CYDBT.js → chunk-Z5Z3MYDL.js} +8 -4
- package/dist/chunk-Z5Z3MYDL.js.map +1 -0
- package/dist/{chunk-M54RYUXY.js → chunk-ZAEJ33Y6.js} +19 -7
- package/dist/chunk-ZAEJ33Y6.js.map +1 -0
- package/dist/cli/index.js +969 -572
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/src/asset-feeds.d.ts.map +1 -1
- package/dist/cli/src/commands/asset-cmd.d.ts +1 -1
- package/dist/cli/src/commands/asset-cmd.d.ts.map +1 -1
- package/dist/cli/src/commands/cache.d.ts +27 -0
- package/dist/cli/src/commands/cache.d.ts.map +1 -0
- package/dist/cli/src/commands/catalog.d.ts +9 -3
- package/dist/cli/src/commands/catalog.d.ts.map +1 -1
- package/dist/cli/src/commands/library-cmd.d.ts.map +1 -1
- package/dist/cli/src/commands/manage.d.ts.map +1 -1
- package/dist/cli/src/commands/npx.d.ts +1 -1
- package/dist/cli/src/commands/skailify-lib.d.ts +108 -0
- package/dist/cli/src/commands/skailify-lib.d.ts.map +1 -0
- package/dist/cli/src/commands/source.d.ts +3 -1
- package/dist/cli/src/commands/source.d.ts.map +1 -1
- package/dist/cli/src/commands/update.d.ts +1 -1
- package/dist/cli/src/ensure-sources.d.ts +2 -2
- package/dist/cli/src/ensure-sources.d.ts.map +1 -1
- package/dist/connectors/config.js +4 -4
- package/dist/connectors/index.js +6 -6
- package/dist/connectors/rclone.js +1 -1
- package/dist/connectors/src/rclone-process-manager.d.ts +57 -2
- package/dist/connectors/src/rclone-process-manager.d.ts.map +1 -1
- package/dist/core/index.js +3 -3
- package/dist/core/runtime-assets.js +2 -2
- package/dist/core/src/cache-paths.d.ts +25 -0
- package/dist/core/src/cache-paths.d.ts.map +1 -0
- package/dist/core/src/index.d.ts +2 -1
- package/dist/core/src/index.d.ts.map +1 -1
- package/dist/core/src/repo-manager.d.ts +11 -8
- package/dist/core/src/repo-manager.d.ts.map +1 -1
- package/dist/core/src/runtime-assets.d.ts.map +1 -1
- package/dist/core/src/workspace-config.d.ts +2 -2
- package/dist/core/src/workspace-config.d.ts.map +1 -1
- package/dist/core/workspace-config.js +1 -1
- package/dist/deploy/index.js +3 -3
- package/dist/{ensure-sources-VQDZB7NT.js → ensure-sources-NSDMTAWN.js} +6 -12
- package/dist/ensure-sources-NSDMTAWN.js.map +1 -0
- package/dist/factory-assets/connectors/deploy.js +6 -6
- package/dist/factory-assets/connectors/devserver.js +6 -6
- package/dist/factory-assets/connectors/flow/adapter.js +6 -6
- package/dist/factory-assets/connectors/flow/engine.js +3 -3
- package/dist/factory-assets/connectors/flow/run-flow.js +7 -7
- package/dist/factory-assets/connectors/flow.js +6 -6
- package/dist/factory-assets/connectors/git.js +6 -6
- package/dist/factory-assets/connectors/gmail.js +6 -6
- package/dist/factory-assets/connectors/googledrive.js +6 -6
- package/dist/factory-assets/connectors/local.js +6 -6
- package/dist/factory-assets/connectors/mattermost.js +6 -6
- package/dist/factory-assets/connectors/memory.js +6 -6
- package/dist/factory-assets/connectors/minio.js +6 -6
- package/dist/factory-assets/connectors/postgres.js +6 -6
- package/dist/factory-assets/connectors/s3.js +6 -6
- package/dist/factory-assets/connectors/sharepoint.js +6 -6
- package/dist/factory-assets/connectors/sqlite.js +6 -6
- package/dist/factory-assets/connectors/static-server.js +6 -6
- package/dist/factory-assets/connectors/tunnel.js +6 -6
- package/dist/factory-assets/connectors/webdav.js +6 -6
- package/dist/factory-assets/connectors/xstate-store.js +6 -6
- package/dist/factory-assets/connectors/xstate.js +6 -6
- package/dist/factory-assets/skaile.manifest.yaml +3 -0
- package/dist/factory-assets/skills/skailify/SKILL.md +84 -0
- package/dist/{flows-KTBCZ5GQ.js → flows-WELXQ7IG.js} +3 -3
- package/dist/{flows-KTBCZ5GQ.js.map → flows-WELXQ7IG.js.map} +1 -1
- package/dist/library/index.js +4 -4
- package/dist/library/install.js +3 -3
- package/dist/library/src/local/local-catalog-source.d.ts +1 -1
- package/dist/library/src/local/sidecar-git.d.ts +2 -2
- package/dist/library/src/local/sidecar-paths.d.ts +12 -10
- package/dist/library/src/local/sidecar-paths.d.ts.map +1 -1
- package/dist/library/src/local/store-paths.d.ts +2 -2
- package/dist/library/src/remote/cache.d.ts +8 -2
- package/dist/library/src/remote/cache.d.ts.map +1 -1
- package/dist/library/src/remote/remote-catalog-source.d.ts +1 -1
- package/dist/library/src/remote/rest-catalog-source.d.ts +1 -1
- package/dist/{open-library-FHUXOCN7.js → open-library-362BZ6OW.js} +7 -7
- package/dist/{open-library-FHUXOCN7.js.map → open-library-362BZ6OW.js.map} +1 -1
- package/dist/{paths-7H5CSBLQ.js → paths-4SSFMX5Z.js} +6 -6
- package/dist/{paths-7H5CSBLQ.js.map → paths-4SSFMX5Z.js.map} +1 -1
- package/dist/{plugin-store-LGLN2QUX.js → plugin-store-2X2YXJVG.js} +5 -5
- package/dist/{plugin-store-LGLN2QUX.js.map → plugin-store-2X2YXJVG.js.map} +1 -1
- package/dist/runner/index.js +9 -9
- package/dist/runner/src/file-changed-coalescer.d.ts +48 -0
- package/dist/runner/src/file-changed-coalescer.d.ts.map +1 -0
- package/dist/runner/src/resources.d.ts.map +1 -1
- package/dist/sdk/asset-manager.js +5 -5
- package/dist/sdk/core.js +3 -3
- package/dist/sdk/flow.js +3 -3
- package/dist/sdk/index.js +9 -9
- package/dist/sdk/runner.js +9 -9
- package/dist/sdk/session.js +2 -2
- package/dist/sdk/types.js +1 -1
- package/dist/session/index.js +2 -2
- package/dist/session/src/index.d.ts +1 -1
- package/dist/session/src/index.d.ts.map +1 -1
- package/dist/session/src/mentions.d.ts +11 -0
- package/dist/session/src/mentions.d.ts.map +1 -1
- package/dist/{setup-EVNPECSY.js → setup-VGZTFQ32.js} +5 -5
- package/dist/{setup-EVNPECSY.js.map → setup-VGZTFQ32.js.map} +1 -1
- package/dist/{store-client-4XN7IB3R.js → store-client-XFZFKY3W.js} +6 -6
- package/dist/{store-client-4XN7IB3R.js.map → store-client-XFZFKY3W.js.map} +1 -1
- package/dist/tui/index.js +9 -9
- package/dist/types/index.js +1 -1
- package/dist/types/src/mentions.d.ts +12 -0
- package/dist/types/src/mentions.d.ts.map +1 -1
- package/dist/workspace-plugin/adapters/mcp.js +1 -1
- package/dist/workspace-plugin/adapters/omp.js +3 -3
- package/dist/workspace-plugin/index.js +1 -1
- package/package.json +1 -1
- package/dist/asset-feeds-3PSV57NT.js.map +0 -1
- package/dist/chunk-3HUUP3JC.js.map +0 -1
- package/dist/chunk-3K2CYDBT.js.map +0 -1
- package/dist/chunk-GJI6FZ56.js.map +0 -1
- package/dist/chunk-HVCZLD5Z.js.map +0 -1
- package/dist/chunk-M54RYUXY.js.map +0 -1
- package/dist/chunk-N4FSBCLV.js.map +0 -1
- package/dist/chunk-TDSRLMDB.js.map +0 -1
- package/dist/chunk-WKZ5R4NP.js.map +0 -1
- package/dist/ensure-sources-VQDZB7NT.js.map +0 -1
|
@@ -1,15 +1,14 @@
|
|
|
1
|
-
import { deployAll, removeAsset, createScaffold } from './chunk-
|
|
2
|
-
import { writeLock, buildLockFile, readLock, verifyLock, extractForPatch, generatePatch, savePatch, applyPatch } from './chunk-
|
|
3
|
-
import { resolveRuntimeAssets, factoryAssetRoots } from './chunk-
|
|
4
|
-
import { resolveSkWorkspaceConfig,
|
|
1
|
+
import { deployAll, removeAsset, createScaffold } from './chunk-CVWA4RIK.js';
|
|
2
|
+
import { writeLock, buildLockFile, readLock, verifyLock, extractForPatch, generatePatch, savePatch, applyPatch } from './chunk-BLGHFVXE.js';
|
|
3
|
+
import { resolveRuntimeAssets, factoryAssetRoots } from './chunk-VPXV2Z5E.js';
|
|
4
|
+
import { migrateLegacyDir, resolveSkWorkspaceConfig, getGlobalCacheDir, getRepoCommit, resolveAll, buildProvenanceIndex, ensureRepo, scanRepo, SKAILE_YAML_DEFAULT, checkRepoStatus, resolveAsset, readLinks } from './chunk-COSTF7QW.js';
|
|
5
5
|
import { parseAssetRef } from './chunk-GEEW6SY2.js';
|
|
6
6
|
import { deployedBase, isDeployed, deployedDir } from './chunk-XGCXFX7X.js';
|
|
7
7
|
import { appendHistory, getRecentHistory, clearHistory } from './chunk-KTBKW2FI.js';
|
|
8
8
|
import { commitChanges } from './chunk-UQ6LFBPZ.js';
|
|
9
9
|
import { spawnSync } from 'child_process';
|
|
10
10
|
import { existsSync, readdirSync, rmSync, lstatSync, unlinkSync, readFileSync, writeFileSync } from 'fs';
|
|
11
|
-
import {
|
|
12
|
-
import { resolve, join, dirname } from 'path';
|
|
11
|
+
import { resolve, join, sep, dirname } from 'path';
|
|
13
12
|
import { parse, stringify } from 'yaml';
|
|
14
13
|
|
|
15
14
|
function sourceSlug(url) {
|
|
@@ -18,6 +17,46 @@ function sourceSlug(url) {
|
|
|
18
17
|
function normalizeRepoUrl(url) {
|
|
19
18
|
return url.trim().replace(/^git@([^:]+):/, "https://$1/").replace(/^[a-z]+:\/\//i, "").replace(/\.git$/i, "").replace(/\/+$/, "").toLowerCase();
|
|
20
19
|
}
|
|
20
|
+
var MD_BY_KIND = {
|
|
21
|
+
skill: "SKILL.md",
|
|
22
|
+
agent: "AGENT.md",
|
|
23
|
+
bundle: "BUNDLE.md",
|
|
24
|
+
"mcp-server": "MCP.md",
|
|
25
|
+
connector: "CONNECTOR.md",
|
|
26
|
+
prompt: "PROMPT.md",
|
|
27
|
+
contract: "CONTRACT.md"
|
|
28
|
+
};
|
|
29
|
+
function matchManifestPath(kind, paths) {
|
|
30
|
+
const exact = MD_BY_KIND[kind];
|
|
31
|
+
if (exact) {
|
|
32
|
+
const hit = paths.find((p) => p.endsWith(exact));
|
|
33
|
+
if (hit) return hit;
|
|
34
|
+
}
|
|
35
|
+
if (kind === "prompt") return paths.find((p) => p.endsWith(".prompt.md"));
|
|
36
|
+
if (kind === "flow") {
|
|
37
|
+
return paths.find((p) => p.endsWith(".flow.yaml") || p.endsWith(".flow.json"));
|
|
38
|
+
}
|
|
39
|
+
return void 0;
|
|
40
|
+
}
|
|
41
|
+
var NON_DEPLOYABLE_KINDS = /* @__PURE__ */ new Set([
|
|
42
|
+
"bundle",
|
|
43
|
+
"mcp-server",
|
|
44
|
+
"persona",
|
|
45
|
+
"ruleset",
|
|
46
|
+
"knowledge"
|
|
47
|
+
]);
|
|
48
|
+
function commonDirPrefix(paths) {
|
|
49
|
+
if (paths.length === 0) return "";
|
|
50
|
+
const dirs = paths.map((p) => p.split("/").slice(0, -1));
|
|
51
|
+
let common = dirs[0];
|
|
52
|
+
for (let i = 1; i < dirs.length && common.length > 0; i++) {
|
|
53
|
+
const segs = dirs[i];
|
|
54
|
+
let n = 0;
|
|
55
|
+
while (n < common.length && n < segs.length && common[n] === segs[n]) n++;
|
|
56
|
+
common = common.slice(0, n);
|
|
57
|
+
}
|
|
58
|
+
return common.join("/");
|
|
59
|
+
}
|
|
21
60
|
function indexLockByKindName(lock) {
|
|
22
61
|
const lockByKindName = /* @__PURE__ */ new Map();
|
|
23
62
|
for (const [key] of Object.entries(lock?.assets ?? {})) {
|
|
@@ -69,6 +108,14 @@ function parseCanonicalLockKey(key) {
|
|
|
69
108
|
return {};
|
|
70
109
|
}
|
|
71
110
|
}
|
|
111
|
+
var MissingManifestError = class extends Error {
|
|
112
|
+
constructor(projectDir) {
|
|
113
|
+
super(`No skaile.yaml in ${projectDir}.`);
|
|
114
|
+
this.projectDir = projectDir;
|
|
115
|
+
this.name = "MissingManifestError";
|
|
116
|
+
}
|
|
117
|
+
projectDir;
|
|
118
|
+
};
|
|
72
119
|
var FACTORY_SOURCE_URL = "https://github.com/skaile-ai/ai-assets";
|
|
73
120
|
function resolveFactoryAssetsDir() {
|
|
74
121
|
for (const dir of factoryAssetRoots()) {
|
|
@@ -99,13 +146,39 @@ var AssetManager = class {
|
|
|
99
146
|
driverTarget;
|
|
100
147
|
/** Whether this instance operates in global-install mode. */
|
|
101
148
|
global;
|
|
149
|
+
/** Injected catalog fetcher (tests / custom); falls back to a built one. */
|
|
150
|
+
injectedStoreFetcher;
|
|
151
|
+
/** Injected byte fetcher for store staging; falls back to GitHub. */
|
|
152
|
+
injectedAssetFetcher;
|
|
153
|
+
/** Injected global catalog URL override for the no-project-store fallback. */
|
|
154
|
+
catalogUrlOverride;
|
|
102
155
|
constructor(opts) {
|
|
103
156
|
this.projectDir = resolve(opts.projectDir);
|
|
104
157
|
this.driverTarget = opts.driverTarget ?? "claude-code";
|
|
105
158
|
this.global = opts.global ?? false;
|
|
159
|
+
this.injectedStoreFetcher = opts.storeFetcher;
|
|
160
|
+
this.injectedAssetFetcher = opts.assetFetcher;
|
|
161
|
+
this.catalogUrlOverride = opts.catalogUrl;
|
|
162
|
+
}
|
|
163
|
+
get storeCacheDir() {
|
|
164
|
+
return migrateLegacyDir(
|
|
165
|
+
join(this.projectDir, ".skaile", "cache", "store"),
|
|
166
|
+
join(this.projectDir, ".skaile", "store-cache")
|
|
167
|
+
);
|
|
106
168
|
}
|
|
107
169
|
get reposDir() {
|
|
108
|
-
return
|
|
170
|
+
return migrateLegacyDir(
|
|
171
|
+
join(this.projectDir, ".skaile", "cache", "sources"),
|
|
172
|
+
join(this.projectDir, ".skaile", "repos")
|
|
173
|
+
);
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Project-scoped cache dirs rooted at `.skaile/cache/` (`store`, `sources`)
|
|
177
|
+
* relative to `projectDir`. Reading is a side effect: it triggers lazy
|
|
178
|
+
* migration of the legacy `.skaile/{store-cache,repos}` dirs.
|
|
179
|
+
*/
|
|
180
|
+
get projectCacheDirs() {
|
|
181
|
+
return { store: this.storeCacheDir, sources: this.reposDir };
|
|
109
182
|
}
|
|
110
183
|
get lockPath() {
|
|
111
184
|
return join(this.projectDir, "skaile.lock.yaml");
|
|
@@ -123,8 +196,7 @@ var AssetManager = class {
|
|
|
123
196
|
const dependencies = config.dependencies ?? [];
|
|
124
197
|
const overrides = config.overrides ?? [];
|
|
125
198
|
const patches = config.patches ?? {};
|
|
126
|
-
const
|
|
127
|
-
const sourcesDir = join(skaileHome, "sources");
|
|
199
|
+
const sourcesDir = getGlobalCacheDir();
|
|
128
200
|
const repositories = {};
|
|
129
201
|
for (const s of sources) {
|
|
130
202
|
const slug = sourceSlug(s.url);
|
|
@@ -185,15 +257,6 @@ var AssetManager = class {
|
|
|
185
257
|
}
|
|
186
258
|
}
|
|
187
259
|
if (!cloneDir || !slug) return null;
|
|
188
|
-
const MD_BY_KIND = {
|
|
189
|
-
skill: "SKILL.md",
|
|
190
|
-
agent: "AGENT.md",
|
|
191
|
-
bundle: "BUNDLE.md",
|
|
192
|
-
"mcp-server": "MCP.md",
|
|
193
|
-
connector: "CONNECTOR.md",
|
|
194
|
-
prompt: "PROMPT.md",
|
|
195
|
-
contract: "CONTRACT.md"
|
|
196
|
-
};
|
|
197
260
|
const mdName = MD_BY_KIND[c.kind];
|
|
198
261
|
const mdRel = c.files.find((f) => mdName ? f.path.endsWith(mdName) : false)?.path;
|
|
199
262
|
const source = mdRel ? join(cloneDir, mdRel) : cloneDir;
|
|
@@ -215,6 +278,184 @@ var AssetManager = class {
|
|
|
215
278
|
if (c.homepage != null) entry.homepage = c.homepage;
|
|
216
279
|
return entry;
|
|
217
280
|
}
|
|
281
|
+
// ── Store fetch-then-deploy ────────────────────────────────────────────
|
|
282
|
+
/** A candidate's stable identity key (`<publisher>/<kind>:<name>@<version>`). */
|
|
283
|
+
candidateKey(c) {
|
|
284
|
+
return `${c.publisher}/${c.kind}:${c.name}@${c.version}`;
|
|
285
|
+
}
|
|
286
|
+
/**
|
|
287
|
+
* Resolve `deps`, falling back to the global `catalog.url` store when the
|
|
288
|
+
* project declares no store and the first pass leaves something missing.
|
|
289
|
+
*
|
|
290
|
+
* The first pass uses the project stores only, so locally-resolvable refs
|
|
291
|
+
* never trigger a network probe. The fallback retry is best-effort: any error
|
|
292
|
+
* (offline, store down) keeps the first pass's result rather than regressing.
|
|
293
|
+
*/
|
|
294
|
+
async resolveWithStores(deps, opts) {
|
|
295
|
+
const first = await resolveAll(deps, {
|
|
296
|
+
provenanceIndex: opts.provenanceIndex,
|
|
297
|
+
overrides: opts.overrides,
|
|
298
|
+
stores: opts.stores,
|
|
299
|
+
storeFetcher: this.storeFetcherFor(opts.stores),
|
|
300
|
+
projectDir: this.projectDir
|
|
301
|
+
});
|
|
302
|
+
if (first.missing.length === 0) return first;
|
|
303
|
+
const fallback = await this.globalStoreFallback(opts.stores);
|
|
304
|
+
if (fallback.length === 0) return first;
|
|
305
|
+
const stores = [...opts.stores, ...fallback];
|
|
306
|
+
try {
|
|
307
|
+
const retry = await resolveAll(deps, {
|
|
308
|
+
provenanceIndex: opts.provenanceIndex,
|
|
309
|
+
overrides: opts.overrides,
|
|
310
|
+
stores,
|
|
311
|
+
storeFetcher: this.storeFetcherFor(stores),
|
|
312
|
+
projectDir: this.projectDir
|
|
313
|
+
});
|
|
314
|
+
return retry.missing.length < first.missing.length ? retry : first;
|
|
315
|
+
} catch {
|
|
316
|
+
return first;
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
/** The catalog fetcher to use: an injected one, else built from `stores`. */
|
|
320
|
+
storeFetcherFor(stores) {
|
|
321
|
+
return this.injectedStoreFetcher ?? this.buildStoreFetcher(stores);
|
|
322
|
+
}
|
|
323
|
+
/**
|
|
324
|
+
* The global `catalog.url` as a single-store fallback, or `[]` when no
|
|
325
|
+
* project store should be synthesized — `local` sentinel, already-declared,
|
|
326
|
+
* or no URL. Honours an explicit `catalogUrl` injection (`""` disables it).
|
|
327
|
+
*/
|
|
328
|
+
async globalStoreFallback(projectStores) {
|
|
329
|
+
let url = this.catalogUrlOverride;
|
|
330
|
+
if (url === void 0) {
|
|
331
|
+
try {
|
|
332
|
+
const { resolveConfig } = await import('./library/index.js');
|
|
333
|
+
url = resolveConfig({ projectDir: this.projectDir }).catalog.url;
|
|
334
|
+
} catch {
|
|
335
|
+
return [];
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
if (!url || url.trim().toLowerCase() === "local") return [];
|
|
339
|
+
if (projectStores.some((s) => normalizeRepoUrl(s.url) === normalizeRepoUrl(url))) return [];
|
|
340
|
+
return [{ url }];
|
|
341
|
+
}
|
|
342
|
+
/**
|
|
343
|
+
* Build deployable catalog entries from resolved candidates. Store-resolved
|
|
344
|
+
* candidates (no local clone bytes) are fetched + SHA-verified into the
|
|
345
|
+
* project store-cache first, then their entry points at the staged bytes so
|
|
346
|
+
* the existing copy-deploy path works. Source-backed candidates keep the
|
|
347
|
+
* clone-relative entry.
|
|
348
|
+
*/
|
|
349
|
+
async buildCatalogEntries(resolved, repositories) {
|
|
350
|
+
const staged = await this.stageStoreAssets(resolved, repositories);
|
|
351
|
+
const entries = [];
|
|
352
|
+
for (const c of resolved) {
|
|
353
|
+
const stagedPath = staged.get(this.candidateKey(c));
|
|
354
|
+
const entry = stagedPath ? this.stagedCandidateToEntry(c, stagedPath) : this.candidateToCatalogEntry(c, repositories);
|
|
355
|
+
if (entry) entries.push(entry);
|
|
356
|
+
}
|
|
357
|
+
return entries;
|
|
358
|
+
}
|
|
359
|
+
/**
|
|
360
|
+
* Fetch + SHA-verify the bytes of every store-resolved deployable candidate
|
|
361
|
+
* into `.skaile/cache/store/`, reusing the same verified-fetch path the
|
|
362
|
+
* pointer-only `library.install` uses (`installFromManifest` flat mode).
|
|
363
|
+
*
|
|
364
|
+
* @returns Map of candidate key → staged primary-manifest path.
|
|
365
|
+
*/
|
|
366
|
+
async stageStoreAssets(resolved, repositories) {
|
|
367
|
+
const staged = /* @__PURE__ */ new Map();
|
|
368
|
+
let installFromManifest;
|
|
369
|
+
for (const c of resolved) {
|
|
370
|
+
if (NON_DEPLOYABLE_KINDS.has(c.kind)) continue;
|
|
371
|
+
if (!c.files || c.files.length === 0 || !c.sourceUrl || !c.commit) continue;
|
|
372
|
+
if (this.candidateHasLocalBytes(c, repositories)) continue;
|
|
373
|
+
if (!installFromManifest) {
|
|
374
|
+
({ installFromManifest } = await import('./library/index.js'));
|
|
375
|
+
}
|
|
376
|
+
const targetDir = join(this.storeCacheDir, c.publisher, c.kind, c.name, c.version);
|
|
377
|
+
const cacheRoot = resolve(this.storeCacheDir);
|
|
378
|
+
if (!resolve(targetDir).startsWith(cacheRoot + sep)) {
|
|
379
|
+
throw new Error(`unsafe store-cache path for ${this.candidateKey(c)}`);
|
|
380
|
+
}
|
|
381
|
+
const manifest = {
|
|
382
|
+
ref: `${c.kind}:@${c.publisher}/${c.name}#${c.version}`,
|
|
383
|
+
source: { url: c.sourceUrl, commitSha: c.commit },
|
|
384
|
+
files: c.files,
|
|
385
|
+
sha256: c.sha256,
|
|
386
|
+
kind: c.kind,
|
|
387
|
+
// tier = catalog storage hint (S3/CDN); flat-mode verified fetch pulls
|
|
388
|
+
// from source.url@commit and ignores it, so "" is inert.
|
|
389
|
+
tier: ""
|
|
390
|
+
};
|
|
391
|
+
const { installPath } = await installFromManifest({
|
|
392
|
+
manifest,
|
|
393
|
+
libraryRoot: this.storeCacheDir,
|
|
394
|
+
targetDir,
|
|
395
|
+
fetcher: this.injectedAssetFetcher
|
|
396
|
+
});
|
|
397
|
+
staged.set(this.candidateKey(c), join(installPath, this.stagedManifestRel(c)));
|
|
398
|
+
}
|
|
399
|
+
return staged;
|
|
400
|
+
}
|
|
401
|
+
/** Repo-relative path of a candidate's primary manifest (un-stripped). */
|
|
402
|
+
primaryManifestRel(c) {
|
|
403
|
+
const paths = (c.files ?? []).map((f) => f.path);
|
|
404
|
+
return matchManifestPath(c.kind, paths) ?? paths[0];
|
|
405
|
+
}
|
|
406
|
+
/**
|
|
407
|
+
* The primary-manifest path relative to a staged asset dir. Takes the kind's
|
|
408
|
+
* manifest (e.g. `SKILL.md`), then strips the same common-dir prefix
|
|
409
|
+
* `installFromManifest` flat mode removed on write.
|
|
410
|
+
*/
|
|
411
|
+
stagedManifestRel(c) {
|
|
412
|
+
const paths = (c.files ?? []).map((f) => f.path);
|
|
413
|
+
const mdRel = this.primaryManifestRel(c) ?? "";
|
|
414
|
+
const root = commonDirPrefix(paths);
|
|
415
|
+
return root && mdRel.startsWith(`${root}/`) ? mdRel.slice(root.length + 1) : mdRel;
|
|
416
|
+
}
|
|
417
|
+
/**
|
|
418
|
+
* `true` when a candidate's primary manifest is present on a local source
|
|
419
|
+
* clone — its `sourceUrl` matches a registered source AND the manifest file
|
|
420
|
+
* exists on disk at the expected path. A URL match alone is not enough: a
|
|
421
|
+
* store can pin a different commit (or a subtree not bundled) of a repo that
|
|
422
|
+
* is also a registered source, in which case the bytes must be fetched from
|
|
423
|
+
* the store rather than read from the clone. (Only the primary manifest is
|
|
424
|
+
* probed — a partially-cloned source is deployed as-is, matching the existing
|
|
425
|
+
* clone-deploy path.)
|
|
426
|
+
*/
|
|
427
|
+
candidateHasLocalBytes(c, repositories) {
|
|
428
|
+
if (!c.sourceUrl) return false;
|
|
429
|
+
const rel = this.primaryManifestRel(c);
|
|
430
|
+
for (const [slug, decl] of Object.entries(repositories)) {
|
|
431
|
+
if (decl.url === void 0 || decl.url !== c.sourceUrl) continue;
|
|
432
|
+
const dir = this.resolveRepoDir(decl, slug);
|
|
433
|
+
if (!dir) continue;
|
|
434
|
+
if (existsSync(rel ? join(dir, rel) : dir)) return true;
|
|
435
|
+
}
|
|
436
|
+
return false;
|
|
437
|
+
}
|
|
438
|
+
/** Build a copy-deploy catalog entry pointing at staged store bytes. */
|
|
439
|
+
stagedCandidateToEntry(c, stagedManifestPath) {
|
|
440
|
+
const entry = {
|
|
441
|
+
name: c.name,
|
|
442
|
+
kind: c.kind,
|
|
443
|
+
description: c.description ?? "",
|
|
444
|
+
source: stagedManifestPath,
|
|
445
|
+
// Real publisher (never a clone slug) → deployAsset copies rather than
|
|
446
|
+
// symlinking the ephemeral store-cache dir.
|
|
447
|
+
publisher: c.publisher,
|
|
448
|
+
version: c.version,
|
|
449
|
+
requires: [],
|
|
450
|
+
dependencies: c.deps ?? [],
|
|
451
|
+
metadata: c.metadata
|
|
452
|
+
};
|
|
453
|
+
if (c.category != null) entry.category = c.category;
|
|
454
|
+
if (c.keywords && c.keywords.length > 0) entry.keywords = c.keywords;
|
|
455
|
+
if (c.license != null) entry.license = c.license;
|
|
456
|
+
if (c.homepage != null) entry.homepage = c.homepage;
|
|
457
|
+
return entry;
|
|
458
|
+
}
|
|
218
459
|
// ── Install / resolve ──────────────────────────────────────────────────
|
|
219
460
|
/**
|
|
220
461
|
* Install all dependencies declared in `skaile.yaml`.
|
|
@@ -237,15 +478,13 @@ var AssetManager = class {
|
|
|
237
478
|
const provenanceIndex = buildProvenanceIndex(this.buildClones(repositories), {
|
|
238
479
|
projectDir: this.projectDir
|
|
239
480
|
});
|
|
240
|
-
const { resolved, missing, overridesApplied } = await
|
|
481
|
+
const { resolved, missing, overridesApplied } = await this.resolveWithStores(dependencies, {
|
|
241
482
|
provenanceIndex,
|
|
242
483
|
overrides,
|
|
243
|
-
stores
|
|
244
|
-
storeFetcher: this.buildStoreFetcher(stores),
|
|
245
|
-
projectDir: this.projectDir
|
|
484
|
+
stores
|
|
246
485
|
});
|
|
247
486
|
const removed = this.reconcileRemovedAssets(resolved);
|
|
248
|
-
const entries =
|
|
487
|
+
const entries = await this.buildCatalogEntries(resolved, repositories);
|
|
249
488
|
const deployed = deployAll(entries, repositories, patches, this.deployOpts);
|
|
250
489
|
writeLock(this.lockPath, buildLockFile(resolved, overridesApplied));
|
|
251
490
|
this.recordInstallHistory(deployed, removed);
|
|
@@ -453,19 +692,17 @@ var AssetManager = class {
|
|
|
453
692
|
const provenanceIndex = buildProvenanceIndex(this.buildClones(repositories), {
|
|
454
693
|
projectDir: this.projectDir
|
|
455
694
|
});
|
|
456
|
-
const { resolved, missing } = await
|
|
695
|
+
const { resolved, missing } = await this.resolveWithStores([ref], {
|
|
457
696
|
provenanceIndex,
|
|
458
697
|
overrides,
|
|
459
|
-
stores
|
|
460
|
-
storeFetcher: this.buildStoreFetcher(stores),
|
|
461
|
-
projectDir: this.projectDir
|
|
698
|
+
stores
|
|
462
699
|
});
|
|
463
700
|
if (resolved.length === 0) {
|
|
464
701
|
throw new Error(
|
|
465
702
|
`Asset not found: ${ref}${missing.length ? ` (missing: ${missing.join(", ")})` : ""}`
|
|
466
703
|
);
|
|
467
704
|
}
|
|
468
|
-
const entries =
|
|
705
|
+
const entries = await this.buildCatalogEntries(resolved, repositories);
|
|
469
706
|
const deployed = deployAll(entries, repositories, patches, this.deployOpts);
|
|
470
707
|
this.addDependencyToConfig(ref);
|
|
471
708
|
for (const d of deployed) {
|
|
@@ -590,6 +827,65 @@ var AssetManager = class {
|
|
|
590
827
|
}
|
|
591
828
|
return result;
|
|
592
829
|
}
|
|
830
|
+
/**
|
|
831
|
+
* List the **declared** top-level dependencies from `skaile.yaml`, each tagged
|
|
832
|
+
* with a reconciliation {@link DeclaredState}:
|
|
833
|
+
*
|
|
834
|
+
* - `declared` — in `skaile.yaml`, not yet resolved into the lock.
|
|
835
|
+
* - `installed` — declared + locked, and (for deployable kinds) materialized on
|
|
836
|
+
* disk. Non-deployable kinds ({@link NON_DEPLOYABLE_KINDS}) count as installed
|
|
837
|
+
* once locked — they are wired at session start, never written to the target dir.
|
|
838
|
+
* - `drift` — declared + locked but the deployed files are missing on disk.
|
|
839
|
+
* - `invalid` — the `dependencies:` entry isn't a parseable canonical ref. Only
|
|
840
|
+
* surfaced in the unfiltered listing (a `kind` filter can't classify it).
|
|
841
|
+
*
|
|
842
|
+
* Transitive (lock-only) deps are excluded by construction — only the declared
|
|
843
|
+
* set is walked, so a lock entry with no matching `dependencies:` ref never shows.
|
|
844
|
+
*
|
|
845
|
+
* @param kind - Filter by asset kind. Omit to return all kinds.
|
|
846
|
+
* @returns One {@link DeclaredAsset} per declared dep (after the optional kind filter).
|
|
847
|
+
* @throws {MissingManifestError} when the project has no `skaile.yaml`.
|
|
848
|
+
* @throws {Error} with a `migrate-skaile-manifest` hint on legacy `repositories:` / `ai_resources:` keys.
|
|
849
|
+
*/
|
|
850
|
+
listDeclared(kind) {
|
|
851
|
+
if (!existsSync(join(this.projectDir, SKAILE_YAML_DEFAULT))) {
|
|
852
|
+
throw new MissingManifestError(this.projectDir);
|
|
853
|
+
}
|
|
854
|
+
const dependencies = resolveSkWorkspaceConfig(this.projectDir).dependencies ?? [];
|
|
855
|
+
const lock = this.tryReadLock();
|
|
856
|
+
const lockKeys = lock ? Object.keys(lock.assets).map(parseCanonicalLockKey) : [];
|
|
857
|
+
const out = [];
|
|
858
|
+
for (const ref of dependencies) {
|
|
859
|
+
let parsed;
|
|
860
|
+
try {
|
|
861
|
+
parsed = parseAssetRef(ref);
|
|
862
|
+
} catch {
|
|
863
|
+
if (!kind) out.push({ ref, kind: "", name: ref, state: "invalid" });
|
|
864
|
+
continue;
|
|
865
|
+
}
|
|
866
|
+
if (kind && parsed.kind !== kind) continue;
|
|
867
|
+
const locked = lockKeys.some(
|
|
868
|
+
(k) => k.kind === parsed.kind && k.name === parsed.name && (!parsed.publisher || k.publisher === parsed.publisher)
|
|
869
|
+
);
|
|
870
|
+
let state;
|
|
871
|
+
if (!locked) {
|
|
872
|
+
state = "declared";
|
|
873
|
+
} else if (NON_DEPLOYABLE_KINDS.has(parsed.kind)) {
|
|
874
|
+
state = "installed";
|
|
875
|
+
} else {
|
|
876
|
+
const onDisk = isDeployed(
|
|
877
|
+
parsed.kind,
|
|
878
|
+
parsed.name,
|
|
879
|
+
this.driverTarget,
|
|
880
|
+
this.global,
|
|
881
|
+
this.projectDir
|
|
882
|
+
);
|
|
883
|
+
state = onDisk ? "installed" : "drift";
|
|
884
|
+
}
|
|
885
|
+
out.push({ ref, kind: parsed.kind, name: parsed.name, state });
|
|
886
|
+
}
|
|
887
|
+
return out;
|
|
888
|
+
}
|
|
593
889
|
/**
|
|
594
890
|
* Build an aggregated workspace overview with domain grouping and sync status.
|
|
595
891
|
*
|
|
@@ -739,12 +1035,10 @@ var AssetManager = class {
|
|
|
739
1035
|
const provenanceIndex = buildProvenanceIndex(this.buildClones(repositories), {
|
|
740
1036
|
projectDir: this.projectDir
|
|
741
1037
|
});
|
|
742
|
-
const { resolved, overridesApplied } = await
|
|
1038
|
+
const { resolved, overridesApplied } = await this.resolveWithStores(dependencies, {
|
|
743
1039
|
provenanceIndex,
|
|
744
1040
|
overrides,
|
|
745
|
-
stores
|
|
746
|
-
storeFetcher: this.buildStoreFetcher(stores),
|
|
747
|
-
projectDir: this.projectDir
|
|
1041
|
+
stores
|
|
748
1042
|
});
|
|
749
1043
|
const lockData = buildLockFile(resolved, overridesApplied);
|
|
750
1044
|
writeLock(this.lockPath, lockData);
|
|
@@ -911,8 +1205,8 @@ var AssetManager = class {
|
|
|
911
1205
|
* Remove deployed assets tracked by the lock file and report unmanaged ones.
|
|
912
1206
|
*
|
|
913
1207
|
* With `opts.all`, also deletes `.skaile/history.yaml`, `.skaile/patches/`,
|
|
914
|
-
* `.skaile/
|
|
915
|
-
* to a pre-install state.
|
|
1208
|
+
* `.skaile/cache/sources/`, and `skaile.lock.yaml` — effectively resetting the
|
|
1209
|
+
* workspace to a pre-install state.
|
|
916
1210
|
*
|
|
917
1211
|
* @param opts - Optional cleanup options.
|
|
918
1212
|
* @param opts.all - When `true`, remove all Skaile-managed state in addition to deployed assets.
|
|
@@ -976,7 +1270,7 @@ var AssetManager = class {
|
|
|
976
1270
|
}
|
|
977
1271
|
return unmanaged;
|
|
978
1272
|
}
|
|
979
|
-
/** Delete all Skaile-managed state: history file, patches/,
|
|
1273
|
+
/** Delete all Skaile-managed state: history file, patches/, cache/sources/, lock. */
|
|
980
1274
|
removeAllManagedState() {
|
|
981
1275
|
const historyFile = join(this.projectDir, ".skaile", "history.yaml");
|
|
982
1276
|
try {
|
|
@@ -1039,6 +1333,6 @@ var AssetManager = class {
|
|
|
1039
1333
|
}
|
|
1040
1334
|
};
|
|
1041
1335
|
|
|
1042
|
-
export { AssetManager, parseCanonicalLockKey };
|
|
1043
|
-
//# sourceMappingURL=chunk-
|
|
1044
|
-
//# sourceMappingURL=chunk-
|
|
1336
|
+
export { AssetManager, MissingManifestError, NON_DEPLOYABLE_KINDS, parseCanonicalLockKey };
|
|
1337
|
+
//# sourceMappingURL=chunk-L6BKSTAX.js.map
|
|
1338
|
+
//# sourceMappingURL=chunk-L6BKSTAX.js.map
|