@quantiya/codevibe-claude-plugin 2.0.31 → 2.0.32
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/.claude-plugin/plugin.json +1 -1
- package/node_modules/@quantiya/codevibe-core/dist/__tests__/no-raw-control-bytes-in-source.test.d.ts +1 -0
- package/node_modules/@quantiya/codevibe-core/dist/index.js +339 -339
- package/node_modules/@quantiya/codevibe-core/dist/orchestration-shell/__tests__/browse-prompt-urls.test.d.ts +1 -0
- package/node_modules/@quantiya/codevibe-core/dist/orchestration-shell/cli.js +139 -38
- package/node_modules/@quantiya/codevibe-core/dist/orchestration-shell/index.d.ts +15 -0
- package/node_modules/@quantiya/codevibe-core/dist/planner/__tests__/local-gemma-browse-regression.test.d.ts +1 -0
- package/node_modules/@quantiya/codevibe-core/dist/planner/__tests__/url-protect.test.d.ts +1 -0
- package/node_modules/@quantiya/codevibe-core/dist/planner/local-gemma.d.ts +12 -1
- package/node_modules/@quantiya/codevibe-core/dist/planner/url-protect.d.ts +20 -0
- package/node_modules/@quantiya/codevibe-core/package.json +1 -1
- package/package.json +2 -2
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -18310,7 +18310,52 @@ ${formatReviewerPolicy(snapshot)}`
|
|
|
18310
18310
|
}
|
|
18311
18311
|
|
|
18312
18312
|
// src/planner/local-advisory.ts
|
|
18313
|
-
var import_path2 = __toESM(require("path"))
|
|
18313
|
+
var import_path2 = __toESM(require("path"));
|
|
18314
|
+
|
|
18315
|
+
// src/planner/url-protect.ts
|
|
18316
|
+
var HTTP_URL_PATTERN_SOURCE = "https?:\\/\\/[^\\s\"'`<>,)}\\]\u3001\u3002\u3003\u3008\u3009\u300A\u300B\u300C\u300D\u300E\u300F\u3010\u3011\u3014\u3015\u3016\u3017\u3018\u3019\u301A\u301B\u301C\u301D\u301E\u301F\uFF01-\uFF0F\uFF1A-\uFF20\uFF3B-\uFF40\uFF5B-\uFF65]+";
|
|
18317
|
+
function httpUrlPattern() {
|
|
18318
|
+
return new RegExp(HTTP_URL_PATTERN_SOURCE, "g");
|
|
18319
|
+
}
|
|
18320
|
+
var URL_PLACEHOLDER_PREFIX = "__CODEVIBE_URL_", URL_PLACEHOLDER_SOURCE = `${URL_PLACEHOLDER_PREFIX}(\\d+)__`, TRAILING_PUNCTUATION = /[.;:!?]+$/;
|
|
18321
|
+
function protectUrls(text2) {
|
|
18322
|
+
let urls = [];
|
|
18323
|
+
return {
|
|
18324
|
+
text: text2.replace(httpUrlPattern(), (url) => {
|
|
18325
|
+
let token = `${URL_PLACEHOLDER_PREFIX}${urls.length}__`;
|
|
18326
|
+
return urls.push(url), token;
|
|
18327
|
+
}),
|
|
18328
|
+
urls
|
|
18329
|
+
};
|
|
18330
|
+
}
|
|
18331
|
+
function restoreUrls(text2, urls) {
|
|
18332
|
+
return text2.replace(new RegExp(URL_PLACEHOLDER_SOURCE, "g"), (token, index) => urls[Number(index)] ?? token);
|
|
18333
|
+
}
|
|
18334
|
+
function isWellFormedHttpUrl(candidate) {
|
|
18335
|
+
if (candidate.includes("[path]")) return !1;
|
|
18336
|
+
try {
|
|
18337
|
+
let url = new URL(candidate);
|
|
18338
|
+
return url.protocol === "http:" || url.protocol === "https:";
|
|
18339
|
+
} catch {
|
|
18340
|
+
return !1;
|
|
18341
|
+
}
|
|
18342
|
+
}
|
|
18343
|
+
function extractHttpUrls(text2) {
|
|
18344
|
+
let seen = /* @__PURE__ */ new Set(), out = [], re = httpUrlPattern(), tail = new RegExp(`^(?:${HTTP_URL_PATTERN_SOURCE.slice(HTTP_URL_PATTERN_SOURCE.indexOf("[^"))})`);
|
|
18345
|
+
for (let m = re.exec(text2); m !== null; m = re.exec(text2)) {
|
|
18346
|
+
let url = m[0], end = m.index + url.length;
|
|
18347
|
+
for (; text2[end] === ")" && url.split("(").length - 1 > url.split(")").length - 1; ) {
|
|
18348
|
+
url += ")", end += 1;
|
|
18349
|
+
let more = tail.exec(text2.slice(end));
|
|
18350
|
+
more && (url += more[0], end += more[0].length);
|
|
18351
|
+
}
|
|
18352
|
+
re.lastIndex = end, url = url.replace(TRAILING_PUNCTUATION, ""), !(url.length === 0 || seen.has(url)) && (seen.add(url), out.push(url));
|
|
18353
|
+
}
|
|
18354
|
+
return out;
|
|
18355
|
+
}
|
|
18356
|
+
|
|
18357
|
+
// src/planner/local-advisory.ts
|
|
18358
|
+
var MAX_USER_PROMPT_CHARS = 2e3, MAX_README_PREVIEW_CHARS = 900, MAX_RENDERED_PROMPT_CHARS = 18e3, MAX_ADVISORY_SUMMARY_CHARS = 6e3, MAX_BRAINSTORM_PRIOR_TURN_CHARS = 1200, PATH_REDACTION = "[path]", LOCAL_SINGLE_SEGMENT_ROOTS = /* @__PURE__ */ new Set([
|
|
18314
18359
|
"Applications",
|
|
18315
18360
|
"Library",
|
|
18316
18361
|
"System",
|
|
@@ -18334,19 +18379,6 @@ var import_path2 = __toESM(require("path")), MAX_USER_PROMPT_CHARS = 2e3, MAX_RE
|
|
|
18334
18379
|
"workspace",
|
|
18335
18380
|
"workspaces"
|
|
18336
18381
|
]);
|
|
18337
|
-
function protectUrls(text2) {
|
|
18338
|
-
let urls = [];
|
|
18339
|
-
return {
|
|
18340
|
-
text: text2.replace(/https?:\/\/[^\s"'`<>,)}\]]+/g, (url) => {
|
|
18341
|
-
let token = `${URL_PLACEHOLDER_PREFIX}${urls.length}__`;
|
|
18342
|
-
return urls.push(url), token;
|
|
18343
|
-
}),
|
|
18344
|
-
urls
|
|
18345
|
-
};
|
|
18346
|
-
}
|
|
18347
|
-
function restoreUrls(text2, urls) {
|
|
18348
|
-
return text2.replace(new RegExp(`${URL_PLACEHOLDER_PREFIX}(\\d+)__`, "g"), (_token, index) => urls[Number(index)] ?? _token);
|
|
18349
|
-
}
|
|
18350
18382
|
function isPathBoundary(text2, index) {
|
|
18351
18383
|
return index <= 0 ? !0 : !/[A-Za-z0-9_./~-]/.test(text2[index - 1] ?? "");
|
|
18352
18384
|
}
|
|
@@ -27645,7 +27677,7 @@ var PlannerOutputUnparseableError = class _PlannerOutputUnparseableError extends
|
|
|
27645
27677
|
rationale: { type: "string" },
|
|
27646
27678
|
clarifying_question: { type: "string" },
|
|
27647
27679
|
advisory_summary: { type: "string" },
|
|
27648
|
-
browseUrls: { type: "array", items: { type: "string"
|
|
27680
|
+
browseUrls: { type: "array", items: { type: "string" } },
|
|
27649
27681
|
browseQuery: { type: "string" },
|
|
27650
27682
|
action: { type: "string", enum: [...LOCAL_GEMMA_ALLOWED_ACTIONS] }
|
|
27651
27683
|
},
|
|
@@ -27663,7 +27695,7 @@ function truncatePlannerTextPreservingEnds(text2, maxChars) {
|
|
|
27663
27695
|
return `${text2.slice(0, headChars)}${omission}${text2.slice(-tailChars)}`;
|
|
27664
27696
|
}
|
|
27665
27697
|
function sanitizePlannerText(text2, maxChars) {
|
|
27666
|
-
let sanitized =
|
|
27698
|
+
let protectedInput = protectUrls(text2), sanitized = protectedInput.text.replace(/```[\s\S]*?```/g, "[code block omitted]").replace(/```[\s\S]*$/g, "[code block omitted]").replace(
|
|
27667
27699
|
/^\s*(?:function|class|interface|type|enum|import|export|const|let|var)\b[^\n]{0,240}/gm,
|
|
27668
27700
|
"[code snippet omitted]"
|
|
27669
27701
|
).replace(
|
|
@@ -27679,7 +27711,7 @@ function sanitizePlannerText(text2, maxChars) {
|
|
|
27679
27711
|
/(^|[\s"'`([{,])(?:\.{1,2}\/)?(?:\.[A-Za-z0-9_.-]+|[A-Za-z0-9_.-]+\.(?:json|ts|tsx|js|jsx|mjs|cjs|env|pem|key|p12|yaml|yml|toml|lock))(?=$|[\s"'`),\]}])/g,
|
|
27680
27712
|
"$1[path]"
|
|
27681
27713
|
);
|
|
27682
|
-
return truncatePlannerTextPreservingEnds(sanitized, maxChars);
|
|
27714
|
+
return truncatePlannerTextPreservingEnds(restoreUrls(sanitized, protectedInput.urls), maxChars);
|
|
27683
27715
|
}
|
|
27684
27716
|
function sanitizeCanonicalConversationContext(text2, maxChars) {
|
|
27685
27717
|
let sanitized = sanitizePlannerText(text2, Number.MAX_SAFE_INTEGER).trim();
|
|
@@ -27845,11 +27877,59 @@ ${keptOptionalLines.join(`
|
|
|
27845
27877
|
${payloadJson}
|
|
27846
27878
|
${outputReminder}` : baseRendered;
|
|
27847
27879
|
}
|
|
27848
|
-
function
|
|
27880
|
+
function firstBalancedJsonObject(raw, from = 0) {
|
|
27881
|
+
let start = raw.indexOf("{", from);
|
|
27882
|
+
if (start < 0) return null;
|
|
27883
|
+
let depth = 0, inString = !1, escaped = !1;
|
|
27884
|
+
for (let i = start; i < raw.length; i++) {
|
|
27885
|
+
let ch = raw[i];
|
|
27886
|
+
if (inString) {
|
|
27887
|
+
escaped ? escaped = !1 : ch === "\\" ? escaped = !0 : ch === '"' && (inString = !1);
|
|
27888
|
+
continue;
|
|
27889
|
+
}
|
|
27890
|
+
if (ch === '"')
|
|
27891
|
+
inString = !0;
|
|
27892
|
+
else if (ch === "{")
|
|
27893
|
+
depth += 1;
|
|
27894
|
+
else if (ch === "}" && (depth -= 1, depth === 0))
|
|
27895
|
+
return { text: raw.slice(start, i + 1), end: i + 1 };
|
|
27896
|
+
}
|
|
27897
|
+
return null;
|
|
27898
|
+
}
|
|
27899
|
+
function assertNoConflictingTrailingDecision(rest, first) {
|
|
27900
|
+
let firstAction = typeof first.action == "string" ? first.action : void 0, conflict = (action) => {
|
|
27901
|
+
throw new PlannerOutputUnparseableError(
|
|
27902
|
+
`local Gemma planner output contained a second decision object with a conflicting action (${String(firstAction)} then ${action})`
|
|
27903
|
+
);
|
|
27904
|
+
}, cursor = 0;
|
|
27905
|
+
for (; ; ) {
|
|
27906
|
+
let next = firstBalancedJsonObject(rest, cursor);
|
|
27907
|
+
if (next === null) break;
|
|
27908
|
+
cursor = next.end;
|
|
27909
|
+
let parsed = parseJsonObjectText(next.text, []);
|
|
27910
|
+
if (parsed === null) continue;
|
|
27911
|
+
let action = parsed.action;
|
|
27912
|
+
typeof action == "string" && action !== firstAction && conflict(action);
|
|
27913
|
+
}
|
|
27914
|
+
let lexical = /(?<!\\)"action"\s*:\s*"([^"\\]*)"/g;
|
|
27915
|
+
for (let m = lexical.exec(rest); m !== null; m = lexical.exec(rest))
|
|
27916
|
+
m[1] !== firstAction && conflict(m[1]);
|
|
27917
|
+
}
|
|
27918
|
+
function parseJsonObjectText(text2, errors) {
|
|
27919
|
+
try {
|
|
27920
|
+
return JSON.parse(text2);
|
|
27921
|
+
} catch (err) {
|
|
27922
|
+
errors.push(err);
|
|
27923
|
+
}
|
|
27924
|
+
try {
|
|
27925
|
+
return JSON.parse(stripTrailingCommas(text2));
|
|
27926
|
+
} catch {
|
|
27927
|
+
return null;
|
|
27928
|
+
}
|
|
27929
|
+
}
|
|
27930
|
+
function legacyJsonObjectSlice(raw) {
|
|
27849
27931
|
let trimmed = raw.trim(), fenced = /```(?:json)?\s*([\s\S]*?)```/i.exec(trimmed), body = fenced ? fenced[1].trim() : trimmed, start = body.indexOf("{"), end = body.lastIndexOf("}");
|
|
27850
|
-
|
|
27851
|
-
throw new PlannerOutputUnparseableError("local Gemma planner output contained no JSON object");
|
|
27852
|
-
return body.slice(start, end + 1);
|
|
27932
|
+
return start < 0 || end <= start ? null : body.slice(start, end + 1);
|
|
27853
27933
|
}
|
|
27854
27934
|
function stripTrailingCommas(jsonStr) {
|
|
27855
27935
|
let result = "", inString = !1, escaped = !1;
|
|
@@ -27874,23 +27954,29 @@ function stripTrailingCommas(jsonStr) {
|
|
|
27874
27954
|
}
|
|
27875
27955
|
return result;
|
|
27876
27956
|
}
|
|
27877
|
-
function
|
|
27878
|
-
let
|
|
27879
|
-
|
|
27880
|
-
|
|
27881
|
-
|
|
27882
|
-
|
|
27883
|
-
`local Gemma planner output was not valid JSON: ${initialErr.message}`
|
|
27884
|
-
);
|
|
27957
|
+
function parseLocalGemmaJsonObject(raw) {
|
|
27958
|
+
let errors = [], balanced = firstBalancedJsonObject(raw);
|
|
27959
|
+
if (balanced !== null) {
|
|
27960
|
+
let parsed = parseJsonObjectText(balanced.text, errors);
|
|
27961
|
+
if (parsed !== null)
|
|
27962
|
+
return assertNoConflictingTrailingDecision(raw.slice(balanced.end), parsed), parsed;
|
|
27885
27963
|
}
|
|
27964
|
+
let legacy = legacyJsonObjectSlice(raw);
|
|
27965
|
+
if (legacy !== null && legacy !== balanced?.text) {
|
|
27966
|
+
let parsed = parseJsonObjectText(legacy, errors);
|
|
27967
|
+
if (parsed !== null) return parsed;
|
|
27968
|
+
}
|
|
27969
|
+
throw balanced === null && legacy === null ? new PlannerOutputUnparseableError("local Gemma planner output contained no JSON object") : new PlannerOutputUnparseableError(
|
|
27970
|
+
`local Gemma planner output was not valid JSON: ${errors[0]?.message ?? "unknown parse error"}`
|
|
27971
|
+
);
|
|
27972
|
+
}
|
|
27973
|
+
var RAW_OUTPUT_HEAD_CHARS = 500;
|
|
27974
|
+
function summarizeRawOutputForLog(raw) {
|
|
27975
|
+
let cleaned = raw.replace(/\u001b\[[0-?]*[ -/]*[@-~]/g, "").replace(/\u001b\][^\u0007\u001b]*(?:\u0007|\u001b\\)?/g, "").replace(/[\u0000-\u0008\u000b\u000c\u000e-\u001f\u007f-\u009f]/g, "");
|
|
27976
|
+
return cleaned.length <= RAW_OUTPUT_HEAD_CHARS ? cleaned : `${cleaned.slice(0, RAW_OUTPUT_HEAD_CHARS)}\u2026 (+${cleaned.length - RAW_OUTPUT_HEAD_CHARS} chars)`;
|
|
27886
27977
|
}
|
|
27887
27978
|
function parseLocalGemmaPlannerDecision(raw) {
|
|
27888
|
-
let parsed;
|
|
27889
|
-
try {
|
|
27890
|
-
parsed = JSON.parse(extractJsonObject2(raw));
|
|
27891
|
-
} catch (err) {
|
|
27892
|
-
parsed = repairAndParseLocalGemmaJson(raw, err);
|
|
27893
|
-
}
|
|
27979
|
+
let parsed = parseLocalGemmaJsonObject(raw);
|
|
27894
27980
|
if (!parsed || typeof parsed != "object")
|
|
27895
27981
|
throw new PlannerOutputUnparseableError("local Gemma planner output was not a JSON object");
|
|
27896
27982
|
let obj = parsed;
|
|
@@ -27938,7 +28024,11 @@ var LocalGemmaPlannerAdapter = class {
|
|
|
27938
28024
|
jsonSchema: LOCAL_GEMMA_DECISION_JSON_SCHEMA,
|
|
27939
28025
|
numPredict: 1024
|
|
27940
28026
|
});
|
|
27941
|
-
|
|
28027
|
+
try {
|
|
28028
|
+
return parseLocalGemmaPlannerDecision(raw);
|
|
28029
|
+
} catch (err) {
|
|
28030
|
+
throw err instanceof PlannerOutputUnparseableError && err.rawOutputHead === void 0 && (err.rawOutputHead = summarizeRawOutputForLog(raw)), err;
|
|
28031
|
+
}
|
|
27942
28032
|
}
|
|
27943
28033
|
async probe() {
|
|
27944
28034
|
return this.runner.probe ? this.runner.probe() : {
|
|
@@ -60807,6 +60897,13 @@ var LastModeFileSchema = import_zod3.z.object({
|
|
|
60807
60897
|
var React19 = __toESM(require("react"));
|
|
60808
60898
|
|
|
60809
60899
|
// src/orchestration-shell/index.ts
|
|
60900
|
+
function resolveBrowseUrls(modelUrls, prompt) {
|
|
60901
|
+
if (!modelUrls || modelUrls.length === 0) return;
|
|
60902
|
+
let promptUrls = extractHttpUrls(prompt);
|
|
60903
|
+
if (promptUrls.length > 0) return promptUrls;
|
|
60904
|
+
let usable = modelUrls.filter(isWellFormedHttpUrl);
|
|
60905
|
+
return usable.length > 0 ? usable : void 0;
|
|
60906
|
+
}
|
|
60810
60907
|
var OrchestrationShellStartupError = class extends Error {
|
|
60811
60908
|
constructor(message, cause) {
|
|
60812
60909
|
super(message), this.name = "OrchestrationShellStartupError", this.cause = cause;
|
|
@@ -65248,7 +65345,10 @@ async function handleShellUserInput(deps) {
|
|
|
65248
65345
|
if (err instanceof PlannerOutputUnparseableError && isLocalPlannerRuntime(args)) {
|
|
65249
65346
|
logger.warn(
|
|
65250
65347
|
"[orchestration-shell] planner output unparseable; request not dispatched",
|
|
65251
|
-
|
|
65348
|
+
// `rawOutputHead` (2026-09-11): the bounded, control-free head of what
|
|
65349
|
+
// the model actually returned — the incident line without it needed a
|
|
65350
|
+
// live repro to explain "Expected property name … at position 1".
|
|
65351
|
+
{ error: errMsg, rawOutputHead: err.rawOutputHead }
|
|
65252
65352
|
), store.dispatch({
|
|
65253
65353
|
type: "SHELL_ADVISORY",
|
|
65254
65354
|
source: "shell",
|
|
@@ -65411,6 +65511,7 @@ async function handleShellUserInput(deps) {
|
|
|
65411
65511
|
return;
|
|
65412
65512
|
}
|
|
65413
65513
|
if (decision.action === "browse") {
|
|
65514
|
+
let browseUrls = resolveBrowseUrls(decision.browseUrls, plannerInput.prompt);
|
|
65414
65515
|
await routeBrowse({
|
|
65415
65516
|
store,
|
|
65416
65517
|
localAdvisoryRunner: args.localAdvisoryRunner,
|
|
@@ -65418,7 +65519,7 @@ async function handleShellUserInput(deps) {
|
|
|
65418
65519
|
// Recent conversation → the model formulates a context-aware search query (resolve
|
|
65419
65520
|
// acronyms/pronouns) instead of searching the raw command sentence.
|
|
65420
65521
|
priorTurns: collectRecentConversationTurns(store.getState().conversation, plannerInput.prompt),
|
|
65421
|
-
...
|
|
65522
|
+
...browseUrls && browseUrls.length > 0 ? { browseUrls } : {},
|
|
65422
65523
|
...decision.browseQuery ? { browseQuery: decision.browseQuery } : {}
|
|
65423
65524
|
});
|
|
65424
65525
|
return;
|
|
@@ -2,6 +2,21 @@ import { AsyncLocalStorage } from 'node:async_hooks';
|
|
|
2
2
|
import { AppSyncClient } from '../appsync';
|
|
3
3
|
import { Session } from '../types';
|
|
4
4
|
import { OrchestrationStore } from './store';
|
|
5
|
+
/**
|
|
6
|
+
* WEB-BROWSING-DESIGN.md rev 6 — the address for a model-chosen fetch.
|
|
7
|
+
*
|
|
8
|
+
* The classifier owns the fetch-vs-search decision: a `browse` decision WITH
|
|
9
|
+
* `browseUrls` is a fetch, one WITHOUT is a search (`browseQuery`). This helper
|
|
10
|
+
* never turns a search into a fetch (Stage-1 r1 F4: a URL that merely appears
|
|
11
|
+
* in "search for alternatives to https://x.com" stays a search). For a fetch,
|
|
12
|
+
* the user's literal URL is the address: the classify prompt is path-redacted
|
|
13
|
+
* before the model sees it, so the model's echo can be mangled
|
|
14
|
+
* (`https://[path]` in the 2026-09-11 incident) or drift. Only when the prompt
|
|
15
|
+
* carries no URL are the model's well-formed URLs used; a fetch decision whose
|
|
16
|
+
* every URL is unusable and whose prompt has none yields no URL (the route then
|
|
17
|
+
* falls back to `browseQuery` or asks for a URL).
|
|
18
|
+
*/
|
|
19
|
+
export declare function resolveBrowseUrls(modelUrls: string[] | undefined, prompt: string): string[] | undefined;
|
|
5
20
|
import { AdvisoryAttachmentJournal } from './advisory-attachment-journal';
|
|
6
21
|
import type { ImageAttachment } from './types';
|
|
7
22
|
import { type GateDecisionSubmitDeps, type GroupDecisionSubmitDeps } from './gate-decision-submit';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -31,6 +31,14 @@ export interface LocalGemmaPlannerRunner {
|
|
|
31
31
|
* without inventing a successful classification or starting a task.
|
|
32
32
|
*/
|
|
33
33
|
export declare class PlannerOutputUnparseableError extends Error {
|
|
34
|
+
/**
|
|
35
|
+
* The first {@link RAW_OUTPUT_HEAD_CHARS} characters of the model output that
|
|
36
|
+
* failed to parse (terminal-control bytes stripped), attached by the adapter so
|
|
37
|
+
* the shell's warn line records WHAT the model said. Before 2026-09-11 nothing
|
|
38
|
+
* logged the raw text and the `<channel|>` echo incident needed a live repro
|
|
39
|
+
* to diagnose. Absent when the error was raised without a raw string in hand.
|
|
40
|
+
*/
|
|
41
|
+
rawOutputHead?: string;
|
|
34
42
|
constructor(message: string);
|
|
35
43
|
}
|
|
36
44
|
export declare const LOCAL_GEMMA_DECISION_JSON_SCHEMA: {
|
|
@@ -49,7 +57,6 @@ export declare const LOCAL_GEMMA_DECISION_JSON_SCHEMA: {
|
|
|
49
57
|
type: string;
|
|
50
58
|
items: {
|
|
51
59
|
type: string;
|
|
52
|
-
pattern: string;
|
|
53
60
|
};
|
|
54
61
|
};
|
|
55
62
|
browseQuery: {
|
|
@@ -70,6 +77,10 @@ export declare const LOCAL_GEMMA_DECISION_JSON_SCHEMA: {
|
|
|
70
77
|
export declare function renderLocalGemmaPlannerPrompt(input: PlannerInput, options?: {
|
|
71
78
|
isSubprocessRunner?: boolean;
|
|
72
79
|
}): string;
|
|
80
|
+
/** Characters of raw model output retained on {@link PlannerOutputUnparseableError.rawOutputHead}. */
|
|
81
|
+
export declare const RAW_OUTPUT_HEAD_CHARS = 500;
|
|
82
|
+
/** Terminal-control-free, bounded head of a raw model output for the warn log. */
|
|
83
|
+
export declare function summarizeRawOutputForLog(raw: string): string;
|
|
73
84
|
export declare function parseLocalGemmaPlannerDecision(raw: string): PlannerDecision;
|
|
74
85
|
export declare class LocalGemmaPlannerAdapter implements PlannerAdapter {
|
|
75
86
|
private readonly runner;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/** Source of the shared http(s) URL matcher (no `g` state — build with {@link httpUrlPattern}). */
|
|
2
|
+
export declare const HTTP_URL_PATTERN_SOURCE = "https?:\\/\\/[^\\s\"'`<>,)}\\]\u3001\u3002\u3003\u3008\u3009\u300A\u300B\u300C\u300D\u300E\u300F\u3010\u3011\u3014\u3015\u3016\u3017\u3018\u3019\u301A\u301B\u301C\u301D\u301E\u301F\uFF01-\uFF0F\uFF1A-\uFF20\uFF3B-\uFF40\uFF5B-\uFF65]+";
|
|
3
|
+
/** A fresh global RegExp for {@link HTTP_URL_PATTERN_SOURCE}. */
|
|
4
|
+
export declare function httpUrlPattern(): RegExp;
|
|
5
|
+
/** Replace every http(s) URL with an opaque placeholder; returns the URLs in order. */
|
|
6
|
+
export declare function protectUrls(text: string): {
|
|
7
|
+
text: string;
|
|
8
|
+
urls: string[];
|
|
9
|
+
};
|
|
10
|
+
/** Put the URLs captured by {@link protectUrls} back in place of their placeholders. */
|
|
11
|
+
export declare function restoreUrls(text: string, urls: string[]): string;
|
|
12
|
+
/** `http:`/`https:` and parseable by WHATWG `URL`; never a redacted `[path]` echo. */
|
|
13
|
+
export declare function isWellFormedHttpUrl(candidate: string): boolean;
|
|
14
|
+
/**
|
|
15
|
+
* The literal http(s) URLs a user typed, in order, de-duplicated, with trailing
|
|
16
|
+
* sentence punctuation dropped (`read https://x.com/a.` → `https://x.com/a`) and
|
|
17
|
+
* balanced parentheses kept (`…/wiki/Foo_(bar)` stays whole — F7). Pure text
|
|
18
|
+
* extraction — scheme/port/host validation stays in `guardedFetch`.
|
|
19
|
+
*/
|
|
20
|
+
export declare function extractHttpUrls(text: string): string[];
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@quantiya/codevibe-claude-plugin",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.32",
|
|
4
4
|
"description": "Control Claude Code from your iPhone and Android — real-time sync, approve file edits, send prompts by voice. Part of CodeVibe.",
|
|
5
5
|
"main": "dist/server.js",
|
|
6
6
|
"codevibe": {
|
|
@@ -48,7 +48,7 @@
|
|
|
48
48
|
"node": ">=22.0.0"
|
|
49
49
|
},
|
|
50
50
|
"dependencies": {
|
|
51
|
-
"@quantiya/codevibe-core": "^2.0.
|
|
51
|
+
"@quantiya/codevibe-core": "^2.0.27",
|
|
52
52
|
"@quantiya/quorum-core": "^1.0.1",
|
|
53
53
|
"dotenv": "^16.6.1",
|
|
54
54
|
"express": "^5.1.0",
|