@skaile/workspaces 0.12.2 → 0.14.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.
Files changed (106) hide show
  1. package/CHANGELOG.md +47 -0
  2. package/dist/asset-manager/index.js +4 -6
  3. package/dist/asset-manager/installer.js +1 -2
  4. package/dist/asset-manager/src/index.d.ts +1 -2
  5. package/dist/asset-manager/src/index.d.ts.map +1 -1
  6. package/dist/asset-manager/src/{scaffold/layers/agents.d.ts → install-agent.d.ts} +11 -33
  7. package/dist/asset-manager/src/install-agent.d.ts.map +1 -0
  8. package/dist/base-assets/connectors/deploy.js +2 -2
  9. package/dist/base-assets/connectors/devserver.js +2 -2
  10. package/dist/base-assets/connectors/flow/adapter.js +2 -2
  11. package/dist/base-assets/connectors/flow/run-flow.js +3 -3
  12. package/dist/base-assets/connectors/flow.js +2 -2
  13. package/dist/base-assets/connectors/git.js +2 -2
  14. package/dist/base-assets/connectors/gmail.js +2 -2
  15. package/dist/base-assets/connectors/googledrive/driver.d.ts +47 -0
  16. package/dist/base-assets/connectors/googledrive/driver.d.ts.map +1 -0
  17. package/dist/base-assets/connectors/googledrive.js +20 -0
  18. package/dist/base-assets/connectors/googledrive.js.map +1 -0
  19. package/dist/base-assets/connectors/local.js +2 -2
  20. package/dist/base-assets/connectors/mattermost.js +2 -2
  21. package/dist/base-assets/connectors/memory.js +2 -2
  22. package/dist/base-assets/connectors/minio.js +2 -2
  23. package/dist/base-assets/connectors/postgres.js +2 -2
  24. package/dist/base-assets/connectors/redis.js +2 -2
  25. package/dist/base-assets/connectors/s3.js +2 -2
  26. package/dist/base-assets/connectors/sharepoint/driver.d.ts.map +1 -1
  27. package/dist/base-assets/connectors/sharepoint.js +2 -2
  28. package/dist/base-assets/connectors/sqlite.js +2 -2
  29. package/dist/base-assets/connectors/static-server.js +2 -2
  30. package/dist/base-assets/connectors/tunnel.js +2 -2
  31. package/dist/base-assets/connectors/webdav/driver.d.ts.map +1 -1
  32. package/dist/base-assets/connectors/webdav.js +2 -2
  33. package/dist/base-assets/connectors/xstate-store.js +2 -2
  34. package/dist/base-assets/connectors/xstate.js +2 -2
  35. package/dist/base-assets/connectors/yjs.js +2 -2
  36. package/dist/{chunk-M2NLRGIX.js → chunk-4GEVGRWB.js} +159 -6
  37. package/dist/chunk-4GEVGRWB.js.map +1 -0
  38. package/dist/{chunk-EARKGKKB.js → chunk-7R4WLTZW.js} +5 -5
  39. package/dist/{chunk-EARKGKKB.js.map → chunk-7R4WLTZW.js.map} +1 -1
  40. package/dist/{chunk-UTKGPNLV.js → chunk-DN5476SV.js} +5 -5
  41. package/dist/{chunk-UTKGPNLV.js.map → chunk-DN5476SV.js.map} +1 -1
  42. package/dist/{chunk-Z5PO7ZVP.js → chunk-G7O7WDXX.js} +2 -2
  43. package/dist/{chunk-Z5PO7ZVP.js.map → chunk-G7O7WDXX.js.map} +1 -1
  44. package/dist/{chunk-EAJKY27M.js → chunk-HSOEX3TA.js} +250 -92
  45. package/dist/chunk-HSOEX3TA.js.map +1 -0
  46. package/dist/{chunk-DDVKNST3.js → chunk-OIFGKFZY.js} +3 -3
  47. package/dist/{chunk-DDVKNST3.js.map → chunk-OIFGKFZY.js.map} +1 -1
  48. package/dist/chunk-QAVZOJCV.js +72 -0
  49. package/dist/chunk-QAVZOJCV.js.map +1 -0
  50. package/dist/cli/index.js +93 -33
  51. package/dist/cli/index.js.map +1 -1
  52. package/dist/connectors/index.js +2 -2
  53. package/dist/connectors/rclone-config.js +1 -1
  54. package/dist/connectors/src/connector-registry.d.ts.map +1 -1
  55. package/dist/connectors/src/fleet-utils.d.ts +35 -0
  56. package/dist/connectors/src/fleet-utils.d.ts.map +1 -0
  57. package/dist/connectors/src/index.d.ts +2 -1
  58. package/dist/connectors/src/index.d.ts.map +1 -1
  59. package/dist/connectors/src/rclone-config/googledrive.d.ts +59 -0
  60. package/dist/connectors/src/rclone-config/googledrive.d.ts.map +1 -0
  61. package/dist/connectors/src/rclone-config/index.d.ts +1 -0
  62. package/dist/connectors/src/rclone-config/index.d.ts.map +1 -1
  63. package/dist/connectors/src/rclone-config/onedrive.d.ts +1 -0
  64. package/dist/connectors/src/rclone-config/onedrive.d.ts.map +1 -1
  65. package/dist/connectors/src/rclone-config/sanitize.d.ts +9 -0
  66. package/dist/connectors/src/rclone-config/sanitize.d.ts.map +1 -0
  67. package/dist/connectors/src/rclone-config/webdav.d.ts +1 -0
  68. package/dist/connectors/src/rclone-config/webdav.d.ts.map +1 -1
  69. package/dist/runner/index.js +5 -5
  70. package/dist/sdk/asset-manager.js +4 -6
  71. package/dist/sdk/index.js +5 -5
  72. package/dist/sdk/runner.js +5 -5
  73. package/dist/tui/index.js +5 -5
  74. package/dist/workspace-plugin/index.js +1 -1
  75. package/package.json +7 -7
  76. package/dist/asset-manager/scaffold.js +0 -18
  77. package/dist/asset-manager/scaffold.js.map +0 -1
  78. package/dist/asset-manager/src/scaffold/index.d.ts +0 -19
  79. package/dist/asset-manager/src/scaffold/index.d.ts.map +0 -1
  80. package/dist/asset-manager/src/scaffold/layers/agents.d.ts.map +0 -1
  81. package/dist/asset-manager/src/scaffold/layers/base.d.ts +0 -17
  82. package/dist/asset-manager/src/scaffold/layers/base.d.ts.map +0 -1
  83. package/dist/asset-manager/src/scaffold/layers/connectors.d.ts +0 -18
  84. package/dist/asset-manager/src/scaffold/layers/connectors.d.ts.map +0 -1
  85. package/dist/asset-manager/src/scaffold/layers/container.d.ts +0 -16
  86. package/dist/asset-manager/src/scaffold/layers/container.d.ts.map +0 -1
  87. package/dist/asset-manager/src/scaffold/layers/driver-target.d.ts +0 -17
  88. package/dist/asset-manager/src/scaffold/layers/driver-target.d.ts.map +0 -1
  89. package/dist/asset-manager/src/scaffold/layers/hooks.d.ts +0 -22
  90. package/dist/asset-manager/src/scaffold/layers/hooks.d.ts.map +0 -1
  91. package/dist/asset-manager/src/scaffold/layers/skills.d.ts +0 -31
  92. package/dist/asset-manager/src/scaffold/layers/skills.d.ts.map +0 -1
  93. package/dist/asset-manager/src/scaffold/layers/template.d.ts +0 -16
  94. package/dist/asset-manager/src/scaffold/layers/template.d.ts.map +0 -1
  95. package/dist/asset-manager/src/scaffold/scaffolder.d.ts +0 -77
  96. package/dist/asset-manager/src/scaffold/scaffolder.d.ts.map +0 -1
  97. package/dist/asset-manager/src/scaffold/types.d.ts +0 -241
  98. package/dist/asset-manager/src/scaffold/types.d.ts.map +0 -1
  99. package/dist/chunk-DIKFRNCS.js +0 -195
  100. package/dist/chunk-DIKFRNCS.js.map +0 -1
  101. package/dist/chunk-EAJKY27M.js.map +0 -1
  102. package/dist/chunk-GCRKAFH7.js +0 -40
  103. package/dist/chunk-GCRKAFH7.js.map +0 -1
  104. package/dist/chunk-M2NLRGIX.js.map +0 -1
  105. package/dist/chunk-YHXBQLXX.js +0 -546
  106. package/dist/chunk-YHXBQLXX.js.map +0 -1
