@quantiya/codevibe-core 2.0.88 → 2.0.90
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/companion-mode/codex-native-dispatcher.d.ts +43 -0
- package/dist/companion-mode/codex-native-state.d.ts +1151 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +582 -582
- package/dist/local-executor/binary-classifier.d.ts +117 -0
- package/dist/local-executor/office-extractor.d.ts +61 -0
- package/dist/orchestration-shell/cli.js +83 -20
- package/dist/orchestration-shell/gemma-intent-classifier.d.ts +1 -0
- package/dist/planner/local-gemma.d.ts +29 -20
- package/package.json +1 -1
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
/** Random access to one immutable file. The caller owns opening and closing it. */
|
|
2
|
+
export interface FileSource {
|
|
3
|
+
size: number;
|
|
4
|
+
read(position: number, length: number): Promise<Buffer>;
|
|
5
|
+
}
|
|
6
|
+
export type OfficeFormat = 'docx' | 'xlsx' | 'pptx';
|
|
7
|
+
export type FileClass = {
|
|
8
|
+
kind: 'text';
|
|
9
|
+
} | {
|
|
10
|
+
kind: 'office';
|
|
11
|
+
format: OfficeFormat;
|
|
12
|
+
} | {
|
|
13
|
+
kind: 'image';
|
|
14
|
+
format: 'png' | 'jpeg' | 'gif' | 'webp' | 'heic';
|
|
15
|
+
} | {
|
|
16
|
+
kind: 'pdf';
|
|
17
|
+
} | {
|
|
18
|
+
kind: 'other';
|
|
19
|
+
format: 'audio' | 'video' | 'archive' | 'other_binary';
|
|
20
|
+
};
|
|
21
|
+
/** §10.2: per-part inflate output limit (64 MiB). */
|
|
22
|
+
export declare const MAX_OFFICE_PART_BYTES: number;
|
|
23
|
+
/**
|
|
24
|
+
* Per-archive cumulative inflated output limit (256 MiB) across all parts of one
|
|
25
|
+
* Office file version, bounding total memory and inflate work on multi-part archives.
|
|
26
|
+
*/
|
|
27
|
+
export declare const MAX_OFFICE_ARCHIVE_INFLATED_BYTES: number;
|
|
28
|
+
/** Initial header scan length (8 KiB) for magic detection and initial UTF-8/NUL check. */
|
|
29
|
+
export declare const HEADER_SCAN_BYTES: number;
|
|
30
|
+
/** Chunk size (64 KiB) for streaming full-file strict UTF-8 and NUL verification. */
|
|
31
|
+
export declare const UTF8_SCAN_CHUNK_BYTES: number;
|
|
32
|
+
/**
|
|
33
|
+
* Compute standard IEEE 802.3 CRC32 of `buf` as an unsigned 32-bit integer (`0..0xffffffff`).
|
|
34
|
+
* Uses a deterministic lookup table so CRC32 verification works across all Node.js >= 22.0.0
|
|
35
|
+
* runtimes without depending on `zlib.crc32` (added in Node 22.2.0).
|
|
36
|
+
*/
|
|
37
|
+
export declare function computeCrc32(buf: Buffer): number;
|
|
38
|
+
export interface ZipEntryMeta {
|
|
39
|
+
name: string;
|
|
40
|
+
method: number;
|
|
41
|
+
flags: number;
|
|
42
|
+
crc32: number;
|
|
43
|
+
compressedSize: number;
|
|
44
|
+
uncompressedSize: number;
|
|
45
|
+
localHeaderOffset: number;
|
|
46
|
+
}
|
|
47
|
+
export interface ZipArchiveMeta {
|
|
48
|
+
cdOffset: number;
|
|
49
|
+
entries: Map<string, ZipEntryMeta>;
|
|
50
|
+
}
|
|
51
|
+
export type ZipInspectResult = {
|
|
52
|
+
ok: true;
|
|
53
|
+
archive: ZipArchiveMeta;
|
|
54
|
+
} | {
|
|
55
|
+
ok: false;
|
|
56
|
+
reason: 'zip64' | 'part_too_large' | 'malformed';
|
|
57
|
+
};
|
|
58
|
+
export type ZipEntryReadResult = {
|
|
59
|
+
ok: true;
|
|
60
|
+
bytes: Buffer;
|
|
61
|
+
} | {
|
|
62
|
+
ok: false;
|
|
63
|
+
reason: 'zip64' | 'part_too_large' | 'malformed';
|
|
64
|
+
};
|
|
65
|
+
/**
|
|
66
|
+
* Read up to `length` bytes starting at `position`, looping across short reads.
|
|
67
|
+
* Returns `null` if EOF is reached before `length` bytes or arguments are out of range.
|
|
68
|
+
* Rejections from `source.read` propagate untouched.
|
|
69
|
+
*/
|
|
70
|
+
export declare function readExact(source: FileSource, position: number, length: number): Promise<Buffer | null>;
|
|
71
|
+
/**
|
|
72
|
+
* Validate a ZIP central-directory entry name:
|
|
73
|
+
* - non-empty and bounded length
|
|
74
|
+
* - no ASCII or C1 control characters (`\p{Cc}`), format/bidi/BOM characters (`\p{Cf}`),
|
|
75
|
+
* or Unicode line/paragraph separators (`\p{Zl}`, `\p{Zp}`)
|
|
76
|
+
* - no backslashes (`\`) or leading `/`
|
|
77
|
+
* - no empty (`//`), `.`, or `..` path segments
|
|
78
|
+
*/
|
|
79
|
+
export declare function isSafeZipPartName(name: string): boolean;
|
|
80
|
+
/**
|
|
81
|
+
* Parse a ZIP archive's End of Central Directory and Central Directory via random access.
|
|
82
|
+
* Refuses ZIP64 archives (`reason: 'zip64'`), oversized central directories (`reason: 'part_too_large'`),
|
|
83
|
+
* and malformed/unsafe/duplicate part names (`reason: 'malformed'`).
|
|
84
|
+
*/
|
|
85
|
+
export declare function inspectZipArchive(source: FileSource): Promise<ZipInspectResult>;
|
|
86
|
+
/**
|
|
87
|
+
* Read and inflate one entry from a validated ZIP archive, enforcing the 64 MiB
|
|
88
|
+
* per-part bound, verifying local file header consistency, and checking CRC32 integrity.
|
|
89
|
+
*/
|
|
90
|
+
export declare function readZipEntryBytes(source: FileSource, archive: ZipArchiveMeta, entry: ZipEntryMeta): Promise<ZipEntryReadResult>;
|
|
91
|
+
/**
|
|
92
|
+
* Find the index past the closing `>` of an XML declaration (`<!DOCTYPE ...>`,
|
|
93
|
+
* `<!ENTITY ...>`, etc.) starting at `lt` (`xml.startsWith('<!', lt)`),
|
|
94
|
+
* respecting quoted strings (`"..."`, `'...'`), nested comments (`<!-- ... -->`),
|
|
95
|
+
* nested processing instructions (`<? ... ?>`), and internal DTD subset brackets (`[ ... ]`).
|
|
96
|
+
* Returns `-1` if the declaration is unclosed.
|
|
97
|
+
*/
|
|
98
|
+
export declare function findXmlDeclarationEnd(xml: string, lt: number): number;
|
|
99
|
+
/**
|
|
100
|
+
* Linear O(N) stripper for XML comments (`<!-- ... -->`), processing instructions (`<? ... ?>`),
|
|
101
|
+
* CDATA sections (`<![CDATA[ ... ]]>`), and DOCTYPE/declarations (`<! ... >`).
|
|
102
|
+
* Used when inspecting structural XML tags so commented-out or DTD-declared elements are ignored.
|
|
103
|
+
*/
|
|
104
|
+
export declare function stripXmlCommentsAndDeclarations(xml: string): string;
|
|
105
|
+
/**
|
|
106
|
+
* Detect whether `[Content_Types].xml` names a WordprocessingML (`docx`),
|
|
107
|
+
* SpreadsheetML (`xlsx`), or PresentationML (`pptx`) main part.
|
|
108
|
+
* Strips XML comments and declarations first so commented-out `<Override>` elements are ignored.
|
|
109
|
+
* Returns `'ambiguous'` if multiple distinct Office main content types are present.
|
|
110
|
+
*/
|
|
111
|
+
export declare function detectOfficeFormatFromContentTypes(contentTypesXml: string): OfficeFormat | 'ambiguous' | null;
|
|
112
|
+
/** Verify that the archive contains the structural parts required for `format`. */
|
|
113
|
+
export declare function hasRequiredOfficeMainParts(entries: Map<string, ZipEntryMeta>, format: OfficeFormat): boolean;
|
|
114
|
+
/**
|
|
115
|
+
* Classify `source` according to §10.1 (`text`, `office`, `image`, `pdf`, or `other`).
|
|
116
|
+
*/
|
|
117
|
+
export declare function classifyFile(source: FileSource): Promise<FileClass>;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { type FileSource, type OfficeFormat } from './binary-classifier';
|
|
2
|
+
export type { FileSource, OfficeFormat } from './binary-classifier';
|
|
3
|
+
export interface OfficePartChange {
|
|
4
|
+
part: string;
|
|
5
|
+
change: 'added' | 'removed' | 'modified';
|
|
6
|
+
mark: 'text changed' | 'no text change — inspect the part';
|
|
7
|
+
}
|
|
8
|
+
export type OfficeExtraction = {
|
|
9
|
+
ok: true;
|
|
10
|
+
format: OfficeFormat;
|
|
11
|
+
beforeText: string | null;
|
|
12
|
+
afterText: string;
|
|
13
|
+
parts: OfficePartChange[];
|
|
14
|
+
} | {
|
|
15
|
+
ok: false;
|
|
16
|
+
fallback: 'other_binary';
|
|
17
|
+
reason: 'zip64' | 'part_too_large' | 'malformed';
|
|
18
|
+
};
|
|
19
|
+
/**
|
|
20
|
+
* Maximum cumulative extracted text characters and element-overhead units (32 MiB)
|
|
21
|
+
* per Office archive version, preventing memory exhaustion or V8 RangeError on
|
|
22
|
+
* high-expansion shared-string or dense-element inputs.
|
|
23
|
+
*/
|
|
24
|
+
export declare const MAX_OFFICE_EXTRACTED_TEXT_BYTES: number;
|
|
25
|
+
/**
|
|
26
|
+
* Maximum cumulative decoded XML characters (64 MiB) across all extracted XML parts
|
|
27
|
+
* of one Office archive version before text extraction runs.
|
|
28
|
+
*/
|
|
29
|
+
export declare const MAX_OFFICE_DECODED_XML_CHARS: number;
|
|
30
|
+
/**
|
|
31
|
+
* Per-element budget charge (64 bytes) applied to structural XML elements (`<si>`, `<c>`,
|
|
32
|
+
* `<sheet>`, `<definedName>`, `<Relationship>`, `<p:sldId>`, `<w:p>`, `<a:p>`, `<w:comment>`,
|
|
33
|
+
* and inner elements buffered inside `<w:comment>`) so millions of empty tags
|
|
34
|
+
* (`<si/>`, `<c/>`, `<sheet/>`, `<a>`) cannot allocate unbounded arrays.
|
|
35
|
+
*/
|
|
36
|
+
export declare const ELEMENT_BUDGET_OVERHEAD = 64;
|
|
37
|
+
/**
|
|
38
|
+
* Per-chunk budget charge (32 bytes) applied alongside character length whenever a
|
|
39
|
+
* text fragment is pushed into an intermediate chunk array or string accumulator,
|
|
40
|
+
* bounding V8 array/string-object overhead on millions of tiny text runs.
|
|
41
|
+
*/
|
|
42
|
+
export declare const CHUNK_BUDGET_OVERHEAD = 32;
|
|
43
|
+
declare class TextBudget {
|
|
44
|
+
private readonly limit;
|
|
45
|
+
private used;
|
|
46
|
+
constructor(limit?: number);
|
|
47
|
+
add(chars: number): boolean;
|
|
48
|
+
get exceeded(): boolean;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Decode standard XML named and numeric character entities in a single linear O(N) pass
|
|
52
|
+
* without global regex replacement (`Runtime_RegExpExecMultiple`). Caches `nextSemi` so
|
|
53
|
+
* semicolons are never rescanned across multiple `&` characters, emits slices only when
|
|
54
|
+
* a valid entity is decoded (charging `CHUNK_BUDGET_OVERHEAD` per decoded entity when a
|
|
55
|
+
* budget is supplied), and leaves undecoded `&` sequences in the original contiguous
|
|
56
|
+
* string slice with zero intermediate string allocations. Doubly-escaped sequences
|
|
57
|
+
* (e.g. `&lt;` or `&#65;`) are decoded once.
|
|
58
|
+
*/
|
|
59
|
+
export declare function decodeXmlEntities(raw: string, budget?: TextBudget): string;
|
|
60
|
+
/** `before` is null for a created file. A deletion needs no extraction text beyond the `before/` original. */
|
|
61
|
+
export declare function extractOfficeChange(before: FileSource | null, after: FileSource): Promise<OfficeExtraction>;
|
|
@@ -24263,7 +24263,13 @@ var AppSyncClient = class _AppSyncClient {
|
|
|
24263
24263
|
this.assertSyncAccount(userId);
|
|
24264
24264
|
let session2 = await this.getSession(state.sessionId);
|
|
24265
24265
|
if (!current()) return;
|
|
24266
|
-
if (this.assertSyncAccount(userId), !session2 || session2.userId !== userId ||
|
|
24266
|
+
if (this.assertSyncAccount(userId), !session2 || session2.sessionId !== state.sessionId || session2.userId !== userId || state.syncSessionGenerationId !== void 0 && session2.sessionGenerationId !== state.syncSessionGenerationId)
|
|
24267
|
+
throw new SyncEventClientError("SYNC_SESSION_UNAVAILABLE");
|
|
24268
|
+
if (session2.status === "INACTIVE" /* INACTIVE */ && session2.sessionGenerationId) {
|
|
24269
|
+
this.notifyRetiredSession(state.sessionId);
|
|
24270
|
+
return;
|
|
24271
|
+
}
|
|
24272
|
+
if (!["ACTIVE" /* ACTIVE */, "PAUSED" /* PAUSED */].includes(session2.status))
|
|
24267
24273
|
throw new SyncEventClientError("SYNC_SESSION_UNAVAILABLE");
|
|
24268
24274
|
let retainedIds = /* @__PURE__ */ new Set();
|
|
24269
24275
|
state.mobileInputRecoveryHeld = !1, session2.sessionGenerationId && (state.compatibilityInboundIds = retainedIds, state.syncSessionGenerationId = session2.sessionGenerationId), this.createLegacySubscription(state), !(!session2.sessionGenerationId || !current()) && (async () => {
|
|
@@ -25289,11 +25295,23 @@ var AppSyncClient = class _AppSyncClient {
|
|
|
25289
25295
|
sessionId,
|
|
25290
25296
|
lastHeartbeatAt: heartbeatAt
|
|
25291
25297
|
});
|
|
25292
|
-
|
|
25298
|
+
if (this.heartbeatTokens.get(sessionId) !== token4 || refreshed.status !== "ACTIVE" /* ACTIVE */ && (await this.updateSession({
|
|
25293
25299
|
sessionId,
|
|
25294
25300
|
lastHeartbeatAt: heartbeatAt,
|
|
25295
25301
|
status: "ACTIVE" /* ACTIVE */
|
|
25296
|
-
}), this.heartbeatTokens.get(sessionId) !== token4)
|
|
25302
|
+
}), this.heartbeatTokens.get(sessionId) !== token4))
|
|
25303
|
+
return "stopped";
|
|
25304
|
+
if (this.syncDisplayListeners.size > 0 && this.authenticated && this.currentUserId) {
|
|
25305
|
+
let userId = this.currentUserId;
|
|
25306
|
+
if (Array.from(this.syncDisplayListeners).some(
|
|
25307
|
+
(entry5) => entry5.userId === userId
|
|
25308
|
+
) && !this.companionSyncStatusSnapshot(userId)) {
|
|
25309
|
+
let refreshAbort = new AbortController(), refreshDeadline = setTimeout(() => refreshAbort.abort(), 4500);
|
|
25310
|
+
refreshDeadline.unref?.(), this.refreshCompanionSyncDisplayOnMaintenance(userId, refreshAbort.signal).catch(() => {
|
|
25311
|
+
}).finally(() => clearTimeout(refreshDeadline));
|
|
25312
|
+
}
|
|
25313
|
+
}
|
|
25314
|
+
return logger.debug("[AppSyncClient] Heartbeat sent", { sessionId }), "confirmed";
|
|
25297
25315
|
} catch (error) {
|
|
25298
25316
|
return logger.warn("[AppSyncClient] Heartbeat failed", { sessionId, error }), isRetiredSessionError(error) ? "retired" : "failed";
|
|
25299
25317
|
}
|
|
@@ -28797,22 +28815,43 @@ var LOCAL_GEMMA_ALLOWED_OUTPUT_KEYS = /* @__PURE__ */ new Set([
|
|
|
28797
28815
|
// would throw "included unsupported keys" on every browse decision.
|
|
28798
28816
|
"browseUrls",
|
|
28799
28817
|
"browseQuery"
|
|
28800
|
-
]), LOCAL_GEMMA_NULLABLE_OUTPUT_KEYS = ["clarifying_question", "advisory_summary", "browseUrls", "browseQuery"];
|
|
28801
|
-
function
|
|
28818
|
+
]), LOCAL_GEMMA_NULLABLE_OUTPUT_KEYS = ["clarifying_question", "advisory_summary", "browseUrls", "browseQuery"], LOCAL_GEMMA_DECISION_REQUIRED_KEYS = ["rationale", "clarifying_question", "advisory_summary", "browseUrls", "browseQuery", "action"], LOCAL_GEMMA_FIELD_CARRYING_ACTIONS = /* @__PURE__ */ new Set(["browse", "ask_user", "advisory_response"]);
|
|
28819
|
+
function decisionBranch(actions, fields) {
|
|
28802
28820
|
return {
|
|
28803
28821
|
type: "object",
|
|
28804
28822
|
properties: {
|
|
28805
28823
|
rationale: { type: "string" },
|
|
28806
|
-
clarifying_question:
|
|
28807
|
-
advisory_summary:
|
|
28808
|
-
browseUrls:
|
|
28809
|
-
browseQuery:
|
|
28810
|
-
action: { type: "string", enum:
|
|
28824
|
+
clarifying_question: fields.clarifying_question,
|
|
28825
|
+
advisory_summary: fields.advisory_summary,
|
|
28826
|
+
browseUrls: fields.browseUrls,
|
|
28827
|
+
browseQuery: fields.browseQuery,
|
|
28828
|
+
action: { type: "string", enum: actions }
|
|
28811
28829
|
},
|
|
28812
|
-
required: [
|
|
28830
|
+
required: [...LOCAL_GEMMA_DECISION_REQUIRED_KEYS],
|
|
28813
28831
|
additionalProperties: !1
|
|
28814
28832
|
};
|
|
28815
28833
|
}
|
|
28834
|
+
function buildLocalGemmaDecisionJsonSchema() {
|
|
28835
|
+
let nul = { type: "null" }, otherActions = [...localGemmaAllowedActions()].filter((a) => !LOCAL_GEMMA_FIELD_CARRYING_ACTIONS.has(a));
|
|
28836
|
+
return {
|
|
28837
|
+
anyOf: [
|
|
28838
|
+
decisionBranch(["browse"], {
|
|
28839
|
+
clarifying_question: nul,
|
|
28840
|
+
advisory_summary: nul,
|
|
28841
|
+
browseUrls: { type: ["array", "null"], items: { type: "string" } },
|
|
28842
|
+
browseQuery: { type: ["string", "null"] }
|
|
28843
|
+
}),
|
|
28844
|
+
decisionBranch(["ask_user"], { clarifying_question: { type: "string" }, advisory_summary: nul, browseUrls: nul, browseQuery: nul }),
|
|
28845
|
+
decisionBranch(["advisory_response"], {
|
|
28846
|
+
clarifying_question: nul,
|
|
28847
|
+
advisory_summary: { type: ["string", "null"] },
|
|
28848
|
+
browseUrls: nul,
|
|
28849
|
+
browseQuery: nul
|
|
28850
|
+
}),
|
|
28851
|
+
decisionBranch(otherActions, { clarifying_question: nul, advisory_summary: nul, browseUrls: nul, browseQuery: nul })
|
|
28852
|
+
]
|
|
28853
|
+
};
|
|
28854
|
+
}
|
|
28816
28855
|
var LOCAL_GEMMA_DECISION_JSON_SCHEMA = buildLocalGemmaDecisionJsonSchema();
|
|
28817
28856
|
var LOCAL_GEMMA_MAX_USER_PROMPT_CHARS = 4e3, LOCAL_GEMMA_MAX_CLARIFICATIONS = 4, LOCAL_GEMMA_MAX_CLARIFICATION_QUESTION_CHARS = 300, LOCAL_GEMMA_MAX_CLARIFICATION_ANSWER_CHARS = 900, LOCAL_GEMMA_MAX_CANONICAL_CONTEXT_CHARS = 6e3, LOCAL_GEMMA_MAX_RENDERED_PROMPT_CHARS = 24e3;
|
|
28818
28857
|
function truncatePlannerTextPreservingEnds(text2, maxChars) {
|
|
@@ -29170,7 +29209,7 @@ function parseLocalGemmaPlannerDecision(raw) {
|
|
|
29170
29209
|
throw validationError("Gemma planner browse output must not include advisory_summary or clarifying_question", obj, canDegrade);
|
|
29171
29210
|
} else {
|
|
29172
29211
|
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"))
|
|
29212
|
+
if ((hasRealBrowseUrls || hasRealBrowseQuery) && (userFacingPlannerText || taskStartingAction || obj.action === "advisory_response" && hasRealBrowseQuery || obj.action === "refuse" || obj.action === "ask_user"))
|
|
29174
29213
|
throw new PlannerOutputUnparseableError(
|
|
29175
29214
|
"Gemma planner non-browse output must not combine browse fields with user-facing or task-starting planner output",
|
|
29176
29215
|
{ kind: "validation" }
|
|
@@ -77317,7 +77356,7 @@ function OrchestrationApp(props) {
|
|
|
77317
77356
|
setLiveRuntimeKind(kind), setLiveRuntimeLabel(props.plannerLabel ?? "");
|
|
77318
77357
|
});
|
|
77319
77358
|
}, [props.plannerPipeline, props.plannerLabel]);
|
|
77320
|
-
let [syncDisplay, setSyncDisplay] = React22.useState(null), syncDisplayRef = React22.useRef(syncDisplay), syncOwner = state.session.userId;
|
|
77359
|
+
let [syncDisplay, setSyncDisplay] = React22.useState(null), [syncBootstrapSettledFor, setSyncBootstrapSettledFor] = React22.useState(null), syncDisplayRef = React22.useRef(syncDisplay), syncOwner = state.session.userId;
|
|
77321
77360
|
React22.useEffect(() => {
|
|
77322
77361
|
let source2 = props.companionSyncStateSource;
|
|
77323
77362
|
if (!source2) return;
|
|
@@ -77325,16 +77364,19 @@ function OrchestrationApp(props) {
|
|
|
77325
77364
|
if (!active) return;
|
|
77326
77365
|
clearTimeout(expiry);
|
|
77327
77366
|
let display = { userId: syncOwner, state: next };
|
|
77328
|
-
syncDisplayRef.current = display, setSyncDisplay(display), next && (expiry = setTimeout(() => update(null), Math.max(0, next.validUntilEpochMs - Date.now())), expiry.unref?.());
|
|
77367
|
+
syncDisplayRef.current = display, setSyncDisplay(display), next && (setSyncBootstrapSettledFor(syncOwner), expiry = setTimeout(() => update(null), Math.max(0, next.validUntilEpochMs - Date.now())), expiry.unref?.());
|
|
77329
77368
|
};
|
|
77330
|
-
update(null);
|
|
77369
|
+
setSyncBootstrapSettledFor(null), update(null);
|
|
77331
77370
|
try {
|
|
77332
77371
|
unsubscribe = source2.subscribeCompanionSyncState(syncOwner, update);
|
|
77333
77372
|
} catch {
|
|
77373
|
+
active && setSyncBootstrapSettledFor(syncOwner);
|
|
77334
77374
|
}
|
|
77335
77375
|
let deadline = setTimeout(() => abort.abort(), 4500);
|
|
77336
77376
|
return deadline.unref?.(), Promise.resolve().then(() => source2.getCompanionSyncState(abort.signal)).catch(() => {
|
|
77337
|
-
}).finally(() =>
|
|
77377
|
+
}).finally(() => {
|
|
77378
|
+
clearTimeout(deadline), active && setSyncBootstrapSettledFor(syncOwner);
|
|
77379
|
+
}), () => {
|
|
77338
77380
|
active = !1, clearTimeout(expiry), clearTimeout(deadline), abort.abort(), unsubscribe?.();
|
|
77339
77381
|
};
|
|
77340
77382
|
}, [props.companionSyncStateSource, syncOwner]);
|
|
@@ -77613,7 +77655,7 @@ ${formatImplementorPolicy(detected, updated, props.tier)}`
|
|
|
77613
77655
|
tier: props.tier,
|
|
77614
77656
|
plannerRuntimeKind: liveRuntimeKind,
|
|
77615
77657
|
plannerLabel: liveRuntimeLabel,
|
|
77616
|
-
companionSyncBadge: props.companionSyncStateSource ? companionSyncBadge(syncDisplay?.userId === syncOwner ? syncDisplay.state : null) : null
|
|
77658
|
+
companionSyncBadge: props.companionSyncStateSource && (syncDisplay?.userId === syncOwner && syncDisplay.state || syncBootstrapSettledFor === syncOwner) ? companionSyncBadge(syncDisplay?.userId === syncOwner ? syncDisplay.state : null) : null
|
|
77617
77659
|
}),
|
|
77618
77660
|
// CP-12 W3 §3.5 — minimal multi-track status node, mounted ONLY when a team
|
|
77619
77661
|
// is active. Single-track / Companion sessions leave `state.team`
|
|
@@ -83897,7 +83939,7 @@ var INTENT_CLASSIFIER_JSON_SCHEMA = {
|
|
|
83897
83939
|
rationale: { type: "string" }
|
|
83898
83940
|
},
|
|
83899
83941
|
required: ["action", "is_code_or_disk_mutation", "confidence", "requires_file_read", "rationale"]
|
|
83900
|
-
}, DEFAULT_INTENT_TIMEOUT_MS =
|
|
83942
|
+
}, DEFAULT_INTENT_TIMEOUT_MS = 3e4, INTENT_MAX_OUTPUT_TOKENS = 256;
|
|
83901
83943
|
function buildIntentClassifierPrompt(prompt, clarifications) {
|
|
83902
83944
|
return [
|
|
83903
83945
|
"You are a strict code/workspace intent classifier for CodeVibe.",
|
|
@@ -86714,7 +86756,7 @@ async function runOrchestrationShellSession(args) {
|
|
|
86714
86756
|
{ teardownDeadlineExpired: !0 }
|
|
86715
86757
|
) : void 0,
|
|
86716
86758
|
start: () => {
|
|
86717
|
-
shellSubmissionsFenced = !0, shellSyncRecovery.stop(), fenceHostedSessionIngress(), taskOrdinalsAtEarlyRelease = store.getState().taskOrdinals.size, earlySessionWorkRelease = releaseSessionWorkBeforeRetirement();
|
|
86759
|
+
shellSubmissionsFenced = !0, activeBrowseAbortController?.abort(), shellSyncRecovery.stop(), fenceHostedSessionIngress(), taskOrdinalsAtEarlyRelease = store.getState().taskOrdinals.size, earlySessionWorkRelease = releaseSessionWorkBeforeRetirement();
|
|
86718
86760
|
let splitLocalDurableRetirement = typeof args.localExecutor?.disposeDurableSessionResources == "function", workspaceShutdown = startWorkspaceShutdownOperations({
|
|
86719
86761
|
...args.plannerAdapter || args.localAdvisoryRunner ? {
|
|
86720
86762
|
clearPlannerSession: () => {
|
|
@@ -91342,6 +91384,13 @@ async function handleShellUserInput(deps) {
|
|
|
91342
91384
|
} finally {
|
|
91343
91385
|
stopClassifyRelabel?.();
|
|
91344
91386
|
}
|
|
91387
|
+
if (browseSignal?.aborted) {
|
|
91388
|
+
logger.info(
|
|
91389
|
+
"[orchestration-shell] Planner classify turn aborted via browseSignal; returning silently",
|
|
91390
|
+
{ prompt: plannerInput.prompt }
|
|
91391
|
+
), clearPendingClarificationIfPresent(store);
|
|
91392
|
+
return;
|
|
91393
|
+
}
|
|
91345
91394
|
logger.info("[orchestration-shell] Planner classified input", {
|
|
91346
91395
|
prompt: plannerInput.prompt,
|
|
91347
91396
|
action: decision.action,
|
|
@@ -91354,8 +91403,16 @@ async function handleShellUserInput(deps) {
|
|
|
91354
91403
|
if ((decision.action === "start_task" || decision.action === "browse") && args.localAdvisoryRunner && process.env.CODEVIBE_INTENT_CLASSIFIER !== "regex") {
|
|
91355
91404
|
let gemmaIntent = await classifyPromptIntentWithGemma(
|
|
91356
91405
|
{ prompt: plannerInput.prompt, clarifications: plannerInput.clarifications },
|
|
91357
|
-
args.localAdvisoryRunner
|
|
91406
|
+
args.localAdvisoryRunner,
|
|
91407
|
+
...browseSignal ? [{ signal: browseSignal }] : []
|
|
91358
91408
|
);
|
|
91409
|
+
if (browseSignal?.aborted) {
|
|
91410
|
+
logger.info(
|
|
91411
|
+
"[orchestration-shell] Gemma intent classifier aborted via browseSignal; returning silently",
|
|
91412
|
+
{ prompt: plannerInput.prompt, rationale: gemmaIntent.rationale }
|
|
91413
|
+
), clearPendingClarificationIfPresent(store);
|
|
91414
|
+
return;
|
|
91415
|
+
}
|
|
91359
91416
|
if (gemmaIntent.source === "model")
|
|
91360
91417
|
gemmaEvaluatedIntent = !0, decision.action === "browse" ? gemmaIntent.is_code_or_disk_mutation && (logger.info(
|
|
91361
91418
|
"[orchestration-shell] Gemma intent classifier: promoting browse to start_task with code/disk mutation",
|
|
@@ -91372,6 +91429,12 @@ async function handleShellUserInput(deps) {
|
|
|
91372
91429
|
), decision = {
|
|
91373
91430
|
action: "familiarize",
|
|
91374
91431
|
rationale: decision.rationale ? `${decision.rationale} (demoted to familiarize via Gemma intent classifier)` : gemmaIntent.rationale
|
|
91432
|
+
}) : gemmaIntent.action === "browse" && !gemmaIntent.requires_file_read ? (logger.info(
|
|
91433
|
+
"[orchestration-shell] Gemma intent classifier: demoting start_task to browse",
|
|
91434
|
+
{ prompt: plannerInput.prompt, rationale: gemmaIntent.rationale }
|
|
91435
|
+
), decision = {
|
|
91436
|
+
action: "browse",
|
|
91437
|
+
rationale: decision.rationale ? `${decision.rationale} (demoted to browse via Gemma intent classifier)` : gemmaIntent.rationale
|
|
91375
91438
|
}) : (logger.info(
|
|
91376
91439
|
"[orchestration-shell] Gemma intent classifier: demoting start_task to advisory_response",
|
|
91377
91440
|
{ prompt: plannerInput.prompt, rationale: gemmaIntent.rationale }
|
|
@@ -20,6 +20,7 @@ export interface GemmaIntentPort {
|
|
|
20
20
|
}>;
|
|
21
21
|
}
|
|
22
22
|
export declare const INTENT_CLASSIFIER_JSON_SCHEMA: Record<string, unknown>;
|
|
23
|
+
export declare const DEFAULT_INTENT_TIMEOUT_MS = 30000;
|
|
23
24
|
export declare function buildIntentClassifierPrompt(prompt: string, clarifications?: {
|
|
24
25
|
question: string;
|
|
25
26
|
answer: string;
|
|
@@ -67,35 +67,44 @@ export declare class PlannerOutputUnparseableError extends Error {
|
|
|
67
67
|
});
|
|
68
68
|
}
|
|
69
69
|
export declare function localGemmaAllowedActions(): ReadonlySet<PlannerDecision['action']>;
|
|
70
|
-
|
|
70
|
+
type NullField = {
|
|
71
|
+
type: 'null';
|
|
72
|
+
};
|
|
73
|
+
type StringField = {
|
|
74
|
+
type: 'string';
|
|
75
|
+
};
|
|
76
|
+
type NullableStringField = {
|
|
77
|
+
type: ['string', 'null'];
|
|
78
|
+
};
|
|
79
|
+
type NullableUrlsField = {
|
|
80
|
+
type: ['array', 'null'];
|
|
81
|
+
items: {
|
|
82
|
+
type: 'string';
|
|
83
|
+
};
|
|
84
|
+
};
|
|
85
|
+
/** One per-action branch of the planner decision schema (planner parity D-15). */
|
|
86
|
+
export interface LocalGemmaDecisionBranchSchema {
|
|
71
87
|
type: 'object';
|
|
72
88
|
properties: {
|
|
73
|
-
rationale:
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
};
|
|
79
|
-
advisory_summary: {
|
|
80
|
-
type: ['string', 'null'];
|
|
81
|
-
};
|
|
82
|
-
browseUrls: {
|
|
83
|
-
type: ['array', 'null'];
|
|
84
|
-
items: {
|
|
85
|
-
type: 'string';
|
|
86
|
-
};
|
|
87
|
-
};
|
|
88
|
-
browseQuery: {
|
|
89
|
-
type: ['string', 'null'];
|
|
90
|
-
};
|
|
89
|
+
rationale: StringField;
|
|
90
|
+
clarifying_question: StringField | NullableStringField | NullField;
|
|
91
|
+
advisory_summary: NullableStringField | NullField;
|
|
92
|
+
browseUrls: NullableUrlsField | NullField;
|
|
93
|
+
browseQuery: NullableStringField | NullField;
|
|
91
94
|
action: {
|
|
92
95
|
type: 'string';
|
|
93
96
|
enum: PlannerDecision['action'][];
|
|
94
97
|
};
|
|
95
98
|
};
|
|
96
99
|
required: string[];
|
|
97
|
-
additionalProperties:
|
|
100
|
+
additionalProperties: false;
|
|
101
|
+
}
|
|
102
|
+
/** The planner decision schema: exactly one branch per action family (planner parity D-15). */
|
|
103
|
+
export interface LocalGemmaDecisionJsonSchema {
|
|
104
|
+
anyOf: LocalGemmaDecisionBranchSchema[];
|
|
98
105
|
}
|
|
106
|
+
/** Every action the decision schema can emit, in branch order (each exactly once). */
|
|
107
|
+
export declare function localGemmaDecisionSchemaActions(schema?: LocalGemmaDecisionJsonSchema): PlannerDecision['action'][];
|
|
99
108
|
/**
|
|
100
109
|
* The ONE planner decision schema (both runtimes). Its canonical SHA-256 is allow-listed by
|
|
101
110
|
* planner-proxy (`lambda/planner-proxy/schemas.ts`); a change here needs the backend
|
package/package.json
CHANGED