skill-flow 1.3.1 → 1.3.4

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.
@@ -1,385 +1,443 @@
1
- import { buildBridgeResponse, isJsonObject, } from "@skill-flow/shared-types/protocol";
2
- export async function executeBridgeRequest(app, request) {
1
+ // ../../packages/shared-types/dist/protocol.js
2
+ var PROTOCOL_VERSION = "1.0";
3
+ function buildBridgeResponse(args) {
4
+ return {
5
+ protocolVersion: PROTOCOL_VERSION,
6
+ command: args.command,
7
+ ...args.requestId ? { requestId: args.requestId } : {},
8
+ ok: args.ok,
9
+ ...args.data !== void 0 ? { data: args.data } : {},
10
+ warnings: args.warnings ?? [],
11
+ errors: args.errors ?? []
12
+ };
13
+ }
14
+ function isJsonObject(value) {
15
+ return typeof value === "object" && value !== null && !Array.isArray(value);
16
+ }
17
+
18
+ // src/bridge-command.ts
19
+ async function executeBridgeRequest(app, request) {
20
+ try {
21
+ const previousCaller = process.env.SKILL_FLOW_CALLER;
22
+ process.env.SKILL_FLOW_CALLER = previousCaller?.trim() || "bridge";
3
23
  try {
4
- const previousCaller = process.env.SKILL_FLOW_CALLER;
5
- process.env.SKILL_FLOW_CALLER = previousCaller?.trim() || "bridge";
6
- try {
7
- switch (request.command) {
8
- case "bootstrap": {
9
- const result = await app.bootstrapWorkspaceState();
10
- if (!result.ok) {
11
- return toFailureResponse(request, result.errors, result.warnings);
12
- }
13
- return buildResponseWithRequest({
14
- request,
15
- ok: true,
16
- data: sanitizeForJson(result.data),
17
- warnings: result.warnings.map((warning) => ({
18
- code: warning.code,
19
- message: warning.message,
20
- })),
21
- });
22
- }
23
- case "list": {
24
- const result = await app.listWorkflows();
25
- if (!result.ok) {
26
- return toFailureResponse(request, result.errors, result.warnings);
27
- }
28
- return buildResponseWithRequest({
29
- request,
30
- ok: true,
31
- data: sanitizeForJson(result.data),
32
- warnings: result.warnings.map((warning) => ({
33
- code: warning.code,
34
- message: warning.message,
35
- })),
36
- });
37
- }
38
- case "inspect": {
39
- const payload = expectObjectPayload(request.payload, "inspect");
40
- const sourceId = expectString(payload.sourceId, "sourceId", "inspect");
41
- const scope = expectProjectScope(payload.scope);
42
- const result = await app.inspectSource(sourceId, scope);
43
- if (!result.ok) {
44
- return toFailureResponse(request, result.errors, result.warnings);
45
- }
46
- return buildResponseWithRequest({
47
- request,
48
- ok: true,
49
- data: sanitizeForJson(result.data),
50
- warnings: result.warnings.map((warning) => ({
51
- code: warning.code,
52
- message: warning.message,
53
- })),
54
- });
55
- }
56
- case "inspect-enrichment": {
57
- const payload = expectObjectPayload(request.payload, "inspect-enrichment");
58
- const sourceId = expectString(payload.sourceId, "sourceId", "inspect-enrichment");
59
- const result = await app.inspectSourceEnrichment(sourceId);
60
- if (!result.ok) {
61
- return toFailureResponse(request, result.errors, result.warnings);
62
- }
63
- return buildResponseWithRequest({
64
- request,
65
- ok: true,
66
- data: sanitizeForJson(result.data),
67
- warnings: result.warnings.map((warning) => ({
68
- code: warning.code,
69
- message: warning.message,
70
- })),
71
- });
72
- }
73
- case "search-import-groups": {
74
- const payload = expectOptionalObject(request.payload, "search-import-groups");
75
- const query = payload ? expectOptionalString(payload.query, "query", "search-import-groups") : undefined;
76
- const result = await app.searchImportGroups(query ?? "");
77
- if (!result.ok) {
78
- return toFailureResponse(request, result.errors, result.warnings);
79
- }
80
- return buildResponseWithRequest({
81
- request,
82
- ok: true,
83
- data: sanitizeForJson(result.data),
84
- warnings: result.warnings.map((warning) => ({
85
- code: warning.code,
86
- message: warning.message,
87
- })),
88
- });
89
- }
90
- case "preview-import-source": {
91
- const payload = expectObjectPayload(request.payload, "preview-import-source");
92
- const locator = expectString(payload.locator, "locator", "preview-import-source");
93
- const result = await app.previewImportSource(locator);
94
- if (!result.ok) {
95
- return toFailureResponse(request, result.errors, result.warnings);
96
- }
97
- return buildResponseWithRequest({
98
- request,
99
- ok: true,
100
- data: sanitizeForJson(result.data),
101
- warnings: result.warnings.map((warning) => ({
102
- code: warning.code,
103
- message: warning.message,
104
- })),
105
- });
106
- }
107
- case "import-source": {
108
- const payload = expectObjectPayload(request.payload, "import-source");
109
- const locator = expectString(payload.locator, "locator", "import-source");
110
- const draft = expectOptionalImportDraft(payload.draft);
111
- const result = await app.importSource(locator, draft);
112
- if (!result.ok) {
113
- return toFailureResponse(request, result.errors, result.warnings);
114
- }
115
- return buildResponseWithRequest({
116
- request,
117
- ok: true,
118
- data: sanitizeForJson(result.data),
119
- warnings: result.warnings.map((warning) => ({
120
- code: warning.code,
121
- message: warning.message,
122
- })),
123
- });
124
- }
125
- case "toggle-pin": {
126
- const payload = expectObjectPayload(request.payload, "toggle-pin");
127
- const sourceId = expectString(payload.sourceId, "sourceId", "toggle-pin");
128
- const result = await app.togglePinnedSource(sourceId);
129
- if (!result.ok) {
130
- return toFailureResponse(request, result.errors, result.warnings);
131
- }
132
- return buildResponseWithRequest({
133
- request,
134
- ok: true,
135
- data: sanitizeForJson(result.data),
136
- warnings: result.warnings.map((warning) => ({
137
- code: warning.code,
138
- message: warning.message,
139
- })),
140
- });
141
- }
142
- case "doctor": {
143
- const result = await app.doctor();
144
- if (!result.ok) {
145
- return toFailureResponse(request, result.errors, result.warnings);
146
- }
147
- return buildResponseWithRequest({
148
- request,
149
- ok: true,
150
- data: sanitizeForJson(result.data),
151
- warnings: result.warnings.map((warning) => ({
152
- code: warning.code,
153
- message: warning.message,
154
- })),
155
- });
156
- }
157
- case "add": {
158
- const payload = expectObjectPayload(request.payload, "add");
159
- const locator = expectString(payload.locator, "locator", "add");
160
- const options = expectOptionalObject(payload.options, "add.options");
161
- const applyNow = payload.applyNow === true;
162
- const result = applyNow
163
- ? await app.addSource(locator, options)
164
- : await app.prepareAddSource(locator, options);
165
- if (!result.ok) {
166
- return toFailureResponse(request, result.errors, result.warnings);
167
- }
168
- return buildResponseWithRequest({
169
- request,
170
- ok: true,
171
- data: sanitizeForJson(result.data),
172
- warnings: result.warnings.map((warning) => ({
173
- code: warning.code,
174
- message: warning.message,
175
- })),
176
- });
177
- }
178
- case "apply": {
179
- const payload = expectObjectPayload(request.payload, "apply");
180
- const sourceId = expectString(payload.sourceId, "sourceId", "apply");
181
- const draft = expectDraftBinding(payload.draft);
182
- const scope = expectProjectScope(payload.scope);
183
- const result = await app.applyDraft(sourceId, draft, scope);
184
- if (!result.ok) {
185
- return toFailureResponse(request, result.errors, result.warnings);
186
- }
187
- return buildResponseWithRequest({
188
- request,
189
- ok: true,
190
- data: sanitizeForJson(result.data),
191
- warnings: result.warnings.map((warning) => ({
192
- code: warning.code,
193
- message: warning.message,
194
- })),
195
- });
196
- }
197
- case "update": {
198
- const payload = expectOptionalObject(request.payload, "update");
199
- const sourceIds = parseOptionalStringArray(payload?.sourceIds, "update.sourceIds");
200
- const result = await app.updateSources(sourceIds);
201
- if (!result.ok) {
202
- return toFailureResponse(request, result.errors, result.warnings);
203
- }
204
- return buildResponseWithRequest({
205
- request,
206
- ok: true,
207
- data: sanitizeForJson(result.data),
208
- warnings: result.warnings.map((warning) => ({
209
- code: warning.code,
210
- message: warning.message,
211
- })),
212
- });
213
- }
214
- case "uninstall": {
215
- const payload = expectObjectPayload(request.payload, "uninstall");
216
- const sourceIds = parseRequiredStringArray(payload.sourceIds, "uninstall.sourceIds");
217
- const result = await app.uninstall(sourceIds);
218
- if (!result.ok) {
219
- return toFailureResponse(request, result.errors, result.warnings);
220
- }
221
- return buildResponseWithRequest({
222
- request,
223
- ok: true,
224
- data: sanitizeForJson(result.data),
225
- });
226
- }
227
- default:
228
- return buildResponseWithRequest({
229
- request,
230
- ok: false,
231
- errors: [
232
- {
233
- code: "UNSUPPORTED_COMMAND",
234
- message: `Bridge command '${request.command}' is not supported.`,
235
- },
236
- ],
237
- });
238
- }
24
+ switch (request.command) {
25
+ case "bootstrap": {
26
+ const result = await app.bootstrapWorkspaceState();
27
+ if (!result.ok) {
28
+ return toFailureResponse(request, result.errors, result.warnings);
29
+ }
30
+ return buildResponseWithRequest({
31
+ request,
32
+ ok: true,
33
+ data: sanitizeForJson(result.data),
34
+ warnings: result.warnings.map((warning) => ({
35
+ code: warning.code,
36
+ message: warning.message
37
+ }))
38
+ });
239
39
  }
240
- finally {
241
- if (previousCaller === undefined) {
242
- delete process.env.SKILL_FLOW_CALLER;
243
- }
244
- else {
245
- process.env.SKILL_FLOW_CALLER = previousCaller;
246
- }
40
+ case "list": {
41
+ const result = await app.listWorkflows();
42
+ if (!result.ok) {
43
+ return toFailureResponse(request, result.errors, result.warnings);
44
+ }
45
+ return buildResponseWithRequest({
46
+ request,
47
+ ok: true,
48
+ data: sanitizeForJson(result.data),
49
+ warnings: result.warnings.map((warning) => ({
50
+ code: warning.code,
51
+ message: warning.message
52
+ }))
53
+ });
247
54
  }
248
- }
249
- catch (error) {
250
- return buildResponseWithRequest({
55
+ case "inspect": {
56
+ const payload = expectObjectPayload(request.payload, "inspect");
57
+ const sourceId = expectString(payload.sourceId, "sourceId", "inspect");
58
+ const scope = expectProjectScope(payload.scope);
59
+ const result = await app.inspectSource(sourceId, scope);
60
+ if (!result.ok) {
61
+ return toFailureResponse(request, result.errors, result.warnings);
62
+ }
63
+ return buildResponseWithRequest({
64
+ request,
65
+ ok: true,
66
+ data: sanitizeForJson(result.data),
67
+ warnings: result.warnings.map((warning) => ({
68
+ code: warning.code,
69
+ message: warning.message
70
+ }))
71
+ });
72
+ }
73
+ case "inspect-enrichment": {
74
+ const payload = expectObjectPayload(request.payload, "inspect-enrichment");
75
+ const sourceId = expectString(payload.sourceId, "sourceId", "inspect-enrichment");
76
+ const result = await app.inspectSourceEnrichment(sourceId);
77
+ if (!result.ok) {
78
+ return toFailureResponse(request, result.errors, result.warnings);
79
+ }
80
+ return buildResponseWithRequest({
81
+ request,
82
+ ok: true,
83
+ data: sanitizeForJson(result.data),
84
+ warnings: result.warnings.map((warning) => ({
85
+ code: warning.code,
86
+ message: warning.message
87
+ }))
88
+ });
89
+ }
90
+ case "search-import-groups": {
91
+ const payload = expectOptionalObject(request.payload, "search-import-groups");
92
+ const query = payload ? expectOptionalString(payload.query, "query", "search-import-groups") : void 0;
93
+ const result = await app.searchImportGroups(query ?? "");
94
+ if (!result.ok) {
95
+ return toFailureResponse(request, result.errors, result.warnings);
96
+ }
97
+ return buildResponseWithRequest({
98
+ request,
99
+ ok: true,
100
+ data: sanitizeForJson(result.data),
101
+ warnings: result.warnings.map((warning) => ({
102
+ code: warning.code,
103
+ message: warning.message
104
+ }))
105
+ });
106
+ }
107
+ case "preview-import-source": {
108
+ const payload = expectObjectPayload(request.payload, "preview-import-source");
109
+ const locator = expectString(payload.locator, "locator", "preview-import-source");
110
+ const result = await app.previewImportSource(locator);
111
+ if (!result.ok) {
112
+ return toFailureResponse(request, result.errors, result.warnings);
113
+ }
114
+ return buildResponseWithRequest({
115
+ request,
116
+ ok: true,
117
+ data: sanitizeForJson(result.data),
118
+ warnings: result.warnings.map((warning) => ({
119
+ code: warning.code,
120
+ message: warning.message
121
+ }))
122
+ });
123
+ }
124
+ case "import-source": {
125
+ const payload = expectObjectPayload(request.payload, "import-source");
126
+ const locator = expectString(payload.locator, "locator", "import-source");
127
+ const draft = expectOptionalImportDraft(payload.draft);
128
+ const result = await app.importSource(locator, draft);
129
+ if (!result.ok) {
130
+ return toFailureResponse(request, result.errors, result.warnings);
131
+ }
132
+ return buildResponseWithRequest({
133
+ request,
134
+ ok: true,
135
+ data: sanitizeForJson(result.data),
136
+ warnings: result.warnings.map((warning) => ({
137
+ code: warning.code,
138
+ message: warning.message
139
+ }))
140
+ });
141
+ }
142
+ case "toggle-pin": {
143
+ const payload = expectObjectPayload(request.payload, "toggle-pin");
144
+ const sourceId = expectString(payload.sourceId, "sourceId", "toggle-pin");
145
+ const result = await app.togglePinnedSource(sourceId);
146
+ if (!result.ok) {
147
+ return toFailureResponse(request, result.errors, result.warnings);
148
+ }
149
+ return buildResponseWithRequest({
150
+ request,
151
+ ok: true,
152
+ data: sanitizeForJson(result.data),
153
+ warnings: result.warnings.map((warning) => ({
154
+ code: warning.code,
155
+ message: warning.message
156
+ }))
157
+ });
158
+ }
159
+ case "doctor": {
160
+ const result = await app.doctor();
161
+ if (!result.ok) {
162
+ return toFailureResponse(request, result.errors, result.warnings);
163
+ }
164
+ return buildResponseWithRequest({
165
+ request,
166
+ ok: true,
167
+ data: sanitizeForJson(result.data),
168
+ warnings: result.warnings.map((warning) => ({
169
+ code: warning.code,
170
+ message: warning.message
171
+ }))
172
+ });
173
+ }
174
+ case "add": {
175
+ const payload = expectObjectPayload(request.payload, "add");
176
+ const locator = expectString(payload.locator, "locator", "add");
177
+ const options = expectOptionalObject(payload.options, "add.options");
178
+ const applyNow = payload.applyNow === true;
179
+ const result = applyNow ? await app.addSource(locator, options) : await app.prepareAddSource(locator, options);
180
+ if (!result.ok) {
181
+ return toFailureResponse(request, result.errors, result.warnings);
182
+ }
183
+ return buildResponseWithRequest({
184
+ request,
185
+ ok: true,
186
+ data: sanitizeForJson(result.data),
187
+ warnings: result.warnings.map((warning) => ({
188
+ code: warning.code,
189
+ message: warning.message
190
+ }))
191
+ });
192
+ }
193
+ case "apply": {
194
+ const payload = expectObjectPayload(request.payload, "apply");
195
+ const sourceId = expectString(payload.sourceId, "sourceId", "apply");
196
+ const draft = expectDraftBinding(payload.draft);
197
+ const scope = expectProjectScope(payload.scope);
198
+ const result = await app.applyDraft(sourceId, draft, scope);
199
+ if (!result.ok) {
200
+ return toFailureResponse(request, result.errors, result.warnings);
201
+ }
202
+ return buildResponseWithRequest({
203
+ request,
204
+ ok: true,
205
+ data: sanitizeForJson(result.data),
206
+ warnings: result.warnings.map((warning) => ({
207
+ code: warning.code,
208
+ message: warning.message
209
+ }))
210
+ });
211
+ }
212
+ case "update": {
213
+ const payload = expectOptionalObject(request.payload, "update");
214
+ const sourceIds = parseOptionalStringArray(payload?.sourceIds, "update.sourceIds");
215
+ const result = await app.updateSources(sourceIds);
216
+ if (!result.ok) {
217
+ return toFailureResponse(request, result.errors, result.warnings);
218
+ }
219
+ return buildResponseWithRequest({
220
+ request,
221
+ ok: true,
222
+ data: sanitizeForJson(result.data),
223
+ warnings: result.warnings.map((warning) => ({
224
+ code: warning.code,
225
+ message: warning.message
226
+ }))
227
+ });
228
+ }
229
+ case "uninstall": {
230
+ const payload = expectObjectPayload(request.payload, "uninstall");
231
+ const sourceIds = parseRequiredStringArray(payload.sourceIds, "uninstall.sourceIds");
232
+ const result = await app.uninstall(sourceIds);
233
+ if (!result.ok) {
234
+ return toFailureResponse(request, result.errors, result.warnings);
235
+ }
236
+ return buildResponseWithRequest({
237
+ request,
238
+ ok: true,
239
+ data: sanitizeForJson(result.data)
240
+ });
241
+ }
242
+ case "save-settings": {
243
+ const payload = expectObjectPayload(request.payload, "save-settings");
244
+ const customTargets = expectCustomTargets(payload.customTargets);
245
+ const agentDisplayOrder = parseOptionalStringArray(
246
+ payload.agentDisplayOrder,
247
+ "save-settings.agentDisplayOrder"
248
+ ) ?? [];
249
+ const result = await app.saveSettings({ customTargets, agentDisplayOrder });
250
+ if (!result.ok) {
251
+ return toFailureResponse(request, result.errors, result.warnings);
252
+ }
253
+ return buildResponseWithRequest({
254
+ request,
255
+ ok: true,
256
+ data: sanitizeForJson(result.data),
257
+ warnings: result.warnings.map((warning) => ({
258
+ code: warning.code,
259
+ message: warning.message
260
+ }))
261
+ });
262
+ }
263
+ default:
264
+ return buildResponseWithRequest({
251
265
  request,
252
266
  ok: false,
253
267
  errors: [
254
- {
255
- code: "BRIDGE_REQUEST_INVALID",
256
- message: error instanceof Error ? error.message : String(error),
257
- },
258
- ],
259
- });
268
+ {
269
+ code: "UNSUPPORTED_COMMAND",
270
+ message: `Bridge command '${request.command}' is not supported.`
271
+ }
272
+ ]
273
+ });
274
+ }
275
+ } finally {
276
+ if (previousCaller === void 0) {
277
+ delete process.env.SKILL_FLOW_CALLER;
278
+ } else {
279
+ process.env.SKILL_FLOW_CALLER = previousCaller;
280
+ }
260
281
  }
261
- }
262
- function toFailureResponse(request, errors, warnings) {
282
+ } catch (error) {
263
283
  return buildResponseWithRequest({
264
- request,
265
- ok: false,
266
- warnings: warnings.map((warning) => ({ code: warning.code, message: warning.message })),
267
- errors: errors.map((error) => ({ code: error.code, message: error.message })),
284
+ request,
285
+ ok: false,
286
+ errors: [
287
+ {
288
+ code: "BRIDGE_REQUEST_INVALID",
289
+ message: error instanceof Error ? error.message : String(error)
290
+ }
291
+ ]
268
292
  });
293
+ }
294
+ }
295
+ function toFailureResponse(request, errors, warnings) {
296
+ return buildResponseWithRequest({
297
+ request,
298
+ ok: false,
299
+ warnings: warnings.map((warning) => ({ code: warning.code, message: warning.message })),
300
+ errors: errors.map((error) => ({ code: error.code, message: error.message }))
301
+ });
269
302
  }
270
303
  function buildResponseWithRequest(args) {
271
- return buildBridgeResponse({
272
- command: args.request.command,
273
- ...(args.request.requestId ? { requestId: args.request.requestId } : {}),
274
- ok: args.ok,
275
- ...(args.data !== undefined ? { data: args.data } : {}),
276
- ...(args.warnings ? { warnings: args.warnings } : {}),
277
- ...(args.errors ? { errors: args.errors } : {}),
278
- });
304
+ return buildBridgeResponse({
305
+ command: args.request.command,
306
+ ...args.request.requestId ? { requestId: args.request.requestId } : {},
307
+ ok: args.ok,
308
+ ...args.data !== void 0 ? { data: args.data } : {},
309
+ ...args.warnings ? { warnings: args.warnings } : {},
310
+ ...args.errors ? { errors: args.errors } : {}
311
+ });
279
312
  }
280
313
  function expectObjectPayload(payload, command) {
281
- if (!isJsonObject(payload)) {
282
- throw new Error(`Bridge command '${command}' requires an object payload.`);
283
- }
284
- return payload;
314
+ if (!isJsonObject(payload)) {
315
+ throw new Error(`Bridge command '${command}' requires an object payload.`);
316
+ }
317
+ return payload;
285
318
  }
286
319
  function expectOptionalObject(value, field) {
287
- if (value === undefined) {
288
- return undefined;
289
- }
290
- if (!isJsonObject(value)) {
291
- throw new Error(`Field '${field}' must be a JSON object when provided.`);
292
- }
293
- return value;
320
+ if (value === void 0) {
321
+ return void 0;
322
+ }
323
+ if (!isJsonObject(value)) {
324
+ throw new Error(`Field '${field}' must be a JSON object when provided.`);
325
+ }
326
+ return value;
294
327
  }
295
328
  function expectString(value, field, command) {
296
- if (typeof value !== "string" || value.length === 0) {
297
- throw new Error(`Bridge command '${command}' requires a non-empty string field '${field}'.`);
298
- }
299
- return value;
329
+ if (typeof value !== "string" || value.length === 0) {
330
+ throw new Error(`Bridge command '${command}' requires a non-empty string field '${field}'.`);
331
+ }
332
+ return value;
300
333
  }
301
334
  function expectOptionalString(value, field, command) {
302
- if (value === undefined) {
303
- return undefined;
304
- }
305
- if (typeof value !== "string") {
306
- throw new Error(`Bridge command '${command}' requires string field '${field}' when provided.`);
307
- }
308
- return value;
335
+ if (value === void 0) {
336
+ return void 0;
337
+ }
338
+ if (typeof value !== "string") {
339
+ throw new Error(`Bridge command '${command}' requires string field '${field}' when provided.`);
340
+ }
341
+ return value;
309
342
  }
310
343
  function parseRequiredStringArray(value, field) {
311
- const parsed = parseOptionalStringArray(value, field);
312
- if (!parsed || parsed.length === 0) {
313
- throw new Error(`Field '${field}' must be a non-empty string array.`);
314
- }
315
- return parsed;
344
+ const parsed = parseOptionalStringArray(value, field);
345
+ if (!parsed || parsed.length === 0) {
346
+ throw new Error(`Field '${field}' must be a non-empty string array.`);
347
+ }
348
+ return parsed;
316
349
  }
317
350
  function parseOptionalStringArray(value, field) {
318
- if (value === undefined) {
319
- return undefined;
320
- }
321
- if (!Array.isArray(value) || value.some((item) => typeof item !== "string" || item.length === 0)) {
322
- throw new Error(`Field '${field}' must be a string array.`);
323
- }
324
- return value;
351
+ if (value === void 0) {
352
+ return void 0;
353
+ }
354
+ if (!Array.isArray(value) || value.some((item) => typeof item !== "string" || item.length === 0)) {
355
+ throw new Error(`Field '${field}' must be a string array.`);
356
+ }
357
+ return value;
325
358
  }
326
359
  function expectDraftBinding(value) {
327
- if (!isJsonObject(value)) {
328
- throw new Error("Bridge command 'apply' requires object field 'draft'.");
329
- }
330
- const selectedLeafIds = parseOptionalStringArray(value.selectedLeafIds, "draft.selectedLeafIds");
331
- if (!selectedLeafIds) {
332
- throw new Error("Field 'draft.selectedLeafIds' must be a string array.");
333
- }
334
- const enabledTargets = parseOptionalStringArray(value.enabledTargets, "draft.enabledTargets") ?? [];
335
- return {
336
- selectedLeafIds,
337
- enabledTargets: enabledTargets,
338
- };
360
+ if (!isJsonObject(value)) {
361
+ throw new Error("Bridge command 'apply' requires object field 'draft'.");
362
+ }
363
+ const selectedLeafIds = parseOptionalStringArray(value.selectedLeafIds, "draft.selectedLeafIds");
364
+ if (!selectedLeafIds) {
365
+ throw new Error("Field 'draft.selectedLeafIds' must be a string array.");
366
+ }
367
+ const enabledTargets = parseOptionalStringArray(value.enabledTargets, "draft.enabledTargets") ?? [];
368
+ return {
369
+ selectedLeafIds,
370
+ enabledTargets
371
+ };
339
372
  }
340
373
  function expectOptionalImportDraft(value) {
341
- if (value === undefined) {
342
- return undefined;
343
- }
344
- if (!isJsonObject(value)) {
345
- throw new Error("Field 'draft' must be a JSON object when provided.");
346
- }
347
- const selectedSkillIds = parseOptionalStringArray(value.selectedSkillIds, "draft.selectedSkillIds");
348
- if (!selectedSkillIds) {
349
- throw new Error("Field 'draft.selectedSkillIds' must be a string array.");
374
+ if (value === void 0) {
375
+ return void 0;
376
+ }
377
+ if (!isJsonObject(value)) {
378
+ throw new Error("Field 'draft' must be a JSON object when provided.");
379
+ }
380
+ const selectedSkillIds = parseOptionalStringArray(value.selectedSkillIds, "draft.selectedSkillIds");
381
+ if (!selectedSkillIds) {
382
+ throw new Error("Field 'draft.selectedSkillIds' must be a string array.");
383
+ }
384
+ const enabledTargets = parseOptionalStringArray(value.enabledTargets, "draft.enabledTargets") ?? [];
385
+ return {
386
+ selectedSkillIds,
387
+ enabledTargets
388
+ };
389
+ }
390
+ function expectCustomTargets(value) {
391
+ if (!Array.isArray(value)) {
392
+ throw new Error("Field 'customTargets' must be an array.");
393
+ }
394
+ return value.map((entry, index) => {
395
+ if (!isJsonObject(entry)) {
396
+ throw new Error(`Field 'customTargets[${index}]' must be an object.`);
350
397
  }
351
- const enabledTargets = parseOptionalStringArray(value.enabledTargets, "draft.enabledTargets") ?? [];
352
398
  return {
353
- selectedSkillIds,
354
- enabledTargets: enabledTargets,
399
+ id: expectString(entry.id, `customTargets[${index}].id`, "save-settings"),
400
+ name: expectString(entry.name, `customTargets[${index}].name`, "save-settings"),
401
+ globalPath: expectString(entry.globalPath, `customTargets[${index}].globalPath`, "save-settings"),
402
+ projectPathTemplate: expectString(entry.projectPathTemplate, `customTargets[${index}].projectPathTemplate`, "save-settings"),
403
+ strategy: expectString(entry.strategy, `customTargets[${index}].strategy`, "save-settings"),
404
+ createdAt: expectString(entry.createdAt, `customTargets[${index}].createdAt`, "save-settings"),
405
+ updatedAt: expectString(entry.updatedAt, `customTargets[${index}].updatedAt`, "save-settings")
355
406
  };
407
+ });
356
408
  }
357
409
  function expectProjectScope(value) {
358
- if (value === undefined) {
359
- return { kind: "global" };
360
- }
361
- if (!isJsonObject(value) || typeof value.kind !== "string") {
362
- throw new Error("Field 'scope' must be a JSON object with kind 'global' or kind 'project' and a non-empty string 'projectId'.");
363
- }
364
- if (value.kind === "global") {
365
- return { kind: "global" };
410
+ if (value === void 0) {
411
+ return { kind: "global" };
412
+ }
413
+ if (!isJsonObject(value) || typeof value.kind !== "string") {
414
+ throw new Error(
415
+ "Field 'scope' must be a JSON object with kind 'global' or kind 'project' and a non-empty string 'projectId'."
416
+ );
417
+ }
418
+ if (value.kind === "global") {
419
+ return { kind: "global" };
420
+ }
421
+ if (value.kind === "project") {
422
+ if (typeof value.projectId === "string" && value.projectId.length > 0) {
423
+ return { kind: "project", projectId: value.projectId };
366
424
  }
367
- if (value.kind === "project") {
368
- if (typeof value.projectId === "string" && value.projectId.length > 0) {
369
- return { kind: "project", projectId: value.projectId };
370
- }
371
- throw new Error("Field 'scope.projectId' must be a non-empty string when scope.kind is 'project'.");
372
- }
373
- throw new Error("Field 'scope.kind' must be either 'global' or 'project'.");
425
+ throw new Error("Field 'scope.projectId' must be a non-empty string when scope.kind is 'project'.");
426
+ }
427
+ throw new Error("Field 'scope.kind' must be either 'global' or 'project'.");
374
428
  }
375
429
  function sanitizeForJson(value) {
376
- return JSON.parse(JSON.stringify(value));
430
+ return JSON.parse(JSON.stringify(value));
377
431
  }
378
- export function buildBridgeParseFailure(command, failure) {
379
- return buildBridgeResponse({
380
- command: command,
381
- ok: false,
382
- errors: [failure],
383
- });
432
+ function buildBridgeParseFailure(command, failure) {
433
+ return buildBridgeResponse({
434
+ command,
435
+ ok: false,
436
+ errors: [failure]
437
+ });
384
438
  }
385
- //# sourceMappingURL=bridge-command.js.map
439
+ export {
440
+ buildBridgeParseFailure,
441
+ executeBridgeRequest
442
+ };
443
+ //# sourceMappingURL=bridge-command.js.map