@excitedjs/dreamux 0.2.0 → 0.3.1

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 (80) hide show
  1. package/README.md +155 -160
  2. package/bin/dreamux +2 -1
  3. package/bin/tm +30 -0
  4. package/dist/admin/client.js +98 -0
  5. package/dist/admin/client.js.map +1 -0
  6. package/dist/admin/methods.js +83 -38
  7. package/dist/admin/methods.js.map +1 -1
  8. package/dist/admin/socket.js +2 -2
  9. package/dist/admin/socket.js.map +1 -1
  10. package/dist/channel/feishu-gate.js +187 -18
  11. package/dist/channel/feishu-gate.js.map +1 -1
  12. package/dist/channel/feishu-message.js +92 -0
  13. package/dist/channel/feishu-message.js.map +1 -0
  14. package/dist/cli/doctor.js +242 -62
  15. package/dist/cli/doctor.js.map +1 -1
  16. package/dist/cli/dreamux.js +33 -51
  17. package/dist/cli/dreamux.js.map +1 -1
  18. package/dist/cli/server-ctl.js +6 -8
  19. package/dist/cli/server-ctl.js.map +1 -1
  20. package/dist/cli/server.js +22 -32
  21. package/dist/cli/server.js.map +1 -1
  22. package/dist/codex/events.js +3 -2
  23. package/dist/codex/events.js.map +1 -1
  24. package/dist/codex/mcp-config.js +24 -0
  25. package/dist/codex/mcp-config.js.map +1 -0
  26. package/dist/codex/supervisor.js +16 -0
  27. package/dist/codex/supervisor.js.map +1 -1
  28. package/dist/dispatcher/approval.js +2 -3
  29. package/dist/dispatcher/approval.js.map +1 -1
  30. package/dist/dispatcher/runtime.js +193 -141
  31. package/dist/dispatcher/runtime.js.map +1 -1
  32. package/dist/dispatcher/turn-manager.js +78 -97
  33. package/dist/dispatcher/turn-manager.js.map +1 -1
  34. package/dist/feishu/bot.js +71 -9
  35. package/dist/feishu/bot.js.map +1 -1
  36. package/dist/mcp/feishu-mcp.js +269 -0
  37. package/dist/mcp/feishu-mcp.js.map +1 -0
  38. package/dist/onboard/commands.js +10 -6
  39. package/dist/onboard/commands.js.map +1 -1
  40. package/dist/onboard/config-files.js +52 -22
  41. package/dist/onboard/config-files.js.map +1 -1
  42. package/dist/onboard/dispatcher-skill.js +18 -0
  43. package/dist/onboard/dispatcher-skill.js.map +1 -0
  44. package/dist/onboard/run.js +36 -52
  45. package/dist/onboard/run.js.map +1 -1
  46. package/dist/onboard/service.js +106 -9
  47. package/dist/onboard/service.js.map +1 -1
  48. package/dist/onboard/uninstall.js +47 -13
  49. package/dist/onboard/uninstall.js.map +1 -1
  50. package/dist/onboard/wizard.js +3 -27
  51. package/dist/onboard/wizard.js.map +1 -1
  52. package/dist/runtime/config.js +158 -64
  53. package/dist/runtime/config.js.map +1 -1
  54. package/dist/runtime/dispatcher-codex-home.js +14 -51
  55. package/dist/runtime/dispatcher-codex-home.js.map +1 -1
  56. package/dist/runtime/dispatcher-id.js +9 -0
  57. package/dist/runtime/dispatcher-id.js.map +1 -0
  58. package/dist/runtime/dispatcher-store.js +202 -0
  59. package/dist/runtime/dispatcher-store.js.map +1 -0
  60. package/dist/runtime/package-bin.js +41 -0
  61. package/dist/runtime/package-bin.js.map +1 -0
  62. package/dist/runtime/paths.js +82 -48
  63. package/dist/runtime/paths.js.map +1 -1
  64. package/dist/runtime/secrets.js +4 -3
  65. package/dist/runtime/secrets.js.map +1 -1
  66. package/dist/server.js +110 -36
  67. package/dist/server.js.map +1 -1
  68. package/package.json +6 -6
  69. package/skills/dispatcher/SKILL.md +107 -0
  70. package/db/migrations/0001_init.sql +0 -49
  71. package/dist/channel/outbound.js +0 -12
  72. package/dist/channel/outbound.js.map +0 -1
  73. package/dist/db/repository.js +0 -223
  74. package/dist/db/repository.js.map +0 -1
  75. package/dist/db/schema.js +0 -29
  76. package/dist/db/schema.js.map +0 -1
  77. package/dist/db/types.js +0 -2
  78. package/dist/db/types.js.map +0 -1
  79. package/dist/onboard/plugins.js +0 -202
  80. package/dist/onboard/plugins.js.map +0 -1
