@mytegroupinc/myte-core 0.0.21 → 0.0.23

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/README.md +3 -1
  2. package/cli.js +797 -37
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -19,6 +19,8 @@ This package exists so the public wrapper can stay small and versioned cleanly.
19
19
  ## Behavior Summary
20
20
 
21
21
  - Snapshot-style commands such as `bootstrap`, `sync-qaqc`, `feedback-sync`, and `suggestions sync` write local `MyteCommandCenter` data.
22
- - `feedback status|edit|assign|archive` writes reviewable local YAML artifacts, while `feedback validate|apply` sends those artifacts to the backend so business rules stay server-side.
22
+ - `feedback status|edit|assign|archive` writes reviewable local YAML artifacts; `feedback submit|revise|reviews|review` routes them through the backend owner-review membrane.
23
+ - `feedback move|undo|prd-versions|prd-diff|history` calls the project-key Feedback API while leaving lifecycle rules and permissions server-side.
24
+ - `feedback validate|apply` remains available for validation and owner-direct apply paths; live authorization, stale checks, and history stay server-side.
23
25
  - `query --with-diff` requires project repos to be configured for diff collection and fails fast when no matching local project repo can be resolved.
24
26
  - Public package documentation is intentionally minimal. Internal rollout and design notes are not part of the npm package contract.
package/cli.js CHANGED
@@ -22,6 +22,7 @@ const {
22
22
  } = require("./lib/ai-gateway");
23
23
 
24
24
  const DEFAULT_API_BASE = "https://api.myte.dev";