@@ -1,40 +0,0 @@
1
- // connectors/src/rclone-config/onedrive.ts
2
- function renderOneDriveConfig(opts) {
3
- const tokenObj = {
4
- access_token: opts.accessToken,
5
- token_type: "Bearer"
6
- };
7
- if (opts.refreshToken) tokenObj.refresh_token = opts.refreshToken;
8
- if (opts.expiresAtMs != null) {
9
- tokenObj.expiry = new Date(opts.expiresAtMs).toISOString();
10
- }
11
- const lines = [];
12
- lines.push(`[${opts.remoteName}]`);
13
- lines.push("type = onedrive");
14
- lines.push(`drive_id = ${opts.driveId}`);
15
- lines.push(`drive_type = ${opts.driveType ?? "business"}`);
16
- lines.push(`token = ${JSON.stringify(tokenObj)}`);
17
- if (opts.clientId) lines.push(`client_id = ${opts.clientId}`);
18
- if (opts.clientSecret) lines.push(`client_secret = ${opts.clientSecret}`);
19
- if (opts.tenantId) lines.push(`tenant = ${opts.tenantId}`);
20
- lines.push("");
21
- return lines.join("\n");
22
- }
23
-
24
- // connectors/src/rclone-config/webdav.ts
25
- function renderWebDAVConfig(opts) {
26
- const lines = [];
27
- lines.push(`[${opts.remoteName}]`);
28
- lines.push("type = webdav");
29
- lines.push(`url = ${opts.url}`);
30
- lines.push(`vendor = ${opts.vendor}`);
31
- if (opts.username) lines.push(`user = ${opts.username}`);
32
- if (opts.obscuredPassword) lines.push(`pass = ${opts.obscuredPassword}`);
33
- if (opts.bearerToken) lines.push(`bearer_token = ${opts.bearerToken}`);
34
- lines.push("");
35
- return lines.join("\n");
36
- }
37
-
38
- export { renderOneDriveConfig, renderWebDAVConfig };
39
- //# sourceMappingURL=chunk-GCRKAFH7.js.map
40
- //# sourceMappingURL=chunk-GCRKAFH7.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../connectors/src/rclone-config/onedrive.ts","../connectors/src/rclone-config/webdav.ts"],"names":[],"mappings":";AA+CO,SAAS,qBAAqB,IAAA,EAA2C;AAC9E,EAAA,MAAM,QAAA,GAAmC;AAAA,IACvC,cAAc,IAAA,CAAK,WAAA;AAAA,IACnB,UAAA,EAAY;AAAA,GACd;AACA,EAAA,IAAI,IAAA,CAAK,YAAA,EAAc,QAAA,CAAS,aAAA,GAAgB,IAAA,CAAK,YAAA;AACrD,EAAA,IAAI,IAAA,CAAK,eAAe,IAAA,EAAM;AAC5B,IAAA,QAAA,CAAS,SAAS,IAAI,IAAA,CAAK,IAAA,CAAK,WAAW,EAAE,WAAA,EAAY;AAAA,EAC3D;AAEA,EAAA,MAAM,QAAkB,EAAC;AACzB,EAAA,KAAA,CAAM,IAAA,CAAK,CAAA,CAAA,EAAI,IAAA,CAAK,UAAU,CAAA,CAAA,CAAG,CAAA;AACjC,EAAA,KAAA,CAAM,KAAK,iBAAiB,CAAA;AAC5B,EAAA,KAAA,CAAM,IAAA,CAAK,CAAA,WAAA,EAAc,IAAA,CAAK,OAAO,CAAA,CAAE,CAAA;AACvC,EAAA,KAAA,CAAM,IAAA,CAAK,CAAA,aAAA,EAAgB,IAAA,CAAK,SAAA,IAAa,UAAU,CAAA,CAAE,CAAA;AACzD,EAAA,KAAA,CAAM,KAAK,CAAA,QAAA,EAAW,IAAA,CAAK,SAAA,CAAU,QAAQ,CAAC,CAAA,CAAE,CAAA;AAChD,EAAA,IAAI,KAAK,QAAA,EAAU,KAAA,CAAM,KAAK,CAAA,YAAA,EAAe,IAAA,CAAK,QAAQ,CAAA,CAAE,CAAA;AAC5D,EAAA,IAAI,KAAK,YAAA,EAAc,KAAA,CAAM,KAAK,CAAA,gBAAA,EAAmB,IAAA,CAAK,YAAY,CAAA,CAAE,CAAA;AACxE,EAAA,IAAI,KAAK,QAAA,EAAU,KAAA,CAAM,KAAK,CAAA,SAAA,EAAY,IAAA,CAAK,QAAQ,CAAA,CAAE,CAAA;AACzD,EAAA,KAAA,CAAM,KAAK,EAAE,CAAA;AACb,EAAA,OAAO,KAAA,CAAM,KAAK,IAAI,CAAA;AACxB;;;AClBO,SAAS,mBAAmB,IAAA,EAAyC;AAC1E,EAAA,MAAM,QAAkB,EAAC;AACzB,EAAA,KAAA,CAAM,IAAA,CAAK,CAAA,CAAA,EAAI,IAAA,CAAK,UAAU,CAAA,CAAA,CAAG,CAAA;AACjC,EAAA,KAAA,CAAM,KAAK,eAAe,CAAA;AAC1B,EAAA,KAAA,CAAM,IAAA,CAAK,CAAA,MAAA,EAAS,IAAA,CAAK,GAAG,CAAA,CAAE,CAAA;AAC9B,EAAA,KAAA,CAAM,IAAA,CAAK,CAAA,SAAA,EAAY,IAAA,CAAK,MAAM,CAAA,CAAE,CAAA;AACpC,EAAA,IAAI,KAAK,QAAA,EAAU,KAAA,CAAM,KAAK,CAAA,OAAA,EAAU,IAAA,CAAK,QAAQ,CAAA,CAAE,CAAA;AACvD,EAAA,IAAI,KAAK,gBAAA,EAAkB,KAAA,CAAM,KAAK,CAAA,OAAA,EAAU,IAAA,CAAK,gBAAgB,CAAA,CAAE,CAAA;AACvE,EAAA,IAAI,KAAK,WAAA,EAAa,KAAA,CAAM,KAAK,CAAA,eAAA,EAAkB,IAAA,CAAK,WAAW,CAAA,CAAE,CAAA;AACrE,EAAA,KAAA,CAAM,KAAK,EAAE,CAAA;AACb,EAAA,OAAO,KAAA,CAAM,KAAK,IAAI,CAAA;AACxB","file":"chunk-GCRKAFH7.js","sourcesContent":["/**\n * Render an rclone INI config snippet for a single OneDrive/SharePoint remote.\n *\n * Pure helper — no IO, no logging — so it can be unit-tested by string compare.\n * The output is the full text for one `[<remoteName>]` section using rclone's\n * `onedrive` backend. The OAuth `token` field is a single-line JSON literal as\n * rclone expects.\n *\n * Lives in `@skaile/workspaces/connectors/rclone-config` so both consumers can\n * reach it: the in-container `sharepoint` mount driver\n * (`ai-assets-skaile/mounts/sharepoint/driver.ts`) and the platform-side\n * `RcloneFleetService` (`platform/backend/libs/session/`) which renders the\n * same INI on the host before spawning a shared rclone process.\n */\n\n/**\n * Options for `renderOneDriveConfig`. Carries OAuth token, drive ID, and optional tenant/client credentials.\n * @docLink packages/connectors/api-reference#render-one-drive-config-options\n */\nexport interface RenderOneDriveConfigOptions {\n /** The rclone remote section name (e.g. `skaile-sharepoint`). */\n remoteName: string;\n /** Current OAuth access token. */\n accessToken: string;\n /** Long-lived refresh token (embedded in the rclone `token` JSON field). */\n refreshToken?: string | null;\n /** Expiry of the access token as a Unix timestamp in milliseconds. */\n expiresAtMs?: number | null;\n /** Azure tenant ID for MSAL authentication. */\n tenantId?: string | null;\n /** OAuth client (application) ID. */\n clientId?: string | null;\n /** OAuth client secret. */\n clientSecret?: string | null;\n /** OneDrive drive ID (required by the rclone `onedrive` backend). */\n driveId: string;\n /** Drive type. Defaults to `\"business\"`. */\n driveType?: \"business\" | \"personal\" | \"documentLibrary\";\n}\n\n/**\n * Render an rclone INI config section for a OneDrive / SharePoint remote. Pure — no IO, no side effects.\n * The `token` field is serialised as a single-line JSON literal as rclone expects.\n * @param opts - Remote name, OAuth token, drive ID, and optional tenant/client credentials.\n * @returns Full INI text for one `[<remoteName>]` rclone section.\n * @docLink packages/connectors/api-reference#render-one-drive-config\n */\nexport function renderOneDriveConfig(opts: RenderOneDriveConfigOptions): string {\n const tokenObj: Record<string, string> = {\n access_token: opts.accessToken,\n token_type: \"Bearer\",\n };\n if (opts.refreshToken) tokenObj.refresh_token = opts.refreshToken;\n if (opts.expiresAtMs != null) {\n tokenObj.expiry = new Date(opts.expiresAtMs).toISOString();\n }\n\n const lines: string[] = [];\n lines.push(`[${opts.remoteName}]`);\n lines.push(\"type = onedrive\");\n lines.push(`drive_id = ${opts.driveId}`);\n lines.push(`drive_type = ${opts.driveType ?? \"business\"}`);\n lines.push(`token = ${JSON.stringify(tokenObj)}`);\n if (opts.clientId) lines.push(`client_id = ${opts.clientId}`);\n if (opts.clientSecret) lines.push(`client_secret = ${opts.clientSecret}`);\n if (opts.tenantId) lines.push(`tenant = ${opts.tenantId}`);\n lines.push(\"\");\n return lines.join(\"\\n\");\n}\n","/**\n * Render an rclone INI config snippet for a single WebDAV remote.\n *\n * Pure helper -- no IO, no logging -- so it can be unit-tested by string compare.\n * The output is the full text for one `[<remoteName>]` section using rclone's\n * `webdav` backend.\n *\n * NOTE: rclone's `pass` field is not plaintext; it must already be passed\n * through `rclone obscure` by the caller. See the driver's `obscurePassword`\n * helper for the spawn that produces it.\n *\n * Lives in `@skaile/workspaces/connectors/rclone-config` so both consumers can\n * reach it: the in-container `webdav` mount driver\n * (`ai-assets-skaile/mounts/webdav/driver.ts`) and the platform-side\n * `RcloneFleetService` (`platform/backend/libs/session/`) which renders the\n * same INI on the host before spawning a shared rclone process.\n */\n\n/**\n * Supported WebDAV vendor identifiers for the rclone `webdav` backend.\n * @docLink packages/connectors/api-reference#web-dav-vendor\n */\nexport type WebDAVVendor = \"nextcloud\" | \"owncloud\" | \"sharepoint\" | \"fastmail\" | \"other\";\n\n/**\n * Options for `renderWebDAVConfig`. Carries remote name, URL, vendor, and credentials.\n * @docLink packages/connectors/api-reference#render-web-dav-config-options\n */\nexport interface RenderWebDAVConfigOptions {\n /** The rclone remote section name (e.g. `skaile-docs`). */\n remoteName: string;\n /** Base URL of the WebDAV server. */\n url: string;\n /** WebDAV vendor; drives rclone's `vendor =` field. */\n vendor: WebDAVVendor;\n /** Basic-auth username. */\n username?: string | null;\n /** Already passed through `rclone obscure`. */\n obscuredPassword?: string | null;\n /** OAuth bearer token (used instead of basic-auth for SharePoint). */\n bearerToken?: string | null;\n}\n\n/**\n * Render an rclone INI config section for a WebDAV remote. Pure — no IO, no side effects.\n * The `obscuredPassword` field must already have been processed through `rclone obscure`.\n * @param opts - Remote name, URL, vendor, and credentials.\n * @returns Full INI text for one `[<remoteName>]` rclone section.\n * @docLink packages/connectors/api-reference#render-web-dav-config\n */\nexport function renderWebDAVConfig(opts: RenderWebDAVConfigOptions): string {\n const lines: string[] = [];\n lines.push(`[${opts.remoteName}]`);\n lines.push(\"type = webdav\");\n lines.push(`url = ${opts.url}`);\n lines.push(`vendor = ${opts.vendor}`);\n if (opts.username) lines.push(`user = ${opts.username}`);\n if (opts.obscuredPassword) lines.push(`pass = ${opts.obscuredPassword}`);\n if (opts.bearerToken) lines.push(`bearer_token = ${opts.bearerToken}`);\n lines.push(\"\");\n return lines.join(\"\\n\");\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../asset-manager/src/installer.ts"],"names":[],"mappings":"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","file":"chunk-M2NLRGIX.js","sourcesContent":["/**\n * Asset deployment — symlink (local repos) or copy (remote repos) to framework dirs.\n */\n\nimport { cpSync, existsSync, lstatSync, mkdirSync, rmSync, symlinkSync, unlinkSync } from \"node:fs\";\nimport { basename, dirname, join, resolve } from \"node:path\";\nimport type { AiComponent, CatalogEntry } from \"@skaile/workspaces/core\";\nimport {\n DRIVER_TARGETS,\n computeHash,\n deployedBase,\n deployedDir,\n isDeployed,\n resolveSkWorkspaceConfig,\n} from \"@skaile/workspaces/core\";\nimport type { DriverTarget, RepositoryDeclaration } from \"@skaile/workspaces/core\";\nimport { applyPatch } from \"@skaile/workspaces/core\";\nimport type { Log } from \"./renderers.js\";\nimport { installAgent } from \"./scaffold/layers/agents.js\";\n\nexport type { Log } from \"./renderers.js\";\n\nconst noop: Log = () => {};\n\n// ── Filesystem helpers ────────────────────────────────────────────────────────\n\nconst DIRECTORY_MANIFESTS = new Set([\"SKILL.md\", \"AGENT.md\", \"agent.yaml\", \"CONTRACT.md\"]);\n\nfunction clearDest(dest: string): void {\n try {\n const s = lstatSync(dest);\n if (s.isSymbolicLink()) unlinkSync(dest);\n else rmSync(dest, { recursive: true, force: true });\n } catch {}\n}\n\nfunction copyFromManifest(manifestPath: string, dest: string): void {\n const name = basename(manifestPath);\n const parentDir = dirname(manifestPath);\n clearDest(dest);\n\n if (DIRECTORY_MANIFESTS.has(name) || basename(parentDir) === basename(dest)) {\n cpSync(parentDir, dest, { recursive: true });\n } else {\n mkdirSync(dest, { recursive: true });\n cpSync(manifestPath, join(dest, name));\n }\n}\n\nfunction symlinkFromManifest(manifestPath: string, dest: string): void {\n const name = basename(manifestPath);\n const parentDir = dirname(manifestPath);\n clearDest(dest);\n mkdirSync(dirname(dest), { recursive: true });\n\n if (DIRECTORY_MANIFESTS.has(name) || basename(parentDir) === basename(dest)) {\n symlinkSync(resolve(parentDir), dest);\n } else {\n mkdirSync(dest, { recursive: true });\n symlinkSync(resolve(manifestPath), join(dest, name));\n }\n}\n\n// ── Deploy options ───────────────────────────────────────────────────────────\n\n/**\n * Options controlling where and how assets are deployed.\n *\n * @docLink packages/asset-manager/api-reference#installer\n */\nexport interface DeployOptions {\n /** Agent framework to target (determines framework-specific directory layout). Defaults to `\"claude-code\"`. */\n driverTarget?: DriverTarget;\n /** When `true`, deploy into the global Skaile cache rather than a project workspace. */\n global?: boolean;\n /** Absolute path to the workspace root. Defaults to `process.cwd()`. */\n cwd?: string;\n}\n\n// ── Deploy / remove ──────────────────────────────────────────────────────────\n\n/**\n * Deploy a single asset to the framework-specific directory.\n *\n * Uses symlinks for local-path repositories (fast, live-updating) and copies\n * for remote repositories (persists after repo wipes). Agents are rendered\n * via the enriched `installAgent` path which resolves abilities, contracts,\n * and framework fragments before writing the native agent file.\n *\n * @param entry - Catalog entry describing the asset to deploy.\n * @param repositories - Repository declarations from `skaile.yaml` (used to\n * determine whether the source is a local path or a remote clone).\n * @param opts - Deployment target options.\n * @param log - Optional logger callback for progress messages.\n * @returns `true` when the asset was deployed successfully.\n * @docLink packages/asset-manager/api-reference#installer\n */\nexport function deployAsset(\n entry: CatalogEntry,\n repositories: Record<string, RepositoryDeclaration>,\n opts: DeployOptions = {},\n log: Log = noop,\n): boolean {\n const driverTarget = opts.driverTarget ?? \"claude-code\";\n const globalInstall = opts.global ?? false;\n const cwd = opts.cwd;\n\n // Bundles are not deployed directly — their dependencies are.\n // MCP servers are configured in skaile.yaml, not deployed to driver target dirs.\n if (entry.kind === \"bundle\" || entry.kind === \"mcp-server\") return true;\n\n // Agents need framework-specific rendering via the enriched installAgent path\n if (entry.kind === \"agent\") {\n const workspaceRoot = cwd ?? process.cwd();\n const agentDeployDir = deployedBase(\n \"agent\" as AiComponent,\n driverTarget as DriverTarget,\n globalInstall,\n cwd,\n );\n const targetMap = DRIVER_TARGETS[driverTarget as DriverTarget];\n const skillsRelDir = targetMap?.local.skill ?? \"\";\n const wsConfig = resolveSkWorkspaceConfig(workspaceRoot);\n const name = basename(entry.source);\n const srcDir = DIRECTORY_MANIFESTS.has(name) ? dirname(entry.source) : entry.source;\n const result = installAgent(\n srcDir,\n agentDeployDir,\n workspaceRoot,\n driverTarget,\n skillsRelDir,\n entry.name,\n /* includeSubAgents */ true,\n new Set<string>(),\n wsConfig,\n log,\n );\n for (const w of result.warnings) log(` warn: ${w}`);\n if (result.created.length > 0) return true;\n // Fall through to raw deploy if renderer produces no files (unsupported framework, etc.)\n }\n\n const dest = deployedDir(entry.kind as AiComponent, entry.name, driverTarget, globalInstall, cwd);\n mkdirSync(dirname(dest), { recursive: true });\n\n // Determine if local or remote\n const repoDecl = entry.repository ? repositories[entry.repository] : undefined;\n const isLocal = repoDecl?.path != null;\n\n if (isLocal) {\n symlinkFromManifest(entry.source, dest);\n log(` symlink ${entry.kind}:${entry.name}`);\n return true;\n } else {\n copyFromManifest(entry.source, dest);\n log(` copy ${entry.kind}:${entry.name}`);\n return true;\n }\n}\n\n/**\n * Deploy all resolved assets, applying patches where configured.\n *\n * Already-deployed assets are skipped unless their deployed manifest content differs\n * from the source. This handles copies (remote repos) that have gone stale after a\n * source update. Symlinked (local) repos always resolve to the live source, so their\n * hashes always match and they are never needlessly re-linked.\n *\n * @param resolved - Catalog entries to deploy (output of `resolveAll`).\n * @param repositories - Repository declarations from `skaile.yaml`.\n * @param patches - Map of `kind:name` → patch file path for patch application.\n * @param opts - Deployment target options.\n * @param log - Optional logger callback for progress messages.\n * @returns Array of asset refs (`kind:name`) that were newly deployed in this call.\n * @docLink packages/asset-manager/api-reference#installer\n */\nexport function deployAll(\n resolved: CatalogEntry[],\n repositories: Record<string, RepositoryDeclaration>,\n patches: Record<string, string>,\n opts: DeployOptions = {},\n log: Log = noop,\n): string[] {\n const deployed: string[] = [];\n const driverTarget = opts.driverTarget ?? \"claude-code\";\n const globalInstall = opts.global ?? false;\n const cwd = opts.cwd;\n\n for (const entry of resolved) {\n // Skip non-deployable asset kinds — bundles are resolved to their contents,\n // mcp-servers are wired at session startup, and mixin kinds (persona, ruleset,\n // knowledge) are resolved by the mixin-resolver at session creation time.\n if (\n entry.kind === \"bundle\" ||\n entry.kind === \"mcp-server\" ||\n entry.kind === \"persona\" ||\n entry.kind === \"ruleset\" ||\n entry.kind === \"knowledge\"\n )\n continue;\n\n const ref = `${entry.kind}:${entry.name}`;\n\n if (isDeployed(entry.kind as AiComponent, entry.name, driverTarget, globalInstall, cwd)) {\n // Compare the deployed manifest file against the source to detect stale copies.\n // For symlinks the deployed path resolves through to the source file, so hashes\n // always match — symlinked installs are never needlessly re-linked.\n const dest = deployedDir(\n entry.kind as AiComponent,\n entry.name,\n driverTarget,\n globalInstall,\n cwd,\n );\n const manifestName = basename(entry.source);\n const deployedManifest = join(dest, manifestName);\n try {\n const srcHash = computeHash(entry.source);\n const depHash = computeHash(deployedManifest);\n if (srcHash === depHash) {\n log(` already deployed: ${ref}`);\n continue;\n }\n log(` updating: ${ref} (content changed)`);\n // fall through to redeploy\n } catch {\n // Deployed manifest unreadable (e.g. agent rendered to a different path) — skip\n log(` already deployed: ${ref}`);\n continue;\n }\n }\n\n deployAsset(entry, repositories, opts, log);\n deployed.push(ref);\n\n // Apply patch if configured\n const patchFile = patches[ref];\n if (patchFile && existsSync(patchFile)) {\n const dest = deployedDir(\n entry.kind as AiComponent,\n entry.name,\n driverTarget,\n globalInstall,\n cwd,\n );\n if (applyPatch(dest, patchFile)) {\n log(` patched ${ref}`);\n } else {\n log(` patch failed for ${ref}`);\n }\n }\n }\n\n return deployed;\n}\n\n/**\n * Remove a deployed asset from the framework directory.\n *\n * Removes symlinks with `unlink`; removes copied directories with `rm -rf`.\n *\n * @param kind - Asset kind (`skill`, `agent`, `prompt`, `flow`, `contract`).\n * @param name - Asset name as registered in the catalog.\n * @param opts - Deployment target options (must match the options used at install time).\n * @returns `true` if the asset existed and was removed; `false` if it was not deployed.\n * @docLink packages/asset-manager/api-reference#installer\n */\nexport function removeAsset(kind: string, name: string, opts: DeployOptions = {}): boolean {\n const driverTarget = opts.driverTarget ?? \"claude-code\";\n const globalInstall = opts.global ?? false;\n const cwd = opts.cwd;\n\n const dest = deployedDir(kind as AiComponent, name, driverTarget, globalInstall, cwd);\n try {\n const s = lstatSync(dest);\n if (s.isSymbolicLink()) unlinkSync(dest);\n else rmSync(dest, { recursive: true, force: true });\n return true;\n } catch {\n return false;\n }\n}\n\n// ── Scaffold ─────────────────────────────────────────────────────────────────\n\nconst SKILL_TEMPLATE = `---\nname: \"{name}\"\ndescription: \"\"\nmetadata:\n version: \"0.1.0\"\n---\n\n# {name}\n\nSkill prompt goes here.\n`;\n\nconst BUNDLE_TEMPLATE = `name: {name}\ndescription: A curated set of assets\nversion: 0.1.0\ndependencies:\n - skill:example-skill\n`;\n\nconst FLOW_TEMPLATE = `id: \"{name}\"\nversion: \"0.1.0\"\nname: \"{name}\"\ndescription: Flow description\n\nglobals:\n approval_mode: checkpoint\n\nnodes: []\n`;\n\n/**\n * Create a minimal scaffold directory for a new asset.\n *\n * Writes the appropriate manifest file (`SKILL.md`, `AGENT.md`, `CONTRACT.md`,\n * `<name>.bundle.yaml`, `<name>.flow.yaml`, or `<name>.prompt.md`) inside a\n * new `<destDir>/<name>/` directory.\n *\n * @param name - Asset name (also used as the directory name).\n * @param kind - Asset kind: `skill` | `agent` | `bundle` | `flow` | `prompt` | `contract`.\n * @param destDir - Parent directory to create the asset in.\n * @returns `{ ok: true, path }` on success, `{ ok: false, path: errorMessage }` if the\n * directory already exists.\n * @docLink packages/asset-manager/api-reference#installer\n */\nexport function createScaffold(\n name: string,\n kind: string,\n destDir: string,\n): { ok: boolean; path: string } {\n const { writeFileSync: write } = require(\"node:fs\");\n const dest = join(destDir, name);\n if (existsSync(dest)) {\n return { ok: false, path: `Directory '${name}' already exists in ${destDir}` };\n }\n mkdirSync(dest, { recursive: true });\n\n if (kind === \"bundle\") {\n write(join(dest, `${name}.bundle.yaml`), BUNDLE_TEMPLATE.replace(/\\{name\\}/g, name), \"utf8\");\n } else if (kind === \"flow\") {\n write(join(dest, `${name}.flow.yaml`), FLOW_TEMPLATE.replace(/\\{name\\}/g, name), \"utf8\");\n } else if (kind === \"prompt\") {\n write(join(dest, `${name}.prompt.md`), SKILL_TEMPLATE.replace(/\\{name\\}/g, name), \"utf8\");\n } else if (kind === \"agent\") {\n write(join(dest, \"AGENT.md\"), SKILL_TEMPLATE.replace(/\\{name\\}/g, name), \"utf8\");\n } else if (kind === \"contract\") {\n write(join(dest, \"CONTRACT.md\"), SKILL_TEMPLATE.replace(/\\{name\\}/g, name), \"utf8\");\n } else {\n // Default: skill\n write(join(dest, \"SKILL.md\"), SKILL_TEMPLATE.replace(/\\{name\\}/g, name), \"utf8\");\n }\n\n return { ok: true, path: dest };\n}\n"]}
@@ -1,546 +0,0 @@
1
- import { applyAgentsLayer } from './chunk-DIKFRNCS.js';
2
- import { WorkspaceYamlEditor } from './chunk-4RUVG5GX.js';
3
- import { DRIVER_TARGETS } from './chunk-O4JH3KUE.js';
4
- import { loadSkWorkspaceConfig } from './chunk-GAZINYCS.js';
5
- import { __require } from './chunk-NSBPE2FW.js';
6
- import { existsSync, mkdirSync, writeFileSync, readFileSync, copyFileSync, statSync, readdirSync } from 'fs';
7
- import { join, basename, dirname, relative, resolve } from 'path';
8
- import { stringify, parse } from 'yaml';
9
- import { execSync } from 'child_process';
10
-
11
- function applyBaseLayer(dest, aiResources, templateSettings, framework, opts) {
12
- const created = [];
13
- if (!existsSync(dest)) {
14
- mkdirSync(dest, { recursive: true });
15
- created.push(".");
16
- }
17
- const skaileDir = join(dest, ".skaile");
18
- if (!existsSync(skaileDir)) {
19
- mkdirSync(skaileDir, { recursive: true });
20
- created.push(".skaile/");
21
- }
22
- const sessionsDir = join(skaileDir, "sessions");
23
- if (!existsSync(sessionsDir)) {
24
- mkdirSync(sessionsDir, { recursive: true });
25
- created.push(".skaile/sessions/");
26
- }
27
- const settingsPath = join(skaileDir, "settings.json");
28
- if (!existsSync(settingsPath)) {
29
- const settings = {
30
- ...templateSettings ?? {},
31
- ...opts.settings ?? {}
32
- };
33
- writeFileSync(settingsPath, `${JSON.stringify(settings, null, 2)}
34
- `);
35
- created.push(".skaile/settings.json");
36
- }
37
- const sources = opts.resources ?? aiResources?.resources ?? [];
38
- const requires = opts.requires ?? aiResources?.requires ?? [];
39
- const wsConfigPath = join(dest, "skaile.yaml");
40
- if (!existsSync(wsConfigPath)) {
41
- const projectName = opts.name ?? basename(dest);
42
- const aiResourceEntries = sources.map((r, i) => {
43
- const entry = { name: r.name, path: r.path };
44
- if (r.branch) entry.branch = r.branch;
45
- if (i === 0 && requires.length > 0) entry.dependencies = requires;
46
- return entry;
47
- });
48
- const wsConfig = {
49
- name: projectName,
50
- description: `${projectName} AI skill dependencies`,
51
- "agent-config": {
52
- default: {
53
- agent: framework,
54
- provider: "anthropic",
55
- model: "claude-sonnet-4-6",
56
- driver: "claude-sdk",
57
- max_turns: 200
58
- }
59
- },
60
- ai_resources: aiResourceEntries
61
- };
62
- writeFileSync(wsConfigPath, stringify(wsConfig));
63
- created.push("skaile.yaml");
64
- }
65
- return created;
66
- }
67
- function applyContainerLayer(dest, config, projectName) {
68
- const created = [];
69
- if (!config?.enabled) return created;
70
- const name = projectName ?? basename(dest);
71
- const baseImage = config.baseImage ?? "node:22-alpine";
72
- const wsPort = config.wsPort ?? 3100;
73
- const dockerfilePath = join(dest, "Dockerfile");
74
- if (!existsSync(dockerfilePath)) {
75
- const dockerfile = generateDockerfile(baseImage, config, wsPort);
76
- writeFileSync(dockerfilePath, dockerfile);
77
- created.push("Dockerfile");
78
- }
79
- const composePath = join(dest, "docker-compose.yml");
80
- if (!existsSync(composePath)) {
81
- const compose = generateCompose(name, config, wsPort);
82
- writeFileSync(composePath, compose);
83
- created.push("docker-compose.yml");
84
- }
85
- const dockerignorePath = join(dest, ".dockerignore");
86
- if (!existsSync(dockerignorePath)) {
87
- writeFileSync(
88
- dockerignorePath,
89
- ["node_modules", ".git", ".skaile/sessions", "*.log", ".env.local", ""].join("\n")
90
- );
91
- created.push(".dockerignore");
92
- }
93
- return created;
94
- }
95
- function generateDockerfile(baseImage, config, wsPort) {
96
- const lines = [`FROM ${baseImage}`, "", "# System packages"];
97
- const packages = ["git", "curl", ...config.packages ?? []];
98
- if (baseImage.includes("alpine")) {
99
- lines.push(`RUN apk add --no-cache ${packages.join(" ")}`);
100
- } else {
101
- lines.push(
102
- `RUN apt-get update && apt-get install -y ${packages.join(" ")} && rm -rf /var/lib/apt/lists/*`
103
- );
104
- }
105
- lines.push("");
106
- if (config.agents && config.agents.length > 0) {
107
- lines.push("# Agent CLIs");
108
- for (const agent of config.agents) {
109
- lines.push(`RUN npm install -g ${agent}`);
110
- }
111
- lines.push("");
112
- }
113
- lines.push("WORKDIR /workspace");
114
- lines.push("");
115
- lines.push("# Copy workspace configuration");
116
- lines.push("COPY skaile.yaml ./");
117
- lines.push("COPY .skaile/ ./.skaile/");
118
- lines.push("");
119
- const ports = [String(wsPort), ...config.ports ?? []];
120
- for (const port of ports) {
121
- lines.push(`EXPOSE ${port}`);
122
- }
123
- lines.push("");
124
- if (config.env && config.env.length > 0) {
125
- lines.push("# Environment");
126
- for (const envVar of config.env) {
127
- lines.push(`ENV ${envVar}`);
128
- }
129
- lines.push("");
130
- }
131
- lines.push("# Default entrypoint \u2014 override in compose or at runtime");
132
- lines.push('ENTRYPOINT ["sh", "-c"]');
133
- lines.push('CMD ["echo Agent workspace ready && exec sh"]');
134
- lines.push("");
135
- return lines.join("\n");
136
- }
137
- function generateCompose(name, config, wsPort) {
138
- const serviceName = name.replace(/[^a-z0-9-]/gi, "-").toLowerCase();
139
- const ports = [`${wsPort}:${wsPort}`, ...(config.ports ?? []).map((p) => `${p}:${p}`)];
140
- const lines = [
141
- "services:",
142
- ` ${serviceName}:`,
143
- " build: .",
144
- ` container_name: ${serviceName}`
145
- ];
146
- if (ports.length > 0) {
147
- lines.push(" ports:");
148
- for (const port of ports) {
149
- lines.push(` - "${port}"`);
150
- }
151
- }
152
- if (config.mounts && config.mounts.length > 0) {
153
- lines.push(" volumes:");
154
- for (const mount of config.mounts) {
155
- if (mount.type === "bind") {
156
- lines.push(` - ${mount.source}:${mount.target}`);
157
- } else {
158
- lines.push(` - ${mount.source}:${mount.target}`);
159
- }
160
- }
161
- }
162
- if (config.env && config.env.length > 0) {
163
- lines.push(" environment:");
164
- for (const envVar of config.env) {
165
- if (envVar.includes("=")) {
166
- lines.push(` - ${envVar}`);
167
- } else {
168
- lines.push(` - ${envVar}`);
169
- }
170
- }
171
- }
172
- lines.push(" restart: unless-stopped");
173
- lines.push("");
174
- return lines.join("\n");
175
- }
176
- function applyDriverTargetLayer(dest, config, driverTargetOverride) {
177
- const created = [];
178
- const driverTarget = driverTargetOverride ?? config?.["default-target"] ?? "claude-code";
179
- const targetMap = DRIVER_TARGETS[driverTarget];
180
- if (!targetMap) return created;
181
- const dirsToCreate = /* @__PURE__ */ new Set();
182
- for (const dir of Object.values(targetMap.local)) {
183
- dirsToCreate.add(dir);
184
- }
185
- if (config?.extras) {
186
- for (const extra of config.extras) {
187
- dirsToCreate.add(extra);
188
- }
189
- }
190
- for (const dir of dirsToCreate) {
191
- const fullPath = join(dest, dir);
192
- if (!existsSync(fullPath)) {
193
- mkdirSync(fullPath, { recursive: true });
194
- created.push(`${dir}/`);
195
- }
196
- }
197
- return created;
198
- }
199
- function applyHooksLayer(dest, config, log) {
200
- const result = { created: [], warnings: [] };
201
- if (!config) return result;
202
- if (config.gitInit) {
203
- const gitDir = join(dest, ".git");
204
- if (!existsSync(gitDir)) {
205
- try {
206
- execSync("git init", { cwd: dest, stdio: "pipe" });
207
- result.created.push(".git/");
208
- log?.("Initialized git repository");
209
- } catch (err) {
210
- const msg = err instanceof Error ? err.message : String(err);
211
- result.warnings.push(`git init failed: ${msg}`);
212
- }
213
- }
214
- }
215
- if (config.gitignore && config.gitignore.length > 0) {
216
- const gitignorePath = join(dest, ".gitignore");
217
- let existing = "";
218
- if (existsSync(gitignorePath)) {
219
- existing = readFileSync(gitignorePath, "utf-8");
220
- }
221
- const existingLines = new Set(existing.split("\n").map((l) => l.trim()));
222
- const newEntries = config.gitignore.filter((e) => !existingLines.has(e));
223
- if (newEntries.length > 0) {
224
- const append = `${(existing && !existing.endsWith("\n") ? "\n" : "") + newEntries.join("\n")}
225
- `;
226
- writeFileSync(gitignorePath, existing + append);
227
- if (!existingLines.size) {
228
- result.created.push(".gitignore");
229
- }
230
- }
231
- }
232
- if (config.setupScripts) {
233
- for (const script of config.setupScripts) {
234
- try {
235
- log?.(`Running setup script: ${script.name}`);
236
- const cwd = script.cwd ? join(dest, script.cwd) : dest;
237
- if (!existsSync(cwd)) {
238
- mkdirSync(cwd, { recursive: true });
239
- }
240
- execSync(script.run, {
241
- cwd,
242
- stdio: "pipe",
243
- timeout: 6e4,
244
- env: { ...process.env, WORKSPACE_DIR: dest }
245
- });
246
- log?.(`Setup script "${script.name}" completed`);
247
- } catch (err) {
248
- const msg = err instanceof Error ? err.message : String(err);
249
- result.warnings.push(`Setup script "${script.name}" failed: ${msg}`);
250
- }
251
- }
252
- }
253
- return result;
254
- }
255
- function applyConnectorsLayer(dest, connectors, log) {
256
- const created = [];
257
- const entries = Array.isArray(connectors) ? connectors : [];
258
- if (!entries.length) return created;
259
- const yamlPath = join(dest, "skaile.yaml");
260
- if (existsSync(yamlPath)) {
261
- const editor = WorkspaceYamlEditor.load(yamlPath);
262
- for (const r of entries) {
263
- editor.setConnector({
264
- id: r.id,
265
- driver: r.driver,
266
- access: r.access ?? "read-only",
267
- auth: r.auth,
268
- options: r.options
269
- });
270
- }
271
- editor.save();
272
- log?.(`Wrote ${entries.length} connector(s) to skaile.yaml`);
273
- } else {
274
- log?.("Skipping connector write: skaile.yaml not found (base layer should create it first)");
275
- }
276
- for (const connector of entries) {
277
- if (connector.autoMount === false) continue;
278
- const mountPath = connector.mountPath ?? `.connectors/${connector.id}`;
279
- const absMount = join(dest, mountPath);
280
- if (!existsSync(absMount)) {
281
- mkdirSync(absMount, { recursive: true });
282
- created.push(`${mountPath}/`);
283
- log?.(`Created mount dir: ${mountPath}`);
284
- }
285
- }
286
- return created;
287
- }
288
- async function loadAssetManager() {
289
- try {
290
- const mod = await import('./asset-manager/index.js');
291
- return mod.AssetManager ?? null;
292
- } catch {
293
- return null;
294
- }
295
- }
296
- async function applySkillsLayer(dest, config, log) {
297
- const result = { installed: [], warnings: [] };
298
- if (!config?.autoInstall) return result;
299
- const wsConfigPath = join(dest, "skaile.yaml");
300
- if (!existsSync(wsConfigPath)) {
301
- result.warnings.push("Skipping skill install: skaile.yaml not found");
302
- return result;
303
- }
304
- const AssetManager = await loadAssetManager();
305
- if (!AssetManager) {
306
- result.warnings.push(
307
- "Skipping skill install: AssetManager could not be loaded. Run `skaile install` manually."
308
- );
309
- return result;
310
- }
311
- try {
312
- log?.("Installing AI resources...");
313
- const am = new AssetManager({ projectDir: dest });
314
- const installResult = await am.install();
315
- if (Array.isArray(installResult)) {
316
- result.installed = installResult;
317
- } else if (installResult?.deployed) {
318
- result.installed = installResult.deployed;
319
- }
320
- log?.(`Installed ${result.installed.length} skill(s)`);
321
- } catch (err) {
322
- const msg = err instanceof Error ? err.message : String(err);
323
- result.warnings.push(`Skill install failed: ${msg}`);
324
- }
325
- return result;
326
- }
327
- function copyDirSkipExisting(src, dest, created, baseDest) {
328
- if (!existsSync(dest)) mkdirSync(dest, { recursive: true });
329
- for (const entry of readdirSync(src, { withFileTypes: true })) {
330
- const srcPath = join(src, entry.name);
331
- const destPath = join(dest, entry.name);
332
- if (entry.isDirectory()) {
333
- copyDirSkipExisting(srcPath, destPath, created, baseDest);
334
- } else if (!existsSync(destPath)) {
335
- mkdirSync(dirname(destPath), { recursive: true });
336
- copyFileSync(srcPath, destPath);
337
- created.push(relative(baseDest, destPath));
338
- }
339
- }
340
- }
341
- function applyTemplateLayer(dest, config, templateDir) {
342
- const created = [];
343
- if (!config) return created;
344
- if (config.agentDir) {
345
- const agentDir = config.agentDir;
346
- if (existsSync(agentDir)) {
347
- for (const file of ["SOUL.md", "RULES.md", "DUTIES.md"]) {
348
- const src = join(agentDir, file);
349
- const destFile = join(dest, ".skaile", "agent", file);
350
- if (existsSync(src) && !existsSync(destFile)) {
351
- mkdirSync(dirname(destFile), { recursive: true });
352
- copyFileSync(src, destFile);
353
- created.push(relative(dest, destFile));
354
- }
355
- }
356
- const knowledgeSrc = join(agentDir, "knowledge");
357
- if (existsSync(knowledgeSrc)) {
358
- const knowledgeDest = join(dest, ".skaile", "agent", "knowledge");
359
- copyDirSkipExisting(knowledgeSrc, knowledgeDest, created, dest);
360
- }
361
- const skillsSrc = join(agentDir, "skills");
362
- if (existsSync(skillsSrc)) {
363
- const skillsDest = join(dest, ".skaile", "agent", "skills");
364
- copyDirSkipExisting(skillsSrc, skillsDest, created, dest);
365
- }
366
- }
367
- }
368
- if (config.soul) {
369
- const soulPath = join(dest, ".skaile", "agent", "SOUL.md");
370
- if (!existsSync(soulPath)) {
371
- mkdirSync(dirname(soulPath), { recursive: true });
372
- writeFileSync(soulPath, config.soul);
373
- created.push(".skaile/agent/SOUL.md");
374
- }
375
- }
376
- if (config.rules) {
377
- const rulesPath = join(dest, ".skaile", "agent", "RULES.md");
378
- if (!existsSync(rulesPath)) {
379
- mkdirSync(dirname(rulesPath), { recursive: true });
380
- writeFileSync(rulesPath, config.rules);
381
- created.push(".skaile/agent/RULES.md");
382
- }
383
- }
384
- if (config.files && templateDir) {
385
- for (const file of config.files) {
386
- const srcPath = join(templateDir, file.src);
387
- const destPath = join(dest, file.dest);
388
- if (!existsSync(srcPath)) continue;
389
- if (existsSync(destPath)) continue;
390
- if (statSync(srcPath).isDirectory()) {
391
- copyDirSkipExisting(srcPath, destPath, created, dest);
392
- } else {
393
- mkdirSync(dirname(destPath), { recursive: true });
394
- copyFileSync(srcPath, destPath);
395
- created.push(file.dest);
396
- }
397
- }
398
- }
399
- return created;
400
- }
401
- var _builtinTemplatesDir = null;
402
- function getBuiltinTemplatesDir() {
403
- if (_builtinTemplatesDir) return _builtinTemplatesDir;
404
- return join(dirname(new URL(import.meta.url).pathname), "..", "..", "templates");
405
- }
406
- function setTemplatesDir(dir) {
407
- _builtinTemplatesDir = resolve(dir);
408
- }
409
- function resolveTemplatePath(template) {
410
- if (template.endsWith(".yaml") || template.endsWith(".yml")) {
411
- const abs = resolve(template);
412
- return existsSync(abs) ? abs : null;
413
- }
414
- const dirPath = resolve(template);
415
- const inDir = join(dirPath, "workspace.yaml");
416
- if (existsSync(inDir)) return inDir;
417
- const builtin = join(getBuiltinTemplatesDir(), template, "workspace.yaml");
418
- if (existsSync(builtin)) return builtin;
419
- return null;
420
- }
421
- function loadTemplate(templatePath) {
422
- const raw = readFileSync(templatePath, "utf-8");
423
- const manifest = parse(raw);
424
- const dir = dirname(templatePath);
425
- if (manifest.extends) {
426
- const parentPath = resolveTemplatePath(manifest.extends) ?? resolveTemplatePath(join(dir, manifest.extends));
427
- if (parentPath) {
428
- const parent = loadTemplate(parentPath);
429
- const { extends: _ext, name, description, version, ...childSections } = manifest;
430
- Object.assign(manifest, {
431
- ...parent.manifest,
432
- name,
433
- description,
434
- version,
435
- extends: _ext,
436
- ...childSections
437
- });
438
- }
439
- }
440
- return { manifest, dir };
441
- }
442
- function listTemplates() {
443
- const templates = [];
444
- const templatesDir = getBuiltinTemplatesDir();
445
- if (!existsSync(templatesDir)) return templates;
446
- const { readdirSync: readdirSync2 } = __require("fs");
447
- for (const entry of readdirSync2(templatesDir, { withFileTypes: true })) {
448
- if (!entry.isDirectory()) continue;
449
- const wsPath = join(templatesDir, entry.name, "workspace.yaml");
450
- if (!existsSync(wsPath)) continue;
451
- try {
452
- const raw = readFileSync(wsPath, "utf-8");
453
- const manifest = parse(raw);
454
- templates.push({
455
- name: manifest.name ?? entry.name,
456
- description: manifest.description ?? "",
457
- path: wsPath
458
- });
459
- } catch {
460
- }
461
- }
462
- return templates;
463
- }
464
- async function scaffoldWorkspace(opts) {
465
- const log = opts.log ?? (() => {
466
- });
467
- const dest = resolve(opts.dest);
468
- const result = {
469
- path: dest,
470
- created: [],
471
- installed: [],
472
- warnings: []
473
- };
474
- const templatePath = resolveTemplatePath(opts.template);
475
- if (!templatePath) {
476
- result.warnings.push(`Template not found: ${opts.template}`);
477
- return result;
478
- }
479
- const { manifest, dir: templateDir } = loadTemplate(templatePath);
480
- log(`Scaffolding workspace from template: ${manifest.name}`);
481
- log("Applying base layer...");
482
- const driverTarget = opts.driverTarget ?? manifest.framework?.["default-target"] ?? "claude-code";
483
- const baseCreated = applyBaseLayer(
484
- dest,
485
- manifest["ai-assets"],
486
- manifest.settings,
487
- driverTarget,
488
- opts
489
- );
490
- result.created.push(...baseCreated);
491
- const connectorEntries = manifest.connectors;
492
- if (connectorEntries?.length) {
493
- log("Applying connectors layer...");
494
- const resCreated = applyConnectorsLayer(dest, connectorEntries, log);
495
- result.created.push(...resCreated);
496
- }
497
- log("Applying driver target layer...");
498
- const fwCreated = applyDriverTargetLayer(dest, manifest.framework, opts.driverTarget);
499
- result.created.push(...fwCreated);
500
- log("Applying template layer...");
501
- const templateConfig = manifest.template;
502
- if (templateConfig?.agentDir && !templateConfig.agentDir.startsWith("/")) {
503
- templateConfig.agentDir = join(templateDir, templateConfig.agentDir);
504
- }
505
- const tmplCreated = applyTemplateLayer(dest, templateConfig, templateDir);
506
- result.created.push(...tmplCreated);
507
- log("Applying agents layer...");
508
- const agentsConfig = opts.agentInstall ? { install: opts.agentInstall } : manifest.agents;
509
- const wsConfig = loadSkWorkspaceConfig(dest)?.config;
510
- const agentsResult = await applyAgentsLayer(
511
- dest,
512
- agentsConfig,
513
- driverTarget,
514
- templateDir,
515
- wsConfig,
516
- log
517
- );
518
- result.created.push(...agentsResult.created);
519
- result.warnings.push(...agentsResult.warnings);
520
- if (!opts.skipInstall) {
521
- log("Applying skills layer...");
522
- const skillsResult = await applySkillsLayer(dest, manifest.skills, log);
523
- result.installed.push(...skillsResult.installed);
524
- result.warnings.push(...skillsResult.warnings);
525
- }
526
- log("Applying hooks layer...");
527
- const hooksResult = applyHooksLayer(dest, manifest.hooks, log);
528
- result.created.push(...hooksResult.created);
529
- result.warnings.push(...hooksResult.warnings);
530
- const enableDocker = opts.docker ?? manifest.container?.enabled ?? false;
531
- if (enableDocker) {
532
- log("Applying container layer...");
533
- const containerCreated = applyContainerLayer(
534
- dest,
535
- { ...manifest.container, enabled: true },
536
- opts.name
537
- );
538
- result.created.push(...containerCreated);
539
- }
540
- log(`Workspace scaffolded: ${result.created.length} files/dirs created`);
541
- return result;
542
- }
543
-
544
- export { applyBaseLayer, applyConnectorsLayer, applyContainerLayer, applyDriverTargetLayer, applyHooksLayer, applySkillsLayer, applyTemplateLayer, listTemplates, loadTemplate, resolveTemplatePath, scaffoldWorkspace, setTemplatesDir };
545
- //# sourceMappingURL=chunk-YHXBQLXX.js.map
546
- //# sourceMappingURL=chunk-YHXBQLXX.js.map