@@ -0,0 +1,269 @@
1
+ import { createInterface } from 'node:readline';
2
+ import { AdminClientError, sendAdminRequest, } from '../admin/client.js';
3
+ import { adminSocketPath as defaultAdminSocketPath } from '../runtime/paths.js';
4
+ import { validateDispatcherId } from '../runtime/dispatcher-id.js';
5
+ const JSONRPC_VERSION = '2.0';
6
+ const DEFAULT_MCP_PROTOCOL_VERSION = '2024-11-05';
7
+ const SUPPORTED_MCP_PROTOCOL_VERSIONS = new Set([
8
+ '2025-06-18',
9
+ '2025-03-26',
10
+ '2024-11-05',
11
+ ]);
12
+ export async function runFeishuMcp(opts) {
13
+ const dispatcherId = validateDispatcherId(opts.dispatcherId);
14
+ const socketPath = opts.adminSocketPath ?? defaultAdminSocketPath();
15
+ const input = opts.input ?? process.stdin;
16
+ const output = opts.output ?? process.stdout;
17
+ const log = opts.log ?? ((message) => console.error(message));
18
+ const lines = createInterface({ input, crlfDelay: Infinity });
19
+ for await (const line of lines) {
20
+ const trimmed = line.trim();
21
+ if (trimmed === '')
22
+ continue;
23
+ let request;
24
+ try {
25
+ request = JSON.parse(trimmed);
26
+ }
27
+ catch (err) {
28
+ write(output, errorResponse(null, -32700, parseMessage(err)));
29
+ continue;
30
+ }
31
+ try {
32
+ await handleRequest(request, {
33
+ dispatcherId,
34
+ socketPath,
35
+ output,
36
+ });
37
+ }
38
+ catch (err) {
39
+ log(`feishu-mcp: ${parseMessage(err)}`);
40
+ if (request.id !== undefined) {
41
+ write(output, errorResponse(request.id, -32603, parseMessage(err)));
42
+ }
43
+ }
44
+ }
45
+ }
46
+ async function handleRequest(request, ctx) {
47
+ if (typeof request.method !== 'string') {
48
+ if (request.id !== undefined) {
49
+ write(ctx.output, errorResponse(request.id, -32600, 'missing method'));
50
+ }
51
+ return;
52
+ }
53
+ switch (request.method) {
54
+ case 'initialize':
55
+ if (request.id !== undefined) {
56
+ write(ctx.output, okResponse(request.id, initializeResult(request.params)));
57
+ }
58
+ return;
59
+ case 'initialized':
60
+ case 'notifications/initialized':
61
+ return;
62
+ case 'tools/list':
63
+ if (request.id !== undefined) {
64
+ write(ctx.output, okResponse(request.id, { tools: feishuTools() }));
65
+ }
66
+ return;
67
+ case 'tools/call':
68
+ if (request.id !== undefined) {
69
+ write(ctx.output, okResponse(request.id, await callTool(request.params, ctx)));
70
+ }
71
+ return;
72
+ default:
73
+ if (request.id !== undefined) {
74
+ write(ctx.output, errorResponse(request.id, -32601, `unknown MCP method '${request.method}'`));
75
+ }
76
+ }
77
+ }
78
+ function initializeResult(params) {
79
+ return {
80
+ protocolVersion: negotiateProtocolVersion(params),
81
+ capabilities: {
82
+ tools: {},
83
+ },
84
+ serverInfo: {
85
+ name: 'dreamux-feishu',
86
+ version: '0.2.0',
87
+ },
88
+ };
89
+ }
90
+ function feishuTools() {
91
+ return [
92
+ {
93
+ name: 'reply',
94
+ description: 'Send a Feishu message through this dispatcher channel.',
95
+ inputSchema: {
96
+ type: 'object',
97
+ additionalProperties: false,
98
+ properties: {
99
+ chat_id: {
100
+ type: 'string',
101
+ description: 'Feishu chat id from the inbound feishu_message block.',
102
+ },
103
+ message_id: {
104
+ type: 'string',
105
+ description: 'Optional source message id to reply under.',
106
+ },
107
+ text: {
108
+ type: 'string',
109
+ description: 'Message text to send.',
110
+ },
111
+ mention_user_ids: {
112
+ type: 'array',
113
+ items: { type: 'string' },
114
+ description: 'Optional Feishu user ids to mention.',
115
+ },
116
+ },
117
+ required: ['chat_id', 'text'],
118
+ },
119
+ },
120
+ {
121
+ name: 'react',
122
+ description: 'Add a model-owned Feishu reaction through this dispatcher channel.',
123
+ inputSchema: {
124
+ type: 'object',
125
+ additionalProperties: false,
126
+ properties: {
127
+ message_id: {
128
+ type: 'string',
129
+ description: 'Feishu message id to react to.',
130
+ },
131
+ emoji: {
132
+ type: 'string',
133
+ description: 'Feishu reaction emoji key.',
134
+ },
135
+ },
136
+ required: ['message_id', 'emoji'],
137
+ },
138
+ },
139
+ ];
140
+ }
141
+ async function callTool(params, ctx) {
142
+ try {
143
+ const call = asToolCallParams(params);
144
+ if (call.name === 'reply') {
145
+ return forwardToolCall('mcp.reply', {
146
+ dispatcher_id: ctx.dispatcherId,
147
+ ...replyArgs(call.arguments),
148
+ }, ctx.socketPath, 'reply');
149
+ }
150
+ if (call.name === 'react') {
151
+ return forwardToolCall('mcp.react', {
152
+ dispatcher_id: ctx.dispatcherId,
153
+ ...reactArgs(call.arguments),
154
+ }, ctx.socketPath, 'react');
155
+ }
156
+ return toolError(`unknown Feishu tool '${String(call.name)}'`);
157
+ }
158
+ catch (err) {
159
+ return toolError(parseMessage(err));
160
+ }
161
+ }
162
+ function negotiateProtocolVersion(params) {
163
+ const requested = params !== null && typeof params === 'object' && !Array.isArray(params)
164
+ ? params['protocolVersion']
165
+ : undefined;
166
+ if (typeof requested === 'string' &&
167
+ SUPPORTED_MCP_PROTOCOL_VERSIONS.has(requested)) {
168
+ return requested;
169
+ }
170
+ return DEFAULT_MCP_PROTOCOL_VERSION;
171
+ }
172
+ async function forwardToolCall(method, params, socketPath, label) {
173
+ try {
174
+ const result = await sendAdminRequest(method, params, { socketPath });
175
+ return {
176
+ content: [{ type: 'text', text: `${label} forwarded to dreamux serve` }],
177
+ structuredContent: result,
178
+ };
179
+ }
180
+ catch (err) {
181
+ const prefix = err instanceof AdminClientError ? `[${err.code}] ` : '';
182
+ return toolError(`${prefix}${parseMessage(err)}`);
183
+ }
184
+ }
185
+ function asToolCallParams(params) {
186
+ const obj = asRecord(params, 'tools/call params');
187
+ const name = obj['name'];
188
+ if (typeof name !== 'string' || name === '') {
189
+ throw new Error('tools/call params.name must be a non-empty string');
190
+ }
191
+ return {
192
+ name,
193
+ arguments: obj['arguments'] ?? {},
194
+ };
195
+ }
196
+ function replyArgs(value) {
197
+ const obj = asRecord(value, 'reply arguments');
198
+ const chatId = requireString(obj, 'chat_id');
199
+ const text = requireString(obj, 'text');
200
+ const messageId = optionalString(obj, 'message_id');
201
+ const mentionUserIds = optionalStringArray(obj, 'mention_user_ids');
202
+ return {
203
+ chat_id: chatId,
204
+ text,
205
+ ...(messageId !== null ? { message_id: messageId } : {}),
206
+ ...(mentionUserIds !== null ? { mention_user_ids: mentionUserIds } : {}),
207
+ };
208
+ }
209
+ function reactArgs(value) {
210
+ const obj = asRecord(value, 'react arguments');
211
+ return {
212
+ message_id: requireString(obj, 'message_id'),
213
+ emoji: requireString(obj, 'emoji'),
214
+ };
215
+ }
216
+ function asRecord(value, label) {
217
+ if (value === null || typeof value !== 'object' || Array.isArray(value)) {
218
+ throw new Error(`${label} must be an object`);
219
+ }
220
+ return value;
221
+ }
222
+ function requireString(obj, key) {
223
+ const value = obj[key];
224
+ if (typeof value !== 'string' || value === '') {
225
+ throw new Error(`${key} must be a non-empty string`);
226
+ }
227
+ return value;
228
+ }
229
+ function optionalString(obj, key) {
230
+ const value = obj[key];
231
+ if (value === undefined || value === null || value === '')
232
+ return null;
233
+ if (typeof value !== 'string') {
234
+ throw new Error(`${key} must be a string`);
235
+ }
236
+ return value;
237
+ }
238
+ function optionalStringArray(obj, key) {
239
+ const value = obj[key];
240
+ if (value === undefined || value === null)
241
+ return null;
242
+ if (!Array.isArray(value) || value.some((item) => typeof item !== 'string')) {
243
+ throw new Error(`${key} must be an array of strings`);
244
+ }
245
+ return value;
246
+ }
247
+ function toolError(message) {
248
+ return {
249
+ isError: true,
250
+ content: [{ type: 'text', text: message }],
251
+ };
252
+ }
253
+ function okResponse(id, result) {
254
+ return { jsonrpc: JSONRPC_VERSION, id, result };
255
+ }
256
+ function errorResponse(id, code, message) {
257
+ return {
258
+ jsonrpc: JSONRPC_VERSION,
259
+ id,
260
+ error: { code, message },
261
+ };
262
+ }
263
+ function write(output, message) {
264
+ output.write(`${JSON.stringify(message)}\n`);
265
+ }
266
+ function parseMessage(err) {
267
+ return err instanceof Error ? err.message : String(err);
268
+ }
269
+ //# sourceMappingURL=feishu-mcp.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"feishu-mcp.js","sourceRoot":"","sources":["../../src/mcp/feishu-mcp.ts"],"names":[],"mappings":"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"}
@@ -4,8 +4,7 @@ export class ExecaCommandRunner {
4
4
  if (options.dryRun)
5
5
  return;
6
6
  await execa(command, args, {
7
- cwd: options.cwd,
8
- env: options.env,
7
+ ...execaEnvironment(options),
9
8
  stdio: 'inherit',
10
9
  });
11
10
  }
