@mytegroupinc/myte-core 0.0.42 → 0.0.44
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 +28 -21
- package/cli.js +706 -377
- package/lib/mytecody-splash.js +3 -3
- package/mytecody-cli.js +393 -28
- package/package.json +1 -1
package/cli.js
CHANGED
|
@@ -231,10 +231,16 @@ 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
|
-
"",
|
|
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
|
+
"",
|
|
238
244
|
"bootstrap contract:",
|
|
239
245
|
" - Run from any workspace where you want local MyteCommandCenter data written",
|
|
240
246
|
" - Writes MyteCommandCenter/data/project.yml plus phases, epics, stories, and missions locally",
|
|
@@ -395,8 +401,10 @@ function printHelp() {
|
|
|
395
401
|
" --actor-scope <id> Actor workspace key inside mission-ops.yml (defaults to machine-cwd slug)",
|
|
396
402
|
" --wait Poll batch status until terminal completion for run-qaqc",
|
|
397
403
|
" --sync After run-qaqc completes, refresh local QAQC file",
|
|
398
|
-
" --force Allow run-qaqc to bypass stale-state protection when supported",
|
|
399
|
-
" --
|
|
404
|
+
" --force Allow run-qaqc to bypass stale-state protection when supported",
|
|
405
|
+
" --confirm-write Confirm the user explicitly approved a live Myte project-key mutation",
|
|
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",
|
|
400
408
|
" --print-context Print JSON payload and exit (no query call)",
|
|
401
409
|
" --no-fetch Don't git fetch origin main/master before diff",
|
|
402
410
|
"",
|
|
@@ -670,10 +678,10 @@ function normalizeApiBase(baseRaw) {
|
|
|
670
678
|
return base.endsWith("/api") ? base : `${base}/api`;
|
|
671
679
|
}
|
|
672
680
|
|
|
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;
|
|
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;
|
|
677
685
|
try {
|
|
678
686
|
const resp = await fetchFn(url, { ...options, signal: controller?.signal });
|
|
679
687
|
const text = await resp.text();
|
|
@@ -689,13 +697,171 @@ async function fetchJsonWithTimeout(fetchFn, url, options, timeoutMs) {
|
|
|
689
697
|
}
|
|
690
698
|
return { resp, body };
|
|
691
699
|
} finally {
|
|
692
|
-
if (timeoutId) clearTimeout(timeoutId);
|
|
693
|
-
}
|
|
694
|
-
}
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
700
|
+
if (timeoutId) clearTimeout(timeoutId);
|
|
701
|
+
}
|
|
702
|
+
}
|
|
703
|
+
|
|
704
|
+
const WRITE_APPROVAL_TRANSPORT_KEYS = new Set(["write_approval", "client_session_id"]);
|
|
705
|
+
|
|
706
|
+
function canonicalizeWritePayload(value) {
|
|
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)
|
|
699
865
|
? diagnostics.repo_summaries
|
|
700
866
|
: [];
|
|
701
867
|
return {
|
|
@@ -1756,15 +1922,16 @@ async function fetchFeedbackHistory({ apiBase, key, timeoutMs, feedbackId }) {
|
|
|
1756
1922
|
return body.data || {};
|
|
1757
1923
|
}
|
|
1758
1924
|
|
|
1759
|
-
async function postFeedbackRefinement({ apiBase, key, timeoutMs, feedbackId, mode, payload, idempotencyKey, clientSessionId }) {
|
|
1925
|
+
async function postFeedbackRefinement({ apiBase, key, timeoutMs, feedbackId, mode, payload, idempotencyKey, clientSessionId, writeApproval }) {
|
|
1760
1926
|
const fetchFn = await getFetch();
|
|
1761
1927
|
const action = String(mode || "").trim();
|
|
1762
1928
|
const url = `${apiBase}/project-assistant/feedback/${encodeURIComponent(String(feedbackId || ""))}/refinement/${action}`;
|
|
1763
|
-
const headers = {
|
|
1764
|
-
"Content-Type": "application/json",
|
|
1765
|
-
Authorization: `Bearer ${key}`,
|
|
1766
|
-
...(String(clientSessionId || "").trim() ? { "X-Client-Session-Id": String(clientSessionId).trim() } : {}),
|
|
1767
|
-
|
|
1929
|
+
const headers = {
|
|
1930
|
+
"Content-Type": "application/json",
|
|
1931
|
+
Authorization: `Bearer ${key}`,
|
|
1932
|
+
...(String(clientSessionId || "").trim() ? { "X-Client-Session-Id": String(clientSessionId).trim() } : {}),
|
|
1933
|
+
...writeApprovalHeaders(writeApproval),
|
|
1934
|
+
};
|
|
1768
1935
|
if (idempotencyKey) {
|
|
1769
1936
|
headers["X-Idempotency-Key"] = String(idempotencyKey).trim();
|
|
1770
1937
|
}
|
|
@@ -1780,7 +1947,7 @@ async function postFeedbackRefinement({ apiBase, key, timeoutMs, feedbackId, mod
|
|
|
1780
1947
|
);
|
|
1781
1948
|
|
|
1782
1949
|
if (!resp.ok || body.status !== "success") {
|
|
1783
|
-
const msg = body
|
|
1950
|
+
const msg = formatProjectApiErrorMessage(body, `Feedback refinement ${action} failed (${resp.status})`);
|
|
1784
1951
|
const err = new Error(msg);
|
|
1785
1952
|
err.status = resp.status;
|
|
1786
1953
|
err.data = body?.data;
|
|
@@ -1859,7 +2026,7 @@ async function fetchFeedbackEvents({ apiBase, key, timeoutMs, feedbackId, limit
|
|
|
1859
2026
|
return body.data || {};
|
|
1860
2027
|
}
|
|
1861
2028
|
|
|
1862
|
-
async function postFeedbackReviewSubmission({ apiBase, key, timeoutMs, feedbackId, payload, idempotencyKey, clientSessionId }) {
|
|
2029
|
+
async function postFeedbackReviewSubmission({ apiBase, key, timeoutMs, feedbackId, payload, idempotencyKey, clientSessionId, writeApproval }) {
|
|
1863
2030
|
const fetchFn = await getFetch();
|
|
1864
2031
|
const url = `${apiBase}/project-assistant/feedback/${encodeURIComponent(String(feedbackId || ""))}/refinement/requests`;
|
|
1865
2032
|
const { resp, body } = await fetchJsonWithTimeout(
|
|
@@ -1869,17 +2036,18 @@ async function postFeedbackReviewSubmission({ apiBase, key, timeoutMs, feedbackI
|
|
|
1869
2036
|
method: "POST",
|
|
1870
2037
|
headers: {
|
|
1871
2038
|
"Content-Type": "application/json",
|
|
1872
|
-
Authorization: `Bearer ${key}`,
|
|
1873
|
-
"X-Idempotency-Key": String(idempotencyKey || "").trim(),
|
|
1874
|
-
...(String(clientSessionId || "").trim() ? { "X-Client-Session-Id": String(clientSessionId).trim() } : {}),
|
|
1875
|
-
|
|
2039
|
+
Authorization: `Bearer ${key}`,
|
|
2040
|
+
"X-Idempotency-Key": String(idempotencyKey || "").trim(),
|
|
2041
|
+
...(String(clientSessionId || "").trim() ? { "X-Client-Session-Id": String(clientSessionId).trim() } : {}),
|
|
2042
|
+
...writeApprovalHeaders(writeApproval),
|
|
2043
|
+
},
|
|
1876
2044
|
body: JSON.stringify(payload || {}),
|
|
1877
2045
|
},
|
|
1878
2046
|
timeoutMs
|
|
1879
2047
|
);
|
|
1880
2048
|
|
|
1881
2049
|
if (!resp.ok || body.status !== "success") {
|
|
1882
|
-
const msg = body
|
|
2050
|
+
const msg = formatProjectApiErrorMessage(body, `Feedback review submission failed (${resp.status})`);
|
|
1883
2051
|
const err = new Error(msg);
|
|
1884
2052
|
err.status = resp.status;
|
|
1885
2053
|
err.data = body?.data;
|
|
@@ -1888,7 +2056,7 @@ async function postFeedbackReviewSubmission({ apiBase, key, timeoutMs, feedbackI
|
|
|
1888
2056
|
return body.data || {};
|
|
1889
2057
|
}
|
|
1890
2058
|
|
|
1891
|
-
async function postFeedbackReviewRequestMutation({ apiBase, key, timeoutMs, requestId, endpointAction, payload, idempotencyKey, clientSessionId }) {
|
|
2059
|
+
async function postFeedbackReviewRequestMutation({ apiBase, key, timeoutMs, requestId, endpointAction, payload, idempotencyKey, clientSessionId, writeApproval }) {
|
|
1892
2060
|
const fetchFn = await getFetch();
|
|
1893
2061
|
const url = `${apiBase}/project-assistant/feedback-review-requests/${encodeURIComponent(String(requestId || ""))}/${endpointAction}`;
|
|
1894
2062
|
const { resp, body } = await fetchJsonWithTimeout(
|
|
@@ -1898,17 +2066,18 @@ async function postFeedbackReviewRequestMutation({ apiBase, key, timeoutMs, requ
|
|
|
1898
2066
|
method: "POST",
|
|
1899
2067
|
headers: {
|
|
1900
2068
|
"Content-Type": "application/json",
|
|
1901
|
-
Authorization: `Bearer ${key}`,
|
|
1902
|
-
"X-Idempotency-Key": String(idempotencyKey || "").trim(),
|
|
1903
|
-
...(String(clientSessionId || "").trim() ? { "X-Client-Session-Id": String(clientSessionId).trim() } : {}),
|
|
1904
|
-
|
|
2069
|
+
Authorization: `Bearer ${key}`,
|
|
2070
|
+
"X-Idempotency-Key": String(idempotencyKey || "").trim(),
|
|
2071
|
+
...(String(clientSessionId || "").trim() ? { "X-Client-Session-Id": String(clientSessionId).trim() } : {}),
|
|
2072
|
+
...writeApprovalHeaders(writeApproval),
|
|
2073
|
+
},
|
|
1905
2074
|
body: JSON.stringify(payload || {}),
|
|
1906
2075
|
},
|
|
1907
2076
|
timeoutMs
|
|
1908
2077
|
);
|
|
1909
2078
|
|
|
1910
2079
|
if (!resp.ok || body.status !== "success") {
|
|
1911
|
-
const msg = body
|
|
2080
|
+
const msg = formatProjectApiErrorMessage(body, `Feedback review ${endpointAction} failed (${resp.status})`);
|
|
1912
2081
|
const err = new Error(msg);
|
|
1913
2082
|
err.status = resp.status;
|
|
1914
2083
|
err.data = body?.data;
|
|
@@ -1917,7 +2086,7 @@ async function postFeedbackReviewRequestMutation({ apiBase, key, timeoutMs, requ
|
|
|
1917
2086
|
return body.data || {};
|
|
1918
2087
|
}
|
|
1919
2088
|
|
|
1920
|
-
async function postFeedbackBatchReviewMutation({ apiBase, key, timeoutMs, payload, idempotencyKey, clientSessionId }) {
|
|
2089
|
+
async function postFeedbackBatchReviewMutation({ apiBase, key, timeoutMs, payload, idempotencyKey, clientSessionId, writeApproval }) {
|
|
1921
2090
|
const fetchFn = await getFetch();
|
|
1922
2091
|
const url = `${apiBase}/project-assistant/feedback-review-requests/batch-review`;
|
|
1923
2092
|
const { resp, body } = await fetchJsonWithTimeout(
|
|
@@ -1927,17 +2096,18 @@ async function postFeedbackBatchReviewMutation({ apiBase, key, timeoutMs, payloa
|
|
|
1927
2096
|
method: "POST",
|
|
1928
2097
|
headers: {
|
|
1929
2098
|
"Content-Type": "application/json",
|
|
1930
|
-
Authorization: `Bearer ${key}`,
|
|
1931
|
-
"X-Idempotency-Key": String(idempotencyKey || "").trim(),
|
|
1932
|
-
...(String(clientSessionId || "").trim() ? { "X-Client-Session-Id": String(clientSessionId).trim() } : {}),
|
|
1933
|
-
|
|
2099
|
+
Authorization: `Bearer ${key}`,
|
|
2100
|
+
"X-Idempotency-Key": String(idempotencyKey || "").trim(),
|
|
2101
|
+
...(String(clientSessionId || "").trim() ? { "X-Client-Session-Id": String(clientSessionId).trim() } : {}),
|
|
2102
|
+
...writeApprovalHeaders(writeApproval),
|
|
2103
|
+
},
|
|
1934
2104
|
body: JSON.stringify(payload || {}),
|
|
1935
2105
|
},
|
|
1936
2106
|
timeoutMs
|
|
1937
2107
|
);
|
|
1938
2108
|
|
|
1939
2109
|
if (!resp.ok || body.status !== "success") {
|
|
1940
|
-
const msg = body
|
|
2110
|
+
const msg = formatProjectApiErrorMessage(body, `Feedback batch review failed (${resp.status})`);
|
|
1941
2111
|
const err = new Error(msg);
|
|
1942
2112
|
err.status = resp.status;
|
|
1943
2113
|
err.data = body?.data;
|
|
@@ -1946,7 +2116,7 @@ async function postFeedbackBatchReviewMutation({ apiBase, key, timeoutMs, payloa
|
|
|
1946
2116
|
return body.data || {};
|
|
1947
2117
|
}
|
|
1948
2118
|
|
|
1949
|
-
async function postFeedbackBoardMutation({ apiBase, key, timeoutMs, feedbackId, endpoint, payload, idempotencyKey, clientSessionId }) {
|
|
2119
|
+
async function postFeedbackBoardMutation({ apiBase, key, timeoutMs, feedbackId, endpoint, payload, idempotencyKey, clientSessionId, writeApproval }) {
|
|
1950
2120
|
const fetchFn = await getFetch();
|
|
1951
2121
|
const url = `${apiBase}/project-assistant/feedback/${encodeURIComponent(String(feedbackId || ""))}/${endpoint}`;
|
|
1952
2122
|
const { resp, body } = await fetchJsonWithTimeout(
|
|
@@ -1956,17 +2126,18 @@ async function postFeedbackBoardMutation({ apiBase, key, timeoutMs, feedbackId,
|
|
|
1956
2126
|
method: "POST",
|
|
1957
2127
|
headers: {
|
|
1958
2128
|
"Content-Type": "application/json",
|
|
1959
|
-
Authorization: `Bearer ${key}`,
|
|
1960
|
-
"X-Idempotency-Key": String(idempotencyKey || "").trim(),
|
|
1961
|
-
...(String(clientSessionId || "").trim() ? { "X-Client-Session-Id": String(clientSessionId).trim() } : {}),
|
|
1962
|
-
|
|
2129
|
+
Authorization: `Bearer ${key}`,
|
|
2130
|
+
"X-Idempotency-Key": String(idempotencyKey || "").trim(),
|
|
2131
|
+
...(String(clientSessionId || "").trim() ? { "X-Client-Session-Id": String(clientSessionId).trim() } : {}),
|
|
2132
|
+
...writeApprovalHeaders(writeApproval),
|
|
2133
|
+
},
|
|
1963
2134
|
body: JSON.stringify(payload || {}),
|
|
1964
2135
|
},
|
|
1965
2136
|
timeoutMs
|
|
1966
2137
|
);
|
|
1967
2138
|
|
|
1968
2139
|
if (!resp.ok || body.status !== "success") {
|
|
1969
|
-
const msg = body
|
|
2140
|
+
const msg = formatProjectApiErrorMessage(body, `Feedback board mutation failed (${resp.status})`);
|
|
1970
2141
|
const err = new Error(msg);
|
|
1971
2142
|
err.status = resp.status;
|
|
1972
2143
|
err.data = body?.data;
|
|
@@ -1975,7 +2146,7 @@ async function postFeedbackBoardMutation({ apiBase, key, timeoutMs, feedbackId,
|
|
|
1975
2146
|
return body.data || {};
|
|
1976
2147
|
}
|
|
1977
2148
|
|
|
1978
|
-
async function postFeedbackBatchBoardMutation({ apiBase, key, timeoutMs, payload, idempotencyKey, clientSessionId }) {
|
|
2149
|
+
async function postFeedbackBatchBoardMutation({ apiBase, key, timeoutMs, payload, idempotencyKey, clientSessionId, writeApproval }) {
|
|
1979
2150
|
const fetchFn = await getFetch();
|
|
1980
2151
|
const url = `${apiBase}/project-assistant/feedback/batch-board-move`;
|
|
1981
2152
|
const { resp, body } = await fetchJsonWithTimeout(
|
|
@@ -1985,17 +2156,18 @@ async function postFeedbackBatchBoardMutation({ apiBase, key, timeoutMs, payload
|
|
|
1985
2156
|
method: "POST",
|
|
1986
2157
|
headers: {
|
|
1987
2158
|
"Content-Type": "application/json",
|
|
1988
|
-
Authorization: `Bearer ${key}`,
|
|
1989
|
-
"X-Idempotency-Key": String(idempotencyKey || "").trim(),
|
|
1990
|
-
...(String(clientSessionId || "").trim() ? { "X-Client-Session-Id": String(clientSessionId).trim() } : {}),
|
|
1991
|
-
|
|
2159
|
+
Authorization: `Bearer ${key}`,
|
|
2160
|
+
"X-Idempotency-Key": String(idempotencyKey || "").trim(),
|
|
2161
|
+
...(String(clientSessionId || "").trim() ? { "X-Client-Session-Id": String(clientSessionId).trim() } : {}),
|
|
2162
|
+
...writeApprovalHeaders(writeApproval),
|
|
2163
|
+
},
|
|
1992
2164
|
body: JSON.stringify(payload || {}),
|
|
1993
2165
|
},
|
|
1994
2166
|
timeoutMs
|
|
1995
2167
|
);
|
|
1996
2168
|
|
|
1997
2169
|
if (!resp.ok || body.status !== "success") {
|
|
1998
|
-
const msg = body
|
|
2170
|
+
const msg = formatProjectApiErrorMessage(body, `Feedback batch board mutation failed (${resp.status})`);
|
|
1999
2171
|
const err = new Error(msg);
|
|
2000
2172
|
err.status = resp.status;
|
|
2001
2173
|
err.data = body?.data;
|
|
@@ -2004,7 +2176,7 @@ async function postFeedbackBatchBoardMutation({ apiBase, key, timeoutMs, payload
|
|
|
2004
2176
|
return body.data || {};
|
|
2005
2177
|
}
|
|
2006
2178
|
|
|
2007
|
-
async function postFeedbackComment({ apiBase, key, timeoutMs, feedbackId, payload, idempotencyKey, clientSessionId }) {
|
|
2179
|
+
async function postFeedbackComment({ apiBase, key, timeoutMs, feedbackId, payload, idempotencyKey, clientSessionId, writeApproval }) {
|
|
2008
2180
|
const fetchFn = await getFetch();
|
|
2009
2181
|
const url = `${apiBase}/project-assistant/feedback/${encodeURIComponent(String(feedbackId || ""))}/comments`;
|
|
2010
2182
|
const { resp, body } = await fetchJsonWithTimeout(
|
|
@@ -2017,6 +2189,7 @@ async function postFeedbackComment({ apiBase, key, timeoutMs, feedbackId, payloa
|
|
|
2017
2189
|
Authorization: `Bearer ${key}`,
|
|
2018
2190
|
"X-Idempotency-Key": String(idempotencyKey || "").trim(),
|
|
2019
2191
|
...(String(clientSessionId || "").trim() ? { "X-Client-Session-Id": String(clientSessionId).trim() } : {}),
|
|
2192
|
+
...writeApprovalHeaders(writeApproval),
|
|
2020
2193
|
},
|
|
2021
2194
|
body: JSON.stringify(payload || {}),
|
|
2022
2195
|
},
|
|
@@ -2024,7 +2197,7 @@ async function postFeedbackComment({ apiBase, key, timeoutMs, feedbackId, payloa
|
|
|
2024
2197
|
);
|
|
2025
2198
|
|
|
2026
2199
|
if (!resp.ok || body.status !== "success") {
|
|
2027
|
-
const msg = body
|
|
2200
|
+
const msg = formatProjectApiErrorMessage(body, `Feedback comment failed (${resp.status})`);
|
|
2028
2201
|
const err = new Error(msg);
|
|
2029
2202
|
err.status = resp.status;
|
|
2030
2203
|
err.data = body?.data;
|
|
@@ -2130,7 +2303,7 @@ function resolveProjectMutationIdempotencyKey({ args, operation, payload }) {
|
|
|
2130
2303
|
return createHash("sha256").update(fingerprint).digest("hex");
|
|
2131
2304
|
}
|
|
2132
2305
|
|
|
2133
|
-
async function postSuggestionsMutation({ apiBase, key, timeoutMs, endpoint, payload, idempotencyKey, clientSessionId }) {
|
|
2306
|
+
async function postSuggestionsMutation({ apiBase, key, timeoutMs, endpoint, payload, idempotencyKey, clientSessionId, writeApproval }) {
|
|
2134
2307
|
const fetchFn = await getFetch();
|
|
2135
2308
|
const url = `${apiBase}${endpoint}`;
|
|
2136
2309
|
const { resp, body } = await fetchJsonWithTimeout(
|
|
@@ -2140,25 +2313,27 @@ async function postSuggestionsMutation({ apiBase, key, timeoutMs, endpoint, payl
|
|
|
2140
2313
|
method: "POST",
|
|
2141
2314
|
headers: {
|
|
2142
2315
|
"Content-Type": "application/json",
|
|
2143
|
-
Authorization: `Bearer ${key}`,
|
|
2144
|
-
"X-Idempotency-Key": String(idempotencyKey || "").trim(),
|
|
2145
|
-
...(String(clientSessionId || "").trim() ? { "X-Client-Session-Id": String(clientSessionId).trim() } : {}),
|
|
2146
|
-
|
|
2316
|
+
Authorization: `Bearer ${key}`,
|
|
2317
|
+
"X-Idempotency-Key": String(idempotencyKey || "").trim(),
|
|
2318
|
+
...(String(clientSessionId || "").trim() ? { "X-Client-Session-Id": String(clientSessionId).trim() } : {}),
|
|
2319
|
+
...writeApprovalHeaders(writeApproval),
|
|
2320
|
+
},
|
|
2147
2321
|
body: JSON.stringify(payload),
|
|
2148
2322
|
},
|
|
2149
2323
|
timeoutMs
|
|
2150
2324
|
);
|
|
2151
2325
|
|
|
2152
2326
|
if (!resp.ok || body.status !== "success") {
|
|
2153
|
-
const msg = body
|
|
2154
|
-
const err = new Error(msg);
|
|
2155
|
-
err.status = resp.status;
|
|
2327
|
+
const msg = formatProjectApiErrorMessage(body, `Mission suggestions request failed (${resp.status})`);
|
|
2328
|
+
const err = new Error(msg);
|
|
2329
|
+
err.status = resp.status;
|
|
2330
|
+
err.data = body?.data;
|
|
2156
2331
|
throw err;
|
|
2157
2332
|
}
|
|
2158
2333
|
return body.data || {};
|
|
2159
2334
|
}
|
|
2160
2335
|
|
|
2161
|
-
async function createRunQaqcBatch({ apiBase, key, timeoutMs, payload, idempotencyKey, clientSessionId }) {
|
|
2336
|
+
async function createRunQaqcBatch({ apiBase, key, timeoutMs, payload, idempotencyKey, clientSessionId, writeApproval }) {
|
|
2162
2337
|
const fetchFn = await getFetch();
|
|
2163
2338
|
const url = `${apiBase}/project-assistant/run-qaqc`;
|
|
2164
2339
|
const { resp, body } = await fetchJsonWithTimeout(
|
|
@@ -2168,25 +2343,27 @@ async function createRunQaqcBatch({ apiBase, key, timeoutMs, payload, idempotenc
|
|
|
2168
2343
|
method: "POST",
|
|
2169
2344
|
headers: {
|
|
2170
2345
|
"Content-Type": "application/json",
|
|
2171
|
-
Authorization: `Bearer ${key}`,
|
|
2172
|
-
"X-Idempotency-Key": String(idempotencyKey || "").trim(),
|
|
2173
|
-
...(String(clientSessionId || "").trim() ? { "X-Client-Session-Id": String(clientSessionId).trim() } : {}),
|
|
2174
|
-
|
|
2346
|
+
Authorization: `Bearer ${key}`,
|
|
2347
|
+
"X-Idempotency-Key": String(idempotencyKey || "").trim(),
|
|
2348
|
+
...(String(clientSessionId || "").trim() ? { "X-Client-Session-Id": String(clientSessionId).trim() } : {}),
|
|
2349
|
+
...writeApprovalHeaders(writeApproval),
|
|
2350
|
+
},
|
|
2175
2351
|
body: JSON.stringify(payload),
|
|
2176
2352
|
},
|
|
2177
2353
|
timeoutMs
|
|
2178
2354
|
);
|
|
2179
2355
|
|
|
2180
2356
|
if (!resp.ok || body.status !== "success") {
|
|
2181
|
-
const msg = body
|
|
2182
|
-
const err = new Error(msg);
|
|
2183
|
-
err.status = resp.status;
|
|
2184
|
-
|
|
2185
|
-
|
|
2357
|
+
const msg = formatProjectApiErrorMessage(body, `Run QAQC request failed (${resp.status})`);
|
|
2358
|
+
const err = new Error(msg);
|
|
2359
|
+
err.status = resp.status;
|
|
2360
|
+
err.data = body?.data;
|
|
2361
|
+
throw err;
|
|
2362
|
+
}
|
|
2186
2363
|
return body.data || {};
|
|
2187
2364
|
}
|
|
2188
2365
|
|
|
2189
|
-
async function createMissionStatusUpdate({ apiBase, key, timeoutMs, payload, idempotencyKey, clientSessionId }) {
|
|
2366
|
+
async function createMissionStatusUpdate({ apiBase, key, timeoutMs, payload, idempotencyKey, clientSessionId, writeApproval }) {
|
|
2190
2367
|
const fetchFn = await getFetch();
|
|
2191
2368
|
const url = `${apiBase}/project-assistant/mission-status-update`;
|
|
2192
2369
|
const { resp, body } = await fetchJsonWithTimeout(
|
|
@@ -2196,25 +2373,27 @@ async function createMissionStatusUpdate({ apiBase, key, timeoutMs, payload, ide
|
|
|
2196
2373
|
method: "POST",
|
|
2197
2374
|
headers: {
|
|
2198
2375
|
"Content-Type": "application/json",
|
|
2199
|
-
Authorization: `Bearer ${key}`,
|
|
2200
|
-
"X-Idempotency-Key": String(idempotencyKey || "").trim(),
|
|
2201
|
-
...(String(clientSessionId || "").trim() ? { "X-Client-Session-Id": String(clientSessionId).trim() } : {}),
|
|
2202
|
-
|
|
2376
|
+
Authorization: `Bearer ${key}`,
|
|
2377
|
+
"X-Idempotency-Key": String(idempotencyKey || "").trim(),
|
|
2378
|
+
...(String(clientSessionId || "").trim() ? { "X-Client-Session-Id": String(clientSessionId).trim() } : {}),
|
|
2379
|
+
...writeApprovalHeaders(writeApproval),
|
|
2380
|
+
},
|
|
2203
2381
|
body: JSON.stringify(payload),
|
|
2204
2382
|
},
|
|
2205
2383
|
timeoutMs
|
|
2206
2384
|
);
|
|
2207
2385
|
|
|
2208
2386
|
if (!resp.ok || body.status !== "success") {
|
|
2209
|
-
const msg = body
|
|
2210
|
-
const err = new Error(msg);
|
|
2211
|
-
err.status = resp.status;
|
|
2212
|
-
|
|
2213
|
-
|
|
2387
|
+
const msg = formatProjectApiErrorMessage(body, `Mission status update request failed (${resp.status})`);
|
|
2388
|
+
const err = new Error(msg);
|
|
2389
|
+
err.status = resp.status;
|
|
2390
|
+
err.data = body?.data;
|
|
2391
|
+
throw err;
|
|
2392
|
+
}
|
|
2214
2393
|
return body.data || {};
|
|
2215
2394
|
}
|
|
2216
2395
|
|
|
2217
|
-
async function createMissionArchiveUpdate({ apiBase, key, timeoutMs, endpoint, payload, idempotencyKey, clientSessionId }) {
|
|
2396
|
+
async function createMissionArchiveUpdate({ apiBase, key, timeoutMs, endpoint, payload, idempotencyKey, clientSessionId, writeApproval }) {
|
|
2218
2397
|
const fetchFn = await getFetch();
|
|
2219
2398
|
const url = `${apiBase}${endpoint}`;
|
|
2220
2399
|
const { resp, body } = await fetchJsonWithTimeout(
|
|
@@ -2224,19 +2403,21 @@ async function createMissionArchiveUpdate({ apiBase, key, timeoutMs, endpoint, p
|
|
|
2224
2403
|
method: "POST",
|
|
2225
2404
|
headers: {
|
|
2226
2405
|
"Content-Type": "application/json",
|
|
2227
|
-
Authorization: `Bearer ${key}`,
|
|
2228
|
-
"X-Idempotency-Key": String(idempotencyKey || "").trim(),
|
|
2229
|
-
...(String(clientSessionId || "").trim() ? { "X-Client-Session-Id": String(clientSessionId).trim() } : {}),
|
|
2230
|
-
|
|
2406
|
+
Authorization: `Bearer ${key}`,
|
|
2407
|
+
"X-Idempotency-Key": String(idempotencyKey || "").trim(),
|
|
2408
|
+
...(String(clientSessionId || "").trim() ? { "X-Client-Session-Id": String(clientSessionId).trim() } : {}),
|
|
2409
|
+
...writeApprovalHeaders(writeApproval),
|
|
2410
|
+
},
|
|
2231
2411
|
body: JSON.stringify(payload),
|
|
2232
2412
|
},
|
|
2233
2413
|
timeoutMs
|
|
2234
2414
|
);
|
|
2235
2415
|
|
|
2236
2416
|
if (!resp.ok || body.status !== "success") {
|
|
2237
|
-
const msg = body
|
|
2238
|
-
const err = new Error(msg);
|
|
2239
|
-
err.status = resp.status;
|
|
2417
|
+
const msg = formatProjectApiErrorMessage(body, `Mission archive request failed (${resp.status})`);
|
|
2418
|
+
const err = new Error(msg);
|
|
2419
|
+
err.status = resp.status;
|
|
2420
|
+
err.data = body?.data;
|
|
2240
2421
|
throw err;
|
|
2241
2422
|
}
|
|
2242
2423
|
return body.data || {};
|
|
@@ -2366,21 +2547,28 @@ async function runRunQaqc(args) {
|
|
|
2366
2547
|
return;
|
|
2367
2548
|
}
|
|
2368
2549
|
|
|
2369
|
-
const timeoutMs = resolveTimeoutMs(args);
|
|
2370
|
-
const apiBase = resolveApiBase(args);
|
|
2371
|
-
const shouldWait = Boolean(args.wait || args.sync);
|
|
2372
|
-
const shouldSync = Boolean(args.sync);
|
|
2373
|
-
|
|
2374
|
-
|
|
2375
|
-
|
|
2376
|
-
|
|
2377
|
-
|
|
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
|
+
const writeApproval = requireWriteApproval(args, payload, {
|
|
2555
|
+
operation: "run-qaqc",
|
|
2556
|
+
artifactKind: "yaml",
|
|
2557
|
+
targets: missionIds,
|
|
2558
|
+
batchCount: missionIds.length,
|
|
2559
|
+
});
|
|
2560
|
+
|
|
2561
|
+
let data;
|
|
2562
|
+
try {
|
|
2563
|
+
data = await createRunQaqcBatch({
|
|
2564
|
+
apiBase,
|
|
2378
2565
|
key,
|
|
2379
2566
|
timeoutMs,
|
|
2380
|
-
payload,
|
|
2381
|
-
idempotencyKey,
|
|
2382
|
-
clientSessionId,
|
|
2383
|
-
|
|
2567
|
+
payload,
|
|
2568
|
+
idempotencyKey,
|
|
2569
|
+
clientSessionId,
|
|
2570
|
+
writeApproval,
|
|
2571
|
+
});
|
|
2384
2572
|
} catch (err) {
|
|
2385
2573
|
if (err?.name === "AbortError") {
|
|
2386
2574
|
console.error(`Request timed out after ${timeoutMs}ms`);
|
|
@@ -2521,19 +2709,26 @@ async function runMissionStatus(args) {
|
|
|
2521
2709
|
return;
|
|
2522
2710
|
}
|
|
2523
2711
|
|
|
2524
|
-
const timeoutMs = resolveTimeoutMs(args);
|
|
2525
|
-
const apiBase = resolveApiBase(args);
|
|
2526
|
-
|
|
2527
|
-
|
|
2528
|
-
|
|
2529
|
-
|
|
2530
|
-
|
|
2712
|
+
const timeoutMs = resolveTimeoutMs(args);
|
|
2713
|
+
const apiBase = resolveApiBase(args);
|
|
2714
|
+
const writeApproval = requireWriteApproval(args, payload, {
|
|
2715
|
+
operation: "mission-status-update",
|
|
2716
|
+
artifactKind: "yaml",
|
|
2717
|
+
targets: missionIds,
|
|
2718
|
+
batchCount: missionIds.length,
|
|
2719
|
+
});
|
|
2720
|
+
|
|
2721
|
+
let data;
|
|
2722
|
+
try {
|
|
2723
|
+
data = await createMissionStatusUpdate({
|
|
2724
|
+
apiBase,
|
|
2531
2725
|
key,
|
|
2532
2726
|
timeoutMs,
|
|
2533
|
-
payload,
|
|
2534
|
-
idempotencyKey,
|
|
2535
|
-
clientSessionId,
|
|
2536
|
-
|
|
2727
|
+
payload,
|
|
2728
|
+
idempotencyKey,
|
|
2729
|
+
clientSessionId,
|
|
2730
|
+
writeApproval,
|
|
2731
|
+
});
|
|
2537
2732
|
} catch (err) {
|
|
2538
2733
|
if (err?.name === "AbortError") {
|
|
2539
2734
|
console.error(`Request timed out after ${timeoutMs}ms`);
|
|
@@ -2627,21 +2822,28 @@ async function runMissionArchiveCommand(args) {
|
|
|
2627
2822
|
return;
|
|
2628
2823
|
}
|
|
2629
2824
|
|
|
2630
|
-
const timeoutMs = resolveTimeoutMs(args);
|
|
2631
|
-
const apiBase = resolveApiBase(args);
|
|
2632
|
-
const endpoint = "/project-assistant/mission-archive";
|
|
2633
|
-
|
|
2634
|
-
|
|
2635
|
-
|
|
2636
|
-
|
|
2637
|
-
|
|
2825
|
+
const timeoutMs = resolveTimeoutMs(args);
|
|
2826
|
+
const apiBase = resolveApiBase(args);
|
|
2827
|
+
const endpoint = "/project-assistant/mission-archive";
|
|
2828
|
+
const writeApproval = requireWriteApproval(args, payload, {
|
|
2829
|
+
operation: "mission-archive",
|
|
2830
|
+
artifactKind: "yaml",
|
|
2831
|
+
targets: missionIds,
|
|
2832
|
+
batchCount: missionIds.length,
|
|
2833
|
+
});
|
|
2834
|
+
|
|
2835
|
+
let data;
|
|
2836
|
+
try {
|
|
2837
|
+
data = await createMissionArchiveUpdate({
|
|
2838
|
+
apiBase,
|
|
2638
2839
|
key,
|
|
2639
2840
|
timeoutMs,
|
|
2640
2841
|
endpoint,
|
|
2641
|
-
payload,
|
|
2642
|
-
idempotencyKey,
|
|
2643
|
-
clientSessionId,
|
|
2644
|
-
|
|
2842
|
+
payload,
|
|
2843
|
+
idempotencyKey,
|
|
2844
|
+
clientSessionId,
|
|
2845
|
+
writeApproval,
|
|
2846
|
+
});
|
|
2645
2847
|
} catch (err) {
|
|
2646
2848
|
if (err?.name === "AbortError") {
|
|
2647
2849
|
console.error(`Request timed out after ${timeoutMs}ms`);
|
|
@@ -2735,23 +2937,28 @@ async function runUpdateTeam(args) {
|
|
|
2735
2937
|
const apiBase = resolveApiBase(args);
|
|
2736
2938
|
const clientSessionId = firstNonEmptyString(args["client-session-id"], args.clientSessionId, args.client_session_id);
|
|
2737
2939
|
if (clientSessionId) payload.client_session_id = clientSessionId;
|
|
2738
|
-
const idempotencyKey = resolveProjectMutationIdempotencyKey({
|
|
2739
|
-
args,
|
|
2740
|
-
operation: "update_team",
|
|
2741
|
-
payload,
|
|
2742
|
-
});
|
|
2743
|
-
|
|
2744
|
-
|
|
2745
|
-
|
|
2746
|
-
|
|
2940
|
+
const idempotencyKey = resolveProjectMutationIdempotencyKey({
|
|
2941
|
+
args,
|
|
2942
|
+
operation: "update_team",
|
|
2943
|
+
payload,
|
|
2944
|
+
});
|
|
2945
|
+
const writeApproval = requireWriteApproval(args, payload, {
|
|
2946
|
+
operation: "update_team",
|
|
2947
|
+
artifactKind: "markdown",
|
|
2948
|
+
});
|
|
2949
|
+
|
|
2950
|
+
let data;
|
|
2951
|
+
try {
|
|
2952
|
+
data = await postSuggestionsMutation({
|
|
2747
2953
|
apiBase,
|
|
2748
2954
|
key,
|
|
2749
2955
|
payload,
|
|
2750
2956
|
timeoutMs,
|
|
2751
|
-
endpoint: "/project-assistant/project-comment",
|
|
2752
|
-
idempotencyKey,
|
|
2753
|
-
clientSessionId,
|
|
2754
|
-
|
|
2957
|
+
endpoint: "/project-assistant/project-comment",
|
|
2958
|
+
idempotencyKey,
|
|
2959
|
+
clientSessionId,
|
|
2960
|
+
writeApproval,
|
|
2961
|
+
});
|
|
2755
2962
|
} catch (err) {
|
|
2756
2963
|
if (err?.name === "AbortError") {
|
|
2757
2964
|
console.error(`Request timed out after ${timeoutMs}ms`);
|
|
@@ -2804,23 +3011,28 @@ async function runUpdateOwner(args) {
|
|
|
2804
3011
|
const apiBase = resolveApiBase(args);
|
|
2805
3012
|
const clientSessionId = firstNonEmptyString(args["client-session-id"], args.clientSessionId, args.client_session_id);
|
|
2806
3013
|
if (clientSessionId) payload.client_session_id = clientSessionId;
|
|
2807
|
-
const idempotencyKey = resolveProjectMutationIdempotencyKey({
|
|
2808
|
-
args,
|
|
2809
|
-
operation: "update_owner",
|
|
2810
|
-
payload,
|
|
2811
|
-
});
|
|
2812
|
-
|
|
2813
|
-
|
|
2814
|
-
|
|
3014
|
+
const idempotencyKey = resolveProjectMutationIdempotencyKey({
|
|
3015
|
+
args,
|
|
3016
|
+
operation: "update_owner",
|
|
3017
|
+
payload,
|
|
3018
|
+
});
|
|
3019
|
+
const writeApproval = requireWriteApproval(args, payload, {
|
|
3020
|
+
operation: "update_owner",
|
|
3021
|
+
artifactKind: "markdown",
|
|
3022
|
+
});
|
|
3023
|
+
|
|
3024
|
+
let data;
|
|
3025
|
+
try {
|
|
2815
3026
|
data = await postSuggestionsMutation({
|
|
2816
3027
|
apiBase,
|
|
2817
3028
|
key,
|
|
2818
3029
|
payload,
|
|
2819
3030
|
timeoutMs,
|
|
2820
|
-
endpoint: "/project-assistant/update-owner",
|
|
2821
|
-
idempotencyKey,
|
|
2822
|
-
clientSessionId,
|
|
2823
|
-
|
|
3031
|
+
endpoint: "/project-assistant/update-owner",
|
|
3032
|
+
idempotencyKey,
|
|
3033
|
+
clientSessionId,
|
|
3034
|
+
writeApproval,
|
|
3035
|
+
});
|
|
2824
3036
|
} catch (err) {
|
|
2825
3037
|
if (err?.name === "AbortError") {
|
|
2826
3038
|
console.error(`Request timed out after ${timeoutMs}ms`);
|
|
@@ -2882,23 +3094,28 @@ async function runUpdateClient(args) {
|
|
|
2882
3094
|
const apiBase = resolveApiBase(args);
|
|
2883
3095
|
const clientSessionId = firstNonEmptyString(args["client-session-id"], args.clientSessionId, args.client_session_id);
|
|
2884
3096
|
if (clientSessionId) payload.client_session_id = clientSessionId;
|
|
2885
|
-
const idempotencyKey = resolveProjectMutationIdempotencyKey({
|
|
2886
|
-
args,
|
|
2887
|
-
operation: "update_client",
|
|
2888
|
-
payload,
|
|
2889
|
-
});
|
|
2890
|
-
|
|
2891
|
-
|
|
2892
|
-
|
|
3097
|
+
const idempotencyKey = resolveProjectMutationIdempotencyKey({
|
|
3098
|
+
args,
|
|
3099
|
+
operation: "update_client",
|
|
3100
|
+
payload,
|
|
3101
|
+
});
|
|
3102
|
+
const writeApproval = requireWriteApproval(args, payload, {
|
|
3103
|
+
operation: "update_client",
|
|
3104
|
+
artifactKind: "markdown",
|
|
3105
|
+
});
|
|
3106
|
+
|
|
3107
|
+
let data;
|
|
3108
|
+
try {
|
|
2893
3109
|
data = await postSuggestionsMutation({
|
|
2894
3110
|
apiBase,
|
|
2895
3111
|
key,
|
|
2896
3112
|
payload,
|
|
2897
3113
|
timeoutMs,
|
|
2898
|
-
endpoint: "/project-assistant/client-update-drafts",
|
|
2899
|
-
idempotencyKey,
|
|
2900
|
-
clientSessionId,
|
|
2901
|
-
|
|
3114
|
+
endpoint: "/project-assistant/client-update-drafts",
|
|
3115
|
+
idempotencyKey,
|
|
3116
|
+
clientSessionId,
|
|
3117
|
+
writeApproval,
|
|
3118
|
+
});
|
|
2902
3119
|
} catch (err) {
|
|
2903
3120
|
if (err?.name === "AbortError") {
|
|
2904
3121
|
console.error(`Request timed out after ${timeoutMs}ms`);
|
|
@@ -4269,41 +4486,44 @@ async function fetchSuggestionsSyncSnapshot({ apiBase, key, timeoutMs, actorScop
|
|
|
4269
4486
|
return body.data || {};
|
|
4270
4487
|
}
|
|
4271
4488
|
|
|
4272
|
-
async function createProjectSuggestions({ apiBase, key, timeoutMs, payload, idempotencyKey, clientSessionId }) {
|
|
4273
|
-
return postSuggestionsMutation({
|
|
4274
|
-
apiBase,
|
|
4275
|
-
key,
|
|
4276
|
-
timeoutMs,
|
|
4277
|
-
endpoint: "/project-assistant/suggestions",
|
|
4278
|
-
payload,
|
|
4279
|
-
idempotencyKey,
|
|
4280
|
-
clientSessionId,
|
|
4281
|
-
|
|
4282
|
-
}
|
|
4283
|
-
|
|
4284
|
-
|
|
4285
|
-
|
|
4286
|
-
|
|
4287
|
-
|
|
4288
|
-
|
|
4289
|
-
|
|
4290
|
-
|
|
4291
|
-
|
|
4292
|
-
|
|
4293
|
-
|
|
4294
|
-
|
|
4295
|
-
|
|
4296
|
-
|
|
4297
|
-
|
|
4298
|
-
|
|
4299
|
-
|
|
4300
|
-
|
|
4301
|
-
|
|
4302
|
-
|
|
4303
|
-
|
|
4304
|
-
|
|
4305
|
-
|
|
4306
|
-
|
|
4489
|
+
async function createProjectSuggestions({ apiBase, key, timeoutMs, payload, idempotencyKey, clientSessionId, writeApproval }) {
|
|
4490
|
+
return postSuggestionsMutation({
|
|
4491
|
+
apiBase,
|
|
4492
|
+
key,
|
|
4493
|
+
timeoutMs,
|
|
4494
|
+
endpoint: "/project-assistant/suggestions",
|
|
4495
|
+
payload,
|
|
4496
|
+
idempotencyKey,
|
|
4497
|
+
clientSessionId,
|
|
4498
|
+
writeApproval,
|
|
4499
|
+
});
|
|
4500
|
+
}
|
|
4501
|
+
|
|
4502
|
+
async function reviseProjectSuggestions({ apiBase, key, timeoutMs, payload, idempotencyKey, clientSessionId, writeApproval }) {
|
|
4503
|
+
return postSuggestionsMutation({
|
|
4504
|
+
apiBase,
|
|
4505
|
+
key,
|
|
4506
|
+
timeoutMs,
|
|
4507
|
+
endpoint: "/project-assistant/suggestions/revise",
|
|
4508
|
+
payload,
|
|
4509
|
+
idempotencyKey,
|
|
4510
|
+
clientSessionId,
|
|
4511
|
+
writeApproval,
|
|
4512
|
+
});
|
|
4513
|
+
}
|
|
4514
|
+
|
|
4515
|
+
async function reviewProjectSuggestions({ apiBase, key, timeoutMs, payload, idempotencyKey, clientSessionId, writeApproval }) {
|
|
4516
|
+
return postSuggestionsMutation({
|
|
4517
|
+
apiBase,
|
|
4518
|
+
key,
|
|
4519
|
+
timeoutMs,
|
|
4520
|
+
endpoint: "/project-assistant/suggestions/review",
|
|
4521
|
+
payload,
|
|
4522
|
+
idempotencyKey,
|
|
4523
|
+
clientSessionId,
|
|
4524
|
+
writeApproval,
|
|
4525
|
+
});
|
|
4526
|
+
}
|
|
4307
4527
|
|
|
4308
4528
|
async function runCreatePrd(args) {
|
|
4309
4529
|
const key = (process.env.MYTE_API_KEY || process.env.MYTE_PROJECT_API_KEY || "").trim();
|
|
@@ -4414,21 +4634,27 @@ async function runCreatePrd(args) {
|
|
|
4414
4634
|
let data;
|
|
4415
4635
|
const payload = payloads[0];
|
|
4416
4636
|
if (clientSessionId) payload.client_session_id = clientSessionId;
|
|
4417
|
-
const idempotencyKey = resolveProjectMutationIdempotencyKey({
|
|
4418
|
-
args,
|
|
4419
|
-
operation: "create_prd",
|
|
4420
|
-
payload,
|
|
4421
|
-
});
|
|
4422
|
-
|
|
4423
|
-
|
|
4424
|
-
|
|
4425
|
-
|
|
4426
|
-
|
|
4637
|
+
const idempotencyKey = resolveProjectMutationIdempotencyKey({
|
|
4638
|
+
args,
|
|
4639
|
+
operation: "create_prd",
|
|
4640
|
+
payload,
|
|
4641
|
+
});
|
|
4642
|
+
const writeApproval = requireWriteApproval(args, payload, {
|
|
4643
|
+
operation: "create_prd",
|
|
4644
|
+
artifactKind: "markdown",
|
|
4645
|
+
targets: prdApprovalTargets(payload),
|
|
4646
|
+
});
|
|
4647
|
+
try {
|
|
4648
|
+
data = await postSuggestionsMutation({
|
|
4649
|
+
apiBase,
|
|
4650
|
+
key,
|
|
4651
|
+
payload,
|
|
4427
4652
|
timeoutMs,
|
|
4428
|
-
endpoint: "/project-assistant/create-prd",
|
|
4429
|
-
idempotencyKey,
|
|
4430
|
-
clientSessionId,
|
|
4431
|
-
|
|
4653
|
+
endpoint: "/project-assistant/create-prd",
|
|
4654
|
+
idempotencyKey,
|
|
4655
|
+
clientSessionId,
|
|
4656
|
+
writeApproval,
|
|
4657
|
+
});
|
|
4432
4658
|
} catch (err) {
|
|
4433
4659
|
if (err?.name === "AbortError") {
|
|
4434
4660
|
console.error(`Request timed out after ${timeoutMs}ms`);
|
|
@@ -4473,20 +4699,28 @@ async function runCreatePrd(args) {
|
|
|
4473
4699
|
try {
|
|
4474
4700
|
const payload = { items: payloads };
|
|
4475
4701
|
if (clientSessionId) payload.client_session_id = clientSessionId;
|
|
4476
|
-
const idempotencyKey = resolveProjectMutationIdempotencyKey({
|
|
4477
|
-
args,
|
|
4478
|
-
operation: "create_prds",
|
|
4479
|
-
payload,
|
|
4480
|
-
});
|
|
4481
|
-
const
|
|
4482
|
-
|
|
4483
|
-
|
|
4484
|
-
|
|
4485
|
-
|
|
4486
|
-
|
|
4487
|
-
|
|
4488
|
-
|
|
4489
|
-
|
|
4702
|
+
const idempotencyKey = resolveProjectMutationIdempotencyKey({
|
|
4703
|
+
args,
|
|
4704
|
+
operation: "create_prds",
|
|
4705
|
+
payload,
|
|
4706
|
+
});
|
|
4707
|
+
const prdTargets = prdApprovalTargets(payload);
|
|
4708
|
+
const writeApproval = requireWriteApproval(args, payload, {
|
|
4709
|
+
operation: "create_prds",
|
|
4710
|
+
artifactKind: "markdown",
|
|
4711
|
+
targets: prdTargets,
|
|
4712
|
+
batchCount: prdTargets.length,
|
|
4713
|
+
});
|
|
4714
|
+
const data = await postSuggestionsMutation({
|
|
4715
|
+
apiBase,
|
|
4716
|
+
key,
|
|
4717
|
+
payload,
|
|
4718
|
+
timeoutMs,
|
|
4719
|
+
endpoint: "/project-assistant/create-prds",
|
|
4720
|
+
idempotencyKey,
|
|
4721
|
+
clientSessionId,
|
|
4722
|
+
writeApproval,
|
|
4723
|
+
});
|
|
4490
4724
|
aggregated.project_id = data.project_id || null;
|
|
4491
4725
|
aggregated.created_count = Number(data.created_count || 0);
|
|
4492
4726
|
aggregated.failed_count = Number(data.failed_count || 0);
|
|
@@ -5058,26 +5292,34 @@ async function runFeedbackValidateOrApply(args, mode) {
|
|
|
5058
5292
|
args.client_session_id,
|
|
5059
5293
|
payload.client_session_id
|
|
5060
5294
|
);
|
|
5061
|
-
const idempotencyKey = mode === "apply"
|
|
5062
|
-
? resolveProjectMutationIdempotencyKey({
|
|
5063
|
-
args,
|
|
5064
|
-
operation: `feedback_refinement_apply:${feedbackId}`,
|
|
5065
|
-
payload,
|
|
5066
|
-
})
|
|
5067
|
-
: null;
|
|
5068
|
-
|
|
5069
|
-
|
|
5070
|
-
|
|
5071
|
-
|
|
5072
|
-
|
|
5295
|
+
const idempotencyKey = mode === "apply"
|
|
5296
|
+
? resolveProjectMutationIdempotencyKey({
|
|
5297
|
+
args,
|
|
5298
|
+
operation: `feedback_refinement_apply:${feedbackId}`,
|
|
5299
|
+
payload,
|
|
5300
|
+
})
|
|
5301
|
+
: null;
|
|
5302
|
+
const writeApproval = mode === "apply"
|
|
5303
|
+
? requireWriteApproval(args, payload, {
|
|
5304
|
+
operation: `feedback_refinement_apply:${feedbackId}`,
|
|
5305
|
+
artifactKind: "yaml",
|
|
5306
|
+
targets: [feedbackId],
|
|
5307
|
+
})
|
|
5308
|
+
: null;
|
|
5309
|
+
|
|
5310
|
+
let data;
|
|
5311
|
+
try {
|
|
5312
|
+
data = await postFeedbackRefinement({
|
|
5313
|
+
apiBase,
|
|
5073
5314
|
key,
|
|
5074
5315
|
timeoutMs,
|
|
5075
5316
|
feedbackId,
|
|
5076
5317
|
mode,
|
|
5077
|
-
payload,
|
|
5078
|
-
idempotencyKey,
|
|
5079
|
-
clientSessionId,
|
|
5080
|
-
|
|
5318
|
+
payload,
|
|
5319
|
+
idempotencyKey,
|
|
5320
|
+
clientSessionId,
|
|
5321
|
+
writeApproval,
|
|
5322
|
+
});
|
|
5081
5323
|
} catch (err) {
|
|
5082
5324
|
if (args.json) {
|
|
5083
5325
|
console.log(JSON.stringify({
|
|
@@ -5202,23 +5444,29 @@ async function runFeedbackSubmit(args) {
|
|
|
5202
5444
|
args.client_session_id,
|
|
5203
5445
|
payload.client_session_id
|
|
5204
5446
|
);
|
|
5205
|
-
const idempotencyKey = resolveProjectMutationIdempotencyKey({
|
|
5206
|
-
args,
|
|
5207
|
-
operation: `feedback_refinement_request_submit:${feedbackId}`,
|
|
5208
|
-
payload,
|
|
5209
|
-
});
|
|
5210
|
-
|
|
5211
|
-
|
|
5212
|
-
|
|
5213
|
-
|
|
5447
|
+
const idempotencyKey = resolveProjectMutationIdempotencyKey({
|
|
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}`,
|
|
5454
|
+
artifactKind: "yaml",
|
|
5455
|
+
targets: [feedbackId],
|
|
5456
|
+
});
|
|
5457
|
+
|
|
5458
|
+
let data;
|
|
5459
|
+
try {
|
|
5460
|
+
data = await postFeedbackReviewSubmission({
|
|
5214
5461
|
apiBase,
|
|
5215
5462
|
key,
|
|
5216
5463
|
timeoutMs,
|
|
5217
5464
|
feedbackId,
|
|
5218
|
-
payload,
|
|
5219
|
-
idempotencyKey,
|
|
5220
|
-
clientSessionId,
|
|
5221
|
-
|
|
5465
|
+
payload,
|
|
5466
|
+
idempotencyKey,
|
|
5467
|
+
clientSessionId,
|
|
5468
|
+
writeApproval,
|
|
5469
|
+
});
|
|
5222
5470
|
} catch (err) {
|
|
5223
5471
|
if (args.json) {
|
|
5224
5472
|
console.log(JSON.stringify({ ok: false, status: err?.status || null, message: err?.message || String(err), data: err?.data || null, artifact_path: absPath }, null, 2));
|
|
@@ -5268,24 +5516,30 @@ async function runFeedbackRevise(args) {
|
|
|
5268
5516
|
args.client_session_id,
|
|
5269
5517
|
payload.client_session_id
|
|
5270
5518
|
);
|
|
5271
|
-
const idempotencyKey = resolveProjectMutationIdempotencyKey({
|
|
5272
|
-
args,
|
|
5273
|
-
operation: `feedback_refinement_request_revise:${requestId}`,
|
|
5274
|
-
payload,
|
|
5275
|
-
});
|
|
5276
|
-
|
|
5277
|
-
|
|
5278
|
-
|
|
5279
|
-
|
|
5519
|
+
const idempotencyKey = resolveProjectMutationIdempotencyKey({
|
|
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}`,
|
|
5526
|
+
artifactKind: "yaml",
|
|
5527
|
+
targets: [requestId],
|
|
5528
|
+
});
|
|
5529
|
+
|
|
5530
|
+
let data;
|
|
5531
|
+
try {
|
|
5532
|
+
data = await postFeedbackReviewRequestMutation({
|
|
5280
5533
|
apiBase,
|
|
5281
5534
|
key,
|
|
5282
5535
|
timeoutMs,
|
|
5283
5536
|
requestId,
|
|
5284
5537
|
endpointAction: "revise",
|
|
5285
|
-
payload,
|
|
5286
|
-
idempotencyKey,
|
|
5287
|
-
clientSessionId,
|
|
5288
|
-
|
|
5538
|
+
payload,
|
|
5539
|
+
idempotencyKey,
|
|
5540
|
+
clientSessionId,
|
|
5541
|
+
writeApproval,
|
|
5542
|
+
});
|
|
5289
5543
|
} catch (err) {
|
|
5290
5544
|
if (args.json) {
|
|
5291
5545
|
console.log(JSON.stringify({ ok: false, status: err?.status || null, message: err?.message || String(err), data: err?.data || null, artifact_path: absPath }, null, 2));
|
|
@@ -5411,22 +5665,32 @@ async function runFeedbackReviewDecision(args) {
|
|
|
5411
5665
|
const timeoutMs = resolveTimeoutMs(args);
|
|
5412
5666
|
const apiBase = resolveApiBase(args);
|
|
5413
5667
|
const clientSessionId = firstNonEmptyString(args["client-session-id"], args.clientSessionId, args.client_session_id, payload.client_session_id);
|
|
5414
|
-
const idempotencyKey = resolveProjectMutationIdempotencyKey({
|
|
5415
|
-
args,
|
|
5416
|
-
operation: `feedback_review_batch:${action}:${items.map((item) => item.request_id || item.id || "").join(",")}`,
|
|
5417
|
-
payload,
|
|
5418
|
-
});
|
|
5419
|
-
|
|
5420
|
-
|
|
5421
|
-
|
|
5422
|
-
|
|
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}`,
|
|
5678
|
+
artifactKind: "yaml",
|
|
5679
|
+
targets: requestTargets,
|
|
5680
|
+
batchCount: items.length,
|
|
5681
|
+
});
|
|
5682
|
+
|
|
5683
|
+
let data;
|
|
5684
|
+
try {
|
|
5685
|
+
data = await postFeedbackBatchReviewMutation({
|
|
5423
5686
|
apiBase,
|
|
5424
5687
|
key,
|
|
5425
5688
|
timeoutMs,
|
|
5426
|
-
payload,
|
|
5427
|
-
idempotencyKey,
|
|
5428
|
-
clientSessionId,
|
|
5429
|
-
|
|
5689
|
+
payload,
|
|
5690
|
+
idempotencyKey,
|
|
5691
|
+
clientSessionId,
|
|
5692
|
+
writeApproval,
|
|
5693
|
+
});
|
|
5430
5694
|
} catch (err) {
|
|
5431
5695
|
if (args.json) {
|
|
5432
5696
|
console.log(JSON.stringify({ ok: false, status: err?.status || null, message: err?.message || String(err), data: err?.data || null }, null, 2));
|
|
@@ -5470,24 +5734,30 @@ async function runFeedbackReviewDecision(args) {
|
|
|
5470
5734
|
const apiBase = resolveApiBase(args);
|
|
5471
5735
|
const clientSessionId = firstNonEmptyString(args["client-session-id"], args.clientSessionId, args.client_session_id, payload.client_session_id);
|
|
5472
5736
|
const operationAction = action === "request_changes" ? "request_changes" : action;
|
|
5473
|
-
const idempotencyKey = resolveProjectMutationIdempotencyKey({
|
|
5474
|
-
args,
|
|
5475
|
-
operation: `feedback_review_request_${operationAction}:${requestId}`,
|
|
5476
|
-
payload,
|
|
5477
|
-
});
|
|
5478
|
-
|
|
5479
|
-
|
|
5480
|
-
|
|
5481
|
-
|
|
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}`,
|
|
5744
|
+
artifactKind: "yaml",
|
|
5745
|
+
targets: [requestId],
|
|
5746
|
+
});
|
|
5747
|
+
|
|
5748
|
+
let data;
|
|
5749
|
+
try {
|
|
5750
|
+
data = await postFeedbackReviewRequestMutation({
|
|
5482
5751
|
apiBase,
|
|
5483
5752
|
key,
|
|
5484
5753
|
timeoutMs,
|
|
5485
5754
|
requestId,
|
|
5486
5755
|
endpointAction,
|
|
5487
|
-
payload,
|
|
5488
|
-
idempotencyKey,
|
|
5489
|
-
clientSessionId,
|
|
5490
|
-
|
|
5756
|
+
payload,
|
|
5757
|
+
idempotencyKey,
|
|
5758
|
+
clientSessionId,
|
|
5759
|
+
writeApproval,
|
|
5760
|
+
});
|
|
5491
5761
|
} catch (err) {
|
|
5492
5762
|
if (args.json) {
|
|
5493
5763
|
console.log(JSON.stringify({ ok: false, status: err?.status || null, message: err?.message || String(err), data: err?.data || null }, null, 2));
|
|
@@ -5540,21 +5810,28 @@ async function runFeedbackMove(args) {
|
|
|
5540
5810
|
}
|
|
5541
5811
|
const batchId = firstNonEmptyString(args["batch-id"], args.batchId, args.batch_id);
|
|
5542
5812
|
if (batchId) payload.batch_id = batchId;
|
|
5543
|
-
const idempotencyKey = resolveProjectMutationIdempotencyKey({
|
|
5544
|
-
args,
|
|
5545
|
-
operation: `feedback_board_batch_move:${toState}:${feedbackIds.join(",")}`,
|
|
5546
|
-
payload,
|
|
5547
|
-
});
|
|
5548
|
-
|
|
5549
|
-
|
|
5550
|
-
|
|
5551
|
-
|
|
5552
|
-
|
|
5813
|
+
const idempotencyKey = resolveProjectMutationIdempotencyKey({
|
|
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}`,
|
|
5820
|
+
artifactKind: "yaml",
|
|
5821
|
+
targets: feedbackIds,
|
|
5822
|
+
batchCount: feedbackIds.length,
|
|
5823
|
+
});
|
|
5824
|
+
let data;
|
|
5825
|
+
try {
|
|
5826
|
+
data = await postFeedbackBatchBoardMutation({
|
|
5827
|
+
apiBase,
|
|
5828
|
+
key,
|
|
5553
5829
|
timeoutMs,
|
|
5554
|
-
payload,
|
|
5555
|
-
idempotencyKey,
|
|
5556
|
-
clientSessionId,
|
|
5557
|
-
|
|
5830
|
+
payload,
|
|
5831
|
+
idempotencyKey,
|
|
5832
|
+
clientSessionId,
|
|
5833
|
+
writeApproval,
|
|
5834
|
+
});
|
|
5558
5835
|
} catch (err) {
|
|
5559
5836
|
if (args.json) {
|
|
5560
5837
|
console.log(JSON.stringify({ ok: false, status: err?.status || null, message: err?.message || String(err), data: err?.data || null }, null, 2));
|
|
@@ -5576,24 +5853,30 @@ async function runFeedbackMove(args) {
|
|
|
5576
5853
|
}
|
|
5577
5854
|
|
|
5578
5855
|
payload.from_state = fromState;
|
|
5579
|
-
const idempotencyKey = resolveProjectMutationIdempotencyKey({
|
|
5580
|
-
args,
|
|
5581
|
-
operation: `feedback_board_move:${feedbackId}`,
|
|
5582
|
-
payload,
|
|
5583
|
-
});
|
|
5584
|
-
|
|
5585
|
-
|
|
5586
|
-
|
|
5587
|
-
|
|
5856
|
+
const idempotencyKey = resolveProjectMutationIdempotencyKey({
|
|
5857
|
+
args,
|
|
5858
|
+
operation: `feedback_board_move:${feedbackId}`,
|
|
5859
|
+
payload,
|
|
5860
|
+
});
|
|
5861
|
+
const writeApproval = requireWriteApproval(args, payload, {
|
|
5862
|
+
operation: `feedback_board_move:${feedbackId}`,
|
|
5863
|
+
artifactKind: "yaml",
|
|
5864
|
+
targets: [feedbackId],
|
|
5865
|
+
});
|
|
5866
|
+
|
|
5867
|
+
let data;
|
|
5868
|
+
try {
|
|
5869
|
+
data = await postFeedbackBoardMutation({
|
|
5588
5870
|
apiBase,
|
|
5589
5871
|
key,
|
|
5590
5872
|
timeoutMs,
|
|
5591
5873
|
feedbackId,
|
|
5592
5874
|
endpoint: "board-move",
|
|
5593
|
-
payload,
|
|
5594
|
-
idempotencyKey,
|
|
5595
|
-
clientSessionId,
|
|
5596
|
-
|
|
5875
|
+
payload,
|
|
5876
|
+
idempotencyKey,
|
|
5877
|
+
clientSessionId,
|
|
5878
|
+
writeApproval,
|
|
5879
|
+
});
|
|
5597
5880
|
} catch (err) {
|
|
5598
5881
|
if (args.json) {
|
|
5599
5882
|
console.log(JSON.stringify({ ok: false, status: err?.status || null, message: err?.message || String(err), data: err?.data || null }, null, 2));
|
|
@@ -5649,6 +5932,12 @@ async function runFeedbackComment(args) {
|
|
|
5649
5932
|
return;
|
|
5650
5933
|
}
|
|
5651
5934
|
|
|
5935
|
+
const writeApproval = requireWriteApproval(args, payload, {
|
|
5936
|
+
operation: `feedback_comment_create:${feedbackId}`,
|
|
5937
|
+
artifactKind: "markdown",
|
|
5938
|
+
targets: [feedbackId],
|
|
5939
|
+
});
|
|
5940
|
+
|
|
5652
5941
|
let data;
|
|
5653
5942
|
try {
|
|
5654
5943
|
data = await postFeedbackComment({
|
|
@@ -5659,6 +5948,7 @@ async function runFeedbackComment(args) {
|
|
|
5659
5948
|
payload,
|
|
5660
5949
|
idempotencyKey,
|
|
5661
5950
|
clientSessionId,
|
|
5951
|
+
writeApproval,
|
|
5662
5952
|
});
|
|
5663
5953
|
} catch (err) {
|
|
5664
5954
|
if (args.json) {
|
|
@@ -5711,24 +6001,36 @@ async function runFeedbackUndo(args) {
|
|
|
5711
6001
|
const timeoutMs = resolveTimeoutMs(args);
|
|
5712
6002
|
const apiBase = resolveApiBase(args);
|
|
5713
6003
|
const clientSessionId = firstNonEmptyString(args["client-session-id"], args.clientSessionId, args.client_session_id);
|
|
5714
|
-
const idempotencyKey = resolveProjectMutationIdempotencyKey({
|
|
5715
|
-
args,
|
|
5716
|
-
operation: `feedback_event_undo:${feedbackId}:${eventId}`,
|
|
5717
|
-
payload,
|
|
5718
|
-
});
|
|
5719
|
-
|
|
5720
|
-
|
|
5721
|
-
|
|
6004
|
+
const idempotencyKey = resolveProjectMutationIdempotencyKey({
|
|
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}`,
|
|
6017
|
+
artifactKind: "yaml",
|
|
6018
|
+
targets: [feedbackId, eventId],
|
|
6019
|
+
});
|
|
6020
|
+
|
|
6021
|
+
let data;
|
|
6022
|
+
try {
|
|
5722
6023
|
data = await postFeedbackBoardMutation({
|
|
5723
6024
|
apiBase,
|
|
5724
6025
|
key,
|
|
5725
6026
|
timeoutMs,
|
|
5726
6027
|
feedbackId,
|
|
5727
6028
|
endpoint: `events/${encodeURIComponent(String(eventId))}/undo`,
|
|
5728
|
-
payload,
|
|
5729
|
-
idempotencyKey,
|
|
5730
|
-
clientSessionId,
|
|
5731
|
-
|
|
6029
|
+
payload,
|
|
6030
|
+
idempotencyKey,
|
|
6031
|
+
clientSessionId,
|
|
6032
|
+
writeApproval,
|
|
6033
|
+
});
|
|
5732
6034
|
} catch (err) {
|
|
5733
6035
|
if (args.json) {
|
|
5734
6036
|
console.log(JSON.stringify({ ok: false, status: err?.status || null, message: err?.message || String(err), data: err?.data || null }, null, 2));
|
|
@@ -6101,21 +6403,30 @@ async function runSuggestionsCreate(args) {
|
|
|
6101
6403
|
process.exit(1);
|
|
6102
6404
|
}
|
|
6103
6405
|
|
|
6104
|
-
if (args["print-context"] || args.printContext || args["dry-run"] || args.dryRun) {
|
|
6105
|
-
console.log(JSON.stringify(context.payload, null, 2));
|
|
6106
|
-
return;
|
|
6107
|
-
}
|
|
6108
|
-
|
|
6109
|
-
|
|
6110
|
-
|
|
6111
|
-
|
|
6112
|
-
|
|
6113
|
-
|
|
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
|
+
const createTargets = suggestionApprovalTargets(context.payload);
|
|
6412
|
+
const writeApproval = requireWriteApproval(args, context.payload, {
|
|
6413
|
+
operation: "suggestions.create",
|
|
6414
|
+
artifactKind: "yaml",
|
|
6415
|
+
targets: createTargets,
|
|
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,
|
|
6114
6424
|
timeoutMs: context.timeoutMs,
|
|
6115
|
-
payload: context.payload,
|
|
6116
|
-
idempotencyKey: context.idempotencyKey,
|
|
6117
|
-
clientSessionId: context.clientSessionId,
|
|
6118
|
-
|
|
6425
|
+
payload: context.payload,
|
|
6426
|
+
idempotencyKey: context.idempotencyKey,
|
|
6427
|
+
clientSessionId: context.clientSessionId,
|
|
6428
|
+
writeApproval,
|
|
6429
|
+
});
|
|
6119
6430
|
} catch (err) {
|
|
6120
6431
|
console.error("Suggestions create failed:", err?.message || err);
|
|
6121
6432
|
process.exit(1);
|
|
@@ -6186,21 +6497,30 @@ async function runSuggestionsRevise(args) {
|
|
|
6186
6497
|
process.exit(1);
|
|
6187
6498
|
}
|
|
6188
6499
|
|
|
6189
|
-
if (args["print-context"] || args.printContext || args["dry-run"] || args.dryRun) {
|
|
6190
|
-
console.log(JSON.stringify(context.payload, null, 2));
|
|
6191
|
-
return;
|
|
6192
|
-
}
|
|
6193
|
-
|
|
6194
|
-
|
|
6195
|
-
|
|
6196
|
-
|
|
6197
|
-
|
|
6198
|
-
|
|
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
|
+
const reviseTargets = suggestionApprovalTargets(context.payload);
|
|
6506
|
+
const writeApproval = requireWriteApproval(args, context.payload, {
|
|
6507
|
+
operation: "suggestions.revise",
|
|
6508
|
+
artifactKind: "yaml",
|
|
6509
|
+
targets: reviseTargets,
|
|
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,
|
|
6199
6518
|
timeoutMs: context.timeoutMs,
|
|
6200
|
-
payload: context.payload,
|
|
6201
|
-
idempotencyKey: context.idempotencyKey,
|
|
6202
|
-
clientSessionId: context.clientSessionId,
|
|
6203
|
-
|
|
6519
|
+
payload: context.payload,
|
|
6520
|
+
idempotencyKey: context.idempotencyKey,
|
|
6521
|
+
clientSessionId: context.clientSessionId,
|
|
6522
|
+
writeApproval,
|
|
6523
|
+
});
|
|
6204
6524
|
} catch (err) {
|
|
6205
6525
|
console.error("Suggestions revise failed:", err?.message || err);
|
|
6206
6526
|
process.exit(1);
|
|
@@ -6269,21 +6589,30 @@ async function runSuggestionsReview(args) {
|
|
|
6269
6589
|
process.exit(1);
|
|
6270
6590
|
}
|
|
6271
6591
|
|
|
6272
|
-
if (args["print-context"] || args.printContext || args["dry-run"] || args.dryRun) {
|
|
6273
|
-
console.log(JSON.stringify(context.payload, null, 2));
|
|
6274
|
-
return;
|
|
6275
|
-
}
|
|
6276
|
-
|
|
6277
|
-
|
|
6278
|
-
|
|
6279
|
-
|
|
6280
|
-
|
|
6281
|
-
|
|
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
|
+
const reviewTargets = suggestionApprovalTargets(context.payload);
|
|
6598
|
+
const writeApproval = requireWriteApproval(args, context.payload, {
|
|
6599
|
+
operation: "suggestions.review",
|
|
6600
|
+
artifactKind: "yaml",
|
|
6601
|
+
targets: reviewTargets,
|
|
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,
|
|
6282
6610
|
timeoutMs: context.timeoutMs,
|
|
6283
|
-
payload: context.payload,
|
|
6284
|
-
idempotencyKey: context.idempotencyKey,
|
|
6285
|
-
clientSessionId: context.clientSessionId,
|
|
6286
|
-
|
|
6611
|
+
payload: context.payload,
|
|
6612
|
+
idempotencyKey: context.idempotencyKey,
|
|
6613
|
+
clientSessionId: context.clientSessionId,
|
|
6614
|
+
writeApproval,
|
|
6615
|
+
});
|
|
6287
6616
|
} catch (err) {
|
|
6288
6617
|
console.error("Suggestions review failed:", err?.message || err);
|
|
6289
6618
|
process.exit(1);
|