25
+ const DEFAULT_DIFF_LIMIT_CHARS = 500_000;
25
26
  const REMOVED_COMMAND_MESSAGES = {
26
27
  ask: "The `ask` alias has been removed. Use `myte query \"...\"`.",
27
28
  chat: "The `chat` command has been removed. Use repeated `myte query` calls instead.",
@@ -143,6 +144,14 @@ function parseArgs(argv) {
143
144
  "status",
144
145
  "source",
145
146
  "feedback-id",
147
+ "request-id",
148
+ "event-id",
149
+ "version-id",
150
+ "compare-to",
151
+ "action",
152
+ "decision",
153
+ "to-state",
154
+ "from-state",
146
155
  "reason",
147
156
  "review-action",
148
157
  "idempotency-key",
@@ -151,6 +160,7 @@ function parseArgs(argv) {
151
160
  "due-date",
152
161
  "priority",
153
162
  "review-note",
163
+ "final-file",
154
164
  "tags",
155
165
  "tag",
156
166
  "mission-ids",
@@ -226,6 +236,14 @@ function printHelp() {
226
236
  " myte feedback-sync [--status <value>] [--source <value>] [--with-prd-text|--no-with-prd-text] [--output-dir ./MyteCommandCenter] [--json]",
227
237
  " myte feedback status --feedback-id <id> --status todo|in_progress|in_review|completed|deployed|rejected|archived --reason \"...\"",
228
238
  " myte feedback edit --feedback-id <id> [--title \"...\"] [--feedback-text \"...\"] [--priority High] [--reason \"...\"]",
239
+ " myte feedback submit --file ./MyteCommandCenter/reviews/feedback/<id>-edit.yml [--json]",
240
+ " myte feedback revise --request-id <id> --file ./MyteCommandCenter/reviews/feedback/<id>-edit.yml [--json]",
241
+ " myte feedback reviews [--status open|terminal|all] [--request-id <id>] [--json]",
242
+ " myte feedback review --request-id <id> --action approve|reject|request_changes|cancel [--reason \"...\"] [--json]",
243
+ " myte feedback move --feedback-id <id> --to-state in_progress --from-state todo --reason \"...\" [--json]",
244
+ " myte feedback undo --feedback-id <id> --event-id <id> --reason \"...\" [--json]",
245
+ " myte feedback prd-versions --feedback-id <id> [--json]",
246
+ " myte feedback prd-diff --feedback-id <id> --version-id <id> [--compare-to <id>] [--json]",
229
247
  " myte feedback validate --file ./MyteCommandCenter/reviews/feedback/<id>-status.yml [--json]",
230
248
  " myte feedback apply --file ./MyteCommandCenter/reviews/feedback/<id>-status.yml [--json]",
231
249
  " myte create-prd <file.md> [more.md ...] [--json] [--title \"...\"] [--description \"...\"]",
@@ -308,13 +326,17 @@ function printHelp() {
308
326
  "",
309
327
  "feedback review contract:",
310
328
  " - Draft commands write review artifacts under MyteCommandCenter/reviews/feedback/*.yml for local IDE diff review",
311
- " - validate/apply send those artifacts to /api/project-assistant/feedback/<id>/refinement/*",
329
+ " - submit/revise route artifacts through the owner-review membrane before live feedback mutation",
330
+ " - reviews/review expose owner/delegate approval, rejection, request-changes, and cancel decisions",
331
+ " - move/undo operate safe board states directly; governed states remain backend-authorized",
332
+ " - prd-versions/prd-diff expose retained PRD versions and backend-generated text diffs",
333
+ " - validate/apply send artifacts to /api/project-assistant/feedback/<id>/refinement/* for validation or owner-direct apply",
312
334
  " - The backend owns authorization, stale snapshot checks, allowed field/transition rules, and history",
313
335
  " - apply is idempotent and does not rewrite local feedback.yml; run feedback-sync after apply to refresh local state",
314
336
  "",
315
337
  "Options:",
316
338
  " --with-diff Include deterministic git diffs (project-scoped; fails fast if no project repos are configured or resolved)",
317
- " --diff-limit <chars> Truncate diff context to N chars (default: 200000)",
339
+ " --diff-limit <chars> Truncate diff context to N chars (default: 500000)",
318
340
  " --timeout-ms <ms> Request timeout (default: 300000)",
319
341
  " --base-url <url> API base (default: https://api.myte.dev)",
320
342
  " --payload-file <path> Raw OpenAI-style chat-completions payload for `myte ai`",
@@ -333,6 +355,13 @@ function printHelp() {
333
355
  " --target-contact-id Add one client contact ObjectId (repeatable)",
334
356
  " --target-contact-ids Comma-separated client contact ObjectIds",
335
357
  " --feedback-id <id> Feedback ObjectId for feedback review commands",
358
+ " --request-id <id> Feedback review request ObjectId for submit/revise/review flows",
359
+ " --event-id <id> Feedback board event ObjectId for undo",
360
+ " --version-id <id> Feedback PRD version ObjectId for prd-diff",
361
+ " --compare-to <id> Optional base PRD version ObjectId for prd-diff",
362
+ " --action <value> Feedback review action: approve, reject, request_changes, or cancel",
363
+ " --to-state <value> Target canonical feedback board state for feedback move",
364
+ " --from-state <value> Optional current-state guard for feedback move",
336
365
  " --reason <text> Human review reason included in feedback refinement artifacts",
337
366
  " --status <value> Mission status target, feedback-sync filter, or feedback review state depending on command",
338
367
  " --source <value> Feedback source filter for feedback-sync",
@@ -370,6 +399,10 @@ function printHelp() {
370
399
  " myte update-client --subject \"Weekly client update\" --body-file ./updates/week-12.md",
371
400
  " myte feedback-sync --json",
372
401
  " myte feedback status --feedback-id 507f1f77bcf86cd799439011 --status in_review --reason \"Ready for owner review\"",
402
+ " myte feedback submit --file ./MyteCommandCenter/reviews/feedback/507f1f77bcf86cd799439011-edit.yml --json",
403
+ " myte feedback reviews --status open --json",
404
+ " myte feedback review --request-id 507f1f77bcf86cd799439022 --action approve --reason \"Looks correct\" --json",
405
+ " myte feedback move --feedback-id 507f1f77bcf86cd799439011 --to-state in_progress --reason \"Started\" --json",
373
406
  " myte feedback validate --file ./MyteCommandCenter/reviews/feedback/507f1f77bcf86cd799439011-status.yml --json",
374
407
  " myte feedback apply --file ./MyteCommandCenter/reviews/feedback/507f1f77bcf86cd799439011-status.yml --json",
375
408
  " myte suggestions create --file ./suggestions/create.yml",
@@ -604,6 +637,8 @@ async function fetchJsonWithTimeout(fetchFn, url, options, timeoutMs) {
604
637
  } catch {
605
638
  const err = new Error(`Non-JSON response (${resp.status}): ${text.slice(0, 500)}`);
606
639
  err.status = resp.status;
640
+ const retryAfter = resp.headers?.get?.("retry-after");
641
+ if (retryAfter) err.retryAfter = retryAfter;
607
642
  throw err;
608
643
  }
609
644
  return { resp, body };
@@ -1708,6 +1743,208 @@ async function postFeedbackRefinement({ apiBase, key, timeoutMs, feedbackId, mod
1708
1743
  return body.data || {};
1709
1744
  }
1710
1745
 
1746
+ async function fetchFeedbackReviewRequests({ apiBase, key, timeoutMs, status, limit, offset }) {
1747
+ const fetchFn = await getFetch();
1748
+ const url = new URL(`${apiBase}/project-assistant/feedback-review-requests`);
1749
+ if (status) url.searchParams.set("status", String(status));
1750
+ if (limit !== undefined && limit !== null && String(limit).trim()) url.searchParams.set("limit", String(limit));
1751
+ if (offset !== undefined && offset !== null && String(offset).trim()) url.searchParams.set("offset", String(offset));
1752
+ const { resp, body } = await fetchJsonWithTimeout(
1753
+ fetchFn,
1754
+ url.toString(),
1755
+ {
1756
+ method: "GET",
1757
+ headers: { Authorization: `Bearer ${key}` },
1758
+ },
1759
+ timeoutMs
1760
+ );
1761
+
1762
+ if (!resp.ok || body.status !== "success") {
1763
+ const msg = body?.message || `Feedback review requests failed (${resp.status})`;
1764
+ const err = new Error(msg);
1765
+ err.status = resp.status;
1766
+ throw err;
1767
+ }
1768
+ return body.data || {};
1769
+ }
1770
+
1771
+ async function fetchFeedbackReviewRequest({ apiBase, key, timeoutMs, requestId }) {
1772
+ const fetchFn = await getFetch();
1773
+ const url = `${apiBase}/project-assistant/feedback-review-requests/${encodeURIComponent(String(requestId || ""))}`;
1774
+ const { resp, body } = await fetchJsonWithTimeout(
1775
+ fetchFn,
1776
+ url,
1777
+ {
1778
+ method: "GET",
1779
+ headers: { Authorization: `Bearer ${key}` },
1780
+ },
1781
+ timeoutMs
1782
+ );
1783
+
1784
+ if (!resp.ok || body.status !== "success") {
1785
+ const msg = body?.message || `Feedback review request failed (${resp.status})`;
1786
+ const err = new Error(msg);
1787
+ err.status = resp.status;
1788
+ throw err;
1789
+ }
1790
+ return body.data || {};
1791
+ }
1792
+
1793
+ async function fetchFeedbackEvents({ apiBase, key, timeoutMs, feedbackId, limit }) {
1794
+ const fetchFn = await getFetch();
1795
+ const url = new URL(`${apiBase}/project-assistant/feedback/${encodeURIComponent(String(feedbackId || ""))}/events`);
1796
+ if (limit !== undefined && limit !== null && String(limit).trim()) url.searchParams.set("limit", String(limit));
1797
+ const { resp, body } = await fetchJsonWithTimeout(
1798
+ fetchFn,
1799
+ url.toString(),
1800
+ {
1801
+ method: "GET",
1802
+ headers: { Authorization: `Bearer ${key}` },
1803
+ },
1804
+ timeoutMs
1805
+ );
1806
+
1807
+ if (!resp.ok || body.status !== "success") {
1808
+ const msg = body?.message || `Feedback events request failed (${resp.status})`;
1809
+ const err = new Error(msg);
1810
+ err.status = resp.status;
1811
+ throw err;
1812
+ }
1813
+ return body.data || {};
1814
+ }
1815
+
1816
+ async function postFeedbackReviewSubmission({ apiBase, key, timeoutMs, feedbackId, payload, idempotencyKey, clientSessionId }) {
1817
+ const fetchFn = await getFetch();
1818
+ const url = `${apiBase}/project-assistant/feedback/${encodeURIComponent(String(feedbackId || ""))}/refinement/requests`;
1819
+ const { resp, body } = await fetchJsonWithTimeout(
1820
+ fetchFn,
1821
+ url,
1822
+ {
1823
+ method: "POST",
1824
+ headers: {
1825
+ "Content-Type": "application/json",
1826
+ Authorization: `Bearer ${key}`,
1827
+ "X-Idempotency-Key": String(idempotencyKey || "").trim(),
1828
+ ...(String(clientSessionId || "").trim() ? { "X-Client-Session-Id": String(clientSessionId).trim() } : {}),
1829
+ },
1830
+ body: JSON.stringify(payload || {}),
1831
+ },
1832
+ timeoutMs
1833
+ );
1834
+
1835
+ if (!resp.ok || body.status !== "success") {
1836
+ const msg = body?.message || `Feedback review submission failed (${resp.status})`;
1837
+ const err = new Error(msg);
1838
+ err.status = resp.status;
1839
+ err.data = body?.data;
1840
+ throw err;
1841
+ }
1842
+ return body.data || {};
1843
+ }
1844
+
1845
+ async function postFeedbackReviewRequestMutation({ apiBase, key, timeoutMs, requestId, endpointAction, payload, idempotencyKey, clientSessionId }) {
1846
+ const fetchFn = await getFetch();
1847
+ const url = `${apiBase}/project-assistant/feedback-review-requests/${encodeURIComponent(String(requestId || ""))}/${endpointAction}`;
1848
+ const { resp, body } = await fetchJsonWithTimeout(
1849
+ fetchFn,
1850
+ url,
1851
+ {
1852
+ method: "POST",
1853
+ headers: {
1854
+ "Content-Type": "application/json",
1855
+ Authorization: `Bearer ${key}`,
1856
+ "X-Idempotency-Key": String(idempotencyKey || "").trim(),
1857
+ ...(String(clientSessionId || "").trim() ? { "X-Client-Session-Id": String(clientSessionId).trim() } : {}),
1858
+ },
1859
+ body: JSON.stringify(payload || {}),
1860
+ },
1861
+ timeoutMs
1862
+ );
1863
+
1864
+ if (!resp.ok || body.status !== "success") {
1865
+ const msg = body?.message || `Feedback review ${endpointAction} failed (${resp.status})`;
1866
+ const err = new Error(msg);
1867
+ err.status = resp.status;
1868
+ err.data = body?.data;
1869
+ throw err;
1870
+ }
1871
+ return body.data || {};
1872
+ }
1873
+
1874
+ async function postFeedbackBoardMutation({ apiBase, key, timeoutMs, feedbackId, endpoint, payload, idempotencyKey, clientSessionId }) {
1875
+ const fetchFn = await getFetch();
1876
+ const url = `${apiBase}/project-assistant/feedback/${encodeURIComponent(String(feedbackId || ""))}/${endpoint}`;
1877
+ const { resp, body } = await fetchJsonWithTimeout(
1878
+ fetchFn,
1879
+ url,
1880
+ {
1881
+ method: "POST",
1882
+ headers: {
1883
+ "Content-Type": "application/json",
1884
+ Authorization: `Bearer ${key}`,
1885
+ "X-Idempotency-Key": String(idempotencyKey || "").trim(),
1886
+ ...(String(clientSessionId || "").trim() ? { "X-Client-Session-Id": String(clientSessionId).trim() } : {}),
1887
+ },
1888
+ body: JSON.stringify(payload || {}),
1889
+ },
1890
+ timeoutMs
1891
+ );
1892
+
1893
+ if (!resp.ok || body.status !== "success") {
1894
+ const msg = body?.message || `Feedback board mutation failed (${resp.status})`;
1895
+ const err = new Error(msg);
1896
+ err.status = resp.status;
1897
+ err.data = body?.data;
1898
+ throw err;
1899
+ }
1900
+ return body.data || {};
1901
+ }
1902
+
1903
+ async function fetchFeedbackPrdVersions({ apiBase, key, timeoutMs, feedbackId }) {
1904
+ const fetchFn = await getFetch();
1905
+ const url = `${apiBase}/project-assistant/feedback/${encodeURIComponent(String(feedbackId || ""))}/prd/versions`;
1906
+ const { resp, body } = await fetchJsonWithTimeout(
1907
+ fetchFn,
1908
+ url,
1909
+ {
1910
+ method: "GET",
1911
+ headers: { Authorization: `Bearer ${key}` },
1912
+ },
1913
+ timeoutMs
1914
+ );
1915
+
1916
+ if (!resp.ok || body.status !== "success") {
1917
+ const msg = body?.message || `Feedback PRD versions request failed (${resp.status})`;
1918
+ const err = new Error(msg);
1919
+ err.status = resp.status;
1920
+ throw err;
1921
+ }
1922
+ return body.data || {};
1923
+ }
1924
+
1925
+ async function fetchFeedbackPrdVersionDiff({ apiBase, key, timeoutMs, feedbackId, versionId, compareTo }) {
1926
+ const fetchFn = await getFetch();
1927
+ const url = new URL(`${apiBase}/project-assistant/feedback/${encodeURIComponent(String(feedbackId || ""))}/prd/versions/${encodeURIComponent(String(versionId || ""))}/diff`);
1928
+ if (compareTo) url.searchParams.set("compare_to", String(compareTo));
1929
+ const { resp, body } = await fetchJsonWithTimeout(
1930
+ fetchFn,
1931
+ url.toString(),
1932
+ {
1933
+ method: "GET",
1934
+ headers: { Authorization: `Bearer ${key}` },
1935
+ },
1936
+ timeoutMs
1937
+ );
1938
+
1939
+ if (!resp.ok || body.status !== "success") {
1940
+ const msg = body?.message || `Feedback PRD version diff failed (${resp.status})`;
1941
+ const err = new Error(msg);
1942
+ err.status = resp.status;
1943
+ throw err;
1944
+ }
1945
+ return body.data || {};
1946
+ }
1947
+
1711
1948
  async function fetchSuggestionsSyncSnapshot({ apiBase, key, timeoutMs, actorScope = "" }) {
1712
1949
  const fetchFn = await getFetch();
1713
1950
  const url = new URL(`${apiBase}/project-assistant/suggestions`);
@@ -1881,6 +2118,10 @@ function resolveRetryAfterMs(err, fallbackMs = 5_000) {
1881
2118
  return fallbackMs;
1882
2119
  }
1883
2120
 
2121
+ function isTransientQueryStatusError(err) {
2122
+ return [408, 429, 500, 502, 503, 504].includes(Number(err?.status));
2123
+ }
2124
+
1884
2125
  async function createAssistantQueryJob({ apiBase, key, payload, timeoutMs, endpoint = "/project-assistant/query" }) {
1885
2126
  const fetchFn = await getFetch();
1886
2127
  const url = `${apiBase}${endpoint}`;
@@ -4261,7 +4502,7 @@ async function buildFeedbackDraftForCommand(args, subcommand) {
4261
4502
  const reviewNote = firstNonEmptyString(args["review-note"], args.reviewNote, args.review_note);
4262
4503
  if (reviewNote) changes.review_note = feedbackChange(null, reviewNote);
4263
4504
  } else {
4264
- console.error("Unknown feedback command. Use status, edit, assign, archive, get, history, validate, or apply.");
4505
+ console.error("Unknown feedback draft command. Use status, edit, assign, archive, or refine.");
4265
4506
  process.exit(1);
4266
4507
  }
4267
4508
 
@@ -4375,57 +4616,537 @@ async function runFeedbackValidateOrApply(args, mode) {
4375
4616
  }
4376
4617
  }
4377
4618
 
4378
- async function runFeedbackGetOrHistory(args, mode) {
4619
+ function resolveFeedbackRequestIdArg(args) {
4620
+ return firstNonEmptyString(args["request-id"], args.requestId, args.request_id, args._?.[1]);
4621
+ }
4622
+
4623
+ function resolveFeedbackEventIdArg(args) {
4624
+ return firstNonEmptyString(args["event-id"], args.eventId, args.event_id, args._?.[1]);
4625
+ }
4626
+
4627
+ function resolveFeedbackVersionIdArg(args) {
4628
+ return firstNonEmptyString(args["version-id"], args.versionId, args.version_id, args._?.[1]);
4629
+ }
4630
+
4631
+ function summarizeFeedbackReviewRequestPayload(data) {
4632
+ const request = data?.request || data || {};
4633
+ return {
4634
+ request_id: request.request_id || request._id || null,
4635
+ feedback_id: request.feedback_id || request.feedback?.feedback_id || null,
4636
+ status: request.status || null,
4637
+ title: request.title || request.feedback?.title || null,
4638
+ can_review: request.can_review === true,
4639
+ can_approve: request.can_approve === true,
4640
+ is_terminal: request.is_terminal === true,
4641
+ stale: request.stale === true,
4642
+ conflicted: request.conflicted === true,
4643
+ warnings: Array.isArray(request.warnings) ? request.warnings : [],
4644
+ };
4645
+ }
4646
+
4647
+ function printFeedbackReviewRequestSummary(data, args) {
4648
+ const summary = summarizeFeedbackReviewRequestPayload(data);
4649
+ if (args.json) {
4650
+ console.log(JSON.stringify(data, null, 2));
4651
+ return;
4652
+ }
4653
+ console.log(`Request: ${summary.request_id || "(unknown)"}`);
4654
+ console.log(`Feedback: ${summary.feedback_id || "(unknown)"}`);
4655
+ console.log(`Status: ${summary.status || "unknown"}`);
4656
+ if (summary.title) console.log(`Title: ${summary.title}`);
4657
+ console.log(`Can approve: ${summary.can_approve ? "yes" : "no"}`);
4658
+ if (summary.stale || summary.conflicted) {
4659
+ console.log(`Conflict: stale=${summary.stale ? "yes" : "no"}, conflicted=${summary.conflicted ? "yes" : "no"}`);
4660
+ }
4661
+ }
4662
+
4663
+ async function runFeedbackSubmit(args) {
4379
4664
  const key = getProjectApiKey();
4380
4665
  if (!key) {
4381
4666
  console.error("Missing MYTE_API_KEY (project key) in environment/.env");
4382
4667
  process.exit(1);
4383
4668
  }
4384
- const feedbackId = resolveFeedbackIdArg(args);
4669
+ const { absPath, payload } = readFeedbackRefinementArtifact(args);
4670
+ const feedbackId = firstNonEmptyString(args["feedback-id"], args.feedbackId, args.feedback_id, payload.feedback_id);
4385
4671
  if (!feedbackId) {
4386
- console.error("Missing --feedback-id.");
4672
+ console.error("Feedback refinement artifact is missing feedback_id.");
4387
4673
  process.exit(1);
4388
4674
  }
4389
4675
  const timeoutMs = resolveTimeoutMs(args);
4390
4676
  const apiBase = resolveApiBase(args);
4677
+ const clientSessionId = firstNonEmptyString(
4678
+ args["client-session-id"],
4679
+ args.clientSessionId,
4680
+ args.client_session_id,
4681
+ payload.client_session_id
4682
+ );
4683
+ const idempotencyKey = resolveProjectMutationIdempotencyKey({
4684
+ args,
4685
+ operation: `feedback_refinement_request_submit:${feedbackId}`,
4686
+ payload,
4687
+ });
4391
4688
 
4392
4689
  let data;
4393
4690
  try {
4394
- data = mode === "history"
4395
- ? await fetchFeedbackHistory({ apiBase, key, timeoutMs, feedbackId })
4396
- : await fetchFeedbackReview({ apiBase, key, timeoutMs, feedbackId });
4691
+ data = await postFeedbackReviewSubmission({
4692
+ apiBase,
4693
+ key,
4694
+ timeoutMs,
4695
+ feedbackId,
4696
+ payload,
4697
+ idempotencyKey,
4698
+ clientSessionId,
4699
+ });
4397
4700
  } catch (err) {
4398
- console.error(`Feedback ${mode} failed:`, err?.message || err);
4701
+ if (args.json) {
4702
+ console.log(JSON.stringify({ ok: false, status: err?.status || null, message: err?.message || String(err), data: err?.data || null, artifact_path: absPath }, null, 2));
4703
+ } else {
4704
+ console.error("Feedback submit failed:", err?.message || err);
4705
+ if (err?.data) console.error(JSON.stringify(err.data, null, 2));
4706
+ }
4399
4707
  process.exit(1);
4400
4708
  }
4401
4709
 
4710
+ const output = {
4711
+ ok: true,
4712
+ artifact_path: absPath,
4713
+ feedback_id: data.feedback_id || feedbackId,
4714
+ project_id: data.project_id || null,
4715
+ pending_review_count: data.pending_review_count || null,
4716
+ request: data.request || null,
4717
+ permissions: data.permissions || null,
4718
+ };
4402
4719
  if (args.json) {
4403
- console.log(JSON.stringify(data, null, 2));
4404
- return;
4405
- }
4406
- if (mode === "history") {
4407
- console.log(`Feedback: ${data.feedback_id || feedbackId}`);
4408
- console.log(`Events: ${data.count || 0}`);
4409
- for (const event of data.events || []) {
4410
- console.log(`- ${event.created_at || "unknown"} ${event.action || "refine"} ${event.history_id || ""}`);
4411
- }
4720
+ console.log(JSON.stringify(output, null, 2));
4412
4721
  return;
4413
4722
  }
4414
- const feedback = data.feedback || {};
4415
- console.log(`Feedback: ${feedback.feedback_id || feedbackId}`);
4416
- console.log(`Title: ${feedback.title || "(untitled)"}`);
4417
- console.log(`Status: ${feedback.feedback_state || feedback.status || "unknown"} (${feedback.status || "legacy unknown"})`);
4418
- console.log(`Priority: ${feedback.priority || "n/a"}`);
4419
- console.log(`Snapshot: ${feedback.snapshot_hash || "n/a"}`);
4723
+ console.log(`Feedback: ${output.feedback_id}`);
4724
+ console.log(`Review request: ${output.request?.request_id || output.request?._id || "(unknown)"}`);
4725
+ console.log(`Status: ${output.request?.status || "pending_review"}`);
4726
+ console.log("Live feedback was not mutated. Owner/delegate approval is required.");
4420
4727
  }
4421
4728
 
4422
- async function runFeedback(args) {
4423
- const subcommand = firstNonEmptyString(args._?.[0]) || "help";
4424
- if (subcommand === "help") {
4425
- printHelp();
4426
- return;
4729
+ async function runFeedbackRevise(args) {
4730
+ const key = getProjectApiKey();
4731
+ if (!key) {
4732
+ console.error("Missing MYTE_API_KEY (project key) in environment/.env");
4733
+ process.exit(1);
4427
4734
  }
4428
- if (["status", "edit", "assign", "archive", "refine"].includes(subcommand)) {
4735
+ const requestId = resolveFeedbackRequestIdArg(args);
4736
+ if (!requestId) {
4737
+ console.error("Missing --request-id.");
4738
+ process.exit(1);
4739
+ }
4740
+ const { absPath, payload } = readFeedbackRefinementArtifact(args);
4741
+ const timeoutMs = resolveTimeoutMs(args);
4742
+ const apiBase = resolveApiBase(args);
4743
+ const clientSessionId = firstNonEmptyString(
4744
+ args["client-session-id"],
4745
+ args.clientSessionId,
4746
+ args.client_session_id,
4747
+ payload.client_session_id
4748
+ );
4749
+ const idempotencyKey = resolveProjectMutationIdempotencyKey({
4750
+ args,
4751
+ operation: `feedback_refinement_request_revise:${requestId}`,
4752
+ payload,
4753
+ });
4754
+
4755
+ let data;
4756
+ try {
4757
+ data = await postFeedbackReviewRequestMutation({
4758
+ apiBase,
4759
+ key,
4760
+ timeoutMs,
4761
+ requestId,
4762
+ endpointAction: "revise",
4763
+ payload,
4764
+ idempotencyKey,
4765
+ clientSessionId,
4766
+ });
4767
+ } catch (err) {
4768
+ if (args.json) {
4769
+ console.log(JSON.stringify({ ok: false, status: err?.status || null, message: err?.message || String(err), data: err?.data || null, artifact_path: absPath }, null, 2));
4770
+ } else {
4771
+ console.error("Feedback revise failed:", err?.message || err);
4772
+ if (err?.data) console.error(JSON.stringify(err.data, null, 2));
4773
+ }
4774
+ process.exit(1);
4775
+ }
4776
+
4777
+ const output = { ok: true, artifact_path: absPath, ...data };
4778
+ if (args.json) {
4779
+ console.log(JSON.stringify(output, null, 2));
4780
+ return;
4781
+ }
4782
+ printFeedbackReviewRequestSummary(data, args);
4783
+ }
4784
+
4785
+ async function runFeedbackReviews(args) {
4786
+ const key = getProjectApiKey();
4787
+ if (!key) {
4788
+ console.error("Missing MYTE_API_KEY (project key) in environment/.env");
4789
+ process.exit(1);
4790
+ }
4791
+ const timeoutMs = resolveTimeoutMs(args);
4792
+ const apiBase = resolveApiBase(args);
4793
+ const requestId = firstNonEmptyString(args["request-id"], args.requestId, args.request_id);
4794
+
4795
+ let data;
4796
+ try {
4797
+ data = requestId
4798
+ ? await fetchFeedbackReviewRequest({ apiBase, key, timeoutMs, requestId })
4799
+ : await fetchFeedbackReviewRequests({
4800
+ apiBase,
4801
+ key,
4802
+ timeoutMs,
4803
+ status: firstNonEmptyString(args.status) || "open",
4804
+ limit: firstNonEmptyString(args.limit) || undefined,
4805
+ offset: firstNonEmptyString(args.offset) || undefined,
4806
+ });
4807
+ } catch (err) {
4808
+ console.error("Feedback reviews failed:", err?.message || err);
4809
+ process.exit(1);
4810
+ }
4811
+
4812
+ if (args.json) {
4813
+ console.log(JSON.stringify(data, null, 2));
4814
+ return;
4815
+ }
4816
+ if (requestId) {
4817
+ printFeedbackReviewRequestSummary(data, args);
4818
+ return;
4819
+ }
4820
+ const requests = Array.isArray(data.requests) ? data.requests : [];
4821
+ console.log(`Review requests: ${requests.length}/${data.total ?? requests.length}`);
4822
+ for (const requestItem of requests) {
4823
+ const summary = summarizeFeedbackReviewRequestPayload(requestItem);
4824
+ console.log(`- ${summary.request_id || "(unknown)"} ${summary.status || "unknown"} feedback=${summary.feedback_id || "(unknown)"} title=${summary.title || "(untitled)"}`);
4825
+ }
4826
+ }
4827
+
4828
+ function buildFeedbackReviewDecisionPayload(args, action) {
4829
+ const filePath = firstNonEmptyString(args.file);
4830
+ let payload = {};
4831
+ if (filePath) {
4832
+ const fromFile = readStructuredPayloadFile(filePath, "Feedback review");
4833
+ payload = Array.isArray(fromFile?.items) ? fromFile.items[0] || {} : fromFile;
4834
+ }
4835
+ if (!isPlainObject(payload)) {
4836
+ throw new Error("Feedback review payload must be an object.");
4837
+ }
4838
+ const nextPayload = { ...payload };
4839
+ const reason = firstNonEmptyString(args.reason, args["review-note"], args.reviewNote, args.review_note);
4840
+ if (reason && !nextPayload.reason && !nextPayload.review_reason) {
4841
+ nextPayload.reason = reason;
4842
+ }
4843
+ const finalFile = firstNonEmptyString(args["final-file"], args.finalFile, args.final_file);
4844
+ if (finalFile) {
4845
+ nextPayload.final_change_set = readStructuredPayloadFile(finalFile, "Feedback final change set");
4846
+ }
4847
+ if (action === "approve" || action === "reject") {
4848
+ nextPayload.decision = action;
4849
+ }
4850
+ return nextPayload;
4851
+ }
4852
+
4853
+ async function runFeedbackReviewDecision(args) {
4854
+ const key = getProjectApiKey();
4855
+ if (!key) {
4856
+ console.error("Missing MYTE_API_KEY (project key) in environment/.env");
4857
+ process.exit(1);
4858
+ }
4859
+ const requestId = resolveFeedbackRequestIdArg(args);
4860
+ if (!requestId) {
4861
+ console.error("Missing --request-id.");
4862
+ process.exit(1);
4863
+ }
4864
+ const action = String(firstNonEmptyString(args.action, args.decision, args["review-action"], args.reviewAction, args.review_action, args._?.[1]) || "").trim().toLowerCase().replace(/-/g, "_");
4865
+ if (!["approve", "reject", "request_changes", "cancel"].includes(action)) {
4866
+ console.error("Missing or invalid review action. Use approve, reject, request_changes, or cancel.");
4867
+ process.exit(1);
4868
+ }
4869
+
4870
+ let payload;
4871
+ try {
4872
+ payload = buildFeedbackReviewDecisionPayload(args, action);
4873
+ } catch (err) {
4874
+ console.error(err?.message || err);
4875
+ process.exit(1);
4876
+ }
4877
+ const endpointAction = action === "request_changes" ? "request-changes" : action === "cancel" ? "cancel" : "review";
4878
+ const timeoutMs = resolveTimeoutMs(args);
4879
+ const apiBase = resolveApiBase(args);
4880
+ const clientSessionId = firstNonEmptyString(args["client-session-id"], args.clientSessionId, args.client_session_id, payload.client_session_id);
4881
+ const operationAction = action === "request_changes" ? "request_changes" : action;
4882
+ const idempotencyKey = resolveProjectMutationIdempotencyKey({
4883
+ args,
4884
+ operation: `feedback_review_request_${operationAction}:${requestId}`,
4885
+ payload,
4886
+ });
4887
+
4888
+ let data;
4889
+ try {
4890
+ data = await postFeedbackReviewRequestMutation({
4891
+ apiBase,
4892
+ key,
4893
+ timeoutMs,
4894
+ requestId,
4895
+ endpointAction,
4896
+ payload,
4897
+ idempotencyKey,
4898
+ clientSessionId,
4899
+ });
4900
+ } catch (err) {
4901
+ if (args.json) {
4902
+ console.log(JSON.stringify({ ok: false, status: err?.status || null, message: err?.message || String(err), data: err?.data || null }, null, 2));
4903
+ } else {
4904
+ console.error(`Feedback review ${action} failed:`, err?.message || err);
4905
+ if (err?.data) console.error(JSON.stringify(err.data, null, 2));
4906
+ }
4907
+ process.exit(1);
4908
+ }
4909
+
4910
+ if (args.json) {
4911
+ console.log(JSON.stringify({ ok: true, action, ...data }, null, 2));
4912
+ return;
4913
+ }
4914
+ printFeedbackReviewRequestSummary(data, args);
4915
+ }
4916
+
4917
+ async function runFeedbackMove(args) {
4918
+ const key = getProjectApiKey();
4919
+ if (!key) {
4920
+ console.error("Missing MYTE_API_KEY (project key) in environment/.env");
4921
+ process.exit(1);
4922
+ }
4923
+ const feedbackId = resolveFeedbackIdArg(args);
4924
+ if (!feedbackId) {
4925
+ console.error("Missing --feedback-id.");
4926
+ process.exit(1);
4927
+ }
4928
+ const toState = firstNonEmptyString(args["to-state"], args.toState, args.to_state, args.status, args._?.[1]);
4929
+ if (!toState) {
4930
+ console.error("Missing --to-state for feedback move.");
4931
+ process.exit(1);
4932
+ }
4933
+ const payload = {
4934
+ to_state: toState,
4935
+ from_state: firstNonEmptyString(args["from-state"], args.fromState, args.from_state) || undefined,
4936
+ reason: firstNonEmptyString(args.reason) || undefined,
4937
+ };
4938
+ const timeoutMs = resolveTimeoutMs(args);
4939
+ const apiBase = resolveApiBase(args);
4940
+ const clientSessionId = firstNonEmptyString(args["client-session-id"], args.clientSessionId, args.client_session_id);
4941
+ const idempotencyKey = resolveProjectMutationIdempotencyKey({
4942
+ args,
4943
+ operation: `feedback_board_move:${feedbackId}`,
4944
+ payload,
4945
+ });
4946
+
4947
+ let data;
4948
+ try {
4949
+ data = await postFeedbackBoardMutation({
4950
+ apiBase,
4951
+ key,
4952
+ timeoutMs,
4953
+ feedbackId,
4954
+ endpoint: "board-move",
4955
+ payload,
4956
+ idempotencyKey,
4957
+ clientSessionId,
4958
+ });
4959
+ } catch (err) {
4960
+ if (args.json) {
4961
+ console.log(JSON.stringify({ ok: false, status: err?.status || null, message: err?.message || String(err), data: err?.data || null }, null, 2));
4962
+ } else {
4963
+ console.error("Feedback move failed:", err?.message || err);
4964
+ if (err?.data) console.error(JSON.stringify(err.data, null, 2));
4965
+ }
4966
+ process.exit(1);
4967
+ }
4968
+
4969
+ if (args.json) {
4970
+ console.log(JSON.stringify({ ok: true, ...data }, null, 2));
4971
+ return;
4972
+ }
4973
+ console.log(`Feedback: ${data.feedback_id || feedbackId}`);
4974
+ console.log(`State: ${data.feedback_state || toState}`);
4975
+ if (data.event?.event_id) console.log(`Event: ${data.event.event_id}`);
4976
+ }
4977
+
4978
+ async function runFeedbackUndo(args) {
4979
+ const key = getProjectApiKey();
4980
+ if (!key) {
4981
+ console.error("Missing MYTE_API_KEY (project key) in environment/.env");
4982
+ process.exit(1);
4983
+ }
4984
+ const feedbackId = resolveFeedbackIdArg(args);
4985
+ const eventId = resolveFeedbackEventIdArg(args);
4986
+ if (!feedbackId) {
4987
+ console.error("Missing --feedback-id.");
4988
+ process.exit(1);
4989
+ }
4990
+ if (!eventId) {
4991
+ console.error("Missing --event-id.");
4992
+ process.exit(1);
4993
+ }
4994
+ const payload = { reason: firstNonEmptyString(args.reason) || undefined };
4995
+ const timeoutMs = resolveTimeoutMs(args);
4996
+ const apiBase = resolveApiBase(args);
4997
+ const clientSessionId = firstNonEmptyString(args["client-session-id"], args.clientSessionId, args.client_session_id);
4998
+ const idempotencyKey = resolveProjectMutationIdempotencyKey({
4999
+ args,
5000
+ operation: `feedback_event_undo:${feedbackId}:${eventId}`,
5001
+ payload,
5002
+ });
5003
+
5004
+ let data;
5005
+ try {
5006
+ data = await postFeedbackBoardMutation({
5007
+ apiBase,
5008
+ key,
5009
+ timeoutMs,
5010
+ feedbackId,
5011
+ endpoint: `events/${encodeURIComponent(String(eventId))}/undo`,
5012
+ payload,
5013
+ idempotencyKey,
5014
+ clientSessionId,
5015
+ });
5016
+ } catch (err) {
5017
+ if (args.json) {
5018
+ console.log(JSON.stringify({ ok: false, status: err?.status || null, message: err?.message || String(err), data: err?.data || null }, null, 2));
5019
+ } else {
5020
+ console.error("Feedback undo failed:", err?.message || err);
5021
+ if (err?.data) console.error(JSON.stringify(err.data, null, 2));
5022
+ }
5023
+ process.exit(1);
5024
+ }
5025
+
5026
+ if (args.json) {
5027
+ console.log(JSON.stringify({ ok: true, ...data }, null, 2));
5028
+ return;
5029
+ }
5030
+ console.log(`Feedback: ${data.feedback_id || feedbackId}`);
5031
+ console.log(`State: ${data.feedback_state || "unknown"}`);
5032
+ if (data.reverted_event_id) console.log(`Reverted: ${data.reverted_event_id}`);
5033
+ }
5034
+
5035
+ async function runFeedbackPrdVersions(args) {
5036
+ const key = getProjectApiKey();
5037
+ if (!key) {
5038
+ console.error("Missing MYTE_API_KEY (project key) in environment/.env");
5039
+ process.exit(1);
5040
+ }
5041
+ const feedbackId = resolveFeedbackIdArg(args);
5042
+ if (!feedbackId) {
5043
+ console.error("Missing --feedback-id.");
5044
+ process.exit(1);
5045
+ }
5046
+ const timeoutMs = resolveTimeoutMs(args);
5047
+ const apiBase = resolveApiBase(args);
5048
+ let data;
5049
+ try {
5050
+ data = await fetchFeedbackPrdVersions({ apiBase, key, timeoutMs, feedbackId });
5051
+ } catch (err) {
5052
+ console.error("Feedback PRD versions failed:", err?.message || err);
5053
+ process.exit(1);
5054
+ }
5055
+ if (args.json) {
5056
+ console.log(JSON.stringify(data, null, 2));
5057
+ return;
5058
+ }
5059
+ const versions = Array.isArray(data.versions) ? data.versions : [];
5060
+ console.log(`PRD versions: ${versions.length}`);
5061
+ for (const version of versions) {
5062
+ console.log(`- ${version.version_id || version._id || "(unknown)"} v${version.version_number || "?"} active=${String(version._id || version.version_id) === String(data.active_prd_version_id) ? "yes" : "no"}`);
5063
+ }
5064
+ }
5065
+
5066
+ async function runFeedbackPrdDiff(args) {
5067
+ const key = getProjectApiKey();
5068
+ if (!key) {
5069
+ console.error("Missing MYTE_API_KEY (project key) in environment/.env");
5070
+ process.exit(1);
5071
+ }
5072
+ const feedbackId = resolveFeedbackIdArg(args);
5073
+ const versionId = resolveFeedbackVersionIdArg(args);
5074
+ if (!feedbackId) {
5075
+ console.error("Missing --feedback-id.");
5076
+ process.exit(1);
5077
+ }
5078
+ if (!versionId) {
5079
+ console.error("Missing --version-id.");
5080
+ process.exit(1);
5081
+ }
5082
+ const timeoutMs = resolveTimeoutMs(args);
5083
+ const apiBase = resolveApiBase(args);
5084
+ const compareTo = firstNonEmptyString(args["compare-to"], args.compareTo, args.compare_to);
5085
+ let data;
5086
+ try {
5087
+ data = await fetchFeedbackPrdVersionDiff({ apiBase, key, timeoutMs, feedbackId, versionId, compareTo });
5088
+ } catch (err) {
5089
+ console.error("Feedback PRD diff failed:", err?.message || err);
5090
+ process.exit(1);
5091
+ }
5092
+ if (args.json) {
5093
+ console.log(JSON.stringify(data, null, 2));
5094
+ return;
5095
+ }
5096
+ console.log(data.diff || "");
5097
+ }
5098
+
5099
+ async function runFeedbackGetOrHistory(args, mode) {
5100
+ const key = getProjectApiKey();
5101
+ if (!key) {
5102
+ console.error("Missing MYTE_API_KEY (project key) in environment/.env");
5103
+ process.exit(1);
5104
+ }
5105
+ const feedbackId = resolveFeedbackIdArg(args);
5106
+ if (!feedbackId) {
5107
+ console.error("Missing --feedback-id.");
5108
+ process.exit(1);
5109
+ }
5110
+ const timeoutMs = resolveTimeoutMs(args);
5111
+ const apiBase = resolveApiBase(args);
5112
+
5113
+ let data;
5114
+ try {
5115
+ data = mode === "history"
5116
+ ? await fetchFeedbackEvents({ apiBase, key, timeoutMs, feedbackId, limit: firstNonEmptyString(args.limit) || undefined })
5117
+ : await fetchFeedbackReview({ apiBase, key, timeoutMs, feedbackId });
5118
+ } catch (err) {
5119
+ console.error(`Feedback ${mode} failed:`, err?.message || err);
5120
+ process.exit(1);
5121
+ }
5122
+
5123
+ if (args.json) {
5124
+ console.log(JSON.stringify(data, null, 2));
5125
+ return;
5126
+ }
5127
+ if (mode === "history") {
5128
+ console.log(`Feedback: ${data.feedback_id || feedbackId}`);
5129
+ console.log(`Events: ${data.count || 0}`);
5130
+ for (const event of data.events || []) {
5131
+ console.log(`- ${event.created_at || "unknown"} ${event.action || "refine"} ${event.history_id || ""}`);
5132
+ }
5133
+ return;
5134
+ }
5135
+ const feedback = data.feedback || {};
5136
+ console.log(`Feedback: ${feedback.feedback_id || feedbackId}`);
5137
+ console.log(`Title: ${feedback.title || "(untitled)"}`);
5138
+ console.log(`Status: ${feedback.feedback_state || feedback.status || "unknown"} (${feedback.status || "legacy unknown"})`);
5139
+ console.log(`Priority: ${feedback.priority || "n/a"}`);
5140
+ console.log(`Snapshot: ${feedback.snapshot_hash || "n/a"}`);
5141
+ }
5142
+
5143
+ async function runFeedback(args) {
5144
+ const subcommand = firstNonEmptyString(args._?.[0]) || "help";
5145
+ if (subcommand === "help") {
5146
+ printHelp();
5147
+ return;
5148
+ }
5149
+ if (["status", "edit", "assign", "archive", "refine"].includes(subcommand)) {
4429
5150
  await buildFeedbackDraftForCommand(args, subcommand);
4430
5151
  return;
4431
5152
  }
@@ -4433,11 +5154,43 @@ async function runFeedback(args) {
4433
5154
  await runFeedbackValidateOrApply(args, subcommand);
4434
5155
  return;
4435
5156
  }
5157
+ if (subcommand === "submit") {
5158
+ await runFeedbackSubmit(args);
5159
+ return;
5160
+ }
5161
+ if (subcommand === "revise") {
5162
+ await runFeedbackRevise(args);
5163
+ return;
5164
+ }
5165
+ if (subcommand === "reviews" || subcommand === "requests") {
5166
+ await runFeedbackReviews(args);
5167
+ return;
5168
+ }
5169
+ if (subcommand === "review") {
5170
+ await runFeedbackReviewDecision(args);
5171
+ return;
5172
+ }
5173
+ if (subcommand === "move") {
5174
+ await runFeedbackMove(args);
5175
+ return;
5176
+ }
5177
+ if (subcommand === "undo") {
5178
+ await runFeedbackUndo(args);
5179
+ return;
5180
+ }
5181
+ if (subcommand === "prd-versions") {
5182
+ await runFeedbackPrdVersions(args);
5183
+ return;
5184
+ }
5185
+ if (subcommand === "prd-diff") {
5186
+ await runFeedbackPrdDiff(args);
5187
+ return;
5188
+ }
4436
5189
  if (subcommand === "get" || subcommand === "history") {
4437
5190
  await runFeedbackGetOrHistory(args, subcommand);
4438
5191
  return;
4439
5192
  }
4440
- console.error("Unknown feedback command. Use status, edit, assign, archive, get, history, validate, or apply.");
5193
+ console.error("Unknown feedback command. Use status, edit, assign, archive, submit, revise, reviews, review, move, undo, prd-versions, prd-diff, get, history, validate, or apply.");
4441
5194
  process.exit(1);
4442
5195
  }
4443
5196
 
@@ -5002,8 +5755,9 @@ async function runQuery(args) {
5002
5755
  const timeoutMs = Number.isFinite(timeoutParsed) ? timeoutParsed : 300_000;
5003
5756
 
5004
5757
  const charLimitRaw = args["diff-limit"] || args.diffLimit || args.diff_limit;
5005
- const charLimitParsed = charLimitRaw !== undefined && charLimitRaw !== null ? Number(charLimitRaw) : 200_000;
5006
- const diffLimit = Number.isFinite(charLimitParsed) ? charLimitParsed : 200_000;
5758
+ const charLimitParsed =
5759
+ charLimitRaw !== undefined && charLimitRaw !== null ? Number(charLimitRaw) : DEFAULT_DIFF_LIMIT_CHARS;
5760
+ const diffLimit = Number.isFinite(charLimitParsed) ? charLimitParsed : DEFAULT_DIFF_LIMIT_CHARS;
5007
5761
 
5008
5762
  const baseRaw = args["base-url"] || args.baseUrl || args.base_url || process.env.MYTE_API_BASE || DEFAULT_API_BASE;
5009
5763
  const apiBase = normalizeApiBase(baseRaw);
@@ -5077,13 +5831,19 @@ async function runQuery(args) {
5077
5831
  const pollTimeoutMs = Math.max(timeoutMs, 900_000);
5078
5832
  const startedAt = Date.now();
5079
5833
  let finalStatus = null;
5834
+ let pollDelayMs = 2_000;
5080
5835
  do {
5081
- await sleep(2_000);
5836
+ await sleep(pollDelayMs);
5082
5837
  try {
5083
5838
  finalStatus = await fetchAssistantQueryJobStatus({ apiBase, key, timeoutMs, jobId });
5839
+ pollDelayMs = Math.min(10_000, Math.ceil(pollDelayMs * 1.25));
5084
5840
  } catch (err) {
5085
- if (Number(err?.status) === 429) {
5086
- await sleep(resolveRetryAfterMs(err));
5841
+ if (isTransientQueryStatusError(err)) {
5842
+ const fallbackMs =
5843
+ Number(err?.status) === 429 ? 5_000 : Math.min(30_000, Math.max(5_000, pollDelayMs * 2));
5844
+ const waitMs = resolveRetryAfterMs(err, fallbackMs);
5845
+ await sleep(waitMs);
5846
+ pollDelayMs = Math.min(30_000, Math.max(pollDelayMs, waitMs));
5087
5847
  continue;
5088
5848
  }
5089
5849
  throw err;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mytegroupinc/myte-core",
3
- "version": "0.0.21",
3
+ "version": "0.0.23",
4
4
  "description": "Myte CLI core implementation.",
5
5
  "type": "commonjs",
6
6
  "main": "cli.js",