@@ -13,8 +12,7 @@ export class ExecaCommandRunner {
13
12
  if (options.dryRun)
14
13
  return false;
15
14
  const result = await execa(command, args, {
16
- cwd: options.cwd,
17
- env: options.env,
15
+ ...execaEnvironment(options),
18
16
  reject: false,
19
17
  stdout: 'ignore',
20
18
  stderr: 'ignore',
@@ -25,10 +23,16 @@ export class ExecaCommandRunner {
25
23
  if (options.dryRun)
26
24
  return '';
27
25
  const result = await execa(command, args, {
28
- cwd: options.cwd,
29
- env: options.env,
26
+ ...execaEnvironment(options),
30
27
  });
31
28
  return result.stdout;
32
29
  }
33
30
  }
31
+ function execaEnvironment(options) {
32
+ return {
33
+ cwd: options.cwd,
34
+ env: options.env,
35
+ extendEnv: options.env === undefined,
36
+ };
37
+ }
34
38
  //# sourceMappingURL=commands.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"commands.js","sourceRoot":"","sources":["../../src/onboard/commands.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,OAAO,CAAC;AAI9B,MAAM,OAAO,kBAAkB;IAC7B,KAAK,CAAC,GAAG,CACP,OAAe,EACf,IAAc,EACd,UAII,EAAE;QAEN,IAAI,OAAO,CAAC,MAAM;YAAE,OAAO;QAC3B,MAAM,KAAK,CAAC,OAAO,EAAE,IAAI,EAAE;YACzB,GAAG,EAAE,OAAO,CAAC,GAAG;YAChB,GAAG,EAAE,OAAO,CAAC,GAAG;YAChB,KAAK,EAAE,SAAS;SACjB,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,KAAK,CACT,OAAe,EACf,IAAc,EACd,UAII,EAAE;QAEN,IAAI,OAAO,CAAC,MAAM;YAAE,OAAO,KAAK,CAAC;QACjC,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,OAAO,EAAE,IAAI,EAAE;YACxC,GAAG,EAAE,OAAO,CAAC,GAAG;YAChB,GAAG,EAAE,OAAO,CAAC,GAAG;YAChB,MAAM,EAAE,KAAK;YACb,MAAM,EAAE,QAAQ;YAChB,MAAM,EAAE,QAAQ;SACjB,CAAC,CAAC;QACH,OAAO,MAAM,CAAC,QAAQ,KAAK,CAAC,CAAC;IAC/B,CAAC;IAED,KAAK,CAAC,OAAO,CACX,OAAe,EACf,IAAc,EACd,UAII,EAAE;QAEN,IAAI,OAAO,CAAC,MAAM;YAAE,OAAO,EAAE,CAAC;QAC9B,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,OAAO,EAAE,IAAI,EAAE;YACxC,GAAG,EAAE,OAAO,CAAC,GAAG;YAChB,GAAG,EAAE,OAAO,CAAC,GAAG;SACjB,CAAC,CAAC;QACH,OAAO,MAAM,CAAC,MAAM,CAAC;IACvB,CAAC;CACF"}
1
+ {"version":3,"file":"commands.js","sourceRoot":"","sources":["../../src/onboard/commands.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,OAAO,CAAC;AAU9B,MAAM,OAAO,kBAAkB;IAC7B,KAAK,CAAC,GAAG,CACP,OAAe,EACf,IAAc,EACd,UAA0B,EAAE;QAE5B,IAAI,OAAO,CAAC,MAAM;YAAE,OAAO;QAC3B,MAAM,KAAK,CAAC,OAAO,EAAE,IAAI,EAAE;YACzB,GAAG,gBAAgB,CAAC,OAAO,CAAC;YAC5B,KAAK,EAAE,SAAS;SACjB,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,KAAK,CACT,OAAe,EACf,IAAc,EACd,UAA0B,EAAE;QAE5B,IAAI,OAAO,CAAC,MAAM;YAAE,OAAO,KAAK,CAAC;QACjC,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,OAAO,EAAE,IAAI,EAAE;YACxC,GAAG,gBAAgB,CAAC,OAAO,CAAC;YAC5B,MAAM,EAAE,KAAK;YACb,MAAM,EAAE,QAAQ;YAChB,MAAM,EAAE,QAAQ;SACjB,CAAC,CAAC;QACH,OAAO,MAAM,CAAC,QAAQ,KAAK,CAAC,CAAC;IAC/B,CAAC;IAED,KAAK,CAAC,OAAO,CACX,OAAe,EACf,IAAc,EACd,UAA0B,EAAE;QAE5B,IAAI,OAAO,CAAC,MAAM;YAAE,OAAO,EAAE,CAAC;QAC9B,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,OAAO,EAAE,IAAI,EAAE;YACxC,GAAG,gBAAgB,CAAC,OAAO,CAAC;SAC7B,CAAC,CAAC;QACH,OAAO,MAAM,CAAC,MAAM,CAAC;IACvB,CAAC;CACF;AAED,SAAS,gBAAgB,CAAC,OAAuB;IAK/C,OAAO;QACL,GAAG,EAAE,OAAO,CAAC,GAAG;QAChB,GAAG,EAAE,OAAO,CAAC,GAAG;QAChB,SAAS,EAAE,OAAO,CAAC,GAAG,KAAK,SAAS;KACrC,CAAC;AACJ,CAAC"}
@@ -1,32 +1,27 @@
1
1
  import { BUILT_IN_DEFAULTS, stringifyConfig, } from '../runtime/config.js';
2
+ import { validateDispatcherId } from '../runtime/dispatcher-id.js';
2
3
  export function buildDreamuxConfigJson(answers) {
3
4
  return stringifyConfig(dreamuxConfigFromAnswers(answers));
4
5
  }
5
6
  export function dreamuxConfigFromAnswers(answers, existing) {
7
+ validateDispatcherId(answers.dispatcherId);
6
8
  const base = existing ?? dreamuxConfigDefaultsFromAnswers(answers);
7
- return {
8
- runtime_dir: base.runtime_dir,
9
- admin_socket: base.admin_socket,
9
+ const dispatchers = base.dispatchers
10
+ .filter((dispatcher) => dispatcher.id !== answers.dispatcherId)
11
+ .map(cloneDispatcherConfig);
12
+ dispatchers.push(dispatcherConfigFromAnswers(answers));
13
+ const next = {
10
14
  codex: {
11
15
  ...base.codex,
12
16
  extra_args: [...base.codex.extra_args],
13
17
  },
14
- outbound: { ...base.outbound },
15
- feishu: {
16
- bots: {
17
- ...base.feishu.bots,
18
- [answers.dispatcherId]: {
19
- app_id: answers.botAppId,
20
- app_secret: answers.botAppSecret,
21
- },
22
- },
23
- },
18
+ dispatchers,
24
19
  };
20
+ assertUniqueFeishuAppIds(next);
21
+ return next;
25
22
  }
26
23
  function dreamuxConfigDefaultsFromAnswers(answers) {
27
24
  return {
28
- runtime_dir: answers.runtimeDir,
29
- admin_socket: null,
30
25
  codex: {
31
26
  bin: answers.codexBin,
32
27
  approval_policy: 'never',
@@ -34,13 +29,7 @@ function dreamuxConfigDefaultsFromAnswers(answers) {
34
29
  extra_args: [],
35
30
  initialize_timeout_ms: BUILT_IN_DEFAULTS.codex.initialize_timeout_ms,
36
31
  },
37
- outbound: {
38
- retries: BUILT_IN_DEFAULTS.outbound.retries,
39
- retry_delay_ms: BUILT_IN_DEFAULTS.outbound.retry_delay_ms,
40
- },
41
- feishu: {
42
- bots: {},
43
- },
32
+ dispatchers: [],
44
33
  };
45
34
  }
46
35
  export function dispatcherBotSecretRef(dispatcherId) {
@@ -53,4 +42,45 @@ export function dispatcherCodexArgsJson() {
53
42
  extraArgs: [],
54
43
  });
55
44
  }
45
+ function assertUniqueFeishuAppIds(config) {
46
+ const seen = new Map();
47
+ for (const dispatcher of config.dispatchers) {
48
+ const existing = seen.get(dispatcher.feishu.app_id);
49
+ if (existing !== undefined && existing !== dispatcher.id) {
50
+ throw new Error(`Feishu app_id for dispatcher '${dispatcher.id}' duplicates dispatcher '${existing}'`);
51
+ }
52
+ seen.set(dispatcher.feishu.app_id, dispatcher.id);
53
+ }
54
+ }
55
+ function dispatcherConfigFromAnswers(answers) {
56
+ return {
57
+ id: answers.dispatcherId,
58
+ cwd: answers.dispatcherCwd,
59
+ enabled: true,
60
+ feishu: {
61
+ app_id: answers.botAppId,
62
+ app_secret: answers.botAppSecret,
63
+ },
64
+ codex: {
65
+ approval_policy: 'never',
66
+ sandbox_mode: 'workspace-write',
67
+ extra_args: [],
68
+ extra_env: {},
69
+ },
70
+ };
71
+ }
72
+ function cloneDispatcherConfig(dispatcher) {
73
+ return {
74
+ id: dispatcher.id,
75
+ cwd: dispatcher.cwd,
76
+ enabled: dispatcher.enabled,
77
+ feishu: { ...dispatcher.feishu },
78
+ codex: {
79
+ approval_policy: dispatcher.codex.approval_policy,
80
+ sandbox_mode: dispatcher.codex.sandbox_mode,
81
+ extra_args: [...dispatcher.codex.extra_args],
82
+ extra_env: { ...dispatcher.codex.extra_env },
83
+ },
84
+ };
85
+ }
56
86
  //# sourceMappingURL=config-files.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"config-files.js","sourceRoot":"","sources":["../../src/onboard/config-files.ts"],"names":[],"mappings":"AACA,OAAO,EACL,iBAAiB,EACjB,eAAe,GAChB,MAAM,sBAAsB,CAAC;AAG9B,MAAM,UAAU,sBAAsB,CAAC,OAAuB;IAC5D,OAAO,eAAe,CAAC,wBAAwB,CAAC,OAAO,CAAC,CAAC,CAAC;AAC5D,CAAC;AAED,MAAM,UAAU,wBAAwB,CACtC,OAAuB,EACvB,QAAwB;IAExB,MAAM,IAAI,GAAG,QAAQ,IAAI,gCAAgC,CAAC,OAAO,CAAC,CAAC;IACnE,OAAO;QACL,WAAW,EAAE,IAAI,CAAC,WAAW;QAC7B,YAAY,EAAE,IAAI,CAAC,YAAY;QAC/B,KAAK,EAAE;YACL,GAAG,IAAI,CAAC,KAAK;YACb,UAAU,EAAE,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC;SACvC;QACD,QAAQ,EAAE,EAAE,GAAG,IAAI,CAAC,QAAQ,EAAE;QAC9B,MAAM,EAAE;YACN,IAAI,EAAE;gBACJ,GAAG,IAAI,CAAC,MAAM,CAAC,IAAI;gBACnB,CAAC,OAAO,CAAC,YAAY,CAAC,EAAE;oBACtB,MAAM,EAAE,OAAO,CAAC,QAAQ;oBACxB,UAAU,EAAE,OAAO,CAAC,YAAY;iBACjC;aACF;SACF;KACF,CAAC;AACJ,CAAC;AAED,SAAS,gCAAgC,CACvC,OAAuB;IAEvB,OAAO;QACL,WAAW,EAAE,OAAO,CAAC,UAAU;QAC/B,YAAY,EAAE,IAAI;QAClB,KAAK,EAAE;YACL,GAAG,EAAE,OAAO,CAAC,QAAQ;YACrB,eAAe,EAAE,OAAO;YACxB,YAAY,EAAE,iBAAiB;YAC/B,UAAU,EAAE,EAAE;YACd,qBAAqB,EAAE,iBAAiB,CAAC,KAAK,CAAC,qBAAqB;SACrE;QACD,QAAQ,EAAE;YACR,OAAO,EAAE,iBAAiB,CAAC,QAAQ,CAAC,OAAO;YAC3C,cAAc,EAAE,iBAAiB,CAAC,QAAQ,CAAC,cAAc;SAC1D;QACD,MAAM,EAAE;YACN,IAAI,EAAE,EAAE;SACT;KACF,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,sBAAsB,CAAC,YAAoB;IACzD,OAAO,UAAU,YAAY,EAAE,CAAC;AAClC,CAAC;AAED,MAAM,UAAU,uBAAuB;IACrC,OAAO,IAAI,CAAC,SAAS,CAAC;QACpB,cAAc,EAAE,OAAO;QACvB,WAAW,EAAE,iBAAiB;QAC9B,SAAS,EAAE,EAAE;KACd,CAAC,CAAC;AACL,CAAC"}
1
+ {"version":3,"file":"config-files.js","sourceRoot":"","sources":["../../src/onboard/config-files.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ import { existsSync, readFileSync } from 'node:fs';
2
+ import { dirname, join } from 'node:path';
3
+ import { fileURLToPath } from 'node:url';
4
+ import { writeTextFile } from './ledger.js';
5
+ const HERE = dirname(fileURLToPath(import.meta.url));
6
+ const PACKAGE_ROOT = dirname(dirname(HERE));
7
+ const DISPATCHER_SKILL_SOURCE = join(PACKAGE_ROOT, 'skills', 'dispatcher', 'SKILL.md');
8
+ export function installDispatcherSkill(options) {
9
+ const content = readDispatcherSkill();
10
+ writeTextFile(options.skillPath, content, options.ledger, 'workspace-local dispatcher skill', { mode: 0o600, dryRun: options.dryRun });
11
+ }
12
+ function readDispatcherSkill() {
13
+ if (!existsSync(DISPATCHER_SKILL_SOURCE)) {
14
+ throw new Error(`missing bundled dispatcher skill: ${DISPATCHER_SKILL_SOURCE}`);
15
+ }
16
+ return readFileSync(DISPATCHER_SKILL_SOURCE, 'utf8');
17
+ }
18
+ //# sourceMappingURL=dispatcher-skill.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dispatcher-skill.js","sourceRoot":"","sources":["../../src/onboard/dispatcher-skill.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAG5C,MAAM,IAAI,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AACrD,MAAM,YAAY,GAAG,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;AAC5C,MAAM,uBAAuB,GAAG,IAAI,CAClC,YAAY,EACZ,QAAQ,EACR,YAAY,EACZ,UAAU,CACX,CAAC;AAEF,MAAM,UAAU,sBAAsB,CAAC,OAItC;IACC,MAAM,OAAO,GAAG,mBAAmB,EAAE,CAAC;IACtC,aAAa,CACX,OAAO,CAAC,SAAS,EACjB,OAAO,EACP,OAAO,CAAC,MAAM,EACd,kCAAkC,EAClC,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CACxC,CAAC;AACJ,CAAC;AAED,SAAS,mBAAmB;IAC1B,IAAI,CAAC,UAAU,CAAC,uBAAuB,CAAC,EAAE,CAAC;QACzC,MAAM,IAAI,KAAK,CAAC,qCAAqC,uBAAuB,EAAE,CAAC,CAAC;IAClF,CAAC;IACD,OAAO,YAAY,CAAC,uBAAuB,EAAE,MAAM,CAAC,CAAC;AACvD,CAAC"}
@@ -1,16 +1,13 @@
1
- import { existsSync, mkdirSync } from 'node:fs';
2
- import { dirname } from 'node:path';
3
- import { DispatcherRepo } from '../db/repository.js';
4
- import { openDatabase } from '../db/schema.js';
1
+ import { existsSync } from 'node:fs';
5
2
  import { codexArgsToCli, parseCodexArgs } from '../runtime/codex-args.js';
6
3
  import { assertNoLegacyTomlOnly, globalConfigFile, loadConfig, stringifyConfig, } from '../runtime/config.js';
7
- import { dispatcherAppServerControlDir, dispatcherCodexHome, dispatcherCodexPluginsDir, databasePath, setRuntimeConfig, } from '../runtime/paths.js';
4
+ import { dispatcherAppServerControlDir, dispatcherCodexHome, dispatcherWorkspaceCodexSkillsDir, dispatcherWorkspaceSkillPath, logsRoot, setRuntimeConfig, stateRoot, } from '../runtime/paths.js';
8
5
  import { dispatcherCodexHomeDoctorContext, validateDispatcherCodexHome, } from '../runtime/dispatcher-codex-home.js';
9
6
  import { ExecaCommandRunner } from './commands.js';
10
- import { dispatcherBotSecretRef, dispatcherCodexArgsJson, dreamuxConfigFromAnswers, } from './config-files.js';
11
- import { ensureDirectory, recordFileTreeChanges, snapshotFiles, TransparentFileLedger, writeTextFile, } from './ledger.js';
12
- import { installUserService, managedServiceEnvironment } from './service.js';
13
- import { installClaudemuxPlugin, installCodexmuxPlugin, } from './plugins.js';
7
+ import { dispatcherCodexArgsJson, dreamuxConfigFromAnswers, } from './config-files.js';
8
+ import { installDispatcherSkill } from './dispatcher-skill.js';
9
+ import { ensureDirectory, TransparentFileLedger, writeTextFile, } from './ledger.js';
10
+ import { installUserService, managedServiceEnvironment, resolveServiceExecutable, validateManagedServiceLaunch, } from './service.js';
14
11
  export async function runOnboard(options) {
15
12
  const answers = options.answers;
16
13
  const ledger = options.ledger ?? new TransparentFileLedger();
@@ -19,43 +16,48 @@ export async function runOnboard(options) {
19
16
  const configPath = globalConfigFile({ configDir: answers.configDir });
20
17
  const existingConfig = readExistingDreamuxConfig(answers.configDir);
21
18
  const dreamuxConfig = dreamuxConfigFromAnswers(answers, existingConfig);
19
+ const serviceCodexBin = answers.registerService && !answers.dryRun
20
+ ? resolveServiceExecutable(dreamuxConfig.codex.bin, env)
21
+ : dreamuxConfig.codex.bin;
22
22
  const effectiveAnswers = {
23
23
  ...answers,
24
- runtimeDir: dreamuxConfig.runtime_dir,
25
- codexBin: dreamuxConfig.codex.bin,
24
+ runtimeDir: stateRoot(),
25
+ codexBin: serviceCodexBin,
26
+ nodeBin: process.execPath,
26
27
  };
27
28
  setRuntimeConfig(dreamuxConfig);
28
29
  ensureDirectory(answers.configDir, ledger, 'dreamux config directory', {
29
30
  dryRun: answers.dryRun,
30
31
  });
31
- ensureDirectory(effectiveAnswers.runtimeDir, ledger, 'dreamux runtime directory', {
32
+ ensureDirectory(stateRoot(), ledger, 'dreamux state directory', {
33
+ dryRun: answers.dryRun,
34
+ });
35
+ ensureDirectory(logsRoot(), ledger, 'dreamux logs directory', {
32
36
  dryRun: answers.dryRun,
33
37
  });
34
38
  writeTextFile(configPath, stringifyConfig(dreamuxConfig), ledger, 'dreamux global config', { mode: 0o600, dryRun: answers.dryRun });
35
39
  const codexHome = dispatcherCodexHome(answers.dispatcherId);
36
- ensureDirectory(codexHome, ledger, 'operator Codex home', {
40
+ ensureDirectory(codexHome, ledger, 'global Codex home', {
37
41
  dryRun: answers.dryRun,
38
42
  });
39
- ensureDirectory(dispatcherCodexPluginsDir(answers.dispatcherId), ledger, 'dispatcher Codex plugins directory', { dryRun: answers.dryRun });
40
43
  ensureDirectory(dispatcherAppServerControlDir(answers.dispatcherId), ledger, 'dispatcher app-server control directory', { dryRun: answers.dryRun });
41
44
  ensureDirectory(effectiveAnswers.dispatcherCwd, ledger, 'dispatcher cwd', { dryRun: answers.dryRun });
42
- await installCodexmuxPlugin({
43
- answers: effectiveAnswers,
44
- codexHome,
45
- ledger,
46
- runner,
47
- });
48
- await installClaudemuxPlugin({
49
- answers: effectiveAnswers,
50
- codexHome,
45
+ ensureDirectory(dispatcherWorkspaceCodexSkillsDir(effectiveAnswers.dispatcherCwd), ledger, 'workspace-local Codex skills directory', { dryRun: answers.dryRun });
46
+ installDispatcherSkill({
47
+ skillPath: dispatcherWorkspaceSkillPath(effectiveAnswers.dispatcherCwd),
51
48
  ledger,
52
- runner,
49
+ dryRun: answers.dryRun,
53
50
  });
54
- registerDispatcher(effectiveAnswers, ledger);
55
51
  const doctor = runDispatcherDoctor(effectiveAnswers, dreamuxConfig, env);
56
52
  if (!effectiveAnswers.dryRun && !doctor.ok) {
57
53
  throw new Error(formatDoctorFailure(effectiveAnswers, doctor));
58
54
  }
55
+ if (effectiveAnswers.registerService && !effectiveAnswers.dryRun) {
56
+ const serviceLaunch = await validateManagedServiceLaunch(effectiveAnswers, runner);
57
+ if (!serviceLaunch.ok) {
58
+ throw new Error(formatServiceLaunchFailure(serviceLaunch.errors));
59
+ }
60
+ }
59
61
  const service = effectiveAnswers.registerService
60
62
  ? await installUserService({
61
63
  answers: effectiveAnswers,
@@ -72,6 +74,13 @@ export async function runOnboard(options) {
72
74
  service,
73
75
  };
74
76
  }
77
+ function formatServiceLaunchFailure(errors) {
78
+ return [
79
+ 'dreamux managed service launch environment is not ready',
80
+ ...errors.map((error) => `- ${error}`),
81
+ '- rerun dreamux onboard from the desired Node/Codex install, or pass explicit --dreamux-bin / --codex-bin values',
82
+ ].join('\n');
83
+ }
75
84
  function readExistingDreamuxConfig(configDir) {
76
85
  const configPath = globalConfigFile({ configDir });
77
86
  assertNoLegacyTomlOnly({ configDir });
@@ -79,32 +88,6 @@ function readExistingDreamuxConfig(configDir) {
79
88
  return undefined;
80
89
  return loadConfig({ configDir }).config;
81
90
  }
82
- function registerDispatcher(answers, ledger) {
83
- const dbPath = databasePath();
84
- ensureDirectory(dirname(dbPath), ledger, 'dispatcher database directory', {
85
- dryRun: answers.dryRun,
86
- });
87
- if (answers.dryRun) {
88
- ledger.record(dbPath, 'created', 'dispatcher database');
89
- return;
90
- }
91
- mkdirSync(dirname(dbPath), { recursive: true });
92
- const before = snapshotFiles(dirname(dbPath));
93
- const db = openDatabase({ path: dbPath });
94
- try {
95
- new DispatcherRepo(db).upsert({
96
- dispatcher_id: answers.dispatcherId,
97
- bot_app_id: answers.botAppId,
98
- bot_secret_ref: dispatcherBotSecretRef(answers.dispatcherId),
99
- codex_args_json: dispatcherCodexArgsJson(),
100
- codex_cwd: answers.dispatcherCwd,
101
- });
102
- }
103
- finally {
104
- db.close();
105
- }
106
- recordFileTreeChanges(dirname(dbPath), before, ledger, 'dispatcher database');
107
- }
108
91
  function runDispatcherDoctor(answers, dreamuxConfig, env) {
109
92
  const codexArgs = parseCodexArgs(dispatcherCodexArgsJson(), {
110
93
  approvalPolicy: dreamuxConfig.codex.approval_policy,
@@ -114,6 +97,7 @@ function runDispatcherDoctor(answers, dreamuxConfig, env) {
114
97
  const codexCliArgs = codexArgsToCli(codexArgs);
115
98
  const context = dispatcherCodexHomeDoctorContext(answers.dispatcherId, {
116
99
  codexCliArgs,
100
+ dispatcherCwd: answers.dispatcherCwd,
117
101
  });
118
102
  if (answers.dryRun) {
119
103
  return {
@@ -137,7 +121,7 @@ function formatDoctorFailure(answers, doctor) {
137
121
  ];
138
122
  if (answers.registerService &&
139
123
  doctor.errors.some((error) => error.includes('missing Codex auth state'))) {
140
- lines.push('- managed service environments do not inherit your interactive shell auth token', `- authenticate the Codex home before registering the service: CODEX_HOME=${doctor.context.codexHome} ${answers.codexBin} login`);
124
+ lines.push('- managed service environments do not inherit your interactive shell auth token', `- authenticate the global Codex home before registering the service: ${answers.codexBin} login`);
141
125
  }
142
126
  return lines.join('\n');
143
127
  }