@skaile/workspaces 3.9.2 → 3.10.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 +8 -0
- package/dist/{asset-feeds-HDVT2H2A.js → asset-feeds-DT4B37Z3.js} +4 -4
- package/dist/{asset-feeds-HDVT2H2A.js.map → asset-feeds-DT4B37Z3.js.map} +1 -1
- package/dist/asset-manager/index.js +1 -1
- package/dist/{chunk-HGFKNJA5.js → chunk-2D5BYAL6.js} +23 -4
- package/dist/chunk-2D5BYAL6.js.map +1 -0
- package/dist/{chunk-SBTIOWO4.js → chunk-4D4N2VFR.js} +6 -6
- package/dist/{chunk-SBTIOWO4.js.map → chunk-4D4N2VFR.js.map} +1 -1
- package/dist/{chunk-4E47LSC2.js → chunk-7NRZGSTY.js} +2 -2
- package/dist/{chunk-4E47LSC2.js.map → chunk-7NRZGSTY.js.map} +1 -1
- package/dist/{chunk-SBDSTWS3.js → chunk-7WTXE6YS.js} +2 -2
- package/dist/{chunk-SBDSTWS3.js.map → chunk-7WTXE6YS.js.map} +1 -1
- package/dist/{chunk-5EYIOIDR.js → chunk-A5Y2O23Y.js} +6 -6
- package/dist/{chunk-5EYIOIDR.js.map → chunk-A5Y2O23Y.js.map} +1 -1
- package/dist/{chunk-324O5R6K.js → chunk-DQ5MUABO.js} +3 -3
- package/dist/{chunk-324O5R6K.js.map → chunk-DQ5MUABO.js.map} +1 -1
- package/dist/{chunk-M3XON6YS.js → chunk-GE3EDS2M.js} +25 -10
- package/dist/chunk-GE3EDS2M.js.map +1 -0
- package/dist/{chunk-67XFU42M.js → chunk-H6KQB6HL.js} +12 -7
- package/dist/chunk-H6KQB6HL.js.map +1 -0
- package/dist/{chunk-KFUT5YTA.js → chunk-KBAYZ6DK.js} +3 -3
- package/dist/{chunk-KFUT5YTA.js.map → chunk-KBAYZ6DK.js.map} +1 -1
- package/dist/{chunk-3YIW3L25.js → chunk-SI7WZARX.js} +4 -4
- package/dist/{chunk-3YIW3L25.js.map → chunk-SI7WZARX.js.map} +1 -1
- package/dist/{chunk-GTXKA4D6.js → chunk-XDAOECL4.js} +3 -3
- package/dist/{chunk-GTXKA4D6.js.map → chunk-XDAOECL4.js.map} +1 -1
- package/dist/cli/index.js +27 -27
- package/dist/connectors/index.js +2 -2
- package/dist/{ensure-sources-RVWUI3CD.js → ensure-sources-HS66JB6Y.js} +4 -4
- package/dist/{ensure-sources-RVWUI3CD.js.map → ensure-sources-HS66JB6Y.js.map} +1 -1
- package/dist/factory-assets/connectors/box.js +2 -2
- package/dist/factory-assets/connectors/deploy.js +2 -2
- package/dist/factory-assets/connectors/devserver.js +2 -2
- package/dist/factory-assets/connectors/flow/CONNECTOR.md +14 -6
- package/dist/factory-assets/connectors/flow/adapter.d.ts +4 -3
- package/dist/factory-assets/connectors/flow/adapter.d.ts.map +1 -1
- package/dist/factory-assets/connectors/flow/adapter.js +2 -2
- package/dist/factory-assets/connectors/flow/prompt-fragments.d.ts.map +1 -1
- package/dist/factory-assets/connectors/flow/prompt-fragments.js +1 -1
- package/dist/factory-assets/connectors/flow/run-flow.js +3 -3
- package/dist/factory-assets/connectors/flow.js +2 -2
- package/dist/factory-assets/connectors/git.js +2 -2
- package/dist/factory-assets/connectors/gmail.js +2 -2
- package/dist/factory-assets/connectors/googledrive.js +2 -2
- package/dist/factory-assets/connectors/local.js +2 -2
- package/dist/factory-assets/connectors/mattermost.js +2 -2
- package/dist/factory-assets/connectors/memory.js +2 -2
- package/dist/factory-assets/connectors/minio.js +2 -2
- package/dist/factory-assets/connectors/postgres.js +2 -2
- package/dist/factory-assets/connectors/s3.js +2 -2
- package/dist/factory-assets/connectors/sharepoint.js +2 -2
- package/dist/factory-assets/connectors/sqlite.js +2 -2
- package/dist/factory-assets/connectors/static-server.js +2 -2
- package/dist/factory-assets/connectors/tunnel.js +2 -2
- package/dist/factory-assets/connectors/webdav.js +2 -2
- package/dist/factory-assets/connectors/xstate-store.js +2 -2
- package/dist/factory-assets/connectors/xstate.js +2 -2
- package/dist/{helpers-3P3UA2GP.js → helpers-GPD3WJQQ.js} +4 -4
- package/dist/{helpers-3P3UA2GP.js.map → helpers-GPD3WJQQ.js.map} +1 -1
- package/dist/{library-publish-MSOMO5DJ.js → library-publish-T7VSMTGZ.js} +6 -6
- package/dist/{library-publish-MSOMO5DJ.js.map → library-publish-T7VSMTGZ.js.map} +1 -1
- package/dist/{open-library-4LQIWUA7.js → open-library-FGHDS7AZ.js} +5 -5
- package/dist/{open-library-4LQIWUA7.js.map → open-library-FGHDS7AZ.js.map} +1 -1
- package/dist/{project-D6KNP6EF.js → project-GU7X4WO2.js} +5 -5
- package/dist/{project-D6KNP6EF.js.map → project-GU7X4WO2.js.map} +1 -1
- package/dist/runner/index.js +5 -5
- package/dist/runner/src/serve.d.ts.map +1 -1
- package/dist/sdk/asset-manager.js +1 -1
- package/dist/sdk/index.js +5 -5
- package/dist/sdk/runner.js +5 -5
- package/dist/{source-3MIFZTMX.js → source-5GTOJ4SD.js} +6 -6
- package/dist/{source-3MIFZTMX.js.map → source-5GTOJ4SD.js.map} +1 -1
- package/dist/{source-manifest-publish-YBMVHMOX.js → source-manifest-publish-KR5MXXGD.js} +7 -7
- package/dist/{source-manifest-publish-YBMVHMOX.js.map → source-manifest-publish-KR5MXXGD.js.map} +1 -1
- package/dist/tui/index.js +5 -5
- package/dist/workspace-plugin/index.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-67XFU42M.js.map +0 -1
- package/dist/chunk-HGFKNJA5.js.map +0 -1
- package/dist/chunk-M3XON6YS.js.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 3.10.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [#600](https://github.com/skaile-ai/workspaces/pull/600) [`547a7ca`](https://github.com/skaile-ai/workspaces/commit/547a7ca91025a2f99043833cd6c9e579bce5909a) Thanks [@henkbla](https://github.com/henkbla)! - Approving an escalated `check` node is now a human override: `applyApproval` accepts `"approved"` when given a non-empty reason, completes the node so the flow advances, and records the decision without rewriting the observation (`CheckEvidence.passed` stays `false`); `"rejected"` remains terminal. The orchestrator prompt now describes a decided check the way it already describes a decided gate, so the agent no longer calls `complete_node` on a node that rejects it.
|
|
8
|
+
|
|
9
|
+
The override is refused when a downstream node consumes the check's declared `contract.output.fields` and the failed attempt does not satisfy them — completing the node there would write an execution that fails to hydrate. A later turn keeps the override visible through a durable "Checks completed by human override" prompt section, and a reason-less override replayed through `hydrate`'s `pendingDecisions` reports `payload_invalid` rather than `not_parked`.
|
|
10
|
+
|
|
3
11
|
## 3.9.2
|
|
4
12
|
|
|
5
13
|
### Patch Changes
|
|
@@ -65,7 +65,7 @@ async function libraryAssets() {
|
|
|
65
65
|
const domains = [];
|
|
66
66
|
try {
|
|
67
67
|
const [{ openLibraryManager }, { skaileHomeDir }, { getGlobalCacheDir }] = await Promise.all([
|
|
68
|
-
import('./open-library-
|
|
68
|
+
import('./open-library-FGHDS7AZ.js'),
|
|
69
69
|
import('./library/index.js'),
|
|
70
70
|
import('./core/index.js')
|
|
71
71
|
]);
|
|
@@ -98,7 +98,7 @@ async function libraryAssets() {
|
|
|
98
98
|
async function storeAssets(projectDir) {
|
|
99
99
|
const notes = [];
|
|
100
100
|
try {
|
|
101
|
-
const { resolveCatalogSource } = await import('./open-library-
|
|
101
|
+
const { resolveCatalogSource } = await import('./open-library-FGHDS7AZ.js');
|
|
102
102
|
const { source, close } = await resolveCatalogSource({ projectDir });
|
|
103
103
|
try {
|
|
104
104
|
const assets = await source.listAssets();
|
|
@@ -202,5 +202,5 @@ function dedupeBySlug(domains) {
|
|
|
202
202
|
}
|
|
203
203
|
|
|
204
204
|
export { gatherAssetFeeds };
|
|
205
|
-
//# sourceMappingURL=asset-feeds-
|
|
206
|
-
//# sourceMappingURL=asset-feeds-
|
|
205
|
+
//# sourceMappingURL=asset-feeds-DT4B37Z3.js.map
|
|
206
|
+
//# sourceMappingURL=asset-feeds-DT4B37Z3.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../cli/src/asset-feeds.ts"],"names":[],"mappings":"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","file":"asset-feeds-HDVT2H2A.js","sourcesContent":["/**\n * asset-feeds.ts — gather installable assets from every feed the manage TUI\n * surfaces.\n *\n * Four feeds, normalized into `CatalogEntry`:\n * - **Project sources** — `skaile.yaml` `sources:` entries (scanned via\n * `AssetManager.search()`; the new `sources:` field is merged into the\n * legacy repositories map in `AssetManager.loadConfig`).\n * - **Local libraries** — user authoring places from `LocalIndex` (filesystem\n * scan of each library's `path`).\n * - **Factory assets** — the bundled first-party `factory-assets` tree\n * (`factoryAssetRoots()`), scanned from disk. Always present; no network.\n * - **Remote store** — the configured catalog source when `catalog.url` is\n * not `local`. Failures are non-fatal — they surface as notes.\n */\n\nimport { existsSync, readFileSync } from \"node:fs\";\nimport * as path from \"node:path\";\nimport {\n type AssetKind,\n type CatalogDomain,\n type CatalogEntry,\n factoryAssetRoots,\n parseFrontmatter,\n scanRepo,\n walkDir,\n} from \"@skaile/workspaces/core\";\nimport {\n assignDomain,\n buildDomainIndex,\n DOMAIN_MD_FILENAME,\n type DomainMd,\n parseDomainMd,\n} from \"@skaile/workspaces/discovery\";\n\n/** One non-fatal note returned to the caller for surfacing in the UI. */\nexport interface FeedNote {\n feed: \"sources\" | \"libraries\" | \"store\" | \"factory\";\n message: string;\n}\n\n/**\n * Which feed an asset came from. This is the top-level grouping axis in the\n * manage TUI (\"where is this skill coming from?\") and is intentionally distinct\n * from `publisher` (asset-intrinsic identity): the same publisher can legitimately\n * appear under more than one origin (e.g. a github repo you added as a `source`\n * that is also listed in the remote `store`).\n */\nexport type AssetOrigin = \"source\" | \"library\" | \"factory\" | \"store\";\n\n/** A catalog entry tagged with the feed it was gathered from. */\nexport interface OriginEntry {\n origin: AssetOrigin;\n entry: CatalogEntry;\n /**\n * Second-level grouping label for the manage tree. Defaults (when unset) to the\n * entry's `publisher`; the source feed sets it to the source's short repo name\n * so the Sources band groups by source — \"which repo did this come from\" — not\n * by the asset-intrinsic publisher.\n */\n group?: string;\n}\n\nexport interface AssetFeedResult {\n entries: OriginEntry[];\n /**\n * Display-only domain metadata, keyed (by the consumer) on `slug`. Populated\n * from the store's `catalog.listDomains` when the connected catalog source\n * exposes it; empty otherwise. The manage TUI joins `entry.domainSlug` → a\n * domain for grouping headers, descriptions, and relation badges.\n */\n domains: CatalogDomain[];\n notes: FeedNote[];\n}\n\n// ── Domain stamping (on-disk feeds) ──────────────────────────────────────────\n//\n// `scanRepo` (the source / library / factory scan path) does not read the\n// `DOMAIN.md` sidecars, so its entries arrive with no `domainSlug` and render\n// flat under their publisher band. We re-derive the grouping here from the\n// root's `DOMAIN.md` files (the same sidecars the remote store computes\n// server-side), and fall back to the repo/source name for any entry no domain\n// claims so it still groups instead of landing in the synthetic \"no domain\" pile.\n\n/** Repo-relative POSIX path (DOMAIN.md slugs are matched whole-segment, `/`-joined). */\nfunction toPosix(p: string): string {\n return p.split(path.sep).join(\"/\");\n}\n\n/** Parse every `DOMAIN.md` sidecar under `root` into a {@link DomainMd}. */\nasync function loadDomainMds(root: string): Promise<DomainMd[]> {\n const out: DomainMd[] = [];\n for await (const { path: filePath, name } of walkDir(root)) {\n if (name !== DOMAIN_MD_FILENAME) continue;\n try {\n const { data } = parseFrontmatter(readFileSync(filePath, \"utf8\"));\n out.push(parseDomainMd(toPosix(path.relative(root, filePath)), data));\n } catch {}\n }\n return out;\n}\n\n/**\n * Stamp `domainSlug` onto every entry scanned from `root` using the root's\n * `DOMAIN.md` sidecars. Returns the `CatalogDomain` registry for the real\n * domains, plus a synthetic fallback domain when any entry used the fallback.\n * Mutates `entries` in place (sets `entry.domainSlug`).\n *\n * `synthesizeFallback` (default true): entries no domain claims fall back to\n * `fallbackSlug` (the repo/source name). Pass `false` when the caller already\n * groups these entries one level up (e.g. the source feed groups by source\n * node) — unmatched entries then get no domain (`\"\"`) and hang directly under\n * that parent, instead of nesting under a same-named fallback domain.\n */\nasync function stampDomains(\n root: string,\n fallbackSlug: string,\n entries: CatalogEntry[],\n synthesizeFallback = true,\n): Promise<CatalogDomain[]> {\n const domainMds = await loadDomainMds(root);\n const assignables = entries.map((entry) => ({\n entry,\n ref: `${entry.kind}:${entry.name}`,\n relativePath: toPosix(path.relative(root, entry.source)),\n }));\n\n let usedFallback = false;\n for (const a of assignables) {\n const slug = assignDomain(a.relativePath, domainMds);\n if (slug) a.entry.domainSlug = slug;\n else if (synthesizeFallback) {\n a.entry.domainSlug = fallbackSlug;\n usedFallback = true;\n } else a.entry.domainSlug = \"\";\n }\n\n const { index } = buildDomainIndex(assignables, domainMds);\n const catalog: CatalogDomain[] = Object.values(index).map((d) => ({\n slug: d.slug,\n title: d.title,\n ...(d.description ? { description: d.description } : {}),\n ...(d.relation ? { relation: d.relation } : {}),\n ...(d.order !== undefined ? { order: d.order } : {}),\n ...(d.recommended[0] ? { recommendedRef: d.recommended[0] } : {}),\n }));\n if (usedFallback) catalog.push({ slug: fallbackSlug, title: fallbackSlug });\n return catalog;\n}\n\n/**\n * Pull assets from local libraries (the authoring places under\n * `~/.skaile/libraries/<name>/`, not the `~/.skaile/cache/sources/` cache). Each\n * library's `path` is scanned with `scanRepo` and grouped under the bare library\n * name (`group: <name>`) so the manage TUI shows a clean `<name>` band — no\n * `library:` prefix and no redundant same-named fallback domain (mirrors the\n * source feed).\n */\nasync function libraryAssets(): Promise<{\n entries: OriginEntry[];\n domains: CatalogDomain[];\n notes: FeedNote[];\n}> {\n const notes: FeedNote[] = [];\n const domains: CatalogDomain[] = [];\n try {\n const [{ openLibraryManager }, { skaileHomeDir }, { getGlobalCacheDir }] = await Promise.all([\n import(\"./open-library.ts\"),\n import(\"@skaile/workspaces/library\"),\n import(\"@skaile/workspaces/core\"),\n ]);\n const { manager, close } = await openLibraryManager();\n try {\n // Authoring libraries are the rows that are NOT source clones. index.db\n // rows predating the cache migration still carry the legacy\n // ~/.skaile/sources path, so exclude both roots.\n const newRoot = getGlobalCacheDir();\n const legacyRoot = path.join(skaileHomeDir(), \"sources\");\n const libs = (await manager.listLibraries()).filter(\n (l) => !l.path.startsWith(newRoot) && !l.path.startsWith(legacyRoot),\n );\n const entries: OriginEntry[] = [];\n for (const lib of libs) {\n if (!existsSync(lib.path)) continue;\n // Scan + group under the bare library name. `synthesizeFallback: false`\n // (as the source feed does) keeps domainless assets directly under the\n // library band instead of a redundant same-named fallback domain.\n const libEntries = [...(await scanRepo(lib.path, lib.name))];\n domains.push(...(await stampDomains(lib.path, lib.name, libEntries, false)));\n for (const entry of libEntries) entries.push({ origin: \"library\", entry, group: lib.name });\n }\n return { entries, domains, notes };\n } finally {\n close();\n }\n } catch (err) {\n notes.push({\n feed: \"libraries\",\n message: err instanceof Error ? err.message : String(err),\n });\n return { entries: [], domains, notes };\n }\n}\n\n/**\n * Pull a (best-effort) snapshot of the connected remote store catalog.\n *\n * - Returns no entries when the resolved catalog is local-only or the host\n * is unreachable (the failure becomes a note, not an exception).\n * - Maps `CatalogAsset` → `CatalogEntry`, carrying `publisher`, `repo`, and\n * `category` straight through and using `source = \"store://<id>\"`; per-file\n * `source` paths are not available for remote assets so the canonical ref is\n * a stable placeholder.\n */\nasync function storeAssets(projectDir: string): Promise<{\n entries: CatalogEntry[];\n domains: CatalogDomain[];\n notes: FeedNote[];\n}> {\n const notes: FeedNote[] = [];\n try {\n const { resolveCatalogSource } = await import(\"./open-library.ts\");\n const { source, close } = await resolveCatalogSource({ projectDir });\n try {\n const assets = await source.listAssets();\n const entries: CatalogEntry[] = assets.map((a) => ({\n name: a.name,\n kind: (a.kind as AssetKind) ?? \"skill\",\n description: a.description ?? \"\",\n source: `store://${a.id}`,\n publisher: a.publisher,\n repo: a.repo,\n domainSlug: a.domainSlug,\n category: a.category,\n version: a.version,\n requires: [],\n dependencies: [],\n }));\n // Domains are optional on the catalog source — only the store backend\n // (post Part 4 `catalog.listDomains`) exposes them. Duck-type the call so\n // older sources and the local catalog degrade to no domains, not an error.\n const domains = await loadDomains(source);\n return { entries, domains, notes };\n } finally {\n close();\n }\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n // Local-only catalog throws a recognizable message — silence it; absence\n // is the user's choice, not an error.\n if (!/local/i.test(msg)) {\n notes.push({ feed: \"store\", message: msg });\n }\n return { entries: [], domains: [], notes };\n }\n}\n\n/** Optional `listDomains` capability — returns `[]` when the source lacks it. */\nasync function loadDomains(source: unknown): Promise<CatalogDomain[]> {\n const fn = (source as { listDomains?: () => Promise<CatalogDomain[]> }).listDomains;\n if (typeof fn !== \"function\") return [];\n const domains = await fn.call(source);\n return Array.isArray(domains) ? domains : [];\n}\n\n/** The slice of `AssetManager` the source feed needs (kept narrow for tests). */\ninterface AssetManagerLike {\n search: () => Promise<CatalogEntry[]>;\n searchRepoRoots: () => { repoName: string; root: string }[];\n}\n\n/**\n * Project-source feed: leans on `AssetManager.search()`, which now merges\n * `skaile.yaml`'s `sources:` field into the repositories map, then stamps\n * `DOMAIN.md`-derived domain grouping onto the scanned entries via\n * `searchRepoRoots()`.\n */\nasync function sourceAssets(\n am: AssetManagerLike,\n): Promise<{ entries: OriginEntry[]; domains: CatalogDomain[] }> {\n // The bundled factory tree is injected into the repositories map as an implicit\n // source, so `am.search()` returns it too. It has its own `factory` origin band,\n // so drop it here — otherwise the same first-party skills list twice under Sources.\n const factoryPrefixes = factoryAssetRoots().map((r) => (r.endsWith(path.sep) ? r : r + path.sep));\n const isFactoryPath = (p: string) =>\n factoryPrefixes.some((fp) => p === fp.slice(0, -1) || p.startsWith(fp));\n\n const all = (await am.search()).filter((e) => !isFactoryPath(e.source));\n const entries: OriginEntry[] = [];\n const domains: CatalogDomain[] = [];\n // Group each source's entries under the source node (its short repo name), not\n // the publisher: under Sources the navigational question is \"which repo did\n // this come from\". Each entry's `source` (absolute manifest path) lives under\n // exactly one declared root, so group + stamp by prefix. The cache slug is\n // URL-keyed `github.com/<org>/<repo>` — take the trailing segment.\n for (const { repoName, root } of am.searchRepoRoots()) {\n if (isFactoryPath(root)) continue;\n const prefix = root.endsWith(path.sep) ? root : root + path.sep;\n const owned = all.filter((e) => e.source === root || e.source.startsWith(prefix));\n if (owned.length === 0) continue;\n const sourceName = repoName.split(\"/\").pop() || repoName;\n // No synthetic fallback domain — the source node already groups these, so a\n // same-named fallback would just nest the source under itself.\n domains.push(...(await stampDomains(root, sourceName, owned, false)));\n for (const entry of owned) entries.push({ origin: \"source\", entry, group: sourceName });\n }\n return { entries, domains };\n}\n\n/**\n * Factory-asset feed: scan the bundled first-party `factory-assets` tree(s)\n * resolved by `factoryAssetRoots()` (the `SKAILE_FACTORY_ASSETS_DIR` override\n * layer ahead of the bundled tree). Local disk only, no network — the entries are\n * the built-in skills / connectors / bundles that ship with `@skaile/workspaces`.\n * `factoryAssetRoots()` already dedupes, so the env override pointing at the\n * bundled dir collapses to one root.\n */\nasync function factoryAssets(): Promise<{\n entries: CatalogEntry[];\n domains: CatalogDomain[];\n notes: FeedNote[];\n}> {\n const notes: FeedNote[] = [];\n const domains: CatalogDomain[] = [];\n try {\n const entries: CatalogEntry[] = [];\n for (const root of factoryAssetRoots()) {\n const rootEntries = [...(await scanRepo(root, \"skaile-factory\"))];\n domains.push(...(await stampDomains(root, \"skaile-factory\", rootEntries)));\n entries.push(...rootEntries);\n }\n return { entries, domains, notes };\n } catch (err) {\n notes.push({\n feed: \"factory\",\n message: err instanceof Error ? err.message : String(err),\n });\n return { entries: [], domains, notes };\n }\n}\n\n/** Tag a flat entry list with a single origin. */\nfunction tag(origin: AssetOrigin, entries: CatalogEntry[]): OriginEntry[] {\n return entries.map((entry) => ({ origin, entry }));\n}\n\n/**\n * Run all feeds and return a single normalized result.\n *\n * Feeds run in parallel where possible — the store fetch is the slow one\n * (one HTTP call) and is fired alongside the local library walk. The factory\n * scan is local disk only, so it runs inline.\n */\nexport async function gatherAssetFeeds(\n am: AssetManagerLike,\n projectDir: string,\n): Promise<AssetFeedResult> {\n const [libs, store] = await Promise.all([libraryAssets(), storeAssets(projectDir)]);\n const factory = await factoryAssets();\n const src = await sourceAssets(am);\n return {\n entries: [\n ...src.entries,\n ...libs.entries,\n ...tag(\"factory\", factory.entries),\n ...tag(\"store\", store.entries),\n ],\n // Store domains first (server-curated), then the on-disk feeds; dedupe by\n // slug, first-wins, so a store-served domain shadows a same-slug local one.\n domains: dedupeBySlug([...store.domains, ...src.domains, ...libs.domains, ...factory.domains]),\n notes: [...libs.notes, ...store.notes, ...factory.notes],\n };\n}\n\n/** First-wins dedupe of a domain list by `slug`. */\nfunction dedupeBySlug(domains: CatalogDomain[]): CatalogDomain[] {\n const seen = new Set<string>();\n const out: CatalogDomain[] = [];\n for (const d of domains) {\n if (seen.has(d.slug)) continue;\n seen.add(d.slug);\n out.push(d);\n }\n return out;\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../cli/src/asset-feeds.ts"],"names":[],"mappings":"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","file":"asset-feeds-DT4B37Z3.js","sourcesContent":["/**\n * asset-feeds.ts — gather installable assets from every feed the manage TUI\n * surfaces.\n *\n * Four feeds, normalized into `CatalogEntry`:\n * - **Project sources** — `skaile.yaml` `sources:` entries (scanned via\n * `AssetManager.search()`; the new `sources:` field is merged into the\n * legacy repositories map in `AssetManager.loadConfig`).\n * - **Local libraries** — user authoring places from `LocalIndex` (filesystem\n * scan of each library's `path`).\n * - **Factory assets** — the bundled first-party `factory-assets` tree\n * (`factoryAssetRoots()`), scanned from disk. Always present; no network.\n * - **Remote store** — the configured catalog source when `catalog.url` is\n * not `local`. Failures are non-fatal — they surface as notes.\n */\n\nimport { existsSync, readFileSync } from \"node:fs\";\nimport * as path from \"node:path\";\nimport {\n type AssetKind,\n type CatalogDomain,\n type CatalogEntry,\n factoryAssetRoots,\n parseFrontmatter,\n scanRepo,\n walkDir,\n} from \"@skaile/workspaces/core\";\nimport {\n assignDomain,\n buildDomainIndex,\n DOMAIN_MD_FILENAME,\n type DomainMd,\n parseDomainMd,\n} from \"@skaile/workspaces/discovery\";\n\n/** One non-fatal note returned to the caller for surfacing in the UI. */\nexport interface FeedNote {\n feed: \"sources\" | \"libraries\" | \"store\" | \"factory\";\n message: string;\n}\n\n/**\n * Which feed an asset came from. This is the top-level grouping axis in the\n * manage TUI (\"where is this skill coming from?\") and is intentionally distinct\n * from `publisher` (asset-intrinsic identity): the same publisher can legitimately\n * appear under more than one origin (e.g. a github repo you added as a `source`\n * that is also listed in the remote `store`).\n */\nexport type AssetOrigin = \"source\" | \"library\" | \"factory\" | \"store\";\n\n/** A catalog entry tagged with the feed it was gathered from. */\nexport interface OriginEntry {\n origin: AssetOrigin;\n entry: CatalogEntry;\n /**\n * Second-level grouping label for the manage tree. Defaults (when unset) to the\n * entry's `publisher`; the source feed sets it to the source's short repo name\n * so the Sources band groups by source — \"which repo did this come from\" — not\n * by the asset-intrinsic publisher.\n */\n group?: string;\n}\n\nexport interface AssetFeedResult {\n entries: OriginEntry[];\n /**\n * Display-only domain metadata, keyed (by the consumer) on `slug`. Populated\n * from the store's `catalog.listDomains` when the connected catalog source\n * exposes it; empty otherwise. The manage TUI joins `entry.domainSlug` → a\n * domain for grouping headers, descriptions, and relation badges.\n */\n domains: CatalogDomain[];\n notes: FeedNote[];\n}\n\n// ── Domain stamping (on-disk feeds) ──────────────────────────────────────────\n//\n// `scanRepo` (the source / library / factory scan path) does not read the\n// `DOMAIN.md` sidecars, so its entries arrive with no `domainSlug` and render\n// flat under their publisher band. We re-derive the grouping here from the\n// root's `DOMAIN.md` files (the same sidecars the remote store computes\n// server-side), and fall back to the repo/source name for any entry no domain\n// claims so it still groups instead of landing in the synthetic \"no domain\" pile.\n\n/** Repo-relative POSIX path (DOMAIN.md slugs are matched whole-segment, `/`-joined). */\nfunction toPosix(p: string): string {\n return p.split(path.sep).join(\"/\");\n}\n\n/** Parse every `DOMAIN.md` sidecar under `root` into a {@link DomainMd}. */\nasync function loadDomainMds(root: string): Promise<DomainMd[]> {\n const out: DomainMd[] = [];\n for await (const { path: filePath, name } of walkDir(root)) {\n if (name !== DOMAIN_MD_FILENAME) continue;\n try {\n const { data } = parseFrontmatter(readFileSync(filePath, \"utf8\"));\n out.push(parseDomainMd(toPosix(path.relative(root, filePath)), data));\n } catch {}\n }\n return out;\n}\n\n/**\n * Stamp `domainSlug` onto every entry scanned from `root` using the root's\n * `DOMAIN.md` sidecars. Returns the `CatalogDomain` registry for the real\n * domains, plus a synthetic fallback domain when any entry used the fallback.\n * Mutates `entries` in place (sets `entry.domainSlug`).\n *\n * `synthesizeFallback` (default true): entries no domain claims fall back to\n * `fallbackSlug` (the repo/source name). Pass `false` when the caller already\n * groups these entries one level up (e.g. the source feed groups by source\n * node) — unmatched entries then get no domain (`\"\"`) and hang directly under\n * that parent, instead of nesting under a same-named fallback domain.\n */\nasync function stampDomains(\n root: string,\n fallbackSlug: string,\n entries: CatalogEntry[],\n synthesizeFallback = true,\n): Promise<CatalogDomain[]> {\n const domainMds = await loadDomainMds(root);\n const assignables = entries.map((entry) => ({\n entry,\n ref: `${entry.kind}:${entry.name}`,\n relativePath: toPosix(path.relative(root, entry.source)),\n }));\n\n let usedFallback = false;\n for (const a of assignables) {\n const slug = assignDomain(a.relativePath, domainMds);\n if (slug) a.entry.domainSlug = slug;\n else if (synthesizeFallback) {\n a.entry.domainSlug = fallbackSlug;\n usedFallback = true;\n } else a.entry.domainSlug = \"\";\n }\n\n const { index } = buildDomainIndex(assignables, domainMds);\n const catalog: CatalogDomain[] = Object.values(index).map((d) => ({\n slug: d.slug,\n title: d.title,\n ...(d.description ? { description: d.description } : {}),\n ...(d.relation ? { relation: d.relation } : {}),\n ...(d.order !== undefined ? { order: d.order } : {}),\n ...(d.recommended[0] ? { recommendedRef: d.recommended[0] } : {}),\n }));\n if (usedFallback) catalog.push({ slug: fallbackSlug, title: fallbackSlug });\n return catalog;\n}\n\n/**\n * Pull assets from local libraries (the authoring places under\n * `~/.skaile/libraries/<name>/`, not the `~/.skaile/cache/sources/` cache). Each\n * library's `path` is scanned with `scanRepo` and grouped under the bare library\n * name (`group: <name>`) so the manage TUI shows a clean `<name>` band — no\n * `library:` prefix and no redundant same-named fallback domain (mirrors the\n * source feed).\n */\nasync function libraryAssets(): Promise<{\n entries: OriginEntry[];\n domains: CatalogDomain[];\n notes: FeedNote[];\n}> {\n const notes: FeedNote[] = [];\n const domains: CatalogDomain[] = [];\n try {\n const [{ openLibraryManager }, { skaileHomeDir }, { getGlobalCacheDir }] = await Promise.all([\n import(\"./open-library.ts\"),\n import(\"@skaile/workspaces/library\"),\n import(\"@skaile/workspaces/core\"),\n ]);\n const { manager, close } = await openLibraryManager();\n try {\n // Authoring libraries are the rows that are NOT source clones. index.db\n // rows predating the cache migration still carry the legacy\n // ~/.skaile/sources path, so exclude both roots.\n const newRoot = getGlobalCacheDir();\n const legacyRoot = path.join(skaileHomeDir(), \"sources\");\n const libs = (await manager.listLibraries()).filter(\n (l) => !l.path.startsWith(newRoot) && !l.path.startsWith(legacyRoot),\n );\n const entries: OriginEntry[] = [];\n for (const lib of libs) {\n if (!existsSync(lib.path)) continue;\n // Scan + group under the bare library name. `synthesizeFallback: false`\n // (as the source feed does) keeps domainless assets directly under the\n // library band instead of a redundant same-named fallback domain.\n const libEntries = [...(await scanRepo(lib.path, lib.name))];\n domains.push(...(await stampDomains(lib.path, lib.name, libEntries, false)));\n for (const entry of libEntries) entries.push({ origin: \"library\", entry, group: lib.name });\n }\n return { entries, domains, notes };\n } finally {\n close();\n }\n } catch (err) {\n notes.push({\n feed: \"libraries\",\n message: err instanceof Error ? err.message : String(err),\n });\n return { entries: [], domains, notes };\n }\n}\n\n/**\n * Pull a (best-effort) snapshot of the connected remote store catalog.\n *\n * - Returns no entries when the resolved catalog is local-only or the host\n * is unreachable (the failure becomes a note, not an exception).\n * - Maps `CatalogAsset` → `CatalogEntry`, carrying `publisher`, `repo`, and\n * `category` straight through and using `source = \"store://<id>\"`; per-file\n * `source` paths are not available for remote assets so the canonical ref is\n * a stable placeholder.\n */\nasync function storeAssets(projectDir: string): Promise<{\n entries: CatalogEntry[];\n domains: CatalogDomain[];\n notes: FeedNote[];\n}> {\n const notes: FeedNote[] = [];\n try {\n const { resolveCatalogSource } = await import(\"./open-library.ts\");\n const { source, close } = await resolveCatalogSource({ projectDir });\n try {\n const assets = await source.listAssets();\n const entries: CatalogEntry[] = assets.map((a) => ({\n name: a.name,\n kind: (a.kind as AssetKind) ?? \"skill\",\n description: a.description ?? \"\",\n source: `store://${a.id}`,\n publisher: a.publisher,\n repo: a.repo,\n domainSlug: a.domainSlug,\n category: a.category,\n version: a.version,\n requires: [],\n dependencies: [],\n }));\n // Domains are optional on the catalog source — only the store backend\n // (post Part 4 `catalog.listDomains`) exposes them. Duck-type the call so\n // older sources and the local catalog degrade to no domains, not an error.\n const domains = await loadDomains(source);\n return { entries, domains, notes };\n } finally {\n close();\n }\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n // Local-only catalog throws a recognizable message — silence it; absence\n // is the user's choice, not an error.\n if (!/local/i.test(msg)) {\n notes.push({ feed: \"store\", message: msg });\n }\n return { entries: [], domains: [], notes };\n }\n}\n\n/** Optional `listDomains` capability — returns `[]` when the source lacks it. */\nasync function loadDomains(source: unknown): Promise<CatalogDomain[]> {\n const fn = (source as { listDomains?: () => Promise<CatalogDomain[]> }).listDomains;\n if (typeof fn !== \"function\") return [];\n const domains = await fn.call(source);\n return Array.isArray(domains) ? domains : [];\n}\n\n/** The slice of `AssetManager` the source feed needs (kept narrow for tests). */\ninterface AssetManagerLike {\n search: () => Promise<CatalogEntry[]>;\n searchRepoRoots: () => { repoName: string; root: string }[];\n}\n\n/**\n * Project-source feed: leans on `AssetManager.search()`, which now merges\n * `skaile.yaml`'s `sources:` field into the repositories map, then stamps\n * `DOMAIN.md`-derived domain grouping onto the scanned entries via\n * `searchRepoRoots()`.\n */\nasync function sourceAssets(\n am: AssetManagerLike,\n): Promise<{ entries: OriginEntry[]; domains: CatalogDomain[] }> {\n // The bundled factory tree is injected into the repositories map as an implicit\n // source, so `am.search()` returns it too. It has its own `factory` origin band,\n // so drop it here — otherwise the same first-party skills list twice under Sources.\n const factoryPrefixes = factoryAssetRoots().map((r) => (r.endsWith(path.sep) ? r : r + path.sep));\n const isFactoryPath = (p: string) =>\n factoryPrefixes.some((fp) => p === fp.slice(0, -1) || p.startsWith(fp));\n\n const all = (await am.search()).filter((e) => !isFactoryPath(e.source));\n const entries: OriginEntry[] = [];\n const domains: CatalogDomain[] = [];\n // Group each source's entries under the source node (its short repo name), not\n // the publisher: under Sources the navigational question is \"which repo did\n // this come from\". Each entry's `source` (absolute manifest path) lives under\n // exactly one declared root, so group + stamp by prefix. The cache slug is\n // URL-keyed `github.com/<org>/<repo>` — take the trailing segment.\n for (const { repoName, root } of am.searchRepoRoots()) {\n if (isFactoryPath(root)) continue;\n const prefix = root.endsWith(path.sep) ? root : root + path.sep;\n const owned = all.filter((e) => e.source === root || e.source.startsWith(prefix));\n if (owned.length === 0) continue;\n const sourceName = repoName.split(\"/\").pop() || repoName;\n // No synthetic fallback domain — the source node already groups these, so a\n // same-named fallback would just nest the source under itself.\n domains.push(...(await stampDomains(root, sourceName, owned, false)));\n for (const entry of owned) entries.push({ origin: \"source\", entry, group: sourceName });\n }\n return { entries, domains };\n}\n\n/**\n * Factory-asset feed: scan the bundled first-party `factory-assets` tree(s)\n * resolved by `factoryAssetRoots()` (the `SKAILE_FACTORY_ASSETS_DIR` override\n * layer ahead of the bundled tree). Local disk only, no network — the entries are\n * the built-in skills / connectors / bundles that ship with `@skaile/workspaces`.\n * `factoryAssetRoots()` already dedupes, so the env override pointing at the\n * bundled dir collapses to one root.\n */\nasync function factoryAssets(): Promise<{\n entries: CatalogEntry[];\n domains: CatalogDomain[];\n notes: FeedNote[];\n}> {\n const notes: FeedNote[] = [];\n const domains: CatalogDomain[] = [];\n try {\n const entries: CatalogEntry[] = [];\n for (const root of factoryAssetRoots()) {\n const rootEntries = [...(await scanRepo(root, \"skaile-factory\"))];\n domains.push(...(await stampDomains(root, \"skaile-factory\", rootEntries)));\n entries.push(...rootEntries);\n }\n return { entries, domains, notes };\n } catch (err) {\n notes.push({\n feed: \"factory\",\n message: err instanceof Error ? err.message : String(err),\n });\n return { entries: [], domains, notes };\n }\n}\n\n/** Tag a flat entry list with a single origin. */\nfunction tag(origin: AssetOrigin, entries: CatalogEntry[]): OriginEntry[] {\n return entries.map((entry) => ({ origin, entry }));\n}\n\n/**\n * Run all feeds and return a single normalized result.\n *\n * Feeds run in parallel where possible — the store fetch is the slow one\n * (one HTTP call) and is fired alongside the local library walk. The factory\n * scan is local disk only, so it runs inline.\n */\nexport async function gatherAssetFeeds(\n am: AssetManagerLike,\n projectDir: string,\n): Promise<AssetFeedResult> {\n const [libs, store] = await Promise.all([libraryAssets(), storeAssets(projectDir)]);\n const factory = await factoryAssets();\n const src = await sourceAssets(am);\n return {\n entries: [\n ...src.entries,\n ...libs.entries,\n ...tag(\"factory\", factory.entries),\n ...tag(\"store\", store.entries),\n ],\n // Store domains first (server-curated), then the on-disk feeds; dedupe by\n // slug, first-wins, so a store-served domain shadows a same-slug local one.\n domains: dedupeBySlug([...store.domains, ...src.domains, ...libs.domains, ...factory.domains]),\n notes: [...libs.notes, ...store.notes, ...factory.notes],\n };\n}\n\n/** First-wins dedupe of a domain list by `slug`. */\nfunction dedupeBySlug(domains: CatalogDomain[]): CatalogDomain[] {\n const seen = new Set<string>();\n const out: CatalogDomain[] = [];\n for (const d of domains) {\n if (seen.has(d.slug)) continue;\n seen.add(d.slug);\n out.push(d);\n }\n return out;\n}\n"]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { AssetManager, FACTORY_SOURCE_URL, MissingManifestError, NON_DEPLOYABLE_KINDS, normalizeRepoUrl, parseCanonicalLockKey, parseRefTolerant, renderMcpServerConfig, softDepName } from '../chunk-
|
|
1
|
+
export { AssetManager, FACTORY_SOURCE_URL, MissingManifestError, NON_DEPLOYABLE_KINDS, normalizeRepoUrl, parseCanonicalLockKey, parseRefTolerant, renderMcpServerConfig, softDepName } from '../chunk-7WTXE6YS.js';
|
|
2
2
|
import '../chunk-OCLCDB7G.js';
|
|
3
3
|
import '../chunk-PW4SJE3X.js';
|
|
4
4
|
import '../chunk-UKJMQZV6.js';
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { isAgentNode, isGateNode, nodeIsOptional, nodeRequiresApproval, nodeLabel, flowDefaults } from './chunk-ELPR5XBG.js';
|
|
1
|
+
import { isAgentNode, isGateNode, isCheckNode, nodeIsOptional, nodeRequiresApproval, nodeLabel, flowDefaults } from './chunk-ELPR5XBG.js';
|
|
2
2
|
|
|
3
3
|
// factory-assets/connectors/flow/prompt-fragments.ts
|
|
4
4
|
function renderStimulusPrompt(stimulus) {
|
|
@@ -30,6 +30,7 @@ function renderStimulusPrompt(stimulus) {
|
|
|
30
30
|
function buildOrchestratorPrompt(flowDef, state, stimulus) {
|
|
31
31
|
const agentNodes = flowDef.nodes.filter(isAgentNode);
|
|
32
32
|
const gateNodes = flowDef.nodes.filter(isGateNode);
|
|
33
|
+
const checkNodes = flowDef.nodes.filter(isCheckNode);
|
|
33
34
|
const promptNodes = flowDef.nodes.filter((node) => isAgentNode(node) || isGateNode(node));
|
|
34
35
|
const agentNodeIds = new Set(agentNodes.map((node) => node.id));
|
|
35
36
|
const promptNodeIds = new Set(promptNodes.map((node) => node.id));
|
|
@@ -86,6 +87,20 @@ ${rejectedGates.join("\n")}
|
|
|
86
87
|
|
|
87
88
|
Revise the surrounding work in conversation, then re-request each gate with \`request_approval(nodeId, summary, artifacts)\`. Every gate remains parked until its new human decision; do not start, complete, skip, or fail a first-class gate.
|
|
88
89
|
|
|
90
|
+
` : "";
|
|
91
|
+
const overriddenChecks = checkNodes.flatMap((node) => {
|
|
92
|
+
const record = state.nodes[node.id];
|
|
93
|
+
if (record?.status !== "complete" || record.approval?.decision !== "approved") return [];
|
|
94
|
+
return [
|
|
95
|
+
`- \`${node.id}\` \u2014 failed, overridden by ${record.approval.decidedBy ?? "unknown reviewer"}: ${record.approval.feedback ?? "(no reason recorded)"}`
|
|
96
|
+
];
|
|
97
|
+
});
|
|
98
|
+
const overriddenCheckSection = overriddenChecks.length > 0 ? `## Checks completed by human override
|
|
99
|
+
|
|
100
|
+
${overriddenChecks.join("\n")}
|
|
101
|
+
|
|
102
|
+
These checks did **not** pass. A human decided the run may continue anyway, so they are \`complete\` and their dependents are unblocked. Their evidence still records the failure \u2014 do not report them as passing, and say so if downstream work depends on what they were meant to verify.
|
|
103
|
+
|
|
89
104
|
` : "";
|
|
90
105
|
const globals = flowDefaults(flowDef);
|
|
91
106
|
const globalsSection = Object.keys(globals).length > 0 ? `## Flow globals
|
|
@@ -107,6 +122,10 @@ ${JSON.stringify(globals, null, 2)}
|
|
|
107
122
|
stimulusParagraph = `Gate node \`${stimulus.nodeId}\` was **rejected** by ${stimulus.decidedBy}.${stimulus.feedback ? ` Feedback: "${stimulus.feedback}".` : ""} Revise the work in conversation and follow the rejected-gate instructions above.`;
|
|
108
123
|
}
|
|
109
124
|
}
|
|
125
|
+
if (stimulus.kind === "approval_received" && stimulusNode && isCheckNode(stimulusNode)) {
|
|
126
|
+
const availableSuccessors = agentNodes.filter((node) => state.nodes[node.id]?.status === "available").map((node) => `\`${node.id}\``);
|
|
127
|
+
stimulusParagraph = stimulus.decision === "approved" ? `Check node \`${stimulus.nodeId}\` failed, and ${stimulus.decidedBy} **overrode** the failure${stimulus.feedback ? `: "${stimulus.feedback}"` : ""}. The node is already \`complete\` and its evidence still records the failure. Do not call \`complete_node\` for it. Advance to successor work${availableSuccessors.length > 0 ? `; available agent nodes: ${availableSuccessors.join(", ")}` : ""} \u2014 call \`get_available\`, then \`build_handoff\` and \`start_node\` for the chosen agent node.` : `Check node \`${stimulus.nodeId}\` failed and ${stimulus.decidedBy} **rejected** it${stimulus.feedback ? `: "${stimulus.feedback}"` : ""}. The node is already terminally \`failed\` \u2014 it did not return to \`available\`. Do not call \`complete_node\` or \`fail_node\` for it. Report the outcome and stop unless other nodes remain available.`;
|
|
128
|
+
}
|
|
110
129
|
return `# Flow Execution Context
|
|
111
130
|
|
|
112
131
|
You are orchestrating the flow **${flowDef.name}** (${flowDef.id} v${flowDef.version}). This is a governed flow execution: your job is to run nodes through the flow tools, summarize their outputs for human review, and yield control at approval gates.
|
|
@@ -124,7 +143,7 @@ Nodes with **Gate = first-class** are runtime-owned human decisions. The runtime
|
|
|
124
143
|
|
|
125
144
|
${stateSummary}
|
|
126
145
|
|
|
127
|
-
${globalsSection}${correctionSection}${rejectedGateSection}## Why this turn is happening
|
|
146
|
+
${globalsSection}${correctionSection}${rejectedGateSection}${overriddenCheckSection}## Why this turn is happening
|
|
128
147
|
|
|
129
148
|
${stimulusParagraph}
|
|
130
149
|
|
|
@@ -186,5 +205,5 @@ function describeStimulus(stimulus) {
|
|
|
186
205
|
}
|
|
187
206
|
|
|
188
207
|
export { buildOrchestratorPrompt, describeStimulus, renderStimulusPrompt, renderSubpromptPrompt };
|
|
189
|
-
//# sourceMappingURL=chunk-
|
|
190
|
-
//# sourceMappingURL=chunk-
|
|
208
|
+
//# sourceMappingURL=chunk-2D5BYAL6.js.map
|
|
209
|
+
//# sourceMappingURL=chunk-2D5BYAL6.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../factory-assets/connectors/flow/prompt-fragments.ts"],"names":[],"mappings":"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","file":"chunk-2D5BYAL6.js","sourcesContent":["/**\n * Prompt fragments for the flow connector.\n *\n * Pure functions that translate a {@link TurnStimulus} into the strings the\n * runner's flow orchestrator splices into the per-turn agent prompt.\n * Extracted from `runner/src/flow-orchestrator.ts` in Phase 3 of the\n * flow-connector extraction (2026-05-08) so the connector owns its\n * prompt-rendering surface without a runtime dep on the orchestrator.\n *\n * The contract is byte-identical to the previous inline implementation —\n * any divergence is a regression.\n *\n * @docLink packages/factory-assets/flow#prompt-fragments\n */\n\nimport type { FlowExecution } from \"@skaile/workspaces/types\";\nimport type { FlowDefinition } from \"./engine/types.js\";\nimport {\n flowDefaults,\n isAgentNode,\n isCheckNode,\n isGateNode,\n nodeIsOptional,\n nodeLabel,\n nodeRequiresApproval,\n} from \"./engine/node-shape.js\";\n\n/**\n * Reasons why a new turn is starting. The flow orchestrator's prompt template\n * renders a stimulus-specific paragraph (via {@link renderStimulusPrompt}) so\n * the agent knows exactly why it has been invoked.\n *\n * @docLink packages/factory-assets/flow#turn-stimulus\n */\nexport type TurnStimulus =\n | { kind: \"flow_started\" }\n | {\n kind: \"approval_received\";\n nodeId: string;\n decision: \"approved\" | \"rejected\";\n feedback?: string;\n decidedBy: string;\n }\n | { kind: \"input_received\"; nodeId: string; response: unknown; providedBy: string }\n | { kind: \"retry_requested\"; nodeId: string; requestedBy: string }\n | { kind: \"user_message\"; text: string; senderId: string }\n | { kind: \"resumed_after_hibernation\" }\n | { kind: \"cancelled\" }\n | { kind: \"state_changed\" };\n\n/**\n * Render the stimulus paragraph the agent sees at turn start.\n *\n * The output is a single paragraph (one or more sentences, no surrounding\n * whitespace) describing why the runner has woken the agent. Spliced into\n * the orchestrator prompt under the `## Why this turn is happening` heading.\n *\n * @docLink packages/factory-assets/flow#render-stimulus-prompt\n */\nexport function renderStimulusPrompt(stimulus: TurnStimulus): string {\n switch (stimulus.kind) {\n case \"flow_started\":\n return \"The user just started this flow. Begin with the first available node — call `get_available`, then `build_handoff` for your chosen node, then `start_node`.\";\n case \"approval_received\": {\n const { nodeId, decision, decidedBy, feedback } = stimulus;\n if (decision === \"approved\") {\n return `Node \\`${nodeId}\\` was **approved** by ${decidedBy}. Call \\`complete_node\\` for this node with the approved output, then advance to the next available node.`;\n }\n const fb = feedback ? ` Feedback: \"${feedback}\".` : \"\";\n return `Node \\`${nodeId}\\` was **rejected** by ${decidedBy}.${fb} Decide how to proceed: retry the node (the engine returned it to \\`available\\`), ask clarifying questions via \\`request_input\\`, or call \\`fail_node(..., recoverable: false)\\` if the issue cannot be addressed.`;\n }\n case \"input_received\":\n return `The user just provided input for node \\`${stimulus.nodeId}\\` (provided by ${stimulus.providedBy}). The node has returned to its prior status. Continue executing the node with this input.`;\n case \"retry_requested\":\n return `A user requested a retry of node \\`${stimulus.nodeId}\\` (requested by ${stimulus.requestedBy}). The node has been returned to \\`available\\` with its prior error preserved in history. Start a fresh attempt — review the error context if relevant and try a different approach.`;\n case \"user_message\":\n return `A user sent a message: \"${stimulus.text}\" (from ${stimulus.senderId}). You can respond directly without touching the flow, continue flow work, or both. If the message is a question about the flow, answer it; if it signals a new direction, consider whether to pause.`;\n case \"resumed_after_hibernation\":\n return \"This session was hibernated and has just resumed. Review the current state above and continue where you left off. No state was lost.\";\n case \"cancelled\":\n return \"The user has cancelled this flow. Wrap up cleanly: do not start any new nodes. You may record a short summary if relevant, then stop.\";\n case \"state_changed\":\n return \"The flow state changed. Review the current state above and continue work accordingly.\";\n }\n}\n\n/**\n * Build the full agent-orchestrator prompt for a flow turn.\n *\n * Reassembles the five-section prompt from the current FlowExecution snapshot\n * and the supplied stimulus:\n *\n * 1. Flow definition (markdown table of nodes)\n * 2. Current state (progress, available/blocked, interaction pointers)\n * 3. Why this turn is happening (stimulus-specific paragraph)\n * 4. Flow tools available (static documentation)\n * 5. Rules\n *\n * Originally a byte-identical lift of the (since-deleted)\n * `FlowOrchestrator.buildOrchestratorPrompt`; the contract now is simply\n * this function's own output. When strict v2 defaults or legacy globals are\n * non-empty, a `## Flow globals` section exposes those run-scoped values. The\n * flow-wide active-node table stays bounded to selection metadata; `build_handoff`\n * supplies a selected agent node's execution payload. First-class gates appear\n * as runtime-owned state but never as agent-executable work.\n * Pure — depends only on its inputs.\n *\n * @docLink packages/factory-assets/flow#build-orchestrator-prompt\n * @since 2.2.0\n */\nexport function buildOrchestratorPrompt(\n flowDef: FlowDefinition,\n state: FlowExecution,\n stimulus: TurnStimulus,\n): string {\n const agentNodes = flowDef.nodes.filter(isAgentNode);\n const gateNodes = flowDef.nodes.filter(isGateNode);\n const checkNodes = flowDef.nodes.filter(isCheckNode);\n const promptNodes = flowDef.nodes.filter((node) => isAgentNode(node) || isGateNode(node));\n const agentNodeIds = new Set(agentNodes.map((node) => node.id));\n const promptNodeIds = new Set(promptNodes.map((node) => node.id));\n\n // ── Section 1: definition table ──\n const nodeRows = promptNodes\n .map((n) => {\n const deps =\n flowDef.edges\n .filter((e) => e.target === n.id && e.type === \"flow\")\n .map((e) => e.source)\n .join(\", \") || \"—\";\n const required = nodeIsOptional(n) ? \"optional\" : \"required\";\n const gate = isGateNode(n) ? \"first-class\" : nodeRequiresApproval(n) ? \"mandatory\" : \"—\";\n const nodeState = state.nodes[n.id];\n const status = nodeState?.status ?? \"not_started\";\n const description = (n.description ?? n.data?.description ?? \"—\")\n .replace(/\\s+/g, \" \")\n .replaceAll(\"|\", \"\\\\|\");\n return `| ${n.id} | ${nodeLabel(n)} | ${description} | ${required} | ${gate} | ${status} | ${deps} |`;\n })\n .join(\"\\n\");\n\n // ── Section 2: current state summary ──\n const nodesByStatus = (s: string) =>\n Object.values(state.nodes)\n .filter((n) => promptNodeIds.has(n.id) && n.status === s)\n .map((n) => n.id);\n const available = nodesByStatus(\"available\");\n const awaitingApproval = nodesByStatus(\"awaiting_approval\");\n const awaitingInput = nodesByStatus(\"awaiting_input\");\n const running = nodesByStatus(\"running\");\n const failed = nodesByStatus(\"failed\");\n const completed = nodesByStatus(\"complete\");\n const totalRequired = promptNodes.filter((n) => !nodeIsOptional(n)).length;\n\n const stateSummary = [\n `- Run ID: ${state.runId}`,\n `- Status: ${state.status}`,\n `- Autonomous mode: ${state.autonomousMode}`,\n `- Progress: ${completed.length} / ${totalRequired} required nodes complete`,\n `- Available now: ${available.join(\", \") || \"(none)\"}`,\n `- Currently running: ${running.join(\", \") || \"(none)\"}`,\n `- Awaiting approval: ${awaitingApproval.join(\", \") || \"(none)\"}`,\n `- Awaiting input: ${awaitingInput.join(\", \") || \"(none)\"}`,\n `- Failed: ${failed.join(\", \") || \"(none)\"}`,\n ].join(\"\\n\");\n\n const outputCorrections = Object.values(state.nodes)\n .filter(\n (node) =>\n agentNodeIds.has(node.id) &&\n node.outputCorrection &&\n node.status !== \"complete\" &&\n node.status !== \"failed\",\n )\n .map(\n (node) =>\n `- Node \\`${node.id}\\`: ${node.outputCorrection?.issues.join(\"; \") ?? \"unknown issue\"}`,\n );\n const correctionSection =\n outputCorrections.length > 0\n ? `## Output correction required\n\nThe following node has already used its single corrective reprompt. Submit one corrected \\`complete_node\\` call that fixes every issue; a second mismatch fails the node.\n\n${outputCorrections.join(\"\\n\")}\n\n`\n : \"\";\n\n const rejectedGates = gateNodes.flatMap((node) => {\n const approval = state.nodes[node.id]?.approval;\n if (approval?.decision !== \"rejected\") return [];\n return [\n `- \\`${node.id}\\` — rejected by ${approval.decidedBy ?? \"unknown reviewer\"}: ${\n approval.feedback ?? \"(no feedback provided)\"\n }`,\n ];\n });\n const rejectedGateSection =\n rejectedGates.length > 0\n ? `## Rejected first-class gates requiring revision\n\n${rejectedGates.join(\"\\n\")}\n\nRevise the surrounding work in conversation, then re-request each gate with \\`request_approval(nodeId, summary, artifacts)\\`. Every gate remains parked until its new human decision; do not start, complete, skip, or fail a first-class gate.\n\n`\n : \"\";\n\n // An override survives only in the approval record: the state table shows the\n // node as `complete` like any other, so without this section the failure is\n // invisible from the turn after the decision onward.\n const overriddenChecks = checkNodes.flatMap((node) => {\n const record = state.nodes[node.id];\n if (record?.status !== \"complete\" || record.approval?.decision !== \"approved\") return [];\n return [\n `- \\`${node.id}\\` — failed, overridden by ${record.approval.decidedBy ?? \"unknown reviewer\"}: ${\n record.approval.feedback ?? \"(no reason recorded)\"\n }`,\n ];\n });\n const overriddenCheckSection =\n overriddenChecks.length > 0\n ? `## Checks completed by human override\n\n${overriddenChecks.join(\"\\n\")}\n\nThese checks did **not** pass. A human decided the run may continue anyway, so they are \\`complete\\` and their dependents are unblocked. Their evidence still records the failure — do not report them as passing, and say so if downstream work depends on what they were meant to verify.\n\n`\n : \"\";\n\n // ── Section 2b: flow globals (additive — omitted entirely when empty so\n // flows without globals keep the byte-identical Phase 3 prompt) ──\n const globals = flowDefaults(flowDef);\n const globalsSection =\n Object.keys(globals).length > 0\n ? `## Flow globals\n\nRun-scoped parameters set by the flow author or by the host that started this run. When \\`run_input\\` is present it carries the payload this run was started with (e.g. a scheduled or webhook-triggered run) — treat it as the run's initial input instead of asking the user for it.\n\n\\`\\`\\`json\n${JSON.stringify(globals, null, 2)}\n\\`\\`\\`\n\n`\n : \"\";\n\n // ── Section 3: stimulus paragraph ──\n const stimulusNode =\n stimulus.kind === \"approval_received\"\n ? flowDef.nodes.find((node) => node.id === stimulus.nodeId)\n : undefined;\n let stimulusParagraph = renderStimulusPrompt(stimulus);\n if (stimulus.kind === \"approval_received\" && stimulusNode && isGateNode(stimulusNode)) {\n if (stimulus.decision === \"approved\") {\n const availableSuccessors = agentNodes\n .filter((node) => state.nodes[node.id]?.status === \"available\")\n .map((node) => `\\`${node.id}\\``);\n stimulusParagraph = `Gate node \\`${stimulus.nodeId}\\` is already \\`complete\\` after approval by ${stimulus.decidedBy}. Do not call \\`complete_node\\` for the gate. Advance to successor work${\n availableSuccessors.length > 0\n ? `; available agent nodes: ${availableSuccessors.join(\", \")}`\n : \"\"\n } — call \\`get_available\\`, then \\`build_handoff\\` and \\`start_node\\` for the chosen agent node.`;\n } else {\n stimulusParagraph = `Gate node \\`${stimulus.nodeId}\\` was **rejected** by ${stimulus.decidedBy}.${\n stimulus.feedback ? ` Feedback: \"${stimulus.feedback}\".` : \"\"\n } Revise the work in conversation and follow the rejected-gate instructions above.`;\n }\n }\n // A check is host-decided the same way a gate is: the adapter already wrote the\n // terminal status, and `complete_node` rejects any non-agent node — so the\n // generic approved/rejected wording would send the agent into a guaranteed throw.\n if (stimulus.kind === \"approval_received\" && stimulusNode && isCheckNode(stimulusNode)) {\n const availableSuccessors = agentNodes\n .filter((node) => state.nodes[node.id]?.status === \"available\")\n .map((node) => `\\`${node.id}\\``);\n stimulusParagraph =\n stimulus.decision === \"approved\"\n ? `Check node \\`${stimulus.nodeId}\\` failed, and ${stimulus.decidedBy} **overrode** the failure${\n stimulus.feedback ? `: \"${stimulus.feedback}\"` : \"\"\n }. The node is already \\`complete\\` and its evidence still records the failure. Do not call \\`complete_node\\` for it. Advance to successor work${\n availableSuccessors.length > 0\n ? `; available agent nodes: ${availableSuccessors.join(\", \")}`\n : \"\"\n } — call \\`get_available\\`, then \\`build_handoff\\` and \\`start_node\\` for the chosen agent node.`\n : `Check node \\`${stimulus.nodeId}\\` failed and ${stimulus.decidedBy} **rejected** it${\n stimulus.feedback ? `: \"${stimulus.feedback}\"` : \"\"\n }. The node is already terminally \\`failed\\` — it did not return to \\`available\\`. Do not call \\`complete_node\\` or \\`fail_node\\` for it. Report the outcome and stop unless other nodes remain available.`;\n }\n\n // ── Section 4+5: static tool surface and rules ──\n return `# Flow Execution Context\n\nYou are orchestrating the flow **${flowDef.name}** (${flowDef.id} v${flowDef.version}). This is a governed flow execution: your job is to run nodes through the flow tools, summarize their outputs for human review, and yield control at approval gates.\n\n## Flow definition\n\n| ID | Label | Description | Required | Gate | Status | Depends on |\n|----|-------|-------------|----------|------|--------|------------|\n${nodeRows}\n\nNodes with **Gate = mandatory** are hard approval gates: they always require \\`request_approval\\` and a human decision, even when autonomous mode is on. They cannot be skipped — \\`request_approval\\` → approval is their only completion path.\nNodes with **Gate = first-class** are runtime-owned human decisions. The runtime parks them automatically and completes them directly on approval; the agent never executes them.\n\n## Current state\n\n${stateSummary}\n\n${globalsSection}${correctionSection}${rejectedGateSection}${overriddenCheckSection}## Why this turn is happening\n\n${stimulusParagraph}\n\n## Flow tools available\n\nAll tools are exposed by the \\`flow\\` connector:\n\n- \\`get_available()\\` — list node IDs that are ready to start\n- \\`get_state()\\` — full current state including approvals, inputs, outputs\n- \\`get_globals()\\` — the flow's run-scoped globals (e.g. the \\`run_input\\` payload for scheduled/params-bound runs)\n- \\`build_handoff(nodeId)\\` — selected node instruction, supplied bindings, required assets, and upstream context\n- \\`start_node(nodeId)\\` — transition an agent node from \\`available\\` → \\`running\\`; call before executing it. Never start a first-class gate.\n- \\`request_approval(nodeId, summary, artifacts)\\` — transition a running agent node to \\`awaiting_approval\\`, or replace a rejected first-class gate's decision with a fresh pending request. **This ends your turn.**\n- \\`request_input(nodeId, prompt, schema)\\` — transition to \\`awaiting_input\\`. **This ends your turn.** Legal from \\`available\\`, \\`running\\`, or \\`awaiting_approval\\`.\n- \\`complete_node(nodeId, summary, fields?, artifacts?, concerns?)\\` — complete an agent node. When downstream nodes consume declared output fields, include a conforming JSON object. The first mismatch gets one corrective call; the second fails the node. Valid only if the agent node was approved, OR autonomousMode is true and it does not require mandatory approval. First-class gates are completed by the runtime on approval; never call this tool for them.\n- \\`fail_node(nodeId, message, recoverable)\\` — transition to \\`failed\\`, or to \\`skipped\\` if the node is optional. \\`recoverable=true\\` returns the node to \\`available\\` instead.\n- \\`skip_node(nodeId)\\` — transition to \\`skipped\\`. Only valid for optional nodes.\n\n## Rules\n\n1. Before executing an agent node, call \\`build_handoff(nodeId)\\` and follow its instruction with the supplied bindings, assets, and upstream context; then call \\`start_node(nodeId)\\`.\n2. After executing the node, call \\`request_approval\\` unless \\`autonomousMode\\` is true — in which case call \\`complete_node\\` directly. Exception: nodes marked **Gate = mandatory** always require \\`request_approval\\` and a human decision, even in autonomous mode.\n3. First-class nodes marked **Gate = first-class** are runtime-owned. Never start, complete, skip, fail, or request input for them. After rejection, revise in conversation and only call \\`request_approval\\` to create the next attempt.\n4. If you need information from the user before or during agent execution, call \\`request_input\\`. This ends your turn until the user responds.\n5. On unrecoverable agent failure, call \\`fail_node(..., recoverable: false)\\`; an optional node ends \\`skipped\\` rather than \\`failed\\`, so the run continues past it. On recoverable failure, call \\`fail_node(..., recoverable: true)\\` and the engine returns the node to \\`available\\`.\n6. When all required nodes are \\`complete\\` or \\`skipped\\`, stop. The runner marks the flow done automatically.\n7. Free-chat user messages do not require flow action. Respond directly, continue flow work, or both — your call.\n`;\n}\n\n/**\n * Render the full prompt sent to a subprompt node's isolated driver instance.\n *\n * `instruction` is already interpolated with the node's resolved bindings\n * (the same `interpolateNodeInstruction` step an agent handoff uses) — this\n * function only adds the typed-response directive when the node declares an\n * output contract. There is no corrective reprompt for a subprompt (it has no\n * conversation to reprompt in), so the directive is the runtime's only lever\n * for getting parseable JSON back; a malformed or non-conforming reply is an\n * ordinary node failure handled by the caller, never retried in-band here.\n *\n * The object-only constraint is therefore stated twice, before and after the\n * schema: the serialized schema is a large blob, so a directive placed only\n * ahead of it is not the last thing the model reads.\n *\n * @docLink packages/factory-assets/flow#render-subprompt-prompt\n */\nexport function renderSubpromptPrompt(\n instruction: string,\n outputSchema: Record<string, unknown> | undefined,\n): string {\n if (!outputSchema) return instruction;\n return `${instruction}\\n\\nRespond with a single JSON object matching this JSON Schema, and nothing else — no markdown code fences, no commentary before or after it:\\n\\n${JSON.stringify(outputSchema, null, 2)}\\n\\nReply with the object only. The first character of your reply must be \\`{\\` and the last must be \\`}\\` — no explanation, no restatement, no code fence.`;\n}\n\n/**\n * Single-line tag suitable for telemetry / logging. Derives a short, stable\n * summary of a stimulus that's safe to attach to spans, log entries, and\n * trace events. The kind is always included; node-specific stimuli also\n * include their `nodeId` so log queries can pivot on it.\n *\n * @docLink packages/factory-assets/flow#describe-stimulus\n */\nexport function describeStimulus(stimulus: TurnStimulus): string {\n switch (stimulus.kind) {\n case \"flow_started\":\n return \"flow_started\";\n case \"approval_received\":\n return `approval_received:${stimulus.nodeId}:${stimulus.decision}`;\n case \"input_received\":\n return `input_received:${stimulus.nodeId}`;\n case \"retry_requested\":\n return `retry_requested:${stimulus.nodeId}`;\n case \"user_message\":\n return `user_message:${stimulus.senderId}`;\n case \"resumed_after_hibernation\":\n return \"resumed_after_hibernation\";\n case \"cancelled\":\n return \"cancelled\";\n case \"state_changed\":\n return \"state_changed\";\n }\n}\n"]}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { openLibraryManager, createFullRegistry } from './chunk-
|
|
2
|
-
import { logErr, logInfo, logWarn, logOk, S } from './chunk-
|
|
1
|
+
import { openLibraryManager, createFullRegistry } from './chunk-KBAYZ6DK.js';
|
|
2
|
+
import { logErr, logInfo, logWarn, logOk, S } from './chunk-XDAOECL4.js';
|
|
3
3
|
import { getStoreManifestsDir, LocalCatalogSource, writeCuratedManifest } from './chunk-OCLCDB7G.js';
|
|
4
4
|
import { computeDeterministicHash, discoverAssetsInTree } from './chunk-PW4SJE3X.js';
|
|
5
5
|
import { WorkspaceYamlEditor } from './chunk-AZPXCHDK.js';
|
|
@@ -313,12 +313,12 @@ function addSourceManifestCommands(src) {
|
|
|
313
313
|
).option("-C, --project-dir <dir>", "Project directory", process.cwd()).option("--publisher <name>", "Override the publisher (--overwrite only)").option("--dev", "Include assets under the source's dev_paths", false).option("--overwrite", "Discard curation and re-scan the full inventory", false).action((arg, opts) => runRebuild(arg, opts));
|
|
314
314
|
manifest.command("verify <src>").description("Verify hashes, deps, and schema (read-only)").option("-C, --project-dir <dir>", "Project directory", process.cwd()).option("--strict", "Fail on advisory checks (warnings force a nonzero exit)", false).action((arg, opts) => runVerify(arg, opts));
|
|
315
315
|
manifest.command("publish <src>").description("Push the curated sidecar manifest and publish it to the store").option("-C, --project-dir <dir>", "Project directory", process.cwd()).option("--as <namespace>", "Publisher namespace (default: your store username)").option("--sidecar-repo <url>", "Public GitHub repo you own to hold the curated manifest").option("--ref <gitref>", "Foreign source ref to ingest (branch/sha; default: main)").option("--dry-run", "Print the publish plan without pushing or calling the store", false).action(async (arg, opts) => {
|
|
316
|
-
const { runPublish } = await import('./source-manifest-publish-
|
|
316
|
+
const { runPublish } = await import('./source-manifest-publish-KR5MXXGD.js');
|
|
317
317
|
await runPublish(arg, opts);
|
|
318
318
|
});
|
|
319
319
|
manifest.command("propose <src>").description("Open a PR to upstream with the sidecar manifest").action(() => notWired("propose"));
|
|
320
320
|
manifest.command("yank <src>").description("Retract the source's published assets from the store").option("-C, --project-dir <dir>", "Project directory", process.cwd()).option("--asset <ref>", "Yank only the asset matching this ref/name").action(async (arg, opts) => {
|
|
321
|
-
const { runYank } = await import('./source-manifest-publish-
|
|
321
|
+
const { runYank } = await import('./source-manifest-publish-KR5MXXGD.js');
|
|
322
322
|
await runYank(arg, opts);
|
|
323
323
|
});
|
|
324
324
|
}
|
|
@@ -684,5 +684,5 @@ function makeSourceCommand() {
|
|
|
684
684
|
}
|
|
685
685
|
|
|
686
686
|
export { autoSyncForSearch, ensureClone, findCacheKeyCollision, indexingHadFailures, legacySourceConfigHint, makeSourceCommand, normalizeSourceUrl, readProjectSources, resolveSourceArg, sourceClonePath, sourceMatchesKey, syncProjectSources };
|
|
687
|
-
//# sourceMappingURL=chunk-
|
|
688
|
-
//# sourceMappingURL=chunk-
|
|
687
|
+
//# sourceMappingURL=chunk-4D4N2VFR.js.map
|
|
688
|
+
//# sourceMappingURL=chunk-4D4N2VFR.js.map
|