@crewx/sdk 0.8.0-rc.80 → 0.8.0-rc.82

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 (217) hide show
  1. package/dist/__tests__/adapter/context-builder.test.d.ts +1 -0
  2. package/dist/__tests__/adapter/plugin-helper.test.d.ts +1 -0
  3. package/dist/__tests__/adapter/registration-integration.test.d.ts +1 -0
  4. package/dist/__tests__/adapter/scoped-store.test.d.ts +1 -0
  5. package/dist/__tests__/plugins/conversation.test.d.ts +1 -0
  6. package/dist/__tests__/testing/createMockContext.test.d.ts +1 -0
  7. package/dist/adapter/context-builder.d.ts +0 -9
  8. package/dist/adapter/index.d.ts +0 -1
  9. package/dist/adapter/plugin-helper.d.ts +0 -7
  10. package/dist/adapter/scoped-store.d.ts +0 -10
  11. package/dist/adapter/types.d.ts +0 -7
  12. package/dist/agent/resolver.d.ts +0 -13
  13. package/dist/boxing/box-storage.interface.d.ts +0 -4
  14. package/dist/boxing/box.service.d.ts +0 -4
  15. package/dist/boxing/box.types.d.ts +0 -4
  16. package/dist/boxing/context-builder.d.ts +0 -4
  17. package/dist/client/CrewxClient.d.ts +0 -32
  18. package/dist/client/index.d.ts +0 -1
  19. package/dist/client/index.js +1 -6
  20. package/dist/config/loader.browser.d.ts +0 -8
  21. package/dist/config/loader.d.ts +0 -12
  22. package/dist/conversation/__tests__/sqlite-provider.test.d.ts +1 -0
  23. package/dist/conversation/__tests__/to-task-reader.test.d.ts +1 -0
  24. package/dist/conversation/index.d.ts +0 -1
  25. package/dist/conversation/sqlite-provider.d.ts +0 -9
  26. package/dist/conversation/to-task-reader.d.ts +0 -11
  27. package/dist/conversation/to-template-messages.d.ts +0 -13
  28. package/dist/conversation/types.d.ts +0 -58
  29. package/dist/esm/client/index.js +1 -0
  30. package/dist/esm/hooks/index.js +7 -0
  31. package/dist/esm/index.js +79 -0
  32. package/dist/esm/plugins/index.js +52 -0
  33. package/dist/esm/testing/index.js +1 -0
  34. package/dist/esm/tools/node/index.js +36 -0
  35. package/dist/events/TypedEventEmitter.d.ts +0 -24
  36. package/dist/events/types.d.ts +0 -43
  37. package/dist/facade/Crewx.browser.d.ts +0 -40
  38. package/dist/facade/Crewx.d.ts +0 -163
  39. package/dist/hooks/define.d.ts +0 -1
  40. package/dist/hooks/dispatch.d.ts +0 -12
  41. package/dist/hooks/index.d.ts +0 -1
  42. package/dist/hooks/index.js +7 -24
  43. package/dist/hooks/observer.d.ts +0 -1
  44. package/dist/hooks/plugin.d.ts +0 -1
  45. package/dist/hooks/tool-normalize.d.ts +0 -26
  46. package/dist/hooks/types.d.ts +0 -1
  47. package/dist/hooks/yaml-plugin.d.ts +0 -1
  48. package/dist/index.browser.d.ts +0 -7
  49. package/dist/index.browser.js +2 -25
  50. package/dist/index.d.ts +0 -4
  51. package/dist/index.js +79 -151
  52. package/dist/layout/loader.d.ts +0 -20
  53. package/dist/layout/props-validator.d.ts +0 -6
  54. package/dist/layout/renderer.d.ts +0 -24
  55. package/dist/layout/types.d.ts +0 -42
  56. package/dist/parallel/agent-runtime.d.ts +0 -11
  57. package/dist/parallel/helpers.d.ts +0 -1
  58. package/dist/parallel/index.d.ts +0 -1
  59. package/dist/parallel/parallel-runner.d.ts +0 -8
  60. package/dist/parallel/types.d.ts +0 -24
  61. package/dist/parsers/agent-call.util.d.ts +0 -3
  62. package/dist/parsers/claude.parser.d.ts +0 -8
  63. package/dist/parsers/codex.parser.d.ts +0 -8
  64. package/dist/parsers/copilot.parser.d.ts +0 -9
  65. package/dist/parsers/gemini.parser.d.ts +0 -10
  66. package/dist/parsers/opencode.parser.d.ts +0 -10
  67. package/dist/parsers/router.d.ts +0 -5
  68. package/dist/paths.d.ts +1 -0
  69. package/dist/platform/BrowserFsAdapter.d.ts +0 -20
  70. package/dist/platform/IFsAdapter.d.ts +0 -23
  71. package/dist/platform/NodeFsAdapter.d.ts +0 -8
  72. package/dist/plugin/plugin-provider.d.ts +0 -22
  73. package/dist/plugin/types.d.ts +0 -31
  74. package/dist/plugin.d.ts +0 -27
  75. package/dist/plugins/conversation.d.ts +0 -2
  76. package/dist/plugins/file-logger.d.ts +0 -13
  77. package/dist/plugins/index.d.ts +0 -10
  78. package/dist/plugins/index.js +52 -19
  79. package/dist/plugins/sqlite-tracing.d.ts +0 -13
  80. package/dist/plugins/sqlite-tracing.spec.d.ts +1 -0
  81. package/dist/provider/bridge.browser.d.ts +0 -20
  82. package/dist/provider/bridge.d.ts +0 -47
  83. package/dist/provider/parse-usage.d.ts +0 -14
  84. package/dist/provider/register-api.d.ts +0 -7
  85. package/dist/provider/vercel-runtime.d.ts +0 -29
  86. package/dist/remote/index.d.ts +0 -6
  87. package/dist/remote/remote-agent-manager.d.ts +0 -31
  88. package/dist/remote/remote-provider.d.ts +0 -15
  89. package/dist/remote/remote-transport.d.ts +0 -17
  90. package/dist/remote/types.d.ts +0 -59
  91. package/dist/server/auth.d.ts +0 -16
  92. package/dist/server/handler.d.ts +0 -17
  93. package/dist/server/index.d.ts +0 -4
  94. package/dist/server/tool-adapter.d.ts +0 -16
  95. package/dist/template/engine.d.ts +0 -19
  96. package/dist/template/helpers/exec.browser.d.ts +0 -7
  97. package/dist/template/helpers/exec.d.ts +0 -45
  98. package/dist/template/helpers/fenced_code.d.ts +0 -16
  99. package/dist/template/helpers/format-conversation.d.ts +0 -22
  100. package/dist/template/helpers/include.d.ts +0 -15
  101. package/dist/template/helpers/p1p2.d.ts +0 -32
  102. package/dist/template/loader/DocumentLoader.d.ts +0 -30
  103. package/dist/template/types.d.ts +0 -30
  104. package/dist/testing/index.d.ts +0 -1
  105. package/dist/testing/index.js +1 -16
  106. package/dist/testing/mock-audit.d.ts +0 -1
  107. package/dist/testing/mock-context.d.ts +0 -1
  108. package/dist/testing/mock-logger.d.ts +0 -1
  109. package/dist/testing/mock-router.d.ts +0 -1
  110. package/dist/testing/mock-storage.d.ts +0 -1
  111. package/dist/testing/mock-store.d.ts +0 -1
  112. package/dist/tools/delegate.d.ts +0 -7
  113. package/dist/tools/index.d.ts +0 -4
  114. package/dist/tools/node/builtin.d.ts +0 -16
  115. package/dist/tools/node/index.d.ts +0 -20
  116. package/dist/tools/node/index.js +36 -59
  117. package/dist/types/index.d.ts +0 -20
  118. package/dist/types/task-log.types.d.ts +0 -4
  119. package/dist/utils/env-defaults.d.ts +0 -16
  120. package/dist/utils/glob-match.d.ts +0 -16
  121. package/dist/utils/id.d.ts +0 -15
  122. package/dist/utils/timestamp.d.ts +0 -1
  123. package/dist/utils/workspace.d.ts +0 -4
  124. package/package.json +24 -25
  125. package/dist/adapter/context-builder.js +0 -87
  126. package/dist/adapter/index.js +0 -21
  127. package/dist/adapter/plugin-helper.js +0 -45
  128. package/dist/adapter/scoped-store.js +0 -43
  129. package/dist/adapter/types.js +0 -23
  130. package/dist/agent/resolver.js +0 -46
  131. package/dist/boxing/box-storage.interface.js +0 -6
  132. package/dist/boxing/box.service.js +0 -73
  133. package/dist/boxing/box.types.js +0 -6
  134. package/dist/boxing/context-builder.js +0 -79
  135. package/dist/client/CrewxClient.js +0 -86
  136. package/dist/config/loader.browser.js +0 -59
  137. package/dist/config/loader.js +0 -95
  138. package/dist/conversation/index.js +0 -25
  139. package/dist/conversation/sqlite-provider.js +0 -178
  140. package/dist/conversation/to-task-reader.js +0 -28
  141. package/dist/conversation/to-template-messages.js +0 -34
  142. package/dist/conversation/types.js +0 -10
  143. package/dist/events/TypedEventEmitter.js +0 -65
  144. package/dist/events/types.js +0 -9
  145. package/dist/facade/Crewx.browser.js +0 -314
  146. package/dist/facade/Crewx.js +0 -1299
  147. package/dist/hooks/define.js +0 -13
  148. package/dist/hooks/dispatch.js +0 -147
  149. package/dist/hooks/observer.js +0 -60
  150. package/dist/hooks/plugin.js +0 -17
  151. package/dist/hooks/tool-normalize.js +0 -110
  152. package/dist/hooks/types.js +0 -12
  153. package/dist/hooks/yaml-plugin.js +0 -356
  154. package/dist/layout/loader.js +0 -305
  155. package/dist/layout/props-validator.js +0 -301
  156. package/dist/layout/renderer.js +0 -193
  157. package/dist/layout/types.js +0 -36
  158. package/dist/parallel/agent-runtime.js +0 -25
  159. package/dist/parallel/helpers.js +0 -219
  160. package/dist/parallel/index.js +0 -13
  161. package/dist/parallel/parallel-runner.js +0 -226
  162. package/dist/parallel/types.js +0 -6
  163. package/dist/parsers/agent-call.util.js +0 -19
  164. package/dist/parsers/claude.parser.js +0 -67
  165. package/dist/parsers/codex.parser.js +0 -100
  166. package/dist/parsers/copilot.parser.js +0 -66
  167. package/dist/parsers/gemini.parser.js +0 -46
  168. package/dist/parsers/opencode.parser.js +0 -76
  169. package/dist/parsers/router.js +0 -56
  170. package/dist/platform/BrowserFsAdapter.js +0 -84
  171. package/dist/platform/IFsAdapter.js +0 -3
  172. package/dist/platform/NodeFsAdapter.js +0 -38
  173. package/dist/plugin/plugin-provider.js +0 -207
  174. package/dist/plugin/types.js +0 -9
  175. package/dist/plugin.js +0 -29
  176. package/dist/plugins/conversation.js +0 -59
  177. package/dist/plugins/file-logger.js +0 -87
  178. package/dist/plugins/sqlite-tracing.js +0 -112
  179. package/dist/provider/bridge.browser.js +0 -49
  180. package/dist/provider/bridge.js +0 -381
  181. package/dist/provider/parse-usage.js +0 -83
  182. package/dist/provider/register-api.js +0 -24
  183. package/dist/provider/vercel-runtime.js +0 -347
  184. package/dist/remote/index.js +0 -32
  185. package/dist/remote/remote-agent-manager.js +0 -198
  186. package/dist/remote/remote-provider.js +0 -141
  187. package/dist/remote/remote-transport.js +0 -83
  188. package/dist/remote/types.js +0 -9
  189. package/dist/server/auth.js +0 -35
  190. package/dist/server/handler.js +0 -75
  191. package/dist/server/index.js +0 -9
  192. package/dist/server/tool-adapter.js +0 -95
  193. package/dist/template/engine.js +0 -137
  194. package/dist/template/helpers/exec.browser.js +0 -41
  195. package/dist/template/helpers/exec.js +0 -230
  196. package/dist/template/helpers/fenced_code.js +0 -20
  197. package/dist/template/helpers/format-conversation.js +0 -53
  198. package/dist/template/helpers/include.js +0 -23
  199. package/dist/template/helpers/p1p2.js +0 -90
  200. package/dist/template/loader/DocumentLoader.js +0 -128
  201. package/dist/template/types.js +0 -6
  202. package/dist/testing/mock-audit.js +0 -13
  203. package/dist/testing/mock-context.js +0 -68
  204. package/dist/testing/mock-logger.js +0 -27
  205. package/dist/testing/mock-router.js +0 -67
  206. package/dist/testing/mock-storage.js +0 -21
  207. package/dist/testing/mock-store.js +0 -8
  208. package/dist/tools/delegate.js +0 -60
  209. package/dist/tools/index.js +0 -9
  210. package/dist/tools/node/builtin.js +0 -547
  211. package/dist/types/index.js +0 -32
  212. package/dist/types/task-log.types.js +0 -6
  213. package/dist/utils/env-defaults.js +0 -27
  214. package/dist/utils/glob-match.js +0 -42
  215. package/dist/utils/id.js +0 -50
  216. package/dist/utils/timestamp.js +0 -13
  217. package/dist/utils/workspace.js +0 -58
