@skaile/workspaces 5.1.2 → 5.1.3

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 (113) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/dist/{asset-feeds-EVS3WPWS.js → asset-feeds-C4X4RTZV.js} +4 -4
  3. package/dist/{asset-feeds-EVS3WPWS.js.map → asset-feeds-C4X4RTZV.js.map} +1 -1
  4. package/dist/asset-manager/index.js +1 -1
  5. package/dist/bridge/drivers/claude-sdk.js +98 -12
  6. package/dist/bridge/drivers/claude-sdk.js.map +1 -1
  7. package/dist/bridge/drivers/codex.js +2 -2
  8. package/dist/bridge/drivers/continue.js +3 -3
  9. package/dist/bridge/drivers/echo.js +1 -1
  10. package/dist/bridge/drivers/gemini.js +5 -5
  11. package/dist/bridge/drivers/goose.js +3 -3
  12. package/dist/bridge/drivers/omp.js +2 -2
  13. package/dist/bridge/drivers/opencode.js +3 -3
  14. package/dist/bridge/drivers/qwen.js +5 -5
  15. package/dist/bridge/index.js +3 -3
  16. package/dist/bridge/src/drivers/claude-sdk.d.ts +16 -0
  17. package/dist/bridge/src/drivers/claude-sdk.d.ts.map +1 -1
  18. package/dist/{chunk-56IWSMSD.js → chunk-2HR3RPWD.js} +6 -6
  19. package/dist/{chunk-56IWSMSD.js.map → chunk-2HR3RPWD.js.map} +1 -1
  20. package/dist/{chunk-E67J56FJ.js → chunk-5S4ZK75K.js} +3 -3
  21. package/dist/{chunk-E67J56FJ.js.map → chunk-5S4ZK75K.js.map} +1 -1
  22. package/dist/{chunk-KDH74UWB.js → chunk-AZYIEK3F.js} +3 -3
  23. package/dist/{chunk-KDH74UWB.js.map → chunk-AZYIEK3F.js.map} +1 -1
  24. package/dist/{chunk-YJACHPI7.js → chunk-BEOKEK3B.js} +2 -2
  25. package/dist/{chunk-YJACHPI7.js.map → chunk-BEOKEK3B.js.map} +1 -1
  26. package/dist/{chunk-UO5CWEHZ.js → chunk-BJZHNSQO.js} +4 -4
  27. package/dist/{chunk-UO5CWEHZ.js.map → chunk-BJZHNSQO.js.map} +1 -1
  28. package/dist/{chunk-KAYH6AXN.js → chunk-DLLM4U6C.js} +3 -3
  29. package/dist/{chunk-KAYH6AXN.js.map → chunk-DLLM4U6C.js.map} +1 -1
  30. package/dist/{chunk-6CSSFLGC.js → chunk-I75CM2QF.js} +6 -6
  31. package/dist/{chunk-6CSSFLGC.js.map → chunk-I75CM2QF.js.map} +1 -1
  32. package/dist/{chunk-X6IELFVB.js → chunk-IAGCOAIW.js} +3 -3
  33. package/dist/{chunk-X6IELFVB.js.map → chunk-IAGCOAIW.js.map} +1 -1
  34. package/dist/{chunk-CXGHL75R.js → chunk-KNC55536.js} +2 -2
  35. package/dist/{chunk-CXGHL75R.js.map → chunk-KNC55536.js.map} +1 -1
  36. package/dist/{chunk-P5UQ56RA.js → chunk-KVAI5DGL.js} +3 -3
  37. package/dist/{chunk-P5UQ56RA.js.map → chunk-KVAI5DGL.js.map} +1 -1
  38. package/dist/{chunk-VFAJZE45.js → chunk-KWP4RVTJ.js} +13 -9
  39. package/dist/chunk-KWP4RVTJ.js.map +1 -0
  40. package/dist/{chunk-N2X7DK2S.js → chunk-M4ISBWXR.js} +5 -5
  41. package/dist/{chunk-N2X7DK2S.js.map → chunk-M4ISBWXR.js.map} +1 -1
  42. package/dist/{chunk-EPHQWHOH.js → chunk-O4U7OL6D.js} +6 -6
  43. package/dist/{chunk-EPHQWHOH.js.map → chunk-O4U7OL6D.js.map} +1 -1
  44. package/dist/{chunk-YIVB7GIP.js → chunk-QU4J5YSJ.js} +3 -3
  45. package/dist/{chunk-YIVB7GIP.js.map → chunk-QU4J5YSJ.js.map} +1 -1
  46. package/dist/{chunk-52PFJLBJ.js → chunk-RNOIDD3Y.js} +3 -3
  47. package/dist/{chunk-52PFJLBJ.js.map → chunk-RNOIDD3Y.js.map} +1 -1
  48. package/dist/{chunk-TB6GDL6Q.js → chunk-RO4Z2CBP.js} +3 -3
  49. package/dist/{chunk-TB6GDL6Q.js.map → chunk-RO4Z2CBP.js.map} +1 -1
  50. package/dist/{chunk-CJB5HUY6.js → chunk-WPWJRDR3.js} +3 -3
  51. package/dist/{chunk-CJB5HUY6.js.map → chunk-WPWJRDR3.js.map} +1 -1
  52. package/dist/{chunk-ZMMFBID4.js → chunk-Y6V6NUEV.js} +3 -3
  53. package/dist/{chunk-ZMMFBID4.js.map → chunk-Y6V6NUEV.js.map} +1 -1
  54. package/dist/{chunk-RDTHJSGY.js → chunk-ZD7CX25M.js} +2 -2
  55. package/dist/{chunk-RDTHJSGY.js.map → chunk-ZD7CX25M.js.map} +1 -1
  56. package/dist/{chunk-THPQ6J3U.js → chunk-ZVKJNNME.js} +3 -3
  57. package/dist/{chunk-THPQ6J3U.js.map → chunk-ZVKJNNME.js.map} +1 -1
  58. package/dist/cli/index.js +35 -35
  59. package/dist/connectors/index.js +4 -4
  60. package/dist/{connectors-KSVPVYCA.js → connectors-BQXFKISC.js} +7 -7
  61. package/dist/{connectors-KSVPVYCA.js.map → connectors-BQXFKISC.js.map} +1 -1
  62. package/dist/{ensure-sources-KVV72WRP.js → ensure-sources-CMHOTYFS.js} +4 -4
  63. package/dist/{ensure-sources-KVV72WRP.js.map → ensure-sources-CMHOTYFS.js.map} +1 -1
  64. package/dist/factory-assets/connectors/box.js +4 -4
  65. package/dist/factory-assets/connectors/deploy.js +4 -4
  66. package/dist/factory-assets/connectors/devserver.js +4 -4
  67. package/dist/factory-assets/connectors/flow/adapter.js +4 -4
  68. package/dist/factory-assets/connectors/flow/run-flow.js +5 -5
  69. package/dist/factory-assets/connectors/flow.js +4 -4
  70. package/dist/factory-assets/connectors/git.js +4 -4
  71. package/dist/factory-assets/connectors/gmail.js +4 -4
  72. package/dist/factory-assets/connectors/googledrive.js +4 -4
  73. package/dist/factory-assets/connectors/local.js +4 -4
  74. package/dist/factory-assets/connectors/mattermost.js +4 -4
  75. package/dist/factory-assets/connectors/memory.js +4 -4
  76. package/dist/factory-assets/connectors/minio.js +4 -4
  77. package/dist/factory-assets/connectors/postgres.js +4 -4
  78. package/dist/factory-assets/connectors/s3.js +4 -4
  79. package/dist/factory-assets/connectors/sharepoint.js +4 -4
  80. package/dist/factory-assets/connectors/sqlite.js +4 -4
  81. package/dist/factory-assets/connectors/static-server.js +4 -4
  82. package/dist/factory-assets/connectors/tunnel.js +4 -4
  83. package/dist/factory-assets/connectors/webdav.js +4 -4
  84. package/dist/factory-assets/connectors/xstate-store.js +4 -4
  85. package/dist/factory-assets/connectors/xstate.js +4 -4
  86. package/dist/{helpers-4NT7UX6I.js → helpers-R3GLTAER.js} +4 -4
  87. package/dist/{helpers-4NT7UX6I.js.map → helpers-R3GLTAER.js.map} +1 -1
  88. package/dist/{library-publish-GHIWWEEY.js → library-publish-EL7VYICU.js} +7 -7
  89. package/dist/{library-publish-GHIWWEEY.js.map → library-publish-EL7VYICU.js.map} +1 -1
  90. package/dist/{open-library-XKWTUYU2.js → open-library-MTD34YX3.js} +5 -5
  91. package/dist/{open-library-XKWTUYU2.js.map → open-library-MTD34YX3.js.map} +1 -1
  92. package/dist/{project-P2QS3GNG.js → project-HCNWJP7J.js} +5 -5
  93. package/dist/{project-P2QS3GNG.js.map → project-HCNWJP7J.js.map} +1 -1
  94. package/dist/runner/index.js +9 -9
  95. package/dist/runner/src/ai-provider-switch.d.ts +10 -0
  96. package/dist/runner/src/ai-provider-switch.d.ts.map +1 -1
  97. package/dist/runner/src/serve.d.ts.map +1 -1
  98. package/dist/sdk/asset-manager.js +1 -1
  99. package/dist/sdk/bridge.js +3 -3
  100. package/dist/sdk/index.js +9 -9
  101. package/dist/sdk/runner.js +9 -9
  102. package/dist/{setup-RVP74D37.js → setup-HTXNR2CZ.js} +8 -8
  103. package/dist/{setup-RVP74D37.js.map → setup-HTXNR2CZ.js.map} +1 -1
  104. package/dist/{source-VBROLEFB.js → source-UIFC2PFC.js} +6 -6
  105. package/dist/{source-VBROLEFB.js.map → source-UIFC2PFC.js.map} +1 -1
  106. package/dist/{source-manifest-publish-7XDLJRLX.js → source-manifest-publish-QKAKXDVH.js} +8 -8
  107. package/dist/{source-manifest-publish-7XDLJRLX.js.map → source-manifest-publish-QKAKXDVH.js.map} +1 -1
  108. package/dist/tui/index.js +9 -9
  109. package/dist/workspace-plugin/adapters/mcp.js +6 -6
  110. package/dist/workspace-plugin/adapters/omp.js +7 -7
  111. package/dist/workspace-plugin/index.js +1 -1
  112. package/package.json +1 -1
  113. package/dist/chunk-VFAJZE45.js.map +0 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # Changelog
