@undefineds.co/linx 0.3.20 → 0.3.22

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 (97) hide show
  1. package/dist/generated/version.js +1 -1
  2. package/dist/index.js +6 -1
  3. package/dist/index.js.map +1 -1
  4. package/dist/lib/auto-mode/pod-persistence.js +53 -3
  5. package/dist/lib/auto-mode/pod-persistence.js.map +1 -1
  6. package/dist/lib/auto-mode/secretary.js +2 -2
  7. package/dist/lib/auto-mode/secretary.js.map +1 -1
  8. package/dist/lib/chat-api.js +23 -61
  9. package/dist/lib/chat-api.js.map +1 -1
  10. package/dist/lib/codex-plugin/index.js +1 -0
  11. package/dist/lib/codex-plugin/index.js.map +1 -1
  12. package/dist/lib/codex-plugin/symphony-mcp.js +335 -0
  13. package/dist/lib/codex-plugin/symphony-mcp.js.map +1 -0
  14. package/dist/lib/linx-cloud-errors.js +0 -5
  15. package/dist/lib/linx-cloud-errors.js.map +1 -1
  16. package/dist/lib/linx-status-line.js +1 -8
  17. package/dist/lib/linx-status-line.js.map +1 -1
  18. package/dist/lib/models.js +3 -2
  19. package/dist/lib/models.js.map +1 -1
  20. package/dist/lib/pi-adapter/auth.js +68 -0
  21. package/dist/lib/pi-adapter/auth.js.map +1 -0
  22. package/dist/lib/pi-adapter/branding.js +34 -103
  23. package/dist/lib/pi-adapter/branding.js.map +1 -1
  24. package/dist/lib/pi-adapter/interactive.js +35 -49
  25. package/dist/lib/pi-adapter/interactive.js.map +1 -1
  26. package/dist/lib/pi-adapter/pod-mirror.js +38 -107
  27. package/dist/lib/pi-adapter/pod-mirror.js.map +1 -1
  28. package/dist/lib/pi-adapter/pod-native.js +2 -0
  29. package/dist/lib/pi-adapter/pod-native.js.map +1 -1
  30. package/dist/lib/pi-adapter/pod-tools.js +140 -0
  31. package/dist/lib/pi-adapter/pod-tools.js.map +1 -0
  32. package/dist/lib/pi-adapter/runtime.js +2 -12
  33. package/dist/lib/pi-adapter/runtime.js.map +1 -1
  34. package/dist/lib/pi-adapter/session.js +13 -17
  35. package/dist/lib/pi-adapter/session.js.map +1 -1
  36. package/dist/lib/pi-adapter/stream.js +2 -20
  37. package/dist/lib/pi-adapter/stream.js.map +1 -1
  38. package/dist/lib/pod-chat-store.js +53 -4
  39. package/dist/lib/pod-chat-store.js.map +1 -1
  40. package/dist/lib/resource-identity.js +2 -0
  41. package/dist/lib/resource-identity.js.map +1 -0
  42. package/dist/lib/status-line-command.js +2 -2
  43. package/dist/lib/status-line-command.js.map +1 -1
  44. package/dist/lib/symphony/archive.js +15 -37
  45. package/dist/lib/symphony/archive.js.map +1 -1
  46. package/dist/lib/symphony/pod-projection.js +189 -1346
  47. package/dist/lib/symphony/pod-projection.js.map +1 -1
  48. package/dist/lib/symphony-command.js +209 -109
  49. package/dist/lib/symphony-command.js.map +1 -1
  50. package/dist/plugins/linx-symphony-codex/.codex-plugin/plugin.json +38 -0
  51. package/dist/plugins/linx-symphony-codex/.mcp.json +10 -0
  52. package/dist/plugins/linx-symphony-codex/README.md +9 -0
  53. package/dist/plugins/linx-symphony-codex/hooks.json +60 -0
  54. package/dist/plugins/linx-symphony-codex/scripts/symphony-hook-events.mjs +119 -0
  55. package/dist/plugins/linx-symphony-codex/scripts/symphony-mcp.mjs +335 -0
  56. package/dist/plugins/linx-symphony-codex/skills/symphony/SKILL.md +791 -0
  57. package/dist/skills/symphony/SKILL.md +7 -0
  58. package/dist/skills/xpod-cli/SKILL.md +2 -13
  59. package/package.json +4 -4
  60. package/vendor/agent-runtime/dist/chat-reconciler.d.ts +33 -0
  61. package/vendor/agent-runtime/dist/chat-reconciler.js +108 -0
  62. package/vendor/agent-runtime/dist/index.d.ts +4 -1
  63. package/vendor/agent-runtime/dist/index.js +4 -1
  64. package/vendor/agent-runtime/dist/matrix-client.d.ts +149 -0
  65. package/vendor/agent-runtime/dist/matrix-client.js +220 -0
  66. package/vendor/agent-runtime/dist/pod-resource-identity.d.ts +17 -0
  67. package/vendor/agent-runtime/dist/pod-resource-identity.js +54 -0
  68. package/vendor/agent-runtime/dist/reconciler.d.ts +0 -11
  69. package/vendor/agent-runtime/dist/reconciler.js +5 -43
  70. package/vendor/agent-runtime/dist/symphony.d.ts +272 -27
  71. package/vendor/agent-runtime/dist/symphony.js +1268 -21
  72. package/vendor/agent-runtime/dist/workspace.d.ts +61 -0
  73. package/vendor/agent-runtime/dist/workspace.js +81 -0
  74. package/vendor/agent-runtime/package.json +5 -1
  75. package/vendor/stores/dist/current-pod-base.d.ts +2 -0
  76. package/vendor/stores/dist/current-pod-base.js +14 -0
  77. package/vendor/stores/dist/exact-records.d.ts +7 -0
  78. package/vendor/stores/dist/exact-records.js +87 -0
  79. package/vendor/stores/dist/index.d.ts +1 -0
  80. package/vendor/stores/dist/index.js +1 -0
  81. package/vendor/stores/dist/login.d.ts +51 -0
  82. package/vendor/stores/dist/login.js +195 -0
  83. package/vendor/stores/dist/pod-collection.d.ts +28 -0
  84. package/vendor/stores/dist/pod-collection.js +194 -0
  85. package/vendor/stores/dist/pod-write-guard.d.ts +5 -0
  86. package/vendor/stores/dist/pod-write-guard.js +133 -0
  87. package/vendor/stores/dist/symphony-control.d.ts +245 -0
  88. package/vendor/stores/dist/symphony-control.js +2175 -0
  89. package/vendor/stores/package.json +14 -0
  90. package/dist/lib/capture/persistence.js +0 -377
  91. package/dist/lib/capture/persistence.js.map +0 -1
  92. package/dist/lib/capture/tool.js +0 -242
  93. package/dist/lib/capture/tool.js.map +0 -1
  94. package/dist/skills/basic/SKILL.md +0 -46
  95. package/dist/skills/capture/SKILL.md +0 -165
  96. package/vendor/agent-runtime/dist/coordination.d.ts +0 -93
  97. package/vendor/agent-runtime/dist/coordination.js +0 -145
