@mytegroupinc/myte-core 0.0.44 → 0.0.46
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 +64 -60
- package/cli.js +814 -943
- package/package.json +14 -14
package/cli.js
CHANGED
|
@@ -208,10 +208,10 @@ function printHelp() {
|
|
|
208
208
|
" myte feedback reviews [--status open|terminal|all] [--request-id <id>] [--json]",
|
|
209
209
|
" myte feedback review --request-id <id> --action approve|reject|request_changes|cancel [--reason \"...\"] [--json]",
|
|
210
210
|
" myte feedback review --request-ids \"<id1,id2>\" --action approve|reject|request_changes|cancel [--reason \"...\"] [--json]",
|
|
211
|
-
" myte feedback move --feedback-id <id> --to-state in_progress --from-state todo --reason \"...\" [--json]",
|
|
212
|
-
" myte feedback move --feedback-ids \"<id1,id2>\" --to-state in_progress --reason \"...\" [--json]",
|
|
213
|
-
" myte feedback comment --feedback-id <id> --body \"...\" [--body-file ./comment.md] [--json]",
|
|
214
|
-
" myte feedback undo --feedback-id <id> --event-id <id> --reason \"...\" [--json]",
|
|
211
|
+
" myte feedback move --feedback-id <id> --to-state in_progress --from-state todo --reason \"...\" [--json]",
|
|
212
|
+
" myte feedback move --feedback-ids \"<id1,id2>\" --to-state in_progress --reason \"...\" [--json]",
|
|
213
|
+
" myte feedback comment --feedback-id <id> --body \"...\" [--body-file ./comment.md] [--json]",
|
|
214
|
+
" myte feedback undo --feedback-id <id> --event-id <id> --reason \"...\" [--json]",
|
|
215
215
|
" myte feedback prd-versions --feedback-id <id> [--json]",
|
|
216
216
|
" myte feedback prd-diff --feedback-id <id> --version-id <id> [--compare-to <id>] [--json]",
|
|
217
217
|
" myte feedback validate --file ./MyteCommandCenter/reviews/feedback/<id>-status.yml [--json]",
|
|
@@ -231,16 +231,10 @@ function printHelp() {
|
|
|
231
231
|
" npx myte@latest query \"What changed in logging?\" --with-diff",
|
|
232
232
|
" npx myte@latest ai \"Return a JSON checklist\" --json-response",
|
|
233
233
|
"",
|
|
234
|
-
"Auth:",
|
|
235
|
-
" - Set MYTE_API_KEY in a workspace .env (or env var)",
|
|
236
|
-
" - Set MYTEAI_API_KEY in a workspace .env (or env var) for `myte ai`",
|
|
237
|
-
"",
|
|
238
|
-
"Live write approval:",
|
|
239
|
-
" - Live project-key mutations require --confirm-write --approval-artifact <path>",
|
|
240
|
-
" - The artifact must be a local .md, .yml/.yaml, or .json file shown to and approved by the user before the command is rerun",
|
|
241
|
-
" - Batch artifacts must enumerate every feedback id, mission id, suggestion id, request id, or PRD item",
|
|
242
|
-
" - Read/sync/query/validate, --print-context, and --dry-run commands do not require write approval",
|
|
243
|
-
"",
|
|
234
|
+
"Auth:",
|
|
235
|
+
" - Set MYTE_API_KEY in a workspace .env (or env var)",
|
|
236
|
+
" - Set MYTEAI_API_KEY in a workspace .env (or env var) for `myte ai`",
|
|
237
|
+
"",
|
|
244
238
|
"bootstrap contract:",
|
|
245
239
|
" - Run from any workspace where you want local MyteCommandCenter data written",
|
|
246
240
|
" - Writes MyteCommandCenter/data/project.yml plus phases, epics, stories, and missions locally",
|
|
@@ -319,7 +313,7 @@ function printHelp() {
|
|
|
319
313
|
" - Archived feedback is intentionally excluded from normal sync; returning it to active work is web UI only",
|
|
320
314
|
" - Writes project feedback metadata and conversation turns into MyteCommandCenter/data/feedback.yml",
|
|
321
315
|
" - Stores full PRD context in MyteCommandCenter/PRD/feedback-sync/*.md and points to those files from feedback.yml",
|
|
322
|
-
" - Reads existing feedback comments and can create text-only feedback-specific comments through the project-key API",
|
|
316
|
+
" - Reads existing feedback comments and can create text-only feedback-specific comments through the project-key API",
|
|
323
317
|
"",
|
|
324
318
|
"feedback review contract:",
|
|
325
319
|
" - Draft commands write review artifacts under MyteCommandCenter/reviews/feedback/*.yml for local IDE diff review",
|
|
@@ -328,9 +322,9 @@ function printHelp() {
|
|
|
328
322
|
" - reviews/review expose owner/delegate approval, rejection, request-changes, and cancel decisions",
|
|
329
323
|
" - review with --request-ids sends one batch review request; it does not loop single-review calls",
|
|
330
324
|
" - live lifecycle moves return pending_feedback_review while an active linked review request exists",
|
|
331
|
-
" - move/undo operate safe board states directly; governed states remain backend-authorized",
|
|
332
|
-
" - move with --feedback-ids sends one batch board move request; it supports active-state moves and authorized archive",
|
|
333
|
-
" - comment creates text-only feedback-specific comments; attachments remain web UI only for this endpoint",
|
|
325
|
+
" - move/undo operate safe board states directly; governed states remain backend-authorized",
|
|
326
|
+
" - move with --feedback-ids sends one batch board move request; it supports active-state moves and authorized archive",
|
|
327
|
+
" - comment creates text-only feedback-specific comments; attachments remain web UI only for this endpoint",
|
|
334
328
|
" - project-key API/CLI cannot unarchive archived Feedback; use the web archived Feedback view",
|
|
335
329
|
" - get/history read current feedback snapshots and audited event history through the project-key API",
|
|
336
330
|
" - prd-versions/prd-diff expose retained PRD versions and backend-generated text diffs",
|
|
@@ -346,9 +340,9 @@ function printHelp() {
|
|
|
346
340
|
" - revise: resubmit the original submitter's request after request_changes",
|
|
347
341
|
" - reviews: list open/terminal/all requests or inspect one request",
|
|
348
342
|
" - review: approve, reject, request_changes, or cancel; backend restricts this to owner/delegate capability",
|
|
349
|
-
" - move: direct audited board movement for allowed states; governed transitions remain backend-authorized",
|
|
350
|
-
" - comment: create a text-only comment on one Feedback item",
|
|
351
|
-
" - undo: reverse an audited board event when conflict checks allow it",
|
|
343
|
+
" - move: direct audited board movement for allowed states; governed transitions remain backend-authorized",
|
|
344
|
+
" - comment: create a text-only comment on one Feedback item",
|
|
345
|
+
" - undo: reverse an audited board event when conflict checks allow it",
|
|
352
346
|
" - prd-versions: list retained PRD baselines/revisions for a feedback item",
|
|
353
347
|
" - prd-diff: fetch backend-generated text diff between PRD versions",
|
|
354
348
|
" - history: list board/refinement events for audit review",
|
|
@@ -369,11 +363,11 @@ function printHelp() {
|
|
|
369
363
|
" --stdin Read supported command content from stdin instead of inline text or a file path",
|
|
370
364
|
" --title <text> Override PRD title for raw markdown uploads",
|
|
371
365
|
" --description <text> Set feedback description/card summary for raw markdown uploads",
|
|
372
|
-
" --content <text> Team update content for update-team",
|
|
373
|
-
" --body <text> Feedback comment body for feedback comment",
|
|
374
|
-
" --subject <text> Subject for update-owner or update-client",
|
|
366
|
+
" --content <text> Team update content for update-team",
|
|
367
|
+
" --body <text> Feedback comment body for feedback comment",
|
|
368
|
+
" --subject <text> Subject for update-owner or update-client",
|
|
375
369
|
" --body-markdown <md> Markdown body for update-owner or update-client",
|
|
376
|
-
" --body-file <path> Read feedback comment, update-owner, or update-client markdown body from a file",
|
|
370
|
+
" --body-file <path> Read feedback comment, update-owner, or update-client markdown body from a file",
|
|
377
371
|
" --target-contact-id Add one client contact ObjectId (repeatable)",
|
|
378
372
|
" --target-contact-ids Comma-separated client contact ObjectIds",
|
|
379
373
|
" --feedback-id <id> Feedback ObjectId for feedback review commands",
|
|
@@ -401,10 +395,8 @@ function printHelp() {
|
|
|
401
395
|
" --actor-scope <id> Actor workspace key inside mission-ops.yml (defaults to machine-cwd slug)",
|
|
402
396
|
" --wait Poll batch status until terminal completion for run-qaqc",
|
|
403
397
|
" --sync After run-qaqc completes, refresh local QAQC file",
|
|
404
|
-
" --force Allow run-qaqc to bypass stale-state protection when supported",
|
|
405
|
-
" --
|
|
406
|
-
" --approval-artifact Local .md/.yml/.json approval artifact shown to and approved by the user",
|
|
407
|
-
" --no-sync Skip automatic post-mutation sync for suggestions, missions, and feedback mutations",
|
|
398
|
+
" --force Allow run-qaqc to bypass stale-state protection when supported",
|
|
399
|
+
" --no-sync Skip automatic post-mutation sync for suggestions, missions, and feedback mutations",
|
|
408
400
|
" --print-context Print JSON payload and exit (no query call)",
|
|
409
401
|
" --no-fetch Don't git fetch origin main/master before diff",
|
|
410
402
|
"",
|
|
@@ -429,10 +421,10 @@ function printHelp() {
|
|
|
429
421
|
" myte feedback status --feedback-id 507f1f77bcf86cd799439011 --status in_review --reason \"Ready for owner review\"",
|
|
430
422
|
" myte feedback submit --file ./MyteCommandCenter/reviews/feedback/507f1f77bcf86cd799439011-edit.yml --json",
|
|
431
423
|
" myte feedback reviews --status open --json",
|
|
432
|
-
" myte feedback review --request-id 507f1f77bcf86cd799439022 --action approve --reason \"Looks correct\" --json",
|
|
433
|
-
" myte feedback move --feedback-id 507f1f77bcf86cd799439011 --to-state in_progress --reason \"Started\" --json",
|
|
434
|
-
" myte feedback comment --feedback-id 507f1f77bcf86cd799439011 --body \"Implementation notes are ready for review.\" --json",
|
|
435
|
-
" myte feedback validate --file ./MyteCommandCenter/reviews/feedback/507f1f77bcf86cd799439011-status.yml --json",
|
|
424
|
+
" myte feedback review --request-id 507f1f77bcf86cd799439022 --action approve --reason \"Looks correct\" --json",
|
|
425
|
+
" myte feedback move --feedback-id 507f1f77bcf86cd799439011 --to-state in_progress --reason \"Started\" --json",
|
|
426
|
+
" myte feedback comment --feedback-id 507f1f77bcf86cd799439011 --body \"Implementation notes are ready for review.\" --json",
|
|
427
|
+
" myte feedback validate --file ./MyteCommandCenter/reviews/feedback/507f1f77bcf86cd799439011-status.yml --json",
|
|
436
428
|
" myte feedback apply --file ./MyteCommandCenter/reviews/feedback/507f1f77bcf86cd799439011-status.yml --json",
|
|
437
429
|
" myte suggestions create --file ./suggestions/create.yml",
|
|
438
430
|
" myte suggestions revise",
|
|
@@ -678,10 +670,10 @@ function normalizeApiBase(baseRaw) {
|
|
|
678
670
|
return base.endsWith("/api") ? base : `${base}/api`;
|
|
679
671
|
}
|
|
680
672
|
|
|
681
|
-
async function fetchJsonWithTimeout(fetchFn, url, options, timeoutMs) {
|
|
682
|
-
const controller = typeof AbortController !== "undefined" ? new AbortController() : undefined;
|
|
683
|
-
const timeoutId =
|
|
684
|
-
controller && timeoutMs > 0 ? setTimeout(() => controller.abort(), timeoutMs) : undefined;
|
|
673
|
+
async function fetchJsonWithTimeout(fetchFn, url, options, timeoutMs) {
|
|
674
|
+
const controller = typeof AbortController !== "undefined" ? new AbortController() : undefined;
|
|
675
|
+
const timeoutId =
|
|
676
|
+
controller && timeoutMs > 0 ? setTimeout(() => controller.abort(), timeoutMs) : undefined;
|
|
685
677
|
try {
|
|
686
678
|
const resp = await fetchFn(url, { ...options, signal: controller?.signal });
|
|
687
679
|
const text = await resp.text();
|
|
@@ -697,171 +689,13 @@ async function fetchJsonWithTimeout(fetchFn, url, options, timeoutMs) {
|
|
|
697
689
|
}
|
|
698
690
|
return { resp, body };
|
|
699
691
|
} finally {
|
|
700
|
-
if (timeoutId) clearTimeout(timeoutId);
|
|
701
|
-
}
|
|
702
|
-
}
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
if (Array.isArray(value)) {
|
|
708
|
-
return value.map((item) => canonicalizeWritePayload(item));
|
|
709
|
-
}
|
|
710
|
-
if (value && typeof value === "object") {
|
|
711
|
-
return Object.fromEntries(
|
|
712
|
-
Object.keys(value)
|
|
713
|
-
.filter((key) => !WRITE_APPROVAL_TRANSPORT_KEYS.has(String(key)))
|
|
714
|
-
.sort()
|
|
715
|
-
.map((key) => [key, canonicalizeWritePayload(value[key])])
|
|
716
|
-
);
|
|
717
|
-
}
|
|
718
|
-
return value;
|
|
719
|
-
}
|
|
720
|
-
|
|
721
|
-
function projectApiWritePayloadHash(payload) {
|
|
722
|
-
return createHash("sha256")
|
|
723
|
-
.update(stableJsonStringify(canonicalizeWritePayload(payload || {})))
|
|
724
|
-
.digest("hex");
|
|
725
|
-
}
|
|
726
|
-
|
|
727
|
-
function isConfirmWrite(args) {
|
|
728
|
-
return Boolean(args["confirm-write"] || args.confirmWrite || args.confirm_write);
|
|
729
|
-
}
|
|
730
|
-
|
|
731
|
-
function resolveWriteApprovalArtifactPath(args) {
|
|
732
|
-
const explicit = firstNonEmptyString(args["approval-artifact"], args.approvalArtifact, args.approval_artifact);
|
|
733
|
-
if (!explicit) return "";
|
|
734
|
-
const resolved = path.resolve(process.cwd(), explicit);
|
|
735
|
-
if (!fs.existsSync(resolved) || !fs.statSync(resolved).isFile()) {
|
|
736
|
-
console.error(`Approval artifact not found: ${resolved}`);
|
|
737
|
-
process.exit(1);
|
|
738
|
-
}
|
|
739
|
-
return resolved;
|
|
740
|
-
}
|
|
741
|
-
|
|
742
|
-
function inferApprovalArtifactKind(filePath, fallbackKind) {
|
|
743
|
-
const ext = path.extname(String(filePath || "")).toLowerCase();
|
|
744
|
-
if (ext === ".md" || ext === ".markdown") return "markdown";
|
|
745
|
-
if (ext === ".yml" || ext === ".yaml") return "yaml";
|
|
746
|
-
if (ext === ".json") return "json";
|
|
747
|
-
return fallbackKind || "artifact";
|
|
748
|
-
}
|
|
749
|
-
|
|
750
|
-
function normalizeApprovalTargets(targets) {
|
|
751
|
-
return toStringArray(targets).map((item) => item.trim()).filter(Boolean);
|
|
752
|
-
}
|
|
753
|
-
|
|
754
|
-
function writePayloadItems(payload) {
|
|
755
|
-
if (Array.isArray(payload?.items)) return payload.items;
|
|
756
|
-
if (Array.isArray(payload)) return payload;
|
|
757
|
-
return payload && typeof payload === "object" ? [payload] : [];
|
|
758
|
-
}
|
|
759
|
-
|
|
760
|
-
function suggestionApprovalTargets(payload) {
|
|
761
|
-
return writePayloadItems(payload).map((item, index) => {
|
|
762
|
-
if (!item || typeof item !== "object") return `index:${index}`;
|
|
763
|
-
return firstNonEmptyString(
|
|
764
|
-
item.suggestion_id,
|
|
765
|
-
item.id,
|
|
766
|
-
item._id,
|
|
767
|
-
item.mission_id,
|
|
768
|
-
item.target_mission_id,
|
|
769
|
-
item.title ? `${item.change_type || "suggestion"}:${item.title}` : ""
|
|
770
|
-
) || `index:${index}`;
|
|
771
|
-
});
|
|
772
|
-
}
|
|
773
|
-
|
|
774
|
-
function prdApprovalTargets(payload) {
|
|
775
|
-
return writePayloadItems(payload).map((item, index) => {
|
|
776
|
-
if (!item || typeof item !== "object") return `index:${index}`;
|
|
777
|
-
return firstNonEmptyString(item.client_ref, item.title) || `index:${index}`;
|
|
778
|
-
});
|
|
779
|
-
}
|
|
780
|
-
|
|
781
|
-
function requireWriteApproval(args, payload, { operation, artifactKind, targets = [], batchCount = null } = {}) {
|
|
782
|
-
const payloadSha256 = projectApiWritePayloadHash(payload || {});
|
|
783
|
-
const targetValues = normalizeApprovalTargets(targets);
|
|
784
|
-
const expectedBatchCount = batchCount !== null && batchCount !== undefined
|
|
785
|
-
? Number(batchCount)
|
|
786
|
-
: targetValues.length > 1
|
|
787
|
-
? targetValues.length
|
|
788
|
-
: null;
|
|
789
|
-
|
|
790
|
-
if (!isConfirmWrite(args)) {
|
|
791
|
-
console.error("Refusing live Myte write without explicit human approval.");
|
|
792
|
-
console.error(`Operation: ${operation || "unknown"}`);
|
|
793
|
-
console.error(`Payload SHA256: ${payloadSha256}`);
|
|
794
|
-
if (targetValues.length) console.error(`Targets: ${targetValues.join(", ")}`);
|
|
795
|
-
if (expectedBatchCount !== null) console.error(`Batch count: ${expectedBatchCount}`);
|
|
796
|
-
console.error("Create a local .md/.yml/.json approval artifact that lists the exact operation, payload summary, and every target.");
|
|
797
|
-
console.error("Show that artifact to the user and ask for explicit approval.");
|
|
798
|
-
console.error("Then rerun with --confirm-write --approval-artifact <path>.");
|
|
799
|
-
process.exit(1);
|
|
800
|
-
}
|
|
801
|
-
|
|
802
|
-
const artifactPath = resolveWriteApprovalArtifactPath(args);
|
|
803
|
-
if (!artifactPath) {
|
|
804
|
-
console.error("Missing --approval-artifact <path> for approved Myte write.");
|
|
805
|
-
console.error(`Payload SHA256: ${payloadSha256}`);
|
|
806
|
-
console.error("The artifact must be a local .md/.yml/.json file shown to and explicitly approved by the user.");
|
|
807
|
-
process.exit(1);
|
|
808
|
-
}
|
|
809
|
-
|
|
810
|
-
return {
|
|
811
|
-
approved: true,
|
|
812
|
-
source: "explicit_user_approval",
|
|
813
|
-
artifact_path: artifactPath,
|
|
814
|
-
artifact_kind: inferApprovalArtifactKind(artifactPath, artifactKind),
|
|
815
|
-
payload_sha256: payloadSha256,
|
|
816
|
-
targets: targetValues,
|
|
817
|
-
batch_count: expectedBatchCount,
|
|
818
|
-
};
|
|
819
|
-
}
|
|
820
|
-
|
|
821
|
-
function writeApprovalHeaders(writeApproval) {
|
|
822
|
-
if (!writeApproval) return {};
|
|
823
|
-
const headers = {
|
|
824
|
-
"X-Myte-Write-Approval": "explicit_user_approval",
|
|
825
|
-
"X-Myte-Approval-Artifact": String(writeApproval.artifact_path || ""),
|
|
826
|
-
"X-Myte-Approval-Artifact-Kind": String(writeApproval.artifact_kind || ""),
|
|
827
|
-
"X-Myte-Approval-Payload-SHA256": String(writeApproval.payload_sha256 || ""),
|
|
828
|
-
};
|
|
829
|
-
if (writeApproval.batch_count !== null && writeApproval.batch_count !== undefined) {
|
|
830
|
-
headers["X-Myte-Approval-Batch-Count"] = String(writeApproval.batch_count);
|
|
831
|
-
}
|
|
832
|
-
if (Array.isArray(writeApproval.targets) && writeApproval.targets.length) {
|
|
833
|
-
headers["X-Myte-Approval-Targets"] = writeApproval.targets.join(",");
|
|
834
|
-
}
|
|
835
|
-
return headers;
|
|
836
|
-
}
|
|
837
|
-
|
|
838
|
-
function formatProjectApiErrorMessage(body, fallback) {
|
|
839
|
-
const message = body?.message || fallback;
|
|
840
|
-
const data = body?.data || {};
|
|
841
|
-
const code = String(data?.code || "");
|
|
842
|
-
if (!code.startsWith("myte_write_approval")) {
|
|
843
|
-
return message;
|
|
844
|
-
}
|
|
845
|
-
const lines = [
|
|
846
|
-
message,
|
|
847
|
-
`Approval error: ${code}`,
|
|
848
|
-
];
|
|
849
|
-
if (data.operation) lines.push(`Operation: ${data.operation}`);
|
|
850
|
-
if (data.payload_sha256) lines.push(`Payload SHA256: ${data.payload_sha256}`);
|
|
851
|
-
if (Array.isArray(data.targets) && data.targets.length) lines.push(`Targets: ${data.targets.join(", ")}`);
|
|
852
|
-
if (data.batch_count !== undefined && data.batch_count !== null) lines.push(`Batch count: ${data.batch_count}`);
|
|
853
|
-
if (Array.isArray(data.required_agent_steps) && data.required_agent_steps.length) {
|
|
854
|
-
lines.push("Required agent steps:");
|
|
855
|
-
for (const step of data.required_agent_steps) {
|
|
856
|
-
lines.push(`- ${step}`);
|
|
857
|
-
}
|
|
858
|
-
}
|
|
859
|
-
return lines.join("\n");
|
|
860
|
-
}
|
|
861
|
-
|
|
862
|
-
function summarizeDiffDiagnosticsForContext(diagnostics) {
|
|
863
|
-
if (!diagnostics) return null;
|
|
864
|
-
const repos = Array.isArray(diagnostics.repo_summaries)
|
|
692
|
+
if (timeoutId) clearTimeout(timeoutId);
|
|
693
|
+
}
|
|
694
|
+
}
|
|
695
|
+
|
|
696
|
+
function summarizeDiffDiagnosticsForContext(diagnostics) {
|
|
697
|
+
if (!diagnostics) return null;
|
|
698
|
+
const repos = Array.isArray(diagnostics.repo_summaries)
|
|
865
699
|
? diagnostics.repo_summaries
|
|
866
700
|
: [];
|
|
867
701
|
return {
|
|
@@ -1922,16 +1756,15 @@ async function fetchFeedbackHistory({ apiBase, key, timeoutMs, feedbackId }) {
|
|
|
1922
1756
|
return body.data || {};
|
|
1923
1757
|
}
|
|
1924
1758
|
|
|
1925
|
-
async function postFeedbackRefinement({ apiBase, key, timeoutMs, feedbackId, mode, payload, idempotencyKey, clientSessionId
|
|
1759
|
+
async function postFeedbackRefinement({ apiBase, key, timeoutMs, feedbackId, mode, payload, idempotencyKey, clientSessionId }) {
|
|
1926
1760
|
const fetchFn = await getFetch();
|
|
1927
1761
|
const action = String(mode || "").trim();
|
|
1928
1762
|
const url = `${apiBase}/project-assistant/feedback/${encodeURIComponent(String(feedbackId || ""))}/refinement/${action}`;
|
|
1929
|
-
const headers = {
|
|
1930
|
-
"Content-Type": "application/json",
|
|
1931
|
-
Authorization: `Bearer ${key}`,
|
|
1932
|
-
...(String(clientSessionId || "").trim() ? { "X-Client-Session-Id": String(clientSessionId).trim() } : {}),
|
|
1933
|
-
|
|
1934
|
-
};
|
|
1763
|
+
const headers = {
|
|
1764
|
+
"Content-Type": "application/json",
|
|
1765
|
+
Authorization: `Bearer ${key}`,
|
|
1766
|
+
...(String(clientSessionId || "").trim() ? { "X-Client-Session-Id": String(clientSessionId).trim() } : {}),
|
|
1767
|
+
};
|
|
1935
1768
|
if (idempotencyKey) {
|
|
1936
1769
|
headers["X-Idempotency-Key"] = String(idempotencyKey).trim();
|
|
1937
1770
|
}
|
|
@@ -1947,7 +1780,7 @@ async function postFeedbackRefinement({ apiBase, key, timeoutMs, feedbackId, mod
|
|
|
1947
1780
|
);
|
|
1948
1781
|
|
|
1949
1782
|
if (!resp.ok || body.status !== "success") {
|
|
1950
|
-
const msg =
|
|
1783
|
+
const msg = body?.message || `Feedback refinement ${action} failed (${resp.status})`;
|
|
1951
1784
|
const err = new Error(msg);
|
|
1952
1785
|
err.status = resp.status;
|
|
1953
1786
|
err.data = body?.data;
|
|
@@ -2026,7 +1859,7 @@ async function fetchFeedbackEvents({ apiBase, key, timeoutMs, feedbackId, limit
|
|
|
2026
1859
|
return body.data || {};
|
|
2027
1860
|
}
|
|
2028
1861
|
|
|
2029
|
-
async function postFeedbackReviewSubmission({ apiBase, key, timeoutMs, feedbackId, payload, idempotencyKey, clientSessionId
|
|
1862
|
+
async function postFeedbackReviewSubmission({ apiBase, key, timeoutMs, feedbackId, payload, idempotencyKey, clientSessionId }) {
|
|
2030
1863
|
const fetchFn = await getFetch();
|
|
2031
1864
|
const url = `${apiBase}/project-assistant/feedback/${encodeURIComponent(String(feedbackId || ""))}/refinement/requests`;
|
|
2032
1865
|
const { resp, body } = await fetchJsonWithTimeout(
|
|
@@ -2036,18 +1869,17 @@ async function postFeedbackReviewSubmission({ apiBase, key, timeoutMs, feedbackI
|
|
|
2036
1869
|
method: "POST",
|
|
2037
1870
|
headers: {
|
|
2038
1871
|
"Content-Type": "application/json",
|
|
2039
|
-
Authorization: `Bearer ${key}`,
|
|
2040
|
-
"X-Idempotency-Key": String(idempotencyKey || "").trim(),
|
|
2041
|
-
...(String(clientSessionId || "").trim() ? { "X-Client-Session-Id": String(clientSessionId).trim() } : {}),
|
|
2042
|
-
|
|
2043
|
-
},
|
|
1872
|
+
Authorization: `Bearer ${key}`,
|
|
1873
|
+
"X-Idempotency-Key": String(idempotencyKey || "").trim(),
|
|
1874
|
+
...(String(clientSessionId || "").trim() ? { "X-Client-Session-Id": String(clientSessionId).trim() } : {}),
|
|
1875
|
+
},
|
|
2044
1876
|
body: JSON.stringify(payload || {}),
|
|
2045
1877
|
},
|
|
2046
1878
|
timeoutMs
|
|
2047
1879
|
);
|
|
2048
1880
|
|
|
2049
1881
|
if (!resp.ok || body.status !== "success") {
|
|
2050
|
-
const msg =
|
|
1882
|
+
const msg = body?.message || `Feedback review submission failed (${resp.status})`;
|
|
2051
1883
|
const err = new Error(msg);
|
|
2052
1884
|
err.status = resp.status;
|
|
2053
1885
|
err.data = body?.data;
|
|
@@ -2056,7 +1888,7 @@ async function postFeedbackReviewSubmission({ apiBase, key, timeoutMs, feedbackI
|
|
|
2056
1888
|
return body.data || {};
|
|
2057
1889
|
}
|
|
2058
1890
|
|
|
2059
|
-
async function postFeedbackReviewRequestMutation({ apiBase, key, timeoutMs, requestId, endpointAction, payload, idempotencyKey, clientSessionId
|
|
1891
|
+
async function postFeedbackReviewRequestMutation({ apiBase, key, timeoutMs, requestId, endpointAction, payload, idempotencyKey, clientSessionId }) {
|
|
2060
1892
|
const fetchFn = await getFetch();
|
|
2061
1893
|
const url = `${apiBase}/project-assistant/feedback-review-requests/${encodeURIComponent(String(requestId || ""))}/${endpointAction}`;
|
|
2062
1894
|
const { resp, body } = await fetchJsonWithTimeout(
|
|
@@ -2066,18 +1898,17 @@ async function postFeedbackReviewRequestMutation({ apiBase, key, timeoutMs, requ
|
|
|
2066
1898
|
method: "POST",
|
|
2067
1899
|
headers: {
|
|
2068
1900
|
"Content-Type": "application/json",
|
|
2069
|
-
Authorization: `Bearer ${key}`,
|
|
2070
|
-
"X-Idempotency-Key": String(idempotencyKey || "").trim(),
|
|
2071
|
-
...(String(clientSessionId || "").trim() ? { "X-Client-Session-Id": String(clientSessionId).trim() } : {}),
|
|
2072
|
-
|
|
2073
|
-
},
|
|
1901
|
+
Authorization: `Bearer ${key}`,
|
|
1902
|
+
"X-Idempotency-Key": String(idempotencyKey || "").trim(),
|
|
1903
|
+
...(String(clientSessionId || "").trim() ? { "X-Client-Session-Id": String(clientSessionId).trim() } : {}),
|
|
1904
|
+
},
|
|
2074
1905
|
body: JSON.stringify(payload || {}),
|
|
2075
1906
|
},
|
|
2076
1907
|
timeoutMs
|
|
2077
1908
|
);
|
|
2078
1909
|
|
|
2079
1910
|
if (!resp.ok || body.status !== "success") {
|
|
2080
|
-
const msg =
|
|
1911
|
+
const msg = body?.message || `Feedback review ${endpointAction} failed (${resp.status})`;
|
|
2081
1912
|
const err = new Error(msg);
|
|
2082
1913
|
err.status = resp.status;
|
|
2083
1914
|
err.data = body?.data;
|
|
@@ -2086,7 +1917,7 @@ async function postFeedbackReviewRequestMutation({ apiBase, key, timeoutMs, requ
|
|
|
2086
1917
|
return body.data || {};
|
|
2087
1918
|
}
|
|
2088
1919
|
|
|
2089
|
-
async function postFeedbackBatchReviewMutation({ apiBase, key, timeoutMs, payload, idempotencyKey, clientSessionId
|
|
1920
|
+
async function postFeedbackBatchReviewMutation({ apiBase, key, timeoutMs, payload, idempotencyKey, clientSessionId }) {
|
|
2090
1921
|
const fetchFn = await getFetch();
|
|
2091
1922
|
const url = `${apiBase}/project-assistant/feedback-review-requests/batch-review`;
|
|
2092
1923
|
const { resp, body } = await fetchJsonWithTimeout(
|
|
@@ -2096,18 +1927,17 @@ async function postFeedbackBatchReviewMutation({ apiBase, key, timeoutMs, payloa
|
|
|
2096
1927
|
method: "POST",
|
|
2097
1928
|
headers: {
|
|
2098
1929
|
"Content-Type": "application/json",
|
|
2099
|
-
Authorization: `Bearer ${key}`,
|
|
2100
|
-
"X-Idempotency-Key": String(idempotencyKey || "").trim(),
|
|
2101
|
-
...(String(clientSessionId || "").trim() ? { "X-Client-Session-Id": String(clientSessionId).trim() } : {}),
|
|
2102
|
-
|
|
2103
|
-
},
|
|
1930
|
+
Authorization: `Bearer ${key}`,
|
|
1931
|
+
"X-Idempotency-Key": String(idempotencyKey || "").trim(),
|
|
1932
|
+
...(String(clientSessionId || "").trim() ? { "X-Client-Session-Id": String(clientSessionId).trim() } : {}),
|
|
1933
|
+
},
|
|
2104
1934
|
body: JSON.stringify(payload || {}),
|
|
2105
1935
|
},
|
|
2106
1936
|
timeoutMs
|
|
2107
1937
|
);
|
|
2108
1938
|
|
|
2109
1939
|
if (!resp.ok || body.status !== "success") {
|
|
2110
|
-
const msg =
|
|
1940
|
+
const msg = body?.message || `Feedback batch review failed (${resp.status})`;
|
|
2111
1941
|
const err = new Error(msg);
|
|
2112
1942
|
err.status = resp.status;
|
|
2113
1943
|
err.data = body?.data;
|
|
@@ -2116,7 +1946,7 @@ async function postFeedbackBatchReviewMutation({ apiBase, key, timeoutMs, payloa
|
|
|
2116
1946
|
return body.data || {};
|
|
2117
1947
|
}
|
|
2118
1948
|
|
|
2119
|
-
async function postFeedbackBoardMutation({ apiBase, key, timeoutMs, feedbackId, endpoint, payload, idempotencyKey, clientSessionId
|
|
1949
|
+
async function postFeedbackBoardMutation({ apiBase, key, timeoutMs, feedbackId, endpoint, payload, idempotencyKey, clientSessionId }) {
|
|
2120
1950
|
const fetchFn = await getFetch();
|
|
2121
1951
|
const url = `${apiBase}/project-assistant/feedback/${encodeURIComponent(String(feedbackId || ""))}/${endpoint}`;
|
|
2122
1952
|
const { resp, body } = await fetchJsonWithTimeout(
|
|
@@ -2126,18 +1956,17 @@ async function postFeedbackBoardMutation({ apiBase, key, timeoutMs, feedbackId,
|
|
|
2126
1956
|
method: "POST",
|
|
2127
1957
|
headers: {
|
|
2128
1958
|
"Content-Type": "application/json",
|
|
2129
|
-
Authorization: `Bearer ${key}`,
|
|
2130
|
-
"X-Idempotency-Key": String(idempotencyKey || "").trim(),
|
|
2131
|
-
...(String(clientSessionId || "").trim() ? { "X-Client-Session-Id": String(clientSessionId).trim() } : {}),
|
|
2132
|
-
|
|
2133
|
-
},
|
|
1959
|
+
Authorization: `Bearer ${key}`,
|
|
1960
|
+
"X-Idempotency-Key": String(idempotencyKey || "").trim(),
|
|
1961
|
+
...(String(clientSessionId || "").trim() ? { "X-Client-Session-Id": String(clientSessionId).trim() } : {}),
|
|
1962
|
+
},
|
|
2134
1963
|
body: JSON.stringify(payload || {}),
|
|
2135
1964
|
},
|
|
2136
1965
|
timeoutMs
|
|
2137
1966
|
);
|
|
2138
1967
|
|
|
2139
1968
|
if (!resp.ok || body.status !== "success") {
|
|
2140
|
-
const msg =
|
|
1969
|
+
const msg = body?.message || `Feedback board mutation failed (${resp.status})`;
|
|
2141
1970
|
const err = new Error(msg);
|
|
2142
1971
|
err.status = resp.status;
|
|
2143
1972
|
err.data = body?.data;
|
|
@@ -2146,7 +1975,7 @@ async function postFeedbackBoardMutation({ apiBase, key, timeoutMs, feedbackId,
|
|
|
2146
1975
|
return body.data || {};
|
|
2147
1976
|
}
|
|
2148
1977
|
|
|
2149
|
-
async function postFeedbackBatchBoardMutation({ apiBase, key, timeoutMs, payload, idempotencyKey, clientSessionId
|
|
1978
|
+
async function postFeedbackBatchBoardMutation({ apiBase, key, timeoutMs, payload, idempotencyKey, clientSessionId }) {
|
|
2150
1979
|
const fetchFn = await getFetch();
|
|
2151
1980
|
const url = `${apiBase}/project-assistant/feedback/batch-board-move`;
|
|
2152
1981
|
const { resp, body } = await fetchJsonWithTimeout(
|
|
@@ -2156,57 +1985,55 @@ async function postFeedbackBatchBoardMutation({ apiBase, key, timeoutMs, payload
|
|
|
2156
1985
|
method: "POST",
|
|
2157
1986
|
headers: {
|
|
2158
1987
|
"Content-Type": "application/json",
|
|
2159
|
-
Authorization: `Bearer ${key}`,
|
|
2160
|
-
"X-Idempotency-Key": String(idempotencyKey || "").trim(),
|
|
2161
|
-
...(String(clientSessionId || "").trim() ? { "X-Client-Session-Id": String(clientSessionId).trim() } : {}),
|
|
2162
|
-
|
|
2163
|
-
},
|
|
1988
|
+
Authorization: `Bearer ${key}`,
|
|
1989
|
+
"X-Idempotency-Key": String(idempotencyKey || "").trim(),
|
|
1990
|
+
...(String(clientSessionId || "").trim() ? { "X-Client-Session-Id": String(clientSessionId).trim() } : {}),
|
|
1991
|
+
},
|
|
2164
1992
|
body: JSON.stringify(payload || {}),
|
|
2165
1993
|
},
|
|
2166
1994
|
timeoutMs
|
|
2167
1995
|
);
|
|
2168
1996
|
|
|
2169
1997
|
if (!resp.ok || body.status !== "success") {
|
|
2170
|
-
const msg =
|
|
1998
|
+
const msg = body?.message || `Feedback batch board mutation failed (${resp.status})`;
|
|
2171
1999
|
const err = new Error(msg);
|
|
2172
2000
|
err.status = resp.status;
|
|
2173
2001
|
err.data = body?.data;
|
|
2174
2002
|
throw err;
|
|
2175
2003
|
}
|
|
2176
|
-
return body.data || {};
|
|
2177
|
-
}
|
|
2178
|
-
|
|
2179
|
-
async function postFeedbackComment({ apiBase, key, timeoutMs, feedbackId, payload, idempotencyKey, clientSessionId
|
|
2180
|
-
const fetchFn = await getFetch();
|
|
2181
|
-
const url = `${apiBase}/project-assistant/feedback/${encodeURIComponent(String(feedbackId || ""))}/comments`;
|
|
2182
|
-
const { resp, body } = await fetchJsonWithTimeout(
|
|
2183
|
-
fetchFn,
|
|
2184
|
-
url,
|
|
2185
|
-
{
|
|
2186
|
-
method: "POST",
|
|
2187
|
-
headers: {
|
|
2188
|
-
"Content-Type": "application/json",
|
|
2189
|
-
Authorization: `Bearer ${key}`,
|
|
2190
|
-
"X-Idempotency-Key": String(idempotencyKey || "").trim(),
|
|
2191
|
-
...(String(clientSessionId || "").trim() ? { "X-Client-Session-Id": String(clientSessionId).trim() } : {}),
|
|
2192
|
-
|
|
2193
|
-
},
|
|
2194
|
-
|
|
2195
|
-
|
|
2196
|
-
|
|
2197
|
-
|
|
2198
|
-
|
|
2199
|
-
|
|
2200
|
-
const
|
|
2201
|
-
|
|
2202
|
-
err.
|
|
2203
|
-
err
|
|
2204
|
-
|
|
2205
|
-
}
|
|
2206
|
-
|
|
2207
|
-
|
|
2208
|
-
|
|
2209
|
-
async function fetchFeedbackPrdVersions({ apiBase, key, timeoutMs, feedbackId }) {
|
|
2004
|
+
return body.data || {};
|
|
2005
|
+
}
|
|
2006
|
+
|
|
2007
|
+
async function postFeedbackComment({ apiBase, key, timeoutMs, feedbackId, payload, idempotencyKey, clientSessionId }) {
|
|
2008
|
+
const fetchFn = await getFetch();
|
|
2009
|
+
const url = `${apiBase}/project-assistant/feedback/${encodeURIComponent(String(feedbackId || ""))}/comments`;
|
|
2010
|
+
const { resp, body } = await fetchJsonWithTimeout(
|
|
2011
|
+
fetchFn,
|
|
2012
|
+
url,
|
|
2013
|
+
{
|
|
2014
|
+
method: "POST",
|
|
2015
|
+
headers: {
|
|
2016
|
+
"Content-Type": "application/json",
|
|
2017
|
+
Authorization: `Bearer ${key}`,
|
|
2018
|
+
"X-Idempotency-Key": String(idempotencyKey || "").trim(),
|
|
2019
|
+
...(String(clientSessionId || "").trim() ? { "X-Client-Session-Id": String(clientSessionId).trim() } : {}),
|
|
2020
|
+
},
|
|
2021
|
+
body: JSON.stringify(payload || {}),
|
|
2022
|
+
},
|
|
2023
|
+
timeoutMs
|
|
2024
|
+
);
|
|
2025
|
+
|
|
2026
|
+
if (!resp.ok || body.status !== "success") {
|
|
2027
|
+
const msg = body?.message || `Feedback comment failed (${resp.status})`;
|
|
2028
|
+
const err = new Error(msg);
|
|
2029
|
+
err.status = resp.status;
|
|
2030
|
+
err.data = body?.data;
|
|
2031
|
+
throw err;
|
|
2032
|
+
}
|
|
2033
|
+
return body.data || {};
|
|
2034
|
+
}
|
|
2035
|
+
|
|
2036
|
+
async function fetchFeedbackPrdVersions({ apiBase, key, timeoutMs, feedbackId }) {
|
|
2210
2037
|
const fetchFn = await getFetch();
|
|
2211
2038
|
const url = `${apiBase}/project-assistant/feedback/${encodeURIComponent(String(feedbackId || ""))}/prd/versions`;
|
|
2212
2039
|
const { resp, body } = await fetchJsonWithTimeout(
|
|
@@ -2303,7 +2130,7 @@ function resolveProjectMutationIdempotencyKey({ args, operation, payload }) {
|
|
|
2303
2130
|
return createHash("sha256").update(fingerprint).digest("hex");
|
|
2304
2131
|
}
|
|
2305
2132
|
|
|
2306
|
-
async function postSuggestionsMutation({ apiBase, key, timeoutMs, endpoint, payload, idempotencyKey, clientSessionId
|
|
2133
|
+
async function postSuggestionsMutation({ apiBase, key, timeoutMs, endpoint, payload, idempotencyKey, clientSessionId }) {
|
|
2307
2134
|
const fetchFn = await getFetch();
|
|
2308
2135
|
const url = `${apiBase}${endpoint}`;
|
|
2309
2136
|
const { resp, body } = await fetchJsonWithTimeout(
|
|
@@ -2313,27 +2140,25 @@ async function postSuggestionsMutation({ apiBase, key, timeoutMs, endpoint, payl
|
|
|
2313
2140
|
method: "POST",
|
|
2314
2141
|
headers: {
|
|
2315
2142
|
"Content-Type": "application/json",
|
|
2316
|
-
Authorization: `Bearer ${key}`,
|
|
2317
|
-
"X-Idempotency-Key": String(idempotencyKey || "").trim(),
|
|
2318
|
-
...(String(clientSessionId || "").trim() ? { "X-Client-Session-Id": String(clientSessionId).trim() } : {}),
|
|
2319
|
-
|
|
2320
|
-
},
|
|
2143
|
+
Authorization: `Bearer ${key}`,
|
|
2144
|
+
"X-Idempotency-Key": String(idempotencyKey || "").trim(),
|
|
2145
|
+
...(String(clientSessionId || "").trim() ? { "X-Client-Session-Id": String(clientSessionId).trim() } : {}),
|
|
2146
|
+
},
|
|
2321
2147
|
body: JSON.stringify(payload),
|
|
2322
2148
|
},
|
|
2323
2149
|
timeoutMs
|
|
2324
2150
|
);
|
|
2325
2151
|
|
|
2326
2152
|
if (!resp.ok || body.status !== "success") {
|
|
2327
|
-
const msg =
|
|
2328
|
-
const err = new Error(msg);
|
|
2329
|
-
err.status = resp.status;
|
|
2330
|
-
err.data = body?.data;
|
|
2153
|
+
const msg = body?.message || `Mission suggestions request failed (${resp.status})`;
|
|
2154
|
+
const err = new Error(msg);
|
|
2155
|
+
err.status = resp.status;
|
|
2331
2156
|
throw err;
|
|
2332
2157
|
}
|
|
2333
2158
|
return body.data || {};
|
|
2334
2159
|
}
|
|
2335
2160
|
|
|
2336
|
-
async function createRunQaqcBatch({ apiBase, key, timeoutMs, payload, idempotencyKey, clientSessionId
|
|
2161
|
+
async function createRunQaqcBatch({ apiBase, key, timeoutMs, payload, idempotencyKey, clientSessionId }) {
|
|
2337
2162
|
const fetchFn = await getFetch();
|
|
2338
2163
|
const url = `${apiBase}/project-assistant/run-qaqc`;
|
|
2339
2164
|
const { resp, body } = await fetchJsonWithTimeout(
|
|
@@ -2343,27 +2168,25 @@ async function createRunQaqcBatch({ apiBase, key, timeoutMs, payload, idempotenc
|
|
|
2343
2168
|
method: "POST",
|
|
2344
2169
|
headers: {
|
|
2345
2170
|
"Content-Type": "application/json",
|
|
2346
|
-
Authorization: `Bearer ${key}`,
|
|
2347
|
-
"X-Idempotency-Key": String(idempotencyKey || "").trim(),
|
|
2348
|
-
...(String(clientSessionId || "").trim() ? { "X-Client-Session-Id": String(clientSessionId).trim() } : {}),
|
|
2349
|
-
|
|
2350
|
-
},
|
|
2171
|
+
Authorization: `Bearer ${key}`,
|
|
2172
|
+
"X-Idempotency-Key": String(idempotencyKey || "").trim(),
|
|
2173
|
+
...(String(clientSessionId || "").trim() ? { "X-Client-Session-Id": String(clientSessionId).trim() } : {}),
|
|
2174
|
+
},
|
|
2351
2175
|
body: JSON.stringify(payload),
|
|
2352
2176
|
},
|
|
2353
2177
|
timeoutMs
|
|
2354
2178
|
);
|
|
2355
2179
|
|
|
2356
2180
|
if (!resp.ok || body.status !== "success") {
|
|
2357
|
-
const msg =
|
|
2358
|
-
const err = new Error(msg);
|
|
2359
|
-
err.status = resp.status;
|
|
2360
|
-
err
|
|
2361
|
-
|
|
2362
|
-
}
|
|
2181
|
+
const msg = body?.message || `Run QAQC request failed (${resp.status})`;
|
|
2182
|
+
const err = new Error(msg);
|
|
2183
|
+
err.status = resp.status;
|
|
2184
|
+
throw err;
|
|
2185
|
+
}
|
|
2363
2186
|
return body.data || {};
|
|
2364
2187
|
}
|
|
2365
2188
|
|
|
2366
|
-
async function createMissionStatusUpdate({ apiBase, key, timeoutMs, payload, idempotencyKey, clientSessionId
|
|
2189
|
+
async function createMissionStatusUpdate({ apiBase, key, timeoutMs, payload, idempotencyKey, clientSessionId }) {
|
|
2367
2190
|
const fetchFn = await getFetch();
|
|
2368
2191
|
const url = `${apiBase}/project-assistant/mission-status-update`;
|
|
2369
2192
|
const { resp, body } = await fetchJsonWithTimeout(
|
|
@@ -2373,27 +2196,25 @@ async function createMissionStatusUpdate({ apiBase, key, timeoutMs, payload, ide
|
|
|
2373
2196
|
method: "POST",
|
|
2374
2197
|
headers: {
|
|
2375
2198
|
"Content-Type": "application/json",
|
|
2376
|
-
Authorization: `Bearer ${key}`,
|
|
2377
|
-
"X-Idempotency-Key": String(idempotencyKey || "").trim(),
|
|
2378
|
-
...(String(clientSessionId || "").trim() ? { "X-Client-Session-Id": String(clientSessionId).trim() } : {}),
|
|
2379
|
-
|
|
2380
|
-
},
|
|
2199
|
+
Authorization: `Bearer ${key}`,
|
|
2200
|
+
"X-Idempotency-Key": String(idempotencyKey || "").trim(),
|
|
2201
|
+
...(String(clientSessionId || "").trim() ? { "X-Client-Session-Id": String(clientSessionId).trim() } : {}),
|
|
2202
|
+
},
|
|
2381
2203
|
body: JSON.stringify(payload),
|
|
2382
2204
|
},
|
|
2383
2205
|
timeoutMs
|
|
2384
2206
|
);
|
|
2385
2207
|
|
|
2386
2208
|
if (!resp.ok || body.status !== "success") {
|
|
2387
|
-
const msg =
|
|
2388
|
-
const err = new Error(msg);
|
|
2389
|
-
err.status = resp.status;
|
|
2390
|
-
err
|
|
2391
|
-
|
|
2392
|
-
}
|
|
2209
|
+
const msg = body?.message || `Mission status update request failed (${resp.status})`;
|
|
2210
|
+
const err = new Error(msg);
|
|
2211
|
+
err.status = resp.status;
|
|
2212
|
+
throw err;
|
|
2213
|
+
}
|
|
2393
2214
|
return body.data || {};
|
|
2394
2215
|
}
|
|
2395
2216
|
|
|
2396
|
-
async function createMissionArchiveUpdate({ apiBase, key, timeoutMs, endpoint, payload, idempotencyKey, clientSessionId
|
|
2217
|
+
async function createMissionArchiveUpdate({ apiBase, key, timeoutMs, endpoint, payload, idempotencyKey, clientSessionId }) {
|
|
2397
2218
|
const fetchFn = await getFetch();
|
|
2398
2219
|
const url = `${apiBase}${endpoint}`;
|
|
2399
2220
|
const { resp, body } = await fetchJsonWithTimeout(
|
|
@@ -2403,21 +2224,19 @@ async function createMissionArchiveUpdate({ apiBase, key, timeoutMs, endpoint, p
|
|
|
2403
2224
|
method: "POST",
|
|
2404
2225
|
headers: {
|
|
2405
2226
|
"Content-Type": "application/json",
|
|
2406
|
-
Authorization: `Bearer ${key}`,
|
|
2407
|
-
"X-Idempotency-Key": String(idempotencyKey || "").trim(),
|
|
2408
|
-
...(String(clientSessionId || "").trim() ? { "X-Client-Session-Id": String(clientSessionId).trim() } : {}),
|
|
2409
|
-
|
|
2410
|
-
},
|
|
2227
|
+
Authorization: `Bearer ${key}`,
|
|
2228
|
+
"X-Idempotency-Key": String(idempotencyKey || "").trim(),
|
|
2229
|
+
...(String(clientSessionId || "").trim() ? { "X-Client-Session-Id": String(clientSessionId).trim() } : {}),
|
|
2230
|
+
},
|
|
2411
2231
|
body: JSON.stringify(payload),
|
|
2412
2232
|
},
|
|
2413
2233
|
timeoutMs
|
|
2414
2234
|
);
|
|
2415
2235
|
|
|
2416
2236
|
if (!resp.ok || body.status !== "success") {
|
|
2417
|
-
const msg =
|
|
2418
|
-
const err = new Error(msg);
|
|
2419
|
-
err.status = resp.status;
|
|
2420
|
-
err.data = body?.data;
|
|
2237
|
+
const msg = body?.message || `Mission archive request failed (${resp.status})`;
|
|
2238
|
+
const err = new Error(msg);
|
|
2239
|
+
err.status = resp.status;
|
|
2421
2240
|
throw err;
|
|
2422
2241
|
}
|
|
2423
2242
|
return body.data || {};
|
|
@@ -2530,15 +2349,20 @@ async function runRunQaqc(args) {
|
|
|
2530
2349
|
process.exit(1);
|
|
2531
2350
|
}
|
|
2532
2351
|
|
|
2533
|
-
|
|
2534
|
-
mission_ids: missionIds,
|
|
2535
|
-
force: Boolean(args.force),
|
|
2536
|
-
};
|
|
2537
|
-
const clientSessionId = firstNonEmptyString(args["client-session-id"], args.clientSessionId, args.client_session_id);
|
|
2538
|
-
if (clientSessionId) payload.client_session_id = clientSessionId;
|
|
2539
|
-
|
|
2540
|
-
|
|
2541
|
-
|
|
2352
|
+
let payload = {
|
|
2353
|
+
mission_ids: missionIds,
|
|
2354
|
+
force: Boolean(args.force),
|
|
2355
|
+
};
|
|
2356
|
+
const clientSessionId = firstNonEmptyString(args["client-session-id"], args.clientSessionId, args.client_session_id);
|
|
2357
|
+
if (clientSessionId) payload.client_session_id = clientSessionId;
|
|
2358
|
+
payload = withWriteApproval(args, payload, {
|
|
2359
|
+
artifactKind: "yaml",
|
|
2360
|
+
targets: missionIds,
|
|
2361
|
+
batchCount: missionIds.length > 1 ? missionIds.length : null,
|
|
2362
|
+
});
|
|
2363
|
+
const idempotencyKey = resolveProjectMutationIdempotencyKey({
|
|
2364
|
+
args,
|
|
2365
|
+
operation: "run-qaqc",
|
|
2542
2366
|
payload,
|
|
2543
2367
|
});
|
|
2544
2368
|
|
|
@@ -2547,28 +2371,21 @@ async function runRunQaqc(args) {
|
|
|
2547
2371
|
return;
|
|
2548
2372
|
}
|
|
2549
2373
|
|
|
2550
|
-
const timeoutMs = resolveTimeoutMs(args);
|
|
2551
|
-
const apiBase = resolveApiBase(args);
|
|
2552
|
-
const shouldWait = Boolean(args.wait || args.sync);
|
|
2553
|
-
const shouldSync = Boolean(args.sync);
|
|
2554
|
-
|
|
2555
|
-
|
|
2556
|
-
|
|
2557
|
-
|
|
2558
|
-
|
|
2559
|
-
});
|
|
2560
|
-
|
|
2561
|
-
let data;
|
|
2562
|
-
try {
|
|
2563
|
-
data = await createRunQaqcBatch({
|
|
2564
|
-
apiBase,
|
|
2374
|
+
const timeoutMs = resolveTimeoutMs(args);
|
|
2375
|
+
const apiBase = resolveApiBase(args);
|
|
2376
|
+
const shouldWait = Boolean(args.wait || args.sync);
|
|
2377
|
+
const shouldSync = Boolean(args.sync);
|
|
2378
|
+
|
|
2379
|
+
let data;
|
|
2380
|
+
try {
|
|
2381
|
+
data = await createRunQaqcBatch({
|
|
2382
|
+
apiBase,
|
|
2565
2383
|
key,
|
|
2566
2384
|
timeoutMs,
|
|
2567
|
-
payload,
|
|
2568
|
-
idempotencyKey,
|
|
2569
|
-
clientSessionId,
|
|
2570
|
-
|
|
2571
|
-
});
|
|
2385
|
+
payload,
|
|
2386
|
+
idempotencyKey,
|
|
2387
|
+
clientSessionId,
|
|
2388
|
+
});
|
|
2572
2389
|
} catch (err) {
|
|
2573
2390
|
if (err?.name === "AbortError") {
|
|
2574
2391
|
console.error(`Request timed out after ${timeoutMs}ms`);
|
|
@@ -2692,15 +2509,20 @@ async function runMissionStatus(args) {
|
|
|
2692
2509
|
process.exit(1);
|
|
2693
2510
|
}
|
|
2694
2511
|
|
|
2695
|
-
|
|
2696
|
-
mission_ids: missionIds,
|
|
2697
|
-
new_status: newStatus,
|
|
2698
|
-
};
|
|
2699
|
-
const clientSessionId = firstNonEmptyString(args["client-session-id"], args.clientSessionId, args.client_session_id);
|
|
2700
|
-
if (clientSessionId) payload.client_session_id = clientSessionId;
|
|
2701
|
-
|
|
2702
|
-
|
|
2703
|
-
|
|
2512
|
+
let payload = {
|
|
2513
|
+
mission_ids: missionIds,
|
|
2514
|
+
new_status: newStatus,
|
|
2515
|
+
};
|
|
2516
|
+
const clientSessionId = firstNonEmptyString(args["client-session-id"], args.clientSessionId, args.client_session_id);
|
|
2517
|
+
if (clientSessionId) payload.client_session_id = clientSessionId;
|
|
2518
|
+
payload = withWriteApproval(args, payload, {
|
|
2519
|
+
artifactKind: "yaml",
|
|
2520
|
+
targets: missionIds,
|
|
2521
|
+
batchCount: missionIds.length > 1 ? missionIds.length : null,
|
|
2522
|
+
});
|
|
2523
|
+
const idempotencyKey = resolveProjectMutationIdempotencyKey({
|
|
2524
|
+
args,
|
|
2525
|
+
operation: "mission-status-update",
|
|
2704
2526
|
payload,
|
|
2705
2527
|
});
|
|
2706
2528
|
|
|
@@ -2709,26 +2531,19 @@ async function runMissionStatus(args) {
|
|
|
2709
2531
|
return;
|
|
2710
2532
|
}
|
|
2711
2533
|
|
|
2712
|
-
const timeoutMs = resolveTimeoutMs(args);
|
|
2713
|
-
const apiBase = resolveApiBase(args);
|
|
2714
|
-
|
|
2715
|
-
|
|
2716
|
-
|
|
2717
|
-
|
|
2718
|
-
|
|
2719
|
-
});
|
|
2720
|
-
|
|
2721
|
-
let data;
|
|
2722
|
-
try {
|
|
2723
|
-
data = await createMissionStatusUpdate({
|
|
2724
|
-
apiBase,
|
|
2534
|
+
const timeoutMs = resolveTimeoutMs(args);
|
|
2535
|
+
const apiBase = resolveApiBase(args);
|
|
2536
|
+
|
|
2537
|
+
let data;
|
|
2538
|
+
try {
|
|
2539
|
+
data = await createMissionStatusUpdate({
|
|
2540
|
+
apiBase,
|
|
2725
2541
|
key,
|
|
2726
2542
|
timeoutMs,
|
|
2727
|
-
payload,
|
|
2728
|
-
idempotencyKey,
|
|
2729
|
-
clientSessionId,
|
|
2730
|
-
|
|
2731
|
-
});
|
|
2543
|
+
payload,
|
|
2544
|
+
idempotencyKey,
|
|
2545
|
+
clientSessionId,
|
|
2546
|
+
});
|
|
2732
2547
|
} catch (err) {
|
|
2733
2548
|
if (err?.name === "AbortError") {
|
|
2734
2549
|
console.error(`Request timed out after ${timeoutMs}ms`);
|
|
@@ -2802,13 +2617,18 @@ async function runMissionArchiveCommand(args) {
|
|
|
2802
2617
|
process.exit(1);
|
|
2803
2618
|
}
|
|
2804
2619
|
|
|
2805
|
-
|
|
2806
|
-
mission_ids: missionIds,
|
|
2807
|
-
};
|
|
2808
|
-
const reason = firstNonEmptyString(args.reason);
|
|
2809
|
-
if (reason) payload.reason = reason;
|
|
2810
|
-
const clientSessionId = firstNonEmptyString(args["client-session-id"], args.clientSessionId, args.client_session_id);
|
|
2811
|
-
if (clientSessionId) payload.client_session_id = clientSessionId;
|
|
2620
|
+
let payload = {
|
|
2621
|
+
mission_ids: missionIds,
|
|
2622
|
+
};
|
|
2623
|
+
const reason = firstNonEmptyString(args.reason);
|
|
2624
|
+
if (reason) payload.reason = reason;
|
|
2625
|
+
const clientSessionId = firstNonEmptyString(args["client-session-id"], args.clientSessionId, args.client_session_id);
|
|
2626
|
+
if (clientSessionId) payload.client_session_id = clientSessionId;
|
|
2627
|
+
payload = withWriteApproval(args, payload, {
|
|
2628
|
+
artifactKind: "yaml",
|
|
2629
|
+
targets: missionIds,
|
|
2630
|
+
batchCount: missionIds.length > 1 ? missionIds.length : null,
|
|
2631
|
+
});
|
|
2812
2632
|
|
|
2813
2633
|
const operation = "mission-archive";
|
|
2814
2634
|
const idempotencyKey = resolveProjectMutationIdempotencyKey({
|
|
@@ -2822,28 +2642,21 @@ async function runMissionArchiveCommand(args) {
|
|
|
2822
2642
|
return;
|
|
2823
2643
|
}
|
|
2824
2644
|
|
|
2825
|
-
const timeoutMs = resolveTimeoutMs(args);
|
|
2826
|
-
const apiBase = resolveApiBase(args);
|
|
2827
|
-
const endpoint = "/project-assistant/mission-archive";
|
|
2828
|
-
|
|
2829
|
-
|
|
2830
|
-
|
|
2831
|
-
|
|
2832
|
-
|
|
2833
|
-
});
|
|
2834
|
-
|
|
2835
|
-
let data;
|
|
2836
|
-
try {
|
|
2837
|
-
data = await createMissionArchiveUpdate({
|
|
2838
|
-
apiBase,
|
|
2645
|
+
const timeoutMs = resolveTimeoutMs(args);
|
|
2646
|
+
const apiBase = resolveApiBase(args);
|
|
2647
|
+
const endpoint = "/project-assistant/mission-archive";
|
|
2648
|
+
|
|
2649
|
+
let data;
|
|
2650
|
+
try {
|
|
2651
|
+
data = await createMissionArchiveUpdate({
|
|
2652
|
+
apiBase,
|
|
2839
2653
|
key,
|
|
2840
2654
|
timeoutMs,
|
|
2841
2655
|
endpoint,
|
|
2842
|
-
payload,
|
|
2843
|
-
idempotencyKey,
|
|
2844
|
-
clientSessionId,
|
|
2845
|
-
|
|
2846
|
-
});
|
|
2656
|
+
payload,
|
|
2657
|
+
idempotencyKey,
|
|
2658
|
+
clientSessionId,
|
|
2659
|
+
});
|
|
2847
2660
|
} catch (err) {
|
|
2848
2661
|
if (err?.name === "AbortError") {
|
|
2849
2662
|
console.error(`Request timed out after ${timeoutMs}ms`);
|
|
@@ -2924,9 +2737,9 @@ async function runUpdateTeam(args) {
|
|
|
2924
2737
|
process.exit(1);
|
|
2925
2738
|
}
|
|
2926
2739
|
|
|
2927
|
-
|
|
2928
|
-
content: await resolveTeamUpdateContent(args),
|
|
2929
|
-
};
|
|
2740
|
+
let payload = {
|
|
2741
|
+
content: await resolveTeamUpdateContent(args),
|
|
2742
|
+
};
|
|
2930
2743
|
|
|
2931
2744
|
if (args["print-context"] || args.printContext || args["dry-run"] || args.dryRun) {
|
|
2932
2745
|
console.log(JSON.stringify(payload, null, 2));
|
|
@@ -2934,31 +2747,30 @@ async function runUpdateTeam(args) {
|
|
|
2934
2747
|
}
|
|
2935
2748
|
|
|
2936
2749
|
const timeoutMs = resolveTimeoutMs(args);
|
|
2937
|
-
const apiBase = resolveApiBase(args);
|
|
2938
|
-
const clientSessionId = firstNonEmptyString(args["client-session-id"], args.clientSessionId, args.client_session_id);
|
|
2939
|
-
if (clientSessionId) payload.client_session_id = clientSessionId;
|
|
2940
|
-
|
|
2941
|
-
args,
|
|
2942
|
-
operation: "update_team",
|
|
2943
|
-
payload,
|
|
2944
|
-
});
|
|
2945
|
-
const writeApproval = requireWriteApproval(args, payload, {
|
|
2946
|
-
operation: "update_team",
|
|
2750
|
+
const apiBase = resolveApiBase(args);
|
|
2751
|
+
const clientSessionId = firstNonEmptyString(args["client-session-id"], args.clientSessionId, args.client_session_id);
|
|
2752
|
+
if (clientSessionId) payload.client_session_id = clientSessionId;
|
|
2753
|
+
payload = withWriteApproval(args, payload, {
|
|
2947
2754
|
artifactKind: "markdown",
|
|
2755
|
+
targets: ["project"],
|
|
2948
2756
|
});
|
|
2949
|
-
|
|
2950
|
-
|
|
2951
|
-
|
|
2952
|
-
|
|
2757
|
+
const idempotencyKey = resolveProjectMutationIdempotencyKey({
|
|
2758
|
+
args,
|
|
2759
|
+
operation: "update_team",
|
|
2760
|
+
payload,
|
|
2761
|
+
});
|
|
2762
|
+
|
|
2763
|
+
let data;
|
|
2764
|
+
try {
|
|
2765
|
+
data = await postSuggestionsMutation({
|
|
2953
2766
|
apiBase,
|
|
2954
2767
|
key,
|
|
2955
2768
|
payload,
|
|
2956
2769
|
timeoutMs,
|
|
2957
|
-
endpoint: "/project-assistant/project-comment",
|
|
2958
|
-
idempotencyKey,
|
|
2959
|
-
clientSessionId,
|
|
2960
|
-
|
|
2961
|
-
});
|
|
2770
|
+
endpoint: "/project-assistant/project-comment",
|
|
2771
|
+
idempotencyKey,
|
|
2772
|
+
clientSessionId,
|
|
2773
|
+
});
|
|
2962
2774
|
} catch (err) {
|
|
2963
2775
|
if (err?.name === "AbortError") {
|
|
2964
2776
|
console.error(`Request timed out after ${timeoutMs}ms`);
|
|
@@ -2997,10 +2809,10 @@ async function runUpdateOwner(args) {
|
|
|
2997
2809
|
process.exit(1);
|
|
2998
2810
|
}
|
|
2999
2811
|
|
|
3000
|
-
|
|
3001
|
-
subject,
|
|
3002
|
-
body_markdown: await resolveOwnerUpdateBody(args),
|
|
3003
|
-
};
|
|
2812
|
+
let payload = {
|
|
2813
|
+
subject,
|
|
2814
|
+
body_markdown: await resolveOwnerUpdateBody(args),
|
|
2815
|
+
};
|
|
3004
2816
|
|
|
3005
2817
|
if (args["print-context"] || args.printContext || args["dry-run"] || args.dryRun) {
|
|
3006
2818
|
console.log(JSON.stringify(payload, null, 2));
|
|
@@ -3008,31 +2820,30 @@ async function runUpdateOwner(args) {
|
|
|
3008
2820
|
}
|
|
3009
2821
|
|
|
3010
2822
|
const timeoutMs = resolveTimeoutMs(args);
|
|
3011
|
-
const apiBase = resolveApiBase(args);
|
|
3012
|
-
const clientSessionId = firstNonEmptyString(args["client-session-id"], args.clientSessionId, args.client_session_id);
|
|
3013
|
-
if (clientSessionId) payload.client_session_id = clientSessionId;
|
|
3014
|
-
|
|
3015
|
-
|
|
3016
|
-
|
|
3017
|
-
payload,
|
|
3018
|
-
});
|
|
3019
|
-
const writeApproval = requireWriteApproval(args, payload, {
|
|
3020
|
-
operation: "update_owner",
|
|
3021
|
-
artifactKind: "markdown",
|
|
2823
|
+
const apiBase = resolveApiBase(args);
|
|
2824
|
+
const clientSessionId = firstNonEmptyString(args["client-session-id"], args.clientSessionId, args.client_session_id);
|
|
2825
|
+
if (clientSessionId) payload.client_session_id = clientSessionId;
|
|
2826
|
+
payload = withWriteApproval(args, payload, {
|
|
2827
|
+
artifactKind: "markdown",
|
|
2828
|
+
targets: ["project"],
|
|
3022
2829
|
});
|
|
3023
|
-
|
|
3024
|
-
|
|
3025
|
-
|
|
2830
|
+
const idempotencyKey = resolveProjectMutationIdempotencyKey({
|
|
2831
|
+
args,
|
|
2832
|
+
operation: "update_owner",
|
|
2833
|
+
payload,
|
|
2834
|
+
});
|
|
2835
|
+
|
|
2836
|
+
let data;
|
|
2837
|
+
try {
|
|
3026
2838
|
data = await postSuggestionsMutation({
|
|
3027
2839
|
apiBase,
|
|
3028
2840
|
key,
|
|
3029
2841
|
payload,
|
|
3030
2842
|
timeoutMs,
|
|
3031
|
-
endpoint: "/project-assistant/update-owner",
|
|
3032
|
-
idempotencyKey,
|
|
3033
|
-
clientSessionId,
|
|
3034
|
-
|
|
3035
|
-
});
|
|
2843
|
+
endpoint: "/project-assistant/update-owner",
|
|
2844
|
+
idempotencyKey,
|
|
2845
|
+
clientSessionId,
|
|
2846
|
+
});
|
|
3036
2847
|
} catch (err) {
|
|
3037
2848
|
if (err?.name === "AbortError") {
|
|
3038
2849
|
console.error(`Request timed out after ${timeoutMs}ms`);
|
|
@@ -3079,11 +2890,11 @@ async function runUpdateClient(args) {
|
|
|
3079
2890
|
process.exit(1);
|
|
3080
2891
|
}
|
|
3081
2892
|
|
|
3082
|
-
|
|
3083
|
-
subject,
|
|
3084
|
-
body_markdown: await resolveClientUpdateBody(args),
|
|
3085
|
-
target_contact_ids: resolveTargetContactIds(args),
|
|
3086
|
-
};
|
|
2893
|
+
let payload = {
|
|
2894
|
+
subject,
|
|
2895
|
+
body_markdown: await resolveClientUpdateBody(args),
|
|
2896
|
+
target_contact_ids: resolveTargetContactIds(args),
|
|
2897
|
+
};
|
|
3087
2898
|
|
|
3088
2899
|
if (args["print-context"] || args.printContext || args["dry-run"] || args.dryRun) {
|
|
3089
2900
|
console.log(JSON.stringify(payload, null, 2));
|
|
@@ -3091,31 +2902,30 @@ async function runUpdateClient(args) {
|
|
|
3091
2902
|
}
|
|
3092
2903
|
|
|
3093
2904
|
const timeoutMs = resolveTimeoutMs(args);
|
|
3094
|
-
const apiBase = resolveApiBase(args);
|
|
3095
|
-
const clientSessionId = firstNonEmptyString(args["client-session-id"], args.clientSessionId, args.client_session_id);
|
|
3096
|
-
if (clientSessionId) payload.client_session_id = clientSessionId;
|
|
3097
|
-
|
|
3098
|
-
args,
|
|
3099
|
-
operation: "update_client",
|
|
3100
|
-
payload,
|
|
3101
|
-
});
|
|
3102
|
-
const writeApproval = requireWriteApproval(args, payload, {
|
|
3103
|
-
operation: "update_client",
|
|
2905
|
+
const apiBase = resolveApiBase(args);
|
|
2906
|
+
const clientSessionId = firstNonEmptyString(args["client-session-id"], args.clientSessionId, args.client_session_id);
|
|
2907
|
+
if (clientSessionId) payload.client_session_id = clientSessionId;
|
|
2908
|
+
payload = withWriteApproval(args, payload, {
|
|
3104
2909
|
artifactKind: "markdown",
|
|
2910
|
+
targets: ["project"],
|
|
3105
2911
|
});
|
|
3106
|
-
|
|
3107
|
-
|
|
3108
|
-
|
|
2912
|
+
const idempotencyKey = resolveProjectMutationIdempotencyKey({
|
|
2913
|
+
args,
|
|
2914
|
+
operation: "update_client",
|
|
2915
|
+
payload,
|
|
2916
|
+
});
|
|
2917
|
+
|
|
2918
|
+
let data;
|
|
2919
|
+
try {
|
|
3109
2920
|
data = await postSuggestionsMutation({
|
|
3110
2921
|
apiBase,
|
|
3111
2922
|
key,
|
|
3112
2923
|
payload,
|
|
3113
2924
|
timeoutMs,
|
|
3114
|
-
endpoint: "/project-assistant/client-update-drafts",
|
|
3115
|
-
idempotencyKey,
|
|
3116
|
-
clientSessionId,
|
|
3117
|
-
|
|
3118
|
-
});
|
|
2925
|
+
endpoint: "/project-assistant/client-update-drafts",
|
|
2926
|
+
idempotencyKey,
|
|
2927
|
+
clientSessionId,
|
|
2928
|
+
});
|
|
3119
2929
|
} catch (err) {
|
|
3120
2930
|
if (err?.name === "AbortError") {
|
|
3121
2931
|
console.error(`Request timed out after ${timeoutMs}ms`);
|
|
@@ -3207,23 +3017,138 @@ function stringifyYaml(value) {
|
|
|
3207
3017
|
return `${JSON.stringify(value, null, 2)}\n`;
|
|
3208
3018
|
}
|
|
3209
3019
|
|
|
3210
|
-
function stableJsonStringify(value) {
|
|
3211
|
-
if (Array.isArray(value)) {
|
|
3212
|
-
return `[${value.map((item) => stableJsonStringify(item)).join(",")}]`;
|
|
3213
|
-
}
|
|
3020
|
+
function stableJsonStringify(value) {
|
|
3021
|
+
if (Array.isArray(value)) {
|
|
3022
|
+
return `[${value.map((item) => stableJsonStringify(item)).join(",")}]`;
|
|
3023
|
+
}
|
|
3214
3024
|
if (value && typeof value === "object") {
|
|
3215
3025
|
const entries = Object.keys(value)
|
|
3216
3026
|
.sort()
|
|
3217
3027
|
.map((key) => `${JSON.stringify(key)}:${stableJsonStringify(value[key])}`);
|
|
3218
3028
|
return `{${entries.join(",")}}`;
|
|
3219
|
-
}
|
|
3220
|
-
return JSON.stringify(value);
|
|
3221
|
-
}
|
|
3222
|
-
|
|
3223
|
-
function
|
|
3224
|
-
|
|
3225
|
-
|
|
3226
|
-
|
|
3029
|
+
}
|
|
3030
|
+
return JSON.stringify(value);
|
|
3031
|
+
}
|
|
3032
|
+
|
|
3033
|
+
function pythonJsonStringify(value) {
|
|
3034
|
+
if (Array.isArray(value)) {
|
|
3035
|
+
return `[${value.map((item) => pythonJsonStringify(item)).join(", ")}]`;
|
|
3036
|
+
}
|
|
3037
|
+
if (value && typeof value === "object") {
|
|
3038
|
+
const entries = Object.keys(value)
|
|
3039
|
+
.filter((key) => value[key] !== undefined)
|
|
3040
|
+
.sort()
|
|
3041
|
+
.map((key) => `${jsonStringEnsureAscii(key)}: ${pythonJsonStringify(value[key])}`);
|
|
3042
|
+
return `{${entries.join(", ")}}`;
|
|
3043
|
+
}
|
|
3044
|
+
if (typeof value === "string") return jsonStringEnsureAscii(value);
|
|
3045
|
+
if (value === undefined) return "null";
|
|
3046
|
+
return JSON.stringify(value);
|
|
3047
|
+
}
|
|
3048
|
+
|
|
3049
|
+
function jsonStringEnsureAscii(value) {
|
|
3050
|
+
return JSON.stringify(String(value)).replace(/[^\x00-\x7F]/g, (char) => {
|
|
3051
|
+
const code = char.charCodeAt(0);
|
|
3052
|
+
return `\\u${code.toString(16).padStart(4, "0")}`;
|
|
3053
|
+
});
|
|
3054
|
+
}
|
|
3055
|
+
|
|
3056
|
+
function canonicalizeWritePayload(value) {
|
|
3057
|
+
if (Array.isArray(value)) {
|
|
3058
|
+
return value.map((item) => canonicalizeWritePayload(item));
|
|
3059
|
+
}
|
|
3060
|
+
if (value && typeof value === "object") {
|
|
3061
|
+
const next = {};
|
|
3062
|
+
for (const key of Object.keys(value)) {
|
|
3063
|
+
if (key === "write_approval" || key === "client_session_id") continue;
|
|
3064
|
+
if (value[key] === undefined) continue;
|
|
3065
|
+
next[key] = canonicalizeWritePayload(value[key]);
|
|
3066
|
+
}
|
|
3067
|
+
return next;
|
|
3068
|
+
}
|
|
3069
|
+
return value;
|
|
3070
|
+
}
|
|
3071
|
+
|
|
3072
|
+
function projectWritePayloadHash(payload) {
|
|
3073
|
+
const canonical = canonicalizeWritePayload(payload || {});
|
|
3074
|
+
return createHash("sha256").update(pythonJsonStringify(canonical)).digest("hex");
|
|
3075
|
+
}
|
|
3076
|
+
|
|
3077
|
+
function approvalArtifactKind(artifactPath, fallback = "yaml") {
|
|
3078
|
+
const ext = path.extname(String(artifactPath || "")).toLowerCase();
|
|
3079
|
+
if (ext === ".md" || ext === ".markdown") return "markdown";
|
|
3080
|
+
if (ext === ".json") return "json";
|
|
3081
|
+
if (ext === ".yml" || ext === ".yaml") return "yaml";
|
|
3082
|
+
return fallback || "yaml";
|
|
3083
|
+
}
|
|
3084
|
+
|
|
3085
|
+
function resolveWriteApprovalArtifact(args) {
|
|
3086
|
+
const artifactPath = firstNonEmptyString(
|
|
3087
|
+
args["approval-artifact"],
|
|
3088
|
+
args.approvalArtifact,
|
|
3089
|
+
args.approval_artifact
|
|
3090
|
+
);
|
|
3091
|
+
if (!artifactPath) {
|
|
3092
|
+
console.error("Missing --approval-artifact for confirmed live Myte write.");
|
|
3093
|
+
process.exit(1);
|
|
3094
|
+
}
|
|
3095
|
+
const absPath = path.resolve(String(artifactPath));
|
|
3096
|
+
if (!fs.existsSync(absPath) || !fs.statSync(absPath).isFile()) {
|
|
3097
|
+
console.error(`Approval artifact not found: ${absPath}`);
|
|
3098
|
+
process.exit(1);
|
|
3099
|
+
}
|
|
3100
|
+
const ext = path.extname(absPath).toLowerCase();
|
|
3101
|
+
if (![".md", ".markdown", ".yml", ".yaml", ".json"].includes(ext)) {
|
|
3102
|
+
console.error("Approval artifact must be a local .md, .yml, .yaml, or .json file.");
|
|
3103
|
+
process.exit(1);
|
|
3104
|
+
}
|
|
3105
|
+
return { displayPath: String(artifactPath), absPath };
|
|
3106
|
+
}
|
|
3107
|
+
|
|
3108
|
+
function approvalTargets(values) {
|
|
3109
|
+
return uniqueNormalizedStrings(Array.isArray(values) ? values : [values]);
|
|
3110
|
+
}
|
|
3111
|
+
|
|
3112
|
+
function withWriteApproval(args, payload, { artifactKind = "yaml", targets = [], batchCount = null } = {}) {
|
|
3113
|
+
const confirmed = Boolean(args["confirm-write"] || args.confirmWrite || args.confirm_write);
|
|
3114
|
+
if (!confirmed) return payload;
|
|
3115
|
+
const { displayPath } = resolveWriteApprovalArtifact(args);
|
|
3116
|
+
const nextPayload = { ...(payload || {}) };
|
|
3117
|
+
const normalizedTargets = approvalTargets(targets);
|
|
3118
|
+
const approval = {
|
|
3119
|
+
approved: true,
|
|
3120
|
+
source: "explicit_user_approval",
|
|
3121
|
+
artifact_path: displayPath,
|
|
3122
|
+
artifact_kind: approvalArtifactKind(displayPath, artifactKind),
|
|
3123
|
+
payload_sha256: projectWritePayloadHash(nextPayload),
|
|
3124
|
+
};
|
|
3125
|
+
if (normalizedTargets.length) approval.targets = normalizedTargets;
|
|
3126
|
+
if (batchCount !== undefined && batchCount !== null) approval.batch_count = Number(batchCount);
|
|
3127
|
+
nextPayload.write_approval = approval;
|
|
3128
|
+
return nextPayload;
|
|
3129
|
+
}
|
|
3130
|
+
|
|
3131
|
+
function suggestionWriteTargets(items) {
|
|
3132
|
+
return (Array.isArray(items) ? items : [])
|
|
3133
|
+
.map((item, index) => {
|
|
3134
|
+
if (!item || typeof item !== "object") return `index:${index}`;
|
|
3135
|
+
const changeType = String(item.change_type || item.action || "suggestion").trim().toLowerCase() || "suggestion";
|
|
3136
|
+
const changeSet = item.change_set && typeof item.change_set === "object" ? item.change_set : item;
|
|
3137
|
+
return firstNonEmptyString(
|
|
3138
|
+
item.suggestion_id,
|
|
3139
|
+
item.mission_id,
|
|
3140
|
+
item.client_ref,
|
|
3141
|
+
changeSet.title ? `${changeType}:${String(changeSet.title).slice(0, 80)}` : "",
|
|
3142
|
+
`index:${index}`
|
|
3143
|
+
);
|
|
3144
|
+
})
|
|
3145
|
+
.filter(Boolean);
|
|
3146
|
+
}
|
|
3147
|
+
|
|
3148
|
+
function parseYaml(text) {
|
|
3149
|
+
const raw = String(text || "").trim();
|
|
3150
|
+
if (!raw) return null;
|
|
3151
|
+
if (raw.startsWith("{") || raw.startsWith("[")) {
|
|
3227
3152
|
return JSON.parse(raw);
|
|
3228
3153
|
}
|
|
3229
3154
|
return parseSimpleYaml(raw);
|
|
@@ -4486,44 +4411,41 @@ async function fetchSuggestionsSyncSnapshot({ apiBase, key, timeoutMs, actorScop
|
|
|
4486
4411
|
return body.data || {};
|
|
4487
4412
|
}
|
|
4488
4413
|
|
|
4489
|
-
async function createProjectSuggestions({ apiBase, key, timeoutMs, payload, idempotencyKey, clientSessionId
|
|
4490
|
-
return postSuggestionsMutation({
|
|
4491
|
-
apiBase,
|
|
4492
|
-
key,
|
|
4493
|
-
timeoutMs,
|
|
4494
|
-
endpoint: "/project-assistant/suggestions",
|
|
4495
|
-
payload,
|
|
4496
|
-
idempotencyKey,
|
|
4497
|
-
clientSessionId,
|
|
4498
|
-
|
|
4499
|
-
|
|
4500
|
-
|
|
4501
|
-
|
|
4502
|
-
|
|
4503
|
-
|
|
4504
|
-
|
|
4505
|
-
|
|
4506
|
-
|
|
4507
|
-
|
|
4508
|
-
|
|
4509
|
-
|
|
4510
|
-
|
|
4511
|
-
|
|
4512
|
-
|
|
4513
|
-
}
|
|
4514
|
-
|
|
4515
|
-
|
|
4516
|
-
|
|
4517
|
-
|
|
4518
|
-
|
|
4519
|
-
|
|
4520
|
-
|
|
4521
|
-
|
|
4522
|
-
|
|
4523
|
-
|
|
4524
|
-
writeApproval,
|
|
4525
|
-
});
|
|
4526
|
-
}
|
|
4414
|
+
async function createProjectSuggestions({ apiBase, key, timeoutMs, payload, idempotencyKey, clientSessionId }) {
|
|
4415
|
+
return postSuggestionsMutation({
|
|
4416
|
+
apiBase,
|
|
4417
|
+
key,
|
|
4418
|
+
timeoutMs,
|
|
4419
|
+
endpoint: "/project-assistant/suggestions",
|
|
4420
|
+
payload,
|
|
4421
|
+
idempotencyKey,
|
|
4422
|
+
clientSessionId,
|
|
4423
|
+
});
|
|
4424
|
+
}
|
|
4425
|
+
|
|
4426
|
+
async function reviseProjectSuggestions({ apiBase, key, timeoutMs, payload, idempotencyKey, clientSessionId }) {
|
|
4427
|
+
return postSuggestionsMutation({
|
|
4428
|
+
apiBase,
|
|
4429
|
+
key,
|
|
4430
|
+
timeoutMs,
|
|
4431
|
+
endpoint: "/project-assistant/suggestions/revise",
|
|
4432
|
+
payload,
|
|
4433
|
+
idempotencyKey,
|
|
4434
|
+
clientSessionId,
|
|
4435
|
+
});
|
|
4436
|
+
}
|
|
4437
|
+
|
|
4438
|
+
async function reviewProjectSuggestions({ apiBase, key, timeoutMs, payload, idempotencyKey, clientSessionId }) {
|
|
4439
|
+
return postSuggestionsMutation({
|
|
4440
|
+
apiBase,
|
|
4441
|
+
key,
|
|
4442
|
+
timeoutMs,
|
|
4443
|
+
endpoint: "/project-assistant/suggestions/review",
|
|
4444
|
+
payload,
|
|
4445
|
+
idempotencyKey,
|
|
4446
|
+
clientSessionId,
|
|
4447
|
+
});
|
|
4448
|
+
}
|
|
4527
4449
|
|
|
4528
4450
|
async function runCreatePrd(args) {
|
|
4529
4451
|
const key = (process.env.MYTE_API_KEY || process.env.MYTE_PROJECT_API_KEY || "").trim();
|
|
@@ -4630,31 +4552,29 @@ async function runCreatePrd(args) {
|
|
|
4630
4552
|
|
|
4631
4553
|
const clientSessionId = firstNonEmptyString(args["client-session-id"], args.clientSessionId, args.client_session_id);
|
|
4632
4554
|
|
|
4633
|
-
if (payloads.length === 1) {
|
|
4634
|
-
let data;
|
|
4635
|
-
|
|
4636
|
-
if (clientSessionId) payload.client_session_id = clientSessionId;
|
|
4555
|
+
if (payloads.length === 1) {
|
|
4556
|
+
let data;
|
|
4557
|
+
let payload = payloads[0];
|
|
4558
|
+
if (clientSessionId) payload.client_session_id = clientSessionId;
|
|
4559
|
+
payload = withWriteApproval(args, payload, {
|
|
4560
|
+
artifactKind: "markdown",
|
|
4561
|
+
targets: [firstNonEmptyString(payload.client_ref, payload.title, "create-prd")],
|
|
4562
|
+
});
|
|
4637
4563
|
const idempotencyKey = resolveProjectMutationIdempotencyKey({
|
|
4638
4564
|
args,
|
|
4639
4565
|
operation: "create_prd",
|
|
4640
|
-
payload,
|
|
4641
|
-
});
|
|
4642
|
-
|
|
4643
|
-
|
|
4644
|
-
|
|
4645
|
-
|
|
4646
|
-
|
|
4647
|
-
try {
|
|
4648
|
-
data = await postSuggestionsMutation({
|
|
4649
|
-
apiBase,
|
|
4650
|
-
key,
|
|
4651
|
-
payload,
|
|
4566
|
+
payload,
|
|
4567
|
+
});
|
|
4568
|
+
try {
|
|
4569
|
+
data = await postSuggestionsMutation({
|
|
4570
|
+
apiBase,
|
|
4571
|
+
key,
|
|
4572
|
+
payload,
|
|
4652
4573
|
timeoutMs,
|
|
4653
|
-
endpoint: "/project-assistant/create-prd",
|
|
4654
|
-
idempotencyKey,
|
|
4655
|
-
clientSessionId,
|
|
4656
|
-
|
|
4657
|
-
});
|
|
4574
|
+
endpoint: "/project-assistant/create-prd",
|
|
4575
|
+
idempotencyKey,
|
|
4576
|
+
clientSessionId,
|
|
4577
|
+
});
|
|
4658
4578
|
} catch (err) {
|
|
4659
4579
|
if (err?.name === "AbortError") {
|
|
4660
4580
|
console.error(`Request timed out after ${timeoutMs}ms`);
|
|
@@ -4695,32 +4615,29 @@ async function runCreatePrd(args) {
|
|
|
4695
4615
|
failed_count: 0,
|
|
4696
4616
|
items: [],
|
|
4697
4617
|
};
|
|
4698
|
-
|
|
4699
|
-
try {
|
|
4700
|
-
|
|
4701
|
-
if (clientSessionId) payload.client_session_id = clientSessionId;
|
|
4618
|
+
|
|
4619
|
+
try {
|
|
4620
|
+
let payload = { items: payloads };
|
|
4621
|
+
if (clientSessionId) payload.client_session_id = clientSessionId;
|
|
4622
|
+
payload = withWriteApproval(args, payload, {
|
|
4623
|
+
artifactKind: "markdown",
|
|
4624
|
+
targets: payloads.map((item, index) => firstNonEmptyString(item.client_ref, item.title, `index:${index}`)),
|
|
4625
|
+
batchCount: payloads.length,
|
|
4626
|
+
});
|
|
4702
4627
|
const idempotencyKey = resolveProjectMutationIdempotencyKey({
|
|
4703
4628
|
args,
|
|
4704
4629
|
operation: "create_prds",
|
|
4705
|
-
payload,
|
|
4706
|
-
});
|
|
4707
|
-
const
|
|
4708
|
-
|
|
4709
|
-
|
|
4710
|
-
|
|
4711
|
-
|
|
4712
|
-
|
|
4713
|
-
|
|
4714
|
-
|
|
4715
|
-
|
|
4716
|
-
key,
|
|
4717
|
-
payload,
|
|
4718
|
-
timeoutMs,
|
|
4719
|
-
endpoint: "/project-assistant/create-prds",
|
|
4720
|
-
idempotencyKey,
|
|
4721
|
-
clientSessionId,
|
|
4722
|
-
writeApproval,
|
|
4723
|
-
});
|
|
4630
|
+
payload,
|
|
4631
|
+
});
|
|
4632
|
+
const data = await postSuggestionsMutation({
|
|
4633
|
+
apiBase,
|
|
4634
|
+
key,
|
|
4635
|
+
payload,
|
|
4636
|
+
timeoutMs,
|
|
4637
|
+
endpoint: "/project-assistant/create-prds",
|
|
4638
|
+
idempotencyKey,
|
|
4639
|
+
clientSessionId,
|
|
4640
|
+
});
|
|
4724
4641
|
aggregated.project_id = data.project_id || null;
|
|
4725
4642
|
aggregated.created_count = Number(data.created_count || 0);
|
|
4726
4643
|
aggregated.failed_count = Number(data.failed_count || 0);
|
|
@@ -5276,7 +5193,8 @@ async function runFeedbackValidateOrApply(args, mode) {
|
|
|
5276
5193
|
console.error("Missing MYTE_API_KEY (project key) in environment/.env");
|
|
5277
5194
|
process.exit(1);
|
|
5278
5195
|
}
|
|
5279
|
-
const { absPath, payload } = readFeedbackRefinementArtifact(args);
|
|
5196
|
+
const { absPath, payload: artifactPayload } = readFeedbackRefinementArtifact(args);
|
|
5197
|
+
let payload = artifactPayload;
|
|
5280
5198
|
const feedbackId = firstNonEmptyString(args["feedback-id"], args.feedbackId, args.feedback_id, payload.feedback_id);
|
|
5281
5199
|
if (!feedbackId) {
|
|
5282
5200
|
console.error("Feedback refinement artifact is missing feedback_id.");
|
|
@@ -5286,40 +5204,38 @@ async function runFeedbackValidateOrApply(args, mode) {
|
|
|
5286
5204
|
|
|
5287
5205
|
const timeoutMs = resolveTimeoutMs(args);
|
|
5288
5206
|
const apiBase = resolveApiBase(args);
|
|
5289
|
-
const clientSessionId = firstNonEmptyString(
|
|
5207
|
+
const clientSessionId = firstNonEmptyString(
|
|
5290
5208
|
args["client-session-id"],
|
|
5291
5209
|
args.clientSessionId,
|
|
5292
5210
|
args.client_session_id,
|
|
5293
5211
|
payload.client_session_id
|
|
5294
|
-
);
|
|
5212
|
+
);
|
|
5213
|
+
if (mode === "apply") {
|
|
5214
|
+
payload = withWriteApproval(args, payload, {
|
|
5215
|
+
artifactKind: "yaml",
|
|
5216
|
+
targets: [feedbackId],
|
|
5217
|
+
});
|
|
5218
|
+
}
|
|
5295
5219
|
const idempotencyKey = mode === "apply"
|
|
5296
|
-
? resolveProjectMutationIdempotencyKey({
|
|
5297
|
-
args,
|
|
5298
|
-
operation: `feedback_refinement_apply:${feedbackId}`,
|
|
5299
|
-
payload,
|
|
5300
|
-
})
|
|
5301
|
-
: null;
|
|
5302
|
-
|
|
5303
|
-
|
|
5304
|
-
|
|
5305
|
-
|
|
5306
|
-
|
|
5307
|
-
})
|
|
5308
|
-
: null;
|
|
5309
|
-
|
|
5310
|
-
let data;
|
|
5311
|
-
try {
|
|
5312
|
-
data = await postFeedbackRefinement({
|
|
5313
|
-
apiBase,
|
|
5220
|
+
? resolveProjectMutationIdempotencyKey({
|
|
5221
|
+
args,
|
|
5222
|
+
operation: `feedback_refinement_apply:${feedbackId}`,
|
|
5223
|
+
payload,
|
|
5224
|
+
})
|
|
5225
|
+
: null;
|
|
5226
|
+
|
|
5227
|
+
let data;
|
|
5228
|
+
try {
|
|
5229
|
+
data = await postFeedbackRefinement({
|
|
5230
|
+
apiBase,
|
|
5314
5231
|
key,
|
|
5315
5232
|
timeoutMs,
|
|
5316
5233
|
feedbackId,
|
|
5317
5234
|
mode,
|
|
5318
|
-
payload,
|
|
5319
|
-
idempotencyKey,
|
|
5320
|
-
clientSessionId,
|
|
5321
|
-
|
|
5322
|
-
});
|
|
5235
|
+
payload,
|
|
5236
|
+
idempotencyKey,
|
|
5237
|
+
clientSessionId,
|
|
5238
|
+
});
|
|
5323
5239
|
} catch (err) {
|
|
5324
5240
|
if (args.json) {
|
|
5325
5241
|
console.log(JSON.stringify({
|
|
@@ -5364,33 +5280,33 @@ function resolveFeedbackRequestIdArg(args) {
|
|
|
5364
5280
|
return firstNonEmptyString(args["request-id"], args.requestId, args.request_id, args._?.[1]);
|
|
5365
5281
|
}
|
|
5366
5282
|
|
|
5367
|
-
function resolveFeedbackEventIdArg(args) {
|
|
5368
|
-
return firstNonEmptyString(args["event-id"], args.eventId, args.event_id, args._?.[1]);
|
|
5369
|
-
}
|
|
5283
|
+
function resolveFeedbackEventIdArg(args) {
|
|
5284
|
+
return firstNonEmptyString(args["event-id"], args.eventId, args.event_id, args._?.[1]);
|
|
5285
|
+
}
|
|
5370
5286
|
|
|
5371
|
-
function resolveFeedbackVersionIdArg(args) {
|
|
5372
|
-
return firstNonEmptyString(args["version-id"], args.versionId, args.version_id, args._?.[1]);
|
|
5373
|
-
}
|
|
5374
|
-
|
|
5375
|
-
async function resolveFeedbackCommentContent(args, feedbackId) {
|
|
5376
|
-
const explicit = firstNonEmptyString(args.body, args.content, args["body-markdown"], args.bodyMarkdown, args.body_markdown);
|
|
5377
|
-
if (explicit) return explicit;
|
|
5378
|
-
|
|
5379
|
-
const bodyFile = firstNonEmptyString(args["body-file"], args.bodyFile, args.body_file);
|
|
5380
|
-
if (bodyFile) {
|
|
5381
|
-
const bodyPath = resolveInputFile(bodyFile, "Feedback comment body");
|
|
5382
|
-
return fs.readFileSync(bodyPath, "utf8");
|
|
5383
|
-
}
|
|
5384
|
-
|
|
5385
|
-
if (args.stdin) {
|
|
5386
|
-
return readStdinText();
|
|
5387
|
-
}
|
|
5388
|
-
|
|
5389
|
-
const positionals = Array.isArray(args._) ? args._.slice(1) : [];
|
|
5390
|
-
const feedbackIdFromPositional = positionals[0] && String(positionals[0]) === String(feedbackId);
|
|
5391
|
-
const textParts = feedbackIdFromPositional ? positionals.slice(1) : positionals;
|
|
5392
|
-
return textParts.join(" ");
|
|
5393
|
-
}
|
|
5287
|
+
function resolveFeedbackVersionIdArg(args) {
|
|
5288
|
+
return firstNonEmptyString(args["version-id"], args.versionId, args.version_id, args._?.[1]);
|
|
5289
|
+
}
|
|
5290
|
+
|
|
5291
|
+
async function resolveFeedbackCommentContent(args, feedbackId) {
|
|
5292
|
+
const explicit = firstNonEmptyString(args.body, args.content, args["body-markdown"], args.bodyMarkdown, args.body_markdown);
|
|
5293
|
+
if (explicit) return explicit;
|
|
5294
|
+
|
|
5295
|
+
const bodyFile = firstNonEmptyString(args["body-file"], args.bodyFile, args.body_file);
|
|
5296
|
+
if (bodyFile) {
|
|
5297
|
+
const bodyPath = resolveInputFile(bodyFile, "Feedback comment body");
|
|
5298
|
+
return fs.readFileSync(bodyPath, "utf8");
|
|
5299
|
+
}
|
|
5300
|
+
|
|
5301
|
+
if (args.stdin) {
|
|
5302
|
+
return readStdinText();
|
|
5303
|
+
}
|
|
5304
|
+
|
|
5305
|
+
const positionals = Array.isArray(args._) ? args._.slice(1) : [];
|
|
5306
|
+
const feedbackIdFromPositional = positionals[0] && String(positionals[0]) === String(feedbackId);
|
|
5307
|
+
const textParts = feedbackIdFromPositional ? positionals.slice(1) : positionals;
|
|
5308
|
+
return textParts.join(" ");
|
|
5309
|
+
}
|
|
5394
5310
|
|
|
5395
5311
|
function summarizeFeedbackReviewRequestPayload(data) {
|
|
5396
5312
|
const request = data?.request || data || {};
|
|
@@ -5430,7 +5346,8 @@ async function runFeedbackSubmit(args) {
|
|
|
5430
5346
|
console.error("Missing MYTE_API_KEY (project key) in environment/.env");
|
|
5431
5347
|
process.exit(1);
|
|
5432
5348
|
}
|
|
5433
|
-
const { absPath, payload } = readFeedbackRefinementArtifact(args);
|
|
5349
|
+
const { absPath, payload: artifactPayload } = readFeedbackRefinementArtifact(args);
|
|
5350
|
+
let payload = artifactPayload;
|
|
5434
5351
|
const feedbackId = firstNonEmptyString(args["feedback-id"], args.feedbackId, args.feedback_id, payload.feedback_id);
|
|
5435
5352
|
if (!feedbackId) {
|
|
5436
5353
|
console.error("Feedback refinement artifact is missing feedback_id.");
|
|
@@ -5438,35 +5355,33 @@ async function runFeedbackSubmit(args) {
|
|
|
5438
5355
|
}
|
|
5439
5356
|
const timeoutMs = resolveTimeoutMs(args);
|
|
5440
5357
|
const apiBase = resolveApiBase(args);
|
|
5441
|
-
const clientSessionId = firstNonEmptyString(
|
|
5358
|
+
const clientSessionId = firstNonEmptyString(
|
|
5442
5359
|
args["client-session-id"],
|
|
5443
5360
|
args.clientSessionId,
|
|
5444
5361
|
args.client_session_id,
|
|
5445
5362
|
payload.client_session_id
|
|
5446
|
-
);
|
|
5447
|
-
|
|
5448
|
-
args,
|
|
5449
|
-
operation: `feedback_refinement_request_submit:${feedbackId}`,
|
|
5450
|
-
payload,
|
|
5451
|
-
});
|
|
5452
|
-
const writeApproval = requireWriteApproval(args, payload, {
|
|
5453
|
-
operation: `feedback_refinement_request_submit:${feedbackId}`,
|
|
5363
|
+
);
|
|
5364
|
+
payload = withWriteApproval(args, payload, {
|
|
5454
5365
|
artifactKind: "yaml",
|
|
5455
5366
|
targets: [feedbackId],
|
|
5456
5367
|
});
|
|
5457
|
-
|
|
5458
|
-
|
|
5459
|
-
|
|
5460
|
-
|
|
5368
|
+
const idempotencyKey = resolveProjectMutationIdempotencyKey({
|
|
5369
|
+
args,
|
|
5370
|
+
operation: `feedback_refinement_request_submit:${feedbackId}`,
|
|
5371
|
+
payload,
|
|
5372
|
+
});
|
|
5373
|
+
|
|
5374
|
+
let data;
|
|
5375
|
+
try {
|
|
5376
|
+
data = await postFeedbackReviewSubmission({
|
|
5461
5377
|
apiBase,
|
|
5462
5378
|
key,
|
|
5463
5379
|
timeoutMs,
|
|
5464
5380
|
feedbackId,
|
|
5465
|
-
payload,
|
|
5466
|
-
idempotencyKey,
|
|
5467
|
-
clientSessionId,
|
|
5468
|
-
|
|
5469
|
-
});
|
|
5381
|
+
payload,
|
|
5382
|
+
idempotencyKey,
|
|
5383
|
+
clientSessionId,
|
|
5384
|
+
});
|
|
5470
5385
|
} catch (err) {
|
|
5471
5386
|
if (args.json) {
|
|
5472
5387
|
console.log(JSON.stringify({ ok: false, status: err?.status || null, message: err?.message || String(err), data: err?.data || null, artifact_path: absPath }, null, 2));
|
|
@@ -5507,39 +5422,38 @@ async function runFeedbackRevise(args) {
|
|
|
5507
5422
|
console.error("Missing --request-id.");
|
|
5508
5423
|
process.exit(1);
|
|
5509
5424
|
}
|
|
5510
|
-
const { absPath, payload } = readFeedbackRefinementArtifact(args);
|
|
5425
|
+
const { absPath, payload: artifactPayload } = readFeedbackRefinementArtifact(args);
|
|
5426
|
+
let payload = artifactPayload;
|
|
5511
5427
|
const timeoutMs = resolveTimeoutMs(args);
|
|
5512
5428
|
const apiBase = resolveApiBase(args);
|
|
5513
|
-
const clientSessionId = firstNonEmptyString(
|
|
5429
|
+
const clientSessionId = firstNonEmptyString(
|
|
5514
5430
|
args["client-session-id"],
|
|
5515
5431
|
args.clientSessionId,
|
|
5516
5432
|
args.client_session_id,
|
|
5517
5433
|
payload.client_session_id
|
|
5518
|
-
);
|
|
5519
|
-
|
|
5520
|
-
args,
|
|
5521
|
-
operation: `feedback_refinement_request_revise:${requestId}`,
|
|
5522
|
-
payload,
|
|
5523
|
-
});
|
|
5524
|
-
const writeApproval = requireWriteApproval(args, payload, {
|
|
5525
|
-
operation: `feedback_refinement_request_revise:${requestId}`,
|
|
5434
|
+
);
|
|
5435
|
+
payload = withWriteApproval(args, payload, {
|
|
5526
5436
|
artifactKind: "yaml",
|
|
5527
5437
|
targets: [requestId],
|
|
5528
5438
|
});
|
|
5529
|
-
|
|
5530
|
-
|
|
5531
|
-
|
|
5532
|
-
|
|
5439
|
+
const idempotencyKey = resolveProjectMutationIdempotencyKey({
|
|
5440
|
+
args,
|
|
5441
|
+
operation: `feedback_refinement_request_revise:${requestId}`,
|
|
5442
|
+
payload,
|
|
5443
|
+
});
|
|
5444
|
+
|
|
5445
|
+
let data;
|
|
5446
|
+
try {
|
|
5447
|
+
data = await postFeedbackReviewRequestMutation({
|
|
5533
5448
|
apiBase,
|
|
5534
5449
|
key,
|
|
5535
5450
|
timeoutMs,
|
|
5536
5451
|
requestId,
|
|
5537
5452
|
endpointAction: "revise",
|
|
5538
|
-
payload,
|
|
5539
|
-
idempotencyKey,
|
|
5540
|
-
clientSessionId,
|
|
5541
|
-
|
|
5542
|
-
});
|
|
5453
|
+
payload,
|
|
5454
|
+
idempotencyKey,
|
|
5455
|
+
clientSessionId,
|
|
5456
|
+
});
|
|
5543
5457
|
} catch (err) {
|
|
5544
5458
|
if (args.json) {
|
|
5545
5459
|
console.log(JSON.stringify({ ok: false, status: err?.status || null, message: err?.message || String(err), data: err?.data || null, artifact_path: absPath }, null, 2));
|
|
@@ -5656,41 +5570,36 @@ async function runFeedbackReviewDecision(args) {
|
|
|
5656
5570
|
process.exit(1);
|
|
5657
5571
|
}
|
|
5658
5572
|
const reason = firstNonEmptyString(args.reason, args["review-note"], args.reviewNote, args.review_note);
|
|
5659
|
-
|
|
5660
|
-
...(isPlainObject(filePayload) && !Array.isArray(filePayload) ? filePayload : {}),
|
|
5661
|
-
items,
|
|
5662
|
-
action,
|
|
5663
|
-
reason: reason || undefined,
|
|
5664
|
-
};
|
|
5665
|
-
|
|
5666
|
-
const apiBase = resolveApiBase(args);
|
|
5667
|
-
const clientSessionId = firstNonEmptyString(args["client-session-id"], args.clientSessionId, args.client_session_id, payload.client_session_id);
|
|
5668
|
-
const idempotencyKey = resolveProjectMutationIdempotencyKey({
|
|
5669
|
-
args,
|
|
5670
|
-
operation: `feedback_review_batch:${action}:${items.map((item) => item.request_id || item.id || "").join(",")}`,
|
|
5671
|
-
payload,
|
|
5672
|
-
});
|
|
5673
|
-
const requestTargets = items
|
|
5674
|
-
.map((item, index) => firstNonEmptyString(item.request_id, item.id, item._id) || `index:${index}`)
|
|
5675
|
-
.filter(Boolean);
|
|
5676
|
-
const writeApproval = requireWriteApproval(args, payload, {
|
|
5677
|
-
operation: `feedback_review_batch:${action}`,
|
|
5573
|
+
let payload = {
|
|
5574
|
+
...(isPlainObject(filePayload) && !Array.isArray(filePayload) ? filePayload : {}),
|
|
5575
|
+
items,
|
|
5576
|
+
action,
|
|
5577
|
+
reason: reason || undefined,
|
|
5578
|
+
};
|
|
5579
|
+
payload = withWriteApproval(args, payload, {
|
|
5678
5580
|
artifactKind: "yaml",
|
|
5679
|
-
targets:
|
|
5581
|
+
targets: items.map((item) => item.request_id || item.id).filter(Boolean),
|
|
5680
5582
|
batchCount: items.length,
|
|
5681
5583
|
});
|
|
5682
|
-
|
|
5683
|
-
|
|
5684
|
-
|
|
5685
|
-
|
|
5584
|
+
const timeoutMs = resolveTimeoutMs(args);
|
|
5585
|
+
const apiBase = resolveApiBase(args);
|
|
5586
|
+
const clientSessionId = firstNonEmptyString(args["client-session-id"], args.clientSessionId, args.client_session_id, payload.client_session_id);
|
|
5587
|
+
const idempotencyKey = resolveProjectMutationIdempotencyKey({
|
|
5588
|
+
args,
|
|
5589
|
+
operation: `feedback_review_batch:${action}:${items.map((item) => item.request_id || item.id || "").join(",")}`,
|
|
5590
|
+
payload,
|
|
5591
|
+
});
|
|
5592
|
+
|
|
5593
|
+
let data;
|
|
5594
|
+
try {
|
|
5595
|
+
data = await postFeedbackBatchReviewMutation({
|
|
5686
5596
|
apiBase,
|
|
5687
5597
|
key,
|
|
5688
5598
|
timeoutMs,
|
|
5689
|
-
payload,
|
|
5690
|
-
idempotencyKey,
|
|
5691
|
-
clientSessionId,
|
|
5692
|
-
|
|
5693
|
-
});
|
|
5599
|
+
payload,
|
|
5600
|
+
idempotencyKey,
|
|
5601
|
+
clientSessionId,
|
|
5602
|
+
});
|
|
5694
5603
|
} catch (err) {
|
|
5695
5604
|
if (args.json) {
|
|
5696
5605
|
console.log(JSON.stringify({ ok: false, status: err?.status || null, message: err?.message || String(err), data: err?.data || null }, null, 2));
|
|
@@ -5717,8 +5626,8 @@ async function runFeedbackReviewDecision(args) {
|
|
|
5717
5626
|
process.exit(1);
|
|
5718
5627
|
}
|
|
5719
5628
|
|
|
5720
|
-
let payload;
|
|
5721
|
-
try {
|
|
5629
|
+
let payload;
|
|
5630
|
+
try {
|
|
5722
5631
|
payload = filePayload && !Array.isArray(filePayload?.items)
|
|
5723
5632
|
? buildFeedbackReviewDecisionPayload({ ...args, file: "" }, action)
|
|
5724
5633
|
: buildFeedbackReviewDecisionPayload(args, action);
|
|
@@ -5729,35 +5638,33 @@ async function runFeedbackReviewDecision(args) {
|
|
|
5729
5638
|
console.error(err?.message || err);
|
|
5730
5639
|
process.exit(1);
|
|
5731
5640
|
}
|
|
5732
|
-
const endpointAction = action === "request_changes" ? "request-changes" : action === "cancel" ? "cancel" : "review";
|
|
5733
|
-
|
|
5734
|
-
const apiBase = resolveApiBase(args);
|
|
5735
|
-
const clientSessionId = firstNonEmptyString(args["client-session-id"], args.clientSessionId, args.client_session_id, payload.client_session_id);
|
|
5736
|
-
const operationAction = action === "request_changes" ? "request_changes" : action;
|
|
5737
|
-
const idempotencyKey = resolveProjectMutationIdempotencyKey({
|
|
5738
|
-
args,
|
|
5739
|
-
operation: `feedback_review_request_${operationAction}:${requestId}`,
|
|
5740
|
-
payload,
|
|
5741
|
-
});
|
|
5742
|
-
const writeApproval = requireWriteApproval(args, payload, {
|
|
5743
|
-
operation: `feedback_review_request_${operationAction}:${requestId}`,
|
|
5641
|
+
const endpointAction = action === "request_changes" ? "request-changes" : action === "cancel" ? "cancel" : "review";
|
|
5642
|
+
payload = withWriteApproval(args, payload, {
|
|
5744
5643
|
artifactKind: "yaml",
|
|
5745
5644
|
targets: [requestId],
|
|
5746
5645
|
});
|
|
5747
|
-
|
|
5748
|
-
|
|
5749
|
-
|
|
5750
|
-
|
|
5646
|
+
const timeoutMs = resolveTimeoutMs(args);
|
|
5647
|
+
const apiBase = resolveApiBase(args);
|
|
5648
|
+
const clientSessionId = firstNonEmptyString(args["client-session-id"], args.clientSessionId, args.client_session_id, payload.client_session_id);
|
|
5649
|
+
const operationAction = action === "request_changes" ? "request_changes" : action;
|
|
5650
|
+
const idempotencyKey = resolveProjectMutationIdempotencyKey({
|
|
5651
|
+
args,
|
|
5652
|
+
operation: `feedback_review_request_${operationAction}:${requestId}`,
|
|
5653
|
+
payload,
|
|
5654
|
+
});
|
|
5655
|
+
|
|
5656
|
+
let data;
|
|
5657
|
+
try {
|
|
5658
|
+
data = await postFeedbackReviewRequestMutation({
|
|
5751
5659
|
apiBase,
|
|
5752
5660
|
key,
|
|
5753
5661
|
timeoutMs,
|
|
5754
5662
|
requestId,
|
|
5755
5663
|
endpointAction,
|
|
5756
|
-
payload,
|
|
5757
|
-
idempotencyKey,
|
|
5758
|
-
clientSessionId,
|
|
5759
|
-
|
|
5760
|
-
});
|
|
5664
|
+
payload,
|
|
5665
|
+
idempotencyKey,
|
|
5666
|
+
clientSessionId,
|
|
5667
|
+
});
|
|
5761
5668
|
} catch (err) {
|
|
5762
5669
|
if (args.json) {
|
|
5763
5670
|
console.log(JSON.stringify({ ok: false, status: err?.status || null, message: err?.message || String(err), data: err?.data || null }, null, 2));
|
|
@@ -5777,7 +5684,7 @@ async function runFeedbackReviewDecision(args) {
|
|
|
5777
5684
|
if (postSync?.error) console.error(`Feedback sync warning: ${postSync.error}`);
|
|
5778
5685
|
}
|
|
5779
5686
|
|
|
5780
|
-
async function runFeedbackMove(args) {
|
|
5687
|
+
async function runFeedbackMove(args) {
|
|
5781
5688
|
const key = getProjectApiKey();
|
|
5782
5689
|
if (!key) {
|
|
5783
5690
|
console.error("Missing MYTE_API_KEY (project key) in environment/.env");
|
|
@@ -5795,43 +5702,41 @@ async function runFeedbackMove(args) {
|
|
|
5795
5702
|
process.exit(1);
|
|
5796
5703
|
}
|
|
5797
5704
|
const fromState = firstNonEmptyString(args["from-state"], args.fromState, args.from_state) || undefined;
|
|
5798
|
-
|
|
5799
|
-
to_state: toState,
|
|
5800
|
-
reason: firstNonEmptyString(args.reason) || undefined,
|
|
5801
|
-
};
|
|
5705
|
+
let payload = {
|
|
5706
|
+
to_state: toState,
|
|
5707
|
+
reason: firstNonEmptyString(args.reason) || undefined,
|
|
5708
|
+
};
|
|
5802
5709
|
const timeoutMs = resolveTimeoutMs(args);
|
|
5803
5710
|
const apiBase = resolveApiBase(args);
|
|
5804
5711
|
const clientSessionId = firstNonEmptyString(args["client-session-id"], args.clientSessionId, args.client_session_id);
|
|
5805
5712
|
const isBatch = feedbackIds.length > 1 || Boolean(firstNonEmptyString(args["feedback-ids"], args.feedbackIds, args.feedback_ids));
|
|
5806
|
-
if (isBatch) {
|
|
5807
|
-
payload.feedback_ids = feedbackIds;
|
|
5713
|
+
if (isBatch) {
|
|
5714
|
+
payload.feedback_ids = feedbackIds;
|
|
5808
5715
|
if (fromState) {
|
|
5809
5716
|
payload.from_states = Object.fromEntries(feedbackIds.map((id) => [id, fromState]));
|
|
5810
5717
|
}
|
|
5811
5718
|
const batchId = firstNonEmptyString(args["batch-id"], args.batchId, args.batch_id);
|
|
5812
|
-
if (batchId) payload.batch_id = batchId;
|
|
5813
|
-
|
|
5814
|
-
args,
|
|
5815
|
-
operation: `feedback_board_batch_move:${toState}:${feedbackIds.join(",")}`,
|
|
5816
|
-
payload,
|
|
5817
|
-
});
|
|
5818
|
-
const writeApproval = requireWriteApproval(args, payload, {
|
|
5819
|
-
operation: `feedback_board_batch_move:${toState}`,
|
|
5719
|
+
if (batchId) payload.batch_id = batchId;
|
|
5720
|
+
payload = withWriteApproval(args, payload, {
|
|
5820
5721
|
artifactKind: "yaml",
|
|
5821
5722
|
targets: feedbackIds,
|
|
5822
5723
|
batchCount: feedbackIds.length,
|
|
5823
5724
|
});
|
|
5824
|
-
|
|
5825
|
-
|
|
5826
|
-
|
|
5827
|
-
|
|
5828
|
-
|
|
5725
|
+
const idempotencyKey = resolveProjectMutationIdempotencyKey({
|
|
5726
|
+
args,
|
|
5727
|
+
operation: `feedback_board_batch_move:${toState}:${feedbackIds.join(",")}`,
|
|
5728
|
+
payload,
|
|
5729
|
+
});
|
|
5730
|
+
let data;
|
|
5731
|
+
try {
|
|
5732
|
+
data = await postFeedbackBatchBoardMutation({
|
|
5733
|
+
apiBase,
|
|
5734
|
+
key,
|
|
5829
5735
|
timeoutMs,
|
|
5830
|
-
payload,
|
|
5831
|
-
idempotencyKey,
|
|
5832
|
-
clientSessionId,
|
|
5833
|
-
|
|
5834
|
-
});
|
|
5736
|
+
payload,
|
|
5737
|
+
idempotencyKey,
|
|
5738
|
+
clientSessionId,
|
|
5739
|
+
});
|
|
5835
5740
|
} catch (err) {
|
|
5836
5741
|
if (args.json) {
|
|
5837
5742
|
console.log(JSON.stringify({ ok: false, status: err?.status || null, message: err?.message || String(err), data: err?.data || null }, null, 2));
|
|
@@ -5851,32 +5756,30 @@ async function runFeedbackMove(args) {
|
|
|
5851
5756
|
if (postSync?.error) console.error(`Feedback sync warning: ${postSync.error}`);
|
|
5852
5757
|
return;
|
|
5853
5758
|
}
|
|
5854
|
-
|
|
5855
|
-
payload.from_state = fromState;
|
|
5856
|
-
|
|
5857
|
-
args,
|
|
5858
|
-
operation: `feedback_board_move:${feedbackId}`,
|
|
5859
|
-
payload,
|
|
5860
|
-
});
|
|
5861
|
-
const writeApproval = requireWriteApproval(args, payload, {
|
|
5862
|
-
operation: `feedback_board_move:${feedbackId}`,
|
|
5759
|
+
|
|
5760
|
+
payload.from_state = fromState;
|
|
5761
|
+
payload = withWriteApproval(args, payload, {
|
|
5863
5762
|
artifactKind: "yaml",
|
|
5864
5763
|
targets: [feedbackId],
|
|
5865
5764
|
});
|
|
5866
|
-
|
|
5867
|
-
|
|
5868
|
-
|
|
5869
|
-
|
|
5765
|
+
const idempotencyKey = resolveProjectMutationIdempotencyKey({
|
|
5766
|
+
args,
|
|
5767
|
+
operation: `feedback_board_move:${feedbackId}`,
|
|
5768
|
+
payload,
|
|
5769
|
+
});
|
|
5770
|
+
|
|
5771
|
+
let data;
|
|
5772
|
+
try {
|
|
5773
|
+
data = await postFeedbackBoardMutation({
|
|
5870
5774
|
apiBase,
|
|
5871
5775
|
key,
|
|
5872
5776
|
timeoutMs,
|
|
5873
5777
|
feedbackId,
|
|
5874
5778
|
endpoint: "board-move",
|
|
5875
|
-
payload,
|
|
5876
|
-
idempotencyKey,
|
|
5877
|
-
clientSessionId,
|
|
5878
|
-
|
|
5879
|
-
});
|
|
5779
|
+
payload,
|
|
5780
|
+
idempotencyKey,
|
|
5781
|
+
clientSessionId,
|
|
5782
|
+
});
|
|
5880
5783
|
} catch (err) {
|
|
5881
5784
|
if (args.json) {
|
|
5882
5785
|
console.log(JSON.stringify({ ok: false, status: err?.status || null, message: err?.message || String(err), data: err?.data || null }, null, 2));
|
|
@@ -5896,92 +5799,89 @@ async function runFeedbackMove(args) {
|
|
|
5896
5799
|
console.log(`State: ${data.feedback_state || toState}`);
|
|
5897
5800
|
if (data.event?.event_id) console.log(`Event: ${data.event.event_id}`);
|
|
5898
5801
|
if (postSync?.error) console.error(`Feedback sync warning: ${postSync.error}`);
|
|
5899
|
-
}
|
|
5900
|
-
|
|
5901
|
-
async function runFeedbackComment(args) {
|
|
5902
|
-
const key = getProjectApiKey();
|
|
5903
|
-
if (!key) {
|
|
5904
|
-
console.error("Missing MYTE_API_KEY (project key) in environment/.env");
|
|
5905
|
-
process.exit(1);
|
|
5906
|
-
}
|
|
5907
|
-
const feedbackId = resolveFeedbackIdArg(args);
|
|
5908
|
-
if (!feedbackId) {
|
|
5909
|
-
console.error("Missing --feedback-id.");
|
|
5910
|
-
process.exit(1);
|
|
5911
|
-
}
|
|
5912
|
-
|
|
5913
|
-
const content = String(await resolveFeedbackCommentContent(args, feedbackId) || "").trim();
|
|
5914
|
-
if (!content) {
|
|
5915
|
-
console.error("Missing feedback comment body. Use --body, --body-file, --stdin, or positional text.");
|
|
5916
|
-
process.exit(1);
|
|
5917
|
-
}
|
|
5918
|
-
|
|
5919
|
-
|
|
5802
|
+
}
|
|
5803
|
+
|
|
5804
|
+
async function runFeedbackComment(args) {
|
|
5805
|
+
const key = getProjectApiKey();
|
|
5806
|
+
if (!key) {
|
|
5807
|
+
console.error("Missing MYTE_API_KEY (project key) in environment/.env");
|
|
5808
|
+
process.exit(1);
|
|
5809
|
+
}
|
|
5810
|
+
const feedbackId = resolveFeedbackIdArg(args);
|
|
5811
|
+
if (!feedbackId) {
|
|
5812
|
+
console.error("Missing --feedback-id.");
|
|
5813
|
+
process.exit(1);
|
|
5814
|
+
}
|
|
5815
|
+
|
|
5816
|
+
const content = String(await resolveFeedbackCommentContent(args, feedbackId) || "").trim();
|
|
5817
|
+
if (!content) {
|
|
5818
|
+
console.error("Missing feedback comment body. Use --body, --body-file, --stdin, or positional text.");
|
|
5819
|
+
process.exit(1);
|
|
5820
|
+
}
|
|
5821
|
+
|
|
5822
|
+
let payload = { content };
|
|
5920
5823
|
const timeoutMs = resolveTimeoutMs(args);
|
|
5921
5824
|
const apiBase = resolveApiBase(args);
|
|
5922
5825
|
const clientSessionId = firstNonEmptyString(args["client-session-id"], args.clientSessionId, args.client_session_id);
|
|
5923
5826
|
if (clientSessionId) payload.client_session_id = clientSessionId;
|
|
5924
|
-
|
|
5925
|
-
args,
|
|
5926
|
-
operation: `feedback_comment_create:${feedbackId}`,
|
|
5927
|
-
payload,
|
|
5928
|
-
});
|
|
5929
|
-
|
|
5930
|
-
if (args["print-context"] || args.printContext || args["dry-run"] || args.dryRun) {
|
|
5931
|
-
console.log(JSON.stringify(payload, null, 2));
|
|
5932
|
-
return;
|
|
5933
|
-
}
|
|
5934
|
-
|
|
5935
|
-
const writeApproval = requireWriteApproval(args, payload, {
|
|
5936
|
-
operation: `feedback_comment_create:${feedbackId}`,
|
|
5827
|
+
payload = withWriteApproval(args, payload, {
|
|
5937
5828
|
artifactKind: "markdown",
|
|
5938
5829
|
targets: [feedbackId],
|
|
5939
5830
|
});
|
|
5940
|
-
|
|
5941
|
-
|
|
5942
|
-
|
|
5943
|
-
|
|
5944
|
-
|
|
5945
|
-
|
|
5946
|
-
|
|
5947
|
-
|
|
5948
|
-
|
|
5949
|
-
|
|
5950
|
-
|
|
5951
|
-
|
|
5952
|
-
|
|
5953
|
-
|
|
5954
|
-
|
|
5955
|
-
|
|
5956
|
-
|
|
5957
|
-
|
|
5958
|
-
|
|
5959
|
-
|
|
5960
|
-
|
|
5961
|
-
|
|
5962
|
-
|
|
5963
|
-
|
|
5964
|
-
|
|
5965
|
-
|
|
5966
|
-
|
|
5967
|
-
|
|
5968
|
-
|
|
5969
|
-
|
|
5970
|
-
|
|
5971
|
-
|
|
5972
|
-
|
|
5973
|
-
if (
|
|
5974
|
-
|
|
5975
|
-
|
|
5976
|
-
|
|
5977
|
-
|
|
5978
|
-
|
|
5979
|
-
}
|
|
5980
|
-
if (
|
|
5981
|
-
if (
|
|
5982
|
-
}
|
|
5983
|
-
|
|
5984
|
-
|
|
5831
|
+
const idempotencyKey = resolveProjectMutationIdempotencyKey({
|
|
5832
|
+
args,
|
|
5833
|
+
operation: `feedback_comment_create:${feedbackId}`,
|
|
5834
|
+
payload,
|
|
5835
|
+
});
|
|
5836
|
+
|
|
5837
|
+
if (args["print-context"] || args.printContext || args["dry-run"] || args.dryRun) {
|
|
5838
|
+
console.log(JSON.stringify(payload, null, 2));
|
|
5839
|
+
return;
|
|
5840
|
+
}
|
|
5841
|
+
|
|
5842
|
+
let data;
|
|
5843
|
+
try {
|
|
5844
|
+
data = await postFeedbackComment({
|
|
5845
|
+
apiBase,
|
|
5846
|
+
key,
|
|
5847
|
+
timeoutMs,
|
|
5848
|
+
feedbackId,
|
|
5849
|
+
payload,
|
|
5850
|
+
idempotencyKey,
|
|
5851
|
+
clientSessionId,
|
|
5852
|
+
});
|
|
5853
|
+
} catch (err) {
|
|
5854
|
+
if (args.json) {
|
|
5855
|
+
console.log(JSON.stringify({ ok: false, status: err?.status || null, message: err?.message || String(err), data: err?.data || null }, null, 2));
|
|
5856
|
+
} else {
|
|
5857
|
+
console.error("Feedback comment failed:", err?.message || err);
|
|
5858
|
+
if (err?.data) console.error(JSON.stringify(err.data, null, 2));
|
|
5859
|
+
}
|
|
5860
|
+
process.exit(1);
|
|
5861
|
+
}
|
|
5862
|
+
|
|
5863
|
+
const postSync = await refreshFeedbackSnapshotAfterMutation(args, { apiBase, key, timeoutMs });
|
|
5864
|
+
if (args.json) {
|
|
5865
|
+
console.log(JSON.stringify({ ok: true, ...data, post_sync: postSync }, null, 2));
|
|
5866
|
+
return;
|
|
5867
|
+
}
|
|
5868
|
+
|
|
5869
|
+
if (data.comment_id) console.log(`Comment ID: ${data.comment_id}`);
|
|
5870
|
+
console.log(`Feedback: ${data.feedback_id || feedbackId}`);
|
|
5871
|
+
if (data.project_id) console.log(`Project ID: ${data.project_id}`);
|
|
5872
|
+
if (data.user_name) console.log(`Author: ${data.user_name}`);
|
|
5873
|
+
if (data.created_at) console.log(`Created At: ${data.created_at}`);
|
|
5874
|
+
if (data.content) {
|
|
5875
|
+
const body = String(data.content);
|
|
5876
|
+
const truncated = body.length > 2000 ? `${body.slice(0, 2000)}\n...[truncated]` : body;
|
|
5877
|
+
console.log("Content:");
|
|
5878
|
+
console.log(truncated);
|
|
5879
|
+
}
|
|
5880
|
+
if (postSync?.data_root) console.log(`Synced feedback: ${postSync.data_root}`);
|
|
5881
|
+
if (postSync?.error) console.error(`Feedback sync warning: ${postSync.error}`);
|
|
5882
|
+
}
|
|
5883
|
+
|
|
5884
|
+
async function runFeedbackUndo(args) {
|
|
5985
5885
|
const key = getProjectApiKey();
|
|
5986
5886
|
if (!key) {
|
|
5987
5887
|
console.error("Missing MYTE_API_KEY (project key) in environment/.env");
|
|
@@ -5997,40 +5897,32 @@ async function runFeedbackUndo(args) {
|
|
|
5997
5897
|
console.error("Missing --event-id.");
|
|
5998
5898
|
process.exit(1);
|
|
5999
5899
|
}
|
|
6000
|
-
|
|
6001
|
-
const timeoutMs = resolveTimeoutMs(args);
|
|
6002
|
-
const apiBase = resolveApiBase(args);
|
|
6003
|
-
const clientSessionId = firstNonEmptyString(args["client-session-id"], args.clientSessionId, args.client_session_id);
|
|
6004
|
-
|
|
6005
|
-
args,
|
|
6006
|
-
operation: `feedback_event_undo:${feedbackId}:${eventId}`,
|
|
6007
|
-
payload,
|
|
6008
|
-
});
|
|
6009
|
-
|
|
6010
|
-
if (args["print-context"] || args.printContext || args["dry-run"] || args.dryRun) {
|
|
6011
|
-
console.log(JSON.stringify(payload, null, 2));
|
|
6012
|
-
return;
|
|
6013
|
-
}
|
|
6014
|
-
|
|
6015
|
-
const writeApproval = requireWriteApproval(args, payload, {
|
|
6016
|
-
operation: `feedback_event_undo:${feedbackId}:${eventId}`,
|
|
5900
|
+
let payload = { reason: firstNonEmptyString(args.reason) || undefined };
|
|
5901
|
+
const timeoutMs = resolveTimeoutMs(args);
|
|
5902
|
+
const apiBase = resolveApiBase(args);
|
|
5903
|
+
const clientSessionId = firstNonEmptyString(args["client-session-id"], args.clientSessionId, args.client_session_id);
|
|
5904
|
+
payload = withWriteApproval(args, payload, {
|
|
6017
5905
|
artifactKind: "yaml",
|
|
6018
5906
|
targets: [feedbackId, eventId],
|
|
6019
5907
|
});
|
|
6020
|
-
|
|
6021
|
-
|
|
6022
|
-
|
|
5908
|
+
const idempotencyKey = resolveProjectMutationIdempotencyKey({
|
|
5909
|
+
args,
|
|
5910
|
+
operation: `feedback_event_undo:${feedbackId}:${eventId}`,
|
|
5911
|
+
payload,
|
|
5912
|
+
});
|
|
5913
|
+
|
|
5914
|
+
let data;
|
|
5915
|
+
try {
|
|
6023
5916
|
data = await postFeedbackBoardMutation({
|
|
6024
5917
|
apiBase,
|
|
6025
5918
|
key,
|
|
6026
5919
|
timeoutMs,
|
|
6027
5920
|
feedbackId,
|
|
6028
5921
|
endpoint: `events/${encodeURIComponent(String(eventId))}/undo`,
|
|
6029
|
-
payload,
|
|
6030
|
-
idempotencyKey,
|
|
6031
|
-
clientSessionId,
|
|
6032
|
-
|
|
6033
|
-
});
|
|
5922
|
+
payload,
|
|
5923
|
+
idempotencyKey,
|
|
5924
|
+
clientSessionId,
|
|
5925
|
+
});
|
|
6034
5926
|
} catch (err) {
|
|
6035
5927
|
if (args.json) {
|
|
6036
5928
|
console.log(JSON.stringify({ ok: false, status: err?.status || null, message: err?.message || String(err), data: err?.data || null }, null, 2));
|
|
@@ -6188,15 +6080,15 @@ async function runFeedback(args) {
|
|
|
6188
6080
|
await runFeedbackReviewDecision(args);
|
|
6189
6081
|
return;
|
|
6190
6082
|
}
|
|
6191
|
-
if (subcommand === "move") {
|
|
6192
|
-
await runFeedbackMove(args);
|
|
6193
|
-
return;
|
|
6194
|
-
}
|
|
6195
|
-
if (subcommand === "comment" || subcommand === "comments") {
|
|
6196
|
-
await runFeedbackComment(args);
|
|
6197
|
-
return;
|
|
6198
|
-
}
|
|
6199
|
-
if (subcommand === "undo") {
|
|
6083
|
+
if (subcommand === "move") {
|
|
6084
|
+
await runFeedbackMove(args);
|
|
6085
|
+
return;
|
|
6086
|
+
}
|
|
6087
|
+
if (subcommand === "comment" || subcommand === "comments") {
|
|
6088
|
+
await runFeedbackComment(args);
|
|
6089
|
+
return;
|
|
6090
|
+
}
|
|
6091
|
+
if (subcommand === "undo") {
|
|
6200
6092
|
await runFeedbackUndo(args);
|
|
6201
6093
|
return;
|
|
6202
6094
|
}
|
|
@@ -6212,7 +6104,7 @@ async function runFeedback(args) {
|
|
|
6212
6104
|
await runFeedbackGetOrHistory(args, subcommand);
|
|
6213
6105
|
return;
|
|
6214
6106
|
}
|
|
6215
|
-
console.error("Unknown feedback command. Use status, edit, assign, archive, submit, revise, reviews, review, move, comment, undo, prd-versions, prd-diff, get, history, validate, or apply.");
|
|
6107
|
+
console.error("Unknown feedback command. Use status, edit, assign, archive, submit, revise, reviews, review, move, comment, undo, prd-versions, prd-diff, get, history, validate, or apply.");
|
|
6216
6108
|
process.exit(1);
|
|
6217
6109
|
}
|
|
6218
6110
|
|
|
@@ -6315,14 +6207,20 @@ async function buildSuggestionsMutationContext(args, mode) {
|
|
|
6315
6207
|
if (clientSessionId && !payload.client_session_id) {
|
|
6316
6208
|
payload.client_session_id = clientSessionId;
|
|
6317
6209
|
}
|
|
6318
|
-
if (mode === "create") {
|
|
6319
|
-
validateSuggestionsCreatePayload(payload);
|
|
6320
|
-
} else if (mode === "revise") {
|
|
6321
|
-
validateSuggestionsRevisePayload(payload);
|
|
6322
|
-
}
|
|
6323
|
-
const
|
|
6324
|
-
|
|
6325
|
-
|
|
6210
|
+
if (mode === "create") {
|
|
6211
|
+
validateSuggestionsCreatePayload(payload);
|
|
6212
|
+
} else if (mode === "revise") {
|
|
6213
|
+
validateSuggestionsRevisePayload(payload);
|
|
6214
|
+
}
|
|
6215
|
+
const items = Array.isArray(payload?.items) ? payload.items : [];
|
|
6216
|
+
payload = withWriteApproval(args, payload, {
|
|
6217
|
+
artifactKind: "yaml",
|
|
6218
|
+
targets: suggestionWriteTargets(items),
|
|
6219
|
+
batchCount: items.length > 1 ? items.length : null,
|
|
6220
|
+
});
|
|
6221
|
+
const idempotencyKey = resolveSuggestionsIdempotencyKey({
|
|
6222
|
+
args,
|
|
6223
|
+
mode,
|
|
6326
6224
|
actorScope,
|
|
6327
6225
|
payload,
|
|
6328
6226
|
});
|
|
@@ -6403,30 +6301,21 @@ async function runSuggestionsCreate(args) {
|
|
|
6403
6301
|
process.exit(1);
|
|
6404
6302
|
}
|
|
6405
6303
|
|
|
6406
|
-
if (args["print-context"] || args.printContext || args["dry-run"] || args.dryRun) {
|
|
6407
|
-
console.log(JSON.stringify(context.payload, null, 2));
|
|
6408
|
-
return;
|
|
6409
|
-
}
|
|
6410
|
-
|
|
6411
|
-
|
|
6412
|
-
|
|
6413
|
-
|
|
6414
|
-
|
|
6415
|
-
|
|
6416
|
-
batchCount: createTargets.length > 1 ? createTargets.length : null,
|
|
6417
|
-
});
|
|
6418
|
-
|
|
6419
|
-
let data;
|
|
6420
|
-
try {
|
|
6421
|
-
data = await createProjectSuggestions({
|
|
6422
|
-
apiBase: context.apiBase,
|
|
6423
|
-
key: context.key,
|
|
6304
|
+
if (args["print-context"] || args.printContext || args["dry-run"] || args.dryRun) {
|
|
6305
|
+
console.log(JSON.stringify(context.payload, null, 2));
|
|
6306
|
+
return;
|
|
6307
|
+
}
|
|
6308
|
+
|
|
6309
|
+
let data;
|
|
6310
|
+
try {
|
|
6311
|
+
data = await createProjectSuggestions({
|
|
6312
|
+
apiBase: context.apiBase,
|
|
6313
|
+
key: context.key,
|
|
6424
6314
|
timeoutMs: context.timeoutMs,
|
|
6425
|
-
payload: context.payload,
|
|
6426
|
-
idempotencyKey: context.idempotencyKey,
|
|
6427
|
-
clientSessionId: context.clientSessionId,
|
|
6428
|
-
|
|
6429
|
-
});
|
|
6315
|
+
payload: context.payload,
|
|
6316
|
+
idempotencyKey: context.idempotencyKey,
|
|
6317
|
+
clientSessionId: context.clientSessionId,
|
|
6318
|
+
});
|
|
6430
6319
|
} catch (err) {
|
|
6431
6320
|
console.error("Suggestions create failed:", err?.message || err);
|
|
6432
6321
|
process.exit(1);
|
|
@@ -6497,30 +6386,21 @@ async function runSuggestionsRevise(args) {
|
|
|
6497
6386
|
process.exit(1);
|
|
6498
6387
|
}
|
|
6499
6388
|
|
|
6500
|
-
if (args["print-context"] || args.printContext || args["dry-run"] || args.dryRun) {
|
|
6501
|
-
console.log(JSON.stringify(context.payload, null, 2));
|
|
6502
|
-
return;
|
|
6503
|
-
}
|
|
6504
|
-
|
|
6505
|
-
|
|
6506
|
-
|
|
6507
|
-
|
|
6508
|
-
|
|
6509
|
-
|
|
6510
|
-
batchCount: reviseTargets.length > 1 ? reviseTargets.length : null,
|
|
6511
|
-
});
|
|
6512
|
-
|
|
6513
|
-
let data;
|
|
6514
|
-
try {
|
|
6515
|
-
data = await reviseProjectSuggestions({
|
|
6516
|
-
apiBase: context.apiBase,
|
|
6517
|
-
key: context.key,
|
|
6389
|
+
if (args["print-context"] || args.printContext || args["dry-run"] || args.dryRun) {
|
|
6390
|
+
console.log(JSON.stringify(context.payload, null, 2));
|
|
6391
|
+
return;
|
|
6392
|
+
}
|
|
6393
|
+
|
|
6394
|
+
let data;
|
|
6395
|
+
try {
|
|
6396
|
+
data = await reviseProjectSuggestions({
|
|
6397
|
+
apiBase: context.apiBase,
|
|
6398
|
+
key: context.key,
|
|
6518
6399
|
timeoutMs: context.timeoutMs,
|
|
6519
|
-
payload: context.payload,
|
|
6520
|
-
idempotencyKey: context.idempotencyKey,
|
|
6521
|
-
clientSessionId: context.clientSessionId,
|
|
6522
|
-
|
|
6523
|
-
});
|
|
6400
|
+
payload: context.payload,
|
|
6401
|
+
idempotencyKey: context.idempotencyKey,
|
|
6402
|
+
clientSessionId: context.clientSessionId,
|
|
6403
|
+
});
|
|
6524
6404
|
} catch (err) {
|
|
6525
6405
|
console.error("Suggestions revise failed:", err?.message || err);
|
|
6526
6406
|
process.exit(1);
|
|
@@ -6589,30 +6469,21 @@ async function runSuggestionsReview(args) {
|
|
|
6589
6469
|
process.exit(1);
|
|
6590
6470
|
}
|
|
6591
6471
|
|
|
6592
|
-
if (args["print-context"] || args.printContext || args["dry-run"] || args.dryRun) {
|
|
6593
|
-
console.log(JSON.stringify(context.payload, null, 2));
|
|
6594
|
-
return;
|
|
6595
|
-
}
|
|
6596
|
-
|
|
6597
|
-
|
|
6598
|
-
|
|
6599
|
-
|
|
6600
|
-
|
|
6601
|
-
|
|
6602
|
-
batchCount: reviewTargets.length > 1 ? reviewTargets.length : null,
|
|
6603
|
-
});
|
|
6604
|
-
|
|
6605
|
-
let data;
|
|
6606
|
-
try {
|
|
6607
|
-
data = await reviewProjectSuggestions({
|
|
6608
|
-
apiBase: context.apiBase,
|
|
6609
|
-
key: context.key,
|
|
6472
|
+
if (args["print-context"] || args.printContext || args["dry-run"] || args.dryRun) {
|
|
6473
|
+
console.log(JSON.stringify(context.payload, null, 2));
|
|
6474
|
+
return;
|
|
6475
|
+
}
|
|
6476
|
+
|
|
6477
|
+
let data;
|
|
6478
|
+
try {
|
|
6479
|
+
data = await reviewProjectSuggestions({
|
|
6480
|
+
apiBase: context.apiBase,
|
|
6481
|
+
key: context.key,
|
|
6610
6482
|
timeoutMs: context.timeoutMs,
|
|
6611
|
-
payload: context.payload,
|
|
6612
|
-
idempotencyKey: context.idempotencyKey,
|
|
6613
|
-
clientSessionId: context.clientSessionId,
|
|
6614
|
-
|
|
6615
|
-
});
|
|
6483
|
+
payload: context.payload,
|
|
6484
|
+
idempotencyKey: context.idempotencyKey,
|
|
6485
|
+
clientSessionId: context.clientSessionId,
|
|
6486
|
+
});
|
|
6616
6487
|
} catch (err) {
|
|
6617
6488
|
console.error("Suggestions review failed:", err?.message || err);
|
|
6618
6489
|
process.exit(1);
|