2
2
 
3
+ ## 5.1.3
4
+
5
+ ### Patch Changes
6
+
7
+ - [#1007](https://github.com/skaile-ai/workspaces/pull/1007) [`30dd4ef`](https://github.com/skaile-ai/workspaces/commit/30dd4efb5c9098b6a2c758729a8c74c8b0255eaa) Thanks [@Frozen666](https://github.com/Frozen666)! - A turn that the claude-sdk driver replays on another AI provider seat after a usage limit no longer shows a fatal "Agent stopped" error before the replayed reply. A turn still running on the old seat after a `credentialRotated` switch is now replayed on the new seat when it hits the old seat's limit, instead of ending with the limit error.
8
+
3
9
  ## 5.1.2
4
10
 
5
11
  ### Patch Changes
@@ -23,7 +23,7 @@ import * as path from 'path';
23
23
  async function libraryAssets() {
24
24
  const notes = [];
25
25
  try {
26
- const { openLibraryManager, authoringLibraries } = await import('./open-library-XKWTUYU2.js');
26
+ const { openLibraryManager, authoringLibraries } = await import('./open-library-MTD34YX3.js');
27
27
  const { manager, close } = await openLibraryManager();
28
28
  try {
29
29
  const libs = authoringLibraries(await manager.listLibraries());
@@ -48,7 +48,7 @@ async function libraryAssets() {
48
48
  async function storeAssets(projectDir) {
49
49
  const notes = [];
50
50
  try {
51
- const { resolveCatalogSource } = await import('./open-library-XKWTUYU2.js');
51
+ const { resolveCatalogSource } = await import('./open-library-MTD34YX3.js');
52
52
  const { source, close } = await resolveCatalogSource({ projectDir });
53
53
  try {
54
54
  const assets = await source.listAssets();
@@ -127,5 +127,5 @@ async function gatherAssetFeeds(am, projectDir) {
127
127
  }
128
128
 
129
129
  export { gatherAssetFeeds };
130
- //# sourceMappingURL=asset-feeds-EVS3WPWS.js.map
131
- //# sourceMappingURL=asset-feeds-EVS3WPWS.js.map
130
+ //# sourceMappingURL=asset-feeds-C4X4RTZV.js.map
131
+ //# sourceMappingURL=asset-feeds-C4X4RTZV.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../cli/src/asset-feeds.ts"],"names":[],"mappings":"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","file":"asset-feeds-EVS3WPWS.js","sourcesContent":["/**\n * asset-feeds.ts — gather installable assets from every feed the manage TUI\n * surfaces.\n *\n * Four feeds, normalized into `CatalogEntry`:\n * - **Project sources** — `skaile.yaml` `sources:` entries (scanned via\n * `AssetManager.search()`; the new `sources:` field is merged into the\n * legacy repositories map in `AssetManager.loadConfig`).\n * - **Local libraries** — user authoring places from `LocalIndex` (filesystem\n * scan of each library's `path`).\n * - **Factory assets** — the bundled first-party `factory-assets` tree\n * (`factoryAssetRoots()`), scanned from disk. Always present; no network.\n * - **Remote store** — the configured catalog source when `catalog.url` is\n * not `local`. Failures are non-fatal — they surface as notes.\n */\n\nimport { existsSync } from \"node:fs\";\nimport * as path from \"node:path\";\nimport {\n type AssetKind,\n type CatalogEntry,\n factoryAssetRoots,\n scanRepo,\n} from \"@skaile/workspaces/core\";\n\n/** One non-fatal note returned to the caller for surfacing in the UI. */\nexport interface FeedNote {\n feed: \"sources\" | \"libraries\" | \"store\" | \"factory\";\n message: string;\n}\n\n/**\n * Which feed an asset came from. This is the top-level grouping axis in the\n * manage TUI (\"where is this skill coming from?\") and is intentionally distinct\n * from `publisher` (asset-intrinsic identity): the same publisher can legitimately\n * appear under more than one origin (e.g. a github repo you added as a `source`\n * that is also listed in the remote `store`).\n */\nexport type AssetOrigin = \"source\" | \"library\" | \"factory\" | \"store\";\n\n/** A catalog entry tagged with the feed it was gathered from. */\nexport interface OriginEntry {\n origin: AssetOrigin;\n entry: CatalogEntry;\n /**\n * Second-level grouping label for the manage tree. Defaults (when unset) to the\n * entry's `publisher`; the source feed sets it to the source's short repo name\n * so the Sources band groups by source — \"which repo did this come from\" — not\n * by the asset-intrinsic publisher.\n */\n group?: string;\n}\n\nexport interface AssetFeedResult {\n entries: OriginEntry[];\n notes: FeedNote[];\n}\n\n/**\n * Pull assets from local libraries (the authoring places under\n * `~/.skaile/libraries/<name>/`, not the `~/.skaile/cache/sources/` cache). Each\n * library's `path` is scanned with `scanRepo` and grouped under the bare library\n * name (`group: <name>`) so the manage TUI shows a clean `<name>` band — no\n * `library:` prefix (mirrors the source feed). Plugin grouping (`entry.plugin`)\n * is stamped by `scanRepo`.\n */\nasync function libraryAssets(): Promise<{\n entries: OriginEntry[];\n notes: FeedNote[];\n}> {\n const notes: FeedNote[] = [];\n try {\n const { openLibraryManager, authoringLibraries } = await import(\"./open-library.ts\");\n const { manager, close } = await openLibraryManager();\n try {\n // Authoring libraries are the rows that are NOT source clones.\n const libs = authoringLibraries(await manager.listLibraries());\n const entries: OriginEntry[] = [];\n for (const lib of libs) {\n if (!existsSync(lib.path)) continue;\n const libEntries = [...(await scanRepo(lib.path, lib.name))];\n for (const entry of libEntries) entries.push({ origin: \"library\", entry, group: lib.name });\n }\n return { entries, notes };\n } finally {\n close();\n }\n } catch (err) {\n notes.push({\n feed: \"libraries\",\n message: err instanceof Error ? err.message : String(err),\n });\n return { entries: [], notes };\n }\n}\n\n/**\n * Pull a (best-effort) snapshot of the connected remote store catalog.\n *\n * - Returns no entries when the resolved catalog is local-only or the host\n * is unreachable (the failure becomes a note, not an exception).\n * - Maps `CatalogAsset` → `CatalogEntry`, carrying `publisher`, `repo`, and\n * `category` straight through and using `source = \"store://<id>\"`; per-file\n * `source` paths are not available for remote assets so the canonical ref is\n * a stable placeholder.\n */\nasync function storeAssets(projectDir: string): Promise<{\n entries: CatalogEntry[];\n notes: FeedNote[];\n}> {\n const notes: FeedNote[] = [];\n try {\n const { resolveCatalogSource } = await import(\"./open-library.ts\");\n const { source, close } = await resolveCatalogSource({ projectDir });\n try {\n const assets = await source.listAssets();\n const entries: CatalogEntry[] = assets.map((a) => ({\n name: a.name,\n kind: (a.kind as AssetKind) ?? \"skill\",\n description: a.description ?? \"\",\n source: `store://${a.id}`,\n publisher: a.publisher,\n repo: a.repo,\n plugin: a.plugin,\n category: a.category,\n version: a.version,\n requires: [],\n dependencies: [],\n }));\n return { entries, notes };\n } finally {\n close();\n }\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n // Local-only catalog throws a recognizable message — silence it; absence\n // is the user's choice, not an error.\n if (!/local/i.test(msg)) {\n notes.push({ feed: \"store\", message: msg });\n }\n return { entries: [], notes };\n }\n}\n\n/** The slice of `AssetManager` the source feed needs (kept narrow for tests). */\ninterface AssetManagerLike {\n search: () => Promise<CatalogEntry[]>;\n searchRepoRoots: () => { repoName: string; root: string }[];\n}\n\n/**\n * Project-source feed: leans on `AssetManager.search()`, which merges\n * `skaile.yaml`'s `sources:` field into the repositories map. Plugin grouping\n * (`entry.plugin`) is stamped by the scanner, so entries pass through as-is.\n */\nasync function sourceAssets(am: AssetManagerLike): Promise<OriginEntry[]> {\n // The bundled factory tree is injected into the repositories map as an implicit\n // source, so `am.search()` returns it too. It has its own `factory` origin band,\n // so drop it here — otherwise the same first-party skills list twice under Sources.\n const factoryPrefixes = factoryAssetRoots().map((r) => (r.endsWith(path.sep) ? r : r + path.sep));\n const isFactoryPath = (p: string) =>\n factoryPrefixes.some((fp) => p === fp.slice(0, -1) || p.startsWith(fp));\n\n const all = (await am.search()).filter((e) => !isFactoryPath(e.source));\n const entries: OriginEntry[] = [];\n // Group each source's entries under the source node (its short repo name), not\n // the publisher: under Sources the navigational question is \"which repo did\n // this come from\". Each entry's `source` (absolute manifest path) lives under\n // exactly one declared root, so group by prefix. The cache slug is\n // URL-keyed `github.com/<org>/<repo>` — take the trailing segment.\n for (const { repoName, root } of am.searchRepoRoots()) {\n if (isFactoryPath(root)) continue;\n const prefix = root.endsWith(path.sep) ? root : root + path.sep;\n const owned = all.filter((e) => e.source === root || e.source.startsWith(prefix));\n if (owned.length === 0) continue;\n const sourceName = repoName.split(\"/\").pop() || repoName;\n for (const entry of owned) entries.push({ origin: \"source\", entry, group: sourceName });\n }\n return entries;\n}\n\n/**\n * Factory-asset feed: scan the bundled first-party `factory-assets` tree(s)\n * resolved by `factoryAssetRoots()` (the `SKAILE_FACTORY_ASSETS_DIR` override\n * layer ahead of the bundled tree). Local disk only, no network — the entries are\n * the built-in skills / connectors / bundles that ship with `@skaile/workspaces`.\n * `factoryAssetRoots()` already dedupes, so the env override pointing at the\n * bundled dir collapses to one root.\n */\nasync function factoryAssets(): Promise<{\n entries: CatalogEntry[];\n notes: FeedNote[];\n}> {\n const notes: FeedNote[] = [];\n try {\n const entries: CatalogEntry[] = [];\n for (const root of factoryAssetRoots()) {\n entries.push(...(await scanRepo(root, \"skaile-factory\")));\n }\n return { entries, notes };\n } catch (err) {\n notes.push({\n feed: \"factory\",\n message: err instanceof Error ? err.message : String(err),\n });\n return { entries: [], notes };\n }\n}\n\n/** Tag a flat entry list with a single origin. */\nfunction tag(origin: AssetOrigin, entries: CatalogEntry[]): OriginEntry[] {\n return entries.map((entry) => ({ origin, entry }));\n}\n\n/**\n * Run all feeds and return a single normalized result.\n *\n * Feeds run in parallel where possible — the store fetch is the slow one\n * (one HTTP call) and is fired alongside the local library walk. The factory\n * scan is local disk only, so it runs inline.\n */\nexport async function gatherAssetFeeds(\n am: AssetManagerLike,\n projectDir: string,\n): Promise<AssetFeedResult> {\n const [libs, store] = await Promise.all([libraryAssets(), storeAssets(projectDir)]);\n const factory = await factoryAssets();\n const src = await sourceAssets(am);\n return {\n entries: [\n ...src,\n ...libs.entries,\n ...tag(\"factory\", factory.entries),\n ...tag(\"store\", store.entries),\n ],\n notes: [...libs.notes, ...store.notes, ...factory.notes],\n };\n}\n"]}
1
+ {"version":3,"sources":["../cli/src/asset-feeds.ts"],"names":[],"mappings":"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","file":"asset-feeds-C4X4RTZV.js","sourcesContent":["/**\n * asset-feeds.ts — gather installable assets from every feed the manage TUI\n * surfaces.\n *\n * Four feeds, normalized into `CatalogEntry`:\n * - **Project sources** — `skaile.yaml` `sources:` entries (scanned via\n * `AssetManager.search()`; the new `sources:` field is merged into the\n * legacy repositories map in `AssetManager.loadConfig`).\n * - **Local libraries** — user authoring places from `LocalIndex` (filesystem\n * scan of each library's `path`).\n * - **Factory assets** — the bundled first-party `factory-assets` tree\n * (`factoryAssetRoots()`), scanned from disk. Always present; no network.\n * - **Remote store** — the configured catalog source when `catalog.url` is\n * not `local`. Failures are non-fatal — they surface as notes.\n */\n\nimport { existsSync } from \"node:fs\";\nimport * as path from \"node:path\";\nimport {\n type AssetKind,\n type CatalogEntry,\n factoryAssetRoots,\n scanRepo,\n} from \"@skaile/workspaces/core\";\n\n/** One non-fatal note returned to the caller for surfacing in the UI. */\nexport interface FeedNote {\n feed: \"sources\" | \"libraries\" | \"store\" | \"factory\";\n message: string;\n}\n\n/**\n * Which feed an asset came from. This is the top-level grouping axis in the\n * manage TUI (\"where is this skill coming from?\") and is intentionally distinct\n * from `publisher` (asset-intrinsic identity): the same publisher can legitimately\n * appear under more than one origin (e.g. a github repo you added as a `source`\n * that is also listed in the remote `store`).\n */\nexport type AssetOrigin = \"source\" | \"library\" | \"factory\" | \"store\";\n\n/** A catalog entry tagged with the feed it was gathered from. */\nexport interface OriginEntry {\n origin: AssetOrigin;\n entry: CatalogEntry;\n /**\n * Second-level grouping label for the manage tree. Defaults (when unset) to the\n * entry's `publisher`; the source feed sets it to the source's short repo name\n * so the Sources band groups by source — \"which repo did this come from\" — not\n * by the asset-intrinsic publisher.\n */\n group?: string;\n}\n\nexport interface AssetFeedResult {\n entries: OriginEntry[];\n notes: FeedNote[];\n}\n\n/**\n * Pull assets from local libraries (the authoring places under\n * `~/.skaile/libraries/<name>/`, not the `~/.skaile/cache/sources/` cache). Each\n * library's `path` is scanned with `scanRepo` and grouped under the bare library\n * name (`group: <name>`) so the manage TUI shows a clean `<name>` band — no\n * `library:` prefix (mirrors the source feed). Plugin grouping (`entry.plugin`)\n * is stamped by `scanRepo`.\n */\nasync function libraryAssets(): Promise<{\n entries: OriginEntry[];\n notes: FeedNote[];\n}> {\n const notes: FeedNote[] = [];\n try {\n const { openLibraryManager, authoringLibraries } = await import(\"./open-library.ts\");\n const { manager, close } = await openLibraryManager();\n try {\n // Authoring libraries are the rows that are NOT source clones.\n const libs = authoringLibraries(await manager.listLibraries());\n const entries: OriginEntry[] = [];\n for (const lib of libs) {\n if (!existsSync(lib.path)) continue;\n const libEntries = [...(await scanRepo(lib.path, lib.name))];\n for (const entry of libEntries) entries.push({ origin: \"library\", entry, group: lib.name });\n }\n return { entries, notes };\n } finally {\n close();\n }\n } catch (err) {\n notes.push({\n feed: \"libraries\",\n message: err instanceof Error ? err.message : String(err),\n });\n return { entries: [], notes };\n }\n}\n\n/**\n * Pull a (best-effort) snapshot of the connected remote store catalog.\n *\n * - Returns no entries when the resolved catalog is local-only or the host\n * is unreachable (the failure becomes a note, not an exception).\n * - Maps `CatalogAsset` → `CatalogEntry`, carrying `publisher`, `repo`, and\n * `category` straight through and using `source = \"store://<id>\"`; per-file\n * `source` paths are not available for remote assets so the canonical ref is\n * a stable placeholder.\n */\nasync function storeAssets(projectDir: string): Promise<{\n entries: CatalogEntry[];\n notes: FeedNote[];\n}> {\n const notes: FeedNote[] = [];\n try {\n const { resolveCatalogSource } = await import(\"./open-library.ts\");\n const { source, close } = await resolveCatalogSource({ projectDir });\n try {\n const assets = await source.listAssets();\n const entries: CatalogEntry[] = assets.map((a) => ({\n name: a.name,\n kind: (a.kind as AssetKind) ?? \"skill\",\n description: a.description ?? \"\",\n source: `store://${a.id}`,\n publisher: a.publisher,\n repo: a.repo,\n plugin: a.plugin,\n category: a.category,\n version: a.version,\n requires: [],\n dependencies: [],\n }));\n return { entries, notes };\n } finally {\n close();\n }\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n // Local-only catalog throws a recognizable message — silence it; absence\n // is the user's choice, not an error.\n if (!/local/i.test(msg)) {\n notes.push({ feed: \"store\", message: msg });\n }\n return { entries: [], notes };\n }\n}\n\n/** The slice of `AssetManager` the source feed needs (kept narrow for tests). */\ninterface AssetManagerLike {\n search: () => Promise<CatalogEntry[]>;\n searchRepoRoots: () => { repoName: string; root: string }[];\n}\n\n/**\n * Project-source feed: leans on `AssetManager.search()`, which merges\n * `skaile.yaml`'s `sources:` field into the repositories map. Plugin grouping\n * (`entry.plugin`) is stamped by the scanner, so entries pass through as-is.\n */\nasync function sourceAssets(am: AssetManagerLike): Promise<OriginEntry[]> {\n // The bundled factory tree is injected into the repositories map as an implicit\n // source, so `am.search()` returns it too. It has its own `factory` origin band,\n // so drop it here — otherwise the same first-party skills list twice under Sources.\n const factoryPrefixes = factoryAssetRoots().map((r) => (r.endsWith(path.sep) ? r : r + path.sep));\n const isFactoryPath = (p: string) =>\n factoryPrefixes.some((fp) => p === fp.slice(0, -1) || p.startsWith(fp));\n\n const all = (await am.search()).filter((e) => !isFactoryPath(e.source));\n const entries: OriginEntry[] = [];\n // Group each source's entries under the source node (its short repo name), not\n // the publisher: under Sources the navigational question is \"which repo did\n // this come from\". Each entry's `source` (absolute manifest path) lives under\n // exactly one declared root, so group by prefix. The cache slug is\n // URL-keyed `github.com/<org>/<repo>` — take the trailing segment.\n for (const { repoName, root } of am.searchRepoRoots()) {\n if (isFactoryPath(root)) continue;\n const prefix = root.endsWith(path.sep) ? root : root + path.sep;\n const owned = all.filter((e) => e.source === root || e.source.startsWith(prefix));\n if (owned.length === 0) continue;\n const sourceName = repoName.split(\"/\").pop() || repoName;\n for (const entry of owned) entries.push({ origin: \"source\", entry, group: sourceName });\n }\n return entries;\n}\n\n/**\n * Factory-asset feed: scan the bundled first-party `factory-assets` tree(s)\n * resolved by `factoryAssetRoots()` (the `SKAILE_FACTORY_ASSETS_DIR` override\n * layer ahead of the bundled tree). Local disk only, no network — the entries are\n * the built-in skills / connectors / bundles that ship with `@skaile/workspaces`.\n * `factoryAssetRoots()` already dedupes, so the env override pointing at the\n * bundled dir collapses to one root.\n */\nasync function factoryAssets(): Promise<{\n entries: CatalogEntry[];\n notes: FeedNote[];\n}> {\n const notes: FeedNote[] = [];\n try {\n const entries: CatalogEntry[] = [];\n for (const root of factoryAssetRoots()) {\n entries.push(...(await scanRepo(root, \"skaile-factory\")));\n }\n return { entries, notes };\n } catch (err) {\n notes.push({\n feed: \"factory\",\n message: err instanceof Error ? err.message : String(err),\n });\n return { entries: [], notes };\n }\n}\n\n/** Tag a flat entry list with a single origin. */\nfunction tag(origin: AssetOrigin, entries: CatalogEntry[]): OriginEntry[] {\n return entries.map((entry) => ({ origin, entry }));\n}\n\n/**\n * Run all feeds and return a single normalized result.\n *\n * Feeds run in parallel where possible — the store fetch is the slow one\n * (one HTTP call) and is fired alongside the local library walk. The factory\n * scan is local disk only, so it runs inline.\n */\nexport async function gatherAssetFeeds(\n am: AssetManagerLike,\n projectDir: string,\n): Promise<AssetFeedResult> {\n const [libs, store] = await Promise.all([libraryAssets(), storeAssets(projectDir)]);\n const factory = await factoryAssets();\n const src = await sourceAssets(am);\n return {\n entries: [\n ...src,\n ...libs.entries,\n ...tag(\"factory\", factory.entries),\n ...tag(\"store\", store.entries),\n ],\n notes: [...libs.notes, ...store.notes, ...factory.notes],\n };\n}\n"]}
@@ -1,4 +1,4 @@
1
- export { AssetManager, FACTORY_SOURCE_URL, MissingManifestError, NON_DEPLOYABLE_KINDS, normalizeRepoUrl, parseCanonicalLockKey, parseRefTolerant, renderMcpServerConfig, softDepName } from '../chunk-YJACHPI7.js';
1
+ export { AssetManager, FACTORY_SOURCE_URL, MissingManifestError, NON_DEPLOYABLE_KINDS, normalizeRepoUrl, parseCanonicalLockKey, parseRefTolerant, renderMcpServerConfig, softDepName } from '../chunk-BEOKEK3B.js';
2
2
  import '../chunk-SP47UJKE.js';
3
3
  import '../chunk-UVOJSWD2.js';
4
4
  import '../chunk-H4EGUQ7M.js';
@@ -2,10 +2,10 @@ import { formatDroppedToolsNotice, filterInProcessMcpServerTools, checkToolPrope
2
2
  import { scrubPoisonedTranscript, transcriptStoreForRuntime, resolveClaudeConfigDir, claudeEndpointMode, buildClaudeEndpointEnv } from '../../chunk-TVOODIZE.js';
3
3
  import { scopeReconfigureModel } from '../../chunk-EINLFFP6.js';
4
4
  import { dispatchCapability } from '../../chunk-RDYI4MML.js';
5
- import { fetchProviderModels } from '../../chunk-P5UQ56RA.js';
5
+ import { fetchProviderModels } from '../../chunk-KVAI5DGL.js';
6
6
  import { AuthError, stripRunnerPrivateEnv, classifyClaudeSdkError, reclassifyAuthAsAccountUnavailable, AccountUnavailableError, isLongContextEntitlementRejection, LONG_CONTEXT_CREDITS_API_ERROR } from '../../chunk-XBSQ4KMC.js';
7
7
  import { agentExecRequested, wrapAgentCommand, resolveAgentExec } from '../../chunk-YROR332M.js';
8
- import { BUILTIN_DRIVER_CATALOG, AgentDriver, getBridgeLogger, entryCredentialValue, registryDriverConfig } from '../../chunk-RDTHJSGY.js';
8
+ import { BUILTIN_DRIVER_CATALOG, AgentDriver, getBridgeLogger, entryCredentialValue, registryDriverConfig } from '../../chunk-ZD7CX25M.js';
9
9
  import '../../chunk-6E6PKKAD.js';
10
10
  import { withActivityLabelShape } from '../../chunk-IDEA6CYI.js';
11
11
  import '../../chunk-IWCCZL7C.js';
@@ -414,6 +414,43 @@ var MODEL_USAGE_COUNTERS = [
414
414
  ["cacheCreationTokens", "cacheCreationInputTokens"],
415
415
  ["costUsd", "costUSD"]
416
416
  ];
417
+ var USAGE_COUNTERS = [
418
+ "inputTokens",
419
+ "outputTokens",
420
+ "cacheReadTokens",
421
+ "cacheCreationTokens",
422
+ "reasoningTokens",
423
+ "totalTokens"
424
+ ];
425
+ function addTokens(a, b) {
426
+ const sum = { ...a, ...b };
427
+ for (const key of USAGE_COUNTERS) {
428
+ if (typeof a[key] === "number" && typeof b[key] === "number") {
429
+ sum[key] = a[key] + b[key];
430
+ }
431
+ }
432
+ return sum;
433
+ }
434
+ function addAttemptUsage(event, earlier) {
435
+ const out = {};
436
+ if (typeof event.costUsd === "number" || typeof earlier.costUsd === "number") {
437
+ out.costUsd = (event.costUsd ?? 0) + (earlier.costUsd ?? 0);
438
+ }
439
+ if (event.tokens || earlier.tokens)
440
+ out.tokens = addTokens(event.tokens ?? {}, earlier.tokens ?? {});
441
+ if (event.modelUsage || earlier.modelUsage) {
442
+ const merged = { ...event.modelUsage };
443
+ for (const [model, usage] of Object.entries(earlier.modelUsage ?? {})) {
444
+ const current = merged[model];
445
+ merged[model] = current ? {
446
+ ...addTokens(current, usage),
447
+ ...typeof current.costUsd === "number" || typeof usage.costUsd === "number" ? { costUsd: (current.costUsd ?? 0) + (usage.costUsd ?? 0) } : {}
448
+ } : usage;
449
+ }
450
+ out.modelUsage = merged;
451
+ }
452
+ return out;
453
+ }
417
454
  function diffModelUsage(current, previous) {
418
455
  const out = {};
419
456
  for (const [model, usage] of Object.entries(current)) {
@@ -617,6 +654,18 @@ var ClaudeSdkDriver = class extends AgentDriver {
617
654
  * promise) rather than also drawing the runner's fatal "prompt failed".
618
655
  */
619
656
  limitTurnRejectedForFailover = false;
657
+ /**
658
+ * The error `result` of an attempt rejected for a seat failover, held back
659
+ * like the error event: a host normalizes it into a fatal "Agent stopped"
660
+ * error, which a replayed turn must not show. Emitted only if the turn is
661
+ * not replayed after all.
662
+ */
663
+ heldFailoverResult = null;
664
+ /**
665
+ * What a replayed failover attempt billed. Its `result` is dropped, so the
666
+ * replay's own `result` carries this too; seat A's spend is otherwise lost.
667
+ */
668
+ failoverUsageCarry = null;
620
669
  /**
621
670
  * Whether this attempt already reported a provider rejection. One upstream
622
671
  * failure routinely reaches the driver twice — `rejected` telemetry followed
@@ -896,12 +945,14 @@ var ClaudeSdkDriver = class extends AgentDriver {
896
945
  this.longContextRejectionLogged = false;
897
946
  this.lastLimitInfo = null;
898
947
  this.deferredTurnError = null;
948
+ this.heldFailoverResult = null;
899
949
  let retrying = false;
900
950
  const isFirstAttempt = !_budget.staleResume && !_budget.poison && !_budget.auth && !_budget.queryEnded && !_budget.limit;
901
951
  if (isFirstAttempt) {
902
952
  this._lastTokens = null;
903
953
  this._lastContextTokens = null;
904
954
  this._lastModelUsage = null;
955
+ this.failoverUsageCarry = null;
905
956
  }
906
957
  this.running = true;
907
958
  this.prevText = "";
@@ -969,9 +1020,13 @@ var ClaudeSdkDriver = class extends AgentDriver {
969
1020
  if (await this.attemptLimitFailover(err)) {
970
1021
  if (this.abortController?.signal.aborted) {
971
1022
  this.log.info("aborted during the seat failover; not replaying the prompt");
1023
+ this.emitHeldFailoverResult();
972
1024
  this.emitAgentEnd();
973
1025
  return;
974
1026
  }
1027
+ const held = this.heldFailoverResult;
1028
+ if (held) this.failoverUsageCarry = addAttemptUsage(held, this.failoverUsageCarry ?? {});
1029
+ this.heldFailoverResult = null;
975
1030
  this.retractUnfinishedText();
976
1031
  retrying = true;
977
1032
  return this.runPrompt(message, { ..._budget, limit: true });
@@ -994,6 +1049,8 @@ var ClaudeSdkDriver = class extends AgentDriver {
994
1049
  this.limitTurnRejectedForFailover = false;
995
1050
  this.lastLimitInfo = null;
996
1051
  this.deferredTurnError = null;
1052
+ this.heldFailoverResult = null;
1053
+ this.failoverUsageCarry = null;
997
1054
  this.suppressedAuthRenderText = null;
998
1055
  this.lastApiErrorRender = null;
999
1056
  }
@@ -1456,6 +1513,7 @@ var ClaudeSdkDriver = class extends AgentDriver {
1456
1513
  this.log.info("no alternative AI provider config available; surfacing the limit error", {
1457
1514
  reason: outcome?.reason
1458
1515
  });
1516
+ this.emitHeldFailoverResult();
1459
1517
  const detail = err?.detail;
1460
1518
  this.emitDeferredTurnError({
1461
1519
  type: "error",
@@ -2222,6 +2280,26 @@ var ClaudeSdkDriver = class extends AgentDriver {
2222
2280
  });
2223
2281
  }
2224
2282
  }
2283
+ /** Fold a replayed failover attempt's usage into the `result` that ends the turn, once. */
2284
+ withFailoverUsage(event) {
2285
+ const carry = this.failoverUsageCarry;
2286
+ if (!carry) return event;
2287
+ this.failoverUsageCarry = null;
2288
+ return { ...event, ...addAttemptUsage(event, carry) };
2289
+ }
2290
+ /** Emit the result {@link handleErrorResult} held for a failover that did not replay. */
2291
+ emitHeldFailoverResult() {
2292
+ const event = this.heldFailoverResult;
2293
+ this.heldFailoverResult = null;
2294
+ if (!event) return;
2295
+ try {
2296
+ this.emit("agent-event", event);
2297
+ } catch (emitErr) {
2298
+ this.log.warn("agent-event listener threw while surfacing a held result; suppressing", {
2299
+ error: emitErr instanceof Error ? emitErr.message : String(emitErr)
2300
+ });
2301
+ }
2302
+ }
2225
2303
  /**
2226
2304
  * Emit the error {@link failTurn} withheld, exactly once. Called by a
2227
2305
  * recovery path that decided NOT to retry, so every failure produces one
@@ -2613,14 +2691,17 @@ var ClaudeSdkDriver = class extends AgentDriver {
2613
2691
  };
2614
2692
  this.emit("agent-event", { type: "message_end", message: agentMsg });
2615
2693
  }
2616
- this.emit("agent-event", {
2617
- type: "result",
2618
- subtype: msg.subtype,
2619
- summary: result ?? "Task completed",
2620
- costUsd: this._lastTurnCostUsd,
2621
- ...this._lastTokens ? { tokens: this._lastTokens } : {},
2622
- ...this.turnUsageFields()
2623
- });
2694
+ this.emit(
2695
+ "agent-event",
2696
+ this.withFailoverUsage({
2697
+ type: "result",
2698
+ subtype: msg.subtype,
2699
+ summary: result ?? "Task completed",
2700
+ costUsd: this._lastTurnCostUsd,
2701
+ ...this._lastTokens ? { tokens: this._lastTokens } : {},
2702
+ ...this.turnUsageFields()
2703
+ })
2704
+ );
2624
2705
  }
2625
2706
  /**
2626
2707
  * Handle the non-clean branch (legacy `SDKResultError`, or a `success`
@@ -2632,14 +2713,19 @@ var ClaudeSdkDriver = class extends AgentDriver {
2632
2713
  const looseMsg = msg;
2633
2714
  const errors = looseMsg.errors?.length ? looseMsg.errors : [];
2634
2715
  if (looseMsg.is_error && this.handleResultErrorPayload(msg, errors)) return;
2635
- this.emit("agent-event", {
2716
+ const resultEvent = {
2636
2717
  type: "result",
2637
2718
  subtype: msg.subtype,
2638
2719
  errors,
2639
2720
  ...this._lastCostReported ? { costUsd: this._lastTurnCostUsd } : {},
2640
2721
  ...this._lastTokens ? { tokens: this._lastTokens } : {},
2641
2722
  ...this.turnUsageFields()
2642
- });
2723
+ };
2724
+ if (this.limitTurnRejectedForFailover) {
2725
+ this.heldFailoverResult = resultEvent;
2726
+ } else {
2727
+ this.emit("agent-event", this.withFailoverUsage(resultEvent));
2728
+ }
2643
2729
  const awaitingFollowUpThrow = looseMsg.is_error === true && errors.length === 0;
2644
2730
  if (!this.turnCompleted && !awaitingFollowUpThrow) {
2645
2731
  this.completeTurn();