@@ -0,0 +1,60 @@
1
+ {
2
+ "hooks": {
3
+ "SessionStart": [
4
+ {
5
+ "matcher": "startup|resume|clear",
6
+ "hooks": [
7
+ {
8
+ "type": "command",
9
+ "command": "node ./scripts/symphony-hook-events.mjs",
10
+ "timeout": 5
11
+ }
12
+ ]
13
+ }
14
+ ],
15
+ "UserPromptSubmit": [
16
+ {
17
+ "hooks": [
18
+ {
19
+ "type": "command",
20
+ "command": "node ./scripts/symphony-hook-events.mjs",
21
+ "timeout": 5
22
+ }
23
+ ]
24
+ }
25
+ ],
26
+ "PreToolUse": [
27
+ {
28
+ "hooks": [
29
+ {
30
+ "type": "command",
31
+ "command": "node ./scripts/symphony-hook-events.mjs",
32
+ "timeout": 5
33
+ }
34
+ ]
35
+ }
36
+ ],
37
+ "PostToolUse": [
38
+ {
39
+ "hooks": [
40
+ {
41
+ "type": "command",
42
+ "command": "node ./scripts/symphony-hook-events.mjs",
43
+ "timeout": 5
44
+ }
45
+ ]
46
+ }
47
+ ],
48
+ "Stop": [
49
+ {
50
+ "hooks": [
51
+ {
52
+ "type": "command",
53
+ "command": "node ./scripts/symphony-hook-events.mjs",
54
+ "timeout": 5
55
+ }
56
+ ]
57
+ }
58
+ ]
59
+ }
60
+ }
@@ -0,0 +1,119 @@
1
+ #!/usr/bin/env node
2
+ import { createHash } from 'node:crypto'
3
+ import { appendFileSync, mkdirSync, readFileSync } from 'node:fs'
4
+ import { dirname, resolve } from 'node:path'
5
+ import { fileURLToPath } from 'node:url'
6
+
7
+ function readStdinJson() {
8
+ const input = readFileSync(0, 'utf-8').trim()
9
+ if (!input) return {}
10
+ const parsed = JSON.parse(input)
11
+ return parsed && typeof parsed === 'object' && !Array.isArray(parsed) ? parsed : {}
12
+ }
13
+
14
+ function optionalString(value) {
15
+ return typeof value === 'string' && value.trim() ? value.trim() : undefined
16
+ }
17
+
18
+ function optionalNumber(value) {
19
+ return typeof value === 'number' && Number.isFinite(value) ? value : undefined
20
+ }
21
+
22
+ function safeObject(value) {
23
+ return value && typeof value === 'object' && !Array.isArray(value) ? value : {}
24
+ }
25
+
26
+ function sha256(value) {
27
+ return createHash('sha256').update(value).digest('hex')
28
+ }
29
+
30
+ function textDigest(value) {
31
+ if (typeof value !== 'string') return undefined
32
+ return {
33
+ length: value.length,
34
+ sha256: sha256(value),
35
+ }
36
+ }
37
+
38
+ function toolInputSummary(payload) {
39
+ const toolName = optionalString(payload.tool_name ?? payload.toolName)
40
+ const toolInput = safeObject(payload.tool_input ?? payload.toolInput)
41
+ if (toolName === 'Bash' && typeof toolInput.command === 'string') {
42
+ const command = toolInput.command
43
+ return {
44
+ kind: 'bash',
45
+ commandLength: command.length,
46
+ commandSha256: sha256(command),
47
+ }
48
+ }
49
+ if (Object.keys(toolInput).length > 0) {
50
+ return {
51
+ kind: 'structured',
52
+ keyCount: Object.keys(toolInput).length,
53
+ keys: Object.keys(toolInput).sort().slice(0, 20),
54
+ }
55
+ }
56
+ return undefined
57
+ }
58
+
59
+ function toolResponseSummary(payload) {
60
+ const response = safeObject(payload.tool_response ?? payload.toolResponse)
61
+ if (Object.keys(response).length === 0) return undefined
62
+ return {
63
+ exitCode: optionalNumber(response.exit_code ?? response.exitCode),
64
+ stdout: textDigest(response.stdout),
65
+ stderr: textDigest(response.stderr),
66
+ }
67
+ }
68
+
69
+ function resolveEventsPath(env) {
70
+ const explicit = optionalString(env.LINX_SYMPHONY_HOOK_EVENTS)
71
+ return explicit ? resolve(explicit) : undefined
72
+ }
73
+
74
+ function buildEvent(payload, env = process.env, now = new Date()) {
75
+ const eventName = optionalString(payload.hook_event_name ?? payload.hookEventName ?? payload.event) ?? 'unknown'
76
+ const sessionId = optionalString(payload.session_id ?? payload.sessionId)
77
+ const cwd = optionalString(payload.cwd) ?? optionalString(env.PWD)
78
+ const prompt = typeof payload.prompt === 'string' ? payload.prompt : undefined
79
+ return {
80
+ symphonyHookEvent: true,
81
+ source: 'codex-native-hook',
82
+ hookEventName: eventName,
83
+ createdAt: now.toISOString(),
84
+ ...(sessionId ? { sessionId } : {}),
85
+ ...(cwd ? { cwd } : {}),
86
+ ...(optionalString(payload.transcript_path ?? payload.transcriptPath) ? { transcriptPath: optionalString(payload.transcript_path ?? payload.transcriptPath) } : {}),
87
+ ...(optionalString(payload.tool_name ?? payload.toolName) ? { toolName: optionalString(payload.tool_name ?? payload.toolName) } : {}),
88
+ ...(optionalString(payload.tool_use_id ?? payload.toolUseId) ? { toolUseId: optionalString(payload.tool_use_id ?? payload.toolUseId) } : {}),
89
+ ...(prompt ? { prompt: textDigest(prompt) } : {}),
90
+ ...(toolInputSummary(payload) ? { toolInput: toolInputSummary(payload) } : {}),
91
+ ...(toolResponseSummary(payload) ? { toolResponse: toolResponseSummary(payload) } : {}),
92
+ }
93
+ }
94
+
95
+ function writeEvent(record, env = process.env) {
96
+ const eventsPath = resolveEventsPath(env)
97
+ if (!eventsPath) return { written: false, reason: 'not_configured' }
98
+ mkdirSync(dirname(eventsPath), { recursive: true })
99
+ appendFileSync(eventsPath, `${JSON.stringify(record)}\n`, 'utf-8')
100
+ return { written: true, eventsPath }
101
+ }
102
+
103
+ export function recordSymphonyCodexHookEvent(payload, options = {}) {
104
+ const env = options.env ?? process.env
105
+ const now = options.now ?? new Date()
106
+ const record = buildEvent(payload, env, now)
107
+ return {
108
+ record,
109
+ ...writeEvent(record, env),
110
+ }
111
+ }
112
+
113
+ if (process.argv[1] && resolve(process.argv[1]) === resolve(fileURLToPath(import.meta.url))) {
114
+ try {
115
+ recordSymphonyCodexHookEvent(readStdinJson())
116
+ } catch (error) {
117
+ process.stderr.write(`[linx-symphony-hook] ${error instanceof Error ? error.message : String(error)}\n`)
118
+ }
119
+ }
@@ -0,0 +1,335 @@
1
+ import { createInterface } from 'node:readline';
2
+ import { join, resolve } from 'node:path';
3
+ import { mkdirSync, readFileSync, writeFileSync } from 'node:fs';
4
+ import { fileURLToPath } from 'node:url';
5
+ import { createSymphonyDeliveryUri, getSymphonyArchiveRelativePaths, normalizeSymphonyRuntimeDeliveryResult as normalizeSymphonyDeliveryResult, reconcileSymphonyThreadEvents, SYMPHONY_HOME_DIRNAME, } from '@linx/agent-runtime/symphony';
6
+ const PROTOCOL_VERSION = '2025-03-26';
7
+ const SERVER_INFO = {
8
+ name: 'linx-symphony-codex',
9
+ title: 'LinX Symphony',
10
+ version: '0.1.0',
11
+ };
12
+ export function createSymphonyCodexMcpServer(options = {}) {
13
+ const input = options.input ?? process.stdin;
14
+ const output = options.output ?? process.stdout;
15
+ const err = options.err ?? process.stderr;
16
+ const env = options.env ?? process.env;
17
+ async function handleMessage(message) {
18
+ if (typeof message.method !== 'string') {
19
+ return null;
20
+ }
21
+ const id = readJsonRpcId(message.id);
22
+ const method = message.method;
23
+ if (method === 'notifications/initialized' || method.startsWith('notifications/')) {
24
+ return null;
25
+ }
26
+ try {
27
+ if (method === 'initialize') {
28
+ return response(id, {
29
+ protocolVersion: readProtocolVersion(message.params) ?? PROTOCOL_VERSION,
30
+ capabilities: {
31
+ tools: {
32
+ listChanged: false,
33
+ },
34
+ },
35
+ serverInfo: SERVER_INFO,
36
+ });
37
+ }
38
+ if (method === 'ping') {
39
+ return response(id, {});
40
+ }
41
+ if (method === 'tools/list') {
42
+ return response(id, {
43
+ tools: buildToolDefinitions(),
44
+ });
45
+ }
46
+ if (method === 'tools/call') {
47
+ return response(id, await handleToolCall(readParamsObject(message.params), env));
48
+ }
49
+ return errorResponse(id, -32601, `Unknown MCP method: ${method}`);
50
+ }
51
+ catch (error) {
52
+ return errorResponse(id, -32000, error instanceof Error ? error.message : String(error));
53
+ }
54
+ }
55
+ return {
56
+ handleMessage,
57
+ async run() {
58
+ const rl = createInterface({ input, crlfDelay: Infinity });
59
+ for await (const line of rl) {
60
+ const trimmed = line.trim();
61
+ if (!trimmed)
62
+ continue;
63
+ try {
64
+ const parsed = JSON.parse(trimmed);
65
+ if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed))
66
+ continue;
67
+ const reply = await handleMessage(parsed);
68
+ if (reply) {
69
+ output.write(`${JSON.stringify(reply)}\n`);
70
+ }
71
+ }
72
+ catch (error) {
73
+ err.write(`[linx-symphony-codex-mcp] ${error instanceof Error ? error.message : String(error)}\n`);
74
+ }
75
+ }
76
+ return 0;
77
+ },
78
+ };
79
+ }
80
+ async function handleToolCall(params, env) {
81
+ const name = typeof params.name === 'string' ? params.name : '';
82
+ const args = readParamsObject(params.arguments);
83
+ if (name === 'delivery_status') {
84
+ const podRoot = resolvePodMirrorRoot(args, env);
85
+ return toolResult({
86
+ configured: true,
87
+ podRoot,
88
+ instructions: 'Call submit_delivery with the final worker report before ending this Codex session.',
89
+ });
90
+ }
91
+ if (name === 'validate_delivery') {
92
+ const normalized = normalizeDeliveryFromToolArgs(args);
93
+ return toolResult({
94
+ valid: true,
95
+ status: normalized.status,
96
+ exitCode: normalized.exitCode,
97
+ eventCount: normalized.events.length,
98
+ hasReport: Boolean(normalized.reportText),
99
+ autoModeSessionId: normalized.autoModeSessionId ?? null,
100
+ });
101
+ }
102
+ if (name === 'submit_delivery') {
103
+ const podRoot = resolvePodMirrorRoot(args, env);
104
+ const normalized = normalizeDeliveryFromToolArgs(args);
105
+ const submitted = writeDeliveryToPodMirror(args, normalized, podRoot);
106
+ return toolResult({
107
+ submitted: true,
108
+ podRoot,
109
+ ...submitted,
110
+ status: normalized.status,
111
+ exitCode: normalized.exitCode,
112
+ eventCount: normalized.events.length,
113
+ hasReport: Boolean(normalized.reportText),
114
+ autoModeSessionId: normalized.autoModeSessionId ?? null,
115
+ });
116
+ }
117
+ if (name === 'reconcile') {
118
+ return toolResult(reconcileSymphonyThreadEvents({
119
+ chat: readOptionalString(args.chat),
120
+ thread: readOptionalString(args.thread),
121
+ randomId: readOptionalString(args.randomId),
122
+ events: readThreadReconcileEvents(args, env),
123
+ }));
124
+ }
125
+ return toolResult({ error: `Unknown Symphony tool: ${name}` }, true);
126
+ }
127
+ function normalizeDeliveryFromToolArgs(args) {
128
+ const delivery = readDeliveryInput(args.delivery);
129
+ const candidate = normalizeSymphonyDeliveryResult(delivery ?? {
130
+ status: args.status,
131
+ exitCode: args.exitCode,
132
+ autoModeSessionId: args.autoModeSessionId,
133
+ events: args.events,
134
+ report: args.report,
135
+ reportText: args.reportText,
136
+ });
137
+ if (!candidate) {
138
+ throw new Error('Invalid Symphony Delivery. Provide a delivery object or fields with status/events/report.');
139
+ }
140
+ return candidate;
141
+ }
142
+ function writeDeliveryToPodMirror(args, normalized, podRoot) {
143
+ const deliveryUri = readOptionalString(args.deliveryUri)
144
+ ?? createSymphonyDeliveryUri({ randomId: readOptionalString(args.randomId) ?? normalized.autoModeSessionId });
145
+ const paths = getSymphonyArchiveRelativePaths(deliveryUri, 'delivery');
146
+ const deliveryDir = join(podRoot, SYMPHONY_HOME_DIRNAME, paths.dir);
147
+ const deliveryFile = join(podRoot, SYMPHONY_HOME_DIRNAME, paths.file);
148
+ const reportFile = normalized.reportText ? join(deliveryDir, 'report.md') : undefined;
149
+ const eventsFile = normalized.events.length > 0 ? join(deliveryDir, 'events.jsonl') : undefined;
150
+ mkdirSync(deliveryDir, { recursive: true });
151
+ writeFileSync(deliveryFile, `${JSON.stringify({
152
+ symphonyDelivery: true,
153
+ uri: deliveryUri,
154
+ status: normalized.status,
155
+ exitCode: normalized.exitCode,
156
+ ...(normalized.autoModeSessionId ? { autoModeSessionId: normalized.autoModeSessionId } : {}),
157
+ eventCount: normalized.events.length,
158
+ ...(reportFile ? { reportFile: relativePodMirrorPath(podRoot, reportFile) } : {}),
159
+ ...(eventsFile ? { eventsFile: relativePodMirrorPath(podRoot, eventsFile) } : {}),
160
+ submittedAt: new Date().toISOString(),
161
+ }, null, 2)}\n`, 'utf-8');
162
+ if (reportFile) {
163
+ writeFileSync(reportFile, `${normalized.reportText}\n`, 'utf-8');
164
+ }
165
+ if (eventsFile) {
166
+ writeFileSync(eventsFile, `${normalized.events.map((event) => JSON.stringify(event)).join('\n')}\n`, 'utf-8');
167
+ }
168
+ return {
169
+ deliveryUri,
170
+ deliveryFile,
171
+ ...(reportFile ? { reportFile } : {}),
172
+ ...(eventsFile ? { eventsFile } : {}),
173
+ };
174
+ }
175
+ function readDeliveryInput(value) {
176
+ if (typeof value === 'string' && value.trim()) {
177
+ const parsed = JSON.parse(value);
178
+ return parsed && typeof parsed === 'object' && !Array.isArray(parsed) ? parsed : undefined;
179
+ }
180
+ return value && typeof value === 'object' && !Array.isArray(value) ? value : undefined;
181
+ }
182
+ function resolvePodMirrorRoot(args, env) {
183
+ return resolve(readOptionalString(args.podRoot)
184
+ ?? readOptionalString(env.LINX_POD_MIRROR_ROOT)
185
+ ?? join(process.cwd(), '.pod'));
186
+ }
187
+ function relativePodMirrorPath(podRoot, path) {
188
+ return path.startsWith(`${podRoot}/`) ? path.slice(podRoot.length + 1) : path;
189
+ }
190
+ function buildToolDefinitions() {
191
+ return [
192
+ {
193
+ name: 'delivery_status',
194
+ title: 'Delivery Status',
195
+ description: 'Report the local Pod mirror root where Codex worker Deliveries will be written.',
196
+ inputSchema: {
197
+ type: 'object',
198
+ properties: {
199
+ podRoot: { type: 'string', description: 'Optional local Pod mirror root. Defaults to LINX_POD_MIRROR_ROOT or ./.pod.' },
200
+ },
201
+ additionalProperties: false,
202
+ },
203
+ },
204
+ {
205
+ name: 'validate_delivery',
206
+ title: 'Validate Delivery',
207
+ description: 'Validate a Symphony worker Delivery without writing it.',
208
+ inputSchema: deliveryInputSchema(),
209
+ },
210
+ {
211
+ name: 'submit_delivery',
212
+ title: 'Submit Delivery',
213
+ description: 'Write a Symphony worker Delivery into the local Pod mirror for later Pod sync.',
214
+ inputSchema: {
215
+ ...deliveryInputSchema(),
216
+ properties: {
217
+ ...deliveryInputSchema().properties,
218
+ podRoot: { type: 'string', description: 'Optional local Pod mirror root. Defaults to LINX_POD_MIRROR_ROOT or ./.pod.' },
219
+ deliveryUri: { type: 'string', description: 'Optional stable Delivery URI.' },
220
+ randomId: { type: 'string', description: 'Optional stable id seed when creating a Delivery URI.' },
221
+ },
222
+ },
223
+ },
224
+ {
225
+ name: 'reconcile',
226
+ title: 'Reconcile',
227
+ description: 'Run the storage-agnostic Symphony reconciler over Codex events. This is the Codex-side MCP runner; Pod writes stay in LinX/xpod adapters.',
228
+ inputSchema: {
229
+ type: 'object',
230
+ properties: {
231
+ chat: { type: 'string', description: 'Optional Chat URI or portable chat reference.' },
232
+ thread: { type: 'string', description: 'Optional Thread URI or portable thread reference.' },
233
+ randomId: { type: 'string', description: 'Optional stable id seed for deterministic reconciler ids.' },
234
+ events: {
235
+ type: 'array',
236
+ description: 'Thread control events or redacted Codex hook events to reconcile.',
237
+ items: { type: 'object', additionalProperties: true },
238
+ },
239
+ eventsPath: {
240
+ type: 'string',
241
+ description: 'Optional JSONL path containing redacted Codex hook events. Defaults to LINX_SYMPHONY_HOOK_EVENTS when set.',
242
+ },
243
+ },
244
+ additionalProperties: false,
245
+ },
246
+ },
247
+ ];
248
+ }
249
+ function deliveryInputSchema() {
250
+ return {
251
+ type: 'object',
252
+ properties: {
253
+ delivery: {
254
+ description: 'Full Symphony Delivery object or JSON string. Preferred when available.',
255
+ anyOf: [{ type: 'object', additionalProperties: true }, { type: 'string' }],
256
+ },
257
+ status: { type: 'string', enum: ['completed', 'failed', 'success', 'succeeded', 'ok', 'failure', 'error'] },
258
+ exitCode: { type: 'number' },
259
+ autoModeSessionId: { type: 'string' },
260
+ events: { type: 'array', items: { type: 'object', additionalProperties: true } },
261
+ report: { description: 'Structured final report.', type: 'object', additionalProperties: true },
262
+ reportText: { type: 'string' },
263
+ },
264
+ additionalProperties: false,
265
+ };
266
+ }
267
+ function toolResult(structuredContent, isError = false) {
268
+ const text = typeof structuredContent === 'string'
269
+ ? structuredContent
270
+ : JSON.stringify(structuredContent, null, 2);
271
+ return {
272
+ content: [{ type: 'text', text }],
273
+ structuredContent,
274
+ isError,
275
+ };
276
+ }
277
+ function readParamsObject(value) {
278
+ return value && typeof value === 'object' && !Array.isArray(value) ? value : {};
279
+ }
280
+ function readThreadReconcileEvents(args, env) {
281
+ const inline = readRecordArray(args.events);
282
+ const eventsPath = readOptionalString(args.eventsPath) ?? readOptionalString(env.LINX_SYMPHONY_HOOK_EVENTS);
283
+ if (!eventsPath) {
284
+ return inline;
285
+ }
286
+ return [...readJsonlRecords(eventsPath), ...inline];
287
+ }
288
+ function readRecordArray(value) {
289
+ return Array.isArray(value)
290
+ ? value.filter((item) => Boolean(item) && typeof item === 'object' && !Array.isArray(item))
291
+ : [];
292
+ }
293
+ function readJsonlRecords(path) {
294
+ const body = readFileSync(path, 'utf-8');
295
+ return body
296
+ .split(/\r?\n/u)
297
+ .map((line) => line.trim())
298
+ .filter(Boolean)
299
+ .map((line) => JSON.parse(line))
300
+ .filter((item) => Boolean(item) && typeof item === 'object' && !Array.isArray(item));
301
+ }
302
+ function readOptionalString(value) {
303
+ return typeof value === 'string' && value.trim() ? value.trim() : undefined;
304
+ }
305
+ function readJsonRpcId(value) {
306
+ if (typeof value === 'string' || typeof value === 'number' || value === null) {
307
+ return value;
308
+ }
309
+ return null;
310
+ }
311
+ function readProtocolVersion(params) {
312
+ const object = readParamsObject(params);
313
+ return typeof object.protocolVersion === 'string' ? object.protocolVersion : undefined;
314
+ }
315
+ function response(id, result) {
316
+ return { jsonrpc: '2.0', id, result };
317
+ }
318
+ function errorResponse(id, code, message) {
319
+ return {
320
+ jsonrpc: '2.0',
321
+ id,
322
+ error: { code, message },
323
+ };
324
+ }
325
+ if (process.argv[1] && resolve(process.argv[1]) === resolve(fileURLToPath(import.meta.url))) {
326
+ createSymphonyCodexMcpServer().run()
327
+ .then((code) => {
328
+ process.exitCode = code;
329
+ })
330
+ .catch((error) => {
331
+ process.stderr.write(`[linx-symphony-codex-mcp] ${error instanceof Error ? error.message : String(error)}\n`);
332
+ process.exitCode = 1;
333
+ });
334
+ }
335
+ //# sourceMappingURL=symphony-mcp.js.map