@quantiya/codevibe-core 2.0.86 → 2.0.88
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/dist/index.d.ts +4 -2
- package/dist/index.js +527 -524
- package/dist/orchestration-shell/cli.js +88 -20
- package/dist/orchestration-shell/quorum-loop.d.ts +11 -0
- package/dist/prompt-parser.d.ts +3 -2
- package/dist/terminal-menu.d.ts +10 -2
- package/dist/tui-parser/gemma-tui-parser.d.ts +23 -0
- package/dist/tui-parser/index.d.ts +2 -1
- package/dist/tui-parser/port-adapters.d.ts +17 -0
- package/package.json +1 -1
|
@@ -23604,7 +23604,7 @@ var AppSyncClient = class _AppSyncClient {
|
|
|
23604
23604
|
throw logger.warn("[AppSyncClient] explicit review-scope reset rejected by old backend schema; failing closed", {
|
|
23605
23605
|
gateId: input.gateId,
|
|
23606
23606
|
taskId: input.taskId
|
|
23607
|
-
}), err;
|
|
23607
|
+
}), err.reviewScopeResetUnsupported = !0, err;
|
|
23608
23608
|
logger.warn("[AppSyncClient] submitImplementorOutput additive fields rejected by backend schema; retrying legacy input", {
|
|
23609
23609
|
gateId: input.gateId,
|
|
23610
23610
|
taskId: input.taskId,
|
|
@@ -23621,7 +23621,10 @@ var AppSyncClient = class _AppSyncClient {
|
|
|
23621
23621
|
};
|
|
23622
23622
|
response = await this.graphqlRequest(mutations.submitImplementorOutput, retryVariables);
|
|
23623
23623
|
}
|
|
23624
|
-
|
|
23624
|
+
let parsed = this.#parseOrchestrationResult(response.data?.submitImplementorOutput, "submitImplementorOutput");
|
|
23625
|
+
if (typeof parsed.gateId != "string" || parsed.gateId.length === 0 || typeof parsed.workflowState != "string" || parsed.workflowState.length === 0)
|
|
23626
|
+
throw new Error("submitImplementorOutput: result missing string `gateId` / `workflowState`");
|
|
23627
|
+
return { gateId: parsed.gateId, workflowState: parsed.workflowState };
|
|
23625
23628
|
}
|
|
23626
23629
|
/**
|
|
23627
23630
|
* §3.C.22 — submit one reviewer seat's verdict. The full `ReviewerVerdict`
|
|
@@ -23679,7 +23682,7 @@ var AppSyncClient = class _AppSyncClient {
|
|
|
23679
23682
|
throw new Error("getReviewerPrompt: gateId is required");
|
|
23680
23683
|
if (!Number.isInteger(seatId) || seatId < 0)
|
|
23681
23684
|
throw new Error("getReviewerPrompt: seatId must be a non-negative integer");
|
|
23682
|
-
let response = await this.graphqlRequest(queries.getReviewerPrompt, { gateId, seatId }), parsed = this.#
|
|
23685
|
+
let response = await this.graphqlRequest(queries.getReviewerPrompt, { gateId, seatId }), parsed = this.#parseOrchestrationResult(response.data?.getReviewerPrompt, "getReviewerPrompt");
|
|
23683
23686
|
if (!parsed.encPrompt || typeof parsed.encPrompt.ciphertextB64 != "string")
|
|
23684
23687
|
throw new Error("getReviewerPrompt: response missing encPrompt.ciphertextB64");
|
|
23685
23688
|
let prompt = cryptoService.decryptContent(parsed.encPrompt.ciphertextB64, sessionKeyBase64);
|
|
@@ -23751,7 +23754,7 @@ var AppSyncClient = class _AppSyncClient {
|
|
|
23751
23754
|
* key.
|
|
23752
23755
|
*/
|
|
23753
23756
|
async getClassBSigningPublicKey() {
|
|
23754
|
-
let response = await this.graphqlRequest(queries.getClassBSigningPublicKey, {}), parsed = this.#
|
|
23757
|
+
let response = await this.graphqlRequest(queries.getClassBSigningPublicKey, {}), parsed = this.#parseOrchestrationResult(
|
|
23755
23758
|
response.data?.getClassBSigningPublicKey,
|
|
23756
23759
|
"getClassBSigningPublicKey"
|
|
23757
23760
|
);
|
|
@@ -23767,7 +23770,7 @@ var AppSyncClient = class _AppSyncClient {
|
|
|
23767
23770
|
async getInReviewAssignments(taskId) {
|
|
23768
23771
|
if (typeof taskId != "string" || taskId.length === 0)
|
|
23769
23772
|
throw new Error("getInReviewAssignments: taskId is required");
|
|
23770
|
-
let response = await this.graphqlRequest(queries.getInReviewAssignments, { taskId }), parsed = this.#
|
|
23773
|
+
let response = await this.graphqlRequest(queries.getInReviewAssignments, { taskId }), parsed = this.#parseOrchestrationResult(
|
|
23771
23774
|
response.data?.getInReviewAssignments,
|
|
23772
23775
|
"getInReviewAssignments"
|
|
23773
23776
|
);
|
|
@@ -23785,7 +23788,7 @@ var AppSyncClient = class _AppSyncClient {
|
|
|
23785
23788
|
async getTaskGroupTracks(taskGroupId) {
|
|
23786
23789
|
if (typeof taskGroupId != "string" || taskGroupId.length === 0)
|
|
23787
23790
|
throw new Error("getTaskGroupTracks: taskGroupId is required");
|
|
23788
|
-
let response = await this.graphqlRequest(queries.getTaskGroupTracks, { taskGroupId }), parsed = this.#
|
|
23791
|
+
let response = await this.graphqlRequest(queries.getTaskGroupTracks, { taskGroupId }), parsed = this.#parseOrchestrationResult(
|
|
23789
23792
|
response.data?.getTaskGroupTracks,
|
|
23790
23793
|
"getTaskGroupTracks"
|
|
23791
23794
|
);
|
|
@@ -23804,7 +23807,7 @@ var AppSyncClient = class _AppSyncClient {
|
|
|
23804
23807
|
async getInFlightTeamTracks(sessionId) {
|
|
23805
23808
|
if (typeof sessionId != "string" || sessionId.length === 0)
|
|
23806
23809
|
throw new Error("getInFlightTeamTracks: sessionId is required");
|
|
23807
|
-
let response = await this.graphqlRequest(queries.getInFlightTeamTracks, { sessionId }), parsed = this.#
|
|
23810
|
+
let response = await this.graphqlRequest(queries.getInFlightTeamTracks, { sessionId }), parsed = this.#parseOrchestrationResult(
|
|
23808
23811
|
response.data?.getInFlightTeamTracks,
|
|
23809
23812
|
"getInFlightTeamTracks"
|
|
23810
23813
|
);
|
|
@@ -23825,7 +23828,7 @@ var AppSyncClient = class _AppSyncClient {
|
|
|
23825
23828
|
async getTaskGroupStatus(taskGroupId) {
|
|
23826
23829
|
if (typeof taskGroupId != "string" || taskGroupId.length === 0)
|
|
23827
23830
|
throw new Error("getTaskGroupStatus: taskGroupId is required");
|
|
23828
|
-
let response = await this.graphqlRequest(queries.getTaskGroupStatus, { taskGroupId }), parsed = this.#
|
|
23831
|
+
let response = await this.graphqlRequest(queries.getTaskGroupStatus, { taskGroupId }), parsed = this.#parseOrchestrationResult(
|
|
23829
23832
|
response.data?.getTaskGroupStatus,
|
|
23830
23833
|
"getTaskGroupStatus"
|
|
23831
23834
|
);
|
|
@@ -23989,7 +23992,11 @@ var AppSyncClient = class _AppSyncClient {
|
|
|
23989
23992
|
}
|
|
23990
23993
|
/**
|
|
23991
23994
|
* P46b (ID-16) — parse an orchestration Lambda AWSJSON result and surface the
|
|
23992
|
-
* handler's `{errorType, errorMessage}` envelope as a thrown error.
|
|
23995
|
+
* handler's `{errorType, errorMessage}` envelope as a thrown error. SB-67: every read that went through a raw
|
|
23996
|
+
* `#parseAwsJson` now goes through here — read raw, the envelope was data (a hang on submit, an empty list on the
|
|
23997
|
+
* recovery reads). Reads parsed by hand or by `coerceAwsJsonObject` (createTaskGroup, submitMergeGateVerdict,
|
|
23998
|
+
* submitTrackVerificationOutcome, claimGroupDecision, getTaskReviewSummary) check a required field and throw an
|
|
23999
|
+
* untyped error on an envelope.
|
|
23993
24000
|
*/
|
|
23994
24001
|
#parseOrchestrationResult(raw, op) {
|
|
23995
24002
|
let parsed = this.#parseAwsJson(raw, op);
|
|
@@ -28751,8 +28758,13 @@ var PlannerOutputUnparseableError = class _PlannerOutputUnparseableError extends
|
|
|
28751
28758
|
"brainstorm",
|
|
28752
28759
|
"refuse"
|
|
28753
28760
|
]);
|
|
28761
|
+
function isRealHttpUrl(url) {
|
|
28762
|
+
if (typeof url != "string") return !1;
|
|
28763
|
+
let trimmed = url.trim();
|
|
28764
|
+
return trimmed.length === 0 || trimmed === "http(s) url" || trimmed === "https://[path]" ? !1 : new RegExp("^" + HTTP_URL_PATTERN_SOURCE + "$").test(trimmed);
|
|
28765
|
+
}
|
|
28754
28766
|
function hasRealBrowseFields(obj) {
|
|
28755
|
-
let hasRealBrowseUrls = Array.isArray(obj.browseUrls) && obj.browseUrls.
|
|
28767
|
+
let hasRealBrowseUrls = Array.isArray(obj.browseUrls) && obj.browseUrls.some(isRealHttpUrl), hasRealBrowseQuery = typeof obj.browseQuery == "string" && obj.browseQuery.trim().length > 0;
|
|
28756
28768
|
return hasRealBrowseUrls || hasRealBrowseQuery;
|
|
28757
28769
|
}
|
|
28758
28770
|
function validationError(message2, obj, canDegrade) {
|
|
@@ -28938,7 +28950,7 @@ function renderLocalGemmaPlannerPromptWithShape(input) {
|
|
|
28938
28950
|
'User: "also add a --cv-quiet flag to release.sh" (session.currentTaskState is in_progress) -> {"action":"start_task","rationale":"asks for a new deliverable while a task runs"}',
|
|
28939
28951
|
"",
|
|
28940
28952
|
OUTPUT_CONTRACT_HEADER,
|
|
28941
|
-
`{"action":"${[...localGemmaAllowedActions()].join("|")}","rationale":"short reason","clarifying_question":"question text or null","advisory_summary":"answer text or null","browseUrls":["
|
|
28953
|
+
`{"action":"${[...localGemmaAllowedActions()].join("|")}","rationale":"short reason","clarifying_question":"question text or null","advisory_summary":"answer text or null","browseUrls":["https://example.com"] or null,"browseQuery":"web-search query or null"}`,
|
|
28942
28954
|
"Only a browse action may set browseUrls/browseQuery (null for every other action). ask_user always sets clarifying_question to the question for the user. Do not include gateRequest or any other keys.",
|
|
28943
28955
|
"Destructive workspace operations: a bounded operation that removes named project files requires explicit confirmation of that operation and target before dispatch, rather than blanket refusal. If confirmation is not yet present in clarifications, choose ask_user and ask a concise question identifying the target and consequence. If the user confirms the same operation and target in clarifications, choose start_task; the implementor still enforces filesystem authority and execution safeguards. If the user declines, choose advisory_response acknowledging cancellation and do not start a task. This does not permit destructive root/home deletion or override unsafe-request refusal rules. Keep rationale to one short sentence.",
|
|
28944
28956
|
'turnState identifies this submission: new_request means the user has submitted a NEW request, even when its text repeats an earlier request; clarification_answer means the user is answering the current question in clarifications. priorSessionContext is historical reference material only. Never treat an old answer as the current answer or respond to an earlier request instead of userPrompt. For example: history says the user declined deletion; turnState is new_request; userPrompt asks to delete the same file -> ask_user for fresh confirmation, NOT advisory_response about the old cancellation. A previous approval also cannot authorize a new deletion \u2014 even when the LAST line of priorSessionContext is a bare "yes": that answered an EARLIER question, and turnState says this is a NEW request that needs its own confirmation.',
|
|
@@ -29157,8 +29169,8 @@ function parseLocalGemmaPlannerDecision(raw) {
|
|
|
29157
29169
|
if (obj.advisory_summary !== void 0 || obj.clarifying_question !== void 0)
|
|
29158
29170
|
throw validationError("Gemma planner browse output must not include advisory_summary or clarifying_question", obj, canDegrade);
|
|
29159
29171
|
} else {
|
|
29160
|
-
let hasRealBrowseUrls = Array.isArray(obj.browseUrls) && obj.browseUrls.
|
|
29161
|
-
if ((hasRealBrowseUrls || hasRealBrowseQuery) && (
|
|
29172
|
+
let hasRealBrowseUrls = Array.isArray(obj.browseUrls) && obj.browseUrls.some(isRealHttpUrl), hasRealBrowseQuery = typeof obj.browseQuery == "string" && obj.browseQuery.trim().length > 0, userFacingPlannerText = typeof obj.advisory_summary == "string" && obj.advisory_summary.trim().length > 0 || typeof obj.clarifying_question == "string" && obj.clarifying_question.trim().length > 0, taskStartingAction = obj.action === "start_task" || obj.action === "team_decompose";
|
|
29173
|
+
if ((hasRealBrowseUrls || hasRealBrowseQuery) && (userFacingPlannerText || taskStartingAction || obj.action === "refuse" || obj.action === "ask_user"))
|
|
29162
29174
|
throw new PlannerOutputUnparseableError(
|
|
29163
29175
|
"Gemma planner non-browse output must not combine browse fields with user-facing or task-starting planner output",
|
|
29164
29176
|
{ kind: "validation" }
|
|
@@ -67650,6 +67662,9 @@ function classifyImplementorRoundFailure(err) {
|
|
|
67650
67662
|
return AUTHORITY_REFUSAL_LABEL[err.refusal.category] ?? "the implementor was refused authority";
|
|
67651
67663
|
if (err instanceof StaleShadowRootError)
|
|
67652
67664
|
return `the recorded workspace-copy folder ${err.stalePath} is missing and its contents could not be accounted for (they may have been moved). Run \`codevibe doctor\` to review and clear it`;
|
|
67665
|
+
let engine = err;
|
|
67666
|
+
if (engine && engine.name === "AppSyncGraphQLError" && typeof engine.errorType == "string")
|
|
67667
|
+
return engine.errorType === "ClientError" && String(engine.responseMessage ?? "").startsWith("payload too large") ? "the change is too large to submit for review" : "the review service rejected the submission";
|
|
67653
67668
|
let msg = err instanceof Error ? err.message.toLowerCase() : "";
|
|
67654
67669
|
return msg.includes("enoent") || msg.includes("spawn") || msg.includes("command not found") || msg.includes("not installed") ? "the coding agent could not be started" : "an unexpected error occurred";
|
|
67655
67670
|
}
|
|
@@ -68772,6 +68787,11 @@ var QuorumLoop = class _QuorumLoop {
|
|
|
68772
68787
|
this.inFlightImplementorGates = /* @__PURE__ */ new Set();
|
|
68773
68788
|
/** Gates whose implementor output has been submitted. */
|
|
68774
68789
|
this.submittedOutputGates = /* @__PURE__ */ new Set();
|
|
68790
|
+
/**
|
|
68791
|
+
* SB-67 (Stage 1 R1-F1) — gates whose round failed after its submission started. The engine can dispatch reviewers
|
|
68792
|
+
* before it reports an error; a late dispatch for one of these gates belongs to a discarded task and is dropped.
|
|
68793
|
+
*/
|
|
68794
|
+
this.abandonedSubmitGates = /* @__PURE__ */ new Set();
|
|
68775
68795
|
/**
|
|
68776
68796
|
* PHASE-CP-10-MIN (#585) #C10M-16 / Codex-H1 — the per-task ACTIVE
|
|
68777
68797
|
* implementor context. `runImplementorRound` populates it at spawn (wiring
|
|
@@ -71377,7 +71397,13 @@ ${section}`);
|
|
|
71377
71397
|
reviewScopeReset: args.reviewScopeReset
|
|
71378
71398
|
});
|
|
71379
71399
|
if (args.reviewScopeReset && this.reviewScopeResetTasks.delete(args.taskId), this.teamRunIsHalted(args.teamAuthority)) return;
|
|
71380
|
-
if (this.submittedOutputGates.add(gateId), result &&
|
|
71400
|
+
if (this.submittedOutputGates.add(gateId), result?.replayedAfterEngineError === !0 && result.workflowState === "halted" && !isEngineEmptyArtifact(files))
|
|
71401
|
+
logger.info("[QuorumLoop] submission confirmed by the engine replay of an already-resolved gate", {
|
|
71402
|
+
gateId,
|
|
71403
|
+
taskId: args.taskId,
|
|
71404
|
+
workflowState: result.workflowState
|
|
71405
|
+
});
|
|
71406
|
+
else if (result && (result.workflowState === "halted" || result.workflowState === "idle")) {
|
|
71381
71407
|
let crashedEmpty = files.length === 0 && exit.exitCode !== 0, reason = files.length === 0 ? crashedEmpty ? "The coding agent exited with an error before making any changes \u2014 nothing to review. Re-run the task; if this repeats, check the desktop log." : "The implementor produced no changes \u2014 nothing to review." : "The task was halted before review (no reviewer quorum ran).";
|
|
71382
71408
|
(crashedEmpty ? logger.warn.bind(logger) : logger.info.bind(logger))("[QuorumLoop] execute-first born-halt surfaced synchronously (#EF-1)", {
|
|
71383
71409
|
gateId,
|
|
@@ -71393,7 +71419,11 @@ ${section}`);
|
|
|
71393
71419
|
}
|
|
71394
71420
|
} catch (err) {
|
|
71395
71421
|
if (this.teamRunIsHalted(args.teamAuthority)) return;
|
|
71396
|
-
if (
|
|
71422
|
+
if (
|
|
71423
|
+
// SB-67 (Stage 2 R1-F2): only an implementor failure can be a provider quota; once the submission started,
|
|
71424
|
+
// an error is the engine's (its own `HTTP 429/503` text must not read as the coding agent's usage limit).
|
|
71425
|
+
!submissionStarted && classifyImplementorQuotaFailure(void 0, err.message ?? "")
|
|
71426
|
+
) {
|
|
71397
71427
|
logger.info("[QuorumLoop] implementor round threw a quota error \u2014 continuation fork (defensive)", {
|
|
71398
71428
|
gateId,
|
|
71399
71429
|
taskId: args.taskId
|
|
@@ -71411,8 +71441,8 @@ ${section}`);
|
|
|
71411
71441
|
});
|
|
71412
71442
|
let reason = classifyImplementorRoundFailure(err);
|
|
71413
71443
|
this.surfaceHalt(`The task could not proceed \u2014 ${reason}.`);
|
|
71414
|
-
let reviseFeedbackId = args.reviseFeedbackId, preserveResetForRetry = submissionStarted && args.reviewScopeReset === !0 && reviseFeedbackId !== void 0 && this.reviewScopeResetTasks.has(args.taskId);
|
|
71415
|
-
this.emitProgress(
|
|
71444
|
+
let reviseFeedbackId = args.reviseFeedbackId, preserveResetForRetry = submissionStarted && args.reviewScopeReset === !0 && reviseFeedbackId !== void 0 && this.reviewScopeResetTasks.has(args.taskId) && err?.reviewScopeResetUnsupported === !0;
|
|
71445
|
+
submissionStarted && !preserveResetForRetry && this.abandonedSubmitGates.add(gateId), this.emitProgress(
|
|
71416
71446
|
{
|
|
71417
71447
|
phase: "round_failed",
|
|
71418
71448
|
round: args.roundNumber,
|
|
@@ -73153,10 +73183,10 @@ ${section}`);
|
|
|
73153
73183
|
* error propagates (the caller surfaces it fail-closed).
|
|
73154
73184
|
*/
|
|
73155
73185
|
async submitImplementorOutputWithRetry(args) {
|
|
73156
|
-
let lastErr = null;
|
|
73186
|
+
let lastErr = null, replayedAfterEngineError = !1;
|
|
73157
73187
|
for (let attempt = 0; attempt < SUBMIT_OUTPUT_MAX_ATTEMPTS; attempt++)
|
|
73158
73188
|
try {
|
|
73159
|
-
|
|
73189
|
+
let result = await this.deps.appsyncClient.submitImplementorOutput(
|
|
73160
73190
|
{
|
|
73161
73191
|
taskId: args.taskId,
|
|
73162
73192
|
gateId: args.gateId,
|
|
@@ -73168,8 +73198,9 @@ ${section}`);
|
|
|
73168
73198
|
},
|
|
73169
73199
|
args.sessionKey
|
|
73170
73200
|
);
|
|
73201
|
+
return replayedAfterEngineError ? { ...result, replayedAfterEngineError } : result;
|
|
73171
73202
|
} catch (err) {
|
|
73172
|
-
if (lastErr = err, !isNotFoundError(lastErr) || attempt === SUBMIT_OUTPUT_MAX_ATTEMPTS - 1)
|
|
73203
|
+
if (lastErr = err, isPossiblyAfterWriteSubmitError(lastErr) && (replayedAfterEngineError = !0), isDefinitiveSubmitRejection(lastErr) || !(isNotFoundError(lastErr) || isPossiblyAfterWriteSubmitError(lastErr)) || attempt === SUBMIT_OUTPUT_MAX_ATTEMPTS - 1)
|
|
73173
73204
|
throw lastErr;
|
|
73174
73205
|
await this.sleep(SUBMIT_OUTPUT_BASE_DELAY_MS * Math.pow(2, attempt));
|
|
73175
73206
|
}
|
|
@@ -73177,6 +73208,13 @@ ${section}`);
|
|
|
73177
73208
|
}
|
|
73178
73209
|
// ─── §3.C.21 — REVIEWER_DISPATCH → spawn one seat ───────────────────────
|
|
73179
73210
|
async handleReviewerDispatch(payload) {
|
|
73211
|
+
if (this.abandonedSubmitGates.has(payload.gateId)) {
|
|
73212
|
+
logger.info("[QuorumLoop] ReviewerDispatch for an abandoned submission \u2014 dropped", {
|
|
73213
|
+
gateId: payload.gateId,
|
|
73214
|
+
seatId: payload.seatId
|
|
73215
|
+
});
|
|
73216
|
+
return;
|
|
73217
|
+
}
|
|
73180
73218
|
let dispatchTaskId = this.taskByGateId.get(payload.gateId), originEpoch = this.originEpochFor(dispatchTaskId), seat = numericSeatId(payload.seatId);
|
|
73181
73219
|
if (seat === null) {
|
|
73182
73220
|
logger.warn("[QuorumLoop] ReviewerDispatch with non-numeric seat \u2014 dropped", {
|
|
@@ -73214,6 +73252,10 @@ ${section}`);
|
|
|
73214
73252
|
*/
|
|
73215
73253
|
async spawnOneSeat(args) {
|
|
73216
73254
|
let key = seatKey(args.gateId, args.seatId);
|
|
73255
|
+
if (this.abandonedSubmitGates.has(args.gateId)) {
|
|
73256
|
+
logger.info("[QuorumLoop] seat spawn dropped (abandoned submission)", { key });
|
|
73257
|
+
return;
|
|
73258
|
+
}
|
|
73217
73259
|
if (this.runningSeats.has(key) || this.submittedSeats.has(key)) {
|
|
73218
73260
|
logger.info("[QuorumLoop] seat spawn no-op (already running/submitted)", { key });
|
|
73219
73261
|
return;
|
|
@@ -75932,6 +75974,27 @@ function diffCapturedProgress(round, files) {
|
|
|
75932
75974
|
deleted
|
|
75933
75975
|
};
|
|
75934
75976
|
}
|
|
75977
|
+
var SUBMIT_DEFINITIVE_ERROR_TYPES = /* @__PURE__ */ new Set([
|
|
75978
|
+
"ClientError",
|
|
75979
|
+
"SessionError",
|
|
75980
|
+
"Unauthorized",
|
|
75981
|
+
"CryptoError",
|
|
75982
|
+
"BudgetExhausted",
|
|
75983
|
+
"NotImplemented"
|
|
75984
|
+
]), RUST_WHITESPACE_ONLY = /^[\t\n\v\f\r \u0085\u00A0\u1680\u2000-\u200A\u2028\u2029\u202F\u205F\u3000]*$/;
|
|
75985
|
+
function isEngineEmptyArtifact(files) {
|
|
75986
|
+
return files.every(
|
|
75987
|
+
(f) => RUST_WHITESPACE_ONLY.test(f.content) && f.change_kind.trim().toLowerCase() !== "deleted"
|
|
75988
|
+
);
|
|
75989
|
+
}
|
|
75990
|
+
function isDefinitiveSubmitRejection(err) {
|
|
75991
|
+
let e = err;
|
|
75992
|
+
return e.reviewScopeResetUnsupported === !0 || e.name === "AppSyncGraphQLError" && typeof e.errorType == "string" && SUBMIT_DEFINITIVE_ERROR_TYPES.has(e.errorType);
|
|
75993
|
+
}
|
|
75994
|
+
function isPossiblyAfterWriteSubmitError(err) {
|
|
75995
|
+
let e = err;
|
|
75996
|
+
return e.name === "AppSyncGraphQLError" && typeof e.errorType == "string" && !isDefinitiveSubmitRejection(err);
|
|
75997
|
+
}
|
|
75935
75998
|
function isNotFoundError(err) {
|
|
75936
75999
|
let m = err.message.toLowerCase();
|
|
75937
76000
|
return m.includes("notfound") || m.includes("not found") || m.includes("not yet written") || m.includes("not present") || m.includes("gatenotfound");
|
|
@@ -86464,6 +86527,11 @@ async function runOrchestrationShellSession(args) {
|
|
|
86464
86527
|
}
|
|
86465
86528
|
), handleUserInput = (text2, images, options) => {
|
|
86466
86529
|
if (shellSubmissionsFenced) return Promise.resolve();
|
|
86530
|
+
if (args.appsyncClient && args.session?.userId && !args.appsyncClient.companionSyncStatusSnapshot?.(args.session.userId)) {
|
|
86531
|
+
let refreshAbort = new AbortController(), timeout = setTimeout(() => refreshAbort.abort(), 4500);
|
|
86532
|
+
timeout.unref?.(), args.appsyncClient.getCompanionSyncState(refreshAbort.signal).catch(() => {
|
|
86533
|
+
}).finally(() => clearTimeout(timeout));
|
|
86534
|
+
}
|
|
86467
86535
|
let submission = serializedHandleUserInput(text2, images, options);
|
|
86468
86536
|
return isShellSlashCommand(text2) || (activeShellSubmissions.add(submission), submission.then(
|
|
86469
86537
|
() => activeShellSubmissions.delete(submission),
|
|
@@ -57,6 +57,8 @@ export declare function failureReasonTemplate(agentKind: ReviewerAgentKind, reas
|
|
|
57
57
|
* "blocked by the local authority allowlist", etc.).
|
|
58
58
|
* - A spawn/start failure (ENOENT / "spawn" / "not found" on the agent binary)
|
|
59
59
|
* → a generic "the agent could not be started" label.
|
|
60
|
+
* - The engine's typed rejection of a submission (SB-67) → "the change is too large to submit for review"
|
|
61
|
+
* for PayloadTooLarge, else "the review service rejected the submission".
|
|
60
62
|
* - Anything else → a generic "an unexpected error occurred" label.
|
|
61
63
|
*
|
|
62
64
|
* Exported for the sanitization test (proves no raw message leaks).
|
|
@@ -1027,6 +1029,11 @@ export declare class QuorumLoop {
|
|
|
1027
1029
|
private readonly inFlightImplementorGates;
|
|
1028
1030
|
/** Gates whose implementor output has been submitted. */
|
|
1029
1031
|
private readonly submittedOutputGates;
|
|
1032
|
+
/**
|
|
1033
|
+
* SB-67 (Stage 1 R1-F1) — gates whose round failed after its submission started. The engine can dispatch reviewers
|
|
1034
|
+
* before it reports an error; a late dispatch for one of these gates belongs to a discarded task and is dropped.
|
|
1035
|
+
*/
|
|
1036
|
+
private readonly abandonedSubmitGates;
|
|
1030
1037
|
/**
|
|
1031
1038
|
* PHASE-CP-10-MIN (#585) #C10M-16 / Codex-H1 — the per-task ACTIVE
|
|
1032
1039
|
* implementor context. `runImplementorRound` populates it at spawn (wiring
|
|
@@ -3087,4 +3094,8 @@ export declare class QuorumLoop {
|
|
|
3087
3094
|
_replaceShadowForRound0UnlockedForTests(taskId: string): Promise<void>;
|
|
3088
3095
|
_ensureShadowUnlockedForTests(taskId: string): Promise<WorkspaceShadow>;
|
|
3089
3096
|
}
|
|
3097
|
+
export declare function isEngineEmptyArtifact(files: readonly {
|
|
3098
|
+
change_kind: string;
|
|
3099
|
+
content: string;
|
|
3100
|
+
}[]): boolean;
|
|
3090
3101
|
export { reviewerAgentToLeAgent, renderAgenticResolveBrief };
|
package/dist/prompt-parser.d.ts
CHANGED
|
@@ -40,10 +40,11 @@ export declare function parseInteractivePrompt(snapshot: string, options?: {
|
|
|
40
40
|
*/
|
|
41
41
|
export declare function normalizeSnapshot(snapshot: string): string;
|
|
42
42
|
export declare function countUnescapedBackticks(str: string): number;
|
|
43
|
+
export declare function extractPromptBlock(lines: string[], endIndex: number, boundedOptionBlock?: boolean, isApprovalPrompt?: boolean): string[];
|
|
43
44
|
export declare function isMcpHeadingLine(line: string): boolean;
|
|
44
45
|
export declare function isPromptHeadingLine(line: string): boolean;
|
|
45
|
-
import { parseInteractivePromptWithGemma, type TuiGemmaPort } from './tui-parser/gemma-tui-parser';
|
|
46
|
-
export { parseInteractivePromptWithGemma, type TuiGemmaPort };
|
|
46
|
+
import { parseInteractivePromptWithGemma, ModelPortUnavailableError, type TuiGemmaPort } from './tui-parser/gemma-tui-parser';
|
|
47
|
+
export { parseInteractivePromptWithGemma, ModelPortUnavailableError, type TuiGemmaPort };
|
|
47
48
|
/**
|
|
48
49
|
* Asynchronously parse an interactive prompt with model-based structured JSON parsing
|
|
49
50
|
* when available, respecting the CODEVIBE_TUI_PARSER operational kill-switch.
|
package/dist/terminal-menu.d.ts
CHANGED
|
@@ -14,6 +14,14 @@ export declare function selectTerminalMenuOption(identity: string, number: strin
|
|
|
14
14
|
key(key: 'Up' | 'Down' | 'Enter'): Promise<boolean>;
|
|
15
15
|
wait(): Promise<void>;
|
|
16
16
|
}): Promise<TerminalMenuDelivery>;
|
|
17
|
+
export interface StyledRow {
|
|
18
|
+
text: string;
|
|
19
|
+
bold: boolean;
|
|
20
|
+
dim: boolean;
|
|
21
|
+
highlighted: boolean;
|
|
22
|
+
}
|
|
23
|
+
/** Preserve the small amount of terminal style that identifies a live selector. */
|
|
24
|
+
export declare function styledRows(snapshot: string): StyledRow[];
|
|
17
25
|
/**
|
|
18
26
|
* Recognize a bottom-pane numbered selector, never a bare numbered list.
|
|
19
27
|
* Recognizes styled (bold) titles or prompt heading patterns (with bounded
|
|
@@ -21,8 +29,8 @@ export declare function selectTerminalMenuOption(identity: string, number: strin
|
|
|
21
29
|
* and a separate terminal footer with key hints.
|
|
22
30
|
*/
|
|
23
31
|
export declare function parseActiveTerminalMenu(snapshot: string): TerminalMenu | null;
|
|
24
|
-
import { parseActiveTerminalMenuWithGemma, type GemmaTerminalMenu, type TuiGemmaPort } from './tui-parser/gemma-tui-parser';
|
|
25
|
-
export { parseActiveTerminalMenuWithGemma, type GemmaTerminalMenu };
|
|
32
|
+
import { parseActiveTerminalMenuWithGemma, ModelPortUnavailableError, type GemmaTerminalMenu, type TuiGemmaPort } from './tui-parser/gemma-tui-parser';
|
|
33
|
+
export { parseActiveTerminalMenuWithGemma, ModelPortUnavailableError, type GemmaTerminalMenu };
|
|
26
34
|
/**
|
|
27
35
|
* Asynchronously parse an active terminal menu using Gemma structured JSON when available,
|
|
28
36
|
* respecting the CODEVIBE_TUI_PARSER operational kill-switch.
|
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
import type { ParsedInteractivePrompt } from '../prompt-parser';
|
|
2
|
+
export declare class ModelPortUnavailableError extends Error {
|
|
3
|
+
readonly cause?: unknown | undefined;
|
|
4
|
+
constructor(message: string, cause?: unknown | undefined);
|
|
5
|
+
}
|
|
2
6
|
export interface TuiGemmaPort {
|
|
3
7
|
classify(req: {
|
|
4
8
|
prompt: string;
|
|
@@ -34,6 +38,7 @@ export declare function parseTuiGemmaResponse(raw: string): RawGemmaTuiResponse
|
|
|
34
38
|
export declare function parseRawTuiWithGemma(snapshot: string, port: TuiGemmaPort, opts?: {
|
|
35
39
|
timeoutMs?: number;
|
|
36
40
|
signal?: AbortSignal;
|
|
41
|
+
rethrowPortErrors?: boolean;
|
|
37
42
|
}): Promise<RawGemmaTuiResponse | null>;
|
|
38
43
|
/**
|
|
39
44
|
* Parse an interactive terminal prompt using Gemma with structured JSON.
|
|
@@ -42,6 +47,8 @@ export declare function parseRawTuiWithGemma(snapshot: string, port: TuiGemmaPor
|
|
|
42
47
|
export declare function parseInteractivePromptWithGemma(snapshot: string, port: TuiGemmaPort, opts?: {
|
|
43
48
|
timeoutMs?: number;
|
|
44
49
|
signal?: AbortSignal;
|
|
50
|
+
boundedOptionBlock?: boolean;
|
|
51
|
+
rethrowPortErrors?: boolean;
|
|
45
52
|
}): Promise<ParsedInteractivePrompt | null>;
|
|
46
53
|
/** Check whether an option's label matches its row text without altering meaning or imposing ASCII word boundaries (Codex R51-F2). */
|
|
47
54
|
export declare function isOptionTextRowMatch(rowContent: string, label: string): boolean;
|
|
@@ -49,12 +56,27 @@ export interface GroundedMenuRow {
|
|
|
49
56
|
optionNumber: string;
|
|
50
57
|
rowText: string;
|
|
51
58
|
lineIndex: number;
|
|
59
|
+
fullSpanText?: string;
|
|
60
|
+
fullSpanJoinedNoSpace?: string;
|
|
61
|
+
continuationLines?: string[];
|
|
52
62
|
}
|
|
53
63
|
/**
|
|
54
64
|
* Extract candidate option rows from snapshot and isolate the single active menu block
|
|
55
65
|
* at the bottom of the snapshot, ignoring stale options in prior scrollback blocks (Codex R52-F2).
|
|
56
66
|
*/
|
|
57
67
|
export declare function getActiveMenuBlock(snapshot: string): GroundedMenuRow[];
|
|
68
|
+
/**
|
|
69
|
+
* Enumerate possible string joins for multi-line wrapped option rows (Codex R3-F4, R4-F4, R5-F3).
|
|
70
|
+
* Each continuation line can be joined with either a space (' ') or without space ('') for mid-token wraps.
|
|
71
|
+
* For up to 10 continuation lines, enumerates full combinations. For >10 lines, generates complete
|
|
72
|
+
* space and no-space joins without returning truncated combinations.
|
|
73
|
+
*/
|
|
74
|
+
export declare function enumerateWrappedRowJoins(rowText: string, continuations: string[]): string[];
|
|
75
|
+
/**
|
|
76
|
+
* Progressive prefix-pruned matcher for multi-line wrapped option rows (Codex R4-F4, R5-F3, R6-F3, R6-F4).
|
|
77
|
+
* Matches complete continuation spans without arbitrary length truncation while supporting full normalization.
|
|
78
|
+
*/
|
|
79
|
+
export declare function isWrappedOptionMatch(rowText: string, continuations: string[], targetText: string): boolean;
|
|
58
80
|
/**
|
|
59
81
|
* Structured TerminalMenu returned by Gemma TUI parser.
|
|
60
82
|
*/
|
|
@@ -71,4 +93,5 @@ export interface GemmaTerminalMenu {
|
|
|
71
93
|
export declare function parseActiveTerminalMenuWithGemma(snapshot: string, port: TuiGemmaPort, opts?: {
|
|
72
94
|
timeoutMs?: number;
|
|
73
95
|
signal?: AbortSignal;
|
|
96
|
+
rethrowPortErrors?: boolean;
|
|
74
97
|
}): Promise<GemmaTerminalMenu | null>;
|
|
@@ -1 +1,2 @@
|
|
|
1
|
-
export { parseInteractivePromptWithGemma, parseActiveTerminalMenuWithGemma, hasInteractivePromptMarkers, buildTuiParserPrompt, parseTuiGemmaResponse, isOptionTextRowMatch, TUI_PARSER_JSON_SCHEMA, type TuiGemmaPort, type RawGemmaTuiOption, type RawGemmaTuiResponse, type GemmaTerminalMenu, } from './gemma-tui-parser';
|
|
1
|
+
export { parseInteractivePromptWithGemma, parseActiveTerminalMenuWithGemma, getActiveMenuBlock, enumerateWrappedRowJoins, isWrappedOptionMatch, ModelPortUnavailableError, hasInteractivePromptMarkers, buildTuiParserPrompt, parseTuiGemmaResponse, isOptionTextRowMatch, TUI_PARSER_JSON_SCHEMA, type TuiGemmaPort, type RawGemmaTuiOption, type RawGemmaTuiResponse, type GemmaTerminalMenu, type GroundedMenuRow, } from './gemma-tui-parser';
|
|
2
|
+
export { createTuiGemmaPortFromRunner, createHostedTuiGemmaPort, } from './port-adapters';
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { AppSyncClient } from '../appsync';
|
|
2
|
+
import type { GemmaRunner } from '../planner/gemma-runner';
|
|
3
|
+
import type { TuiGemmaPort } from './gemma-tui-parser';
|
|
4
|
+
export declare class ModelPortUnavailableError extends Error {
|
|
5
|
+
readonly cause?: unknown | undefined;
|
|
6
|
+
constructor(message: string, cause?: unknown | undefined);
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Creates a TuiGemmaPort over any GemmaRunner (local or hosted).
|
|
10
|
+
*/
|
|
11
|
+
export declare function createTuiGemmaPortFromRunner(runner: GemmaRunner): TuiGemmaPort;
|
|
12
|
+
/**
|
|
13
|
+
* Creates a hosted TuiGemmaPort backed by AppSync and the session key.
|
|
14
|
+
* This is suitable for companion daemons (Codex, Claude, etc.) that have an active AppSyncClient
|
|
15
|
+
* and access to the session key.
|
|
16
|
+
*/
|
|
17
|
+
export declare function createHostedTuiGemmaPort(appsyncClient: AppSyncClient, getSessionId: () => string | null | undefined, getTier?: () => string | null | undefined): TuiGemmaPort;
|
package/package.json
CHANGED