@@ -1,87 +0,0 @@
1
- "use strict";
2
- /**
3
- * FileLoggerPlugin — writes structured log files to .crewx/logs/.
4
- *
5
- * Subscribes to task:start and task:end events and writes one log file
6
- * per task execution. Format mirrors cli-bak TaskManagementService for
7
- * backward compatibility.
8
- *
9
- * File name: {YYYYMMDDTHHmmss}_{traceId}.log
10
- * e.g. 20260412T145044_tsk_AbCdEfGh.log
11
- */
12
- Object.defineProperty(exports, "__esModule", { value: true });
13
- exports.FileLoggerPlugin = void 0;
14
- const fs_1 = require("fs");
15
- const path_1 = require("path");
16
- const plugin_1 = require("../plugin");
17
- const timestamp_1 = require("../utils/timestamp");
18
- class FileLoggerPlugin extends plugin_1.CrewxPlugin {
19
- name = 'file-logger';
20
- unsubs = [];
21
- logFiles = new Map();
22
- logsDir;
23
- version;
24
- constructor(opts) {
25
- super();
26
- this.logsDir = (0, path_1.join)(opts?.workspaceRoot ?? process.cwd(), '.crewx', 'logs');
27
- this.version = opts?.version ?? 'unknown';
28
- }
29
- attach(crewx) {
30
- this.unsubs.push(crewx.on('task:start', (event) => {
31
- try {
32
- if (!(0, fs_1.existsSync)(this.logsDir)) {
33
- (0, fs_1.mkdirSync)(this.logsDir, { recursive: true });
34
- }
35
- const ts = (0, timestamp_1.formatTimestamp)(event.timestamp);
36
- const logFile = (0, path_1.join)(this.logsDir, `${ts}_${event.traceId}.log`);
37
- this.logFiles.set(event.traceId, logFile);
38
- const header = `=== TASK LOG: ${event.traceId} ===\n` +
39
- `CrewX Version: ${this.version}\n` +
40
- `Mode: ${event.mode}\n` +
41
- `Agent: ${event.agentRef}\n` +
42
- `Started: ${event.timestamp.toLocaleString()}\n` +
43
- `Message: ${event.message}\n` +
44
- `\n`;
45
- (0, fs_1.writeFileSync)(logFile, header, { encoding: 'utf8', mode: 0o600 });
46
- }
47
- catch {
48
- // Non-fatal: logging must never crash the main process
49
- }
50
- }), crewx.on('task:output', (event) => {
51
- try {
52
- const logFile = this.logFiles.get(event.traceId);
53
- if (!logFile)
54
- return;
55
- const ts = new Date().toISOString();
56
- (0, fs_1.appendFileSync)(logFile, `[${ts}] STDOUT: ${event.output}\n`, 'utf8');
57
- }
58
- catch {
59
- // Non-fatal
60
- }
61
- }), crewx.on('task:end', (event) => {
62
- try {
63
- const logFile = this.logFiles.get(event.traceId);
64
- if (!logFile)
65
- return;
66
- const ts = new Date().toLocaleString();
67
- const status = event.error
68
- ? `failed: ${event.error.message}`
69
- : 'completed successfully';
70
- const completion = `[${ts}] INFO: Task ${status} in ${event.durationMs}ms\n` +
71
- `[${ts}] INFO: Process closed with exit code: ${event.error ? 1 : 0}\n`;
72
- (0, fs_1.appendFileSync)(logFile, completion, 'utf8');
73
- this.logFiles.delete(event.traceId);
74
- }
75
- catch {
76
- // Non-fatal
77
- }
78
- }));
79
- }
80
- detach(_crewx) {
81
- this.unsubs.forEach(fn => fn());
82
- this.unsubs = [];
83
- this.logFiles.clear();
84
- }
85
- }
86
- exports.FileLoggerPlugin = FileLoggerPlugin;
87
- //# sourceMappingURL=file-logger.js.map
@@ -1,112 +0,0 @@
1
- "use strict";
2
- /**
3
- * SqliteTracingPlugin — records task execution data to ~/.crewx/crewx.db.
4
- *
5
- * Subscribes to task:start, task:output, and task:end events and persists
6
- * full records to the global CrewX SQLite database. Matches the schema
7
- * written by the global crewx CLI (0.8.x).
8
- *
9
- * DB location: {dbRoot}/.crewx/crewx.db
10
- * (dbRoot defaults to os.homedir())
11
- */
12
- var __importDefault = (this && this.__importDefault) || function (mod) {
13
- return (mod && mod.__esModule) ? mod : { "default": mod };
14
- };
15
- Object.defineProperty(exports, "__esModule", { value: true });
16
- exports.SqliteTracingPlugin = void 0;
17
- const fs_1 = require("fs");
18
- const path_1 = require("path");
19
- const os_1 = require("os");
20
- const better_sqlite3_1 = __importDefault(require("better-sqlite3"));
21
- const plugin_1 = require("../plugin");
22
- const workspace_1 = require("../utils/workspace");
23
- /** Detect host AI caller agent ID from environment (set by parent crewx process). */
24
- function detectCallerAgentId() {
25
- return process.env['CREWX_CALLER_AGENT_ID'] ?? null;
26
- }
27
- class SqliteTracingPlugin extends plugin_1.CrewxPlugin {
28
- name = 'sqlite-tracing';
29
- db = null;
30
- unsubs = [];
31
- dbPath;
32
- version;
33
- constructor(opts) {
34
- super();
35
- this.dbPath = (0, path_1.join)(opts?.dbRoot ?? (0, os_1.homedir)(), '.crewx', 'crewx.db');
36
- this.version = opts?.version ?? 'unknown';
37
- }
38
- attach(crewx) {
39
- // Ensure parent directory exists
40
- const dbDir = (0, path_1.dirname)(this.dbPath);
41
- if (!(0, fs_1.existsSync)(dbDir)) {
42
- (0, fs_1.mkdirSync)(dbDir, { recursive: true });
43
- }
44
- this.db = new better_sqlite3_1.default(this.dbPath);
45
- // Fallback workspace only when crewx.yaml/.yml exists in cwd — prevents phantom workspace entries
46
- const cwd = process.cwd();
47
- const yamlExists = (0, fs_1.existsSync)((0, path_1.join)(cwd, 'crewx.yaml')) || (0, fs_1.existsSync)((0, path_1.join)(cwd, 'crewx.yml'));
48
- const fallbackWorkspaceId = yamlExists ? (0, workspace_1.hashWorkspaceId)(cwd) : null;
49
- const fallbackWorkspaceName = yamlExists ? (0, path_1.basename)(cwd) : null;
50
- const callerAgentId = detectCallerAgentId();
51
- const command = process.argv.join(' ');
52
- this.unsubs.push(crewx.on('task:start', (event) => {
53
- try {
54
- const metadata = event.metadata
55
- ? JSON.stringify(event.metadata)
56
- : JSON.stringify({ provider: event.provider ?? 'cli/claude' });
57
- this.db.prepare(`INSERT OR IGNORE INTO tasks
58
- (id, agent_id, prompt, mode, status, pid, started_at,
59
- crewx_version, platform,
60
- model, rendered_prompt, command, coding_agent_command,
61
- workspace_id, workspace_name,
62
- caller_agent_id, trace_id, metadata, thread_id)
63
- VALUES (?, ?, ?, ?, 'running', ?, ?,
64
- ?, ?,
65
- ?, ?, ?, ?,
66
- ?, ?,
67
- ?, ?, ?, ?)`).run(event.traceId, event.agentRef.replace(/^@/, ''), event.message, event.mode, event.pid ?? null, event.timestamp.toISOString(), this.version, event.platform ?? 'cli', event.model ?? null, event.renderedPrompt ?? null, command, event.codingAgentCommand ?? null, event.workspaceId ?? fallbackWorkspaceId, event.workspaceName ?? fallbackWorkspaceName, callerAgentId, event.traceId, // trace_id mirrors the task id for root requests
68
- metadata, event.threadId ?? null);
69
- }
70
- catch {
71
- // Non-fatal: tracing must never crash the main process
72
- }
73
- }), crewx.on('task:output', (event) => {
74
- try {
75
- const row = this.db.prepare('SELECT logs FROM tasks WHERE id=?').get(event.traceId);
76
- const existing = row?.logs ? JSON.parse(row.logs) : [];
77
- existing.push({
78
- timestamp: event.timestamp.toISOString(),
79
- level: event.level ?? 'stdout',
80
- message: event.output,
81
- });
82
- this.db.prepare('UPDATE tasks SET logs=? WHERE id=?').run(JSON.stringify(existing), event.traceId);
83
- }
84
- catch {
85
- // Non-fatal
86
- }
87
- }), crewx.on('task:end', (event) => {
88
- try {
89
- const status = event.error ? 'failed' : 'success';
90
- this.db.prepare(`UPDATE tasks
91
- SET status=?, result=?, error=?,
92
- completed_at=?, duration_ms=?,
93
- exit_code=?,
94
- input_tokens=?, output_tokens=?, cached_input_tokens=?,
95
- cost_usd=?,
96
- model=COALESCE(?, model)
97
- WHERE id=?`).run(status, event.result ?? null, event.error ? JSON.stringify(event.error) : null, event.timestamp.toISOString(), event.durationMs, event.exitCode ?? null, event.inputTokens ?? 0, event.outputTokens ?? 0, event.cachedInputTokens ?? 0, event.costUsd ?? 0, event.model ?? null, event.traceId);
98
- }
99
- catch {
100
- // Non-fatal
101
- }
102
- }));
103
- }
104
- detach(_crewx) {
105
- this.unsubs.forEach(fn => fn());
106
- this.unsubs = [];
107
- this.db?.close();
108
- this.db = null;
109
- }
110
- }
111
- exports.SqliteTracingPlugin = SqliteTracingPlugin;
112
- //# sourceMappingURL=sqlite-tracing.js.map
@@ -1,49 +0,0 @@
1
- "use strict";
2
- /**
3
- * Browser-safe provider bridge.
4
- * Registry pattern only — no child_process / CLI spawn.
5
- */
6
- Object.defineProperty(exports, "__esModule", { value: true });
7
- exports.ProviderError = void 0;
8
- exports.registerProviderFactory = registerProviderFactory;
9
- exports.createProvider = createProvider;
10
- class ProviderError extends Error {
11
- providerStr;
12
- constructor(message, providerStr) {
13
- super(message);
14
- this.providerStr = providerStr;
15
- this.name = 'ProviderError';
16
- }
17
- }
18
- exports.ProviderError = ProviderError;
19
- // ── Provider factory registry ───────────────────────────────────────────────
20
- const _providerFactories = new Map();
21
- /**
22
- * Register a provider factory for a given namespace.
23
- *
24
- * @example
25
- * registerProviderFactory('api', (id, providerStr) => ({
26
- * async query(message, options) { ... },
27
- * async execute(message, options) { ... },
28
- * }));
29
- */
30
- function registerProviderFactory(namespace, factory) {
31
- _providerFactories.set(namespace, factory);
32
- }
33
- /**
34
- * Create a provider runtime for the given provider string.
35
- * Browser version — only supports registered factories (no CLI fallback).
36
- */
37
- function createProvider(providerStr) {
38
- const parts = providerStr.split('/');
39
- if (parts.length !== 2) {
40
- throw new ProviderError(`Invalid provider format: "${providerStr}". Expected namespace/id (e.g., api/webllm)`, providerStr);
41
- }
42
- const [namespace, id] = parts;
43
- const factory = _providerFactories.get(namespace);
44
- if (factory) {
45
- return factory(id, providerStr);
46
- }
47
- throw new ProviderError(`Unsupported provider namespace: "${namespace}". Register a factory with registerProviderFactory('${namespace}', factory).`, providerStr);
48
- }
49
- //# sourceMappingURL=bridge.browser.js.map
@@ -1,381 +0,0 @@
1
- "use strict";
2
- /**
3
- * Provider bridge: creates a runtime that can invoke AI providers.
4
- *
5
- * Supports a registry pattern — built-in cli/* providers are registered by default,
6
- * and additional namespaces (e.g. api/*, webllm/*) can be added via registerProviderFactory().
7
- */
8
- Object.defineProperty(exports, "__esModule", { value: true });
9
- exports.ClientToolCallRequiredError = exports.ProviderError = void 0;
10
- exports.parseStreamJsonOutput = parseStreamJsonOutput;
11
- exports.parseResultEventUsage = parseResultEventUsage;
12
- exports.registerProviderFactory = registerProviderFactory;
13
- exports.createProvider = createProvider;
14
- const child_process_1 = require("child_process");
15
- const parse_usage_js_1 = require("./parse-usage.js");
16
- function parseStreamJsonOutput(raw) {
17
- const lines = raw.split('\n').filter(l => l.trim());
18
- const assistantTexts = [];
19
- const geminiDeltaTokens = [];
20
- const copilotTexts = [];
21
- const codexTexts = [];
22
- const opencodeTexts = [];
23
- let resultText = null;
24
- for (const line of lines) {
25
- try {
26
- const parsed = JSON.parse(line);
27
- // Claude format: { type: 'assistant', message: { content: [...] } }
28
- if (parsed.type === 'assistant' && Array.isArray(parsed.message?.content)) {
29
- for (const block of parsed.message.content) {
30
- if (block.type === 'text' && typeof block.text === 'string' && block.text.trim()) {
31
- assistantTexts.push(block.text.trim());
32
- }
33
- }
34
- }
35
- // Gemini format: { type: 'message', role: 'assistant', delta: true, content: '...' }
36
- if (parsed.type === 'message' &&
37
- parsed.role === 'assistant' &&
38
- parsed.delta === true &&
39
- typeof parsed.content === 'string') {
40
- geminiDeltaTokens.push(parsed.content);
41
- }
42
- // Copilot format: { type: 'assistant.message', data: { content: '...' } }
43
- if (parsed.type === 'assistant.message' &&
44
- typeof parsed.data?.content === 'string') {
45
- const content = parsed.data.content;
46
- if (content.trim())
47
- copilotTexts.push(content.trim());
48
- }
49
- // Codex format: { type: 'item.completed', item: { type: 'message'|'agent_message', text: '...' } }
50
- // codex-specific: both 'message' and 'agent_message' item types are accepted
51
- if (parsed.type === 'item.completed' &&
52
- (parsed.item?.type === 'message' || parsed.item?.type === 'agent_message') &&
53
- typeof parsed.item?.text === 'string') {
54
- const text = parsed.item.text;
55
- if (text.trim())
56
- codexTexts.push(text.trim());
57
- }
58
- // OpenCode format: { type: 'text', part: { text: '...' } }
59
- if (parsed.type === 'text' && typeof parsed.part?.text === 'string') {
60
- const text = parsed.part.text;
61
- if (text.trim())
62
- opencodeTexts.push(text.trim());
63
- }
64
- if (parsed.type === 'result' && typeof parsed.result === 'string') {
65
- resultText = parsed.result;
66
- }
67
- }
68
- catch {
69
- // Not valid JSON line — skip
70
- }
71
- }
72
- if (assistantTexts.length > 0)
73
- return assistantTexts.join('\n\n');
74
- if (geminiDeltaTokens.length > 0)
75
- return geminiDeltaTokens.join('');
76
- if (copilotTexts.length > 0)
77
- return copilotTexts.join('\n\n');
78
- if (codexTexts.length > 0)
79
- return codexTexts.join('\n\n');
80
- if (opencodeTexts.length > 0)
81
- return opencodeTexts.join('');
82
- if (resultText)
83
- return resultText;
84
- return raw.trim();
85
- }
86
- function parseResultEventUsage(raw) {
87
- const parsed = (0, parse_usage_js_1.parseUsage)(raw);
88
- if (!parsed)
89
- return null;
90
- return {
91
- inputTokens: parsed.inputTokens,
92
- outputTokens: parsed.outputTokens,
93
- cachedInputTokens: parsed.cachedInputTokens,
94
- costUsd: 0,
95
- };
96
- }
97
- class ProviderError extends Error {
98
- providerStr;
99
- constructor(message, providerStr) {
100
- super(message);
101
- this.providerStr = providerStr;
102
- this.name = 'ProviderError';
103
- }
104
- }
105
- exports.ProviderError = ProviderError;
106
- /**
107
- * Thrown by VercelProviderRuntime when generateText() encounters a tool without
108
- * an execute function (client tool). The caller should return requires_action
109
- * to the client, collect the tool result, and call continueWithToolResults().
110
- */
111
- class ClientToolCallRequiredError extends Error {
112
- toolCall;
113
- continuationState;
114
- name = 'ClientToolCallRequiredError';
115
- constructor(toolCall, continuationState) {
116
- super(`Client tool call required: ${toolCall.toolName}`);
117
- this.toolCall = toolCall;
118
- this.continuationState = continuationState;
119
- }
120
- }
121
- exports.ClientToolCallRequiredError = ClientToolCallRequiredError;
122
- // ── Provider factory registry ───────────────────────────────────────────────
123
- const _providerFactories = new Map();
124
- /**
125
- * Register a provider factory for a given namespace.
126
- *
127
- * @example
128
- * // Register an API-based provider namespace
129
- * registerProviderFactory('api', (id, providerStr) => new MyApiProvider(id));
130
- *
131
- * // Now createProvider('api/claude') works
132
- * const provider = createProvider('api/claude');
133
- */
134
- function registerProviderFactory(namespace, factory) {
135
- _providerFactories.set(namespace, factory);
136
- }
137
- // CLI command mapping for each supported provider id
138
- const CLI_COMMANDS = {
139
- claude: 'claude',
140
- gemini: 'gemini',
141
- copilot: 'copilot', // GitHub Copilot CLI (standalone binary)
142
- codex: 'codex',
143
- opencode: 'opencode', // OpenCode CLI (--format json stream)
144
- };
145
- /**
146
- * Create a provider runtime for the given provider string.
147
- *
148
- * Looks up the namespace in the provider registry first.
149
- * Falls back to built-in cli/* providers for backward compatibility.
150
- *
151
- * @param providerStr - Provider string in namespace/id format (e.g., 'cli/claude', 'api/claude')
152
- * @throws ProviderError for unknown or unsupported providers
153
- */
154
- function createProvider(providerStr) {
155
- const parts = providerStr.split('/');
156
- if (parts.length !== 2) {
157
- throw new ProviderError(`Invalid provider format: "${providerStr}". Expected namespace/id (e.g., cli/claude)`, providerStr);
158
- }
159
- const [namespace, id] = parts;
160
- // Check registry first (covers both user-registered and built-in cli namespace)
161
- const factory = _providerFactories.get(namespace);
162
- if (factory) {
163
- return factory(id, providerStr);
164
- }
165
- // Built-in cli/* fallback (for backward compatibility when cli factory is not explicitly registered)
166
- if (namespace === 'cli') {
167
- const cliCommand = CLI_COMMANDS[id];
168
- if (!cliCommand) {
169
- throw new ProviderError(`Unknown CLI provider id: "${id}". Supported: ${Object.keys(CLI_COMMANDS).join(', ')}`, providerStr);
170
- }
171
- return new CliProviderRuntime(id, cliCommand, providerStr);
172
- }
173
- throw new ProviderError(`Unsupported provider namespace: "${namespace}". Register a factory with registerProviderFactory('${namespace}', factory).`, providerStr);
174
- }
175
- /**
176
- * Provider runtime that spawns a CLI process and collects its output.
177
- */
178
- class CliProviderRuntime {
179
- providerId;
180
- cliCommand;
181
- providerStr;
182
- constructor(providerId, cliCommand, providerStr) {
183
- this.providerId = providerId;
184
- this.cliCommand = cliCommand;
185
- this.providerStr = providerStr;
186
- }
187
- async execute(message, options) {
188
- const { args, stdinMessage } = this.buildArgs(message, options, true);
189
- options?.onCommand?.(`${this.cliCommand} ${args.join(' ')}`);
190
- return this.runProcess(args, options, stdinMessage);
191
- }
192
- async query(message, options) {
193
- const { args, stdinMessage } = this.buildArgs(message, options);
194
- options?.onCommand?.(`${this.cliCommand} ${args.join(' ')}`);
195
- return this.runProcess(args, options, stdinMessage);
196
- }
197
- runProcess(args, options, stdinMessage) {
198
- return new Promise((resolve, reject) => {
199
- const proc = (0, child_process_1.spawn)(this.cliCommand, args, {
200
- env: { ...process.env, ...(options?.env ?? {}) },
201
- cwd: options?.cwd,
202
- stdio: ['pipe', 'pipe', 'pipe'],
203
- shell: process.platform === 'win32',
204
- });
205
- // Write message to stdin for providers that read prompt from stdin (e.g. codex)
206
- // Always close stdin afterwards — some CLIs (e.g. opencode) hang waiting for
207
- // input otherwise, even when the prompt was passed via argv.
208
- if (stdinMessage !== undefined) {
209
- proc.stdin.write(stdinMessage);
210
- }
211
- proc.stdin.end();
212
- // Report child PID immediately after spawn
213
- if (proc.pid !== undefined) {
214
- options?.onPid?.(proc.pid);
215
- }
216
- let stdout = '';
217
- let stderr = '';
218
- let stdoutBuf = '';
219
- let stderrBuf = '';
220
- proc.stdout.on('data', (chunk) => {
221
- const str = chunk.toString();
222
- stdout += str;
223
- stdoutBuf += str;
224
- const lines = stdoutBuf.split('\n');
225
- stdoutBuf = lines.pop() ?? '';
226
- for (const line of lines) {
227
- if (line.trim())
228
- options?.onOutput?.(line, 'stdout');
229
- }
230
- });
231
- proc.stderr.on('data', (chunk) => {
232
- const str = chunk.toString();
233
- stderr += str;
234
- stderrBuf += str;
235
- const lines = stderrBuf.split('\n');
236
- stderrBuf = lines.pop() ?? '';
237
- for (const line of lines) {
238
- if (line.trim())
239
- options?.onOutput?.(line, 'stderr');
240
- }
241
- });
242
- proc.on('error', (err) => {
243
- if (err.code === 'ENOENT') {
244
- reject(new ProviderError(`CLI command "${this.cliCommand}" not found. Is ${this.providerStr} installed?`, this.providerStr));
245
- }
246
- else {
247
- reject(new ProviderError(`Spawn error: ${err.message}`, this.providerStr));
248
- }
249
- });
250
- proc.on('close', (code) => {
251
- // Flush any residual buffered content (no trailing newline)
252
- if (stdoutBuf.trim())
253
- options?.onOutput?.(stdoutBuf, 'stdout');
254
- if (stderrBuf.trim())
255
- options?.onOutput?.(stderrBuf, 'stderr');
256
- const exitCode = code ?? 0;
257
- options?.onExitCode?.(exitCode);
258
- if (code !== 0) {
259
- reject(new ProviderError(`Process exited with code ${code}: ${stderr.slice(0, 500)}`, this.providerStr));
260
- return;
261
- }
262
- // Extract usage and model from stream-json result event before resolving
263
- const { usage, model } = this.parseResultEvent(stdout);
264
- if (usage && options?.onUsage) {
265
- options.onUsage(usage);
266
- }
267
- // OpenCode stream doesn't emit model info in events; fall back to configured model
268
- const effectiveModel = model ?? (this.providerId === 'opencode' ? (options?.model ?? null) : null);
269
- if (effectiveModel && options?.onModel) {
270
- options.onModel(effectiveModel);
271
- }
272
- const parsed = this.parseOutput(stdout);
273
- resolve(parsed);
274
- });
275
- });
276
- }
277
- buildArgs(message, options, isExecute = false) {
278
- // HOTFIX: compose systemPrompt into the outgoing message for all CLI providers.
279
- // CLI providers don't have a common --system-prompt flag, and agent-rendered
280
- // prompts (persona, rules, inline.prompt, builtin_tools, skills) were being
281
- // dropped entirely before this fix. Provider-native system-prompt flags
282
- // (e.g. claude --append-system-prompt) should be adopted per-provider later
283
- // for proper system/user separation + prompt caching.
284
- const effectiveMessage = options?.systemPrompt
285
- ? `${options.systemPrompt}\n\n---\n\n${message}`
286
- : message;
287
- // Copilot uses standalone `copilot` binary with prompt via stdin
288
- // (matching pre-refactoring CopilotProvider behavior)
289
- if (this.providerId === 'copilot') {
290
- const args = options?.additionalArgs ? [...options.additionalArgs] : [];
291
- if (options?.model)
292
- args.push('--model', options.model);
293
- return { args, stdinMessage: effectiveMessage };
294
- }
295
- // OpenCode: prompt is a positional arg appended last; --format json is system-forced.
296
- // Security flags (e.g. --dangerously-skip-permissions) come from options.additionalArgs
297
- // so operators can control them via crewx.yaml.
298
- if (this.providerId === 'opencode') {
299
- const additionalArgs = options?.additionalArgs;
300
- const args = additionalArgs !== undefined ? [...additionalArgs] : ['run'];
301
- // System guarantee: --format json must be present for stream-json parsing
302
- if (!args.includes('--format')) {
303
- args.push('--format', 'json');
304
- }
305
- if (options?.model)
306
- args.push('--model', options.model);
307
- args.push(effectiveMessage);
308
- return { args };
309
- }
310
- // If agent config provides explicit CLI options, use them directly
311
- if (options?.additionalArgs !== undefined) {
312
- const args = [...options.additionalArgs];
313
- const pIdx = args.indexOf('-p');
314
- if (pIdx !== -1) {
315
- // -p flag present: insert message as its value
316
- args.splice(pIdx + 1, 0, effectiveMessage);
317
- if (options.model)
318
- args.push('--model', options.model);
319
- return { args };
320
- }
321
- else {
322
- // No -p flag: provider reads prompt from stdin (e.g. codex)
323
- // codex-specific safety net: ensure a JSON output flag is present.
324
- // Accept both --json (older) and --experimental-json (newer) as equivalent.
325
- if (this.providerId === 'codex' && !args.includes('--json') && !args.includes('--experimental-json')) {
326
- args.push('--json');
327
- }
328
- if (options.model)
329
- args.push('--model', options.model);
330
- return { args, stdinMessage: effectiveMessage };
331
- }
332
- }
333
- // Default fallback: claude/gemini stream-json format
334
- const args = ['-p', effectiveMessage, '--output-format', 'stream-json', '--verbose'];
335
- if (isExecute) {
336
- args.push('--dangerously-skip-permissions');
337
- }
338
- if (options?.model) {
339
- args.push('--model', options.model);
340
- }
341
- return { args };
342
- }
343
- parseOutput(raw) {
344
- return parseStreamJsonOutput(raw);
345
- }
346
- /**
347
- * Extract token usage, cost, and model from the stream-json result event.
348
- * Claude CLI emits: { type: "result", usage: {...}, total_cost_usd: ..., modelUsage: {...} }
349
- * OpenCode CLI emits: { type: "step_finish", part: { tokens: { input, output, cache: { read, write } }, cost: 0 } }
350
- */
351
- parseResultEvent(raw) {
352
- const baseUsage = parseResultEventUsage(raw);
353
- const lines = raw.split('\n');
354
- for (const line of lines) {
355
- if (!line.trim())
356
- continue;
357
- try {
358
- const parsed = JSON.parse(line);
359
- if (parsed.type === 'result') {
360
- const usageRaw = parsed.usage;
361
- const usage = usageRaw
362
- ? {
363
- inputTokens: Number(usageRaw['input_tokens'] ?? 0),
364
- outputTokens: Number(usageRaw['output_tokens'] ?? 0),
365
- cachedInputTokens: Number(usageRaw['cache_read_input_tokens'] ?? 0),
366
- costUsd: Number(parsed['total_cost_usd'] ?? 0),
367
- }
368
- : baseUsage;
369
- const modelUsage = parsed.modelUsage;
370
- const model = modelUsage ? Object.keys(modelUsage)[0] ?? null : null;
371
- return { usage, model };
372
- }
373
- }
374
- catch {
375
- // Not JSON — skip
376
- }
377
- }
378
- return { usage: baseUsage, model: null };
379
- }
380
- }
381
- //# sourceMappingURL=bridge.js.map