@skaile/workspaces 0.21.0 → 0.22.0-beta.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 +40 -0
- package/dist/{asset-feeds-CI76R7FI.js → asset-feeds-PJDJ3QYI.js} +11 -11
- package/dist/{asset-feeds-CI76R7FI.js.map → asset-feeds-PJDJ3QYI.js.map} +1 -1
- package/dist/asset-manager/index.js +9 -9
- package/dist/asset-manager/installer.js +8 -8
- package/dist/base-assets/connectors/deploy.js +10 -9
- package/dist/base-assets/connectors/devserver.js +10 -9
- package/dist/base-assets/connectors/flow/adapter.js +10 -9
- package/dist/base-assets/connectors/flow/run-flow.js +11 -10
- package/dist/base-assets/connectors/flow.js +10 -9
- package/dist/base-assets/connectors/git.js +10 -9
- package/dist/base-assets/connectors/gmail.js +10 -9
- package/dist/base-assets/connectors/googledrive.js +10 -9
- package/dist/base-assets/connectors/local.js +10 -9
- package/dist/base-assets/connectors/mattermost.js +10 -9
- package/dist/base-assets/connectors/memory.js +10 -9
- package/dist/base-assets/connectors/minio.js +10 -9
- package/dist/base-assets/connectors/postgres.js +10 -9
- package/dist/base-assets/connectors/s3.js +10 -9
- package/dist/base-assets/connectors/sharepoint.js +10 -9
- package/dist/base-assets/connectors/sqlite.js +10 -9
- package/dist/base-assets/connectors/static-server.js +10 -9
- package/dist/base-assets/connectors/tunnel.js +10 -9
- package/dist/base-assets/connectors/webdav.js +10 -9
- package/dist/base-assets/connectors/xstate-store.js +10 -9
- package/dist/base-assets/connectors/xstate.js +10 -9
- package/dist/bridge/drivers/claude-sdk.js +13 -3
- package/dist/bridge/drivers/claude-sdk.js.map +1 -1
- package/dist/bridge/drivers/codex.js +13 -3
- package/dist/bridge/drivers/codex.js.map +1 -1
- package/dist/bridge/drivers/echo.js +13 -4
- package/dist/bridge/drivers/echo.js.map +1 -1
- package/dist/bridge/drivers/omp.js +13 -3
- package/dist/bridge/drivers/omp.js.map +1 -1
- package/dist/bridge/index.js +3 -2
- package/dist/bridge/src/drivers/claude-sdk.d.ts +7 -0
- package/dist/bridge/src/drivers/claude-sdk.d.ts.map +1 -1
- package/dist/bridge/src/drivers/codex.d.ts +7 -0
- package/dist/bridge/src/drivers/codex.d.ts.map +1 -1
- package/dist/bridge/src/drivers/echo.d.ts +6 -0
- package/dist/bridge/src/drivers/echo.d.ts.map +1 -1
- package/dist/bridge/src/drivers/omp.d.ts +6 -0
- package/dist/bridge/src/drivers/omp.d.ts.map +1 -1
- package/dist/bridge/src/registry.d.ts +32 -34
- package/dist/bridge/src/registry.d.ts.map +1 -1
- package/dist/{chunk-DEQ3OOTU.js → chunk-2DNSSQ22.js} +7 -7
- package/dist/{chunk-DEQ3OOTU.js.map → chunk-2DNSSQ22.js.map} +1 -1
- package/dist/{chunk-ZWIG55ZX.js → chunk-2XY6732A.js} +3 -3
- package/dist/{chunk-ZWIG55ZX.js.map → chunk-2XY6732A.js.map} +1 -1
- package/dist/{chunk-2WVQMRIE.js → chunk-CSDQBWE6.js} +5 -5
- package/dist/{chunk-2WVQMRIE.js.map → chunk-CSDQBWE6.js.map} +1 -1
- package/dist/{chunk-KFDTS7RX.js → chunk-F3MGZ5E6.js} +3 -3
- package/dist/{chunk-KFDTS7RX.js.map → chunk-F3MGZ5E6.js.map} +1 -1
- package/dist/{chunk-XAVM2BAJ.js → chunk-G6GKWGOW.js} +114 -619
- package/dist/chunk-G6GKWGOW.js.map +1 -0
- package/dist/{chunk-H45ANMIU.js → chunk-GKM6MDUC.js} +3 -3
- package/dist/{chunk-H45ANMIU.js.map → chunk-GKM6MDUC.js.map} +1 -1
- package/dist/{chunk-4ACWI5YT.js → chunk-IGQEXBBG.js} +44 -36
- package/dist/chunk-IGQEXBBG.js.map +1 -0
- package/dist/{chunk-RDH4SSMH.js → chunk-J2FCO6TM.js} +2 -2
- package/dist/{chunk-RDH4SSMH.js.map → chunk-J2FCO6TM.js.map} +1 -1
- package/dist/{chunk-BSY56QS7.js → chunk-KA46DUM4.js} +3 -3
- package/dist/{chunk-BSY56QS7.js.map → chunk-KA46DUM4.js.map} +1 -1
- package/dist/{chunk-XGWGLIHZ.js → chunk-MO4JPTRD.js} +4 -4
- package/dist/{chunk-XGWGLIHZ.js.map → chunk-MO4JPTRD.js.map} +1 -1
- package/dist/{chunk-G4BR355S.js → chunk-NGC7ZQI4.js} +10 -10
- package/dist/{chunk-G4BR355S.js.map → chunk-NGC7ZQI4.js.map} +1 -1
- package/dist/{chunk-W5DFC35Z.js → chunk-RENHNO4J.js} +81 -4
- package/dist/chunk-RENHNO4J.js.map +1 -0
- package/dist/{chunk-4S4TZDCD.js → chunk-SL6JVGRD.js} +3 -3
- package/dist/{chunk-4S4TZDCD.js.map → chunk-SL6JVGRD.js.map} +1 -1
- package/dist/{chunk-5QNQLSBW.js → chunk-TKOLD2O7.js} +22 -5
- package/dist/chunk-TKOLD2O7.js.map +1 -0
- package/dist/{chunk-DFUXWNTS.js → chunk-TTY56FQQ.js} +4 -4
- package/dist/{chunk-DFUXWNTS.js.map → chunk-TTY56FQQ.js.map} +1 -1
- package/dist/chunk-UZRY5UI2.js +96 -0
- package/dist/chunk-UZRY5UI2.js.map +1 -0
- package/dist/{chunk-NCUTHLRV.js → chunk-UZVHJ7LX.js} +4 -4
- package/dist/{chunk-NCUTHLRV.js.map → chunk-UZVHJ7LX.js.map} +1 -1
- package/dist/{chunk-FRPKLIEZ.js → chunk-WIR34WMU.js} +3 -3
- package/dist/{chunk-FRPKLIEZ.js.map → chunk-WIR34WMU.js.map} +1 -1
- package/dist/{chunk-37JKX6D7.js → chunk-X5Y4EGZB.js} +2 -2
- package/dist/{chunk-37JKX6D7.js.map → chunk-X5Y4EGZB.js.map} +1 -1
- package/dist/{chunk-S2OVTCAL.js → chunk-XHFMUGDD.js} +3 -3
- package/dist/{chunk-S2OVTCAL.js.map → chunk-XHFMUGDD.js.map} +1 -1
- package/dist/cli/index.js +701 -413
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/src/commands/deploy.d.ts +24 -0
- package/dist/cli/src/commands/deploy.d.ts.map +1 -0
- package/dist/cli/src/commands/integration.d.ts +19 -0
- package/dist/cli/src/commands/integration.d.ts.map +1 -0
- package/dist/cli/src/commands/plugin-registry-cmd.d.ts +22 -0
- package/dist/cli/src/commands/plugin-registry-cmd.d.ts.map +1 -0
- package/dist/cli/src/commands/serve.d.ts.map +1 -1
- package/dist/cli/src/plugin-store/index.d.ts +37 -0
- package/dist/cli/src/plugin-store/index.d.ts.map +1 -0
- package/dist/cli/src/plugin-store/load.d.ts +35 -0
- package/dist/cli/src/plugin-store/load.d.ts.map +1 -0
- package/dist/cli/src/plugin-store/paths.d.ts +23 -0
- package/dist/cli/src/plugin-store/paths.d.ts.map +1 -0
- package/dist/cli/src/plugin-store/reconcile.d.ts +50 -0
- package/dist/cli/src/plugin-store/reconcile.d.ts.map +1 -0
- package/dist/cli/src/plugin-store/spec.d.ts +25 -0
- package/dist/cli/src/plugin-store/spec.d.ts.map +1 -0
- package/dist/connectors/config.js +8 -8
- package/dist/connectors/index.js +10 -9
- package/dist/connectors/src/connector-manager.d.ts.map +1 -1
- package/dist/connectors/src/connector-registry.d.ts +42 -22
- package/dist/connectors/src/connector-registry.d.ts.map +1 -1
- package/dist/connectors/src/index.d.ts +2 -3
- package/dist/connectors/src/index.d.ts.map +1 -1
- package/dist/connectors-shared/index.js +8 -0
- package/dist/connectors-shared/index.js.map +1 -0
- package/dist/connectors-shared/src/index.d.ts +11 -0
- package/dist/connectors-shared/src/index.d.ts.map +1 -0
- package/dist/connectors-shared/src/schemas.d.ts +10 -0
- package/dist/connectors-shared/src/schemas.d.ts.map +1 -0
- package/dist/connectors-shared/src/types.d.ts +11 -0
- package/dist/connectors-shared/src/types.d.ts.map +1 -0
- package/dist/core/index.js +7 -7
- package/dist/core/manifest.js +2 -2
- package/dist/core/models.js +1 -1
- package/dist/core/runtime-assets.js +4 -4
- package/dist/core/src/index.d.ts +2 -2
- package/dist/core/src/index.d.ts.map +1 -1
- package/dist/core/src/lock.d.ts +20 -1
- package/dist/core/src/lock.d.ts.map +1 -1
- package/dist/core/src/models.d.ts +13 -0
- package/dist/core/src/models.d.ts.map +1 -1
- package/dist/core/src/workspace-config.d.ts +14 -0
- package/dist/core/src/workspace-config.d.ts.map +1 -1
- package/dist/core/src/workspace-yaml-editor.d.ts +20 -0
- package/dist/core/src/workspace-yaml-editor.d.ts.map +1 -1
- package/dist/core/workspace-config.js +3 -3
- package/dist/deploy/index.js +454 -0
- package/dist/deploy/index.js.map +1 -0
- package/dist/deploy/src/handle-store.d.ts +22 -0
- package/dist/deploy/src/handle-store.d.ts.map +1 -0
- package/dist/deploy/src/index.d.ts +21 -0
- package/dist/deploy/src/index.d.ts.map +1 -0
- package/dist/deploy/src/targets/container-runtime.d.ts +38 -0
- package/dist/deploy/src/targets/container-runtime.d.ts.map +1 -0
- package/dist/deploy/src/targets/docker.d.ts +18 -0
- package/dist/deploy/src/targets/docker.d.ts.map +1 -0
- package/dist/deploy/src/targets/local.d.ts +30 -0
- package/dist/deploy/src/targets/local.d.ts.map +1 -0
- package/dist/deploy/src/targets/podman.d.ts +18 -0
- package/dist/deploy/src/targets/podman.d.ts.map +1 -0
- package/dist/deploy/src/targets/port.d.ts +10 -0
- package/dist/deploy/src/targets/port.d.ts.map +1 -0
- package/dist/deploy/src/targets/stream-lines.d.ts +44 -0
- package/dist/deploy/src/targets/stream-lines.d.ts.map +1 -0
- package/dist/discovery/index.js +3 -3
- package/dist/{ensure-sources-IDVQ77NJ.js → ensure-sources-COGVKY44.js} +11 -11
- package/dist/{ensure-sources-IDVQ77NJ.js.map → ensure-sources-COGVKY44.js.map} +1 -1
- package/dist/{flows-6BNO4GKK.js → flows-DYFTPCPM.js} +4 -4
- package/dist/{flows-6BNO4GKK.js.map → flows-DYFTPCPM.js.map} +1 -1
- package/dist/library/index.js +4 -4
- package/dist/open-library-DWAQFUSQ.js +13 -0
- package/dist/{open-library-IOYWFK7M.js.map → open-library-DWAQFUSQ.js.map} +1 -1
- package/dist/plugin-registry/index.js +4 -0
- package/dist/plugin-registry/index.js.map +1 -0
- package/dist/plugin-registry/src/context.d.ts +29 -0
- package/dist/plugin-registry/src/context.d.ts.map +1 -0
- package/dist/plugin-registry/src/deploy-handle.d.ts +60 -0
- package/dist/plugin-registry/src/deploy-handle.d.ts.map +1 -0
- package/dist/plugin-registry/src/errors.d.ts +23 -0
- package/dist/plugin-registry/src/errors.d.ts.map +1 -0
- package/dist/plugin-registry/src/index.d.ts +16 -0
- package/dist/plugin-registry/src/index.d.ts.map +1 -0
- package/dist/plugin-registry/src/internal.d.ts +13 -0
- package/dist/plugin-registry/src/internal.d.ts.map +1 -0
- package/dist/plugin-registry/src/registry.d.ts +25 -0
- package/dist/plugin-registry/src/registry.d.ts.map +1 -0
- package/dist/plugin-registry/src/targets.d.ts +42 -0
- package/dist/plugin-registry/src/targets.d.ts.map +1 -0
- package/dist/plugin-store-6OENKNFW.js +144 -0
- package/dist/plugin-store-6OENKNFW.js.map +1 -0
- package/dist/runner/index.js +14 -13
- package/dist/sdk/asset-manager.js +9 -9
- package/dist/sdk/bridge.js +3 -2
- package/dist/sdk/core.js +7 -7
- package/dist/sdk/index.js +15 -14
- package/dist/sdk/index.js.map +1 -1
- package/dist/sdk/runner.js +14 -13
- package/dist/{setup-AIOLUTKV.js → setup-ACMP3QZC.js} +12 -11
- package/dist/setup-ACMP3QZC.js.map +1 -0
- package/dist/store-client-ZSLNOOQG.js +14 -0
- package/dist/{store-client-CYEH2GKC.js.map → store-client-ZSLNOOQG.js.map} +1 -1
- package/dist/tui/index.js +14 -13
- package/dist/tui/index.js.map +1 -1
- package/dist/workspace-plugin/adapters/mcp.js +2 -2
- package/dist/workspace-plugin/adapters/omp.js +3 -3
- package/dist/workspace-plugin/index.js +1 -1
- package/package.json +20 -23
- package/dist/base-assets/connectors/redis/adapter.d.ts +0 -39
- package/dist/base-assets/connectors/redis/adapter.d.ts.map +0 -1
- package/dist/base-assets/connectors/redis.js +0 -20
- package/dist/base-assets/connectors/redis.js.map +0 -1
- package/dist/base-assets/connectors/yjs/adapter.d.ts +0 -50
- package/dist/base-assets/connectors/yjs/adapter.d.ts.map +0 -1
- package/dist/base-assets/connectors/yjs.js +0 -20
- package/dist/base-assets/connectors/yjs.js.map +0 -1
- package/dist/chunk-4ACWI5YT.js.map +0 -1
- package/dist/chunk-5QNQLSBW.js.map +0 -1
- package/dist/chunk-W5DFC35Z.js.map +0 -1
- package/dist/chunk-XAVM2BAJ.js.map +0 -1
- package/dist/cli/src/commands/plugin.d.ts +0 -14
- package/dist/cli/src/commands/plugin.d.ts.map +0 -1
- package/dist/open-library-IOYWFK7M.js +0 -13
- package/dist/setup-AIOLUTKV.js.map +0 -1
- package/dist/store-client-CYEH2GKC.js +0 -14
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* YjsConnector — CRDT-based shared document state via Yjs.
|
|
3
|
-
* Not mountable. Provides real-time collaborative state that merges
|
|
4
|
-
* concurrent edits from multiple agents and UI clients.
|
|
5
|
-
*
|
|
6
|
-
* Requires `yjs` as an optional peer dependency.
|
|
7
|
-
*/
|
|
8
|
-
import { AbstractConnector } from "@skaile/workspaces/connectors";
|
|
9
|
-
import type { ConnectContext, ConnectorDeclaration, ConnectorHandle, ToolFace } from "@skaile/workspaces/connectors";
|
|
10
|
-
/**
|
|
11
|
-
* Connector for Yjs CRDT-based shared document state — enables real-time collaborative state that merges concurrent edits from multiple agents and UI clients.
|
|
12
|
-
* Compatible with Hocuspocus and y-websocket provider connections via `getDoc()`. Requires the `yjs` optional peer dependency.
|
|
13
|
-
* @docLink packages/base-assets/concepts#yjs-connector
|
|
14
|
-
*/
|
|
15
|
-
export declare class YjsConnector extends AbstractConnector {
|
|
16
|
-
readonly name = "yjs";
|
|
17
|
-
tools: ToolFace;
|
|
18
|
-
constructor();
|
|
19
|
-
connect(declaration: ConnectorDeclaration, _ctx: ConnectContext): Promise<ConnectorHandle>;
|
|
20
|
-
disconnect(handle: ConnectorHandle): Promise<void>;
|
|
21
|
-
private s;
|
|
22
|
-
/**
|
|
23
|
-
* Get the Y.Doc for external provider connections (Hocuspocus, y-websocket).
|
|
24
|
-
*/
|
|
25
|
-
getDoc(handle: ConnectorHandle): unknown;
|
|
26
|
-
/**
|
|
27
|
-
* Register a callback fired on every change to the root map.
|
|
28
|
-
*/
|
|
29
|
-
onDocChange(handle: ConnectorHandle, cb: (snapshot: Record<string, unknown>, changedKeys: string[]) => void): void;
|
|
30
|
-
private _read;
|
|
31
|
-
private _write;
|
|
32
|
-
private _delete;
|
|
33
|
-
private _list;
|
|
34
|
-
private _search;
|
|
35
|
-
private _describeOperations;
|
|
36
|
-
private _executeOp;
|
|
37
|
-
private _getY;
|
|
38
|
-
/** Convert a JS value to a Yjs-compatible value. */
|
|
39
|
-
private _toYjsValue;
|
|
40
|
-
/** Convert a Yjs value back to plain JS. */
|
|
41
|
-
private _fromYjsValue;
|
|
42
|
-
private _recordHistory;
|
|
43
|
-
}
|
|
44
|
-
/**
|
|
45
|
-
* Creates a new YjsConnector instance.
|
|
46
|
-
* @returns Configured YjsConnector ready to be registered in the connector registry.
|
|
47
|
-
* @docLink packages/base-assets/api-reference#yjs-connector-factory
|
|
48
|
-
*/
|
|
49
|
-
export declare function createConnector(): YjsConnector;
|
|
50
|
-
//# sourceMappingURL=adapter.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../../../../base-assets/connectors/yjs/adapter.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,iBAAiB,EAAE,MAAM,+BAA+B,CAAC;AAClE,OAAO,KAAK,EACV,cAAc,EACd,oBAAoB,EACpB,eAAe,EACf,QAAQ,EACT,MAAM,+BAA+B,CAAC;AAiBvC;;;;GAIG;AACH,qBAAa,YAAa,SAAQ,iBAAiB;IACjD,QAAQ,CAAC,IAAI,SAAS;IAEtB,KAAK,EAAE,QAAQ,CAAC;;IAeV,OAAO,CAAC,WAAW,EAAE,oBAAoB,EAAE,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,eAAe,CAAC;IAkC1F,UAAU,CAAC,MAAM,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC;IAUxD,OAAO,CAAC,CAAC;IAIT;;OAEG;IACH,MAAM,CAAC,MAAM,EAAE,eAAe,GAAG,OAAO;IAIxC;;OAEG;IACH,WAAW,CACT,MAAM,EAAE,eAAe,EACvB,EAAE,EAAE,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,WAAW,EAAE,MAAM,EAAE,KAAK,IAAI,GACrE,IAAI;YAMO,KAAK;YAQL,MAAM;YAqBN,OAAO;YAQP,KAAK;YAcL,OAAO;IAkBrB,OAAO,CAAC,mBAAmB;YAoEb,UAAU;YAiFV,KAAK;IAKnB,oDAAoD;IACpD,OAAO,CAAC,WAAW;IAenB,4CAA4C;IAC5C,OAAO,CAAC,aAAa;IAMrB,OAAO,CAAC,cAAc;CAKvB;AAED;;;;GAIG;AACH,wBAAgB,eAAe,IAAI,YAAY,CAE9C"}
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
export { YjsConnector, createConnector15 as createConnector } from '../../chunk-XAVM2BAJ.js';
|
|
2
|
-
import '../../chunk-H45ANMIU.js';
|
|
3
|
-
import '../../chunk-6MB7CRME.js';
|
|
4
|
-
import '../../chunk-QAVZOJCV.js';
|
|
5
|
-
import '../../chunk-ICS76R4T.js';
|
|
6
|
-
import '../../chunk-GZWJGNNN.js';
|
|
7
|
-
import '../../chunk-FVTV7M76.js';
|
|
8
|
-
import '../../chunk-W5DFC35Z.js';
|
|
9
|
-
import '../../chunk-JKNWJ64A.js';
|
|
10
|
-
import '../../chunk-O4JH3KUE.js';
|
|
11
|
-
import '../../chunk-K5GBV4SA.js';
|
|
12
|
-
import '../../chunk-KLNL7QHN.js';
|
|
13
|
-
import '../../chunk-DFUXWNTS.js';
|
|
14
|
-
import '../../chunk-5QNQLSBW.js';
|
|
15
|
-
import '../../chunk-FRPKLIEZ.js';
|
|
16
|
-
import '../../chunk-37JKX6D7.js';
|
|
17
|
-
import '../../chunk-24UIWON4.js';
|
|
18
|
-
import '../../chunk-NSBPE2FW.js';
|
|
19
|
-
//# sourceMappingURL=yjs.js.map
|
|
20
|
-
//# sourceMappingURL=yjs.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":[],"names":[],"mappings":"","file":"yjs.js"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../bridge/src/logger.ts","../bridge/src/types.ts","../bridge/src/registry.ts"],"names":[],"mappings":"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","file":"chunk-4ACWI5YT.js","sourcesContent":["/**\n * Bridge-layer logger factory.\n *\n * Each driver creates its own Logger via `getBridgeLogger(subkind)` at\n * construction time. Falls back to an off-mode Logger (stdout only) when\n * no LogStore is registered — see @skaile/workspaces/core/logging for details.\n */\n\nimport { createLogger } from \"@skaile/workspaces/core/logging\";\nimport type { Logger } from \"@skaile/workspaces/types\";\n\n/**\n * Construct a bridge-scoped Logger for a given driver subkind.\n *\n * Creates a `Logger` with `kind: \"bridge\"` and the specified `subkind`. Falls back to\n * an off-mode Logger (stdout only) when no `LogStore` is registered — see\n * `@skaile/workspaces/core/logging` for details. Each driver calls this once at construction\n * time; never re-construct per call.\n *\n * @param subkind - Driver id, e.g. `\"claude-sdk\"`, `\"omp\"`, `\"echo\"`, `\"codex\"`.\n * @returns A `Logger` scoped to `bridge:<subkind>`.\n * @docLink packages/bridge/api-reference#logger\n */\nexport function getBridgeLogger(subkind: string): Logger {\n return createLogger({ kind: \"bridge\", subkind });\n}\n","import { EventEmitter } from \"node:events\";\nimport type { Span, TelemetryProvider, Trace } from \"@skaile/workspaces/telemetry\";\nimport type {\n Capability,\n CredentialMint,\n RenderInvokedEvent,\n TokenUsage,\n} from \"@skaile/workspaces/types\";\nimport type { ModelEntry } from \"./models.js\";\n\n/**\n * Minimal LLM tool descriptor used by the capability dispatch path. Mirrors\n * the runner's `LLMTool` shape so drivers can consume registry output without\n * importing `@skaile/workspaces/runner` (which would create a circular dep).\n *\n * @category Capabilities\n * @since 2.0.0\n * @docLink packages/bridge/concepts#bridge-capability-tool\n */\nexport interface BridgeCapabilityTool {\n /** Capability name; used as the LLM-visible tool name. */\n name: string;\n /** Human/LLM-readable description. */\n description: string;\n /** JSON Schema for the tool's input parameters. */\n parameters: Record<string, unknown>;\n}\n\n/**\n * Render-cap event emission callback used by the bridge when the LLM invokes\n * a capability that carries a `render` spec. The runner provides the actual\n * sink (transport.send / sendEvent); the bridge only emits.\n *\n * @category Capabilities\n * @since 2.0.0\n * @docLink packages/bridge/concepts#bridge-render-emit\n */\nexport type BridgeRenderEmit = (event: RenderInvokedEvent) => void;\n\n/**\n * Text-event emission callback for render-capability fallbacks. When a\n * `RenderCapability` carries `render.fallback` and the LLM invokes it, the\n * bridge substitutes `{{prop}}` placeholders (top-level keys of `props`,\n * optional dotted-path traversal `{{user.name}}`) and pushes the rendered\n * string through this callback so clients without a render layer still see\n * a textual representation. No-op when `fallback` is absent.\n *\n * @category Capabilities\n * @since 2.0.0\n * @docLink packages/bridge/concepts#bridge-text-emit\n */\nexport type BridgeTextEmit = (text: string) => void;\n\n/**\n * Bundle of capability dispatch hooks. Registered into the driver via\n * `AgentConfig.capabilities`; the driver routes registered LLM tool calls\n * back into `invoke()` instead of using its native dispatch path.\n *\n * The runner constructs this from a `CapabilityRegistry` instance and threads\n * it through `createAgentSession()`. Drivers that don't yet implement\n * capability dispatch ignore the field — legacy v1 paths stay intact.\n *\n * @category Capabilities\n * @since 2.0.0\n * @docLink packages/bridge/concepts#bridge-capability-hooks\n */\nexport interface BridgeCapabilityHooks {\n /** Build the LLM tool descriptor list from the registry. Called per turn so registration changes take effect. */\n composeTools(): BridgeCapabilityTool[];\n /** Resolve a wire-format Capability descriptor by name. Used by the bridge to inspect `fireAndForget` / `render`. */\n resolve(name: string): Capability | null;\n /** Validate input + dispatch through the registry. Logging is wired by the registry. */\n invoke(name: string, input: unknown): Promise<unknown>;\n /** Emit a render-invoked event. The runner forwards via the WebSocket transport. */\n emitRender?: BridgeRenderEmit;\n /** Emit a text fallback for render capabilities with `render.fallback`. */\n emitText?: BridgeTextEmit;\n /** Session id passed through to the runner's per-handler logger. */\n sessionId: string;\n}\n\n/**\n * Static metadata for a registered agent driver backend.\n *\n * Returned by {@link listDrivers} and exposed on every {@link AgentDriver} instance\n * via `driverInfo`.\n *\n * @docLink packages/bridge/concepts#driver-info\n */\nexport interface DriverInfo {\n /** Stable machine identifier used to look up the driver in the registry (e.g. `\"omp\"`, `\"claude-sdk\"`). */\n id: string;\n /** Human-readable display name shown in UIs and logs. */\n name: string;\n /** `true` when the driver can target any LLM provider; `false` for Anthropic-only drivers. */\n modelAgnostic: boolean;\n /**\n * `true` when the driver supports mid-stream abort via `abort()` without killing the process.\n * Drivers that return `false` can only be stopped via `kill()`.\n */\n supportsInBandAbort: boolean;\n}\n\n/**\n * Codex-specific tuning options passed through `DriverOptions.codex`.\n *\n * @remarks These are forwarded verbatim to the Codex driver and have no effect on other drivers.\n * @docLink packages/bridge/concepts#codex-driver-options\n */\nexport interface CodexDriverOptions {\n /** Controls whether Codex may auto-apply edits without user approval. */\n approvalPolicy?: \"never\" | \"on-request\" | \"on-failure\" | \"untrusted\";\n /** Filesystem sandbox level for the Codex process. */\n sandboxMode?: \"read-only\" | \"workspace-write\" | \"danger-full-access\";\n /** Reasoning budget passed to the model. */\n reasoningEffort?: \"minimal\" | \"low\" | \"medium\" | \"high\" | \"xhigh\";\n /** When `true`, the Codex sandbox is allowed to make outbound network requests. */\n networkAccessEnabled?: boolean;\n /** Extra directories made accessible to the Codex sandbox in addition to `cwd`. */\n additionalDirectories?: string[];\n}\n\n/**\n * Driver-specific configuration bag.\n *\n * Fields are keyed by driver ID so that callers can pass driver-specific options\n * through the common {@link AgentConfig} without breaking other drivers.\n *\n * @docLink packages/bridge/concepts#driver-options\n */\nexport interface DriverOptions {\n /** Codex-specific options. Ignored by all other drivers. */\n codex?: CodexDriverOptions;\n}\n\n/**\n * Configuration passed to a driver when it is created via {@link createDriver}.\n *\n * All fields are shared across drivers; driver-specific behaviour is documented\n * per field. Fields that are silently ignored by a driver are marked accordingly.\n *\n * @docLink packages/bridge/concepts#agent-config\n */\nexport interface AgentConfig {\n /** Absolute path to the working directory the agent operates in. */\n cwd: string;\n /**\n * LLM provider name (e.g. `\"anthropic\"`, `\"openai\"`, `\"google\"`).\n * Combined with `model` as `provider/model` for omp's `--model` flag.\n * Ignored by claude-sdk (always Anthropic).\n */\n provider?: string;\n /**\n * LLM model identifier (e.g. `\"claude-sonnet-4-5\"`, `\"gpt-4o\"`).\n * For omp: passed as `--model [provider/]model`.\n * For claude-sdk: passed as the `model` query option.\n */\n model?: string;\n /**\n * Provider API keys keyed by provider name (e.g. `{ anthropic: \"sk-...\" }`).\n * Drivers inject the relevant key into the environment or SDK options.\n */\n apiKeys?: Record<string, string>;\n /**\n * Additional environment variables merged into the child process environment.\n * For omp: merged with `process.env` before spawn. For claude-sdk: accessed\n * via `env.ANTHROPIC_API_KEY` as an alternative to `apiKeys.anthropic`.\n */\n env?: Record<string, string>;\n /** Inline system prompt — written to .omp/system.md and passed via --append-system-prompt (omp driver) */\n systemPrompt?: string;\n /** Path to project .omp/ directory (PI_CODING_AGENT_DIR for omp driver) */\n agentDir?: string;\n /** SSH key path — injected as GIT_SSH_COMMAND */\n sshKeyPath?: string;\n /** Pre-assign a UUID as the session ID for a new session (claude-sdk: passed as sessionId option) */\n sessionId?: string;\n /** Resume this specific past session by UUID instead of starting fresh (claude-sdk: passed as resume option) */\n resumeSessionId?: string;\n /** Maximum agentic turns per query (claude-sdk: passed as maxTurns option) */\n maxTurns?: number;\n /** Agent name — selects a deployed sub-agent definition as the main agent identity.\n * claude-sdk: passed as `agent` option to query() → reads .claude/agents/<name>.md natively.\n * omp: ignored (omp uses agentDir/PI_CODING_AGENT_DIR instead). */\n agentName?: string;\n /** In-process SDK MCP servers for custom tool injection (Claude SDK only, ignored by other drivers) */\n mcpServers?: Record<string, unknown>;\n /** Tool restrictions from agent.yaml — applied to the main agent session */\n tools?: {\n /** Tool names that the agent is allowed to invoke. An empty array means no restriction. */\n allowed?: string[];\n /** Tool names that the agent is explicitly forbidden from invoking. */\n denied?: string[];\n };\n /** Thinking mode for Claude models: adaptive (Claude decides), enabled (always think), disabled (no thinking). */\n thinking?: \"adaptive\" | \"enabled\" | \"disabled\";\n /** Reasoning effort level for Claude models. */\n effort?: \"low\" | \"medium\" | \"high\" | \"max\";\n /** Driver-specific configuration bag. */\n driverOptions?: DriverOptions;\n /**\n * Protocol v2 capability dispatch hooks. When present, the driver uses the\n * registry as the source of LLM tool definitions and routes invocations\n * through `capabilities.invoke()`. Absent → legacy v1 path (existing\n * mcpServers / native dispatch).\n *\n * @since 2.0.0\n */\n capabilities?: BridgeCapabilityHooks;\n /**\n * The platform's `AIProviderConfig.id` for the AI credential currently\n * provisioned into this driver. The runner reads this off `AgentConfig`\n * during 401 mediation and passes it as `configId` in\n * `request_access_token { kind: 'ai-credentials' }`. The driver itself\n * does not consume this field — only the runner uses it.\n *\n * Set by the platform agent-gateway in `ConfigureCommandV2` for mediated\n * sessions. Standalone runners (CLI / forge / Claude plugin) leave it\n * undefined; the runner falls back to surfacing the auth error to the\n * user without mediating.\n *\n * Spec: `_devlog/specs/2026-05-07-unified-credential-mediation.md`\n * § \"Wire `aiProviderConfigId` end-to-end\".\n *\n * @since 3.3.0\n */\n aiProviderConfigId?: string;\n /**\n * Optional callback invoked by the driver when the underlying agent\n * surfaces an `authentication_error`. In Protocol v3 the runner mediates\n * the refresh via the `host.refresh_credential` capability and returns a\n * typed {@link CredentialMint}. The driver inspects the discriminator:\n *\n * - `mint.ok === true`: a fresh credential is now provisioned. The\n * driver re-attempts the in-flight prompt once.\n * - `mint.ok === false`: refresh failed (`code` carries a stable reason\n * such as `revoked`, `not-configured`, `provider-error`,\n * `backend-error`). The driver surfaces the original `AuthError` to\n * the caller.\n *\n * `args.configId` carries the platform `AIProviderConfig.id` the driver\n * was provisioned with (mirrors {@link AgentConfig.aiProviderConfigId}).\n * The runner uses it to scope the refresh to the correct AI credential.\n *\n * When omitted, the driver throws `AuthError` immediately as before\n * (standalone CLI / forge mode — there is no platform mediator to ask).\n *\n * Centralising auth-retry inside the driver means every consumer of\n * `driver.prompt(...)` (serve handler, compaction orchestrator, flow\n * orchestrator, …) gets self-healing for free — there is no per-call-site\n * wrapping.\n *\n * Spec: `_devlog/specs/2026-05-10-deterministic-session-bootstrap.md`\n * § \"host.refresh_credential capability\".\n *\n * @since 3.4.0\n */\n onAuthError?: (args: { configId: string }) => Promise<CredentialMint>;\n}\n\n/**\n * A single message in an agent conversation.\n *\n * Emitted as part of {@link AgentEvent} variants (`message_start`, `message_update`, `message_end`).\n *\n * @docLink packages/bridge/concepts#agent-message\n */\nexport interface AgentMessage {\n /** Originator of the message. */\n role: \"user\" | \"assistant\" | \"tool\";\n /** Message body — either a plain string or a list of typed content blocks. */\n content: string | ContentBlock[];\n /** Tool invocations made by the assistant in this message. */\n toolCalls?: ToolCall[];\n /** For `role === \"tool\"`: the name of the tool whose result this message carries. */\n toolName?: string;\n /** For `role === \"tool\"`: `true` when the tool returned an error. */\n isError?: boolean;\n /** Optional structured payload for tool results. */\n data?: unknown;\n}\n\n/**\n * A typed block within an {@link AgentMessage}'s content array.\n *\n * Mirrors the Anthropic content block schema but is driver-agnostic.\n *\n * @docLink packages/bridge/concepts#content-block\n */\nexport interface ContentBlock {\n /** Block discriminant. */\n type: \"text\" | \"tool_use\" | \"tool_result\" | \"thinking\";\n /** Present for `text` and `thinking` blocks. */\n text?: string;\n /** Tool use / tool result correlation ID. */\n id?: string;\n /** Tool name (present on `tool_use` blocks). */\n name?: string;\n /** Tool input arguments (present on `tool_use` blocks). */\n input?: any;\n /** Serialised tool result content (present on `tool_result` blocks). */\n content?: string;\n}\n\n/**\n * A single tool invocation made by the agent within a message.\n *\n * @docLink packages/bridge/concepts#tool-call\n */\nexport interface ToolCall {\n /** Correlation ID used to match the call with its result. */\n id: string;\n /** Name of the tool being invoked. */\n name: string;\n /** Arguments passed to the tool. */\n input: any;\n}\n\n/**\n * Error classification for agent failures.\n *\n * Used to determine whether a failure is retryable and to surface actionable\n * hints to the user. See `bridge/CLAUDE.md` for the full category-to-behaviour matrix.\n *\n * @see AgentError\n * @docLink packages/bridge/concepts#error-category\n */\nexport type ErrorCategory =\n | \"auth\"\n | \"rate_limit\"\n | \"model\"\n | \"network\"\n | \"config\"\n | \"process\"\n | \"validation\"\n | \"unknown\";\n\n/**\n * Structured error payload emitted inside the `error` {@link AgentEvent}.\n *\n * Consumers should inspect `retryable` before deciding to surface a retry button,\n * and `hint` to provide an actionable message to the user.\n *\n * @docLink packages/bridge/concepts#agent-error\n */\nexport interface AgentError {\n /** Human-readable error description. */\n message: string;\n /** Coarse failure classification used for retry logic and telemetry. */\n category: ErrorCategory;\n /** HTTP status code if the error originated from an API response. */\n statusCode?: number;\n /** `true` when the caller may safely retry the same operation. */\n retryable: boolean;\n /** Short actionable advice suitable for display in the UI. */\n hint?: string;\n}\n\n/**\n * Metadata for a slash command exposed by the active agent runtime.\n *\n * @docLink packages/bridge/concepts#slash-command-info\n */\nexport interface SlashCommandInfo {\n /** Command name without the leading slash (e.g. `\"compact\"`). */\n name: string;\n /** One-line description shown in command pickers. */\n description: string;\n /** Placeholder text describing what argument the command expects. */\n argumentHint?: string;\n}\n\n/**\n * Discriminated union of all events emitted by a driver on the `'agent-event'` channel.\n *\n * @remarks\n * Consumers listen via `driver.on('agent-event', (event: AgentEvent) => ...)`.\n * The `[k: string]: any` index signature on most variants allows drivers to attach\n * driver-specific fields (e.g. `_textDelta`) without breaking the union.\n *\n * @docLink packages/bridge/concepts#agent-event\n */\nexport type AgentEvent =\n | { type: \"message_start\"; message: AgentMessage; [k: string]: any }\n | { type: \"message_update\"; message: AgentMessage; [k: string]: any }\n | { type: \"message_end\"; message: AgentMessage; [k: string]: any }\n | { type: \"turn_end\"; toolResults?: AgentMessage[]; [k: string]: any }\n | { type: \"agent_end\"; [k: string]: any }\n | {\n type: \"result\";\n subtype: string;\n summary?: string;\n costUsd?: number;\n /** Per-turn token usage when the driver tracks it. Added in 3.1.0. */\n tokens?: TokenUsage;\n errors?: string[];\n [k: string]: any;\n }\n | { type: \"error\"; error: string; detail?: AgentError; fatal?: boolean; [k: string]: any }\n | { type: \"tool_call\"; name?: string; tool?: { name: string }; [k: string]: any }\n | { type: \"tool_execution_end\"; toolName?: string; [k: string]: any }\n | { type: \"commands_available\"; commands: SlashCommandInfo[] }\n | { type: \"session_info\"; driverSessionId: string; sessionFile?: string }\n | { type: \"ui_render\"; [k: string]: any }\n | { type: \"ui_render_update\"; [k: string]: any }\n | { type: \"ui_clear\"; [k: string]: any }\n // Phase 3 (resume cascade) — driver-emitted resume outcome.\n | {\n type: \"resume_failed\";\n resumeSessionId: string;\n reason: \"signature_mismatch\" | \"model_mismatch\" | \"jsonl_lost\" | \"jsonl_poisoned\";\n [k: string]: any;\n };\n\n/**\n * Abstract base class for agent driver backends.\n *\n * Wraps an LLM coding agent behind a single `prompt()` interface.\n * All drivers emit `'agent-event'` with {@link AgentEvent} payloads.\n *\n * @remarks\n * Subclasses must implement `start`, `prompt`, `abort`, `kill`, and `isRunning`.\n * Implementations should never emit an event name other than `'agent-event'` as\n * the public streaming channel — internal events (`'ready'`, `'exit'`, etc.) are\n * driver-private.\n *\n * @example\n * ```ts\n * const driver = createDriver('omp', config);\n * driver.on('agent-event', (event) => console.log(event.type));\n * await driver.start();\n * await driver.prompt('Refactor the auth module');\n * driver.kill();\n * ```\n *\n * @docLink packages/bridge/concepts#agent-driver\n */\nexport abstract class AgentDriver extends EventEmitter {\n /** Static metadata describing this driver's capabilities. */\n abstract readonly driverInfo: DriverInfo;\n\n /**\n * Initialises the driver backend — spawns the child process (omp) or loads\n * the SDK module (claude-sdk). Resolves when the backend is ready to accept\n * prompts. Idempotent: calling `start()` on an already-running driver is a no-op.\n *\n * @throws {Error} When the backend binary is missing or the SDK cannot be loaded.\n */\n abstract start(): Promise<void>;\n\n /**\n * Sends a user message to the agent and resolves when the agent's turn completes\n * (i.e. after the `agent_end` event has been emitted).\n *\n * @param message - Plain-text user prompt to send to the agent.\n * @throws {Error} When the driver is not running or the underlying backend reports a fatal error.\n */\n abstract prompt(message: string): Promise<void>;\n\n /**\n * Sends an in-band abort signal to the agent, requesting it to stop the current\n * turn without terminating the process. The driver remains usable after `abort()`.\n *\n * @remarks Only meaningful when `driverInfo.supportsInBandAbort` is `true`.\n * For other drivers, prefer `kill()` followed by creating a new driver instance.\n */\n abstract abort(): Promise<void>;\n\n /**\n * Terminates the agent backend immediately (SIGTERM for subprocess drivers,\n * `close()` for in-process drivers). The driver instance must not be reused\n * after `kill()`.\n */\n abstract kill(): void;\n\n /** `true` when the backend is alive and able to accept new prompts. */\n abstract get isRunning(): boolean;\n\n /** Optional provider-native session/thread identifier for resume support. */\n get runtimeSessionId(): string | undefined {\n return undefined;\n }\n\n /** Slash commands discovered from the agent runtime. Override in drivers that support introspection. */\n getSlashCommands(): SlashCommandInfo[] {\n return [];\n }\n\n // ── Live reconfiguration ────────────────────────────────────────────────\n\n /**\n * Live-update driver configuration. The new values take effect on the next\n * prompt() call. Only model/thinking/effort are reconfigurable mid-session.\n *\n * Subclasses that store config locally should override this to apply the\n * patch to their own config field. The base implementation is a no-op.\n */\n reconfigure(patch: Partial<Pick<AgentConfig, \"model\" | \"thinking\" | \"effort\">>): void {\n // No-op — subclasses override to apply to their own config.\n void patch;\n }\n\n /**\n * Returns the model identifier currently configured on this driver.\n * Subclasses that store config locally should override this.\n */\n getModel(): string | undefined {\n return undefined;\n }\n\n // ── Compaction support ──────────────────────────────────────────────────\n\n /**\n * Returns the token usage from the most recent completed turn.\n * Returns `null` if usage data is unavailable (e.g. driver doesn't track it).\n *\n * Widened in 3.1.0 to return the full `TokenUsage` shape (input / output /\n * cache-read / cache-creation / reasoning). All fields are optional so\n * drivers can populate just what their provider reports. Existing callers\n * that read only `inputTokens` / `outputTokens` keep working — those fields\n * are still present and carry the same semantics as before.\n */\n getTokenUsage(): TokenUsage | null {\n return null;\n }\n\n /**\n * Returns the model's context window size in tokens.\n * Returns `null` if unknown.\n */\n getContextWindow(): number | null {\n return null;\n }\n\n /**\n * Returns the list of models available to this driver without starting a session.\n * Drivers that can enumerate their own models override this method.\n * Returns an empty array by default.\n */\n async listModels(): Promise<ModelEntry[]> {\n return [];\n }\n\n /**\n * Closes the current conversation session and prepares for a fresh start.\n * The next `prompt()` call will begin a new session without prior history.\n * The driver remains usable after `resetSession()`.\n */\n abstract resetSession(): Promise<void>;\n\n // ── Telemetry ─────────────────────────────────────────────────────────────\n\n protected _telemetry?: TelemetryProvider;\n protected _activeTrace?: Trace;\n protected _activeTurnSpan?: Span;\n private _turnStartTime?: number;\n\n /**\n * Attach a telemetry provider and active trace to this driver.\n * Called by the runner after creating the driver but before start().\n */\n setTelemetry(provider: TelemetryProvider, trace: Trace): void {\n this._telemetry = provider;\n this._activeTrace = trace;\n }\n\n /**\n * Begin a turn span. Called by the runner before prompt().\n * Pass a parent span (e.g. the turn span from the orchestrator) for nesting.\n * Returns the span so the runner can annotate it further.\n */\n beginTurnSpan(\n parent?: Trace | Span,\n attrs?: Record<string, string | number | boolean>,\n ): Span | undefined {\n if (!this._telemetry || !this._activeTrace) return undefined;\n this._turnStartTime = Date.now();\n this._activeTurnSpan = this._telemetry.startSpan(parent ?? this._activeTrace, {\n name: \"llm_generation\",\n kind: \"llm_generation\",\n attributes: attrs,\n });\n return this._activeTurnSpan;\n }\n\n /**\n * End the current turn span with generation data.\n * Called by the runner after agent_end. Model and provider are passed\n * explicitly — the driver base class does not access config directly.\n */\n endTurnSpan(result?: {\n model?: string;\n provider?: string;\n inputTokens?: number;\n outputTokens?: number;\n stopReason?: string;\n error?: string;\n }): void {\n if (!this._telemetry || !this._activeTurnSpan) return;\n const durationMs = this._turnStartTime ? Date.now() - this._turnStartTime : 0;\n\n if (result?.inputTokens !== undefined || result?.outputTokens !== undefined) {\n this._telemetry.logGeneration(this._activeTurnSpan, {\n model: result?.model ?? \"unknown\",\n provider: result?.provider ?? \"unknown\",\n inputTokens: result.inputTokens,\n outputTokens: result.outputTokens,\n durationMs,\n stopReason: result.stopReason,\n });\n }\n\n this._telemetry.endSpan(this._activeTurnSpan, {\n status: result?.error ? \"error\" : \"ok\",\n error: result?.error,\n attributes: { \"skaile.turn.duration_ms\": durationMs },\n });\n\n this._activeTurnSpan = undefined;\n this._turnStartTime = undefined;\n }\n}\n\n/**\n * Factory function signature registered in the driver registry.\n *\n * @param config - Configuration for the new driver instance.\n * @returns A freshly constructed (not yet started) {@link AgentDriver}.\n * @docLink packages/bridge/concepts#driver-factory\n */\nexport type DriverFactory = (config: AgentConfig) => AgentDriver;\n","import type { ModelEntry } from \"./models.js\";\nimport type { AgentConfig, AgentDriver, DriverFactory, DriverInfo } from \"./types.js\";\n\n// Build-time backend gating. `bun build --compile --define:__INCLUDE_*__=...`\n// folds these to literal booleans so an excluded backend's driver module and\n// its SDK are dead-code-stripped from the binary. Under tsup / vitest / bun\n// run-on-source no `--define` runs and the `typeof` guard defaults to `true` —\n// every backend is available (the SDKs stay optional peers).\ndeclare const __INCLUDE_CLAUDE_SDK__: boolean;\ndeclare const __INCLUDE_CODEX__: boolean;\nconst INCLUDE_CLAUDE_SDK =\n typeof __INCLUDE_CLAUDE_SDK__ === \"undefined\" ? true : __INCLUDE_CLAUDE_SDK__;\nconst INCLUDE_CODEX = typeof __INCLUDE_CODEX__ === \"undefined\" ? true : __INCLUDE_CODEX__;\n\nconst driverRegistry = new Map<string, { factory: DriverFactory; info: DriverInfo }>();\n\n/**\n * Static capability metadata for every built-in backend.\n *\n * Pure data — this object imports no driver module and references no backend\n * SDK. {@link listDrivers} returns it (merged with any third-party drivers)\n * so selection UIs can enumerate every backend without loading a single\n * driver module. The matching driver module self-registers its factory via\n * {@link registerDriver} when {@link loadDriver} imports it.\n *\n * @docLink packages/bridge/api-reference#registry\n */\nexport const DRIVER_CATALOG: Record<string, DriverInfo> = {\n omp: {\n id: \"omp\",\n name: \"omp (oh-my-pi)\",\n modelAgnostic: true,\n supportsInBandAbort: true,\n },\n \"claude-sdk\": {\n id: \"claude-sdk\",\n name: \"Claude Agent SDK\",\n modelAgnostic: false,\n supportsInBandAbort: true,\n },\n codex: {\n id: \"codex\",\n name: \"OpenAI Codex\",\n modelAgnostic: false,\n supportsInBandAbort: true,\n },\n echo: {\n id: \"echo\",\n name: \"Echo (E2E mock)\",\n modelAgnostic: true,\n supportsInBandAbort: false,\n },\n};\n\n/**\n * Registers a driver factory under a stable string identifier.\n *\n * Built-in drivers (`omp`, `claude-sdk`, `codex`, `echo`) self-register when\n * their driver module is imported by {@link loadDriver} — `createDriver` and\n * `listModelsForDriver` trigger that load for the requested id. Third-party\n * drivers can call `registerDriver` directly at any time before the first\n * `createDriver` call that uses their id.\n *\n * @param id - Stable identifier used to look up the driver (e.g. `\"omp\"`).\n * @param factory - Function that constructs a new driver instance for the given config.\n * @param info - Static capability metadata returned by {@link listDrivers}.\n * @docLink packages/bridge/api-reference#registry\n */\nexport function registerDriver(id: string, factory: DriverFactory, info: DriverInfo): void {\n driverRegistry.set(id, { factory, info });\n}\n\n/**\n * Imports the driver module for the given built-in backend id, which\n * self-registers its factory via {@link registerDriver} on import.\n *\n * This is the single id → module map in bridge core. Every specifier is a\n * literal string so `bun --compile` can statically bundle the driver module\n * (and, transitively, its SDK). The in-process-SDK backends (`claude-sdk`,\n * `codex`) are wrapped in build-constant guards so an excluded backend's\n * `await import` folds to dead code in the compiled binary. `omp` and `echo`\n * carry no SDK weight and are always available.\n *\n * Unknown ids are a no-op — {@link createDriver} surfaces the clear error.\n * Idempotent: a second call re-imports an already-cached module.\n *\n * @param id - Built-in driver identifier (e.g. `\"omp\"`, `\"claude-sdk\"`).\n * @docLink packages/bridge/api-reference#registry\n */\nexport async function loadDriver(id: string): Promise<void> {\n switch (id) {\n case \"omp\":\n await import(\"@skaile/workspaces/drivers/omp\");\n break;\n case \"echo\":\n await import(\"@skaile/workspaces/drivers/echo\");\n break;\n case \"claude-sdk\":\n if (INCLUDE_CLAUDE_SDK) await import(\"@skaile/workspaces/drivers/claude-sdk\");\n break;\n case \"codex\":\n if (INCLUDE_CODEX) await import(\"@skaile/workspaces/drivers/codex\");\n break;\n // unknown id: no-op — createDriver throws its existing clear error\n }\n}\n\n/**\n * Creates a new driver instance for the given backend id.\n *\n * Lazily loads the driver module via {@link loadDriver} first, so callers\n * never have to register built-ins themselves. The returned driver has not\n * been started yet — call `driver.start()` before sending prompts.\n *\n * @param id - Registered driver identifier (e.g. `\"omp\"`, `\"claude-sdk\"`).\n * @param config - Configuration forwarded to the driver constructor.\n * @returns A freshly constructed (not yet started) {@link AgentDriver}.\n * @throws {Error} When `id` is a known backend excluded from this build, or\n * when `id` does not match any registered driver at all.\n * @docLink packages/bridge/api-reference#registry\n */\nexport async function createDriver(id: string, config: AgentConfig): Promise<AgentDriver> {\n await loadDriver(id);\n const entry = driverRegistry.get(id);\n if (!entry) {\n if (id in DRIVER_CATALOG) {\n throw new Error(`Agent driver \"${id}\" is not bundled in this build.`);\n }\n throw new Error(\n `Unknown agent driver: \"${id}\". Available: ${listDrivers()\n .map((d) => d.id)\n .join(\", \")}`,\n );\n }\n return entry.factory(config);\n}\n\n/**\n * Returns the capability metadata for every available driver.\n *\n * Enumerates every built-in backend from {@link DRIVER_CATALOG} without\n * loading a single driver module or backend SDK, then merges in any\n * third-party drivers registered via {@link registerDriver} that are not\n * already in the catalog. Use this to populate driver selection UIs.\n *\n * @returns Array of {@link DriverInfo} objects, one per available driver.\n * @docLink packages/bridge/api-reference#registry\n */\nexport function listDrivers(): DriverInfo[] {\n const merged = new Map<string, DriverInfo>();\n for (const info of Object.values(DRIVER_CATALOG)) {\n merged.set(info.id, info);\n }\n for (const { info } of driverRegistry.values()) {\n if (!merged.has(info.id)) merged.set(info.id, info);\n }\n return [...merged.values()];\n}\n\n/**\n * List models available to a specific driver without starting a full agent session.\n *\n * Lazily loads the driver module via {@link loadDriver}, creates a minimal\n * driver instance (no subprocess spawned, no `start()` call), delegates to\n * its `listModels()` method, and returns the result. API keys are forwarded\n * so drivers can authenticate against provider REST APIs if needed. Returns\n * `[]` when `driverId` is not registered.\n *\n * @param driverId - Registered driver id (e.g. `\"omp\"`, `\"claude-sdk\"`, `\"codex\"`).\n * @param apiKeys - Provider API keys keyed by provider name (e.g. `{ anthropic: \"sk-...\" }`).\n * Pass `settings.apiKeys ?? {}` from forge-assistant's resolved settings.\n * @docLink packages/bridge/api-reference#registry\n */\nexport async function listModelsForDriver(\n driverId: string,\n apiKeys: Record<string, string>,\n): Promise<ModelEntry[]> {\n await loadDriver(driverId);\n const entry = driverRegistry.get(driverId);\n if (!entry) return [];\n // cwd and sessionId are required by AgentConfig but none of the listModels()\n // implementations use them — they only need apiKeys / env for authentication.\n const driver = entry.factory({ cwd: process.cwd(), sessionId: \"model-list\", apiKeys });\n return driver.listModels();\n}\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../core/src/repo-manager.ts","../core/src/workspace-config.ts"],"names":["resolve","join","existsSync","mkdirSync","writeFileSync","homedir","parsePath","parse","stringify","readFileSync"],"mappings":"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","file":"chunk-5QNQLSBW.js","sourcesContent":["/**\n * Repository operations — clone, pull, scan, resolve, link.\n *\n * Remote repos are cloned to a shared global cache (~/.skaile/repos/<name>/).\n * Projects reference the cache via symlinks at .skaile/repos/<name>/.\n * Local repos (path:) are used directly. Linked repos override remote URLs.\n *\n * Supports partial clone + sparse checkout for large repos.\n */\n\nimport { spawnSync } from \"node:child_process\";\nimport {\n existsSync,\n mkdirSync,\n readFileSync,\n rmSync,\n symlinkSync,\n lstatSync,\n writeFileSync,\n} from \"node:fs\";\nimport { resolve, join } from \"node:path\";\nimport { homedir } from \"node:os\";\nimport { parse, stringify } from \"yaml\";\nimport type { AssetRef, CatalogEntry } from \"./models.js\";\nimport { parseAssetRef } from \"./models.js\";\nimport type { RepositoryDeclaration } from \"./workspace-config.js\";\nimport { scanDirectory } from \"./manifest.js\";\n\n// ── Global cache ─────────────────────────────────────────────────────────────\n\n/**\n * Return the global shared repo cache directory (`~/.skaile/repos` by default).\n * Override with the `SKAILE_CACHE_DIR` environment variable.\n * @docLink packages/core/api-reference#get-global-cache-dir\n */\nexport function getGlobalCacheDir(): string {\n return process.env.SKAILE_CACHE_DIR ?? join(homedir(), \".skaile\", \"repos\");\n}\n\n// ── Git operations ───────────────────────────────────────────────────────────\n\n/**\n * Shared env for all git subprocess spawns.\n * GIT_TERMINAL_PROMPT=0 prevents git from opening /dev/tty to ask for\n * credentials when running inside a CLI spinner (which holds the terminal in\n * raw mode). Without this, git bypasses stdio: \"pipe\" and the process hangs\n * indefinitely waiting for input that can never arrive.\n */\nconst GIT_ENV = { ...process.env, GIT_TERMINAL_PROMPT: \"0\" };\n\n/**\n * Clone a remote git repository using partial clone (treeless) with sparse checkout.\n * Falls back to a regular shallow clone if the server does not support partial clones.\n *\n * @param url - Remote git URL\n * @param branch - Branch to clone\n * @param dest - Local destination directory\n * @returns `true` on success, `false` on failure\n * @docLink packages/core/api-reference#clone-repo\n */\nexport function cloneRepo(url: string, branch: string, dest: string): boolean {\n mkdirSync(dest, { recursive: true });\n // Try partial clone first (requires git 2.25+ and server support)\n const r = spawnSync(\n \"git\",\n [\"clone\", \"--depth=1\", \"--filter=blob:none\", \"--sparse\", \"--branch\", branch, url, dest],\n { stdio: \"pipe\", env: GIT_ENV },\n );\n if (r.status === 0) {\n // Enable cone mode for sparse checkout\n spawnSync(\"git\", [\"-C\", dest, \"sparse-checkout\", \"init\", \"--cone\"], {\n stdio: \"pipe\",\n env: GIT_ENV,\n });\n // Check out everything initially (for discovery)\n spawnSync(\"git\", [\"-C\", dest, \"sparse-checkout\", \"disable\"], { stdio: \"pipe\", env: GIT_ENV });\n return true;\n }\n // Fallback: regular shallow clone\n const fallback = spawnSync(\"git\", [\"clone\", \"--depth=1\", \"--branch\", branch, url, dest], {\n stdio: \"pipe\",\n env: GIT_ENV,\n });\n return fallback.status === 0;\n}\n\n/**\n * Pull the latest commits for a cloned repository.\n * On shallow clone divergence, falls back to `git fetch --depth=1` + `git reset --hard`.\n *\n * @param dest - Local repo directory\n * @param branch - Branch to pull\n * @returns `true` on success, `false` on failure\n * @docLink packages/core/api-reference#pull-repo\n */\nexport function pullRepo(dest: string, branch: string): boolean {\n const r = spawnSync(\"git\", [\"-C\", dest, \"pull\", \"--depth=1\", \"--ff-only\"], {\n stdio: \"pipe\",\n env: GIT_ENV,\n });\n if (r.status === 0) return true;\n // Shallow clones can diverge — force-sync via fetch + reset\n const fetch = spawnSync(\"git\", [\"-C\", dest, \"fetch\", \"--depth=1\", \"origin\", branch], {\n stdio: \"pipe\",\n env: GIT_ENV,\n });\n if (fetch.status !== 0) return false;\n const reset = spawnSync(\"git\", [\"-C\", dest, \"reset\", \"--hard\", `origin/${branch}`], {\n stdio: \"pipe\",\n env: GIT_ENV,\n });\n return reset.status === 0;\n}\n\n/**\n * Return the current HEAD commit SHA for a local repository.\n *\n * @param repoDir - Absolute path to the cloned repository\n * @returns Full commit SHA string, or `null` on failure\n * @docLink packages/core/api-reference#get-repo-commit\n */\nexport function getRepoCommit(repoDir: string): string | null {\n const r = spawnSync(\"git\", [\"-C\", repoDir, \"rev-parse\", \"HEAD\"], {\n encoding: \"utf8\",\n stdio: \"pipe\",\n });\n return r.status === 0 ? r.stdout.trim() : null;\n}\n\n/**\n * Check out a specific tag, branch, or commit SHA in a local repository.\n * Fetches the ref from `origin` first, then attempts `FETCH_HEAD` checkout.\n *\n * @param repoDir - Absolute path to the cloned repository\n * @param pin - Tag, branch name, or commit SHA\n * @returns `true` on success, `false` on failure\n * @docLink packages/core/api-reference#checkout-pin\n */\nexport function checkoutPin(repoDir: string, pin: string): boolean {\n // Fetch the ref first (works for tags, branches, and commits)\n spawnSync(\"git\", [\"-C\", repoDir, \"fetch\", \"--depth=1\", \"origin\", pin], {\n stdio: \"pipe\",\n env: GIT_ENV,\n });\n const r = spawnSync(\"git\", [\"-C\", repoDir, \"checkout\", \"FETCH_HEAD\"], {\n stdio: \"pipe\",\n env: GIT_ENV,\n });\n if (r.status === 0) return true;\n // Fallback: try direct checkout (for branches already fetched)\n const r2 = spawnSync(\"git\", [\"-C\", repoDir, \"checkout\", pin], { stdio: \"pipe\", env: GIT_ENV });\n return r2.status === 0;\n}\n\n// ── Link management ──────────────────────────────────────────────────────────\n\n/**\n * Map of repo name → local filesystem path for development overrides.\n * Stored in `.skaile/links.yaml`; used to redirect a named repo to a local clone.\n * @docLink packages/core/api-reference#link-config\n */\nexport interface LinkConfig {\n [repoName: string]: string; // repo name → local path\n}\n\n/** Path to the project-local links file. */\nfunction linksFile(projectDir: string): string {\n return join(projectDir, \".skaile\", \"links.yaml\");\n}\n\n/**\n * Read the dev-link map from `.skaile/links.yaml` in the project directory.\n * Returns an empty object when no links file exists.\n *\n * @param projectDir - Absolute path to the project root\n * @returns `LinkConfig` map (may be empty)\n * @docLink packages/core/api-reference#read-links\n */\nexport function readLinks(projectDir: string): LinkConfig {\n const file = linksFile(projectDir);\n if (!existsSync(file)) return {};\n try {\n return (parse(readFileSync(file, \"utf8\")) as LinkConfig) ?? {};\n } catch {\n return {};\n }\n}\n\n/**\n * Persist the dev-link map to `.skaile/links.yaml` in the project directory.\n *\n * @param projectDir - Absolute path to the project root\n * @param links - Updated `LinkConfig` to write\n * @docLink packages/core/api-reference#write-links\n */\nexport function writeLinks(projectDir: string, links: LinkConfig): void {\n const dir = join(projectDir, \".skaile\");\n mkdirSync(dir, { recursive: true });\n writeFileSync(linksFile(projectDir), stringify(links));\n}\n\n/**\n * Register a local filesystem path as a dev override for a named repository.\n * The path is stored in `.skaile/links.yaml` and takes priority over the remote URL at runtime.\n *\n * @param projectDir - Absolute path to the project root\n * @param repoName - Name of the repository to override\n * @param localPath - Local path (absolute or relative to `projectDir`) to use instead\n * @throws When the resolved path does not exist\n * @docLink packages/core/api-reference#link-repo\n */\nexport function linkRepo(projectDir: string, repoName: string, localPath: string): void {\n const resolved = resolve(projectDir, localPath);\n if (!existsSync(resolved)) {\n throw new Error(`Path not found: ${localPath} (resolved: ${resolved})`);\n }\n const links = readLinks(projectDir);\n links[repoName] = resolved;\n writeLinks(projectDir, links);\n}\n\n/**\n * Remove the dev-link override for a named repository, reverting it to the remote URL.\n *\n * @param projectDir - Absolute path to the project root\n * @param repoName - Name of the repository to unlink\n * @returns `true` if the link existed and was removed, `false` if no link was found\n * @docLink packages/core/api-reference#unlink-repo\n */\nexport function unlinkRepo(projectDir: string, repoName: string): boolean {\n const links = readLinks(projectDir);\n if (!links[repoName]) return false;\n delete links[repoName];\n writeLinks(projectDir, links);\n return true;\n}\n\n// ── Repo lifecycle ───────────────────────────────────────────────────────────\n\n/**\n * Ensure a repository is available locally, cloning or symlinking as needed.\n *\n * Resolution order:\n * 1. Linked override (`.skaile/links.yaml`) — highest priority\n * 2. Local path (`decl.path`) — direct filesystem reference\n * 3. Remote URL (`decl.url`) — cloned to the shared global cache, symlinked into `.skaile/repos/`\n *\n * Pin support: when `opts.pin` is provided, the tag/commit is checked out after clone.\n *\n * @param decl - Repository declaration from `skaile.yaml`\n * @param name - Logical repository name (cache key)\n * @param reposDir - Project-local repos directory (`.skaile/repos/`)\n * @param opts - Optional: `pin` for a specific commit/tag, `projectDir` for link lookup\n * @returns Absolute path to the local repository directory\n * @throws When the repository cannot be resolved or cloned\n * @docLink packages/core/api-reference#ensure-repo\n */\nexport function ensureRepo(\n decl: RepositoryDeclaration,\n name: string,\n reposDir: string,\n opts?: { pin?: string; projectDir?: string },\n): string {\n // 1. Check for linked override\n if (opts?.projectDir) {\n const links = readLinks(opts.projectDir);\n if (links[name]) {\n const linked = links[name];\n if (!existsSync(linked)) {\n throw new Error(\n `Linked path not found: ${linked}. Remove the .skaile/links.yaml entry to clear it.`,\n );\n }\n return linked;\n }\n }\n\n // 2. Local path\n if (decl.path) {\n const projectDir = opts?.projectDir ?? resolve(reposDir, \"..\");\n const resolved = resolve(projectDir, decl.path);\n if (!existsSync(resolved)) {\n throw new Error(`Local repository path not found: ${decl.path} (resolved: ${resolved})`);\n }\n return resolved;\n }\n\n // 3. Remote URL — clone to shared global cache\n if (decl.url) {\n const branch = decl.branch ?? \"main\";\n const globalCache = getGlobalCacheDir();\n const cacheDest = join(globalCache, name);\n\n // Clone or pull in global cache\n if (existsSync(join(cacheDest, \".git\"))) {\n if (!opts?.pin) pullRepo(cacheDest, branch);\n } else {\n if (!cloneRepo(decl.url, branch, cacheDest)) {\n throw new Error(`Failed to clone ${decl.url} (branch: ${branch})`);\n }\n }\n\n // Checkout pin if specified\n if (opts?.pin) {\n checkoutPin(cacheDest, opts.pin);\n }\n\n // Create symlink in project-local .skaile/repos/ → global cache\n const projectDest = join(reposDir, name);\n const projectExists = existsSync(projectDest);\n const isSymlink = projectExists && lstatSync(projectDest).isSymbolicLink();\n\n if (!projectExists) {\n mkdirSync(reposDir, { recursive: true });\n try {\n symlinkSync(cacheDest, projectDest);\n } catch {\n // Symlink failed (Windows?), just use cache dir directly\n return cacheDest;\n }\n } else if (!isSymlink) {\n // Stale real directory (legacy clone) — replace with symlink to global cache\n rmSync(projectDest, { recursive: true });\n try {\n symlinkSync(cacheDest, projectDest);\n } catch {\n // Symlink failed, fall through to return cacheDest\n }\n }\n\n return cacheDest;\n }\n\n throw new Error(`Repository \"${name}\" has neither url nor path`);\n}\n\n// ── Scanning ─────────────────────────────────────────────────────────────────\n\n/**\n * Scan a repository directory and return all discovered asset catalog entries.\n * Delegates to `scanDirectory` from `manifest.ts`.\n *\n * @param repoDir - Absolute path to the repository root\n * @param repoName - Repository name attached to each produced entry\n * @returns Array of `CatalogEntry` objects found in the repository\n * @docLink packages/core/api-reference#scan-repo\n */\nexport function scanRepo(repoDir: string, repoName: string): CatalogEntry[] {\n return scanDirectory(repoDir, repoName);\n}\n\n// ── Resolution ───────────────────────────────────────────────────────────────\n\n/**\n * Resolve a single asset reference to its `CatalogEntry` by scanning declared repositories.\n *\n * Search order:\n * 1. Explicit `@repository` qualifier on the ref — only that repo is searched.\n * 2. `opts.preferRepo` — searched first when set (repo affinity for transitive deps).\n * 3. All declared repos in declaration order.\n *\n * @param ref - Parsed asset reference to resolve\n * @param repositories - Repository declarations from `skaile.yaml`\n * @param reposDir - Project-local repos directory (`.skaile/repos/`)\n * @param opts - Optional: `projectDir` for link lookup, `preferRepo` for affinity\n * @returns Matching `CatalogEntry`, or `null` if not found in any repository\n * @docLink packages/core/api-reference#resolve-asset\n */\nexport function resolveAsset(\n ref: AssetRef,\n repositories: Record<string, RepositoryDeclaration>,\n reposDir: string,\n opts?: { projectDir?: string; preferRepo?: string },\n): CatalogEntry | null {\n let repoNames: string[];\n if (ref.repository) {\n // Explicit @repo qualifier — only search that repo\n repoNames = [ref.repository];\n } else if (opts?.preferRepo && opts.preferRepo in repositories) {\n // Repo affinity from parent — search preferred repo first, then others\n const rest = Object.keys(repositories).filter((n) => n !== opts.preferRepo);\n repoNames = [opts.preferRepo, ...rest];\n } else {\n repoNames = Object.keys(repositories);\n }\n\n for (const repoName of repoNames) {\n const decl = repositories[repoName];\n if (!decl) continue;\n\n const repoDir = resolveRepoDir(decl, repoName, reposDir, opts?.projectDir);\n if (!repoDir || !existsSync(repoDir)) continue;\n\n const entries = scanRepo(repoDir, repoName);\n const match = entries.find((e) => e.kind === ref.kind && e.name === ref.name);\n if (match) return match;\n }\n\n return null;\n}\n\n/** Resolve repo dir without cloning (for lookups). Checks links first. */\nfunction resolveRepoDir(\n decl: RepositoryDeclaration,\n name: string,\n reposDir: string,\n projectDir?: string,\n): string | null {\n // Check links\n if (projectDir) {\n const links = readLinks(projectDir);\n if (links[name]) {\n return existsSync(links[name]) ? links[name] : null;\n }\n }\n\n if (decl.path) {\n const base = projectDir ?? resolve(reposDir, \"..\");\n const resolved = resolve(base, decl.path);\n return existsSync(resolved) ? resolved : null;\n }\n\n // Check project-local symlink or global cache\n const projectDest = join(reposDir, name);\n if (existsSync(projectDest)) return projectDest;\n\n const globalDest = join(getGlobalCacheDir(), name);\n if (existsSync(join(globalDest, \".git\"))) return globalDest;\n\n return null;\n}\n\n/**\n * Collision record: the same `kind:name` was found in more than one repository.\n * Produced by `resolveAll` when multiple repos contain the same asset.\n * @docLink packages/core/api-reference#asset-collision\n */\nexport interface AssetCollision {\n /** \"kind:name\" key. */\n key: string;\n /** Repository the asset was resolved from. */\n resolvedFrom: string;\n /** Other repositories that also contain this asset. */\n shadowedIn: string[];\n}\n\n/**\n * Result of a full transitive dependency resolution via `resolveAll`.\n * @docLink packages/core/api-reference#resolve-result\n */\nexport interface ResolveResult {\n /** All resolved assets in leaf-first (dependency) order. */\n resolved: CatalogEntry[];\n /** Refs that could not be found in any repo. */\n missing: string[];\n /** Maps \"kind:name\" → resolved_by (\"direct\" or \"kind:name\" of parent). */\n resolvedBy: Map<string, string>;\n /** Assets that exist in multiple repos (resolved entry shadows others). */\n collisions: AssetCollision[];\n}\n\n/**\n * Resolve all dependencies (including transitive) from a list of asset ref strings.\n * Returns resolved assets in leaf-first order (dependencies before dependents).\n *\n * Repo affinity: transitive deps inherit the parent entry's repository as a\n * search preference, so bundled assets are found in their own repo first.\n * Explicit `@repo` qualifiers always take precedence over affinity.\n *\n * @param deps - Top-level asset ref strings to resolve (e.g. `[\"skill:use-exa\", \"agent:pi\"]`)\n * @param repositories - Repository declarations from `skaile.yaml`\n * @param reposDir - Project-local repos directory\n * @param opts - Optional: `projectDir` for link lookup\n * @returns `ResolveResult` with resolved entries, missing refs, provenance map, and collisions\n * @docLink packages/core/api-reference#resolve-all\n */\nexport function resolveAll(\n deps: string[],\n repositories: Record<string, RepositoryDeclaration>,\n reposDir: string,\n opts?: { projectDir?: string },\n): ResolveResult {\n const resolved: CatalogEntry[] = [];\n const seen = new Set<string>();\n const missing: string[] = [];\n const resolvedBy = new Map<string, string>();\n\n function visit(refStr: string, parent: string, parentRepo?: string): void {\n const ref = parseAssetRef(refStr);\n const key = `${ref.kind}:${ref.name}`;\n if (seen.has(key)) return;\n seen.add(key);\n\n // Pass repo affinity: explicit @repo on the ref wins, then parent's repo\n const preferRepo = ref.repository ?? parentRepo;\n const entry = resolveAsset(ref, repositories, reposDir, {\n ...opts,\n preferRepo,\n });\n if (!entry) {\n missing.push(refStr);\n return;\n }\n\n resolvedBy.set(key, parent);\n\n // Propagate entry's repository to transitive deps\n const entryRepo = entry.repository;\n\n // Resolve transitive deps (from requires field)\n for (const req of entry.requires) {\n visit(`${req.kind}:${req.name}`, key, entryRepo);\n }\n\n // Resolve bundle dependencies\n for (const dep of entry.dependencies) {\n visit(dep, key, entryRepo);\n }\n\n resolved.push(entry);\n }\n\n for (const dep of deps) {\n visit(dep, \"direct\");\n }\n\n // Detect collisions: check each resolved asset against other repos\n const collisions = detectCollisions(resolved, repositories, reposDir, opts?.projectDir);\n\n return { resolved, missing, resolvedBy, collisions };\n}\n\n/**\n * For each resolved asset, check whether other repos also contain the same\n * kind:name pair. Returns only actual collisions (2+ repos).\n */\nfunction detectCollisions(\n resolved: CatalogEntry[],\n repositories: Record<string, RepositoryDeclaration>,\n reposDir: string,\n projectDir?: string,\n): AssetCollision[] {\n const repoNames = Object.keys(repositories);\n if (repoNames.length < 2) return [];\n\n // Build per-repo catalog caches (avoids re-scanning)\n const repoEntries = new Map<string, CatalogEntry[]>();\n for (const repoName of repoNames) {\n const decl = repositories[repoName];\n if (!decl) continue;\n const repoDir = resolveRepoDir(decl, repoName, reposDir, projectDir);\n if (!repoDir || !existsSync(repoDir)) continue;\n repoEntries.set(repoName, scanRepo(repoDir, repoName));\n }\n\n const collisions: AssetCollision[] = [];\n for (const entry of resolved) {\n const key = `${entry.kind}:${entry.name}`;\n const shadowedIn: string[] = [];\n for (const [repoName, entries] of repoEntries) {\n if (repoName === entry.repository) continue;\n if (entries.some((e) => e.kind === entry.kind && e.name === entry.name)) {\n shadowedIn.push(repoName);\n }\n }\n if (shadowedIn.length > 0 && entry.repository) {\n collisions.push({ key, resolvedFrom: entry.repository, shadowedIn });\n }\n }\n return collisions;\n}\n\n// ── Status ───────────────────────────────────────────────────────────────────\n\n/**\n * Status summary for a repository — local HEAD, remote HEAD, and how far behind.\n * @docLink packages/core/api-reference#repo-status\n */\nexport interface RepoStatus {\n /** Logical name of the repository. */\n name: string;\n /** Whether the repo is local, remote (cloned), or linked (dev override). */\n kind: \"local\" | \"remote\" | \"linked\";\n /** Current local HEAD commit SHA. */\n localHead: string;\n /** Remote HEAD commit SHA (fetched during status check). */\n remoteHead: string;\n /** Number of commits the local clone is behind the remote. */\n behind: number;\n /** `true` when `behind === 0`. */\n upToDate: boolean;\n /** Absolute path the link points to (linked repos only). */\n linkedTo?: string;\n /** Human-readable error string when the status check failed. */\n error?: string;\n}\n\n/**\n * Check whether a repository clone is up to date with its remote.\n * Fetches the last 50 commits to compare local HEAD with `origin/<branch>`.\n *\n * @param decl - Repository declaration from `skaile.yaml`\n * @param name - Logical repository name\n * @param reposDir - Project-local repos directory\n * @param projectDir - Optional project root for link lookup\n * @returns `RepoStatus` describing the current state\n * @docLink packages/core/api-reference#check-repo-status\n */\nexport function checkRepoStatus(\n decl: RepositoryDeclaration,\n name: string,\n reposDir: string,\n projectDir?: string,\n): RepoStatus {\n // Check for linked override\n if (projectDir) {\n const links = readLinks(projectDir);\n if (links[name]) {\n return {\n name,\n kind: \"linked\",\n localHead: \"\",\n remoteHead: \"\",\n behind: 0,\n upToDate: true,\n linkedTo: links[name],\n };\n }\n }\n\n const base: RepoStatus = {\n name,\n kind: decl.path ? \"local\" : \"remote\",\n localHead: \"\",\n remoteHead: \"\",\n behind: 0,\n upToDate: true,\n };\n\n if (decl.path) return base;\n\n // Check global cache first, then project-local\n let dest = join(getGlobalCacheDir(), name);\n if (!existsSync(join(dest, \".git\"))) {\n dest = join(reposDir, name);\n }\n if (!existsSync(join(dest, \".git\"))) {\n return { ...base, error: \"Not cloned yet\" };\n }\n\n const branch = decl.branch ?? \"main\";\n\n const localHead = getRepoCommit(dest);\n if (!localHead) return { ...base, error: \"Failed to read local HEAD\" };\n base.localHead = localHead;\n\n const fetchR = spawnSync(\"git\", [\"-C\", dest, \"fetch\", \"--depth=50\", \"origin\", branch], {\n encoding: \"utf8\",\n stdio: \"pipe\",\n env: GIT_ENV,\n });\n if (fetchR.status !== 0) return { ...base, error: \"Fetch failed\" };\n\n const remoteR = spawnSync(\"git\", [\"-C\", dest, \"rev-parse\", `origin/${branch}`], {\n encoding: \"utf8\",\n stdio: \"pipe\",\n });\n if (remoteR.status !== 0) return { ...base, error: \"Failed to read remote HEAD\" };\n base.remoteHead = remoteR.stdout.trim();\n\n const countR = spawnSync(\n \"git\",\n [\"-C\", dest, \"rev-list\", \"--left-right\", \"--count\", `HEAD...origin/${branch}`],\n { encoding: \"utf8\", stdio: \"pipe\" },\n );\n if (countR.status === 0) {\n const parts = countR.stdout.trim().split(/\\s+/);\n base.behind = parseInt(parts[1] ?? \"0\", 10);\n }\n\n base.upToDate = base.behind === 0;\n return base;\n}\n","/**\n * Unified workspace configuration — `skaile.yaml` / `<name>.skaile.yaml`\n *\n * Single file combining AI resources, data connectors, agent behavior,\n * runtime defaults, and workspace layout.\n *\n * ── File naming ──────────────────────────────────────────────────────────\n *\n * skaile.yaml → canonical default workspace config\n * staging.skaile.yaml → alternative workspace config\n * *.skaile.yaml → glob pattern for named configs\n *\n * ── Stacking ─────────────────────────────────────────────────────────────\n *\n * Files stack across scope levels (same name must match):\n * ~/.skaile/skaile.yaml priority 10 (user)\n * /app/skaile.yaml priority 20 (app)\n * /project/skaile.yaml priority 30 (project)\n *\n * ── Relationship to other files ──────────────────────────────────────────\n *\n * .skaile/settings.json User-specific overrides (API keys, personal\n * model preferences). Gitignored. Overrides\n * workspace config defaults at runtime.\n *\n * workspace.yaml Scaffold template. Generates skaile.yaml\n * at `skaile init` time. Never read at runtime.\n *\n * agent.yaml Agent definition (identity). Referenced from\n * skaile.yaml via `agent.definition`.\n */\n\nimport { existsSync, mkdirSync, readdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { dirname, join, parse as parsePath, resolve } from \"node:path\";\nimport { parse, stringify } from \"yaml\";\nimport { fromMcpServerMd } from \"./manifest.js\";\nimport { type CatalogEntry, parseAssetRef } from \"./models.js\";\nimport { getGlobalCacheDir, resolveAsset } from \"./repo-manager.js\";\n\n// ── Agent config ──────────────────────────────────────────────────────────────\n\n/**\n * Named agent configuration profile. The \"default\" profile is the active one.\n * Personal overrides (apiKeys, model preference) live in .skaile/settings.json.\n * @docLink packages/core/workspace-config#agent-config-profile\n */\nexport interface AgentConfigProfile {\n /** Bridge driver to use: \"claude-sdk\", \"codex\", or \"omp\". */\n driver?: string;\n /** Default LLM provider: \"anthropic\", \"openai\", \"google\", etc. */\n provider?: string;\n /** Default model identifier. */\n model?: string;\n /** Thinking mode for Claude models. */\n thinking?: \"adaptive\" | \"enabled\" | \"disabled\";\n /** Reasoning effort level. */\n effort?: \"low\" | \"medium\" | \"high\" | string;\n /** Override framework install paths (rarely needed). */\n skills_dir?: string;\n agents_dir?: string;\n prompts_dir?: string;\n}\n\n// ── Startup ───────────────────────────────────────────────────────────────────\n\n/**\n * A startup directive — run on workspace launch.\n *\n * String form: \"agent:research-assistant\" — start the named agent\n * Object form: { \"system-prompt-override\": \"...\" } — replace system prompt\n * { \"system-prompt-append\": \"...\" } — append to system prompt\n * @docLink packages/core/workspace-config#startup-directive\n */\nexport type StartupDirective = string | Record<string, string>;\n\n// ── AI Resources ──────────────────────────────────────────────────────────────\n\n/**\n * An AI resource source with its own dependency list.\n * All declared dependencies are installed from this source's catalog.\n * @docLink packages/core/workspace-config#ai-resource-entry\n */\nexport interface AiResourceEntry {\n /** Source name (used as cache key and in CLI output). */\n name: string;\n /** Path to local directory or GitHub repo URL. */\n path: string;\n /** Git branch (default: main). */\n branch?: string;\n /** Skill/agent/package/flow refs to install from this source. Syntax: \"kind:name\". */\n dependencies?: string[];\n /** Auto-deploy to framework dirs on install. */\n auto_deploy?: boolean;\n}\n\n// ── Repository Declaration ────────────────────────────────────────────────────\n\n/**\n * Internal-only data shape used by the legacy asset install pipeline\n * (`repo-manager`, `lock`, `runtime-assets`). Carries the resolved URL or\n * path for an `ai_resources[]` entry. Not surfaced via the workspace config\n * schema — new sources are registered through `@skaile/library`.\n *\n * @docLink packages/core/workspace-config#repository-declaration\n */\nexport interface RepositoryDeclaration {\n /** GitHub or git URL (for remote repos). */\n url?: string;\n /** Local filesystem path (for local repos). */\n path?: string;\n /** Git branch (default: main). */\n branch?: string;\n /** Upstream URL for fork workflows. */\n upstream?: string;\n}\n\n// ── Source Entry ──────────────────────────────────────────────────────────────\n\n/**\n * A github source registered for this project — a third-party repo of AI\n * assets the project depends on. Bytes live under `~/.skaile/sources/<name>/`\n * (machine-global clone cache); this entry is the *per-project* declaration\n * that the project uses the source.\n *\n * Persisted under the `sources:` key in `skaile.yaml`.\n *\n * @docLink packages/core/workspace-config#source-entry\n */\nexport interface SourceEntry {\n /** Slug used as cache directory name (`~/.skaile/sources/<name>/`). */\n name: string;\n /** Git URL (ssh or https). */\n url: string;\n /** Git branch (default: main). */\n branch?: string;\n}\n\n// ── Mounts ──────────────────────────────────────────────────────────────────\n\n/**\n * A filesystem mount — projected storage backend.\n * @docLink packages/core/workspace-config#mount-declaration\n */\ninterface MountDeclaration {\n /** Unique identifier. Used as mount dir name. */\n id: string;\n /** Mount driver: \"local\", \"git\", \"s3\", \"webdav\", \"sharepoint\". */\n driver: string;\n /** What to mount: URL, bucket path, host filesystem path. */\n source: string;\n /** Workspace-relative mount point (default: .mounts/<id>). */\n target?: string;\n /** Access level enforced by the mount driver. */\n access?: \"read-only\" | \"read-write\";\n /** Credential reference: \"env:VAR_NAME\" or inline value. */\n auth?: string;\n /**\n * Whether to watch this mount for filesystem changes.\n * true = always watch, false = never watch, undefined = auto (watch if read-write).\n */\n watch?: boolean;\n /**\n * **Expert-only.** When `true`, the mount manager wires the resolved\n * credential into the workspace so the agent's interactive `git`/`curl`\n * tools can authenticate directly against the mount's host. Defaults to\n * `false` — agents have no credential exposure and rely on driver-managed\n * pulls/pushes. See `_devlog/specs/2026-05-05-git-credential-tiers.md`.\n */\n exposeAccessToken?: boolean;\n /**\n * Optional override for the access token TTL (seconds). When omitted, the\n * provider's natural TTL is used. Values above the provider's documented\n * maximum are silently capped.\n */\n accessTokenTTL?: number;\n /** Driver-specific configuration (branch, region, etc.). */\n options?: Record<string, unknown>;\n}\n\n// ── Connectors ────────────────────────────────────────────────────────────────\n\n/**\n * A data connector — tool-accessed backend the agent interacts with.\n * @docLink packages/core/workspace-config#connector-declaration\n */\nexport interface ConnectorDeclaration {\n /** Unique identifier. Used as tool namespace. */\n id: string;\n /** Connector adapter: \"postgres\", \"redis\", \"sqlite\", \"memory\", \"xstate\", \"xstate-store\", \"yjs\". */\n driver: string;\n /**\n * Access level enforced by ConnectorManager.\n * Optional in config — ConnectorManager defaults to \"read-only\" when absent.\n */\n access?: \"read-only\" | \"read-write\";\n /** Credential reference: \"env:VAR_NAME\" or inline value. */\n auth?: string;\n /** Adapter-specific configuration (dsn, host, etc.). */\n options?: Record<string, unknown>;\n\n // ── Extended fields (Plan A: first-level asset support) ──────────────────\n /** Semver range for future catalog versioning, e.g. \"^1.0.0\". */\n version?: string;\n /**\n * Run a health check (ping) when the connector is first connected.\n * Default: false. Set to true to surface connection errors early.\n */\n health_check?: boolean;\n /**\n * Inject this connector's skill description into the agent's system prompt.\n * Default: false.\n */\n expose_as_skill?: boolean;\n /** Tags for catalog browsing and skill routing. */\n tags?: string[];\n\n /**\n * Optional filesystem face — makes the connector \"mountable\".\n * When present, ConnectorManager allocates a mount directory and passes it\n * to the connector via `ConnectContext.mountTarget`.\n *\n * YAML key: `mount` (sub-block under a `connectors:` entry).\n * Replaces the legacy top-level `mounts:` key (hard cut — see Task 11).\n */\n mount?: {\n /** Source URL or path (repo URL, bucket name, host path). */\n source: string;\n /** Override mount target directory (default: `.mounts/<id>/`). */\n target?: string;\n /** Watch flag: omitted → watch read-write, skip read-only. */\n watch?: boolean;\n /** Expert-only: expose the resolved credential to the agent CLI. */\n exposeAccessToken?: boolean;\n /** Optional access-token TTL override (seconds). */\n accessTokenTTL?: number;\n };\n}\n\n// ── MCP Servers ──────────────────────────────────────────────────────────────\n\n/**\n * Reference to a Nix-built asset recipe.\n *\n * The `attr` field selects an attribute path in the platform's flake\n * (`/etc/skaile/flake/`), e.g. `mcps.excel`, `mcps.ppt`, `stacks.baseline`.\n * Resolution happens at session start (cold) and on `reconfigure_mcps`\n * (hot-add) via `nix path-info --offline`.\n *\n * @docLink packages/core/concepts#asset-recipe\n */\nexport interface AssetRecipe {\n /** Flake attribute path, e.g. `mcps.excel`. */\n attr: string;\n}\n\n/**\n * Validates an `AssetRecipe.attr` value against nix attribute path syntax.\n *\n * Nix attribute paths are dot-separated segments. Each segment must start with\n * a letter and contain only letters, digits, underscores, hyphens, and dots.\n * Characters like `#`, spaces, and nix expression fragments are explicitly\n * rejected — even though `spawnSync` array args prevent shell injection, nix\n * parses the combined `flakeRef#attr` string and invalid chars trigger\n * unintended evaluation paths.\n *\n * Deliberate restriction: leading digits per segment are not allowed even\n * though some nix attrs permit them, because they are rare in practice and\n * the restriction makes the validation straightforward to audit.\n *\n * @throws Error when `attr` is invalid\n */\nexport function validateAssetRecipeAttr(attr: string): void {\n if (typeof attr !== \"string\" || attr.length === 0) {\n throw new Error(\"AssetRecipe.attr must be a non-empty string\");\n }\n if (attr.length > 200) {\n throw new Error(`AssetRecipe.attr too long (${attr.length} chars, max 200)`);\n }\n const VALID_ATTR = /^[a-z][a-z0-9._-]*(?:\\.[a-z][a-z0-9._-]*)*$/i;\n if (!VALID_ATTR.test(attr)) {\n throw new Error(\n `AssetRecipe.attr \"${attr}\" contains invalid characters. ` +\n `Allowed: letters, digits, underscore, hyphen, dot. ` +\n `Each dot-segment must start with a letter.`,\n );\n }\n}\n\n/**\n * A declarative external MCP server — spawned or connected at session startup\n * and injected into the Claude SDK driver as a named `mcpServers` entry.\n *\n * Maps directly to the Claude Agent SDK's `McpServerConfig` union:\n * - `transport: \"stdio\"` (default) → `McpStdioServerConfig` — subprocess spawn\n * - `transport: \"sse\"` → `McpSSEServerConfig` — HTTP Server-Sent Events\n * - `transport: \"http\"` → `McpHttpServerConfig` — HTTP streaming\n *\n * The `id` becomes the key in the SDK's `mcpServers` record and also the MCP\n * tool prefix (e.g., `mcp__my-server__<tool-name>`).\n * @docLink packages/core/workspace-config#mcp-server-declaration\n */\nexport interface McpServerDeclaration {\n /** Unique identifier — used as the `mcpServers` record key and tool prefix. */\n id: string;\n /**\n * Transport type.\n * Default: `\"stdio\"` (subprocess).\n */\n transport?: \"stdio\" | \"sse\" | \"http\";\n /** For `\"stdio\"`: the command to execute (e.g. `\"npx\"`, `\"node\"`, `\"python\"`). */\n command?: string;\n /** For `\"stdio\"`: arguments passed to the command. */\n args?: string[];\n /** For `\"stdio\"`: environment variables injected into the subprocess. */\n env?: Record<string, string>;\n /** For `\"sse\"` and `\"http\"`: the server URL. */\n url?: string;\n /** For `\"sse\"` and `\"http\"`: HTTP headers (e.g. `Authorization`). */\n headers?: Record<string, string>;\n /** Short description of what this server provides (used in catalog). */\n description?: string;\n /** Tags for catalog browsing and discovery. */\n tags?: string[];\n /**\n * Optional Nix recipe binding. When present, the runner resolves the\n * recipe's `/nix/store` out-path before subprocess spawn and substitutes\n * `${recipe:<id>}` / `${recipe:<id>:<sub>}` / `${recipe:<id>:bin}` /\n * `${recipe:<id>:lib}` markers in `command`, `args`, and `env` values.\n * `<id>` matches this declaration's `id` field.\n */\n recipe?: AssetRecipe;\n}\n\n// ── Agent Configuration ──────────────────────────────────────────────────────\n\n/**\n * Platform-level context describing the environment the agent operates in.\n * Rendered by the runner into a \"## Platform\" section of the system prompt.\n */\nexport interface AgentContextConfig {\n /** Platform identifier (e.g. \"skaile\"). Controls the rendered header sentence. */\n platform?: string;\n /** Whether multiple users may interact in the same session. */\n multi_user?: boolean;\n /** Session persistence model. */\n session_model?: \"persistent\" | \"ephemeral\";\n}\n\nexport interface AgentConfig {\n /**\n * Agent definition reference. Resolved in order:\n * - Local path: \".skaile/agent\" or \"./my-agent\"\n * - Catalog reference: \"agent:<name>\" (resolved via asset manager catalog)\n * - Resource path: \"ai-assets://<domain>/agents/<name>\"\n */\n definition?: string;\n\n /**\n * Platform-level context (platform identifier, multi-user flag, session model).\n * Consumed by the runner to build the \"## Platform\" section of the system prompt.\n */\n context?: AgentContextConfig;\n\n /** Agent runtime constraints. */\n permissions?: AgentPermissions;\n\n /** Lifecycle hooks — shell commands run at specific points. */\n hooks?: AgentHooks;\n\n /** Named subagent definitions available for delegation. */\n subagents?: Record<string, SubagentConfig>;\n\n /**\n * Control which framework fragments are included in the rendered system prompt.\n * true (default) — include built-in fragment\n * false — omit this fragment\n * string — path to a custom markdown file (relative to project root)\n *\n * Fragment IDs: \"agent-mode\" | \"skill-discovery\" | \"connector-usage\" | \"handoff\"\n */\n fragments?: Record<string, boolean | string>;\n\n /**\n * Additional markdown files appended at the end of every rendered agent system\n * prompt in this workspace. Paths relative to the project root (skaile.yaml).\n *\n * YAML key: `prompt-extensions`\n */\n \"prompt-extensions\"?: string[];\n\n /**\n * Free-form user-authored agent prompt. Plain text or markdown — no length\n * cap, no template substitution. Prepended immediately after the platform\n * context section and before the environment section in the assembled\n * system prompt (see runner's {@link assembleSystemPrompt}).\n *\n * Written by the platform's wake-time yaml serializer from the combined\n * project-level + session-level prompts stored on `SkaileConfigData.agent.prompt`.\n * Standalone CLI / forge sessions may set this directly in `skaile.yaml`.\n *\n * Spec: `docs/superpowers/specs/2026-05-13-platform-agent-prompt-design.md`\n * @since 2026-05\n */\n prompt?: string;\n}\n\nexport interface AgentPermissions {\n /** Maximum agentic turns per query (default: 15). */\n max_turns?: number;\n /**\n * Permission mode for Claude SDK driver.\n * 'auto' = bypassPermissions (default for automated flows).\n * 'interactive' = prompt for each tool use.\n */\n permission_mode?: \"auto\" | \"interactive\";\n /** Glob patterns the agent may NOT write to. Stacking: union across scopes. */\n deny_write?: string[];\n /** Glob patterns the agent may NOT read. Stacking: union across scopes. */\n deny_read?: string[];\n}\n\nexport interface AgentHooks {\n /** Run before a flow starts (after resources are connected). */\n pre_flow?: HookEntry[];\n /** Run after a flow completes (before resources disconnect). */\n post_flow?: HookEntry[];\n /** Run before each flow node executes. */\n pre_node?: HookEntry[];\n /** Run after each flow node completes successfully. */\n post_node?: HookEntry[];\n}\n\nexport interface HookEntry {\n /** Human-readable hook name. */\n name: string;\n /** Shell command to execute. */\n run: string;\n /** Working directory relative to workspace root (default: workspace root). */\n cwd?: string;\n /** Timeout in seconds (default: 60). */\n timeout?: number;\n /** Continue flow if hook fails (default: false). */\n continue_on_error?: boolean;\n}\n\nexport interface SubagentConfig {\n /** What this subagent does. */\n description: string;\n /** System prompt for the subagent. */\n prompt: string;\n /** Tools this subagent may use (default: all). */\n tools?: string[];\n /** Tools this subagent may NOT use. */\n disallowed_tools?: string[];\n /** Model override. */\n model?: string;\n}\n\n// ── Workspace Layout ─────────────────────────────────────────────────────────\n\nexport interface WorkspaceLayoutConfig {\n /** Directories to ensure exist (created at scaffold time, verified at run time). */\n directories?: string[];\n\n /** Git configuration. */\n git?: GitConfig;\n\n /** Post-scaffold setup commands (run once after `skaile init`). */\n setup?: SetupEntry[];\n\n /** Container configuration (Docker). */\n container?: ContainerConfig;\n}\n\nexport interface GitConfig {\n /** Initialize a git repo at scaffold time (default: true). */\n init?: boolean;\n /** .gitignore entries. Stacking: concatenate + deduplicate. */\n ignore?: string[];\n}\n\nexport interface SetupEntry {\n /** Human-readable name. */\n name: string;\n /** Shell command to execute. */\n run: string;\n /** Working directory relative to workspace root. */\n cwd?: string;\n /** Continue if command fails (default: false). */\n continue_on_error?: boolean;\n}\n\nexport interface NixContainerConfig {\n /**\n * Nixpkgs package attribute names to include in the environment.\n * Example: [\"nodejs_22\", \"bun\", \"git\", \"python3\"]\n */\n packages?: string[];\n /**\n * Nixpkgs registry name used as a package prefix for `nix shell`.\n * MUST be a bare registry name like \"nixpkgs\" — not a channel path like\n * \"nixpkgs/nixos-24.11\" (which is not valid as a flake ref prefix).\n * Defaults to \"nixpkgs\".\n */\n channel?: string;\n /**\n * Path to a Nix file (shell.nix / flake.nix) relative to the project root.\n * When set, `packages` and `channel` are ignored — the file is the source of truth.\n */\n flake?: string;\n /**\n * Predefined named stack to resolve from the system stack registry (SKAILE_NIX_STACK_REGISTRY).\n * Overridden by `packages` if present.\n * Takes precedence over the parent `ContainerConfig.stack` field when nix mode is active.\n */\n stack?: string;\n}\n\nexport interface ContainerConfig {\n /** Enable Docker container generation. */\n enabled?: boolean;\n /** Base Docker image. */\n image?: string;\n /** System packages to install. */\n packages?: string[];\n /** Agent CLIs to install globally in the container. */\n agent_clis?: string[];\n /** Ports to expose. */\n ports?: string[];\n /** Environment variables to pass through. */\n env?: string[];\n /** Docker volume/bind mounts. */\n mounts?: Array<{ type: \"bind\" | \"volume\"; source: string; target: string }>;\n /** WebSocket port for IPC. */\n ws_port?: number;\n /**\n * Named system stack.\n * - Docker mode: resolved to an image tag via `dockerImageMap` (SKAILE_DOCKER_IMAGE_MAP).\n * - Nix mode: resolved to a package list via `nixStackRegistry` (SKAILE_NIX_STACK_REGISTRY).\n * Overridden by `nix.stack` if both are present.\n */\n stack?: string;\n /** Nix-specific environment configuration (nix session mode only). */\n nix?: NixContainerConfig;\n}\n\n// ── Top-level config ──────────────────────────────────────────────────────────\n\nexport interface SkWorkspaceConfig {\n /** Project name (defaults to directory basename). */\n name?: string;\n /** Project description. */\n description?: string;\n\n /**\n * Agent configuration profiles. The \"default\" profile provides runtime\n * defaults (framework, model, provider). Personal overrides live in\n * .skaile/settings.json and always take priority.\n *\n * YAML key: `agent-config` or `agent_config`\n */\n agent_config?: Record<string, AgentConfigProfile>;\n\n /**\n * Startup directives — executed when the workspace is launched.\n * Each item is either a string (\"agent:name\") or a map\n * ({ \"system-prompt-override\": \"...\" }).\n */\n startup?: StartupDirective[];\n\n /**\n * Internal-only — always `{}` on the merged config. Kept on the shape so\n * `repo-manager`, `lock`, and `runtime-assets` keep type-checking; their\n * `Record<string, RepositoryDeclaration>` arguments are built from\n * `ai_resources[]` entries inside the install pipeline.\n */\n repositories?: Record<string, RepositoryDeclaration>;\n\n /**\n * Asset dependencies using kind:name[@repo][#pin] syntax (new format).\n * Top-level flat list — repos and deps are separate concerns.\n *\n * YAML key: `dependencies`\n */\n dependencies?: string[];\n\n /**\n * Github sources this project depends on. Each entry names a clone under\n * `~/.skaile/sources/<name>/` (machine-global cache). `skaile init` and\n * `skaile install` clone any missing entries; `skaile source add/remove/sync`\n * are the CRUD surface.\n *\n * YAML key: `sources`\n */\n sources?: SourceEntry[];\n\n /**\n * Local patches applied during install (new format).\n * Maps \"kind:name\" → patch file path relative to project root.\n *\n * YAML key: `patches`\n */\n patches?: Record<string, string>;\n\n /**\n * AI resource sources, each with its own dependency list.\n * @deprecated Use `repositories` + `dependencies` instead.\n */\n ai_resources?: AiResourceEntry[];\n\n /**\n * @deprecated The top-level `mounts:` key is no longer supported as of Task 11.\n *\n * Move filesystem-projected storage backends under `connectors:` with a\n * `mount:` sub-block. See `docs/migration-mounts-to-connectors.md`.\n *\n * This field is kept on the type **only** so `config.ts` can detect a\n * present `mounts:` block and throw a migration error. It is never merged,\n * applied, or forwarded to any manager. `normalizeConfig` still populates it\n * when `mounts:` is present in the YAML so the detection check works.\n *\n * YAML key: `mounts` (rejected at runtime — do not use)\n */\n mounts?: MountDeclaration[];\n\n /**\n * Data connectors — tool-accessed backends.\n *\n * Each declaration's `driver` field is an *implicit* catalog ref\n * (`connector:<driver>`). The runtime resolves it through\n * `resolveRuntimeAssets()`, which scans every declared `repositories` entry\n * plus the implicit `@skaile/base-assets` repo for matching `CONNECTOR.md`\n * manifests. Drivers that do not match any catalog entry produce a\n * `missing_driver` warning at session startup.\n *\n * YAML key: `connectors`\n */\n connectors?: ConnectorDeclaration[];\n\n /**\n * External MCP servers — injected into the Claude SDK driver at session startup.\n * Supports stdio subprocess, SSE, and HTTP transports.\n *\n * YAML key: `mcp_servers`\n */\n mcp_servers?: McpServerDeclaration[];\n\n /** Agent behavior — definition reference, permissions, hooks, subagents. */\n agent?: AgentConfig;\n\n /** Workspace layout — directories, git, setup scripts, container. */\n workspace?: WorkspaceLayoutConfig;\n\n /**\n * Secret provisioning configuration.\n * Controls how connector credentials are resolved at runtime.\n *\n * YAML key: `secrets`\n */\n secrets?: SecretsConfig;\n\n /**\n * Telemetry configuration — passed through raw to the telemetry package.\n * Parsed by `resolveTelemetryConfig` in `@skaile/workspaces/telemetry`.\n *\n * YAML key: `telemetry`\n */\n telemetry?: Record<string, unknown>;\n\n /**\n * Session compaction settings -- controls when and how conversation\n * snapshots are created.\n *\n * YAML key: `compaction`\n */\n compaction?: CompactionConfig;\n}\n\nexport interface SecretsConfig {\n /**\n * How secrets are provided to the container.\n * \"env\" — read from process.env (default, for CLI/standalone)\n * \"provisioned\" — wait for secrets over transport bridge (platform containers)\n */\n provider?: \"env\" | \"provisioned\";\n /** Timeout in ms for waiting for provisioned secrets (default: 30000). */\n timeoutMs?: number;\n}\n\n// ── Compaction config ────────────────────────────────────────────────────────\n\nexport interface CompactionConfig {\n /** Enable managed compaction (default: true). */\n enabled?: boolean;\n /** Context fill percentage that triggers compaction (default: 80). */\n thresholdPercent?: number;\n /** Compact before hibernation for cheap restores (default: true). */\n compactOnHibernate?: boolean;\n /** Minimum ms between compactions to prevent thrashing (default: 120000). */\n minCooldownMs?: number;\n /** Enable manual compact command in expert mode (default: false). */\n manualCompactEnabled?: boolean;\n}\n\nexport const COMPACTION_DEFAULTS: Required<CompactionConfig> = {\n enabled: true,\n thresholdPercent: 80,\n compactOnHibernate: true,\n minCooldownMs: 120_000,\n manualCompactEnabled: false,\n};\n\n// ── Deprecated type aliases ───────────────────────────────────────────────────\n\n/** @deprecated Use AgentConfigProfile */\nexport interface RuntimeDefaults {\n framework?: string;\n driver?: string;\n provider?: string;\n model?: string;\n skills_dir?: string;\n agents_dir?: string;\n prompts_dir?: string;\n}\n\n/** @deprecated Use AiResourceEntry[] */\nexport interface AiResourcesConfig {\n sources?: AiResourceSource[];\n requires?: string[];\n auto_deploy?: boolean;\n}\n\n/** @deprecated Use AiResourceEntry */\nexport interface AiResourceSource {\n name: string;\n path: string;\n branch?: string;\n}\n\n// ── Config file info ──────────────────────────────────────────────────────────\n\nexport interface SkWorkspaceConfigFile {\n /** Absolute path to the config file. */\n path: string;\n /** Workspace name (extracted from filename). */\n name: string;\n /** Parsed config. */\n config: SkWorkspaceConfig;\n /**\n * Diagnostics from decoding this file — legacy-shape warnings (camelCase keys,\n * flat agent-config, the old ai_resources object) and unrecognized\n * driver/provider/access values. Absent on configs synthesized in-memory.\n */\n diagnostics?: Diagnostic[];\n}\n\n// ── Constants ─────────────────────────────────────────────────────────────────\n\n/** Suffix for named workspace configs: `<name>.skaile.yaml` */\nexport const SKAILE_YAML_SUFFIX = \".skaile.yaml\";\n/** Filename for the default workspace config when no name is given. */\nexport const SKAILE_YAML_DEFAULT = \"skaile.yaml\";\n\n/** @deprecated Use SKAILE_YAML_SUFFIX */\nexport const SK_WORKSPACE_SUFFIX = SKAILE_YAML_SUFFIX;\n/** @deprecated Use SKAILE_YAML_DEFAULT */\nexport const SK_WORKSPACE_DEFAULT_NAME = \"default\";\n\n// ── Config I/O ────────────────────────────────────────────────────────────────\n\n/**\n * Return the canonical filename for a workspace config.\n * The default workspace resolves to `\"skaile.yaml\"`; named workspaces resolve to\n * `\"<name>.skaile.yaml\"`.\n *\n * @param name - Optional workspace name (omit or pass `\"default\"` for the primary config)\n * @returns Filename string (not a full path)\n * @docLink packages/core/workspace-config#workspace-config-filename\n */\nexport function workspaceConfigFilename(name?: string): string {\n if (!name || name === \"default\") return SKAILE_YAML_DEFAULT;\n return `${name}${SKAILE_YAML_SUFFIX}`;\n}\n\n/**\n * Return `true` if `filename` matches the workspace config naming convention\n * (`\"skaile.yaml\"` or any `\"*.skaile.yaml\"`).\n *\n * @param filename - Bare filename (no directory component)\n * @docLink packages/core/workspace-config#is-workspace-config-filename\n */\nexport function isWorkspaceConfigFilename(filename: string): boolean {\n return filename === SKAILE_YAML_DEFAULT || filename.endsWith(SKAILE_YAML_SUFFIX);\n}\n\n/**\n * Extract the workspace name from a config filename.\n * `\"skaile.yaml\"` → `\"default\"`, `\"staging.skaile.yaml\"` → `\"staging\"`.\n *\n * @param filename - Bare filename produced by `workspaceConfigFilename`\n * @returns Workspace name string\n * @docLink packages/core/workspace-config#workspace-name-from-filename\n */\nexport function workspaceNameFromFilename(filename: string): string {\n if (filename === SKAILE_YAML_DEFAULT) return \"default\";\n return filename.slice(0, -SKAILE_YAML_SUFFIX.length);\n}\n\n/**\n * Load a single workspace config file from `dir`.\n * When `name` is omitted and no `skaile.yaml` exists, falls back to the sole\n * `*.skaile.yaml` file in the directory if exactly one is present.\n *\n * @param dir - Directory to search for the config file\n * @param name - Optional workspace name (omit for the default `skaile.yaml`)\n * @returns Parsed config file info, or `null` if no matching file was found\n * @docLink packages/core/workspace-config#load-sk-workspace-config\n */\nexport function loadSkWorkspaceConfig(dir: string, name?: string): SkWorkspaceConfigFile | null {\n const resolvedDir = resolve(dir);\n const canonicalName = name && name !== \"default\" ? name : undefined;\n\n const filename = workspaceConfigFilename(canonicalName);\n const filePath = join(resolvedDir, filename);\n if (existsSync(filePath)) {\n return parseConfigFile(filePath, canonicalName ?? \"default\");\n }\n\n if (!canonicalName) {\n const found = listSkWorkspaceConfigs(resolvedDir);\n if (found.length === 1) return found[0]!;\n }\n\n return null;\n}\n\n/**\n * Serialize and write a workspace config to `dir`, creating the directory if needed.\n *\n * @param dir - Target directory (created recursively if absent)\n * @param config - Config object to serialize as YAML\n * @param name - Optional workspace name (omit for the default `skaile.yaml`)\n * @returns Absolute path of the written file\n * @docLink packages/core/workspace-config#save-sk-workspace-config\n */\nexport function saveSkWorkspaceConfig(\n dir: string,\n config: SkWorkspaceConfig,\n name?: string,\n): string {\n const resolvedDir = resolve(dir);\n const filename = workspaceConfigFilename(name);\n const filePath = join(resolvedDir, filename);\n\n if (!existsSync(resolvedDir)) {\n mkdirSync(resolvedDir, { recursive: true });\n }\n\n writeFileSync(filePath, encodeSkaileYaml(config));\n return filePath;\n}\n\n/**\n * List all workspace config files present in `dir`, sorted alphabetically by name.\n * Returns an empty array when `dir` does not exist or is unreadable.\n *\n * @param dir - Directory to scan for `skaile.yaml` and `*.skaile.yaml` files\n * @returns Array of parsed config file descriptors\n * @docLink packages/core/workspace-config#list-sk-workspace-configs\n */\nexport function listSkWorkspaceConfigs(dir: string): SkWorkspaceConfigFile[] {\n const resolvedDir = resolve(dir);\n if (!existsSync(resolvedDir)) return [];\n\n const configs: SkWorkspaceConfigFile[] = [];\n try {\n for (const entry of readdirSync(resolvedDir)) {\n if (isWorkspaceConfigFilename(entry)) {\n const wsName = workspaceNameFromFilename(entry);\n const parsed = parseConfigFile(join(resolvedDir, entry), wsName);\n if (parsed) configs.push(parsed);\n }\n }\n } catch {\n /* unreadable dir */\n }\n\n return configs.sort((a, b) => a.name.localeCompare(b.name));\n}\n\n/**\n * Resolve the effective workspace config by stacking configs across three scope levels:\n * user (`~/.skaile/`) < app (`opts.appDir`) < project (`projectDir`).\n *\n * Each level's config is merged with `mergeSkWorkspaceConfigs`, with higher-priority\n * scopes winning for scalars and unions applied for arrays (deny lists, directories, etc.).\n * Returns an empty object `{}` when no config files are found.\n *\n * @param projectDir - Root directory of the current project\n * @param opts - Optional overrides: `name` selects a named workspace (default: `\"default\"`),\n * `appDir` inserts an app-level config between user and project scopes\n * @returns Merged effective `SkWorkspaceConfig`\n * @docLink packages/core/workspace-config#resolve-sk-workspace-config\n */\nexport function resolveSkWorkspaceConfig(\n projectDir: string,\n opts?: { name?: string; appDir?: string },\n): SkWorkspaceConfig {\n const name = opts?.name ?? SK_WORKSPACE_DEFAULT_NAME;\n const configs: SkWorkspaceConfig[] = [];\n\n const userConfig = loadSkWorkspaceConfig(join(homedir(), \".skaile\"), name);\n if (userConfig) configs.push(userConfig.config);\n\n if (opts?.appDir) {\n const appConfig = loadSkWorkspaceConfig(opts.appDir, name);\n if (appConfig) configs.push(appConfig.config);\n }\n\n const projectConfig = loadSkWorkspaceConfig(projectDir, name);\n if (projectConfig) configs.push(projectConfig.config);\n\n if (configs.length > 0) return configs.reduce(mergeSkWorkspaceConfigs);\n\n return {};\n}\n\n/**\n * Walk upward from `startDir` looking for a `skaile.yaml` (or `*.skaile.yaml`).\n * Returns the directory containing the first match, or `undefined` if none found.\n *\n * Stops after 20 levels to avoid scanning all the way to `/`.\n *\n * @param startDir - Directory to start searching from (usually `process.cwd()`)\n * @returns Absolute path to the workspace root, or `undefined`\n * @docLink packages/core/workspace-config#find-workspace-root\n */\nexport function findWorkspaceRoot(startDir: string): string | undefined {\n let dir = resolve(startDir);\n const root = parsePath(dir).root; // filesystem root (e.g. \"/\" or \"C:\\\\\")\n let depth = 0;\n\n while (depth < 20) {\n if (existsSync(join(dir, SKAILE_YAML_DEFAULT))) return dir;\n // Check for named workspace configs (*.skaile.yaml)\n try {\n for (const entry of readdirSync(dir)) {\n if (entry.endsWith(SKAILE_YAML_SUFFIX)) return dir;\n }\n } catch {\n /* unreadable */\n }\n\n if (dir === root) break;\n const parent = dirname(dir);\n if (parent === dir) break;\n dir = parent;\n depth++;\n }\n return undefined;\n}\n\n// ── Merge logic ───────────────────────────────────────────────────────────────\n\n/**\n * Deep-merge two workspace configs according to stacking rules.\n * `overlay` takes priority over `base` for scalar fields.\n * Arrays use concatenation + deduplication; deny lists always union.\n * Mounts and connectors are merged by `id` (overlay entry wins for same id).\n * Hooks are concatenated in order (base first, overlay appended).\n *\n * @param base - Lower-priority config (e.g. user or app scope)\n * @param overlay - Higher-priority config (e.g. project scope)\n * @returns Merged `SkWorkspaceConfig`\n * @docLink packages/core/workspace-config#merge-sk-workspace-configs\n */\nexport function mergeSkWorkspaceConfigs(\n base: SkWorkspaceConfig,\n overlay: SkWorkspaceConfig,\n): SkWorkspaceConfig {\n return {\n name: overlay.name ?? base.name,\n description: overlay.description ?? base.description,\n\n // agent_config: per-profile key, overlay profile wins\n agent_config: {\n ...(base.agent_config ?? {}),\n ...(overlay.agent_config ?? {}),\n },\n\n // startup: overlay wins (project-level only)\n startup: overlay.startup ?? base.startup,\n\n // ai_resources: dedupe by source name — overlay entry wins for same name\n ai_resources: dedupeByKey(\n [...(base.ai_resources ?? []), ...(overlay.ai_resources ?? [])],\n \"name\",\n ),\n\n // mounts: by id — overlay wins\n mounts: mergeById(base.mounts ?? [], overlay.mounts ?? []),\n\n // connectors: by id — overlay wins\n connectors: mergeById(base.connectors ?? [], overlay.connectors ?? []),\n\n // mcp_servers: by id — overlay wins\n mcp_servers: mergeById(base.mcp_servers ?? [], overlay.mcp_servers ?? []),\n\n agent: {\n definition: overlay.agent?.definition ?? base.agent?.definition,\n context: overlay.agent?.context ?? base.agent?.context,\n permissions: {\n ...base.agent?.permissions,\n ...stripUndefined(overlay.agent?.permissions),\n deny_write: dedupe([\n ...(base.agent?.permissions?.deny_write ?? []),\n ...(overlay.agent?.permissions?.deny_write ?? []),\n ]),\n deny_read: dedupe([\n ...(base.agent?.permissions?.deny_read ?? []),\n ...(overlay.agent?.permissions?.deny_read ?? []),\n ]),\n },\n subagents: {\n ...(base.agent?.subagents ?? {}),\n ...(overlay.agent?.subagents ?? {}),\n },\n hooks: {\n pre_flow: [\n ...(base.agent?.hooks?.pre_flow ?? []),\n ...(overlay.agent?.hooks?.pre_flow ?? []),\n ],\n post_flow: [\n ...(base.agent?.hooks?.post_flow ?? []),\n ...(overlay.agent?.hooks?.post_flow ?? []),\n ],\n pre_node: [\n ...(base.agent?.hooks?.pre_node ?? []),\n ...(overlay.agent?.hooks?.pre_node ?? []),\n ],\n post_node: [\n ...(base.agent?.hooks?.post_node ?? []),\n ...(overlay.agent?.hooks?.post_node ?? []),\n ],\n },\n },\n\n workspace: {\n directories: dedupe([\n ...(base.workspace?.directories ?? []),\n ...(overlay.workspace?.directories ?? []),\n ]),\n git: {\n init: overlay.workspace?.git?.init ?? base.workspace?.git?.init,\n ignore: dedupe([\n ...(base.workspace?.git?.ignore ?? []),\n ...(overlay.workspace?.git?.ignore ?? []),\n ]),\n },\n setup: overlay.workspace?.setup ?? base.workspace?.setup,\n container: overlay.workspace?.container ?? base.workspace?.container,\n },\n\n // secrets: overlay wins entirely\n secrets: overlay.secrets ?? base.secrets,\n\n // telemetry: overlay wins entirely (raw pass-through)\n telemetry: overlay.telemetry ?? base.telemetry,\n\n // repositories: always empty in merged output; the schema no longer\n // accepts this key. The internal install pipeline builds its own map\n // from `ai_resources[]` entries.\n repositories: {},\n\n // dependencies: concatenate and dedupe\n dependencies: dedupe([...(base.dependencies ?? []), ...(overlay.dependencies ?? [])]),\n\n // sources: dedupe by name — overlay entry wins for the same name\n sources: dedupeByKey([...(base.sources ?? []), ...(overlay.sources ?? [])], \"name\"),\n };\n}\n\n// ── Diagnostics ───────────────────────────────────────────────────────────────\n\n/** Severity of a {@link Diagnostic} produced by {@link decodeSkaileYaml}. */\nexport type DiagnosticSeverity = \"error\" | \"warning\" | \"info\";\n\n/**\n * A structured note about a decoded `skaile.yaml` — a syntax error, a tolerated\n * legacy/non-canonical shape that was normalized, or an unrecognized enum value.\n * {@link decodeSkaileYaml} never throws; it reports problems here so each caller\n * (platform editor, runner, CLI) decides how loud to be.\n */\nexport interface Diagnostic {\n /** Stable machine code, e.g. `\"legacy_key_camelcase\"` / `\"unknown_driver\"`. */\n code: string;\n severity: DiagnosticSeverity;\n /** Human-readable, actionable message. */\n message: string;\n /** Dotted path into the config the note refers to, when applicable. */\n path?: string;\n}\n\n/** Result of {@link decodeSkaileYaml}: the normalized config plus any notes. */\nexport interface DecodeResult {\n config: SkWorkspaceConfig;\n diagnostics: Diagnostic[];\n}\n\n/**\n * Known runtime drivers — mirrors the keys of `DRIVER_DEFAULTS` (framework.ts).\n * Kept local to avoid a settings/framework ↔ workspace-config import cycle; a\n * drift test asserts parity.\n */\nconst KNOWN_DRIVERS = [\"omp\", \"claude-sdk\", \"codex\"] as const;\n\n/**\n * Known LLM/voice providers — mirrors `ALL_PROVIDERS` (settings.ts). Local for\n * the same cycle reason; a drift test asserts parity.\n */\nconst KNOWN_PROVIDERS = [\n \"anthropic\",\n \"openai\",\n \"google\",\n \"mistral\",\n \"groq\",\n \"openrouter\",\n \"deepseek\",\n \"xai\",\n \"together\",\n \"fireworks\",\n \"deepgram\",\n \"elevenlabs\",\n] as const;\n\nconst KNOWN_ACCESS = [\"read-only\", \"read-write\"] as const;\n\n// ── Raw → canonical normalization ─────────────────────────────────────────────\n\n/** Scalar fields that identify a flat (un-profiled) agent-config block. */\nconst AGENT_PROFILE_FIELDS = [\n \"driver\",\n \"provider\",\n \"model\",\n \"thinking\",\n \"effort\",\n \"skills_dir\",\n \"agents_dir\",\n \"prompts_dir\",\n] as const;\n\n/**\n * Coerce a raw agent-config block into the canonical profile-map shape\n * (`{ default: {...}, … }`).\n *\n * Accepts two authoring shapes:\n * - **Profile map** (canonical): `{ default: { driver, model }, staging: {…} }`\n * - **Flat profile**: `{ driver, model, provider }` — emitted by clients that\n * serialize a runtime config object straight to YAML. Wrapped as the\n * `default` profile so `settingsFromWorkspaceConfig` finds it.\n *\n * `wrappedFlat` reports whether a flat block was wrapped, so the caller can emit\n * a diagnostic. A block is flat when any known profile field is present as a\n * scalar; a profile named e.g. `driver` carries an object value, so the scalar\n * check disambiguates.\n */\nfunction normalizeAgentConfig(raw: Record<string, unknown>): {\n profiles: Record<string, AgentConfigProfile>;\n wrappedFlat: boolean;\n} {\n const looksFlat = AGENT_PROFILE_FIELDS.some((f) => typeof raw[f] === \"string\");\n return looksFlat\n ? { profiles: { default: raw as AgentConfigProfile }, wrappedFlat: true }\n : { profiles: raw as Record<string, AgentConfigProfile>, wrappedFlat: false };\n}\n\n/**\n * Normalize a raw parsed YAML object into the canonical SkWorkspaceConfig shape.\n * Pure structural pass; see {@link decodeSkaileYaml} for the diagnostics-aware\n * entry point. Tolerates backward-compatible fields:\n * - `agent-config` (hyphen) / `agent_config` (underscore) / `agentConfig` (camelCase) → `agent_config`\n * - flat agent-config (`{ driver, model }`) → `{ default: { driver, model } }`\n * - `aiResources` (camelCase) → `ai_resources`\n * - `ai_resources` as object (old {sources, requires}) → AiResourceEntry[]\n * @docLink packages/core/workspace-config#normalize-config\n */\nexport function normalizeConfig(raw: Record<string, unknown>): SkWorkspaceConfig {\n return normalizeConfigInternal(raw).config;\n}\n\n/** Diagnostics-collecting core of {@link normalizeConfig}. */\nfunction normalizeConfigInternal(raw: Record<string, unknown>): DecodeResult {\n const config: SkWorkspaceConfig = {};\n const diagnostics: Diagnostic[] = [];\n\n if (raw.name) config.name = String(raw.name);\n if (raw.description) config.description = String(raw.description);\n\n // agent_config: accept hyphen (canonical), underscore, or camelCase, plus a\n // flat single-profile block. Non-canonical shapes are normalized + flagged.\n let agentConfigRaw: unknown;\n let agentConfigKey: string | undefined;\n if (raw[\"agent-config\"] !== undefined) {\n agentConfigRaw = raw[\"agent-config\"];\n agentConfigKey = \"agent-config\";\n } else if (raw.agent_config !== undefined) {\n agentConfigRaw = raw.agent_config;\n agentConfigKey = \"agent_config\";\n } else if (raw.agentConfig !== undefined) {\n agentConfigRaw = raw.agentConfig;\n agentConfigKey = \"agentConfig\";\n }\n if (agentConfigRaw && typeof agentConfigRaw === \"object\" && !Array.isArray(agentConfigRaw)) {\n if (agentConfigKey === \"agentConfig\") {\n diagnostics.push({\n code: \"legacy_key_camelcase\",\n severity: \"warning\",\n message: 'Non-canonical key \"agentConfig\" — use \"agent-config\".',\n path: \"agentConfig\",\n });\n }\n const { profiles, wrappedFlat } = normalizeAgentConfig(\n agentConfigRaw as Record<string, unknown>,\n );\n if (wrappedFlat) {\n diagnostics.push({\n code: \"legacy_agent_config_flat\",\n severity: \"warning\",\n message:\n 'Flat agent-config block wrapped as the \"default\" profile — nest fields under \"default:\".',\n path: agentConfigKey,\n });\n }\n config.agent_config = profiles;\n }\n\n if (Array.isArray(raw.startup)) {\n config.startup = raw.startup as StartupDirective[];\n }\n\n // ai_resources: array (canonical) or old {sources, requires} object; accept\n // the camelCase `aiResources` alias.\n let aiResRaw: unknown;\n let aiResKey: string | undefined;\n if (raw.ai_resources !== undefined) {\n aiResRaw = raw.ai_resources;\n aiResKey = \"ai_resources\";\n } else if (raw.aiResources !== undefined) {\n aiResRaw = raw.aiResources;\n aiResKey = \"aiResources\";\n }\n if (aiResKey === \"aiResources\") {\n diagnostics.push({\n code: \"legacy_key_camelcase\",\n severity: \"warning\",\n message: 'Non-canonical key \"aiResources\" — use \"ai_resources\".',\n path: \"aiResources\",\n });\n }\n if (Array.isArray(aiResRaw)) {\n config.ai_resources = aiResRaw as AiResourceEntry[];\n } else if (aiResRaw && typeof aiResRaw === \"object\") {\n diagnostics.push({\n code: \"legacy_ai_resources_object\",\n severity: \"warning\",\n message:\n \"Legacy ai_resources object form ({sources, requires}) — use an array of {name, path, dependencies}.\",\n path: aiResKey,\n });\n const old = aiResRaw as Record<string, unknown>;\n const sources = Array.isArray(old.sources) ? (old.sources as Record<string, unknown>[]) : [];\n const requires = Array.isArray(old.requires) ? (old.requires as string[]).filter(Boolean) : [];\n const autoDeploy = Boolean(old.auto_deploy ?? false);\n\n config.ai_resources = sources.map((s, i) => {\n const entry: AiResourceEntry = {\n name: String(s.name ?? \"\"),\n path: String(s.path ?? s.url ?? \"\"),\n };\n if (s.branch) entry.branch = String(s.branch);\n if (autoDeploy) entry.auto_deploy = true;\n // Attach global requires to first source\n if (i === 0 && requires.length > 0) entry.dependencies = requires;\n return entry;\n });\n }\n\n // Structural validation deferred — these sections are accepted as raw\n // arrays/objects and cast; the runtime tolerates unexpected shapes.\n if (Array.isArray(raw.mounts)) {\n config.mounts = raw.mounts as MountDeclaration[];\n }\n // connectors: no data_resources fallback — clean break\n if (Array.isArray(raw.connectors)) {\n config.connectors = raw.connectors as ConnectorDeclaration[];\n }\n if (Array.isArray(raw.mcp_servers)) {\n config.mcp_servers = raw.mcp_servers as McpServerDeclaration[];\n }\n if (raw.agent) config.agent = raw.agent as AgentConfig;\n if (raw.workspace) config.workspace = raw.workspace as WorkspaceLayoutConfig;\n if (raw.secrets && typeof raw.secrets === \"object\") {\n config.secrets = raw.secrets as SecretsConfig;\n }\n if (raw.compaction && typeof raw.compaction === \"object\" && !Array.isArray(raw.compaction)) {\n config.compaction = raw.compaction as CompactionConfig;\n }\n if (raw.patches && typeof raw.patches === \"object\" && !Array.isArray(raw.patches)) {\n config.patches = raw.patches as Record<string, string>;\n }\n\n if (Array.isArray(raw.dependencies)) {\n config.dependencies = raw.dependencies.filter((d): d is string => typeof d === \"string\");\n }\n\n if (Array.isArray(raw.sources)) {\n const entries: SourceEntry[] = [];\n for (const item of raw.sources) {\n if (!item || typeof item !== \"object\") continue;\n const s = item as Record<string, unknown>;\n const name = typeof s.name === \"string\" ? s.name : \"\";\n const url = typeof s.url === \"string\" ? s.url : \"\";\n if (!name || !url) continue;\n const entry: SourceEntry = { name, url };\n if (typeof s.branch === \"string\" && s.branch.length > 0) entry.branch = s.branch;\n entries.push(entry);\n }\n if (entries.length > 0) config.sources = entries;\n }\n\n // telemetry: pass through raw — parsed by @skaile/workspaces/telemetry\n if (raw.telemetry && typeof raw.telemetry === \"object\" && !Array.isArray(raw.telemetry)) {\n config.telemetry = raw.telemetry as Record<string, unknown>;\n }\n\n return { config, diagnostics };\n}\n\n// ── Codec (decode / encode) ────────────────────────────────────────────────────\n\n/**\n * Decode `skaile.yaml` text into a normalized {@link SkWorkspaceConfig} plus\n * {@link Diagnostic}s. Total — never throws: a YAML syntax error or a non-object\n * root is reported as an `error`-severity diagnostic with an empty config.\n * Legacy/non-canonical shapes (camelCase keys, flat agent-config, the old\n * ai_resources object) are normalized and reported as `warning`s; unrecognized\n * driver/provider/access values are reported as `warning`s too.\n *\n * Pair with {@link encodeSkaileYaml} for round-tripping. The round-trip is\n * canonical-lossless on the typed model (`decode(encode(config)).config` deep-\n * equals `config`) but does not preserve comments or key order — use\n * `WorkspaceYamlEditor` for comment-preserving in-place edits.\n * @docLink packages/core/workspace-config#decode-skaile-yaml\n */\nexport function decodeSkaileYaml(text: string): DecodeResult {\n let parsed: unknown;\n try {\n parsed = parse(text) ?? {};\n } catch (err) {\n return {\n config: {},\n diagnostics: [\n {\n code: \"yaml_syntax\",\n severity: \"error\",\n message: `Invalid YAML: ${err instanceof Error ? err.message : String(err)}`,\n },\n ],\n };\n }\n if (typeof parsed !== \"object\" || parsed === null || Array.isArray(parsed)) {\n return {\n config: {},\n diagnostics: [\n {\n code: \"non_object_root\",\n severity: \"error\",\n message: \"skaile.yaml must be a mapping at the top level.\",\n },\n ],\n };\n }\n const result = normalizeConfigInternal(parsed as Record<string, unknown>);\n validateConfigValues(result.config, result.diagnostics);\n return result;\n}\n\n/**\n * Encode a {@link SkWorkspaceConfig} to canonical `skaile.yaml` text:\n * deterministic key order, the hyphenated `agent-config` key, only defined\n * fields. This is the single sanctioned writer — clients should build a typed\n * config and encode it here rather than hand-serializing YAML.\n * @docLink packages/core/workspace-config#encode-skaile-yaml\n */\nexport function encodeSkaileYaml(config: SkWorkspaceConfig): string {\n return stringify(toCanonicalObject(config), { lineWidth: 120 });\n}\n\n/** Append `warning` diagnostics for unrecognized driver/provider/access values. */\nfunction validateConfigValues(config: SkWorkspaceConfig, diagnostics: Diagnostic[]): void {\n for (const [profile, p] of Object.entries(config.agent_config ?? {})) {\n if (p?.driver && !(KNOWN_DRIVERS as readonly string[]).includes(p.driver)) {\n diagnostics.push({\n code: \"unknown_driver\",\n severity: \"warning\",\n message: `Unknown driver \"${p.driver}\" — expected one of: ${KNOWN_DRIVERS.join(\", \")}.`,\n path: `agent-config.${profile}.driver`,\n });\n }\n if (p?.provider && !(KNOWN_PROVIDERS as readonly string[]).includes(p.provider)) {\n diagnostics.push({\n code: \"unknown_provider\",\n severity: \"warning\",\n message: `Unknown provider \"${p.provider}\" — expected one of: ${KNOWN_PROVIDERS.join(\", \")}.`,\n path: `agent-config.${profile}.provider`,\n });\n }\n }\n const checkAccess = (access: string | undefined, path: string) => {\n if (access && !(KNOWN_ACCESS as readonly string[]).includes(access)) {\n diagnostics.push({\n code: \"unknown_access\",\n severity: \"warning\",\n message: `Unknown access \"${access}\" — expected \"read-only\" or \"read-write\".`,\n path,\n });\n }\n };\n for (const c of config.connectors ?? []) checkAccess(c.access, `connectors.${c.id}.access`);\n for (const m of config.mounts ?? []) checkAccess(m.access, `mounts.${m.id}.access`);\n}\n\n/**\n * Canonical key order for encode. `agent_config` is emitted under the hyphenated\n * `agent-config` key (see {@link CONFIG_KEY_TO_YAML}); any field not listed here\n * is appended afterward so forward-compat keys survive a round-trip.\n */\nconst CANONICAL_KEY_ORDER: (keyof SkWorkspaceConfig)[] = [\n \"name\",\n \"description\",\n \"agent_config\",\n \"dependencies\",\n \"sources\",\n \"startup\",\n \"ai_resources\",\n \"connectors\",\n \"mcp_servers\",\n \"mounts\",\n \"agent\",\n \"workspace\",\n \"secrets\",\n \"telemetry\",\n \"compaction\",\n \"patches\",\n \"repositories\",\n];\n\n/** Internal field name → canonical YAML key, where they differ. */\nconst CONFIG_KEY_TO_YAML: Partial<Record<keyof SkWorkspaceConfig, string>> = {\n agent_config: \"agent-config\",\n};\n\nfunction toCanonicalObject(config: SkWorkspaceConfig): Record<string, unknown> {\n const out: Record<string, unknown> = {};\n const emit = (key: keyof SkWorkspaceConfig) => {\n const value = config[key];\n if (value === undefined) return;\n out[CONFIG_KEY_TO_YAML[key] ?? key] = value;\n };\n for (const key of CANONICAL_KEY_ORDER) emit(key);\n // Preserve any field not in the canonical order (forward-compat).\n for (const key of Object.keys(config) as (keyof SkWorkspaceConfig)[]) {\n if (CANONICAL_KEY_ORDER.includes(key)) continue;\n emit(key);\n }\n return out;\n}\n\n// ── Helpers ───────────────────────────────────────────────────────────────────\n\nfunction parseConfigFile(filePath: string, name: string): SkWorkspaceConfigFile | null {\n let raw: string;\n try {\n raw = readFileSync(filePath, \"utf-8\");\n } catch {\n return null;\n }\n const { config, diagnostics } = decodeSkaileYaml(raw);\n // Preserve the legacy contract: an unparseable file reads as \"no config\".\n if (diagnostics.some((d) => d.code === \"yaml_syntax\")) return null;\n return { path: filePath, name, config, diagnostics };\n}\n\nfunction dedupe(arr: string[]): string[] {\n return [...new Set(arr)];\n}\n\nfunction dedupeByKey<T extends object>(arr: T[], key: string): T[] {\n const seen = new Set<string>();\n const result: T[] = [];\n for (let i = arr.length - 1; i >= 0; i--) {\n const val = String((arr[i] as any)[key] ?? \"\");\n if (!seen.has(val)) {\n seen.add(val);\n result.unshift(arr[i]!);\n }\n }\n return result;\n}\n\nfunction mergeById<T extends { id: string }>(base: T[], overlay: T[]): T[] {\n const map = new Map<string, T>();\n for (const r of base) map.set(r.id, r);\n for (const r of overlay) map.set(r.id, r);\n return [...map.values()];\n}\n\nfunction stripUndefined<T extends object>(obj?: T): Partial<T> {\n if (!obj) return {};\n const result: Record<string, unknown> = {};\n for (const [k, v] of Object.entries(obj)) {\n if (v !== undefined) result[k] = v;\n }\n return result as Partial<T>;\n}\n\n// ── MCP server loader ─────────────────────────────────────────────────────────\n\n/**\n * Build a `McpServerDeclaration` from a resolved `CatalogEntry` with `kind: \"mcp-server\"`.\n * Maps `metadata` fields (transport, command, args, env, url, headers) to declaration fields.\n * Returns `null` when the entry has no usable metadata (no command and no url).\n */\nfunction mcpDeclFromCatalogEntry(entry: CatalogEntry): McpServerDeclaration | null {\n const m = entry.metadata;\n if (!m) return null;\n\n const decl: McpServerDeclaration = { id: entry.name };\n if (m.transport) decl.transport = String(m.transport) as \"stdio\" | \"sse\" | \"http\";\n if (m.command) decl.command = String(m.command);\n if (Array.isArray(m.args)) decl.args = m.args.map(String);\n if (m.env && typeof m.env === \"object\") decl.env = m.env as Record<string, string>;\n if (m.url) decl.url = String(m.url);\n if (m.headers && typeof m.headers === \"object\") {\n decl.headers = m.headers as Record<string, string>;\n }\n if (entry.description) decl.description = entry.description;\n if (m.recipe && typeof m.recipe === \"object\" && !Array.isArray(m.recipe)) {\n const r = m.recipe as Record<string, unknown>;\n if (typeof r.attr === \"string\") {\n try {\n validateAssetRecipeAttr(r.attr);\n decl.recipe = { attr: r.attr };\n } catch (err) {\n // Invalid attr — skip the recipe field entirely (treat as if recipe was absent).\n // The MCP server may still be usable via a command/url without recipe substitution.\n console.warn(\n `[workspace-config] mcpDeclFromCatalogEntry: invalid recipe.attr for entry \"${entry.name}\": ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n }\n }\n\n // Must have at least a command (stdio) or url (sse/http) to be useful\n if (!decl.command && !decl.url) return null;\n return decl;\n}\n\n/**\n * Merge two `McpServerDeclaration` objects field-by-field.\n * `overlay` values win for every non-undefined field; `base` provides defaults.\n */\nfunction mergeMcpDeclarations(\n base: McpServerDeclaration,\n overlay: McpServerDeclaration,\n): McpServerDeclaration {\n return {\n id: overlay.id,\n transport: overlay.transport ?? base.transport,\n command: overlay.command ?? base.command,\n args: overlay.args ?? base.args,\n env: overlay.env ? (base.env ? { ...base.env, ...overlay.env } : overlay.env) : base.env,\n url: overlay.url ?? base.url,\n headers: overlay.headers\n ? base.headers\n ? { ...base.headers, ...overlay.headers }\n : overlay.headers\n : base.headers,\n description: overlay.description ?? base.description,\n tags: overlay.tags ?? base.tags,\n recipe: overlay.recipe ?? base.recipe,\n };\n}\n\n/**\n * Scan `<projectDir>/.skaile/assets/mcp-server/<name>/MCP.md` for MCP servers\n * that the platform materializer has written to disk for a subscribed asset.\n *\n * For each immediate subdirectory containing an `MCP.md`, the manifest is parsed\n * via {@link fromMcpServerMd} and mapped to a declaration via\n * {@link mcpDeclFromCatalogEntry}. A sibling `.instance.json` (written by the\n * platform materializer) is folded into `decl.env`.\n *\n * **Env-fold precedence (lowest → highest):**\n * 1. `MCP.md` `env` defaults\n * 2. string-valued entries of `.instance.json` `config` (non-string config\n * values — objects/arrays/numbers — are skipped so env never contains\n * `[object Object]`)\n * 3. `.instance.json` `resolvedSecrets` (always folded, all keys)\n *\n * Folded secret *values* are never logged. A malformed `MCP.md` for one asset\n * is caught per-directory and skipped (warned without secret values) so one bad\n * asset never aborts the whole scan.\n *\n * @param projectDir - Workspace root containing `.skaile/assets/mcp-server/`\n * @returns Declarations for every materialized MCP asset (empty if the dir is absent)\n */\nfunction loadMaterializedMcpDeclarations(projectDir: string): McpServerDeclaration[] {\n const dir = join(projectDir, \".skaile/assets/mcp-server\");\n if (!existsSync(dir)) return [];\n\n const result: McpServerDeclaration[] = [];\n\n let subdirs: string[];\n try {\n subdirs = readdirSync(dir, { withFileTypes: true })\n .filter((e) => e.isDirectory())\n .map((e) => e.name);\n } catch {\n return [];\n }\n\n for (const name of subdirs) {\n const subDir = join(dir, name);\n const mdPath = join(subDir, \"MCP.md\");\n if (!existsSync(mdPath)) continue;\n\n try {\n const entry = fromMcpServerMd(mdPath, name);\n const decl = mcpDeclFromCatalogEntry(entry);\n if (!decl) continue;\n\n decl.id = entry.name || name;\n\n const instancePath = join(subDir, \".instance.json\");\n if (existsSync(instancePath)) {\n // A malformed transient .instance.json must not nuke a valid MCP server:\n // catch parse errors here so the decl survives with its MCP.md env.\n try {\n const instance = JSON.parse(readFileSync(instancePath, \"utf8\")) as {\n config?: Record<string, unknown>;\n resolvedSecrets?: Record<string, unknown>;\n };\n\n const env: Record<string, string> = { ...(decl.env ?? {}) };\n\n // string-config < resolvedSecrets (folded after, so secrets win)\n if (instance.config && typeof instance.config === \"object\") {\n for (const [k, v] of Object.entries(instance.config)) {\n if (typeof v === \"string\") env[k] = v;\n }\n }\n if (instance.resolvedSecrets && typeof instance.resolvedSecrets === \"object\") {\n for (const [k, v] of Object.entries(instance.resolvedSecrets)) {\n // Guard like the config fold above — a non-string secret (serializer\n // bug) must not land in subprocess env as \"[object Object]\"/\"null\".\n if (typeof v === \"string\") env[k] = v;\n }\n }\n\n if (Object.keys(env).length > 0) decl.env = env;\n } catch (err) {\n // Never include secret values in the warning — only the failing path + message.\n console.warn(\n `[workspace-config] loadMaterializedMcpDeclarations: ignoring malformed \".instance.json\" for \"${name}\": ${\n err instanceof Error ? err.message : String(err)\n }`,\n );\n }\n }\n\n result.push(decl);\n } catch (err) {\n // Never include secret values in the warning — only the failing path + message.\n console.warn(\n `[workspace-config] loadMaterializedMcpDeclarations: failed to load \"${mdPath}\": ${\n err instanceof Error ? err.message : String(err)\n }`,\n );\n }\n }\n\n return result;\n}\n\n/**\n * Load MCP server declarations by merging three sources:\n *\n * 1. **Catalog defaults** — `mcp-server:*` refs in the `dependencies` array\n * (or legacy `ai_resources[].dependencies`). Each ref is resolved from the\n * repository catalog; the `MCP.md` frontmatter provides default config\n * (transport, command, args, env, url, headers).\n *\n * 2. **Materialized assets** — MCP servers the platform materializer has written\n * to `<projectDir>/.skaile/assets/mcp-server/<name>/MCP.md` for subscribed\n * assets (see {@link loadMaterializedMcpDeclarations}). This scan ALWAYS runs,\n * so a subscribed asset on disk with no `dependencies:` and no `mcp_servers:`\n * entry is still picked up.\n *\n * 3. **Explicit declarations** — entries in the `mcp_servers` section of\n * `skaile.yaml`. These override the other two sources field-by-field when the\n * `id` matches.\n *\n * **Precedence (lowest → highest):** catalog-dep refs < materialized assets <\n * explicit `mcp_servers:`. A catalog-dep and a materialized asset with the same\n * id merge (materialized overlay onto catalog base) rather than double-counting.\n *\n * @param projectDir - Workspace root where `skaile.yaml` lives\n * @returns Unified array of `McpServerDeclaration` objects ready for the runner\n * @docLink packages/core/workspace-config#load-mcp-server-declarations\n */\nexport function loadMcpServerDeclarations(projectDir: string): McpServerDeclaration[] {\n const config = resolveSkWorkspaceConfig(projectDir);\n const explicit = config.mcp_servers ?? [];\n\n // Materialized scan always runs — the primary use case is a subscribed asset\n // on disk with no dependencies: and no mcp_servers: entry.\n const materialized = loadMaterializedMcpDeclarations(projectDir);\n\n // Collect all mcp-server refs from both dependency formats\n const mcpRefStrings: string[] = [];\n\n // New format: top-level dependencies\n for (const dep of config.dependencies ?? []) {\n const ref = parseAssetRef(dep);\n if (ref.kind === \"mcp-server\") mcpRefStrings.push(dep);\n }\n\n // Legacy format: ai_resources[].dependencies\n for (const res of config.ai_resources ?? []) {\n for (const dep of res.dependencies ?? []) {\n const ref = parseAssetRef(dep);\n if (ref.kind === \"mcp-server\") mcpRefStrings.push(dep);\n }\n }\n\n // Resolve catalog entries\n const repositories = config.repositories ?? {};\n\n // Also build repositories from legacy ai_resources for backward compat\n const allRepos = { ...repositories };\n for (const res of config.ai_resources ?? []) {\n if (res.name && res.path && !(res.name in allRepos)) {\n allRepos[res.name] = {\n url: res.path.startsWith(\"/\") ? undefined : res.path,\n path: res.path.startsWith(\"/\") ? res.path : undefined,\n branch: res.branch,\n };\n }\n }\n\n const reposDir = getGlobalCacheDir();\n // byId tracks the current merged decl per id so later, higher-precedence\n // sources overlay onto it instead of double-counting.\n const byId = new Map<string, McpServerDeclaration>();\n const order: string[] = [];\n\n const upsert = (decl: McpServerDeclaration) => {\n const existing = byId.get(decl.id);\n if (existing) {\n byId.set(decl.id, mergeMcpDeclarations(existing, decl));\n } else {\n byId.set(decl.id, decl);\n order.push(decl.id);\n }\n };\n\n // Source 1 (lowest): catalog-dep refs\n const seen = new Set<string>();\n for (const refStr of mcpRefStrings) {\n const ref = parseAssetRef(refStr);\n if (seen.has(ref.name)) continue;\n seen.add(ref.name);\n\n const entry = resolveAsset(ref, allRepos, reposDir, { projectDir });\n if (!entry) continue;\n\n const catalogDecl = mcpDeclFromCatalogEntry(entry);\n if (!catalogDecl) continue;\n\n upsert(catalogDecl);\n }\n\n // Source 2: materialized assets — overlay onto matching catalog base.\n for (const decl of materialized) {\n upsert(decl);\n }\n\n // Source 3 (highest): explicit mcp_servers: — overlay field-by-field.\n for (const decl of explicit) {\n upsert(decl);\n }\n\n return order.map((id) => byId.get(id) as McpServerDeclaration);\n}\n\n// ── Agent definition resolver ──────────────────────────────────────────────────\n\n/**\n * Walk upward from `from` (max 8 levels) until a directory containing\n * `ai-assets/` is found. Returns the absolute path to that `ai-assets/`\n * directory, or undefined if none found.\n */\nfunction findAiAssetsDir(from: string): string | undefined {\n let dir = resolve(from);\n for (let i = 0; i < 8; i++) {\n const candidate = join(dir, \"ai-assets\");\n if (existsSync(candidate)) return candidate;\n const resolved = resolve(dir, \"..\");\n if (resolved === dir) break;\n dir = resolved;\n }\n return undefined;\n}\n\n/**\n * Resolve the `agent.definition` field from `skaile.yaml` in `projectDir`\n * to an absolute filesystem path.\n *\n * Resolution rules:\n * - Absent or empty → undefined\n * - Relative/absolute local path → resolve(projectDir, definition)\n * - `ai-assets://<rest>` → walk up for ai-assets/, join with <rest>\n * - `agent:<name>` catalog refs → resolved via repository scanning\n *\n * Used by the runner to determine agentDir without requiring --agent-dir.\n * @docLink packages/core/workspace-config#resolve-agent-dir\n */\nexport function resolveAgentDir(projectDir: string): string | undefined {\n const config = resolveSkWorkspaceConfig(projectDir);\n const definition = config.agent?.definition;\n if (!definition) return undefined;\n\n // ai-assets:// URI\n if (definition.startsWith(\"ai-assets://\")) {\n const relPath = definition.slice(\"ai-assets://\".length);\n const aiAssetsDir = findAiAssetsDir(projectDir);\n if (!aiAssetsDir) return undefined;\n return join(aiAssetsDir, relPath);\n }\n\n // Catalog reference — resolve via repository scanning\n if (definition.startsWith(\"agent:\")) {\n const ref = parseAssetRef(definition);\n const repositories = config.repositories ?? {};\n const reposDir = getGlobalCacheDir();\n const entry = resolveAsset(ref, repositories, reposDir, { projectDir });\n if (!entry) return undefined;\n return dirname(entry.source);\n }\n\n // Local path (relative or absolute)\n return resolve(projectDir, definition);\n}\n"]}
|