@ted-galago/wave-cli 0.1.5 → 0.1.6
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.
- package/README.md +161 -2
- package/dist/index.cjs +2506 -131
- package/dist/index.js +2503 -128
- package/package.json +2 -1
- package/scripts/benchmark-cli.mjs +626 -0
- package/scripts/verify-dev-api.mjs +341 -26
package/dist/index.js
CHANGED
|
@@ -187,6 +187,16 @@ function inferStatusFromGraphqlErrors(errors) {
|
|
|
187
187
|
if (!Array.isArray(errors) || errors.length === 0) {
|
|
188
188
|
return 400;
|
|
189
189
|
}
|
|
190
|
+
const codes = extractGraphqlErrorCodes(errors);
|
|
191
|
+
if (codes.includes("UNAUTHORIZED")) {
|
|
192
|
+
return 401;
|
|
193
|
+
}
|
|
194
|
+
if (codes.includes("NOT_FOUND")) {
|
|
195
|
+
return 404;
|
|
196
|
+
}
|
|
197
|
+
if (codes.includes("INVALID_SCOPE") || codes.includes("UNSUPPORTED_BRANCH")) {
|
|
198
|
+
return 400;
|
|
199
|
+
}
|
|
190
200
|
const text = JSON.stringify(errors).toLowerCase();
|
|
191
201
|
if (text.includes("unauthorized") || text.includes("not authenticated")) {
|
|
192
202
|
return 401;
|
|
@@ -202,13 +212,260 @@ function inferStatusFromGraphqlErrors(errors) {
|
|
|
202
212
|
}
|
|
203
213
|
return 400;
|
|
204
214
|
}
|
|
215
|
+
function extractGraphqlErrorCodes(errors) {
|
|
216
|
+
if (!Array.isArray(errors)) {
|
|
217
|
+
return [];
|
|
218
|
+
}
|
|
219
|
+
const codes = errors.map((entry) => {
|
|
220
|
+
if (!entry || typeof entry !== "object") return "";
|
|
221
|
+
const extensions = entry.extensions;
|
|
222
|
+
if (!extensions || typeof extensions !== "object") return "";
|
|
223
|
+
return String(extensions.code ?? "").toUpperCase();
|
|
224
|
+
}).filter((code) => code.length > 0);
|
|
225
|
+
return Array.from(new Set(codes));
|
|
226
|
+
}
|
|
227
|
+
function errorCodeFromGraphqlErrors(errors, status) {
|
|
228
|
+
const codes = extractGraphqlErrorCodes(errors);
|
|
229
|
+
if (codes.includes("UNAUTHORIZED")) {
|
|
230
|
+
return "missing_auth";
|
|
231
|
+
}
|
|
232
|
+
if (codes.includes("NOT_FOUND")) {
|
|
233
|
+
return "not_found";
|
|
234
|
+
}
|
|
235
|
+
if (codes.includes("INVALID_SCOPE")) {
|
|
236
|
+
return "invalid_scope";
|
|
237
|
+
}
|
|
238
|
+
if (codes.includes("UNSUPPORTED_BRANCH")) {
|
|
239
|
+
return "unsupported_branch";
|
|
240
|
+
}
|
|
241
|
+
if (status === 401) {
|
|
242
|
+
return "missing_auth";
|
|
243
|
+
}
|
|
244
|
+
if (status === 403) {
|
|
245
|
+
return "forbidden";
|
|
246
|
+
}
|
|
247
|
+
return `http_${status}`;
|
|
248
|
+
}
|
|
205
249
|
function errorFromGraphqlErrors(errors, status) {
|
|
206
250
|
return {
|
|
207
|
-
code:
|
|
251
|
+
code: errorCodeFromGraphqlErrors(errors, status),
|
|
208
252
|
message: "GraphQL request failed.",
|
|
209
253
|
details: { errors }
|
|
210
254
|
};
|
|
211
255
|
}
|
|
256
|
+
function findParentContextFromVariables(variables) {
|
|
257
|
+
const directParent = Object.entries(variables).find(([key, value]) => {
|
|
258
|
+
if (key === "organization_id" || key === "organizationId") return false;
|
|
259
|
+
if (!key.endsWith("_id") && !key.endsWith("Id")) return false;
|
|
260
|
+
return typeof value === "string" && value.trim().length > 0;
|
|
261
|
+
});
|
|
262
|
+
if (directParent) {
|
|
263
|
+
return { parentKey: directParent[0], parentId: String(directParent[1]) };
|
|
264
|
+
}
|
|
265
|
+
const params = variables.params && typeof variables.params === "object" && !Array.isArray(variables.params) ? variables.params : void 0;
|
|
266
|
+
if (!params) {
|
|
267
|
+
return {};
|
|
268
|
+
}
|
|
269
|
+
const rootObjectEntry = Object.entries(params).find(
|
|
270
|
+
([, value]) => value && typeof value === "object" && !Array.isArray(value)
|
|
271
|
+
);
|
|
272
|
+
if (!rootObjectEntry) {
|
|
273
|
+
return {};
|
|
274
|
+
}
|
|
275
|
+
const [, rootObject] = rootObjectEntry;
|
|
276
|
+
const parentEntry = Object.entries(rootObject).find(([key, value]) => {
|
|
277
|
+
if (!key.endsWith("_id") && !key.endsWith("Id")) return false;
|
|
278
|
+
return typeof value === "string" && value.trim().length > 0;
|
|
279
|
+
});
|
|
280
|
+
if (!parentEntry) {
|
|
281
|
+
return {};
|
|
282
|
+
}
|
|
283
|
+
return { parentKey: parentEntry[0], parentId: String(parentEntry[1]) };
|
|
284
|
+
}
|
|
285
|
+
function shouldAddSparse422Diagnostic(status, mutationPayload) {
|
|
286
|
+
if (status !== 422) {
|
|
287
|
+
return false;
|
|
288
|
+
}
|
|
289
|
+
const rawErrors = mutationPayload.errors && typeof mutationPayload.errors === "object" ? mutationPayload.errors : void 0;
|
|
290
|
+
if (!rawErrors) {
|
|
291
|
+
return true;
|
|
292
|
+
}
|
|
293
|
+
const dataErrors = rawErrors.data;
|
|
294
|
+
return Array.isArray(dataErrors) && dataErrors.length === 0;
|
|
295
|
+
}
|
|
296
|
+
function buildSparse422Diagnostic(input) {
|
|
297
|
+
const parentContext = findParentContextFromVariables(input.variables);
|
|
298
|
+
return {
|
|
299
|
+
operation: input.command,
|
|
300
|
+
field: input.field,
|
|
301
|
+
context: parentContext.parentKey && parentContext.parentId ? {
|
|
302
|
+
parentKey: parentContext.parentKey,
|
|
303
|
+
parentId: parentContext.parentId
|
|
304
|
+
} : {
|
|
305
|
+
message: "No explicit parent id found in request variables."
|
|
306
|
+
}
|
|
307
|
+
};
|
|
308
|
+
}
|
|
309
|
+
function isFeedbackCreateCommand(input) {
|
|
310
|
+
return input.operationType === "mutation" && input.command === "feedbacks.create";
|
|
311
|
+
}
|
|
312
|
+
function asRecord(value) {
|
|
313
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
314
|
+
return null;
|
|
315
|
+
}
|
|
316
|
+
return value;
|
|
317
|
+
}
|
|
318
|
+
function asNonEmptyString(value) {
|
|
319
|
+
if (typeof value !== "string") {
|
|
320
|
+
return null;
|
|
321
|
+
}
|
|
322
|
+
const trimmed = value.trim();
|
|
323
|
+
return trimmed.length > 0 ? trimmed : null;
|
|
324
|
+
}
|
|
325
|
+
function extractFeedbackIdentity(variables) {
|
|
326
|
+
const organizationId = asNonEmptyString(variables.organization_id) ?? asNonEmptyString(variables.organizationId);
|
|
327
|
+
const params = asRecord(variables.params);
|
|
328
|
+
const feedback = params ? asRecord(params.feedback) : null;
|
|
329
|
+
const name = feedback ? asNonEmptyString(feedback.name) : null;
|
|
330
|
+
const quarter = feedback ? asNonEmptyString(feedback.quarter) : null;
|
|
331
|
+
const year = feedback ? asNonEmptyString(feedback.year) : null;
|
|
332
|
+
if (!organizationId || !name || !quarter || !year) {
|
|
333
|
+
return null;
|
|
334
|
+
}
|
|
335
|
+
return {
|
|
336
|
+
organizationId,
|
|
337
|
+
name,
|
|
338
|
+
quarter,
|
|
339
|
+
year
|
|
340
|
+
};
|
|
341
|
+
}
|
|
342
|
+
function collectMessageStrings(value) {
|
|
343
|
+
if (typeof value === "string") {
|
|
344
|
+
return [value];
|
|
345
|
+
}
|
|
346
|
+
if (Array.isArray(value)) {
|
|
347
|
+
return value.flatMap((entry) => collectMessageStrings(entry));
|
|
348
|
+
}
|
|
349
|
+
if (!value || typeof value !== "object") {
|
|
350
|
+
return [];
|
|
351
|
+
}
|
|
352
|
+
return Object.values(value).flatMap(
|
|
353
|
+
(entry) => collectMessageStrings(entry)
|
|
354
|
+
);
|
|
355
|
+
}
|
|
356
|
+
function isDuplicateFeedbackMutationError(mutationPayload) {
|
|
357
|
+
const messages = collectMessageStrings(mutationPayload.errors);
|
|
358
|
+
return messages.some(
|
|
359
|
+
(message) => message.toLowerCase().includes("already been taken")
|
|
360
|
+
);
|
|
361
|
+
}
|
|
362
|
+
function extractFeedbackListNode(graph) {
|
|
363
|
+
const data = asRecord(graph.data);
|
|
364
|
+
const feedbacks = data ? asRecord(data.feedbacks) : null;
|
|
365
|
+
if (!feedbacks) {
|
|
366
|
+
return null;
|
|
367
|
+
}
|
|
368
|
+
const rows = Array.isArray(feedbacks.data) ? feedbacks.data : [];
|
|
369
|
+
const first = rows.find((entry) => asRecord(entry));
|
|
370
|
+
return first ? first : null;
|
|
371
|
+
}
|
|
372
|
+
function buildFeedbackReuseEnvelope(params) {
|
|
373
|
+
return {
|
|
374
|
+
envelope: buildEnvelope({
|
|
375
|
+
ok: true,
|
|
376
|
+
command: params.command,
|
|
377
|
+
status: params.status,
|
|
378
|
+
data: {
|
|
379
|
+
[params.field]: {
|
|
380
|
+
ok: true,
|
|
381
|
+
status: params.status,
|
|
382
|
+
errorCode: null,
|
|
383
|
+
data: {
|
|
384
|
+
data: params.feedbackNode
|
|
385
|
+
},
|
|
386
|
+
errors: null,
|
|
387
|
+
reusedExisting: true,
|
|
388
|
+
idempotency: {
|
|
389
|
+
reason: params.reason
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
},
|
|
393
|
+
error: null,
|
|
394
|
+
requestId: params.requestId
|
|
395
|
+
}),
|
|
396
|
+
exitCode: EXIT_CODES.success
|
|
397
|
+
};
|
|
398
|
+
}
|
|
399
|
+
function buildFeedbackFindRequestBody(command, identity) {
|
|
400
|
+
return buildGraphqlBody({
|
|
401
|
+
config: {
|
|
402
|
+
baseUrl: "http://localhost",
|
|
403
|
+
token: "placeholder",
|
|
404
|
+
timeoutMs: 1e3,
|
|
405
|
+
debug: false
|
|
406
|
+
},
|
|
407
|
+
command,
|
|
408
|
+
operationType: "query",
|
|
409
|
+
field: "feedbacks",
|
|
410
|
+
variables: {
|
|
411
|
+
organization_id: identity.organizationId,
|
|
412
|
+
name: identity.name,
|
|
413
|
+
quarter: identity.quarter,
|
|
414
|
+
year: identity.year,
|
|
415
|
+
page: 1,
|
|
416
|
+
per: 1
|
|
417
|
+
},
|
|
418
|
+
selectionSet: "{ data { id type attributes } count currentPage totalPages }"
|
|
419
|
+
});
|
|
420
|
+
}
|
|
421
|
+
async function requestGraphqlHttp(params) {
|
|
422
|
+
const response = await fetch(params.url, {
|
|
423
|
+
method: "POST",
|
|
424
|
+
headers: {
|
|
425
|
+
Authorization: `Bearer ${params.input.config.token}`,
|
|
426
|
+
Accept: "application/json",
|
|
427
|
+
"Content-Type": "application/json",
|
|
428
|
+
"X-Origin": "langgraph-cli",
|
|
429
|
+
"X-Request-Id": params.requestId,
|
|
430
|
+
...params.input.config.agentName ? { "X-Agent-Name": params.input.config.agentName } : {},
|
|
431
|
+
...params.input.config.agentRunId ? { "X-Agent-Run-Id": params.input.config.agentRunId } : {}
|
|
432
|
+
},
|
|
433
|
+
body: JSON.stringify(params.body),
|
|
434
|
+
signal: params.controller.signal
|
|
435
|
+
});
|
|
436
|
+
const responseRequestId = response.headers.get("x-request-id") ?? params.requestId;
|
|
437
|
+
const text = await response.text();
|
|
438
|
+
const payload = text ? parseJsonSafely(text) : null;
|
|
439
|
+
const graph = payload && typeof payload === "object" ? payload : {};
|
|
440
|
+
return {
|
|
441
|
+
status: response.status,
|
|
442
|
+
requestId: responseRequestId,
|
|
443
|
+
graph
|
|
444
|
+
};
|
|
445
|
+
}
|
|
446
|
+
async function findExistingFeedback(params) {
|
|
447
|
+
const command = `${params.input.command}.find-existing`;
|
|
448
|
+
const body = buildFeedbackFindRequestBody(command, params.identity);
|
|
449
|
+
const http = await requestGraphqlHttp({
|
|
450
|
+
input: params.input,
|
|
451
|
+
url: params.url,
|
|
452
|
+
requestId: params.requestId,
|
|
453
|
+
body,
|
|
454
|
+
controller: params.controller
|
|
455
|
+
});
|
|
456
|
+
const gqlErrors = http.graph.errors;
|
|
457
|
+
if (Array.isArray(gqlErrors) && gqlErrors.length > 0) {
|
|
458
|
+
return null;
|
|
459
|
+
}
|
|
460
|
+
const feedbackNode = extractFeedbackListNode(http.graph);
|
|
461
|
+
if (!feedbackNode) {
|
|
462
|
+
return null;
|
|
463
|
+
}
|
|
464
|
+
return {
|
|
465
|
+
feedbackNode,
|
|
466
|
+
requestId: http.requestId
|
|
467
|
+
};
|
|
468
|
+
}
|
|
212
469
|
function graphqlTypeForValue(value) {
|
|
213
470
|
if (Array.isArray(value)) {
|
|
214
471
|
const firstNonNull = value.find((item) => item !== null && item !== void 0);
|
|
@@ -251,9 +508,14 @@ function normalizeGraphqlVariables(variables) {
|
|
|
251
508
|
function buildGraphqlBody(input) {
|
|
252
509
|
const graphqlField = toCamelCase(input.field);
|
|
253
510
|
const graphqlVariables = normalizeGraphqlVariables(input.variables);
|
|
511
|
+
const graphqlVariableTypes = normalizeGraphqlVariables(input.variableTypes ?? {});
|
|
254
512
|
const operationName = input.operationName ?? graphqlOperationName(input.command);
|
|
255
513
|
const variableEntries = Object.entries(graphqlVariables).filter(([, value]) => value !== void 0);
|
|
256
|
-
const variableDecl = variableEntries.map(([name, value]) =>
|
|
514
|
+
const variableDecl = variableEntries.map(([name, value]) => {
|
|
515
|
+
const overriddenType = graphqlVariableTypes[name];
|
|
516
|
+
const typeName = typeof overriddenType === "string" && overriddenType.trim().length > 0 ? overriddenType.trim() : graphqlTypeForVariable(name, value);
|
|
517
|
+
return `$${name}: ${withNonNull(typeName)}`;
|
|
518
|
+
}).join(", ");
|
|
257
519
|
const fieldArgs = variableEntries.map(([name]) => `${name}: $${name}`).join(", ");
|
|
258
520
|
const signature = variableDecl.length > 0 ? `(${variableDecl})` : "";
|
|
259
521
|
const args = fieldArgs.length > 0 ? `(${fieldArgs})` : "";
|
|
@@ -278,24 +540,37 @@ async function graphqlRequest(input) {
|
|
|
278
540
|
const controller = new AbortController();
|
|
279
541
|
const timeoutId = setTimeout(() => controller.abort(), input.config.timeoutMs);
|
|
280
542
|
try {
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
543
|
+
if (isFeedbackCreateCommand(input)) {
|
|
544
|
+
const feedbackIdentity = extractFeedbackIdentity(input.variables);
|
|
545
|
+
if (feedbackIdentity) {
|
|
546
|
+
const existing = await findExistingFeedback({
|
|
547
|
+
input,
|
|
548
|
+
url,
|
|
549
|
+
requestId,
|
|
550
|
+
controller,
|
|
551
|
+
identity: feedbackIdentity
|
|
552
|
+
});
|
|
553
|
+
if (existing) {
|
|
554
|
+
return buildFeedbackReuseEnvelope({
|
|
555
|
+
command: input.command,
|
|
556
|
+
field: input.field,
|
|
557
|
+
status: 200,
|
|
558
|
+
requestId: existing.requestId,
|
|
559
|
+
feedbackNode: existing.feedbackNode,
|
|
560
|
+
reason: "preexisting"
|
|
561
|
+
});
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
}
|
|
565
|
+
const http = await requestGraphqlHttp({
|
|
566
|
+
input,
|
|
567
|
+
url,
|
|
568
|
+
requestId,
|
|
569
|
+
body,
|
|
570
|
+
controller
|
|
294
571
|
});
|
|
295
|
-
const responseRequestId =
|
|
296
|
-
const
|
|
297
|
-
const payload = text ? parseJsonSafely(text) : null;
|
|
298
|
-
const graph = payload && typeof payload === "object" ? payload : {};
|
|
572
|
+
const responseRequestId = http.requestId;
|
|
573
|
+
const graph = http.graph;
|
|
299
574
|
const gqlErrors = graph.errors;
|
|
300
575
|
const gqlData = graph.data && typeof graph.data === "object" ? graph.data : {};
|
|
301
576
|
if (Array.isArray(gqlErrors) && gqlErrors.length > 0) {
|
|
@@ -318,6 +593,36 @@ async function graphqlRequest(input) {
|
|
|
318
593
|
const ok = Boolean(mutationPayload.ok);
|
|
319
594
|
const status = typeof mutationPayload.status === "number" ? mutationPayload.status : ok ? 200 : 400;
|
|
320
595
|
if (!ok) {
|
|
596
|
+
if (isFeedbackCreateCommand(input) && isDuplicateFeedbackMutationError(mutationPayload)) {
|
|
597
|
+
const feedbackIdentity = extractFeedbackIdentity(input.variables);
|
|
598
|
+
if (feedbackIdentity) {
|
|
599
|
+
const existing = await findExistingFeedback({
|
|
600
|
+
input,
|
|
601
|
+
url,
|
|
602
|
+
requestId: responseRequestId,
|
|
603
|
+
controller,
|
|
604
|
+
identity: feedbackIdentity
|
|
605
|
+
});
|
|
606
|
+
if (existing) {
|
|
607
|
+
return buildFeedbackReuseEnvelope({
|
|
608
|
+
command: input.command,
|
|
609
|
+
field: input.field,
|
|
610
|
+
status: 200,
|
|
611
|
+
requestId: existing.requestId,
|
|
612
|
+
feedbackNode: existing.feedbackNode,
|
|
613
|
+
reason: "duplicate_race"
|
|
614
|
+
});
|
|
615
|
+
}
|
|
616
|
+
}
|
|
617
|
+
}
|
|
618
|
+
const mutationErrors = mutationPayload.errors ?? null;
|
|
619
|
+
const details = {
|
|
620
|
+
errors: mutationErrors,
|
|
621
|
+
data: mutationPayload.data ?? null
|
|
622
|
+
};
|
|
623
|
+
if (shouldAddSparse422Diagnostic(status, mutationPayload)) {
|
|
624
|
+
details.fallbackDiagnostic = buildSparse422Diagnostic(input);
|
|
625
|
+
}
|
|
321
626
|
return {
|
|
322
627
|
envelope: buildEnvelope({
|
|
323
628
|
ok: false,
|
|
@@ -329,10 +634,7 @@ async function graphqlRequest(input) {
|
|
|
329
634
|
mutationPayload.errorCode ?? mutationPayload.error_code ?? `http_${status}`
|
|
330
635
|
),
|
|
331
636
|
message: "Mutation failed.",
|
|
332
|
-
details
|
|
333
|
-
errors: mutationPayload.errors ?? null,
|
|
334
|
-
data: mutationPayload.data ?? null
|
|
335
|
-
}
|
|
637
|
+
details
|
|
336
638
|
},
|
|
337
639
|
requestId: responseRequestId
|
|
338
640
|
}),
|
|
@@ -372,7 +674,7 @@ async function graphqlRequest(input) {
|
|
|
372
674
|
envelope: buildEnvelope({
|
|
373
675
|
ok: true,
|
|
374
676
|
command: input.command,
|
|
375
|
-
status:
|
|
677
|
+
status: http.status >= 200 && http.status < 300 ? http.status : 200,
|
|
376
678
|
data: { [input.field]: fieldPayload ?? null },
|
|
377
679
|
error: null,
|
|
378
680
|
requestId: responseRequestId
|
|
@@ -493,6 +795,7 @@ async function runGraphqlQueryCommand(input) {
|
|
|
493
795
|
operationType: "query",
|
|
494
796
|
field: input.field,
|
|
495
797
|
variables: input.variables ?? {},
|
|
798
|
+
variableTypes: input.variableTypes,
|
|
496
799
|
selectionSet: input.selectionSet ?? defaultQuerySelectionSet(input.field, Boolean(input.isList)),
|
|
497
800
|
isShow: input.isShow
|
|
498
801
|
});
|
|
@@ -503,6 +806,17 @@ async function runGraphqlQueryCommand(input) {
|
|
|
503
806
|
...dataRecord,
|
|
504
807
|
[input.field]: transformed
|
|
505
808
|
};
|
|
809
|
+
if (input.isShow && (transformed === null || transformed === void 0)) {
|
|
810
|
+
result.envelope.ok = false;
|
|
811
|
+
result.envelope.status = 404;
|
|
812
|
+
result.envelope.data = null;
|
|
813
|
+
result.envelope.error = {
|
|
814
|
+
code: "not_found",
|
|
815
|
+
message: "Record not found.",
|
|
816
|
+
details: {}
|
|
817
|
+
};
|
|
818
|
+
result.exitCode = EXIT_CODES.notFound;
|
|
819
|
+
}
|
|
506
820
|
}
|
|
507
821
|
printEnvelopeAndExit(result);
|
|
508
822
|
} catch (error) {
|
|
@@ -540,6 +854,7 @@ async function runGraphqlMutationCommand(input) {
|
|
|
540
854
|
operationType: "mutation",
|
|
541
855
|
field: input.field,
|
|
542
856
|
variables: input.variables ?? {},
|
|
857
|
+
variableTypes: input.variableTypes,
|
|
543
858
|
selectionSet: input.selectionSet ?? "{ ok status errorCode data errors }"
|
|
544
859
|
});
|
|
545
860
|
printEnvelopeAndExit(result);
|
|
@@ -849,7 +1164,7 @@ var dtoHelpCatalog = {
|
|
|
849
1164
|
create: [
|
|
850
1165
|
["member_id", "string"],
|
|
851
1166
|
["name", "string"],
|
|
852
|
-
["type", "
|
|
1167
|
+
["type", "enum(TeamMeeting|OneOnOneMeeting)"],
|
|
853
1168
|
["date", "string"],
|
|
854
1169
|
["status", "enum(upcoming|active|completed)"],
|
|
855
1170
|
["start_time", "number"],
|
|
@@ -1474,37 +1789,70 @@ function registerEntityCrudCommands(program, config) {
|
|
|
1474
1789
|
const id = idSchema.parse(opts.id);
|
|
1475
1790
|
const context = await resolveCommandContext(cmd.optsWithGlobals());
|
|
1476
1791
|
const organizationId = resolveOrganizationId(context.organizationId);
|
|
1792
|
+
const defaultCommand = `${config.command}.show`;
|
|
1793
|
+
const defaultField = config.resourcePath === "feedback" ? "feedback" : toSingularResourceName(config.resourcePath);
|
|
1794
|
+
const defaultVariables = normalizeGraphqlVariables2({
|
|
1795
|
+
organization_id: organizationId,
|
|
1796
|
+
id
|
|
1797
|
+
});
|
|
1798
|
+
const showQuery = config.showQueryFactory ? config.showQueryFactory({
|
|
1799
|
+
command: defaultCommand,
|
|
1800
|
+
field: defaultField,
|
|
1801
|
+
variables: defaultVariables,
|
|
1802
|
+
id,
|
|
1803
|
+
organizationId
|
|
1804
|
+
}) : void 0;
|
|
1477
1805
|
await runGraphqlQueryCommand({
|
|
1478
|
-
command:
|
|
1806
|
+
command: showQuery?.command ?? defaultCommand,
|
|
1479
1807
|
runtimeOptions: context.runtimeOptions,
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
isShow: true
|
|
1808
|
+
operationName: showQuery?.operationName,
|
|
1809
|
+
field: showQuery?.field ?? defaultField,
|
|
1810
|
+
variables: showQuery?.variables ?? defaultVariables,
|
|
1811
|
+
variableTypes: showQuery?.variableTypes,
|
|
1812
|
+
selectionSet: showQuery?.selectionSet,
|
|
1813
|
+
isShow: true,
|
|
1814
|
+
transformData: showQuery?.transformData
|
|
1486
1815
|
});
|
|
1487
1816
|
});
|
|
1488
1817
|
entityCommand.command("create").requiredOption("--data-json <dataJson>", createHelp4).action(async (opts, cmd) => {
|
|
1489
1818
|
const context = await resolveCommandContext(cmd.optsWithGlobals());
|
|
1490
1819
|
const organizationId = resolveOrganizationId(context.organizationId);
|
|
1491
|
-
|
|
1820
|
+
let body = normalizeBody(String(opts.dataJson), config.rootKey);
|
|
1821
|
+
if (config.normalizeCreateBody) {
|
|
1822
|
+
body = config.normalizeCreateBody(body);
|
|
1823
|
+
}
|
|
1492
1824
|
assertRequiredCreateFields(body, config.rootKey, config.requiredCreateFields);
|
|
1825
|
+
const defaultCommand = `${config.command}.create`;
|
|
1826
|
+
const defaultField = `create_${toSingularResourceName(config.resourcePath)}`;
|
|
1827
|
+
const defaultVariables = {
|
|
1828
|
+
organization_id: organizationId,
|
|
1829
|
+
params: body
|
|
1830
|
+
};
|
|
1831
|
+
const createMutation = config.createMutationFactory ? config.createMutationFactory({
|
|
1832
|
+
command: defaultCommand,
|
|
1833
|
+
field: defaultField,
|
|
1834
|
+
variables: defaultVariables,
|
|
1835
|
+
body,
|
|
1836
|
+
organizationId
|
|
1837
|
+
}) : void 0;
|
|
1493
1838
|
await runGraphqlMutationCommand({
|
|
1494
|
-
command:
|
|
1839
|
+
command: createMutation?.command ?? defaultCommand,
|
|
1495
1840
|
runtimeOptions: context.runtimeOptions,
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1841
|
+
operationName: createMutation?.operationName,
|
|
1842
|
+
field: createMutation?.field ?? defaultField,
|
|
1843
|
+
variables: createMutation?.variables ?? defaultVariables,
|
|
1844
|
+
variableTypes: createMutation?.variableTypes,
|
|
1845
|
+
selectionSet: createMutation?.selectionSet
|
|
1501
1846
|
});
|
|
1502
1847
|
});
|
|
1503
1848
|
entityCommand.command("update").requiredOption("--id <id>").requiredOption("--data-json <dataJson>", updateHelp5).action(async (opts, cmd) => {
|
|
1504
1849
|
const id = idSchema.parse(opts.id);
|
|
1505
1850
|
const context = await resolveCommandContext(cmd.optsWithGlobals());
|
|
1506
1851
|
const organizationId = resolveOrganizationId(context.organizationId);
|
|
1507
|
-
|
|
1852
|
+
let body = normalizeBody(String(opts.dataJson), config.rootKey);
|
|
1853
|
+
if (config.normalizeUpdateBody) {
|
|
1854
|
+
body = config.normalizeUpdateBody(body);
|
|
1855
|
+
}
|
|
1508
1856
|
const singular = toSingularResourceName(config.resourcePath);
|
|
1509
1857
|
await runGraphqlMutationCommand({
|
|
1510
1858
|
command: `${config.command}.update`,
|
|
@@ -1656,7 +2004,8 @@ function registerProjectCommands(program) {
|
|
|
1656
2004
|
member_id: opts.memberId,
|
|
1657
2005
|
...extra
|
|
1658
2006
|
}),
|
|
1659
|
-
isList: true
|
|
2007
|
+
isList: true,
|
|
2008
|
+
selectionSet: "{ data { id type } count currentPage totalPages }"
|
|
1660
2009
|
});
|
|
1661
2010
|
});
|
|
1662
2011
|
projects.command("show").requiredOption("--id <id>").action(async (opts, cmd) => {
|
|
@@ -1671,7 +2020,8 @@ function registerProjectCommands(program) {
|
|
|
1671
2020
|
organization_id: organizationId,
|
|
1672
2021
|
id
|
|
1673
2022
|
},
|
|
1674
|
-
isShow: true
|
|
2023
|
+
isShow: true,
|
|
2024
|
+
selectionSet: "{ id type }"
|
|
1675
2025
|
});
|
|
1676
2026
|
});
|
|
1677
2027
|
projects.command("create").requiredOption("--data-json <dataJson>", projectCreateDataJsonHelp).action(async (opts, cmd) => {
|
|
@@ -1701,6 +2051,11 @@ function registerProjectCommands(program) {
|
|
|
1701
2051
|
organization_id: organizationId,
|
|
1702
2052
|
project_id: id,
|
|
1703
2053
|
params: body
|
|
2054
|
+
},
|
|
2055
|
+
variableTypes: {
|
|
2056
|
+
organization_id: "ID!",
|
|
2057
|
+
project_id: "ID!",
|
|
2058
|
+
params: "UpdateProjectParamsInput!"
|
|
1704
2059
|
}
|
|
1705
2060
|
});
|
|
1706
2061
|
});
|
|
@@ -1813,8 +2168,142 @@ function registerRockCommands(program) {
|
|
|
1813
2168
|
import { z as z6 } from "zod";
|
|
1814
2169
|
var idSchema5 = z6.string().min(1);
|
|
1815
2170
|
var notesSchema = z6.string().min(1);
|
|
2171
|
+
var MEETING_TYPES = /* @__PURE__ */ new Set(["TeamMeeting", "OneOnOneMeeting"]);
|
|
2172
|
+
var MEETING_STATUSES = /* @__PURE__ */ new Set(["upcoming", "active", "completed"]);
|
|
2173
|
+
var MEETING_REPEATS = /* @__PURE__ */ new Set(["never", "weekly", "biweekly", "monthly", "quarterly"]);
|
|
1816
2174
|
var createHelp2 = buildDataJsonHelp("meeting", "create") ?? 'JSON object for meeting or {"meeting": {...}}';
|
|
1817
2175
|
var updateHelp2 = buildDataJsonHelp("meeting", "update") ?? 'JSON object for meeting or {"meeting": {...}}';
|
|
2176
|
+
function asNonEmptyString2(value) {
|
|
2177
|
+
if (typeof value !== "string") {
|
|
2178
|
+
return void 0;
|
|
2179
|
+
}
|
|
2180
|
+
const trimmed = value.trim();
|
|
2181
|
+
return trimmed.length > 0 ? trimmed : void 0;
|
|
2182
|
+
}
|
|
2183
|
+
function toFiniteNumber(value, field) {
|
|
2184
|
+
if (value === void 0 || value === null) {
|
|
2185
|
+
return void 0;
|
|
2186
|
+
}
|
|
2187
|
+
if (typeof value === "number" && Number.isFinite(value)) {
|
|
2188
|
+
return value;
|
|
2189
|
+
}
|
|
2190
|
+
if (typeof value === "string") {
|
|
2191
|
+
const trimmed = value.trim();
|
|
2192
|
+
if (trimmed.length === 0) {
|
|
2193
|
+
return void 0;
|
|
2194
|
+
}
|
|
2195
|
+
const parsed = Number(trimmed);
|
|
2196
|
+
if (Number.isFinite(parsed)) {
|
|
2197
|
+
return parsed;
|
|
2198
|
+
}
|
|
2199
|
+
}
|
|
2200
|
+
throw new CliError({
|
|
2201
|
+
message: `Invalid ${field}. Expected a numeric value.`,
|
|
2202
|
+
kind: "invalid_args",
|
|
2203
|
+
status: 400,
|
|
2204
|
+
exitCode: EXIT_CODES.invalidArgs
|
|
2205
|
+
});
|
|
2206
|
+
}
|
|
2207
|
+
function toStringArray(value, field) {
|
|
2208
|
+
if (value === void 0 || value === null) {
|
|
2209
|
+
return void 0;
|
|
2210
|
+
}
|
|
2211
|
+
const items = Array.isArray(value) ? value : typeof value === "string" ? value.split(",") : null;
|
|
2212
|
+
if (!items) {
|
|
2213
|
+
throw new CliError({
|
|
2214
|
+
message: `Invalid ${field}. Expected an array or comma-separated string.`,
|
|
2215
|
+
kind: "invalid_args",
|
|
2216
|
+
status: 400,
|
|
2217
|
+
exitCode: EXIT_CODES.invalidArgs
|
|
2218
|
+
});
|
|
2219
|
+
}
|
|
2220
|
+
const normalized = items.map((item) => String(item).trim()).filter((item) => item.length > 0);
|
|
2221
|
+
return normalized.length > 0 ? normalized : void 0;
|
|
2222
|
+
}
|
|
2223
|
+
function normalizeMeetingCreateBody(body) {
|
|
2224
|
+
const entity = body.meeting;
|
|
2225
|
+
if (!entity || typeof entity !== "object" || Array.isArray(entity)) {
|
|
2226
|
+
throw new CliError({
|
|
2227
|
+
message: 'Invalid payload. Expected object at "meeting".',
|
|
2228
|
+
kind: "invalid_args",
|
|
2229
|
+
status: 400,
|
|
2230
|
+
exitCode: EXIT_CODES.invalidArgs
|
|
2231
|
+
});
|
|
2232
|
+
}
|
|
2233
|
+
const meeting = { ...entity };
|
|
2234
|
+
const type = asNonEmptyString2(meeting.type);
|
|
2235
|
+
if (!type || !MEETING_TYPES.has(type)) {
|
|
2236
|
+
throw new CliError({
|
|
2237
|
+
message: "Invalid meeting.type. Use one of: TeamMeeting, OneOnOneMeeting.",
|
|
2238
|
+
kind: "invalid_args",
|
|
2239
|
+
status: 400,
|
|
2240
|
+
exitCode: EXIT_CODES.invalidArgs,
|
|
2241
|
+
details: { field: "meeting.type", allowed: Array.from(MEETING_TYPES) }
|
|
2242
|
+
});
|
|
2243
|
+
}
|
|
2244
|
+
const memberId = asNonEmptyString2(meeting.member_id);
|
|
2245
|
+
const date = asNonEmptyString2(meeting.date);
|
|
2246
|
+
const startTime = toFiniteNumber(meeting.start_time, "meeting.start_time");
|
|
2247
|
+
const missingRequired = [];
|
|
2248
|
+
if (!memberId) missingRequired.push("member_id");
|
|
2249
|
+
if (!date) missingRequired.push("date");
|
|
2250
|
+
if (startTime === void 0) missingRequired.push("start_time");
|
|
2251
|
+
if (missingRequired.length > 0) {
|
|
2252
|
+
throw new CliError({
|
|
2253
|
+
message: `Missing required create fields for meeting: ${missingRequired.join(", ")}.`,
|
|
2254
|
+
kind: "invalid_args",
|
|
2255
|
+
status: 400,
|
|
2256
|
+
exitCode: EXIT_CODES.invalidArgs,
|
|
2257
|
+
details: { requiredFields: ["member_id", "date", "start_time"], rootKey: "meeting" }
|
|
2258
|
+
});
|
|
2259
|
+
}
|
|
2260
|
+
const status = asNonEmptyString2(meeting.status);
|
|
2261
|
+
if (status && !MEETING_STATUSES.has(status)) {
|
|
2262
|
+
throw new CliError({
|
|
2263
|
+
message: "Invalid meeting.status. Use one of: upcoming, active, completed.",
|
|
2264
|
+
kind: "invalid_args",
|
|
2265
|
+
status: 400,
|
|
2266
|
+
exitCode: EXIT_CODES.invalidArgs,
|
|
2267
|
+
details: { field: "meeting.status", allowed: Array.from(MEETING_STATUSES) }
|
|
2268
|
+
});
|
|
2269
|
+
}
|
|
2270
|
+
const repeats = asNonEmptyString2(meeting.repeats) ?? "never";
|
|
2271
|
+
if (!MEETING_REPEATS.has(repeats)) {
|
|
2272
|
+
throw new CliError({
|
|
2273
|
+
message: "Invalid meeting.repeats. Use one of: never, weekly, biweekly, monthly, quarterly.",
|
|
2274
|
+
kind: "invalid_args",
|
|
2275
|
+
status: 400,
|
|
2276
|
+
exitCode: EXIT_CODES.invalidArgs,
|
|
2277
|
+
details: { field: "meeting.repeats", allowed: Array.from(MEETING_REPEATS) }
|
|
2278
|
+
});
|
|
2279
|
+
}
|
|
2280
|
+
const teamsIds = toStringArray(meeting.teams_ids, "meeting.teams_ids");
|
|
2281
|
+
if (type === "TeamMeeting" && (!teamsIds || teamsIds.length === 0)) {
|
|
2282
|
+
throw new CliError({
|
|
2283
|
+
message: "Missing required create fields for meeting: teams_ids.",
|
|
2284
|
+
kind: "invalid_args",
|
|
2285
|
+
status: 400,
|
|
2286
|
+
exitCode: EXIT_CODES.invalidArgs,
|
|
2287
|
+
details: { requiredFields: ["teams_ids"], rootKey: "meeting" }
|
|
2288
|
+
});
|
|
2289
|
+
}
|
|
2290
|
+
const endTime = toFiniteNumber(meeting.end_time, "meeting.end_time");
|
|
2291
|
+
meeting.type = type;
|
|
2292
|
+
meeting.member_id = memberId;
|
|
2293
|
+
meeting.date = date;
|
|
2294
|
+
meeting.start_time = startTime;
|
|
2295
|
+
meeting.repeats = repeats;
|
|
2296
|
+
if (status) {
|
|
2297
|
+
meeting.status = status;
|
|
2298
|
+
}
|
|
2299
|
+
if (endTime !== void 0) {
|
|
2300
|
+
meeting.end_time = endTime;
|
|
2301
|
+
}
|
|
2302
|
+
if (teamsIds) {
|
|
2303
|
+
meeting.teams_ids = teamsIds;
|
|
2304
|
+
}
|
|
2305
|
+
return { ...body, meeting };
|
|
2306
|
+
}
|
|
1818
2307
|
function registerMeetingCommands(program) {
|
|
1819
2308
|
const meetings = program.command("meetings").description("Meeting operations");
|
|
1820
2309
|
meetings.command("list").option("--per <per>").option("--date <date>").option("--occurrence-date <occurrenceDate>").option("--past <past>").option("--start-time <startTime>").option("--today-and-active <todayAndActive>").option("--upcoming <upcoming>").option("--query-json <queryJson>").action(async (opts, cmd) => {
|
|
@@ -1877,7 +2366,8 @@ function registerMeetingCommands(program) {
|
|
|
1877
2366
|
meetings.command("create").requiredOption("--data-json <dataJson>", createHelp2).action(async (opts, cmd) => {
|
|
1878
2367
|
const context = await resolveCommandContext(cmd.optsWithGlobals());
|
|
1879
2368
|
const organizationId = resolveOrganizationId(context.organizationId);
|
|
1880
|
-
const
|
|
2369
|
+
const rawBody = __testables.normalizeBody(String(opts.dataJson), "meeting");
|
|
2370
|
+
const body = normalizeMeetingCreateBody(rawBody);
|
|
1881
2371
|
await runGraphqlMutationCommand({
|
|
1882
2372
|
command: "meetings.create",
|
|
1883
2373
|
runtimeOptions: context.runtimeOptions,
|
|
@@ -1982,7 +2472,9 @@ import { z as z8 } from "zod";
|
|
|
1982
2472
|
var issueGroupIdSchema = z8.string().min(1);
|
|
1983
2473
|
var idSchema7 = z8.string().min(1);
|
|
1984
2474
|
var nameSchema = z8.string().min(1);
|
|
1985
|
-
var issueTypeSchema = z8.string().min(1)
|
|
2475
|
+
var issueTypeSchema = z8.string().min(1).refine((value) => value === "short_term" || value === "long_term", {
|
|
2476
|
+
message: "Invalid issue type. Use one of: short_term, long_term."
|
|
2477
|
+
});
|
|
1986
2478
|
var updateHelp4 = buildDataJsonHelp("issue", "update") ?? 'JSON object for issue or {"issue": {...}}';
|
|
1987
2479
|
function registerIssueCommands(program) {
|
|
1988
2480
|
const issues = program.command("issues").description("Issue operations");
|
|
@@ -2025,7 +2517,7 @@ function registerIssueCommands(program) {
|
|
|
2025
2517
|
isShow: true
|
|
2026
2518
|
});
|
|
2027
2519
|
});
|
|
2028
|
-
issues.command("create").requiredOption("--issue-group-id <issueGroupId>").requiredOption("--name <name>").requiredOption("--issue-type <issueType>").option("--status <status>").option("--priority <priority>").option("--description <description>").option("--due-by <dueBy>").option("--member-id <memberId>").action(async (opts, cmd) => {
|
|
2520
|
+
issues.command("create").requiredOption("--issue-group-id <issueGroupId>").requiredOption("--name <name>").requiredOption("--issue-type <issueType>", "Issue type: short_term | long_term").option("--status <status>").option("--priority <priority>").option("--description <description>").option("--due-by <dueBy>").option("--member-id <memberId>").action(async (opts, cmd) => {
|
|
2029
2521
|
const issueGroupId = issueGroupIdSchema.parse(opts.issueGroupId);
|
|
2030
2522
|
const name = nameSchema.parse(opts.name);
|
|
2031
2523
|
const issueType = issueTypeSchema.parse(opts.issueType);
|
|
@@ -2070,54 +2562,701 @@ function registerIssueCommands(program) {
|
|
|
2070
2562
|
});
|
|
2071
2563
|
}
|
|
2072
2564
|
|
|
2565
|
+
// src/commands/smartKpiNames.ts
|
|
2566
|
+
var SMART_KPI_NAMES = [
|
|
2567
|
+
"total_active_users",
|
|
2568
|
+
"total_new_users",
|
|
2569
|
+
"total_return_users",
|
|
2570
|
+
"total_engaged_sessions",
|
|
2571
|
+
"total_sessions",
|
|
2572
|
+
"engagement_rate",
|
|
2573
|
+
"bounce_rate",
|
|
2574
|
+
"page_call_phone_clicks_logged_in_unique",
|
|
2575
|
+
"page_cta_clicks_logged_in_unique",
|
|
2576
|
+
"page_engaged_users",
|
|
2577
|
+
"page_fan_adds_unique",
|
|
2578
|
+
"page_fan_adds",
|
|
2579
|
+
"page_fan_removes",
|
|
2580
|
+
"page_fans",
|
|
2581
|
+
"page_get_directions_clicks_logged_in_unique",
|
|
2582
|
+
"page_impressions_unique",
|
|
2583
|
+
"page_impressions",
|
|
2584
|
+
"page_negative_feedback",
|
|
2585
|
+
"page_positive_feedback_comment",
|
|
2586
|
+
"page_positive_feedback_like",
|
|
2587
|
+
"page_positive_feedback_other",
|
|
2588
|
+
"page_positive_feedback_share",
|
|
2589
|
+
"page_post_engagements",
|
|
2590
|
+
"page_total_actions",
|
|
2591
|
+
"page_views_logged_in_unique",
|
|
2592
|
+
"page_views_total",
|
|
2593
|
+
"page_website_clicks_logged_in_unique",
|
|
2594
|
+
"post_clicks_by_type_unique",
|
|
2595
|
+
"post_engaged_users",
|
|
2596
|
+
"post_impressions_fan_paid",
|
|
2597
|
+
"post_impressions_fan",
|
|
2598
|
+
"post_impressions_organic",
|
|
2599
|
+
"post_impressions_unique",
|
|
2600
|
+
"post_impressions",
|
|
2601
|
+
"post_reactions_like_total",
|
|
2602
|
+
"get_directions_clicks",
|
|
2603
|
+
"phone_call_clicks",
|
|
2604
|
+
"profile_views",
|
|
2605
|
+
"reach",
|
|
2606
|
+
"text_message_clicks",
|
|
2607
|
+
"website_clicks",
|
|
2608
|
+
"online_followers",
|
|
2609
|
+
"total_interactions",
|
|
2610
|
+
"accounts_engaged",
|
|
2611
|
+
"likes",
|
|
2612
|
+
"comments",
|
|
2613
|
+
"saves",
|
|
2614
|
+
"shares",
|
|
2615
|
+
"replies",
|
|
2616
|
+
"impressions",
|
|
2617
|
+
"email_contacts",
|
|
2618
|
+
"follower_count",
|
|
2619
|
+
"total_new_conversations",
|
|
2620
|
+
"total_unassigned_conversations",
|
|
2621
|
+
"total_closed_conversations",
|
|
2622
|
+
"total_new_contacts",
|
|
2623
|
+
"total_contacts",
|
|
2624
|
+
"total_revenue",
|
|
2625
|
+
"total_expenses",
|
|
2626
|
+
"cash_flow",
|
|
2627
|
+
"paid_invoices",
|
|
2628
|
+
"unpaid_invoices",
|
|
2629
|
+
"total_new_payments",
|
|
2630
|
+
"total_new_invoices",
|
|
2631
|
+
"total_paid_invoices",
|
|
2632
|
+
"total_refunds",
|
|
2633
|
+
"total_disputes",
|
|
2634
|
+
"calls",
|
|
2635
|
+
"sms",
|
|
2636
|
+
"mms",
|
|
2637
|
+
"verify_push",
|
|
2638
|
+
"verify_totp",
|
|
2639
|
+
"recordings",
|
|
2640
|
+
"transcriptions",
|
|
2641
|
+
"programmable_voice",
|
|
2642
|
+
"authy_phone_verifications",
|
|
2643
|
+
"authy_authentications",
|
|
2644
|
+
"twilio_errors",
|
|
2645
|
+
"twilio_warnings",
|
|
2646
|
+
"twilio_notices",
|
|
2647
|
+
"total_subscribers",
|
|
2648
|
+
"total_subscribers_gained",
|
|
2649
|
+
"total_subscribers_lost",
|
|
2650
|
+
"total_engagement",
|
|
2651
|
+
"total_views",
|
|
2652
|
+
"total_comments",
|
|
2653
|
+
"total_likes",
|
|
2654
|
+
"total_dislikes",
|
|
2655
|
+
"total_shares",
|
|
2656
|
+
"total_card_impressions",
|
|
2657
|
+
"total_card_clicks",
|
|
2658
|
+
"total_card_click_rate",
|
|
2659
|
+
"rock_total_new_rock_groups",
|
|
2660
|
+
"rock_total_rock_groups",
|
|
2661
|
+
"rock_total_new_rocks",
|
|
2662
|
+
"rock_total_new_milestones",
|
|
2663
|
+
"rock_total_completed_milestones",
|
|
2664
|
+
"rock_total_incomplete_milestones",
|
|
2665
|
+
"project_total_projects",
|
|
2666
|
+
"project_total_new_projects",
|
|
2667
|
+
"project_total_new_tasks",
|
|
2668
|
+
"project_total_completed_tasks",
|
|
2669
|
+
"project_total_incomplete_tasks",
|
|
2670
|
+
"project_total_new_sub_tasks",
|
|
2671
|
+
"project_total_completed_sub_tasks",
|
|
2672
|
+
"project_total_incomplete_sub_tasks",
|
|
2673
|
+
"list_total_list",
|
|
2674
|
+
"list_total_new_list",
|
|
2675
|
+
"list_total_new_list_items",
|
|
2676
|
+
"list_total_completed_list_items",
|
|
2677
|
+
"list_total_incomplete_list_items",
|
|
2678
|
+
"list_total_new_sub_items",
|
|
2679
|
+
"list_total_completed_sub_items",
|
|
2680
|
+
"list_total_incomplete_sub_items",
|
|
2681
|
+
"issue_total_issue_groups",
|
|
2682
|
+
"issue_total_new_issue_groups",
|
|
2683
|
+
"issue_total_new_issues",
|
|
2684
|
+
"issue_total_completed_issues",
|
|
2685
|
+
"issue_total_incomplete_issues",
|
|
2686
|
+
"issue_total_new_sub_issues",
|
|
2687
|
+
"issue_total_completed_sub_issues",
|
|
2688
|
+
"issue_total_incomplete_sub_issues",
|
|
2689
|
+
"todo_total_todo_groups",
|
|
2690
|
+
"todo_total_new_todo_groups",
|
|
2691
|
+
"todo_total_new_todos",
|
|
2692
|
+
"todo_total_completed_todos",
|
|
2693
|
+
"todo_total_incomplete_todos",
|
|
2694
|
+
"todo_total_new_sub_todos",
|
|
2695
|
+
"todo_total_completed_sub_todos",
|
|
2696
|
+
"todo_total_incomplete_sub_todos",
|
|
2697
|
+
"measurable_total_scorecards",
|
|
2698
|
+
"measurable_total_new_scorecards",
|
|
2699
|
+
"measurable_total_new_measurables",
|
|
2700
|
+
"stand_up_daily_stand_up_completion_rate",
|
|
2701
|
+
"stand_up_total_stand_ups_complete",
|
|
2702
|
+
"stand_up_daily_stand_up_block_rate",
|
|
2703
|
+
"stand_up_total_blocked_stand_ups",
|
|
2704
|
+
"headline_total_new_headlines",
|
|
2705
|
+
"content_total_content",
|
|
2706
|
+
"content_total_new_content",
|
|
2707
|
+
"question_total_questions",
|
|
2708
|
+
"question_total_new_questions",
|
|
2709
|
+
"question_total_questions_answered",
|
|
2710
|
+
"survey_new_surveys_sent",
|
|
2711
|
+
"member_total_new_members",
|
|
2712
|
+
"member_total_members",
|
|
2713
|
+
"responsibility_total_new_responsibilities_added",
|
|
2714
|
+
"responsibility_total_responsibilities",
|
|
2715
|
+
"customer_total_customers",
|
|
2716
|
+
"customer_total_new_customers",
|
|
2717
|
+
"customer_total_new_customer_logs",
|
|
2718
|
+
"contact_total_contacts",
|
|
2719
|
+
"contact_total_new_contacts",
|
|
2720
|
+
"contact_total_new_contact_logs"
|
|
2721
|
+
];
|
|
2722
|
+
var SMART_KPI_NAME_SET = new Set(SMART_KPI_NAMES);
|
|
2723
|
+
|
|
2073
2724
|
// src/commands/systemTools.ts
|
|
2074
|
-
|
|
2075
|
-
|
|
2076
|
-
|
|
2077
|
-
|
|
2078
|
-
|
|
2079
|
-
|
|
2080
|
-
|
|
2081
|
-
|
|
2082
|
-
|
|
2083
|
-
|
|
2084
|
-
|
|
2085
|
-
|
|
2086
|
-
|
|
2087
|
-
|
|
2088
|
-
|
|
2089
|
-
|
|
2090
|
-
|
|
2091
|
-
|
|
2092
|
-
|
|
2093
|
-
|
|
2094
|
-
|
|
2095
|
-
|
|
2096
|
-
|
|
2097
|
-
|
|
2098
|
-
|
|
2099
|
-
|
|
2100
|
-
|
|
2101
|
-
|
|
2102
|
-
|
|
2103
|
-
|
|
2104
|
-
|
|
2105
|
-
|
|
2106
|
-
|
|
2107
|
-
|
|
2108
|
-
|
|
2109
|
-
|
|
2110
|
-
|
|
2111
|
-
|
|
2112
|
-
|
|
2113
|
-
|
|
2725
|
+
var TODO_STATUSES = /* @__PURE__ */ new Set(["open", "completed"]);
|
|
2726
|
+
var KNOWLEDGE_CONTENT_TYPES = /* @__PURE__ */ new Set(["company", "policy", "process"]);
|
|
2727
|
+
var KNOWLEDGE_STATUSES = /* @__PURE__ */ new Set(["draft", "published"]);
|
|
2728
|
+
var NEWS_STATUSES = /* @__PURE__ */ new Set(["active", "completed"]);
|
|
2729
|
+
var NEWS_HEADLINE_TYPES = /* @__PURE__ */ new Set(["team", "org_wide"]);
|
|
2730
|
+
var QUESTION_STATUSES = /* @__PURE__ */ new Set(["asked", "answered"]);
|
|
2731
|
+
var PULSE_STATUSES = /* @__PURE__ */ new Set(["on_track", "at_risk", "off_track"]);
|
|
2732
|
+
var SURVEY_RECIPIENT_TYPES = /* @__PURE__ */ new Set(["member", "team", "org_wide"]);
|
|
2733
|
+
var SURVEY_NAMES = /* @__PURE__ */ new Set([
|
|
2734
|
+
"employee_net_promoter_score",
|
|
2735
|
+
"continuous_performance_review",
|
|
2736
|
+
"core_value_alignment",
|
|
2737
|
+
"engagement",
|
|
2738
|
+
"wellness_and_mental_health",
|
|
2739
|
+
"workspace_culture",
|
|
2740
|
+
"peer_review",
|
|
2741
|
+
"manager_review",
|
|
2742
|
+
"onboarding"
|
|
2743
|
+
]);
|
|
2744
|
+
var FEEDBACK_QUARTERS = /* @__PURE__ */ new Set(["q1", "q2", "q3", "q4"]);
|
|
2745
|
+
var FEEDBACK_NAMES = /* @__PURE__ */ new Set([
|
|
2746
|
+
"productivity_and_focus",
|
|
2747
|
+
"company_collaboration",
|
|
2748
|
+
"project_management",
|
|
2749
|
+
"employee_engagement",
|
|
2750
|
+
"training_and_development",
|
|
2751
|
+
"innovation_and_creativity",
|
|
2752
|
+
"customer_insights",
|
|
2753
|
+
"process_improvement",
|
|
2754
|
+
"leadership_and_management",
|
|
2755
|
+
"company_culture",
|
|
2756
|
+
"roadmap_and_strategy",
|
|
2757
|
+
"customer_testing_and_feedback"
|
|
2758
|
+
]);
|
|
2759
|
+
var SCORECARD_INTERVALS = /* @__PURE__ */ new Set([
|
|
2760
|
+
"daily",
|
|
2761
|
+
"weekly",
|
|
2762
|
+
"monthly",
|
|
2763
|
+
"quarterly",
|
|
2764
|
+
"yearly"
|
|
2765
|
+
]);
|
|
2766
|
+
var SCORECARD_TRENDS = /* @__PURE__ */ new Set(["average", "total"]);
|
|
2767
|
+
function isRecord(value) {
|
|
2768
|
+
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
2769
|
+
}
|
|
2770
|
+
function ensureEntityObject(body, rootKey) {
|
|
2771
|
+
const entity = body[rootKey];
|
|
2772
|
+
if (!isRecord(entity)) {
|
|
2773
|
+
throw new CliError({
|
|
2774
|
+
message: `Invalid payload. Expected object at "${rootKey}".`,
|
|
2775
|
+
kind: "invalid_args",
|
|
2776
|
+
status: 400,
|
|
2777
|
+
exitCode: EXIT_CODES.invalidArgs
|
|
2778
|
+
});
|
|
2779
|
+
}
|
|
2780
|
+
return { ...entity };
|
|
2781
|
+
}
|
|
2782
|
+
function throwMissingRequiredCreateFields(rootKey, fields) {
|
|
2783
|
+
throw new CliError({
|
|
2784
|
+
message: `Missing required create fields for ${rootKey}: ${fields.join(", ")}.`,
|
|
2785
|
+
kind: "invalid_args",
|
|
2786
|
+
status: 400,
|
|
2787
|
+
exitCode: EXIT_CODES.invalidArgs,
|
|
2788
|
+
details: { requiredFields: fields, rootKey }
|
|
2114
2789
|
});
|
|
2115
|
-
|
|
2116
|
-
|
|
2117
|
-
|
|
2118
|
-
|
|
2119
|
-
|
|
2120
|
-
|
|
2790
|
+
}
|
|
2791
|
+
function normalizeTodosCreateBody(body) {
|
|
2792
|
+
const todo = ensureEntityObject(body, "todo");
|
|
2793
|
+
const rawStatus = todo.status;
|
|
2794
|
+
if (rawStatus === void 0 || rawStatus === null || String(rawStatus).trim().length === 0) {
|
|
2795
|
+
todo.status = "open";
|
|
2796
|
+
return { ...body, todo };
|
|
2797
|
+
}
|
|
2798
|
+
if (typeof rawStatus !== "string" || !TODO_STATUSES.has(rawStatus)) {
|
|
2799
|
+
throw new CliError({
|
|
2800
|
+
message: "Invalid todo status. Use one of: open, completed.",
|
|
2801
|
+
kind: "invalid_args",
|
|
2802
|
+
status: 400,
|
|
2803
|
+
exitCode: EXIT_CODES.invalidArgs,
|
|
2804
|
+
details: { allowed: Array.from(TODO_STATUSES) }
|
|
2805
|
+
});
|
|
2806
|
+
}
|
|
2807
|
+
return { ...body, todo };
|
|
2808
|
+
}
|
|
2809
|
+
function asNonEmptyString3(value) {
|
|
2810
|
+
if (typeof value !== "string") {
|
|
2811
|
+
return void 0;
|
|
2812
|
+
}
|
|
2813
|
+
const trimmed = value.trim();
|
|
2814
|
+
return trimmed.length > 0 ? trimmed : void 0;
|
|
2815
|
+
}
|
|
2816
|
+
function validateEnumField(params) {
|
|
2817
|
+
const value = asNonEmptyString3(params.rawValue);
|
|
2818
|
+
if (!value) {
|
|
2819
|
+
return void 0;
|
|
2820
|
+
}
|
|
2821
|
+
if (!params.allowed.has(value)) {
|
|
2822
|
+
throw new CliError({
|
|
2823
|
+
message: params.message,
|
|
2824
|
+
kind: "invalid_args",
|
|
2825
|
+
status: 400,
|
|
2826
|
+
exitCode: EXIT_CODES.invalidArgs,
|
|
2827
|
+
details: { field: params.field, allowed: Array.from(params.allowed) }
|
|
2828
|
+
});
|
|
2829
|
+
}
|
|
2830
|
+
return value;
|
|
2831
|
+
}
|
|
2832
|
+
function normalizeKnowledgeCreateBody(body) {
|
|
2833
|
+
const content = ensureEntityObject(body, "content");
|
|
2834
|
+
const contentType = validateEnumField({
|
|
2835
|
+
rawValue: content.content_type,
|
|
2836
|
+
field: "content.content_type",
|
|
2837
|
+
allowed: KNOWLEDGE_CONTENT_TYPES,
|
|
2838
|
+
message: "Invalid content.content_type. Use one of: company, policy, process."
|
|
2839
|
+
});
|
|
2840
|
+
if (!contentType) {
|
|
2841
|
+
throwMissingRequiredCreateFields("content", ["content_type"]);
|
|
2842
|
+
}
|
|
2843
|
+
content.content_type = contentType;
|
|
2844
|
+
const status = validateEnumField({
|
|
2845
|
+
rawValue: content.status,
|
|
2846
|
+
field: "content.status",
|
|
2847
|
+
allowed: KNOWLEDGE_STATUSES,
|
|
2848
|
+
message: "Invalid content.status. Use one of: draft, published."
|
|
2849
|
+
});
|
|
2850
|
+
content.status = status ?? "draft";
|
|
2851
|
+
const memberId = asNonEmptyString3(content.member_id);
|
|
2852
|
+
if (!memberId) {
|
|
2853
|
+
throwMissingRequiredCreateFields("content", ["member_id"]);
|
|
2854
|
+
}
|
|
2855
|
+
content.member_id = memberId;
|
|
2856
|
+
return { ...body, content };
|
|
2857
|
+
}
|
|
2858
|
+
function normalizeNewsCreateBody(body) {
|
|
2859
|
+
const headline = ensureEntityObject(body, "headline");
|
|
2860
|
+
const memberId = asNonEmptyString3(headline.member_id);
|
|
2861
|
+
if (!memberId) {
|
|
2862
|
+
throwMissingRequiredCreateFields("headline", ["member_id"]);
|
|
2863
|
+
}
|
|
2864
|
+
headline.member_id = memberId;
|
|
2865
|
+
const status = validateEnumField({
|
|
2866
|
+
rawValue: headline.status,
|
|
2867
|
+
field: "headline.status",
|
|
2868
|
+
allowed: NEWS_STATUSES,
|
|
2869
|
+
message: "Invalid headline.status. Use one of: active, completed."
|
|
2870
|
+
});
|
|
2871
|
+
if (!status) {
|
|
2872
|
+
throwMissingRequiredCreateFields("headline", ["status"]);
|
|
2873
|
+
}
|
|
2874
|
+
headline.status = status;
|
|
2875
|
+
const headlineType = validateEnumField({
|
|
2876
|
+
rawValue: headline.headline_type,
|
|
2877
|
+
field: "headline.headline_type",
|
|
2878
|
+
allowed: NEWS_HEADLINE_TYPES,
|
|
2879
|
+
message: "Invalid headline.headline_type. Use one of: team, org_wide."
|
|
2880
|
+
});
|
|
2881
|
+
if (!headlineType) {
|
|
2882
|
+
throwMissingRequiredCreateFields("headline", ["headline_type"]);
|
|
2883
|
+
}
|
|
2884
|
+
headline.headline_type = headlineType;
|
|
2885
|
+
return { ...body, headline };
|
|
2886
|
+
}
|
|
2887
|
+
function normalizeQuestionsCreateBody(body) {
|
|
2888
|
+
const question = ensureEntityObject(body, "question");
|
|
2889
|
+
const summary = asNonEmptyString3(question.summary);
|
|
2890
|
+
const currentName = asNonEmptyString3(question.name);
|
|
2891
|
+
if (!currentName && summary) {
|
|
2892
|
+
question.name = summary;
|
|
2893
|
+
}
|
|
2894
|
+
delete question.summary;
|
|
2895
|
+
const name = asNonEmptyString3(question.name);
|
|
2896
|
+
const memberId = asNonEmptyString3(question.member_id);
|
|
2897
|
+
const missing = [];
|
|
2898
|
+
if (!name) missing.push("name");
|
|
2899
|
+
if (!memberId) missing.push("member_id");
|
|
2900
|
+
if (missing.length > 0) {
|
|
2901
|
+
throwMissingRequiredCreateFields("question", missing);
|
|
2902
|
+
}
|
|
2903
|
+
question.name = name;
|
|
2904
|
+
question.member_id = memberId;
|
|
2905
|
+
const status = validateEnumField({
|
|
2906
|
+
rawValue: question.status,
|
|
2907
|
+
field: "question.status",
|
|
2908
|
+
allowed: QUESTION_STATUSES,
|
|
2909
|
+
message: "Invalid question.status. Use one of: asked, answered."
|
|
2910
|
+
});
|
|
2911
|
+
if (status) {
|
|
2912
|
+
question.status = status;
|
|
2913
|
+
}
|
|
2914
|
+
return { ...body, question };
|
|
2915
|
+
}
|
|
2916
|
+
function normalizeQuestionsUpdateBody(body) {
|
|
2917
|
+
const question = ensureEntityObject(body, "question");
|
|
2918
|
+
const summary = asNonEmptyString3(question.summary);
|
|
2919
|
+
const currentName = asNonEmptyString3(question.name);
|
|
2920
|
+
if (!currentName && summary) {
|
|
2921
|
+
question.name = summary;
|
|
2922
|
+
}
|
|
2923
|
+
delete question.summary;
|
|
2924
|
+
const name = asNonEmptyString3(question.name);
|
|
2925
|
+
if (name) {
|
|
2926
|
+
question.name = name;
|
|
2927
|
+
}
|
|
2928
|
+
const status = validateEnumField({
|
|
2929
|
+
rawValue: question.status,
|
|
2930
|
+
field: "question.status",
|
|
2931
|
+
allowed: QUESTION_STATUSES,
|
|
2932
|
+
message: "Invalid question.status. Use one of: asked, answered."
|
|
2933
|
+
});
|
|
2934
|
+
if (status) {
|
|
2935
|
+
question.status = status;
|
|
2936
|
+
}
|
|
2937
|
+
return { ...body, question };
|
|
2938
|
+
}
|
|
2939
|
+
function normalizePulseCreateBody(body) {
|
|
2940
|
+
const healthUpdate = ensureEntityObject(body, "health_update");
|
|
2941
|
+
const healthUpdatableId = asNonEmptyString3(healthUpdate.health_updatable_id) ?? asNonEmptyString3(healthUpdate.updatable_id);
|
|
2942
|
+
const healthUpdatableType = asNonEmptyString3(healthUpdate.health_updatable_type) ?? asNonEmptyString3(healthUpdate.updatable_type);
|
|
2943
|
+
const memberId = asNonEmptyString3(healthUpdate.member_id);
|
|
2944
|
+
const status = validateEnumField({
|
|
2945
|
+
rawValue: healthUpdate.status,
|
|
2946
|
+
field: "health_update.status",
|
|
2947
|
+
allowed: PULSE_STATUSES,
|
|
2948
|
+
message: "Invalid health_update.status. Use one of: on_track, at_risk, off_track."
|
|
2949
|
+
});
|
|
2950
|
+
const missing = [];
|
|
2951
|
+
if (!healthUpdatableId) missing.push("health_updatable_id");
|
|
2952
|
+
if (!healthUpdatableType) missing.push("health_updatable_type");
|
|
2953
|
+
if (!memberId) missing.push("member_id");
|
|
2954
|
+
if (!status) missing.push("status");
|
|
2955
|
+
if (missing.length > 0) {
|
|
2956
|
+
throwMissingRequiredCreateFields("health_update", missing);
|
|
2957
|
+
}
|
|
2958
|
+
healthUpdate.health_updatable_id = healthUpdatableId;
|
|
2959
|
+
healthUpdate.health_updatable_type = healthUpdatableType;
|
|
2960
|
+
healthUpdate.member_id = memberId;
|
|
2961
|
+
healthUpdate.status = status;
|
|
2962
|
+
delete healthUpdate.updatable_id;
|
|
2963
|
+
delete healthUpdate.updatable_type;
|
|
2964
|
+
return { ...body, health_update: healthUpdate };
|
|
2965
|
+
}
|
|
2966
|
+
function normalizeSurveysCreateBody(body) {
|
|
2967
|
+
const survey = ensureEntityObject(body, "survey");
|
|
2968
|
+
const title = asNonEmptyString3(survey.title);
|
|
2969
|
+
const currentName = asNonEmptyString3(survey.name);
|
|
2970
|
+
if (!currentName && title) {
|
|
2971
|
+
survey.name = title;
|
|
2972
|
+
}
|
|
2973
|
+
delete survey.title;
|
|
2974
|
+
const name = validateEnumField({
|
|
2975
|
+
rawValue: survey.name,
|
|
2976
|
+
field: "survey.name",
|
|
2977
|
+
allowed: SURVEY_NAMES,
|
|
2978
|
+
message: "Invalid survey.name. Use one of: employee_net_promoter_score, continuous_performance_review, core_value_alignment, engagement, wellness_and_mental_health, workspace_culture, peer_review, manager_review, onboarding."
|
|
2979
|
+
});
|
|
2980
|
+
const recipientType = validateEnumField({
|
|
2981
|
+
rawValue: survey.recipient_type,
|
|
2982
|
+
field: "survey.recipient_type",
|
|
2983
|
+
allowed: SURVEY_RECIPIENT_TYPES,
|
|
2984
|
+
message: "Invalid survey.recipient_type. Use one of: member, team, org_wide."
|
|
2985
|
+
});
|
|
2986
|
+
const missing = [];
|
|
2987
|
+
if (!name) missing.push("name");
|
|
2988
|
+
if (!recipientType) missing.push("recipient_type");
|
|
2989
|
+
if (missing.length > 0) {
|
|
2990
|
+
throwMissingRequiredCreateFields("survey", missing);
|
|
2991
|
+
}
|
|
2992
|
+
survey.name = name;
|
|
2993
|
+
survey.recipient_type = recipientType;
|
|
2994
|
+
return { ...body, survey };
|
|
2995
|
+
}
|
|
2996
|
+
function normalizeSurveysUpdateBody(body) {
|
|
2997
|
+
const survey = ensureEntityObject(body, "survey");
|
|
2998
|
+
const title = asNonEmptyString3(survey.title);
|
|
2999
|
+
const currentName = asNonEmptyString3(survey.name);
|
|
3000
|
+
if (!currentName && title) {
|
|
3001
|
+
survey.name = title;
|
|
3002
|
+
}
|
|
3003
|
+
delete survey.title;
|
|
3004
|
+
const name = validateEnumField({
|
|
3005
|
+
rawValue: survey.name,
|
|
3006
|
+
field: "survey.name",
|
|
3007
|
+
allowed: SURVEY_NAMES,
|
|
3008
|
+
message: "Invalid survey.name. Use one of: employee_net_promoter_score, continuous_performance_review, core_value_alignment, engagement, wellness_and_mental_health, workspace_culture, peer_review, manager_review, onboarding."
|
|
3009
|
+
});
|
|
3010
|
+
if (name) {
|
|
3011
|
+
survey.name = name;
|
|
3012
|
+
}
|
|
3013
|
+
const recipientType = validateEnumField({
|
|
3014
|
+
rawValue: survey.recipient_type,
|
|
3015
|
+
field: "survey.recipient_type",
|
|
3016
|
+
allowed: SURVEY_RECIPIENT_TYPES,
|
|
3017
|
+
message: "Invalid survey.recipient_type. Use one of: member, team, org_wide."
|
|
3018
|
+
});
|
|
3019
|
+
if (recipientType) {
|
|
3020
|
+
survey.recipient_type = recipientType;
|
|
3021
|
+
}
|
|
3022
|
+
return { ...body, survey };
|
|
3023
|
+
}
|
|
3024
|
+
function normalizeFeedbacksCreateBody(body) {
|
|
3025
|
+
const feedback = ensureEntityObject(body, "feedback");
|
|
3026
|
+
const title = asNonEmptyString3(feedback.title);
|
|
3027
|
+
const currentName = asNonEmptyString3(feedback.name);
|
|
3028
|
+
if (!currentName && title) {
|
|
3029
|
+
feedback.name = title;
|
|
3030
|
+
}
|
|
3031
|
+
delete feedback.title;
|
|
3032
|
+
const name = validateEnumField({
|
|
3033
|
+
rawValue: feedback.name,
|
|
3034
|
+
field: "feedback.name",
|
|
3035
|
+
allowed: FEEDBACK_NAMES,
|
|
3036
|
+
message: "Invalid feedback.name. Use one of: productivity_and_focus, company_collaboration, project_management, employee_engagement, training_and_development, innovation_and_creativity, customer_insights, process_improvement, leadership_and_management, company_culture, roadmap_and_strategy, customer_testing_and_feedback."
|
|
3037
|
+
});
|
|
3038
|
+
const quarter = validateEnumField({
|
|
3039
|
+
rawValue: feedback.quarter,
|
|
3040
|
+
field: "feedback.quarter",
|
|
3041
|
+
allowed: FEEDBACK_QUARTERS,
|
|
3042
|
+
message: "Invalid feedback.quarter. Use one of: q1, q2, q3, q4."
|
|
3043
|
+
});
|
|
3044
|
+
const year = asNonEmptyString3(feedback.year);
|
|
3045
|
+
const missing = [];
|
|
3046
|
+
if (!name) missing.push("name");
|
|
3047
|
+
if (!quarter) missing.push("quarter");
|
|
3048
|
+
if (!year) missing.push("year");
|
|
3049
|
+
if (missing.length > 0) {
|
|
3050
|
+
throwMissingRequiredCreateFields("feedback", missing);
|
|
3051
|
+
}
|
|
3052
|
+
feedback.name = name;
|
|
3053
|
+
feedback.quarter = quarter;
|
|
3054
|
+
feedback.year = year;
|
|
3055
|
+
return { ...body, feedback };
|
|
3056
|
+
}
|
|
3057
|
+
function normalizeFeedbacksUpdateBody(body) {
|
|
3058
|
+
const feedback = ensureEntityObject(body, "feedback");
|
|
3059
|
+
const title = asNonEmptyString3(feedback.title);
|
|
3060
|
+
const currentName = asNonEmptyString3(feedback.name);
|
|
3061
|
+
if (!currentName && title) {
|
|
3062
|
+
feedback.name = title;
|
|
3063
|
+
}
|
|
3064
|
+
delete feedback.title;
|
|
3065
|
+
const name = validateEnumField({
|
|
3066
|
+
rawValue: feedback.name,
|
|
3067
|
+
field: "feedback.name",
|
|
3068
|
+
allowed: FEEDBACK_NAMES,
|
|
3069
|
+
message: "Invalid feedback.name. Use one of: productivity_and_focus, company_collaboration, project_management, employee_engagement, training_and_development, innovation_and_creativity, customer_insights, process_improvement, leadership_and_management, company_culture, roadmap_and_strategy, customer_testing_and_feedback."
|
|
3070
|
+
});
|
|
3071
|
+
if (name) {
|
|
3072
|
+
feedback.name = name;
|
|
3073
|
+
}
|
|
3074
|
+
const quarter = validateEnumField({
|
|
3075
|
+
rawValue: feedback.quarter,
|
|
3076
|
+
field: "feedback.quarter",
|
|
3077
|
+
allowed: FEEDBACK_QUARTERS,
|
|
3078
|
+
message: "Invalid feedback.quarter. Use one of: q1, q2, q3, q4."
|
|
3079
|
+
});
|
|
3080
|
+
if (quarter) {
|
|
3081
|
+
feedback.quarter = quarter;
|
|
3082
|
+
}
|
|
3083
|
+
return { ...body, feedback };
|
|
3084
|
+
}
|
|
3085
|
+
function normalizeAccountabilityCreateBody(body) {
|
|
3086
|
+
const responsibility = ensureEntityObject(body, "responsibility");
|
|
3087
|
+
const summary = asNonEmptyString3(responsibility.summary);
|
|
3088
|
+
const currentName = asNonEmptyString3(responsibility.name);
|
|
3089
|
+
if (!currentName && summary) {
|
|
3090
|
+
responsibility.name = summary;
|
|
3091
|
+
}
|
|
3092
|
+
delete responsibility.summary;
|
|
3093
|
+
const name = asNonEmptyString3(responsibility.name);
|
|
3094
|
+
const memberId = asNonEmptyString3(responsibility.member_id);
|
|
3095
|
+
const missing = [];
|
|
3096
|
+
if (!name) missing.push("name");
|
|
3097
|
+
if (!memberId) missing.push("member_id");
|
|
3098
|
+
if (missing.length > 0) {
|
|
3099
|
+
throwMissingRequiredCreateFields("responsibility", missing);
|
|
3100
|
+
}
|
|
3101
|
+
responsibility.name = name;
|
|
3102
|
+
responsibility.member_id = memberId;
|
|
3103
|
+
return { ...body, responsibility };
|
|
3104
|
+
}
|
|
3105
|
+
function normalizeAccountabilityUpdateBody(body) {
|
|
3106
|
+
const responsibility = ensureEntityObject(body, "responsibility");
|
|
3107
|
+
const summary = asNonEmptyString3(responsibility.summary);
|
|
3108
|
+
const currentName = asNonEmptyString3(responsibility.name);
|
|
3109
|
+
if (!currentName && summary) {
|
|
3110
|
+
responsibility.name = summary;
|
|
3111
|
+
}
|
|
3112
|
+
delete responsibility.summary;
|
|
3113
|
+
return { ...body, responsibility };
|
|
3114
|
+
}
|
|
3115
|
+
function normalizeScorecardsCreateBody(body) {
|
|
3116
|
+
const measurable = ensureEntityObject(body, "measurable");
|
|
3117
|
+
const interval = validateEnumField({
|
|
3118
|
+
rawValue: measurable.interval,
|
|
3119
|
+
field: "measurable.interval",
|
|
3120
|
+
allowed: SCORECARD_INTERVALS,
|
|
3121
|
+
message: "Invalid measurable.interval. Use one of: daily, weekly, monthly, quarterly, yearly."
|
|
3122
|
+
});
|
|
3123
|
+
measurable.interval = interval ?? "weekly";
|
|
3124
|
+
const trend = validateEnumField({
|
|
3125
|
+
rawValue: measurable.trend,
|
|
3126
|
+
field: "measurable.trend",
|
|
3127
|
+
allowed: SCORECARD_TRENDS,
|
|
3128
|
+
message: "Invalid measurable.trend. Use one of: average, total."
|
|
3129
|
+
});
|
|
3130
|
+
measurable.trend = trend ?? "average";
|
|
3131
|
+
return { ...body, measurable };
|
|
3132
|
+
}
|
|
3133
|
+
function buildKpisCreateMutation(params) {
|
|
3134
|
+
const entity = params.body.smart_kpi;
|
|
3135
|
+
if (!entity || typeof entity !== "object" || Array.isArray(entity)) {
|
|
3136
|
+
throw new CliError({
|
|
3137
|
+
message: 'Invalid payload. Expected object at "smart_kpi".',
|
|
3138
|
+
kind: "invalid_args",
|
|
3139
|
+
status: 400,
|
|
3140
|
+
exitCode: EXIT_CODES.invalidArgs
|
|
3141
|
+
});
|
|
3142
|
+
}
|
|
3143
|
+
const smartKpi = { ...entity };
|
|
3144
|
+
const name = asNonEmptyString3(smartKpi.name);
|
|
3145
|
+
const smartKpiViewId = asNonEmptyString3(smartKpi.smart_kpi_view_id);
|
|
3146
|
+
const measurableGroupId = asNonEmptyString3(smartKpi.measurable_group_id);
|
|
3147
|
+
const hasAllowedName = typeof name === "string" && SMART_KPI_NAME_SET.has(name);
|
|
3148
|
+
if (!name) {
|
|
3149
|
+
throw new CliError({
|
|
3150
|
+
message: "Missing required create fields for smart_kpi: name.",
|
|
3151
|
+
kind: "invalid_args",
|
|
3152
|
+
status: 400,
|
|
3153
|
+
exitCode: EXIT_CODES.invalidArgs,
|
|
3154
|
+
details: { requiredFields: ["name"], rootKey: "smart_kpi" }
|
|
3155
|
+
});
|
|
3156
|
+
}
|
|
3157
|
+
if (measurableGroupId && !hasAllowedName) {
|
|
3158
|
+
const measurable = {
|
|
3159
|
+
measurable_group_id: measurableGroupId,
|
|
3160
|
+
name,
|
|
3161
|
+
interval: "daily",
|
|
3162
|
+
trend: "average",
|
|
3163
|
+
measurable_type: "number",
|
|
3164
|
+
condition: "greater_than_or_equal_to"
|
|
3165
|
+
};
|
|
3166
|
+
const notes = asNonEmptyString3(smartKpi.notes);
|
|
3167
|
+
if (notes) {
|
|
3168
|
+
measurable.notes = notes;
|
|
3169
|
+
}
|
|
3170
|
+
return {
|
|
3171
|
+
command: "measurables.create",
|
|
3172
|
+
field: "create_measurable",
|
|
3173
|
+
variables: {
|
|
3174
|
+
organization_id: params.organizationId,
|
|
3175
|
+
params: { measurable }
|
|
3176
|
+
}
|
|
3177
|
+
};
|
|
3178
|
+
}
|
|
3179
|
+
if (!smartKpiViewId) {
|
|
3180
|
+
throw new CliError({
|
|
3181
|
+
message: "Missing required create fields for smart_kpi: smart_kpi_view_id.",
|
|
3182
|
+
kind: "invalid_args",
|
|
3183
|
+
status: 400,
|
|
3184
|
+
exitCode: EXIT_CODES.invalidArgs,
|
|
3185
|
+
details: { requiredFields: ["smart_kpi_view_id"], rootKey: "smart_kpi" }
|
|
3186
|
+
});
|
|
3187
|
+
}
|
|
3188
|
+
if (!hasAllowedName) {
|
|
3189
|
+
throw new CliError({
|
|
3190
|
+
message: "Invalid smart_kpi.name for kpis.create. Use an allowed enum value or route free-text KPI names to measurable create.",
|
|
3191
|
+
kind: "invalid_args",
|
|
3192
|
+
status: 400,
|
|
3193
|
+
exitCode: EXIT_CODES.invalidArgs,
|
|
3194
|
+
details: {
|
|
3195
|
+
field: "smart_kpi.name",
|
|
3196
|
+
allowedValues: SMART_KPI_NAMES
|
|
3197
|
+
}
|
|
3198
|
+
});
|
|
3199
|
+
}
|
|
3200
|
+
delete smartKpi.measurable_group_id;
|
|
3201
|
+
smartKpi.name = name;
|
|
3202
|
+
smartKpi.smart_kpi_view_id = smartKpiViewId;
|
|
3203
|
+
return {
|
|
3204
|
+
command: "kpis.create",
|
|
3205
|
+
field: "create_smart_kpi",
|
|
3206
|
+
variables: {
|
|
3207
|
+
organization_id: params.organizationId,
|
|
3208
|
+
params: { smart_kpi: smartKpi }
|
|
3209
|
+
}
|
|
3210
|
+
};
|
|
3211
|
+
}
|
|
3212
|
+
function registerSystemToolCommands(program) {
|
|
3213
|
+
registerEntityCrudCommands(program, {
|
|
3214
|
+
command: "lists",
|
|
3215
|
+
description: "List operations",
|
|
3216
|
+
resourcePath: "lists",
|
|
3217
|
+
rootKey: "list",
|
|
3218
|
+
listParams: ["include_archived", "member_id", "team_ids", "term"]
|
|
3219
|
+
});
|
|
3220
|
+
registerEntityCrudCommands(program, {
|
|
3221
|
+
command: "list-items",
|
|
3222
|
+
description: "List item operations",
|
|
3223
|
+
resourcePath: "list_items",
|
|
3224
|
+
rootKey: "list_item",
|
|
3225
|
+
requiredCreateFields: ["list_id"],
|
|
3226
|
+
listParams: [
|
|
3227
|
+
"field_blank",
|
|
3228
|
+
"field_name",
|
|
3229
|
+
"field_value",
|
|
3230
|
+
"include_archived",
|
|
3231
|
+
"list_id",
|
|
3232
|
+
"meeting_id",
|
|
3233
|
+
"member_id",
|
|
3234
|
+
"rank_direction",
|
|
3235
|
+
"team_id",
|
|
3236
|
+
"team_ids"
|
|
3237
|
+
]
|
|
3238
|
+
});
|
|
3239
|
+
registerEntityCrudCommands(program, {
|
|
3240
|
+
command: "issue-groups",
|
|
3241
|
+
description: "Issue group operations",
|
|
3242
|
+
resourcePath: "issue_groups",
|
|
3243
|
+
rootKey: "issue_group",
|
|
3244
|
+
listParams: ["include_archived", "member_id", "team_ids", "term"]
|
|
3245
|
+
});
|
|
3246
|
+
registerEntityCrudCommands(program, {
|
|
3247
|
+
command: "todo-groups",
|
|
3248
|
+
description: "To-do group operations",
|
|
3249
|
+
resourcePath: "todo_groups",
|
|
3250
|
+
rootKey: "todo_group",
|
|
3251
|
+
listParams: ["include_archived", "member_id", "team_ids", "term"]
|
|
3252
|
+
});
|
|
3253
|
+
registerEntityCrudCommands(program, {
|
|
3254
|
+
command: "todos",
|
|
3255
|
+
description: "To-do operations",
|
|
3256
|
+
resourcePath: "todos",
|
|
3257
|
+
rootKey: "todo",
|
|
3258
|
+
requiredCreateFields: ["todo_group_id"],
|
|
3259
|
+
normalizeCreateBody: normalizeTodosCreateBody,
|
|
2121
3260
|
listParams: [
|
|
2122
3261
|
"include_archived",
|
|
2123
3262
|
"meeting_id",
|
|
@@ -2140,6 +3279,7 @@ function registerSystemToolCommands(program) {
|
|
|
2140
3279
|
description: "Knowledge content operations",
|
|
2141
3280
|
resourcePath: "contents",
|
|
2142
3281
|
rootKey: "content",
|
|
3282
|
+
normalizeCreateBody: normalizeKnowledgeCreateBody,
|
|
2143
3283
|
listParams: [
|
|
2144
3284
|
"assigned",
|
|
2145
3285
|
"contentable_id",
|
|
@@ -2170,13 +3310,40 @@ function registerSystemToolCommands(program) {
|
|
|
2170
3310
|
description: "News operations",
|
|
2171
3311
|
resourcePath: "headlines",
|
|
2172
3312
|
rootKey: "headline",
|
|
2173
|
-
|
|
3313
|
+
requiredCreateFields: ["member_id", "status", "headline_type"],
|
|
3314
|
+
normalizeCreateBody: normalizeNewsCreateBody,
|
|
3315
|
+
listParams: ["meeting_id", "unread"],
|
|
3316
|
+
showQueryFactory: ({ id, organizationId }) => ({
|
|
3317
|
+
field: "headlines",
|
|
3318
|
+
variables: {
|
|
3319
|
+
organization_id: organizationId,
|
|
3320
|
+
page: 1,
|
|
3321
|
+
per: 200
|
|
3322
|
+
},
|
|
3323
|
+
selectionSet: "{ data { id type attributes } count currentPage totalPages }",
|
|
3324
|
+
transformData: (value) => {
|
|
3325
|
+
if (!value || typeof value !== "object") {
|
|
3326
|
+
return null;
|
|
3327
|
+
}
|
|
3328
|
+
const payload = value;
|
|
3329
|
+
const rows = Array.isArray(payload.data) ? payload.data : [];
|
|
3330
|
+
return rows.find((row) => {
|
|
3331
|
+
if (!row || typeof row !== "object") {
|
|
3332
|
+
return false;
|
|
3333
|
+
}
|
|
3334
|
+
return String(row.id ?? "") === id;
|
|
3335
|
+
}) ?? null;
|
|
3336
|
+
}
|
|
3337
|
+
})
|
|
2174
3338
|
});
|
|
2175
3339
|
registerEntityCrudCommands(program, {
|
|
2176
3340
|
command: "questions",
|
|
2177
3341
|
description: "Q&A forum operations",
|
|
2178
3342
|
resourcePath: "questions",
|
|
2179
3343
|
rootKey: "question",
|
|
3344
|
+
requiredCreateFields: ["member_id", "name"],
|
|
3345
|
+
normalizeCreateBody: normalizeQuestionsCreateBody,
|
|
3346
|
+
normalizeUpdateBody: normalizeQuestionsUpdateBody,
|
|
2180
3347
|
listParams: ["answered", "asked", "member_id", "team_id", "term"]
|
|
2181
3348
|
});
|
|
2182
3349
|
registerEntityCrudCommands(program, {
|
|
@@ -2184,6 +3351,8 @@ function registerSystemToolCommands(program) {
|
|
|
2184
3351
|
description: "Pulse operations",
|
|
2185
3352
|
resourcePath: "health_updates",
|
|
2186
3353
|
rootKey: "health_update",
|
|
3354
|
+
requiredCreateFields: ["health_updatable_id", "health_updatable_type", "member_id", "status"],
|
|
3355
|
+
normalizeCreateBody: normalizePulseCreateBody,
|
|
2187
3356
|
listParams: ["health_updatable_id", "health_updatable_type"]
|
|
2188
3357
|
});
|
|
2189
3358
|
registerEntityCrudCommands(program, {
|
|
@@ -2191,6 +3360,9 @@ function registerSystemToolCommands(program) {
|
|
|
2191
3360
|
description: "Survey operations",
|
|
2192
3361
|
resourcePath: "surveys",
|
|
2193
3362
|
rootKey: "survey",
|
|
3363
|
+
requiredCreateFields: ["name", "recipient_type"],
|
|
3364
|
+
normalizeCreateBody: normalizeSurveysCreateBody,
|
|
3365
|
+
normalizeUpdateBody: normalizeSurveysUpdateBody,
|
|
2194
3366
|
listParams: ["completed", "current_member", "due", "exclude_completed"]
|
|
2195
3367
|
});
|
|
2196
3368
|
registerEntityCrudCommands(program, {
|
|
@@ -2198,6 +3370,9 @@ function registerSystemToolCommands(program) {
|
|
|
2198
3370
|
description: "Feedback operations",
|
|
2199
3371
|
resourcePath: "feedback",
|
|
2200
3372
|
rootKey: "feedback",
|
|
3373
|
+
requiredCreateFields: ["name", "quarter", "year"],
|
|
3374
|
+
normalizeCreateBody: normalizeFeedbacksCreateBody,
|
|
3375
|
+
normalizeUpdateBody: normalizeFeedbacksUpdateBody,
|
|
2201
3376
|
listParams: ["last", "latest", "start_date"]
|
|
2202
3377
|
});
|
|
2203
3378
|
registerEntityCrudCommands(program, {
|
|
@@ -2205,6 +3380,9 @@ function registerSystemToolCommands(program) {
|
|
|
2205
3380
|
description: "Accountability operations",
|
|
2206
3381
|
resourcePath: "responsibilities",
|
|
2207
3382
|
rootKey: "responsibility",
|
|
3383
|
+
requiredCreateFields: ["name", "member_id"],
|
|
3384
|
+
normalizeCreateBody: normalizeAccountabilityCreateBody,
|
|
3385
|
+
normalizeUpdateBody: normalizeAccountabilityUpdateBody,
|
|
2208
3386
|
listParams: ["meeting_id", "term"]
|
|
2209
3387
|
});
|
|
2210
3388
|
registerEntityCrudCommands(program, {
|
|
@@ -2212,6 +3390,10 @@ function registerSystemToolCommands(program) {
|
|
|
2212
3390
|
description: "KPI operations",
|
|
2213
3391
|
resourcePath: "smart_kpis",
|
|
2214
3392
|
rootKey: "smart_kpi",
|
|
3393
|
+
createMutationFactory: ({ body, organizationId }) => buildKpisCreateMutation({
|
|
3394
|
+
body,
|
|
3395
|
+
organizationId
|
|
3396
|
+
}),
|
|
2215
3397
|
listParams: [
|
|
2216
3398
|
"annual_objective_id",
|
|
2217
3399
|
"include_archived",
|
|
@@ -2237,6 +3419,7 @@ function registerSystemToolCommands(program) {
|
|
|
2237
3419
|
resourcePath: "measurables",
|
|
2238
3420
|
rootKey: "measurable",
|
|
2239
3421
|
requiredCreateFields: ["measurable_group_id"],
|
|
3422
|
+
normalizeCreateBody: normalizeScorecardsCreateBody,
|
|
2240
3423
|
listParams: [
|
|
2241
3424
|
"annual_objective_id",
|
|
2242
3425
|
"include_archived",
|
|
@@ -2338,6 +3521,103 @@ function registerTeamCommands(program) {
|
|
|
2338
3521
|
// src/commands/organizations.ts
|
|
2339
3522
|
import { z as z10 } from "zod";
|
|
2340
3523
|
var idSchema9 = z10.string().min(1);
|
|
3524
|
+
function isRecord2(value) {
|
|
3525
|
+
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
3526
|
+
}
|
|
3527
|
+
function ensureRootObject(body, rootKey) {
|
|
3528
|
+
const root = body[rootKey];
|
|
3529
|
+
if (!isRecord2(root)) {
|
|
3530
|
+
throw new CliError({
|
|
3531
|
+
message: `Invalid payload. Expected object at "${rootKey}".`,
|
|
3532
|
+
kind: "invalid_args",
|
|
3533
|
+
status: 400,
|
|
3534
|
+
exitCode: EXIT_CODES.invalidArgs
|
|
3535
|
+
});
|
|
3536
|
+
}
|
|
3537
|
+
return { ...root };
|
|
3538
|
+
}
|
|
3539
|
+
function asNonEmptyString4(value) {
|
|
3540
|
+
if (typeof value !== "string") {
|
|
3541
|
+
return void 0;
|
|
3542
|
+
}
|
|
3543
|
+
const trimmed = value.trim();
|
|
3544
|
+
return trimmed.length > 0 ? trimmed : void 0;
|
|
3545
|
+
}
|
|
3546
|
+
function normalizeOrganizationUpdateBody(body) {
|
|
3547
|
+
const organization = ensureRootObject(body, "organization");
|
|
3548
|
+
const detail = isRecord2(organization.organization_detail_attributes) ? { ...organization.organization_detail_attributes } : {};
|
|
3549
|
+
const workspaceName = asNonEmptyString4(organization.workspace_name);
|
|
3550
|
+
if (workspaceName) {
|
|
3551
|
+
detail.workspace_name = workspaceName;
|
|
3552
|
+
}
|
|
3553
|
+
delete organization.workspace_name;
|
|
3554
|
+
if (Object.keys(detail).length > 0) {
|
|
3555
|
+
organization.organization_detail_attributes = detail;
|
|
3556
|
+
}
|
|
3557
|
+
return { organization };
|
|
3558
|
+
}
|
|
3559
|
+
function normalizeOrganizationMetaProfileUpdateBody(body) {
|
|
3560
|
+
const root = ensureRootObject(body, "organization_meta_profile");
|
|
3561
|
+
const profile = isRecord2(root.profile) ? { ...root.profile } : {};
|
|
3562
|
+
const title = asNonEmptyString4(root.title);
|
|
3563
|
+
if (title) {
|
|
3564
|
+
const companyIdentity = isRecord2(profile.company_identity) ? { ...profile.company_identity } : {};
|
|
3565
|
+
companyIdentity.one_sentence_summary = title;
|
|
3566
|
+
profile.company_identity = companyIdentity;
|
|
3567
|
+
}
|
|
3568
|
+
const unsupported = Object.keys(root).filter((key) => key !== "profile" && key !== "title");
|
|
3569
|
+
if (unsupported.length > 0) {
|
|
3570
|
+
throw new CliError({
|
|
3571
|
+
message: "Invalid organization_meta_profile update payload. Use organization_meta_profile.profile.<section>.<field>.",
|
|
3572
|
+
kind: "invalid_args",
|
|
3573
|
+
status: 400,
|
|
3574
|
+
exitCode: EXIT_CODES.invalidArgs,
|
|
3575
|
+
details: { unsupportedKeys: unsupported, expectedRootKey: "profile" }
|
|
3576
|
+
});
|
|
3577
|
+
}
|
|
3578
|
+
if (Object.keys(profile).length === 0) {
|
|
3579
|
+
throw new CliError({
|
|
3580
|
+
message: "Missing required update fields for organization_meta_profile: profile.",
|
|
3581
|
+
kind: "invalid_args",
|
|
3582
|
+
status: 400,
|
|
3583
|
+
exitCode: EXIT_CODES.invalidArgs,
|
|
3584
|
+
details: { requiredFields: ["profile"], rootKey: "organization_meta_profile" }
|
|
3585
|
+
});
|
|
3586
|
+
}
|
|
3587
|
+
return { organization_meta_profile: { profile } };
|
|
3588
|
+
}
|
|
3589
|
+
function normalizeKeyMetricMetaProfileUpdateBody(body) {
|
|
3590
|
+
const root = ensureRootObject(body, "key_metric_meta_profile");
|
|
3591
|
+
const profile = isRecord2(root.profile) ? { ...root.profile } : {};
|
|
3592
|
+
const annualRevenue = asNonEmptyString4(root.annual_revenue);
|
|
3593
|
+
if (annualRevenue) {
|
|
3594
|
+
const financial = isRecord2(profile.financial) ? { ...profile.financial } : {};
|
|
3595
|
+
financial.revenue = annualRevenue;
|
|
3596
|
+
profile.financial = financial;
|
|
3597
|
+
}
|
|
3598
|
+
const unsupported = Object.keys(root).filter(
|
|
3599
|
+
(key) => key !== "profile" && key !== "annual_revenue"
|
|
3600
|
+
);
|
|
3601
|
+
if (unsupported.length > 0) {
|
|
3602
|
+
throw new CliError({
|
|
3603
|
+
message: "Invalid key_metric_meta_profile update payload. Use key_metric_meta_profile.profile.<section>.<field>.",
|
|
3604
|
+
kind: "invalid_args",
|
|
3605
|
+
status: 400,
|
|
3606
|
+
exitCode: EXIT_CODES.invalidArgs,
|
|
3607
|
+
details: { unsupportedKeys: unsupported, expectedRootKey: "profile" }
|
|
3608
|
+
});
|
|
3609
|
+
}
|
|
3610
|
+
if (Object.keys(profile).length === 0) {
|
|
3611
|
+
throw new CliError({
|
|
3612
|
+
message: "Missing required update fields for key_metric_meta_profile: profile.",
|
|
3613
|
+
kind: "invalid_args",
|
|
3614
|
+
status: 400,
|
|
3615
|
+
exitCode: EXIT_CODES.invalidArgs,
|
|
3616
|
+
details: { requiredFields: ["profile"], rootKey: "key_metric_meta_profile" }
|
|
3617
|
+
});
|
|
3618
|
+
}
|
|
3619
|
+
return { key_metric_meta_profile: { profile } };
|
|
3620
|
+
}
|
|
2341
3621
|
function registerOrganizationCommands(program) {
|
|
2342
3622
|
const organizations = program.command("organizations").description("Organization operations");
|
|
2343
3623
|
organizations.command("show").option("--id <id>", "Organization ID (defaults to resolved organization context)").action(async (opts, cmd) => {
|
|
@@ -2359,7 +3639,8 @@ function registerOrganizationCommands(program) {
|
|
|
2359
3639
|
const context = await resolveCommandContext(cmd.optsWithGlobals());
|
|
2360
3640
|
const fallbackId = resolveOrganizationId(context.organizationId);
|
|
2361
3641
|
const id = idSchema9.parse(opts.id ?? fallbackId);
|
|
2362
|
-
const
|
|
3642
|
+
const rawBody = __testables.normalizeBody(String(opts.dataJson), "organization");
|
|
3643
|
+
const body = normalizeOrganizationUpdateBody(rawBody);
|
|
2363
3644
|
await runGraphqlMutationCommand({
|
|
2364
3645
|
command: "organizations.update",
|
|
2365
3646
|
runtimeOptions: context.runtimeOptions,
|
|
@@ -2393,10 +3674,11 @@ function registerOrganizationCommands(program) {
|
|
|
2393
3674
|
const context = await resolveCommandContext(cmd.optsWithGlobals());
|
|
2394
3675
|
const organizationId = resolveOrganizationId(context.organizationId);
|
|
2395
3676
|
const id = idSchema9.parse(opts.id ?? organizationId);
|
|
2396
|
-
const
|
|
3677
|
+
const rawBody = __testables.normalizeBody(
|
|
2397
3678
|
String(opts.dataJson),
|
|
2398
3679
|
"organization_meta_profile"
|
|
2399
3680
|
);
|
|
3681
|
+
const body = normalizeOrganizationMetaProfileUpdateBody(rawBody);
|
|
2400
3682
|
await runGraphqlMutationCommand({
|
|
2401
3683
|
command: "organizations.meta-profile.update",
|
|
2402
3684
|
runtimeOptions: context.runtimeOptions,
|
|
@@ -2431,10 +3713,11 @@ function registerOrganizationCommands(program) {
|
|
|
2431
3713
|
const context = await resolveCommandContext(cmd.optsWithGlobals());
|
|
2432
3714
|
const organizationId = resolveOrganizationId(context.organizationId);
|
|
2433
3715
|
const id = idSchema9.parse(opts.id ?? organizationId);
|
|
2434
|
-
const
|
|
3716
|
+
const rawBody = __testables.normalizeBody(
|
|
2435
3717
|
String(opts.dataJson),
|
|
2436
3718
|
"key_metric_meta_profile"
|
|
2437
3719
|
);
|
|
3720
|
+
const body = normalizeKeyMetricMetaProfileUpdateBody(rawBody);
|
|
2438
3721
|
await runGraphqlMutationCommand({
|
|
2439
3722
|
command: "organizations.key-metric-meta-profile.update",
|
|
2440
3723
|
runtimeOptions: context.runtimeOptions,
|
|
@@ -2451,36 +3734,131 @@ function registerOrganizationCommands(program) {
|
|
|
2451
3734
|
// src/commands/foundation.ts
|
|
2452
3735
|
import { z as z11 } from "zod";
|
|
2453
3736
|
var idSchema10 = z11.string().min(1);
|
|
2454
|
-
|
|
2455
|
-
|
|
2456
|
-
|
|
2457
|
-
|
|
2458
|
-
|
|
2459
|
-
|
|
2460
|
-
|
|
2461
|
-
|
|
2462
|
-
|
|
2463
|
-
|
|
2464
|
-
|
|
2465
|
-
|
|
2466
|
-
|
|
2467
|
-
|
|
2468
|
-
|
|
2469
|
-
|
|
2470
|
-
|
|
2471
|
-
|
|
2472
|
-
}
|
|
2473
|
-
|
|
3737
|
+
var STRATEGIC_PLAN_ALLOWED_UPDATE_KEYS = /* @__PURE__ */ new Set([
|
|
3738
|
+
"published_at",
|
|
3739
|
+
"profile",
|
|
3740
|
+
"strategic_plan_reads_attributes"
|
|
3741
|
+
]);
|
|
3742
|
+
var STRATEGIC_OBJECTIVE_ALLOWED_UPDATE_KEYS = /* @__PURE__ */ new Set([
|
|
3743
|
+
"summary",
|
|
3744
|
+
"alignment_score",
|
|
3745
|
+
"published_at",
|
|
3746
|
+
"strategic_objective_reads_attributes"
|
|
3747
|
+
]);
|
|
3748
|
+
function isRecord3(value) {
|
|
3749
|
+
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
3750
|
+
}
|
|
3751
|
+
function ensureRootObject2(body, rootKey) {
|
|
3752
|
+
const root = body[rootKey];
|
|
3753
|
+
if (!isRecord3(root)) {
|
|
3754
|
+
throw new CliError({
|
|
3755
|
+
message: `Invalid payload. Expected object at "${rootKey}".`,
|
|
3756
|
+
kind: "invalid_args",
|
|
3757
|
+
status: 400,
|
|
3758
|
+
exitCode: EXIT_CODES.invalidArgs
|
|
2474
3759
|
});
|
|
2475
|
-
}
|
|
2476
|
-
|
|
2477
|
-
|
|
2478
|
-
|
|
2479
|
-
|
|
2480
|
-
|
|
3760
|
+
}
|
|
3761
|
+
return { ...root };
|
|
3762
|
+
}
|
|
3763
|
+
function asNonEmptyString5(value) {
|
|
3764
|
+
if (typeof value !== "string") {
|
|
3765
|
+
return void 0;
|
|
3766
|
+
}
|
|
3767
|
+
const trimmed = value.trim();
|
|
3768
|
+
return trimmed.length > 0 ? trimmed : void 0;
|
|
3769
|
+
}
|
|
3770
|
+
function normalizeStrategicPlanUpdateBody(body) {
|
|
3771
|
+
const strategicPlan = ensureRootObject2(body, "strategic_plan");
|
|
3772
|
+
const unsupported = Object.keys(strategicPlan).filter(
|
|
3773
|
+
(key) => !STRATEGIC_PLAN_ALLOWED_UPDATE_KEYS.has(key)
|
|
3774
|
+
);
|
|
3775
|
+
if (unsupported.length > 0) {
|
|
3776
|
+
throw new CliError({
|
|
3777
|
+
message: "Invalid strategic_plan update payload. Allowed keys: published_at, profile, strategic_plan_reads_attributes.",
|
|
3778
|
+
kind: "invalid_args",
|
|
3779
|
+
status: 400,
|
|
3780
|
+
exitCode: EXIT_CODES.invalidArgs,
|
|
3781
|
+
details: {
|
|
3782
|
+
unsupportedKeys: unsupported,
|
|
3783
|
+
allowedKeys: Array.from(STRATEGIC_PLAN_ALLOWED_UPDATE_KEYS)
|
|
3784
|
+
}
|
|
3785
|
+
});
|
|
3786
|
+
}
|
|
3787
|
+
return { strategic_plan: strategicPlan };
|
|
3788
|
+
}
|
|
3789
|
+
function normalizeStrategicObjectiveUpdateBody(body) {
|
|
3790
|
+
const strategicObjective = ensureRootObject2(body, "strategic_objective");
|
|
3791
|
+
const title = asNonEmptyString5(strategicObjective.title);
|
|
3792
|
+
if (!asNonEmptyString5(strategicObjective.summary) && title) {
|
|
3793
|
+
strategicObjective.summary = title;
|
|
3794
|
+
}
|
|
3795
|
+
delete strategicObjective.title;
|
|
3796
|
+
const unsupported = Object.keys(strategicObjective).filter(
|
|
3797
|
+
(key) => !STRATEGIC_OBJECTIVE_ALLOWED_UPDATE_KEYS.has(key)
|
|
3798
|
+
);
|
|
3799
|
+
if (unsupported.length > 0) {
|
|
3800
|
+
throw new CliError({
|
|
3801
|
+
message: "Invalid strategic_objective update payload. Allowed keys: summary, alignment_score, published_at, strategic_objective_reads_attributes.",
|
|
3802
|
+
kind: "invalid_args",
|
|
3803
|
+
status: 400,
|
|
3804
|
+
exitCode: EXIT_CODES.invalidArgs,
|
|
3805
|
+
details: {
|
|
3806
|
+
unsupportedKeys: unsupported,
|
|
3807
|
+
allowedKeys: Array.from(STRATEGIC_OBJECTIVE_ALLOWED_UPDATE_KEYS)
|
|
3808
|
+
}
|
|
3809
|
+
});
|
|
3810
|
+
}
|
|
3811
|
+
return { strategic_objective: strategicObjective };
|
|
3812
|
+
}
|
|
3813
|
+
function normalizeAnnualObjectiveCreateBody(body) {
|
|
3814
|
+
const annualObjective = ensureRootObject2(body, "annual_objective");
|
|
3815
|
+
const title = asNonEmptyString5(annualObjective.title);
|
|
3816
|
+
if (!asNonEmptyString5(annualObjective.name) && title) {
|
|
3817
|
+
annualObjective.name = title;
|
|
3818
|
+
}
|
|
3819
|
+
delete annualObjective.title;
|
|
3820
|
+
return { annual_objective: annualObjective };
|
|
3821
|
+
}
|
|
3822
|
+
function normalizeQuarterlyObjectiveCreateBody(body) {
|
|
3823
|
+
const quarterlyObjective = ensureRootObject2(body, "quarterly_objective");
|
|
3824
|
+
const title = asNonEmptyString5(quarterlyObjective.title);
|
|
3825
|
+
if (!asNonEmptyString5(quarterlyObjective.name) && title) {
|
|
3826
|
+
quarterlyObjective.name = title;
|
|
3827
|
+
}
|
|
3828
|
+
delete quarterlyObjective.title;
|
|
3829
|
+
return { quarterly_objective: quarterlyObjective };
|
|
3830
|
+
}
|
|
3831
|
+
function registerFoundationCommands(program) {
|
|
3832
|
+
const foundation = program.command("foundation").description("Foundation operations");
|
|
3833
|
+
const strategicPlans = foundation.command("strategic-plans").description("Strategic plan operations");
|
|
3834
|
+
const strategicObjectives = foundation.command("strategic-objectives").description("Strategic objective operations");
|
|
3835
|
+
strategicPlans.command("show").option("--id <id>", "Strategic plan ID (defaults to organization context)").option("--progress-scope <progressScope>").option("--all-progress <allProgress>").option("--all <all>").action(async (opts, cmd) => {
|
|
3836
|
+
const context = await resolveCommandContext(cmd.optsWithGlobals());
|
|
2481
3837
|
const organizationId = resolveOrganizationId(context.organizationId);
|
|
2482
3838
|
const id = idSchema10.parse(opts.id ?? organizationId);
|
|
2483
|
-
|
|
3839
|
+
await runGraphqlQueryCommand({
|
|
3840
|
+
command: "foundation.strategic-plans.show",
|
|
3841
|
+
runtimeOptions: context.runtimeOptions,
|
|
3842
|
+
field: "strategic_plan",
|
|
3843
|
+
variables: normalizeGraphqlVariables2({
|
|
3844
|
+
organization_id: organizationId,
|
|
3845
|
+
id,
|
|
3846
|
+
progress_scope: opts.progressScope,
|
|
3847
|
+
all_progress: opts.allProgress,
|
|
3848
|
+
all: opts.all
|
|
3849
|
+
}),
|
|
3850
|
+
isShow: true
|
|
3851
|
+
});
|
|
3852
|
+
});
|
|
3853
|
+
strategicPlans.command("update").option("--id <id>", "Strategic plan ID (defaults to organization context)").requiredOption(
|
|
3854
|
+
"--data-json <dataJson>",
|
|
3855
|
+
'JSON object for strategic_plan or {"strategic_plan": {...}}'
|
|
3856
|
+
).action(async (opts, cmd) => {
|
|
3857
|
+
const context = await resolveCommandContext(cmd.optsWithGlobals());
|
|
3858
|
+
const organizationId = resolveOrganizationId(context.organizationId);
|
|
3859
|
+
const id = idSchema10.parse(opts.id ?? organizationId);
|
|
3860
|
+
const rawBody = __testables.normalizeBody(String(opts.dataJson), "strategic_plan");
|
|
3861
|
+
const body = normalizeStrategicPlanUpdateBody(rawBody);
|
|
2484
3862
|
await runGraphqlMutationCommand({
|
|
2485
3863
|
command: "foundation.strategic-plans.update",
|
|
2486
3864
|
runtimeOptions: context.runtimeOptions,
|
|
@@ -2517,10 +3895,11 @@ function registerFoundationCommands(program) {
|
|
|
2517
3895
|
const context = await resolveCommandContext(cmd.optsWithGlobals());
|
|
2518
3896
|
const organizationId = resolveOrganizationId(context.organizationId);
|
|
2519
3897
|
const id = idSchema10.parse(opts.id ?? organizationId);
|
|
2520
|
-
const
|
|
3898
|
+
const rawBody = __testables.normalizeBody(
|
|
2521
3899
|
String(opts.dataJson),
|
|
2522
3900
|
"strategic_objective"
|
|
2523
3901
|
);
|
|
3902
|
+
const body = normalizeStrategicObjectiveUpdateBody(rawBody);
|
|
2524
3903
|
await runGraphqlMutationCommand({
|
|
2525
3904
|
command: "foundation.strategic-objectives.update",
|
|
2526
3905
|
runtimeOptions: context.runtimeOptions,
|
|
@@ -2537,7 +3916,8 @@ function registerFoundationCommands(program) {
|
|
|
2537
3916
|
description: "Foundation annual objective operations",
|
|
2538
3917
|
resourcePath: "annual_objectives",
|
|
2539
3918
|
rootKey: "annual_objective",
|
|
2540
|
-
requiredCreateFields: ["strategic_objective_id"],
|
|
3919
|
+
requiredCreateFields: ["strategic_objective_id", "name"],
|
|
3920
|
+
normalizeCreateBody: normalizeAnnualObjectiveCreateBody,
|
|
2541
3921
|
listParams: []
|
|
2542
3922
|
});
|
|
2543
3923
|
registerEntityCrudCommands(foundation, {
|
|
@@ -2545,7 +3925,8 @@ function registerFoundationCommands(program) {
|
|
|
2545
3925
|
description: "Foundation quarterly objective operations",
|
|
2546
3926
|
resourcePath: "quarterly_objectives",
|
|
2547
3927
|
rootKey: "quarterly_objective",
|
|
2548
|
-
requiredCreateFields: ["strategic_objective_id", "annual_objective_id"],
|
|
3928
|
+
requiredCreateFields: ["strategic_objective_id", "annual_objective_id", "name"],
|
|
3929
|
+
normalizeCreateBody: normalizeQuarterlyObjectiveCreateBody,
|
|
2549
3930
|
listParams: ["annual_objective_id"]
|
|
2550
3931
|
});
|
|
2551
3932
|
}
|
|
@@ -2649,6 +4030,20 @@ function normalizeListPayload(payload, parentKind, parentIdFallback, parentTyped
|
|
|
2649
4030
|
totalPages: record.totalPages ?? 1
|
|
2650
4031
|
};
|
|
2651
4032
|
}
|
|
4033
|
+
function normalizeSubtaskCreateBody(body) {
|
|
4034
|
+
const subtask = body.subtask;
|
|
4035
|
+
if (!subtask || typeof subtask !== "object" || Array.isArray(subtask)) {
|
|
4036
|
+
return body;
|
|
4037
|
+
}
|
|
4038
|
+
const subtaskRecord = subtask;
|
|
4039
|
+
const summary = typeof subtaskRecord.summary === "string" ? subtaskRecord.summary.trim() : void 0;
|
|
4040
|
+
const hasName = typeof subtaskRecord.name === "string" && subtaskRecord.name.trim().length > 0;
|
|
4041
|
+
if (!hasName && summary && summary.length > 0) {
|
|
4042
|
+
subtaskRecord.name = summary;
|
|
4043
|
+
}
|
|
4044
|
+
delete subtaskRecord.summary;
|
|
4045
|
+
return body;
|
|
4046
|
+
}
|
|
2652
4047
|
function registerChildCommands(program, config) {
|
|
2653
4048
|
const command = program.command(config.command).description(config.description);
|
|
2654
4049
|
command.command("list").requiredOption(`--${config.parentFlag} <${config.parentFlag}>`).option("--page <page>").option("--per <per>").action(async (opts, cmd) => {
|
|
@@ -2679,7 +4074,10 @@ function registerChildCommands(program, config) {
|
|
|
2679
4074
|
command.command("create").requiredOption("--data-json <dataJson>").action(async (opts, cmd) => {
|
|
2680
4075
|
const context = await resolveCommandContext(cmd.optsWithGlobals());
|
|
2681
4076
|
const organizationId = resolveOrganizationId(context.organizationId);
|
|
2682
|
-
|
|
4077
|
+
let body = normalizeBody2(String(opts.dataJson), config.rootKey);
|
|
4078
|
+
if (config.normalizeCreateBody) {
|
|
4079
|
+
body = config.normalizeCreateBody(body);
|
|
4080
|
+
}
|
|
2683
4081
|
assertRequiredParent(body, config.rootKey, config.parentFlag.replace(/-/g, "_"));
|
|
2684
4082
|
await runGraphqlMutationCommand({
|
|
2685
4083
|
command: `${config.command}.create`,
|
|
@@ -2742,7 +4140,8 @@ function registerChildEntityCommands(program) {
|
|
|
2742
4140
|
updateOperationName: "UpdateSubtask",
|
|
2743
4141
|
destroyOperationName: "DestroySubtask",
|
|
2744
4142
|
listSelectionSet: "{ data { id type name status taskId attributes } count currentPage totalPages }",
|
|
2745
|
-
listParentTypedField: "taskId"
|
|
4143
|
+
listParentTypedField: "taskId",
|
|
4144
|
+
normalizeCreateBody: normalizeSubtaskCreateBody
|
|
2746
4145
|
});
|
|
2747
4146
|
registerChildCommands(program, {
|
|
2748
4147
|
command: "milestones",
|
|
@@ -3024,8 +4423,980 @@ function registerNoteCommands(program) {
|
|
|
3024
4423
|
});
|
|
3025
4424
|
}
|
|
3026
4425
|
|
|
4426
|
+
// src/commands/markdownTree.ts
|
|
4427
|
+
import { z as z14 } from "zod";
|
|
4428
|
+
var nonEmptyString2 = z14.string().min(1);
|
|
4429
|
+
var nonNegativeInt = z14.coerce.number().int().min(0);
|
|
4430
|
+
function addScopeOptions(command) {
|
|
4431
|
+
return command.requiredOption("--tool-key <toolKey>").requiredOption("--node-key <nodeKey>").option("--parent-id <parentId>").option("--record-id <recordId>").option("--member-id <memberId>").option("--team-id <teamId>").option("--content-type <contentType>").option("--tree-view");
|
|
4432
|
+
}
|
|
4433
|
+
function parseScopeOptions(raw) {
|
|
4434
|
+
const parsed = {
|
|
4435
|
+
toolKey: nonEmptyString2.parse(raw.toolKey),
|
|
4436
|
+
nodeKey: nonEmptyString2.parse(raw.nodeKey)
|
|
4437
|
+
};
|
|
4438
|
+
if (typeof raw.parentId === "string" && raw.parentId.trim() !== "") {
|
|
4439
|
+
parsed.parentId = raw.parentId.trim();
|
|
4440
|
+
}
|
|
4441
|
+
if (typeof raw.recordId === "string" && raw.recordId.trim() !== "") {
|
|
4442
|
+
parsed.recordId = raw.recordId.trim();
|
|
4443
|
+
}
|
|
4444
|
+
if (typeof raw.memberId === "string" && raw.memberId.trim() !== "") {
|
|
4445
|
+
parsed.memberId = raw.memberId.trim();
|
|
4446
|
+
}
|
|
4447
|
+
if (typeof raw.teamId === "string" && raw.teamId.trim() !== "") {
|
|
4448
|
+
parsed.teamId = raw.teamId.trim();
|
|
4449
|
+
}
|
|
4450
|
+
if (typeof raw.contentType === "string" && raw.contentType.trim() !== "") {
|
|
4451
|
+
parsed.contentType = raw.contentType.trim();
|
|
4452
|
+
}
|
|
4453
|
+
if (raw.treeView === true) {
|
|
4454
|
+
parsed.treeView = true;
|
|
4455
|
+
}
|
|
4456
|
+
return parsed;
|
|
4457
|
+
}
|
|
4458
|
+
function baseNodeFields() {
|
|
4459
|
+
return [
|
|
4460
|
+
"toolKey",
|
|
4461
|
+
"nodeKey",
|
|
4462
|
+
"nodeKind",
|
|
4463
|
+
"runtimeLabel",
|
|
4464
|
+
"resolvedScope { parentId recordId memberId teamId contentType }",
|
|
4465
|
+
"isLeaf",
|
|
4466
|
+
"treeView",
|
|
4467
|
+
"details"
|
|
4468
|
+
].join(" ");
|
|
4469
|
+
}
|
|
4470
|
+
function buildChildSelection(depth) {
|
|
4471
|
+
if (depth <= 0) return "";
|
|
4472
|
+
const nested = buildChildSelection(depth - 1);
|
|
4473
|
+
return nested.length > 0 ? `children { ${baseNodeFields()} ${nested} }` : `children { ${baseNodeFields()} }`;
|
|
4474
|
+
}
|
|
4475
|
+
function buildNodeSelectionSet(depth) {
|
|
4476
|
+
const nested = buildChildSelection(depth);
|
|
4477
|
+
return nested.length > 0 ? `{ ${baseNodeFields()} ${nested} }` : `{ ${baseNodeFields()} }`;
|
|
4478
|
+
}
|
|
4479
|
+
function requireExplicitDepth(rawDepth) {
|
|
4480
|
+
if (rawDepth === void 0 || rawDepth === null || rawDepth === "") {
|
|
4481
|
+
throw new CliError({
|
|
4482
|
+
message: "Missing required --depth for markdown-tree subtree.",
|
|
4483
|
+
kind: "invalid_args",
|
|
4484
|
+
status: 400,
|
|
4485
|
+
exitCode: EXIT_CODES.invalidArgs
|
|
4486
|
+
});
|
|
4487
|
+
}
|
|
4488
|
+
return nonNegativeInt.parse(rawDepth);
|
|
4489
|
+
}
|
|
4490
|
+
function registerMarkdownTreeCommands(program) {
|
|
4491
|
+
const markdownTree = program.command("markdown-tree").description("Markdown tree traversal operations");
|
|
4492
|
+
markdownTree.command("root").option("--tree-view").action(async (opts, cmd) => {
|
|
4493
|
+
const context = await resolveCommandContext(cmd.optsWithGlobals());
|
|
4494
|
+
const organizationId = resolveOrganizationId(context.organizationId);
|
|
4495
|
+
await runGraphqlQueryCommand({
|
|
4496
|
+
command: "markdown-tree.root",
|
|
4497
|
+
operationName: "MarkdownTreeRoot",
|
|
4498
|
+
runtimeOptions: context.runtimeOptions,
|
|
4499
|
+
field: "markdown_tree_root",
|
|
4500
|
+
variables: {
|
|
4501
|
+
organization_id: organizationId,
|
|
4502
|
+
tree_view: opts.treeView === true ? true : void 0
|
|
4503
|
+
},
|
|
4504
|
+
selectionSet: buildNodeSelectionSet(1),
|
|
4505
|
+
isShow: true
|
|
4506
|
+
});
|
|
4507
|
+
});
|
|
4508
|
+
addScopeOptions(markdownTree.command("resolve")).action(async (opts, cmd) => {
|
|
4509
|
+
const context = await resolveCommandContext(cmd.optsWithGlobals());
|
|
4510
|
+
const organizationId = resolveOrganizationId(context.organizationId);
|
|
4511
|
+
const scope = parseScopeOptions(opts);
|
|
4512
|
+
await runGraphqlQueryCommand({
|
|
4513
|
+
command: "markdown-tree.resolve",
|
|
4514
|
+
operationName: "MarkdownTreeNode",
|
|
4515
|
+
runtimeOptions: context.runtimeOptions,
|
|
4516
|
+
field: "markdown_tree_node",
|
|
4517
|
+
variables: {
|
|
4518
|
+
organization_id: organizationId,
|
|
4519
|
+
tool_key: scope.toolKey,
|
|
4520
|
+
node_key: scope.nodeKey,
|
|
4521
|
+
parent_id: scope.parentId,
|
|
4522
|
+
record_id: scope.recordId,
|
|
4523
|
+
member_id: scope.memberId,
|
|
4524
|
+
team_id: scope.teamId,
|
|
4525
|
+
content_type: scope.contentType,
|
|
4526
|
+
tree_view: scope.treeView
|
|
4527
|
+
},
|
|
4528
|
+
selectionSet: buildNodeSelectionSet(1),
|
|
4529
|
+
isShow: true
|
|
4530
|
+
});
|
|
4531
|
+
});
|
|
4532
|
+
addScopeOptions(markdownTree.command("children")).action(async (opts, cmd) => {
|
|
4533
|
+
const context = await resolveCommandContext(cmd.optsWithGlobals());
|
|
4534
|
+
const organizationId = resolveOrganizationId(context.organizationId);
|
|
4535
|
+
const scope = parseScopeOptions(opts);
|
|
4536
|
+
await runGraphqlQueryCommand({
|
|
4537
|
+
command: "markdown-tree.children",
|
|
4538
|
+
operationName: "MarkdownTreeChildren",
|
|
4539
|
+
runtimeOptions: context.runtimeOptions,
|
|
4540
|
+
field: "markdown_tree_children",
|
|
4541
|
+
variables: {
|
|
4542
|
+
organization_id: organizationId,
|
|
4543
|
+
tool_key: scope.toolKey,
|
|
4544
|
+
node_key: scope.nodeKey,
|
|
4545
|
+
parent_id: scope.parentId,
|
|
4546
|
+
record_id: scope.recordId,
|
|
4547
|
+
member_id: scope.memberId,
|
|
4548
|
+
team_id: scope.teamId,
|
|
4549
|
+
content_type: scope.contentType,
|
|
4550
|
+
tree_view: scope.treeView
|
|
4551
|
+
},
|
|
4552
|
+
selectionSet: buildNodeSelectionSet(1),
|
|
4553
|
+
isShow: true
|
|
4554
|
+
});
|
|
4555
|
+
});
|
|
4556
|
+
addScopeOptions(
|
|
4557
|
+
markdownTree.command("subtree").requiredOption("--depth <depth>")
|
|
4558
|
+
).action(async (opts, cmd) => {
|
|
4559
|
+
const context = await resolveCommandContext(cmd.optsWithGlobals());
|
|
4560
|
+
const organizationId = resolveOrganizationId(context.organizationId);
|
|
4561
|
+
const scope = parseScopeOptions(opts);
|
|
4562
|
+
const depth = requireExplicitDepth(opts.depth);
|
|
4563
|
+
await runGraphqlQueryCommand({
|
|
4564
|
+
command: "markdown-tree.subtree",
|
|
4565
|
+
operationName: "MarkdownTreeSubtree",
|
|
4566
|
+
runtimeOptions: context.runtimeOptions,
|
|
4567
|
+
field: "markdown_tree_subtree",
|
|
4568
|
+
variables: {
|
|
4569
|
+
organization_id: organizationId,
|
|
4570
|
+
tool_key: scope.toolKey,
|
|
4571
|
+
node_key: scope.nodeKey,
|
|
4572
|
+
parent_id: scope.parentId,
|
|
4573
|
+
record_id: scope.recordId,
|
|
4574
|
+
member_id: scope.memberId,
|
|
4575
|
+
team_id: scope.teamId,
|
|
4576
|
+
content_type: scope.contentType,
|
|
4577
|
+
tree_view: scope.treeView,
|
|
4578
|
+
depth
|
|
4579
|
+
},
|
|
4580
|
+
selectionSet: buildNodeSelectionSet(depth + 1),
|
|
4581
|
+
isShow: true
|
|
4582
|
+
});
|
|
4583
|
+
});
|
|
4584
|
+
}
|
|
4585
|
+
|
|
4586
|
+
// src/commands/navigation.ts
|
|
4587
|
+
import { z as z15 } from "zod";
|
|
4588
|
+
|
|
4589
|
+
// src/internalOptions.ts
|
|
4590
|
+
var INTERNAL_OPTIONS_KEY = "__waveInternalOptions";
|
|
4591
|
+
function asRecord2(value) {
|
|
4592
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
4593
|
+
return null;
|
|
4594
|
+
}
|
|
4595
|
+
return value;
|
|
4596
|
+
}
|
|
4597
|
+
function setInternalCliOptions(program, options) {
|
|
4598
|
+
if (!options) return;
|
|
4599
|
+
const target = program;
|
|
4600
|
+
target[INTERNAL_OPTIONS_KEY] = { ...options };
|
|
4601
|
+
}
|
|
4602
|
+
function getInternalCliOptions(command) {
|
|
4603
|
+
let current = command;
|
|
4604
|
+
while (current) {
|
|
4605
|
+
const record = asRecord2(current[INTERNAL_OPTIONS_KEY]);
|
|
4606
|
+
if (record) {
|
|
4607
|
+
return {
|
|
4608
|
+
enableRetryOnEmptyPhrase: record.enableRetryOnEmptyPhrase === true
|
|
4609
|
+
};
|
|
4610
|
+
}
|
|
4611
|
+
current = current.parent ?? null;
|
|
4612
|
+
}
|
|
4613
|
+
return {};
|
|
4614
|
+
}
|
|
4615
|
+
|
|
4616
|
+
// src/commands/navigation.ts
|
|
4617
|
+
var nonEmpty = z15.string().min(1);
|
|
4618
|
+
var nonNegativeInt2 = z15.coerce.number().int().min(0);
|
|
4619
|
+
var MIGRATED_BRANCHES = ["directory", "projects", "knowledge"];
|
|
4620
|
+
function normalizeText(input) {
|
|
4621
|
+
if (typeof input !== "string") return "";
|
|
4622
|
+
return input.trim().toLowerCase().replace(/\s+/g, " ");
|
|
4623
|
+
}
|
|
4624
|
+
function toDisplay(input) {
|
|
4625
|
+
if (typeof input !== "string") return "";
|
|
4626
|
+
const value = input.trim();
|
|
4627
|
+
return value.length > 0 ? value : "";
|
|
4628
|
+
}
|
|
4629
|
+
function asObject(value) {
|
|
4630
|
+
return value && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
4631
|
+
}
|
|
4632
|
+
function asArray(value) {
|
|
4633
|
+
return Array.isArray(value) ? value : [];
|
|
4634
|
+
}
|
|
4635
|
+
function parseScopeFromOptions(raw) {
|
|
4636
|
+
const scope = {
|
|
4637
|
+
toolKey: nonEmpty.parse(raw.toolKey),
|
|
4638
|
+
nodeKey: nonEmpty.parse(raw.nodeKey)
|
|
4639
|
+
};
|
|
4640
|
+
if (typeof raw.parentId === "string" && raw.parentId.trim() !== "") {
|
|
4641
|
+
scope.parentId = raw.parentId.trim();
|
|
4642
|
+
}
|
|
4643
|
+
if (typeof raw.recordId === "string" && raw.recordId.trim() !== "") {
|
|
4644
|
+
scope.recordId = raw.recordId.trim();
|
|
4645
|
+
}
|
|
4646
|
+
if (typeof raw.memberId === "string" && raw.memberId.trim() !== "") {
|
|
4647
|
+
scope.memberId = raw.memberId.trim();
|
|
4648
|
+
}
|
|
4649
|
+
if (typeof raw.teamId === "string" && raw.teamId.trim() !== "") {
|
|
4650
|
+
scope.teamId = raw.teamId.trim();
|
|
4651
|
+
}
|
|
4652
|
+
if (typeof raw.contentType === "string" && raw.contentType.trim() !== "") {
|
|
4653
|
+
scope.contentType = raw.contentType.trim();
|
|
4654
|
+
}
|
|
4655
|
+
if (raw.treeView === true) {
|
|
4656
|
+
scope.treeView = true;
|
|
4657
|
+
}
|
|
4658
|
+
return scope;
|
|
4659
|
+
}
|
|
4660
|
+
function parseOptionalScopeFromOptions(raw) {
|
|
4661
|
+
if (typeof raw.toolKey !== "string" || raw.toolKey.trim() === "") {
|
|
4662
|
+
return null;
|
|
4663
|
+
}
|
|
4664
|
+
if (typeof raw.nodeKey !== "string" || raw.nodeKey.trim() === "") {
|
|
4665
|
+
return null;
|
|
4666
|
+
}
|
|
4667
|
+
return parseScopeFromOptions(raw);
|
|
4668
|
+
}
|
|
4669
|
+
function scopeFromCandidate(candidate, treeView) {
|
|
4670
|
+
const scopeObj = asObject(candidate.scope);
|
|
4671
|
+
const resolvedScopeObj = asObject(candidate.resolvedScope);
|
|
4672
|
+
const normalizedScope = Object.keys(scopeObj).length > 0 ? scopeObj : resolvedScopeObj;
|
|
4673
|
+
const toolKey = toDisplay(candidate.toolKey);
|
|
4674
|
+
const nodeKey = toDisplay(candidate.nodeKey);
|
|
4675
|
+
return {
|
|
4676
|
+
toolKey,
|
|
4677
|
+
nodeKey,
|
|
4678
|
+
parentId: toDisplay(normalizedScope.parentId) || void 0,
|
|
4679
|
+
recordId: toDisplay(normalizedScope.recordId) || void 0,
|
|
4680
|
+
memberId: toDisplay(normalizedScope.memberId) || void 0,
|
|
4681
|
+
teamId: toDisplay(normalizedScope.teamId) || void 0,
|
|
4682
|
+
contentType: toDisplay(normalizedScope.contentType) || void 0,
|
|
4683
|
+
treeView
|
|
4684
|
+
};
|
|
4685
|
+
}
|
|
4686
|
+
function notFoundEnvelope(params) {
|
|
4687
|
+
return {
|
|
4688
|
+
ok: false,
|
|
4689
|
+
command: params.command,
|
|
4690
|
+
status: 404,
|
|
4691
|
+
data: null,
|
|
4692
|
+
error: {
|
|
4693
|
+
code: "not_found",
|
|
4694
|
+
message: params.message,
|
|
4695
|
+
details: {}
|
|
4696
|
+
},
|
|
4697
|
+
meta: {
|
|
4698
|
+
requestId: params.requestId ?? "local_error"
|
|
4699
|
+
}
|
|
4700
|
+
};
|
|
4701
|
+
}
|
|
4702
|
+
function ambiguityEnvelope(params) {
|
|
4703
|
+
return {
|
|
4704
|
+
ok: false,
|
|
4705
|
+
command: params.command,
|
|
4706
|
+
status: 409,
|
|
4707
|
+
data: null,
|
|
4708
|
+
error: {
|
|
4709
|
+
code: "ambiguous_match",
|
|
4710
|
+
message: params.message,
|
|
4711
|
+
details: {
|
|
4712
|
+
candidates: params.candidates
|
|
4713
|
+
}
|
|
4714
|
+
},
|
|
4715
|
+
meta: {
|
|
4716
|
+
requestId: params.requestId ?? "local_error"
|
|
4717
|
+
}
|
|
4718
|
+
};
|
|
4719
|
+
}
|
|
4720
|
+
function unsupportedBranchEnvelope(params) {
|
|
4721
|
+
const tool = params.tool ?? "unknown";
|
|
4722
|
+
return {
|
|
4723
|
+
ok: false,
|
|
4724
|
+
command: params.command,
|
|
4725
|
+
status: 400,
|
|
4726
|
+
data: null,
|
|
4727
|
+
error: {
|
|
4728
|
+
code: "unsupported_branch",
|
|
4729
|
+
message: `This branch isn't migrated to markdown-tree yet: ${tool}. Try directory/projects/knowledge.`,
|
|
4730
|
+
details: {
|
|
4731
|
+
tool,
|
|
4732
|
+
migratedBranches: [...MIGRATED_BRANCHES],
|
|
4733
|
+
originalError: params.originalError ?? null
|
|
4734
|
+
}
|
|
4735
|
+
},
|
|
4736
|
+
meta: {
|
|
4737
|
+
requestId: params.requestId ?? "local_error"
|
|
4738
|
+
}
|
|
4739
|
+
};
|
|
4740
|
+
}
|
|
4741
|
+
function parseToolFromGraphqlError(errorBody) {
|
|
4742
|
+
const errorObj = asObject(errorBody);
|
|
4743
|
+
const details = asObject(errorObj.details);
|
|
4744
|
+
const errors = asArray(details.errors);
|
|
4745
|
+
for (const item of errors) {
|
|
4746
|
+
const message = toDisplay(item.message);
|
|
4747
|
+
if (message === "") continue;
|
|
4748
|
+
const match = message.match(/tool_key=([a-zA-Z0-9_]+)/);
|
|
4749
|
+
if (match?.[1]) {
|
|
4750
|
+
return match[1];
|
|
4751
|
+
}
|
|
4752
|
+
}
|
|
4753
|
+
return null;
|
|
4754
|
+
}
|
|
4755
|
+
function toolHintFromPathLike(value) {
|
|
4756
|
+
const text = toDisplay(value);
|
|
4757
|
+
if (text === "") return null;
|
|
4758
|
+
const [first] = text.split("/");
|
|
4759
|
+
return first ? first.trim() : null;
|
|
4760
|
+
}
|
|
4761
|
+
function unsupportedToolFromHints(params) {
|
|
4762
|
+
const fromError = parseToolFromGraphqlError(params.envelopeError);
|
|
4763
|
+
if (fromError) return fromError;
|
|
4764
|
+
return toDisplay(params.explicitTool) || toolHintFromPathLike(params.underPath) || toolHintFromPathLike(params.queryLike) || "unknown";
|
|
4765
|
+
}
|
|
4766
|
+
async function requestTraversal(params) {
|
|
4767
|
+
const config = getConfig(params.runtimeOptions);
|
|
4768
|
+
const result = await graphqlRequest({
|
|
4769
|
+
config,
|
|
4770
|
+
command: params.command,
|
|
4771
|
+
operationName: params.operationName,
|
|
4772
|
+
operationType: "query",
|
|
4773
|
+
field: params.field,
|
|
4774
|
+
variables: params.variables,
|
|
4775
|
+
selectionSet: buildNodeSelectionSet(params.depth),
|
|
4776
|
+
isShow: true
|
|
4777
|
+
});
|
|
4778
|
+
if (!result.envelope.ok) {
|
|
4779
|
+
if (result.envelope.error?.code === "unsupported_branch") {
|
|
4780
|
+
printEnvelopeAndExit({
|
|
4781
|
+
envelope: unsupportedBranchEnvelope({
|
|
4782
|
+
command: params.command,
|
|
4783
|
+
requestId: result.envelope.meta.requestId,
|
|
4784
|
+
tool: unsupportedToolFromHints({
|
|
4785
|
+
explicitTool: params.variables.tool_key,
|
|
4786
|
+
envelopeError: result.envelope.error
|
|
4787
|
+
}),
|
|
4788
|
+
originalError: asObject(result.envelope.error)
|
|
4789
|
+
}),
|
|
4790
|
+
exitCode: result.exitCode
|
|
4791
|
+
});
|
|
4792
|
+
}
|
|
4793
|
+
printEnvelopeAndExit({
|
|
4794
|
+
envelope: result.envelope,
|
|
4795
|
+
exitCode: result.exitCode
|
|
4796
|
+
});
|
|
4797
|
+
}
|
|
4798
|
+
const data = asObject(result.envelope.data);
|
|
4799
|
+
return asObject(data[params.field]);
|
|
4800
|
+
}
|
|
4801
|
+
function findSelectionSet() {
|
|
4802
|
+
return `{
|
|
4803
|
+
query
|
|
4804
|
+
underPath
|
|
4805
|
+
candidates {
|
|
4806
|
+
label
|
|
4807
|
+
canonicalPath
|
|
4808
|
+
toolKey
|
|
4809
|
+
nodeKey
|
|
4810
|
+
nodeKind
|
|
4811
|
+
isLeaf
|
|
4812
|
+
scope { parentId recordId memberId teamId contentType }
|
|
4813
|
+
resolvedScope { parentId recordId memberId teamId contentType }
|
|
4814
|
+
matchType
|
|
4815
|
+
rank
|
|
4816
|
+
aliasMatched
|
|
4817
|
+
breadcrumb
|
|
4818
|
+
}
|
|
4819
|
+
}`;
|
|
4820
|
+
}
|
|
4821
|
+
async function requestFind(params) {
|
|
4822
|
+
const config = getConfig(params.runtimeOptions);
|
|
4823
|
+
const result = await graphqlRequest({
|
|
4824
|
+
config,
|
|
4825
|
+
command: params.command,
|
|
4826
|
+
operationName: "MarkdownTreeFind",
|
|
4827
|
+
operationType: "query",
|
|
4828
|
+
field: "markdown_tree_find",
|
|
4829
|
+
variables: {
|
|
4830
|
+
organization_id: params.organizationId,
|
|
4831
|
+
query: params.query,
|
|
4832
|
+
under_path: params.underPath,
|
|
4833
|
+
tool_key: params.toolKey,
|
|
4834
|
+
node_key: params.nodeKey,
|
|
4835
|
+
limit: params.limit
|
|
4836
|
+
},
|
|
4837
|
+
selectionSet: findSelectionSet(),
|
|
4838
|
+
isShow: true
|
|
4839
|
+
});
|
|
4840
|
+
if (!result.envelope.ok) {
|
|
4841
|
+
if (result.envelope.error?.code === "unsupported_branch") {
|
|
4842
|
+
printEnvelopeAndExit({
|
|
4843
|
+
envelope: unsupportedBranchEnvelope({
|
|
4844
|
+
command: params.command,
|
|
4845
|
+
requestId: result.envelope.meta.requestId,
|
|
4846
|
+
tool: unsupportedToolFromHints({
|
|
4847
|
+
explicitTool: params.toolKey,
|
|
4848
|
+
underPath: params.underPath,
|
|
4849
|
+
queryLike: params.query,
|
|
4850
|
+
envelopeError: result.envelope.error
|
|
4851
|
+
}),
|
|
4852
|
+
originalError: asObject(result.envelope.error)
|
|
4853
|
+
}),
|
|
4854
|
+
exitCode: result.exitCode
|
|
4855
|
+
});
|
|
4856
|
+
}
|
|
4857
|
+
printEnvelopeAndExit({
|
|
4858
|
+
envelope: result.envelope,
|
|
4859
|
+
exitCode: result.exitCode
|
|
4860
|
+
});
|
|
4861
|
+
}
|
|
4862
|
+
const data = asObject(result.envelope.data);
|
|
4863
|
+
const payload = asObject(data.markdown_tree_find);
|
|
4864
|
+
return {
|
|
4865
|
+
...payload,
|
|
4866
|
+
candidates: asArray(payload.candidates)
|
|
4867
|
+
};
|
|
4868
|
+
}
|
|
4869
|
+
function matchTypePrecedence(candidate) {
|
|
4870
|
+
const matchType = toDisplay(candidate.matchType).toLowerCase();
|
|
4871
|
+
const order = {
|
|
4872
|
+
exact_label: 0,
|
|
4873
|
+
exact_path: 1,
|
|
4874
|
+
prefix_label: 2,
|
|
4875
|
+
path_prefix: 3,
|
|
4876
|
+
path_fragment: 4,
|
|
4877
|
+
alias_match: 5,
|
|
4878
|
+
fuzzy: 6
|
|
4879
|
+
};
|
|
4880
|
+
return order[matchType] ?? Number.POSITIVE_INFINITY;
|
|
4881
|
+
}
|
|
4882
|
+
function isTopCandidateDominant(candidates) {
|
|
4883
|
+
if (candidates.length <= 1) {
|
|
4884
|
+
return true;
|
|
4885
|
+
}
|
|
4886
|
+
const first = candidates[0];
|
|
4887
|
+
const second = candidates[1];
|
|
4888
|
+
if (typeof first.rank === "number" && typeof second.rank === "number") {
|
|
4889
|
+
return first.rank < second.rank;
|
|
4890
|
+
}
|
|
4891
|
+
const firstMatch = matchTypePrecedence(first);
|
|
4892
|
+
const secondMatch = matchTypePrecedence(second);
|
|
4893
|
+
if (Number.isFinite(firstMatch) || Number.isFinite(secondMatch)) {
|
|
4894
|
+
return firstMatch < secondMatch;
|
|
4895
|
+
}
|
|
4896
|
+
return false;
|
|
4897
|
+
}
|
|
4898
|
+
function findExactPathMatches(candidates, path) {
|
|
4899
|
+
const target = normalizeText(path);
|
|
4900
|
+
if (target === "") return [];
|
|
4901
|
+
return candidates.filter((candidate) => {
|
|
4902
|
+
const canonicalPath = toDisplay(candidate.canonicalPath);
|
|
4903
|
+
return normalizeText(canonicalPath) === target;
|
|
4904
|
+
});
|
|
4905
|
+
}
|
|
4906
|
+
async function resolvePathScope(params) {
|
|
4907
|
+
const findPayload = await requestFind({
|
|
4908
|
+
command: params.command,
|
|
4909
|
+
runtimeOptions: params.runtimeOptions,
|
|
4910
|
+
organizationId: params.organizationId,
|
|
4911
|
+
query: params.path,
|
|
4912
|
+
underPath: params.underPath,
|
|
4913
|
+
limit: 25
|
|
4914
|
+
});
|
|
4915
|
+
const exactMatches = findExactPathMatches(findPayload.candidates, params.path);
|
|
4916
|
+
if (exactMatches.length === 1) {
|
|
4917
|
+
return {
|
|
4918
|
+
scope: scopeFromCandidate(exactMatches[0], params.treeView),
|
|
4919
|
+
match: exactMatches[0],
|
|
4920
|
+
ambiguous: []
|
|
4921
|
+
};
|
|
4922
|
+
}
|
|
4923
|
+
if (exactMatches.length > 1) {
|
|
4924
|
+
return {
|
|
4925
|
+
ambiguous: exactMatches.slice(0, 10)
|
|
4926
|
+
};
|
|
4927
|
+
}
|
|
4928
|
+
return {
|
|
4929
|
+
ambiguous: []
|
|
4930
|
+
};
|
|
4931
|
+
}
|
|
4932
|
+
function isMultiWordQuery(query) {
|
|
4933
|
+
const parts = query.trim().split(/\s+/).filter((part) => part.length > 0);
|
|
4934
|
+
return parts.length > 1;
|
|
4935
|
+
}
|
|
4936
|
+
function reduceMultiWordQuery(query) {
|
|
4937
|
+
const tokens = query.trim().split(/\s+/).map((token) => token.replace(/^[^a-zA-Z0-9]+|[^a-zA-Z0-9]+$/g, "")).filter((token) => token.length > 0);
|
|
4938
|
+
if (tokens.length <= 1) return null;
|
|
4939
|
+
const meaningful = tokens.filter((token) => token.length >= 3);
|
|
4940
|
+
const selected = meaningful.length > 0 ? meaningful[meaningful.length - 1] : tokens[tokens.length - 1];
|
|
4941
|
+
return selected ?? null;
|
|
4942
|
+
}
|
|
4943
|
+
function registerNavigationCommands(program) {
|
|
4944
|
+
program.command("find <query>").description("Find nodes via backend-native markdown tree discovery").option("--under <under>").option("--path <path>").option("--tool-key <toolKey>").option("--node-key <nodeKey>").option("--limit <limit>").action(async (query, opts, cmd) => {
|
|
4945
|
+
const globals = cmd.optsWithGlobals();
|
|
4946
|
+
const context = await resolveCommandContext(globals);
|
|
4947
|
+
const organizationId = resolveOrganizationId(context.organizationId);
|
|
4948
|
+
const internalOptions = getInternalCliOptions(cmd);
|
|
4949
|
+
const limit = typeof opts.limit === "string" && opts.limit.trim() !== "" ? Math.max(1, Number.parseInt(opts.limit, 10) || 20) : 20;
|
|
4950
|
+
const underPath = typeof opts.under === "string" && opts.under.trim() !== "" ? opts.under.trim() : typeof opts.path === "string" && opts.path.trim() !== "" ? opts.path.trim() : void 0;
|
|
4951
|
+
const payload = await requestFind({
|
|
4952
|
+
command: "find",
|
|
4953
|
+
runtimeOptions: context.runtimeOptions,
|
|
4954
|
+
organizationId,
|
|
4955
|
+
query,
|
|
4956
|
+
underPath,
|
|
4957
|
+
toolKey: typeof opts.toolKey === "string" ? opts.toolKey : void 0,
|
|
4958
|
+
nodeKey: typeof opts.nodeKey === "string" ? opts.nodeKey : void 0,
|
|
4959
|
+
limit
|
|
4960
|
+
});
|
|
4961
|
+
let finalPayload = payload;
|
|
4962
|
+
let assistantRecovery;
|
|
4963
|
+
if (internalOptions.enableRetryOnEmptyPhrase === true && payload.candidates.length === 0 && isMultiWordQuery(query)) {
|
|
4964
|
+
const retryQuery = reduceMultiWordQuery(query);
|
|
4965
|
+
if (retryQuery && normalizeText(retryQuery) !== normalizeText(query)) {
|
|
4966
|
+
finalPayload = await requestFind({
|
|
4967
|
+
command: "find",
|
|
4968
|
+
runtimeOptions: context.runtimeOptions,
|
|
4969
|
+
organizationId,
|
|
4970
|
+
query: retryQuery,
|
|
4971
|
+
underPath,
|
|
4972
|
+
toolKey: typeof opts.toolKey === "string" ? opts.toolKey : void 0,
|
|
4973
|
+
nodeKey: typeof opts.nodeKey === "string" ? opts.nodeKey : void 0,
|
|
4974
|
+
limit
|
|
4975
|
+
});
|
|
4976
|
+
assistantRecovery = {
|
|
4977
|
+
triggered: true,
|
|
4978
|
+
originalQuery: query,
|
|
4979
|
+
retryQuery,
|
|
4980
|
+
reason: "empty_multi_word_query"
|
|
4981
|
+
};
|
|
4982
|
+
}
|
|
4983
|
+
}
|
|
4984
|
+
printEnvelopeAndExit({
|
|
4985
|
+
envelope: {
|
|
4986
|
+
ok: true,
|
|
4987
|
+
command: "find",
|
|
4988
|
+
status: 200,
|
|
4989
|
+
data: assistantRecovery ? {
|
|
4990
|
+
...finalPayload,
|
|
4991
|
+
assistantRecovery
|
|
4992
|
+
} : finalPayload,
|
|
4993
|
+
error: null,
|
|
4994
|
+
meta: { requestId: context.runtimeOptions.requestId ?? "local" }
|
|
4995
|
+
}
|
|
4996
|
+
});
|
|
4997
|
+
});
|
|
4998
|
+
program.command("open <name>").description("Resolve one node by backend discovery").option("--under <under>").option("--path <path>").option("--tool-key <toolKey>").option("--node-key <nodeKey>").option("--limit <limit>").option("--tree-view").action(async (name, opts, cmd) => {
|
|
4999
|
+
const context = await resolveCommandContext(cmd.optsWithGlobals());
|
|
5000
|
+
const organizationId = resolveOrganizationId(context.organizationId);
|
|
5001
|
+
const limit = typeof opts.limit === "string" && opts.limit.trim() !== "" ? Math.max(1, Number.parseInt(opts.limit, 10) || 10) : 10;
|
|
5002
|
+
const underPath = typeof opts.under === "string" && opts.under.trim() !== "" ? opts.under.trim() : typeof opts.path === "string" && opts.path.trim() !== "" ? opts.path.trim() : void 0;
|
|
5003
|
+
const payload = await requestFind({
|
|
5004
|
+
command: "open",
|
|
5005
|
+
runtimeOptions: context.runtimeOptions,
|
|
5006
|
+
organizationId,
|
|
5007
|
+
query: name,
|
|
5008
|
+
underPath,
|
|
5009
|
+
toolKey: typeof opts.toolKey === "string" ? opts.toolKey : void 0,
|
|
5010
|
+
nodeKey: typeof opts.nodeKey === "string" ? opts.nodeKey : void 0,
|
|
5011
|
+
limit
|
|
5012
|
+
});
|
|
5013
|
+
const candidates = payload.candidates;
|
|
5014
|
+
if (candidates.length === 0) {
|
|
5015
|
+
printEnvelopeAndExit({
|
|
5016
|
+
envelope: notFoundEnvelope({
|
|
5017
|
+
command: "open",
|
|
5018
|
+
message: `No node matched "${name}".`
|
|
5019
|
+
}),
|
|
5020
|
+
exitCode: EXIT_CODES.notFound
|
|
5021
|
+
});
|
|
5022
|
+
}
|
|
5023
|
+
if (candidates.length > 1 && !isTopCandidateDominant(candidates)) {
|
|
5024
|
+
printEnvelopeAndExit({
|
|
5025
|
+
envelope: ambiguityEnvelope({
|
|
5026
|
+
command: "open",
|
|
5027
|
+
message: `Multiple nodes matched "${name}".`,
|
|
5028
|
+
candidates: candidates.slice(0, 10)
|
|
5029
|
+
}),
|
|
5030
|
+
exitCode: EXIT_CODES.generic
|
|
5031
|
+
});
|
|
5032
|
+
}
|
|
5033
|
+
const selected = candidates[0];
|
|
5034
|
+
const scope = scopeFromCandidate(selected, opts.treeView === true);
|
|
5035
|
+
const node = await requestTraversal({
|
|
5036
|
+
command: "open",
|
|
5037
|
+
runtimeOptions: context.runtimeOptions,
|
|
5038
|
+
operationName: "MarkdownTreeNode",
|
|
5039
|
+
field: "markdown_tree_node",
|
|
5040
|
+
variables: {
|
|
5041
|
+
organization_id: organizationId,
|
|
5042
|
+
tool_key: scope.toolKey,
|
|
5043
|
+
node_key: scope.nodeKey,
|
|
5044
|
+
parent_id: scope.parentId,
|
|
5045
|
+
record_id: scope.recordId,
|
|
5046
|
+
member_id: scope.memberId,
|
|
5047
|
+
team_id: scope.teamId,
|
|
5048
|
+
content_type: scope.contentType,
|
|
5049
|
+
tree_view: scope.treeView
|
|
5050
|
+
},
|
|
5051
|
+
depth: 1
|
|
5052
|
+
});
|
|
5053
|
+
printEnvelopeAndExit({
|
|
5054
|
+
envelope: {
|
|
5055
|
+
ok: true,
|
|
5056
|
+
command: "open",
|
|
5057
|
+
status: 200,
|
|
5058
|
+
data: {
|
|
5059
|
+
match: selected,
|
|
5060
|
+
node
|
|
5061
|
+
},
|
|
5062
|
+
error: null,
|
|
5063
|
+
meta: { requestId: context.runtimeOptions.requestId ?? "local" }
|
|
5064
|
+
}
|
|
5065
|
+
});
|
|
5066
|
+
});
|
|
5067
|
+
program.command("ls [query]").description("List direct children for a target").option("--path <path>").option("--under <under>").option("--tree-view").option("--tool-key <toolKey>").option("--node-key <nodeKey>").option("--parent-id <parentId>").option("--record-id <recordId>").option("--member-id <memberId>").option("--team-id <teamId>").option("--content-type <contentType>").action(async (query, opts, cmd) => {
|
|
5068
|
+
const context = await resolveCommandContext(cmd.optsWithGlobals());
|
|
5069
|
+
const organizationId = resolveOrganizationId(context.organizationId);
|
|
5070
|
+
let scope = null;
|
|
5071
|
+
let pathMatch = null;
|
|
5072
|
+
if (typeof opts.path === "string" && opts.path.trim() !== "") {
|
|
5073
|
+
const resolved = await resolvePathScope({
|
|
5074
|
+
command: "ls",
|
|
5075
|
+
runtimeOptions: context.runtimeOptions,
|
|
5076
|
+
organizationId,
|
|
5077
|
+
path: opts.path,
|
|
5078
|
+
underPath: typeof opts.under === "string" ? opts.under : void 0,
|
|
5079
|
+
treeView: opts.treeView === true
|
|
5080
|
+
});
|
|
5081
|
+
if (!resolved.scope) {
|
|
5082
|
+
if (resolved.ambiguous.length > 0) {
|
|
5083
|
+
printEnvelopeAndExit({
|
|
5084
|
+
envelope: ambiguityEnvelope({
|
|
5085
|
+
command: "ls",
|
|
5086
|
+
message: `Path "${opts.path}" is ambiguous.`,
|
|
5087
|
+
candidates: resolved.ambiguous
|
|
5088
|
+
}),
|
|
5089
|
+
exitCode: EXIT_CODES.generic
|
|
5090
|
+
});
|
|
5091
|
+
}
|
|
5092
|
+
printEnvelopeAndExit({
|
|
5093
|
+
envelope: notFoundEnvelope({
|
|
5094
|
+
command: "ls",
|
|
5095
|
+
message: `Path "${opts.path}" was not found.`
|
|
5096
|
+
}),
|
|
5097
|
+
exitCode: EXIT_CODES.notFound
|
|
5098
|
+
});
|
|
5099
|
+
}
|
|
5100
|
+
scope = resolved.scope;
|
|
5101
|
+
pathMatch = resolved.match ?? null;
|
|
5102
|
+
} else {
|
|
5103
|
+
scope = parseOptionalScopeFromOptions(opts);
|
|
5104
|
+
}
|
|
5105
|
+
if (!scope) {
|
|
5106
|
+
printEnvelopeAndExit({
|
|
5107
|
+
envelope: {
|
|
5108
|
+
ok: false,
|
|
5109
|
+
command: "ls",
|
|
5110
|
+
status: 400,
|
|
5111
|
+
data: null,
|
|
5112
|
+
error: {
|
|
5113
|
+
code: "invalid_args",
|
|
5114
|
+
message: "Provide either --path or full scope args (--tool-key and --node-key).",
|
|
5115
|
+
details: {}
|
|
5116
|
+
},
|
|
5117
|
+
meta: { requestId: context.runtimeOptions.requestId ?? "local_error" }
|
|
5118
|
+
},
|
|
5119
|
+
exitCode: EXIT_CODES.invalidArgs
|
|
5120
|
+
});
|
|
5121
|
+
}
|
|
5122
|
+
const node = await requestTraversal({
|
|
5123
|
+
command: "ls",
|
|
5124
|
+
runtimeOptions: context.runtimeOptions,
|
|
5125
|
+
operationName: "MarkdownTreeChildren",
|
|
5126
|
+
field: "markdown_tree_children",
|
|
5127
|
+
variables: {
|
|
5128
|
+
organization_id: organizationId,
|
|
5129
|
+
tool_key: scope.toolKey,
|
|
5130
|
+
node_key: scope.nodeKey,
|
|
5131
|
+
parent_id: scope.parentId,
|
|
5132
|
+
record_id: scope.recordId,
|
|
5133
|
+
member_id: scope.memberId,
|
|
5134
|
+
team_id: scope.teamId,
|
|
5135
|
+
content_type: scope.contentType,
|
|
5136
|
+
tree_view: scope.treeView
|
|
5137
|
+
},
|
|
5138
|
+
depth: 1
|
|
5139
|
+
});
|
|
5140
|
+
const children = asArray(node.children);
|
|
5141
|
+
const filtered = typeof query === "string" && query.trim() !== "" ? children.filter(
|
|
5142
|
+
(child) => normalizeText(child.runtimeLabel).includes(normalizeText(query))
|
|
5143
|
+
) : children;
|
|
5144
|
+
printEnvelopeAndExit({
|
|
5145
|
+
envelope: {
|
|
5146
|
+
ok: true,
|
|
5147
|
+
command: "ls",
|
|
5148
|
+
status: 200,
|
|
5149
|
+
data: {
|
|
5150
|
+
target: pathMatch,
|
|
5151
|
+
children: filtered
|
|
5152
|
+
},
|
|
5153
|
+
error: null,
|
|
5154
|
+
meta: { requestId: context.runtimeOptions.requestId ?? "local" }
|
|
5155
|
+
}
|
|
5156
|
+
});
|
|
5157
|
+
});
|
|
5158
|
+
program.command("cat").description("Read one node").option("--path <path>").option("--under <under>").option("--tree-view").option("--tool-key <toolKey>").option("--node-key <nodeKey>").option("--parent-id <parentId>").option("--record-id <recordId>").option("--member-id <memberId>").option("--team-id <teamId>").option("--content-type <contentType>").action(async (opts, cmd) => {
|
|
5159
|
+
const context = await resolveCommandContext(cmd.optsWithGlobals());
|
|
5160
|
+
const organizationId = resolveOrganizationId(context.organizationId);
|
|
5161
|
+
let scope = null;
|
|
5162
|
+
let pathMatch = null;
|
|
5163
|
+
if (typeof opts.path === "string" && opts.path.trim() !== "") {
|
|
5164
|
+
const resolved = await resolvePathScope({
|
|
5165
|
+
command: "cat",
|
|
5166
|
+
runtimeOptions: context.runtimeOptions,
|
|
5167
|
+
organizationId,
|
|
5168
|
+
path: opts.path,
|
|
5169
|
+
underPath: typeof opts.under === "string" ? opts.under : void 0,
|
|
5170
|
+
treeView: opts.treeView === true
|
|
5171
|
+
});
|
|
5172
|
+
if (!resolved.scope) {
|
|
5173
|
+
if (resolved.ambiguous.length > 0) {
|
|
5174
|
+
printEnvelopeAndExit({
|
|
5175
|
+
envelope: ambiguityEnvelope({
|
|
5176
|
+
command: "cat",
|
|
5177
|
+
message: `Path "${opts.path}" is ambiguous.`,
|
|
5178
|
+
candidates: resolved.ambiguous
|
|
5179
|
+
}),
|
|
5180
|
+
exitCode: EXIT_CODES.generic
|
|
5181
|
+
});
|
|
5182
|
+
}
|
|
5183
|
+
printEnvelopeAndExit({
|
|
5184
|
+
envelope: notFoundEnvelope({
|
|
5185
|
+
command: "cat",
|
|
5186
|
+
message: `Path "${opts.path}" was not found.`
|
|
5187
|
+
}),
|
|
5188
|
+
exitCode: EXIT_CODES.notFound
|
|
5189
|
+
});
|
|
5190
|
+
}
|
|
5191
|
+
scope = resolved.scope;
|
|
5192
|
+
pathMatch = resolved.match ?? null;
|
|
5193
|
+
} else {
|
|
5194
|
+
scope = parseOptionalScopeFromOptions(opts);
|
|
5195
|
+
}
|
|
5196
|
+
if (!scope) {
|
|
5197
|
+
printEnvelopeAndExit({
|
|
5198
|
+
envelope: {
|
|
5199
|
+
ok: false,
|
|
5200
|
+
command: "cat",
|
|
5201
|
+
status: 400,
|
|
5202
|
+
data: null,
|
|
5203
|
+
error: {
|
|
5204
|
+
code: "invalid_args",
|
|
5205
|
+
message: "Provide either --path or full scope args (--tool-key and --node-key).",
|
|
5206
|
+
details: {}
|
|
5207
|
+
},
|
|
5208
|
+
meta: { requestId: context.runtimeOptions.requestId ?? "local_error" }
|
|
5209
|
+
},
|
|
5210
|
+
exitCode: EXIT_CODES.invalidArgs
|
|
5211
|
+
});
|
|
5212
|
+
}
|
|
5213
|
+
const node = await requestTraversal({
|
|
5214
|
+
command: "cat",
|
|
5215
|
+
runtimeOptions: context.runtimeOptions,
|
|
5216
|
+
operationName: "MarkdownTreeNode",
|
|
5217
|
+
field: "markdown_tree_node",
|
|
5218
|
+
variables: {
|
|
5219
|
+
organization_id: organizationId,
|
|
5220
|
+
tool_key: scope.toolKey,
|
|
5221
|
+
node_key: scope.nodeKey,
|
|
5222
|
+
parent_id: scope.parentId,
|
|
5223
|
+
record_id: scope.recordId,
|
|
5224
|
+
member_id: scope.memberId,
|
|
5225
|
+
team_id: scope.teamId,
|
|
5226
|
+
content_type: scope.contentType,
|
|
5227
|
+
tree_view: scope.treeView
|
|
5228
|
+
},
|
|
5229
|
+
depth: 1
|
|
5230
|
+
});
|
|
5231
|
+
printEnvelopeAndExit({
|
|
5232
|
+
envelope: {
|
|
5233
|
+
ok: true,
|
|
5234
|
+
command: "cat",
|
|
5235
|
+
status: 200,
|
|
5236
|
+
data: {
|
|
5237
|
+
target: pathMatch,
|
|
5238
|
+
node
|
|
5239
|
+
},
|
|
5240
|
+
error: null,
|
|
5241
|
+
meta: { requestId: context.runtimeOptions.requestId ?? "local" }
|
|
5242
|
+
}
|
|
5243
|
+
});
|
|
5244
|
+
});
|
|
5245
|
+
program.command("tree").description("Read bounded subtree").requiredOption("--depth <depth>").option("--path <path>").option("--under <under>").option("--tree-view").option("--tool-key <toolKey>").option("--node-key <nodeKey>").option("--parent-id <parentId>").option("--record-id <recordId>").option("--member-id <memberId>").option("--team-id <teamId>").option("--content-type <contentType>").action(async (opts, cmd) => {
|
|
5246
|
+
const context = await resolveCommandContext(cmd.optsWithGlobals());
|
|
5247
|
+
const organizationId = resolveOrganizationId(context.organizationId);
|
|
5248
|
+
const depth = nonNegativeInt2.parse(opts.depth);
|
|
5249
|
+
let scope = null;
|
|
5250
|
+
let pathMatch = null;
|
|
5251
|
+
if (typeof opts.path === "string" && opts.path.trim() !== "") {
|
|
5252
|
+
const resolved = await resolvePathScope({
|
|
5253
|
+
command: "tree",
|
|
5254
|
+
runtimeOptions: context.runtimeOptions,
|
|
5255
|
+
organizationId,
|
|
5256
|
+
path: opts.path,
|
|
5257
|
+
underPath: typeof opts.under === "string" ? opts.under : void 0,
|
|
5258
|
+
treeView: opts.treeView === true
|
|
5259
|
+
});
|
|
5260
|
+
if (!resolved.scope) {
|
|
5261
|
+
if (resolved.ambiguous.length > 0) {
|
|
5262
|
+
printEnvelopeAndExit({
|
|
5263
|
+
envelope: ambiguityEnvelope({
|
|
5264
|
+
command: "tree",
|
|
5265
|
+
message: `Path "${opts.path}" is ambiguous.`,
|
|
5266
|
+
candidates: resolved.ambiguous
|
|
5267
|
+
}),
|
|
5268
|
+
exitCode: EXIT_CODES.generic
|
|
5269
|
+
});
|
|
5270
|
+
}
|
|
5271
|
+
printEnvelopeAndExit({
|
|
5272
|
+
envelope: notFoundEnvelope({
|
|
5273
|
+
command: "tree",
|
|
5274
|
+
message: `Path "${opts.path}" was not found.`
|
|
5275
|
+
}),
|
|
5276
|
+
exitCode: EXIT_CODES.notFound
|
|
5277
|
+
});
|
|
5278
|
+
}
|
|
5279
|
+
scope = resolved.scope;
|
|
5280
|
+
pathMatch = resolved.match ?? null;
|
|
5281
|
+
} else {
|
|
5282
|
+
scope = parseOptionalScopeFromOptions(opts);
|
|
5283
|
+
}
|
|
5284
|
+
if (!scope) {
|
|
5285
|
+
printEnvelopeAndExit({
|
|
5286
|
+
envelope: {
|
|
5287
|
+
ok: false,
|
|
5288
|
+
command: "tree",
|
|
5289
|
+
status: 400,
|
|
5290
|
+
data: null,
|
|
5291
|
+
error: {
|
|
5292
|
+
code: "invalid_args",
|
|
5293
|
+
message: "Provide either --path or full scope args (--tool-key and --node-key).",
|
|
5294
|
+
details: {}
|
|
5295
|
+
},
|
|
5296
|
+
meta: { requestId: context.runtimeOptions.requestId ?? "local_error" }
|
|
5297
|
+
},
|
|
5298
|
+
exitCode: EXIT_CODES.invalidArgs
|
|
5299
|
+
});
|
|
5300
|
+
}
|
|
5301
|
+
const node = await requestTraversal({
|
|
5302
|
+
command: "tree",
|
|
5303
|
+
runtimeOptions: context.runtimeOptions,
|
|
5304
|
+
operationName: "MarkdownTreeSubtree",
|
|
5305
|
+
field: "markdown_tree_subtree",
|
|
5306
|
+
variables: {
|
|
5307
|
+
organization_id: organizationId,
|
|
5308
|
+
tool_key: scope.toolKey,
|
|
5309
|
+
node_key: scope.nodeKey,
|
|
5310
|
+
parent_id: scope.parentId,
|
|
5311
|
+
record_id: scope.recordId,
|
|
5312
|
+
member_id: scope.memberId,
|
|
5313
|
+
team_id: scope.teamId,
|
|
5314
|
+
content_type: scope.contentType,
|
|
5315
|
+
tree_view: scope.treeView,
|
|
5316
|
+
depth
|
|
5317
|
+
},
|
|
5318
|
+
depth: depth + 1
|
|
5319
|
+
});
|
|
5320
|
+
printEnvelopeAndExit({
|
|
5321
|
+
envelope: {
|
|
5322
|
+
ok: true,
|
|
5323
|
+
command: "tree",
|
|
5324
|
+
status: 200,
|
|
5325
|
+
data: {
|
|
5326
|
+
target: pathMatch,
|
|
5327
|
+
depth,
|
|
5328
|
+
node
|
|
5329
|
+
},
|
|
5330
|
+
error: null,
|
|
5331
|
+
meta: { requestId: context.runtimeOptions.requestId ?? "local" }
|
|
5332
|
+
}
|
|
5333
|
+
});
|
|
5334
|
+
});
|
|
5335
|
+
}
|
|
5336
|
+
|
|
5337
|
+
// src/commands/mutationCapability.ts
|
|
5338
|
+
function unsupportedMutationEnvelope(params) {
|
|
5339
|
+
return {
|
|
5340
|
+
ok: false,
|
|
5341
|
+
command: params.command,
|
|
5342
|
+
status: 400,
|
|
5343
|
+
data: null,
|
|
5344
|
+
error: {
|
|
5345
|
+
code: "mutation_unsupported",
|
|
5346
|
+
message: "No mutation command is supported for this node type.",
|
|
5347
|
+
details: {
|
|
5348
|
+
node: params.node
|
|
5349
|
+
}
|
|
5350
|
+
},
|
|
5351
|
+
meta: {
|
|
5352
|
+
requestId: "local_error"
|
|
5353
|
+
}
|
|
5354
|
+
};
|
|
5355
|
+
}
|
|
5356
|
+
function emitUnsupportedMutation(params) {
|
|
5357
|
+
const canonicalPath = typeof params.canonicalPath === "string" && params.canonicalPath.trim().length > 0 ? params.canonicalPath.trim() : null;
|
|
5358
|
+
printEnvelopeAndExit({
|
|
5359
|
+
envelope: unsupportedMutationEnvelope({
|
|
5360
|
+
command: params.command,
|
|
5361
|
+
node: {
|
|
5362
|
+
toolKey: params.toolKey,
|
|
5363
|
+
nodeKey: params.nodeKey,
|
|
5364
|
+
canonicalPath
|
|
5365
|
+
}
|
|
5366
|
+
}),
|
|
5367
|
+
exitCode: EXIT_CODES.invalidArgs
|
|
5368
|
+
});
|
|
5369
|
+
}
|
|
5370
|
+
function registerMutationCapabilityCommands(program) {
|
|
5371
|
+
const projectNotes = program.command("project-notes").description("Project notes node (read-only in CLI mutation surface)");
|
|
5372
|
+
projectNotes.command("create").option("--path <path>", "Canonical path for the selected node").action((opts) => {
|
|
5373
|
+
emitUnsupportedMutation({
|
|
5374
|
+
command: "project-notes.create",
|
|
5375
|
+
toolKey: "projects",
|
|
5376
|
+
nodeKey: "project_notes",
|
|
5377
|
+
canonicalPath: opts.path
|
|
5378
|
+
});
|
|
5379
|
+
});
|
|
5380
|
+
projectNotes.command("update").option("--path <path>", "Canonical path for the selected node").action((opts) => {
|
|
5381
|
+
emitUnsupportedMutation({
|
|
5382
|
+
command: "project-notes.update",
|
|
5383
|
+
toolKey: "projects",
|
|
5384
|
+
nodeKey: "project_notes",
|
|
5385
|
+
canonicalPath: opts.path
|
|
5386
|
+
});
|
|
5387
|
+
});
|
|
5388
|
+
projectNotes.command("destroy").option("--path <path>", "Canonical path for the selected node").action((opts) => {
|
|
5389
|
+
emitUnsupportedMutation({
|
|
5390
|
+
command: "project-notes.destroy",
|
|
5391
|
+
toolKey: "projects",
|
|
5392
|
+
nodeKey: "project_notes",
|
|
5393
|
+
canonicalPath: opts.path
|
|
5394
|
+
});
|
|
5395
|
+
});
|
|
5396
|
+
}
|
|
5397
|
+
|
|
3027
5398
|
// src/cli.ts
|
|
3028
|
-
function buildCli() {
|
|
5399
|
+
function buildCli(options) {
|
|
3029
5400
|
const program = new Command();
|
|
3030
5401
|
program.name("wave").description("Wave agent CLI").showHelpAfterError(false).allowExcessArguments(false).option("--token <token>", "API token (prefer WAVE_API_TOKEN env var)").option("--jwt <jwt>", "Legacy alias for --token (prefer WAVE_API_TOKEN env var)").option("--token-stdin", "Read API token from stdin").option(
|
|
3031
5402
|
"--auth-json-stdin",
|
|
@@ -3046,6 +5417,7 @@ function buildCli() {
|
|
|
3046
5417
|
"--openapi-version <openapiVersion>",
|
|
3047
5418
|
"Optional pinned OpenAPI version/hash"
|
|
3048
5419
|
).exitOverride();
|
|
5420
|
+
setInternalCliOptions(program, options?.internal);
|
|
3049
5421
|
registerTaskCommands(program);
|
|
3050
5422
|
registerProjectCommands(program);
|
|
3051
5423
|
registerRockCommands(program);
|
|
@@ -3058,6 +5430,9 @@ function buildCli() {
|
|
|
3058
5430
|
registerFoundationCommands(program);
|
|
3059
5431
|
registerChildEntityCommands(program);
|
|
3060
5432
|
registerNoteCommands(program);
|
|
5433
|
+
registerMutationCapabilityCommands(program);
|
|
5434
|
+
registerMarkdownTreeCommands(program);
|
|
5435
|
+
registerNavigationCommands(program);
|
|
3061
5436
|
return program;
|
|
3062
5437
|
}
|
|
3063
5438
|
|