@quantiya/codevibe-codex-plugin 2.0.61 → 2.0.63
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/node_modules/@quantiya/codevibe-core/dist/index.d.ts +1 -0
- package/node_modules/@quantiya/codevibe-core/dist/index.js +535 -526
- package/node_modules/@quantiya/codevibe-core/dist/local-model/ollama.d.ts +2 -0
- package/node_modules/@quantiya/codevibe-core/dist/local-model/runtime.d.ts +1 -0
- package/node_modules/@quantiya/codevibe-core/dist/orchestration-shell/cli.js +1226 -46
- package/node_modules/@quantiya/codevibe-core/dist/orchestration-shell/git-status-summary.d.ts +52 -0
- package/node_modules/@quantiya/codevibe-core/dist/planner/local-advisory.d.ts +9 -0
- package/node_modules/@quantiya/codevibe-core/dist/planner/local-gemma.d.ts +1 -0
- package/node_modules/@quantiya/codevibe-core/package.json +1 -1
- package/package.json +2 -2
|
@@ -8529,7 +8529,12 @@ function renderLocalGemmaPlannerPrompt(input, options) {
|
|
|
8529
8529
|
'User: "Can you code in Rust?" -> {"action":"advisory_response","rationale":"capability question, no repo context","advisory_summary":"Yes \u2014 I can write and review Rust code across libraries, CLIs, and web services."}',
|
|
8530
8530
|
'User: "That sounds like a summary, I am looking for your thoughts" (a web page was read earlier in this session) -> {"action":"advisory_response","rationale":"opinion follow-up on the page read earlier","advisory_summary":"<your own analysis of that page>"}',
|
|
8531
8531
|
'User: "what do you think about that article?" -> {"action":"advisory_response","rationale":"opinion follow-up on earlier content","advisory_summary":"<your view on the article>"}',
|
|
8532
|
-
options?.isSubprocessRunner ? 'User: "what did the last task change?" -> {"action":"summarize_current_status","rationale":"status question"}' :
|
|
8532
|
+
options?.isSubprocessRunner ? 'User: "what did the last task change?" -> {"action":"summarize_current_status","rationale":"status question"}' : [
|
|
8533
|
+
'User: "what did the last task change?" -> {"action":"advisory_response","rationale":"status question; the shell attaches the status record"}',
|
|
8534
|
+
'User: "Show me the diff of the most recent commit on this branch" -> {"action":"advisory_response","rationale":"inspect commit diff status"}',
|
|
8535
|
+
'User: "Are there any untracked or modified files in the working tree right now?" -> {"action":"advisory_response","rationale":"inspect working tree status"}'
|
|
8536
|
+
].join(`
|
|
8537
|
+
`),
|
|
8533
8538
|
'User: "What kind of applications can you implement?" -> {"action":"advisory_response","rationale":"capability question","advisory_summary":"I can implement CLIs, web apps, APIs, libraries, scripts, data pipelines, and tests across most popular languages."}',
|
|
8534
8539
|
'User: "What is this [path]\\n\\n[The user attached 1 image(s).]" -> {"action":"advisory_response","rationale":"describe the attached image"}',
|
|
8535
8540
|
'User: "describe this\\n\\n[The user attached 1 image(s).]" -> {"action":"advisory_response","rationale":"describe the attached image"}',
|
|
@@ -8972,12 +8977,12 @@ function requestOllamaGenerateStream(config, promptText, opts) {
|
|
|
8972
8977
|
num_ctx: numCtx
|
|
8973
8978
|
}
|
|
8974
8979
|
}), url = new URL("/api/generate", config.host), timeoutMs = opts?.timeoutMs ?? config.timeoutMs;
|
|
8975
|
-
return new Promise((resolve24, reject) => {
|
|
8976
|
-
let settled = !1, responseBytes = 0, buffer = "", decoder = new import_string_decoder.StringDecoder("utf8"), out = { text: "" }, emptyRun = 0, chunks = 0, sawDone = !1, lastDone, ndjson = !1, idleTimer = null, activeRes = null, clearIdle = () => {
|
|
8980
|
+
return opts?.signal?.aborted ? Promise.reject(new Error("Ollama generation aborted by signal")) : new Promise((resolve24, reject) => {
|
|
8981
|
+
let settled = !1, responseBytes = 0, buffer = "", decoder = new import_string_decoder.StringDecoder("utf8"), out = { text: "" }, emptyRun = 0, chunks = 0, sawDone = !1, lastDone, ndjson = !1, timeout = null, idleTimer = null, activeRes = null, clearIdle = () => {
|
|
8977
8982
|
idleTimer && (clearTimeout(idleTimer), idleTimer = null);
|
|
8978
8983
|
}, finish = (fn) => {
|
|
8979
8984
|
if (!settled) {
|
|
8980
|
-
settled = !0, clearTimeout(timeout), clearIdle();
|
|
8985
|
+
settled = !0, timeout && clearTimeout(timeout), clearIdle();
|
|
8981
8986
|
try {
|
|
8982
8987
|
fn();
|
|
8983
8988
|
} catch (err) {
|
|
@@ -9078,10 +9083,19 @@ function requestOllamaGenerateStream(config, promptText, opts) {
|
|
|
9078
9083
|
}
|
|
9079
9084
|
}));
|
|
9080
9085
|
}
|
|
9081
|
-
)
|
|
9086
|
+
);
|
|
9087
|
+
if (req.on("error", (err) => finish(() => reject(err))), timeout = setTimeout(() => {
|
|
9082
9088
|
req.destroy(new Error(`Ollama request timed out after ${timeoutMs}ms`));
|
|
9083
|
-
}, timeoutMs)
|
|
9084
|
-
|
|
9089
|
+
}, timeoutMs), opts?.signal) {
|
|
9090
|
+
if (opts.signal.aborted) {
|
|
9091
|
+
finish(() => reject(new Error("Ollama generation aborted by signal"))), req.destroy();
|
|
9092
|
+
return;
|
|
9093
|
+
}
|
|
9094
|
+
opts.signal.addEventListener("abort", () => {
|
|
9095
|
+
finish(() => reject(new Error("Ollama generation aborted by signal"))), req.destroy(), activeRes?.destroy();
|
|
9096
|
+
}, { once: !0 });
|
|
9097
|
+
}
|
|
9098
|
+
req.end(body);
|
|
9085
9099
|
});
|
|
9086
9100
|
}
|
|
9087
9101
|
function describeRecordError(value) {
|
|
@@ -9184,6 +9198,7 @@ function requestOllamaPull(config, onProgress = () => {
|
|
|
9184
9198
|
var OllamaGemmaPlannerRunner = class {
|
|
9185
9199
|
constructor(config) {
|
|
9186
9200
|
this.config = config;
|
|
9201
|
+
this.providerKind = "local";
|
|
9187
9202
|
this.runtimeLabel = `local-gemma-ollama:${config.model}`;
|
|
9188
9203
|
}
|
|
9189
9204
|
classify(promptText, options) {
|
|
@@ -9195,7 +9210,8 @@ var OllamaGemmaPlannerRunner = class {
|
|
|
9195
9210
|
numPredict,
|
|
9196
9211
|
// #618 — advisory generations (long prompts, big output budgets) get the
|
|
9197
9212
|
// advisory timeout floor; classify keeps the fast-fail config timeout.
|
|
9198
|
-
timeoutMs: advisoryTimeoutMs(this.config.timeoutMs),
|
|
9213
|
+
timeoutMs: options?.timeoutMs ?? advisoryTimeoutMs(this.config.timeoutMs),
|
|
9214
|
+
...options?.signal ? { signal: options.signal } : {},
|
|
9199
9215
|
// IMAGE-ATTACHMENT-DESIGN.md §6: forward RAW base64 images (multimodal
|
|
9200
9216
|
// answerer). Only the shell's `routeAdvisory`/image-brainstorm passes these
|
|
9201
9217
|
// with `responseFormat:'text'`; the classifier never does (forced-JSON).
|
|
@@ -67548,7 +67564,1008 @@ function chronologicalSupervisionEvents(newestFirstEvents) {
|
|
|
67548
67564
|
// src/orchestration-shell/git-status-summary.ts
|
|
67549
67565
|
var path64 = __toESM(require("path")), import_child_process5 = require("child_process"), import_util3 = require("util");
|
|
67550
67566
|
init_env_scrub();
|
|
67551
|
-
|
|
67567
|
+
init_logger2();
|
|
67568
|
+
var defaultExecFileAsync = (0, import_util3.promisify)(import_child_process5.execFile), GIT_QUERY_PATTERN = /\b(git\s+(?:status|log|diff|show|branch)|commit\s+history|recent\s+commits)\b/i;
|
|
67569
|
+
var COMMIT_DIFF_PATTERN = /\b(?:diff\s+of\s+(?:the\s+)?(?:most\s+recent|last|latest|current|head)\s+commit\b|(?:most\s+recent|last|latest|current|head)\s+commit(?:'s)?\s+diff\b|(?:show|view|see)\s+(?:the\s+)?diff\s+of\s+(?:the\s+)?(?:most\s+recent|last|latest|current)\b|(?:what\s+changed\s+in|changes?\s+in)\s+(?:the\s+)?(?:most\s+recent|last|latest|current|head)\s+commit\b|(?:show|view|see)\s+what\s+changed\s+in\s+(?:the\s+)?(?:latest|last|most\s+recent)\s+commit\b|(?:show|view|see|inspect|print|display|what\s+is)\s+(?:the\s+)?(?:most\s+recent|last|latest|current)\s+commit\b|[0-9a-f]{7,40}(?:[~^][A-Za-z0-9_/@~^-]*)?'s\s+diff\b|diff\s+of\s+(?:commit\s+)?(?![^\s;,?]*\.\.[a-zA-Z0-9_/@~^-])([0-9a-f]{7,40}(?:[~^][A-Za-z0-9_/@~^-]*)?)(?![0-9a-zA-Z_/@~^-]))/i;
|
|
67570
|
+
var SAFE_REF_PATTERN = /^[A-Za-z0-9_./@~^-]+$/, SAFE_REPO_NAME_PATTERN = /^[A-Za-z0-9_.-]+$/;
|
|
67571
|
+
function stripSentencePunctuation(token, options) {
|
|
67572
|
+
let stripped = token.trim().replace(/^['"`“‘«‹「『(\[(《【]+/u, "");
|
|
67573
|
+
return options?.preserveRangeDots && /\.{2,3}[,;:!?'"`”’»›」』)\])》】]*$/u.test(stripped) ? stripped.replace(/[,;:!?'"`”’»›」』)\])》】]+$/u, "") : (stripped = stripped.replace(/[.,;:!?'"`”’»›」』)\])》】]+$/u, ""), stripped);
|
|
67574
|
+
}
|
|
67575
|
+
function extractBranchOrRefTarget(prompt) {
|
|
67576
|
+
let positivePrompt = prompt.replace(
|
|
67577
|
+
/\b(?:that\s+is\s+|which\s+is\s+)?(?:not|except|excluding|without|instead\s+of)\s+(?:on|in|for|from|to|into)\s+(?:the\s+)?(?:branch\s+[A-Za-z0-9_./@~^-]+|[A-Za-z0-9_./@~^-]+\s+branch|current\s+branch|active\s+branch|this\s+branch)\b/gi,
|
|
67578
|
+
""
|
|
67579
|
+
).replace(
|
|
67580
|
+
/\b(?:that\s+is\s+|which\s+is\s+)?(?:not|except|excluding|without|instead\s+of)\s+(?:the\s+)?(?:current|active|this)\s+branch\b/gi,
|
|
67581
|
+
""
|
|
67582
|
+
);
|
|
67583
|
+
if (/(?:^|[\s,;])(?:on|in|for|from)\s+(?:the\s+|this\s+|current\s+|my\s+|our\s+|active\s+)?(?:this|current|active)\s+branch(?:\s+(?:in\s+detail|and\s+|please|now|here|summary|json))?[\s;,?.]*$/i.test(positivePrompt) || /^(?:this|current|active)\s+branch(?:\s+(?:in\s+detail|and\s+|please|now|here|summary|json))?[\s;,?.]*$/i.test(positivePrompt) || /\b(?:what|which)\s+branch\s+(?:am\s+i|is\s+this)\b/i.test(positivePrompt))
|
|
67584
|
+
return;
|
|
67585
|
+
let explicitPrefixMatch = positivePrompt.match(
|
|
67586
|
+
/(?:(?<![\w-])(?:on|in|for|from|to|into)\s+(?:the\s+)?branch(?:\s+(?:named|called)\s+|:\s*|\s+)|(?<![\w-])(?:the\s+)?branch\s+(?:named|called)\s+|(?<![\w-])branch:\s*|(?<![\w-])(?:named|called)\s+branch\s+)([A-Za-z0-9_./@~^-]+)(?=[\s;,?.]|$)/i
|
|
67587
|
+
);
|
|
67588
|
+
if (explicitPrefixMatch) {
|
|
67589
|
+
let candidate = stripSentencePunctuation(explicitPrefixMatch[1]), lower = candidate.toLowerCase();
|
|
67590
|
+
if (!(/* @__PURE__ */ new Set([
|
|
67591
|
+
"this",
|
|
67592
|
+
"that",
|
|
67593
|
+
"the",
|
|
67594
|
+
"my",
|
|
67595
|
+
"our",
|
|
67596
|
+
"a",
|
|
67597
|
+
"an",
|
|
67598
|
+
"current",
|
|
67599
|
+
"active",
|
|
67600
|
+
"and",
|
|
67601
|
+
"or",
|
|
67602
|
+
"but",
|
|
67603
|
+
"then",
|
|
67604
|
+
"so",
|
|
67605
|
+
"in",
|
|
67606
|
+
"to",
|
|
67607
|
+
"for",
|
|
67608
|
+
"with",
|
|
67609
|
+
"from",
|
|
67610
|
+
"of",
|
|
67611
|
+
"by",
|
|
67612
|
+
"about",
|
|
67613
|
+
"at",
|
|
67614
|
+
"as",
|
|
67615
|
+
"into",
|
|
67616
|
+
"onto",
|
|
67617
|
+
"please",
|
|
67618
|
+
"now",
|
|
67619
|
+
"here",
|
|
67620
|
+
"there",
|
|
67621
|
+
"name",
|
|
67622
|
+
"names",
|
|
67623
|
+
"named",
|
|
67624
|
+
"called",
|
|
67625
|
+
"what",
|
|
67626
|
+
"which",
|
|
67627
|
+
"how",
|
|
67628
|
+
"who",
|
|
67629
|
+
"where",
|
|
67630
|
+
"why",
|
|
67631
|
+
"am",
|
|
67632
|
+
"is",
|
|
67633
|
+
"are"
|
|
67634
|
+
])).has(lower) && SAFE_REF_PATTERN.test(candidate))
|
|
67635
|
+
return candidate;
|
|
67636
|
+
}
|
|
67637
|
+
let suffixBranchMatch = positivePrompt.match(
|
|
67638
|
+
/(?<![\w-])(?:on|in|for|from)\s+(?:the\s+)?([A-Za-z0-9_./@~^-]+)\s+branch\b/i
|
|
67639
|
+
);
|
|
67640
|
+
if (suffixBranchMatch) {
|
|
67641
|
+
let candidate = stripSentencePunctuation(suffixBranchMatch[1]), lower = candidate.toLowerCase();
|
|
67642
|
+
if (!(/* @__PURE__ */ new Set(["this", "that", "the", "my", "our", "a", "an", "current", "active", "which", "what", "each", "every"])).has(lower) && SAFE_REF_PATTERN.test(candidate))
|
|
67643
|
+
return candidate;
|
|
67644
|
+
}
|
|
67645
|
+
let standaloneMatch = positivePrompt.match(
|
|
67646
|
+
/(?:^|[,;(]\s*)branch\s+([A-Za-z0-9_./@~^-]+)(?=[\s;,?.]|$)/i
|
|
67647
|
+
);
|
|
67648
|
+
if (standaloneMatch) {
|
|
67649
|
+
let candidate = stripSentencePunctuation(standaloneMatch[1]), lower = candidate.toLowerCase();
|
|
67650
|
+
if (!(/* @__PURE__ */ new Set([
|
|
67651
|
+
"this",
|
|
67652
|
+
"that",
|
|
67653
|
+
"the",
|
|
67654
|
+
"my",
|
|
67655
|
+
"our",
|
|
67656
|
+
"a",
|
|
67657
|
+
"an",
|
|
67658
|
+
"current",
|
|
67659
|
+
"active",
|
|
67660
|
+
"and",
|
|
67661
|
+
"or",
|
|
67662
|
+
"but",
|
|
67663
|
+
"then",
|
|
67664
|
+
"so",
|
|
67665
|
+
"in",
|
|
67666
|
+
"to",
|
|
67667
|
+
"for",
|
|
67668
|
+
"with",
|
|
67669
|
+
"from",
|
|
67670
|
+
"of",
|
|
67671
|
+
"by",
|
|
67672
|
+
"about",
|
|
67673
|
+
"at",
|
|
67674
|
+
"as",
|
|
67675
|
+
"into",
|
|
67676
|
+
"onto",
|
|
67677
|
+
"please",
|
|
67678
|
+
"now",
|
|
67679
|
+
"here",
|
|
67680
|
+
"there",
|
|
67681
|
+
"name",
|
|
67682
|
+
"names",
|
|
67683
|
+
"named",
|
|
67684
|
+
"called",
|
|
67685
|
+
"what",
|
|
67686
|
+
"which",
|
|
67687
|
+
"how",
|
|
67688
|
+
"who",
|
|
67689
|
+
"where",
|
|
67690
|
+
"why",
|
|
67691
|
+
"am",
|
|
67692
|
+
"is",
|
|
67693
|
+
"are"
|
|
67694
|
+
])).has(lower) && SAFE_REF_PATTERN.test(candidate))
|
|
67695
|
+
return candidate;
|
|
67696
|
+
}
|
|
67697
|
+
let stopwords = /* @__PURE__ */ new Set([
|
|
67698
|
+
"this",
|
|
67699
|
+
"that",
|
|
67700
|
+
"the",
|
|
67701
|
+
"our",
|
|
67702
|
+
"my",
|
|
67703
|
+
"a",
|
|
67704
|
+
"an",
|
|
67705
|
+
"current",
|
|
67706
|
+
"active",
|
|
67707
|
+
"latest",
|
|
67708
|
+
"recent",
|
|
67709
|
+
"most",
|
|
67710
|
+
"head",
|
|
67711
|
+
"commit",
|
|
67712
|
+
"commits",
|
|
67713
|
+
"working",
|
|
67714
|
+
"tree",
|
|
67715
|
+
"directory",
|
|
67716
|
+
"copy",
|
|
67717
|
+
"repo",
|
|
67718
|
+
"repository",
|
|
67719
|
+
"status",
|
|
67720
|
+
"diff",
|
|
67721
|
+
"log",
|
|
67722
|
+
"show",
|
|
67723
|
+
"please",
|
|
67724
|
+
"now",
|
|
67725
|
+
"thanks",
|
|
67726
|
+
"first",
|
|
67727
|
+
"here",
|
|
67728
|
+
"and",
|
|
67729
|
+
"then",
|
|
67730
|
+
"all",
|
|
67731
|
+
"review",
|
|
67732
|
+
"branches",
|
|
67733
|
+
"branch",
|
|
67734
|
+
"detail",
|
|
67735
|
+
"details",
|
|
67736
|
+
"depth",
|
|
67737
|
+
"brief",
|
|
67738
|
+
"short",
|
|
67739
|
+
"summary",
|
|
67740
|
+
"general",
|
|
67741
|
+
"plain",
|
|
67742
|
+
"text",
|
|
67743
|
+
"markdown",
|
|
67744
|
+
"terminal",
|
|
67745
|
+
"json",
|
|
67746
|
+
"name",
|
|
67747
|
+
"names"
|
|
67748
|
+
// Note: 'named' and 'called' removed from stopwords per Codex R12-F5 so
|
|
67749
|
+
// "Show the latest commit on named" correctly resolves to "named"
|
|
67750
|
+
]), qualifiedMatch = positivePrompt.match(/\b(?:commit|diff|changes?|log|inspect|show)\s+(?:on|in|for|from)\s+(?:the\s+)?(?:branch\s+)?([A-Za-z0-9_./@~^-]+)(?:\s+branch)?(?=[\s;,?.]|$)/i);
|
|
67751
|
+
if (qualifiedMatch) {
|
|
67752
|
+
let candidate = stripSentencePunctuation(qualifiedMatch[1]);
|
|
67753
|
+
if (!stopwords.has(candidate.toLowerCase()) && SAFE_REF_PATTERN.test(candidate))
|
|
67754
|
+
return candidate;
|
|
67755
|
+
}
|
|
67756
|
+
let matches = [...positivePrompt.matchAll(/\b(?:on|in|for|from)\s+(?:the\s+)?(?:branch\s+)?([A-Za-z0-9_./@~^-]+)(?:\s+branch)?(?=[\s;,?.]|$)/gi)];
|
|
67757
|
+
for (let m of matches) {
|
|
67758
|
+
let candidate = stripSentencePunctuation(m[1]), lower = candidate.toLowerCase();
|
|
67759
|
+
if (!stopwords.has(lower) && SAFE_REF_PATTERN.test(candidate))
|
|
67760
|
+
return candidate;
|
|
67761
|
+
}
|
|
67762
|
+
}
|
|
67763
|
+
function hasRefSyntax(ref) {
|
|
67764
|
+
let lower = ref.toLowerCase();
|
|
67765
|
+
return !!(["head", "main", "master"].includes(lower) || /^[0-9a-f]{7,40}$/i.test(ref) || /[~^@/]|\.{2,3}/.test(ref) || /^v\d+(?:\.\d+)*$/i.test(ref));
|
|
67766
|
+
}
|
|
67767
|
+
function isLastTokenInPrompt(prompt, token) {
|
|
67768
|
+
let escaped = token.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"), cleaned = prompt.replace(/(?:[\s,;]+(?:please|thanks|thank\s+you|now|for\s+me))+[\s.!?;,:]*$/i, "");
|
|
67769
|
+
return new RegExp(`(?:^|\\s)${escaped}[\\s.!?;,:]*$`, "i").test(cleaned);
|
|
67770
|
+
}
|
|
67771
|
+
var PURPOSE_VERBS = /* @__PURE__ */ new Set([
|
|
67772
|
+
"review",
|
|
67773
|
+
"compare",
|
|
67774
|
+
"inspect",
|
|
67775
|
+
"check",
|
|
67776
|
+
"examine",
|
|
67777
|
+
"see",
|
|
67778
|
+
"view",
|
|
67779
|
+
"verify",
|
|
67780
|
+
"read",
|
|
67781
|
+
"understand",
|
|
67782
|
+
"share",
|
|
67783
|
+
"make",
|
|
67784
|
+
"study",
|
|
67785
|
+
"test",
|
|
67786
|
+
"explain",
|
|
67787
|
+
"commit",
|
|
67788
|
+
"push",
|
|
67789
|
+
"merge",
|
|
67790
|
+
"stage",
|
|
67791
|
+
"apply",
|
|
67792
|
+
"approve"
|
|
67793
|
+
]), PRESENTATION_WORDS = /* @__PURE__ */ new Set([
|
|
67794
|
+
"stat",
|
|
67795
|
+
"stats",
|
|
67796
|
+
"statistics",
|
|
67797
|
+
"context",
|
|
67798
|
+
"color",
|
|
67799
|
+
"colors",
|
|
67800
|
+
"detail",
|
|
67801
|
+
"details",
|
|
67802
|
+
"line",
|
|
67803
|
+
"lines",
|
|
67804
|
+
"number",
|
|
67805
|
+
"numbers",
|
|
67806
|
+
"comment",
|
|
67807
|
+
"comments",
|
|
67808
|
+
"whitespace",
|
|
67809
|
+
"whitespaces",
|
|
67810
|
+
"explanation",
|
|
67811
|
+
"explanations",
|
|
67812
|
+
"message",
|
|
67813
|
+
"messages",
|
|
67814
|
+
"history",
|
|
67815
|
+
"hash",
|
|
67816
|
+
"hashes",
|
|
67817
|
+
"info",
|
|
67818
|
+
"information"
|
|
67819
|
+
]), NON_GIT_SOFTWARE_LIBRARIES = /* @__PURE__ */ new Set([
|
|
67820
|
+
"node",
|
|
67821
|
+
"nodejs",
|
|
67822
|
+
"python",
|
|
67823
|
+
"java",
|
|
67824
|
+
"react",
|
|
67825
|
+
"vue",
|
|
67826
|
+
"angular",
|
|
67827
|
+
"rust",
|
|
67828
|
+
"go",
|
|
67829
|
+
"golang",
|
|
67830
|
+
"ruby",
|
|
67831
|
+
"rails",
|
|
67832
|
+
"django",
|
|
67833
|
+
"spring",
|
|
67834
|
+
"postgres",
|
|
67835
|
+
"postgresql",
|
|
67836
|
+
"mysql",
|
|
67837
|
+
"sqlite",
|
|
67838
|
+
"redis",
|
|
67839
|
+
"docker",
|
|
67840
|
+
"kubernetes",
|
|
67841
|
+
"k8s"
|
|
67842
|
+
]), TEMPORAL_WORDS = /* @__PURE__ */ new Set([
|
|
67843
|
+
"monday",
|
|
67844
|
+
"tuesday",
|
|
67845
|
+
"wednesday",
|
|
67846
|
+
"thursday",
|
|
67847
|
+
"friday",
|
|
67848
|
+
"saturday",
|
|
67849
|
+
"sunday",
|
|
67850
|
+
"yesterday",
|
|
67851
|
+
"today",
|
|
67852
|
+
"tomorrow",
|
|
67853
|
+
"tonight",
|
|
67854
|
+
"morning",
|
|
67855
|
+
"afternoon",
|
|
67856
|
+
"evening",
|
|
67857
|
+
"recent",
|
|
67858
|
+
"week",
|
|
67859
|
+
"month",
|
|
67860
|
+
"year",
|
|
67861
|
+
"day",
|
|
67862
|
+
"hour",
|
|
67863
|
+
"minute",
|
|
67864
|
+
"before",
|
|
67865
|
+
"after",
|
|
67866
|
+
"prior",
|
|
67867
|
+
"earlier",
|
|
67868
|
+
"previous"
|
|
67869
|
+
]), EXPLICIT_STRUCTURAL_EXCLUDED = /* @__PURE__ */ new Set([
|
|
67870
|
+
"working",
|
|
67871
|
+
"tree",
|
|
67872
|
+
"copy",
|
|
67873
|
+
"index",
|
|
67874
|
+
"staging",
|
|
67875
|
+
"cache",
|
|
67876
|
+
"repo",
|
|
67877
|
+
"repository",
|
|
67878
|
+
"it",
|
|
67879
|
+
"me",
|
|
67880
|
+
"us",
|
|
67881
|
+
"them",
|
|
67882
|
+
"this",
|
|
67883
|
+
"that",
|
|
67884
|
+
"the",
|
|
67885
|
+
"a",
|
|
67886
|
+
"an",
|
|
67887
|
+
"my",
|
|
67888
|
+
"our",
|
|
67889
|
+
"your",
|
|
67890
|
+
"their"
|
|
67891
|
+
]), COMMAND_FUNCTION_EXCLUDED = /* @__PURE__ */ new Set([
|
|
67892
|
+
"and",
|
|
67893
|
+
"then",
|
|
67894
|
+
"so",
|
|
67895
|
+
"or",
|
|
67896
|
+
"but",
|
|
67897
|
+
"for",
|
|
67898
|
+
"in",
|
|
67899
|
+
"of",
|
|
67900
|
+
"on",
|
|
67901
|
+
"with",
|
|
67902
|
+
"from",
|
|
67903
|
+
"to",
|
|
67904
|
+
"into",
|
|
67905
|
+
"at",
|
|
67906
|
+
"by",
|
|
67907
|
+
"about",
|
|
67908
|
+
"between",
|
|
67909
|
+
"against",
|
|
67910
|
+
"since",
|
|
67911
|
+
"what",
|
|
67912
|
+
"which",
|
|
67913
|
+
"how",
|
|
67914
|
+
"who",
|
|
67915
|
+
"where",
|
|
67916
|
+
"why",
|
|
67917
|
+
"please",
|
|
67918
|
+
"now",
|
|
67919
|
+
"right",
|
|
67920
|
+
"here",
|
|
67921
|
+
"there",
|
|
67922
|
+
"yesterday",
|
|
67923
|
+
"today",
|
|
67924
|
+
"tomorrow",
|
|
67925
|
+
"week",
|
|
67926
|
+
"month",
|
|
67927
|
+
"year",
|
|
67928
|
+
"last",
|
|
67929
|
+
"past",
|
|
67930
|
+
"recent",
|
|
67931
|
+
"working",
|
|
67932
|
+
"tree",
|
|
67933
|
+
"copy",
|
|
67934
|
+
"index",
|
|
67935
|
+
"staging",
|
|
67936
|
+
"cache",
|
|
67937
|
+
"repo",
|
|
67938
|
+
"repository",
|
|
67939
|
+
"it",
|
|
67940
|
+
"me",
|
|
67941
|
+
"us",
|
|
67942
|
+
"them",
|
|
67943
|
+
"this",
|
|
67944
|
+
"that",
|
|
67945
|
+
"the",
|
|
67946
|
+
"a",
|
|
67947
|
+
"an",
|
|
67948
|
+
"my",
|
|
67949
|
+
"our",
|
|
67950
|
+
"your",
|
|
67951
|
+
"their"
|
|
67952
|
+
]), REQUIRED_VALUE_SHORT_OPTIONS = /* @__PURE__ */ new Set(["-S", "-G", "-O", "-l", "-I"]), REQUIRED_VALUE_LONG_OPTIONS = /* @__PURE__ */ new Set([
|
|
67953
|
+
"--output",
|
|
67954
|
+
"--src-prefix",
|
|
67955
|
+
"--dst-prefix",
|
|
67956
|
+
"--line-prefix",
|
|
67957
|
+
"--diff-filter",
|
|
67958
|
+
"--color-moved-ws",
|
|
67959
|
+
"--word-diff-regex",
|
|
67960
|
+
"--ignore-matching-lines",
|
|
67961
|
+
"--anchored",
|
|
67962
|
+
"--find-object",
|
|
67963
|
+
"--diff-algorithm",
|
|
67964
|
+
"--inter-hunk-context",
|
|
67965
|
+
"--stat-width",
|
|
67966
|
+
"--stat-name-width",
|
|
67967
|
+
"--stat-count",
|
|
67968
|
+
"--stat-graph-width",
|
|
67969
|
+
"--ws-error-highlight",
|
|
67970
|
+
"--rotate-to",
|
|
67971
|
+
"--skip-to",
|
|
67972
|
+
"--output-indicator-new",
|
|
67973
|
+
"--output-indicator-old",
|
|
67974
|
+
"--output-indicator-context"
|
|
67975
|
+
]);
|
|
67976
|
+
function tokenizeShellArgs(str, baseOffset = 0) {
|
|
67977
|
+
let tokens = [], i = 0, n = str.length;
|
|
67978
|
+
for (; i < n; ) {
|
|
67979
|
+
for (; i < n && str[i] !== `
|
|
67980
|
+
` && /\s/.test(str[i]); )
|
|
67981
|
+
i++;
|
|
67982
|
+
if (i >= n) break;
|
|
67983
|
+
let tokenStart = i;
|
|
67984
|
+
if (str[i] === ";" || str[i] === "&" || str[i] === "|" || str[i] === `
|
|
67985
|
+
`) {
|
|
67986
|
+
let ctrl = str[i++];
|
|
67987
|
+
if (ctrl === `
|
|
67988
|
+
`)
|
|
67989
|
+
for (; i < n && (str[i] === `
|
|
67990
|
+
` || str[i] === "\r"); )
|
|
67991
|
+
i++;
|
|
67992
|
+
else i < n && str[i] === ctrl && (ctrl === "&" || ctrl === "|" || ctrl === ";") && (ctrl += str[i++]);
|
|
67993
|
+
tokens.push({
|
|
67994
|
+
token: ctrl,
|
|
67995
|
+
raw: ctrl,
|
|
67996
|
+
isQuoted: !1,
|
|
67997
|
+
isControl: !0,
|
|
67998
|
+
start: tokenStart + baseOffset,
|
|
67999
|
+
end: i + baseOffset
|
|
68000
|
+
});
|
|
68001
|
+
continue;
|
|
68002
|
+
}
|
|
68003
|
+
let token = "", hasQuote = !1;
|
|
68004
|
+
for (; i < n && !/\s/.test(str[i]); ) {
|
|
68005
|
+
let ch = str[i];
|
|
68006
|
+
if (ch === ";" || ch === "&" || ch === "|" || ch === `
|
|
68007
|
+
`)
|
|
68008
|
+
break;
|
|
68009
|
+
if (ch === "\\")
|
|
68010
|
+
i++, i < n && (str[i] === `
|
|
68011
|
+
` ? i++ : token += str[i++]);
|
|
68012
|
+
else if (ch === "'") {
|
|
68013
|
+
for (hasQuote = !0, i++; i < n && str[i] !== "'"; )
|
|
68014
|
+
token += str[i++];
|
|
68015
|
+
i < n && str[i] === "'" && i++;
|
|
68016
|
+
} else if (ch === '"') {
|
|
68017
|
+
for (hasQuote = !0, i++; i < n && str[i] !== '"'; )
|
|
68018
|
+
if (str[i] === "\\" && i + 1 < n) {
|
|
68019
|
+
let next = str[i + 1];
|
|
68020
|
+
next === `
|
|
68021
|
+
` ? i += 2 : ((next === '"' || next === "\\" || next === "$" || next === "`") && i++, token += str[i++]);
|
|
68022
|
+
} else
|
|
68023
|
+
token += str[i++];
|
|
68024
|
+
i < n && str[i] === '"' && i++;
|
|
68025
|
+
} else if (ch === "`") {
|
|
68026
|
+
for (hasQuote = !0, i++; i < n && str[i] !== "`"; )
|
|
68027
|
+
str[i] === "\\" && i + 1 < n && i++, token += str[i++];
|
|
68028
|
+
i < n && str[i] === "`" && i++;
|
|
68029
|
+
} else
|
|
68030
|
+
token += str[i++];
|
|
68031
|
+
}
|
|
68032
|
+
if (i === tokenStart) {
|
|
68033
|
+
i++;
|
|
68034
|
+
continue;
|
|
68035
|
+
}
|
|
68036
|
+
if (!hasQuote && token === "")
|
|
68037
|
+
continue;
|
|
68038
|
+
let raw = str.slice(tokenStart, i);
|
|
68039
|
+
tokens.push({
|
|
68040
|
+
token,
|
|
68041
|
+
raw,
|
|
68042
|
+
isQuoted: hasQuote,
|
|
68043
|
+
start: tokenStart + baseOffset,
|
|
68044
|
+
end: i + baseOffset
|
|
68045
|
+
});
|
|
68046
|
+
}
|
|
68047
|
+
return tokens;
|
|
68048
|
+
}
|
|
68049
|
+
function parseGitDiffTokens(tokens) {
|
|
68050
|
+
for (let i = 0; i < tokens.length; i++) {
|
|
68051
|
+
let tok = tokens[i], { token } = tok;
|
|
68052
|
+
if (tok.isControl || token === "--")
|
|
68053
|
+
break;
|
|
68054
|
+
if (token.startsWith("-") && token !== "-") {
|
|
68055
|
+
if (token.includes("="))
|
|
68056
|
+
continue;
|
|
68057
|
+
if (REQUIRED_VALUE_SHORT_OPTIONS.has(token)) {
|
|
68058
|
+
i + 1 < tokens.length && !tokens[i + 1].isControl && tokens[i + 1].token !== "--" && i++;
|
|
68059
|
+
continue;
|
|
68060
|
+
}
|
|
68061
|
+
if (token.length > 2 && REQUIRED_VALUE_SHORT_OPTIONS.has(token.slice(0, 2)))
|
|
68062
|
+
continue;
|
|
68063
|
+
if (REQUIRED_VALUE_LONG_OPTIONS.has(token)) {
|
|
68064
|
+
i + 1 < tokens.length && !tokens[i + 1].isControl && tokens[i + 1].token !== "--" && i++;
|
|
68065
|
+
continue;
|
|
68066
|
+
}
|
|
68067
|
+
continue;
|
|
68068
|
+
}
|
|
68069
|
+
return tok;
|
|
68070
|
+
}
|
|
68071
|
+
}
|
|
68072
|
+
function extractComparisonBaseRefInfo(prompt, options) {
|
|
68073
|
+
let startIdx = 0;
|
|
68074
|
+
for (; startIdx < prompt.length && /\s/.test(prompt[startIdx]); )
|
|
68075
|
+
startIdx++;
|
|
68076
|
+
let endIdx = prompt.length - 1;
|
|
68077
|
+
for (; endIdx >= startIdx && /\s/.test(prompt[endIdx]); )
|
|
68078
|
+
endIdx--;
|
|
68079
|
+
let promptIndices = [], normalized = "";
|
|
68080
|
+
for (let i = startIdx; i <= endIdx; i++) {
|
|
68081
|
+
let ch = prompt[i];
|
|
68082
|
+
ch !== "`" && ch !== "'" && ch !== '"' && (promptIndices.push(i), normalized += ch);
|
|
68083
|
+
}
|
|
68084
|
+
function makeRefInfo(ref, isExplicit, matchIndex, matchLength, isDirectPromptMatch) {
|
|
68085
|
+
let res = { ref, isExplicit };
|
|
68086
|
+
if (options?.includeSpan && matchIndex !== void 0 && matchLength !== void 0 && matchIndex >= 0) {
|
|
68087
|
+
let start, end;
|
|
68088
|
+
if (isDirectPromptMatch)
|
|
68089
|
+
start = matchIndex, end = matchIndex + matchLength;
|
|
68090
|
+
else {
|
|
68091
|
+
start = promptIndices[matchIndex] ?? matchIndex;
|
|
68092
|
+
let endNormIdx = matchIndex + matchLength - 1;
|
|
68093
|
+
end = (promptIndices[endNormIdx] ?? endNormIdx) + 1;
|
|
68094
|
+
}
|
|
68095
|
+
start > 0 && /[`'"]/.test(prompt[start - 1]) && start--, end < prompt.length && /[`'"]/.test(prompt[end]) && end++, res.span = { start, end };
|
|
68096
|
+
}
|
|
68097
|
+
return res;
|
|
68098
|
+
}
|
|
68099
|
+
let quotedDiffOfRangeMatch = prompt.match(/\b(?:show|view|see)?\s*(?:the\s+)?(?:working\s+(?:tree|copy)\s+)?diff\s+of\s+(?:commit\s+)?([`'"])((?:[A-Za-z0-9_/@~^-]+(?:\.[A-Za-z0-9_/@~^-]+)*)?\.{2,3}(?:[A-Za-z0-9_/@~^-]+(?:\.[A-Za-z0-9_/@~^-]+)*)?)\1/i);
|
|
68100
|
+
if (quotedDiffOfRangeMatch) {
|
|
68101
|
+
let raw = stripSentencePunctuation(quotedDiffOfRangeMatch[2], { preserveRangeDots: !0 });
|
|
68102
|
+
if ((raw.includes("..") || raw.includes("...")) && SAFE_REF_PATTERN.test(raw) && !raw.startsWith("-"))
|
|
68103
|
+
return makeRefInfo(raw, !0, quotedDiffOfRangeMatch.index, quotedDiffOfRangeMatch[0].length, !0);
|
|
68104
|
+
}
|
|
68105
|
+
let diffOfRangeMatch = normalized.match(/\b(?:show|view|see)?\s*(?:the\s+)?(?:working\s+(?:tree|copy)\s+)?diff\s+of\s+(?:commit\s+)?((?:[A-Za-z0-9_/@~^-]+(?:\.[A-Za-z0-9_/@~^-]+)*)?\.{2,3}[A-Za-z0-9_/@~^-]+(?:\.[A-Za-z0-9_/@~^-]+)*)(?![0-9A-Za-z_/@~^-]|\.[0-9A-Za-z_/@~^-])/i);
|
|
68106
|
+
if (diffOfRangeMatch) {
|
|
68107
|
+
let raw = stripSentencePunctuation(diffOfRangeMatch[1], { preserveRangeDots: !0 });
|
|
68108
|
+
if ((raw.includes("..") || raw.includes("...")) && SAFE_REF_PATTERN.test(raw) && !raw.startsWith("-"))
|
|
68109
|
+
return makeRefInfo(raw, !0, diffOfRangeMatch.index, diffOfRangeMatch[0].length, !1);
|
|
68110
|
+
}
|
|
68111
|
+
let quotedBetweenMatch = prompt.match(/\b(?:difference|diff)\s+between\s+(?:my\s+|the\s+)?working\s+(?:tree|copy)\s+and\s+(?:(?:the\s+)?commit\s+)?([`'"])([^`'"]+)\1/i) || prompt.match(/\b(?:difference|diff)\s+between\s+(?:(?:the\s+)?commit\s+)?([`'"])([^`'"]+)\1\s+and\s+(?:my\s+|the\s+)?working\s+(?:tree|copy)/i);
|
|
68112
|
+
if (quotedBetweenMatch) {
|
|
68113
|
+
let raw = stripSentencePunctuation(quotedBetweenMatch[2].trim(), { preserveRangeDots: !0 }), lower = raw.toLowerCase();
|
|
68114
|
+
if (!EXPLICIT_STRUCTURAL_EXCLUDED.has(lower) && SAFE_REF_PATTERN.test(raw) && !raw.startsWith("-") && raw !== "--")
|
|
68115
|
+
return makeRefInfo(lower === "head" ? "HEAD" : raw, !0, quotedBetweenMatch.index, quotedBetweenMatch[0].length, !0);
|
|
68116
|
+
}
|
|
68117
|
+
let betweenMatch = normalized.match(/\b(?:difference|diff)\s+between\s+(?:my\s+|the\s+)?working\s+(?:tree|copy)\s+and\s+(?:\b(?:the\s+)?(?<mod>commit)\s+(?!(?:and|or|then|vs|but|so|also|with|to|for|from|please|pls|kindly|in)(?![a-zA-Z0-9_/@~^-]|\.+[a-zA-Z0-9_/@~^-])))?(?<ref>[a-zA-Z0-9_./@~^-]+)(?![0-9A-Za-z_/@~^-]|\.+[0-9A-Za-z_/@~^-])/i) || normalized.match(/\b(?:difference|diff)\s+between\s+(?:\b(?:the\s+)?(?<mod>commit)\s+(?!(?:and|or|then|vs|but|so|also|with|to|for|from)(?![a-zA-Z0-9_/@~^-]|\.+[a-zA-Z0-9_/@~^-])))?(?<ref>[a-zA-Z0-9_./@~^-]+)\s+and\s+(?:my\s+|the\s+)?working\s+(?:tree|copy)\b/i);
|
|
68118
|
+
if (betweenMatch) {
|
|
68119
|
+
let raw = stripSentencePunctuation(betweenMatch.groups?.ref || betweenMatch[1]), lower = raw.toLowerCase();
|
|
68120
|
+
if (!EXPLICIT_STRUCTURAL_EXCLUDED.has(lower) && SAFE_REF_PATTERN.test(raw) && !raw.startsWith("-")) {
|
|
68121
|
+
let isExplicit = !!betweenMatch.groups?.mod ? hasRefSyntax(raw) : !0;
|
|
68122
|
+
return makeRefInfo(lower === "head" ? "HEAD" : raw, isExplicit, betweenMatch.index, betweenMatch[0].length, !1);
|
|
68123
|
+
}
|
|
68124
|
+
}
|
|
68125
|
+
let quotedDiffAgainstMatch = prompt.match(/\b(?:show|view|see)?\s*(?:the\s+)?(?:working\s+(?:tree|copy)\s+)?diff\s+against\s+(?:(?:the\s+)?commit\s+)?([`'"])([^`'"]+)\1/i);
|
|
68126
|
+
if (quotedDiffAgainstMatch) {
|
|
68127
|
+
let raw = stripSentencePunctuation(quotedDiffAgainstMatch[2], { preserveRangeDots: !0 }), lower = raw.toLowerCase();
|
|
68128
|
+
if (!EXPLICIT_STRUCTURAL_EXCLUDED.has(lower) && SAFE_REF_PATTERN.test(raw) && !raw.startsWith("-"))
|
|
68129
|
+
return makeRefInfo(lower === "head" ? "HEAD" : raw, !0, quotedDiffAgainstMatch.index, quotedDiffAgainstMatch[0].length, !0);
|
|
68130
|
+
}
|
|
68131
|
+
let diffAgainstMatch = normalized.match(/\bdiff\s+against\s+(?:\b(?:the\s+)?(?<mod>commit)\s+(?!(?:and|or|then|vs|but|so|also|with|to|for|from|please|pls|kindly|in)(?![a-zA-Z0-9_/@~^-]|\.+[a-zA-Z0-9_/@~^-])))?(?<ref>[a-zA-Z0-9_./@~^-]+)(?![0-9A-Za-z_/@~^-]|\.+[0-9A-Za-z_/@~^-])/i);
|
|
68132
|
+
if (diffAgainstMatch) {
|
|
68133
|
+
let raw = stripSentencePunctuation(diffAgainstMatch.groups?.ref || diffAgainstMatch[1]), lower = raw.toLowerCase();
|
|
68134
|
+
if (!EXPLICIT_STRUCTURAL_EXCLUDED.has(lower) && SAFE_REF_PATTERN.test(raw) && !raw.startsWith("-")) {
|
|
68135
|
+
let isExplicit = !!diffAgainstMatch.groups?.mod ? hasRefSyntax(raw) : !0;
|
|
68136
|
+
return makeRefInfo(lower === "head" ? "HEAD" : raw, isExplicit, diffAgainstMatch.index, diffAgainstMatch[0].length, !1);
|
|
68137
|
+
}
|
|
68138
|
+
}
|
|
68139
|
+
if (/\b(?:git|repo|repository|working\s+(?:tree|copy)|uncommitted|diff|changes?)\b/i.test(normalized)) {
|
|
68140
|
+
let quotedCompareAgainstMatch = prompt.match(/\bcompare\s+(?:my\s+)?working\s+(?:tree|copy)\s+(?:to|with|against)\s+(?:(?:the\s+)?commit\s+)?([`'"])([^`'"]+)\1/i) || prompt.match(/\bcompare\s+against\s+(?:(?:the\s+)?commit\s+)?([`'"])([^`'"]+)\1/i) || prompt.match(/\bcompare\s+(?:(?:the\s+)?commit\s+)?([`'"])([^`'"]+)\1\s+(?:to|with|against)\s+(?:my\s+)?working\s+(?:tree|copy)\b/i);
|
|
68141
|
+
if (quotedCompareAgainstMatch) {
|
|
68142
|
+
let raw = stripSentencePunctuation(quotedCompareAgainstMatch[2].trim(), { preserveRangeDots: !0 }), lower = raw.toLowerCase();
|
|
68143
|
+
if (!EXPLICIT_STRUCTURAL_EXCLUDED.has(lower) && SAFE_REF_PATTERN.test(raw) && !raw.startsWith("-") && raw !== "--")
|
|
68144
|
+
return makeRefInfo(lower === "head" ? "HEAD" : raw, !0, quotedCompareAgainstMatch.index, quotedCompareAgainstMatch[0].length, !0);
|
|
68145
|
+
}
|
|
68146
|
+
let compareAgainstMatch = normalized.match(/\bcompare\s+(?:my\s+)?working\s+(?:tree|copy)\s+(?:to|with|against)\s+(?:\b(?:the\s+)?(?<mod>commit)\s+(?!(?:and|or|then|vs|but|so|also|with|to|for|from|please|pls|kindly|in)(?![a-zA-Z0-9_/@~^-]|\.+[a-zA-Z0-9_/@~^-])))?(?<ref>[a-zA-Z0-9_./@~^-]+)(?![0-9A-Za-z_/@~^-]|\.+[0-9A-Za-z_/@~^-])/i) || normalized.match(/\bcompare\s+against\s+(?:\b(?:the\s+)?(?<mod>commit)\s+(?!(?:and|or|then|vs|but|so|also|with|to|for|from|please|pls|kindly|in)(?![a-zA-Z0-9_/@~^-]|\.+[a-zA-Z0-9_/@~^-])))?(?<ref>[a-zA-Z0-9_./@~^-]+)(?![0-9A-Za-z_/@~^-]|\.+[0-9A-Za-z_/@~^-])/i) || normalized.match(/\bcompare\s+(?:\b(?:the\s+)?(?<mod>commit)\s+(?!(?:and|or|then|vs|but|so|also|with|to|for|from)(?![a-zA-Z0-9_/@~^-]|\.+[a-zA-Z0-9_/@~^-])))?(?<ref>[a-zA-Z0-9_./@~^-]+)\s+(?:to|with|against)\s+(?:my\s+)?working\s+(?:tree|copy)\b/i);
|
|
68147
|
+
if (compareAgainstMatch) {
|
|
68148
|
+
let raw = stripSentencePunctuation(compareAgainstMatch.groups?.ref || compareAgainstMatch[1]), lower = raw.toLowerCase();
|
|
68149
|
+
if (!EXPLICIT_STRUCTURAL_EXCLUDED.has(lower) && SAFE_REF_PATTERN.test(raw) && !raw.startsWith("-")) {
|
|
68150
|
+
let isExplicit = !!compareAgainstMatch.groups?.mod ? hasRefSyntax(raw) : !0;
|
|
68151
|
+
return makeRefInfo(lower === "head" ? "HEAD" : raw, isExplicit, compareAgainstMatch.index, compareAgainstMatch[0].length, !1);
|
|
68152
|
+
}
|
|
68153
|
+
}
|
|
68154
|
+
}
|
|
68155
|
+
let showDiffAgainstMatch = normalized.match(/\b(?:show|view|see)\s+(?:the\s+)?(?:working\s+(?:tree|copy)\s+)?diff\s+against\s+(?:\b(?:the\s+)?(?<mod>commit)\s+(?!(?:and|or|then|vs|but|so|also|with|to|for|from|please|pls|kindly|in)(?![a-zA-Z0-9_/@~^-]|\.+[a-zA-Z0-9_/@~^-])))?(?<ref>[a-zA-Z0-9_./@~^-]+)(?![0-9A-Za-z_/@~^-]|\.+[0-9A-Za-z_/@~^-])/i);
|
|
68156
|
+
if (showDiffAgainstMatch) {
|
|
68157
|
+
let raw = stripSentencePunctuation(showDiffAgainstMatch.groups?.ref || showDiffAgainstMatch[1]), lower = raw.toLowerCase();
|
|
68158
|
+
if (!EXPLICIT_STRUCTURAL_EXCLUDED.has(lower) && SAFE_REF_PATTERN.test(raw) && !raw.startsWith("-")) {
|
|
68159
|
+
let isExplicit = !!showDiffAgainstMatch.groups?.mod ? hasRefSyntax(raw) : !0;
|
|
68160
|
+
return makeRefInfo(lower === "head" ? "HEAD" : raw, isExplicit, showDiffAgainstMatch.index, showDiffAgainstMatch[0].length, !1);
|
|
68161
|
+
}
|
|
68162
|
+
}
|
|
68163
|
+
let quotedDiffToMatch = prompt.match(/\b(?:show|view|see)?\s*(?:the\s+)?(?:working\s+(?:tree|copy)\s+)?diff\s+to\s+(?:(?:the\s+)?commit\s+)?([`'"])([^`'"]+)\1/i);
|
|
68164
|
+
if (quotedDiffToMatch) {
|
|
68165
|
+
let raw = stripSentencePunctuation(quotedDiffToMatch[2], { preserveRangeDots: !0 }), lower = raw.toLowerCase();
|
|
68166
|
+
if (!EXPLICIT_STRUCTURAL_EXCLUDED.has(lower) && SAFE_REF_PATTERN.test(raw) && !raw.startsWith("-"))
|
|
68167
|
+
return makeRefInfo(lower === "head" ? "HEAD" : raw, !0, quotedDiffToMatch.index, quotedDiffToMatch[0].length, !0);
|
|
68168
|
+
}
|
|
68169
|
+
let diffToMatch = normalized.match(/\bdiff\s+to\s+(?:\b(?:the\s+)?(?<mod>commit)\s+(?!(?:and|or|then|vs|but|so|also|with|to|for|from|please|pls|kindly|in)(?![a-zA-Z0-9_/@~^-]|\.+[a-zA-Z0-9_/@~^-])))?(?<ref>[a-zA-Z0-9_./@~^-]+)(?![0-9A-Za-z_/@~^-]|\.+[0-9A-Za-z_/@~^-])/i) || normalized.match(/\b(?:show|view|see)\s+(?:the\s+)?(?:working\s+(?:tree|copy)\s+)?diff\s+to\s+(?:\b(?:the\s+)?(?<mod>commit)\s+(?!(?:and|or|then|vs|but|so|also|with|to|for|from|please|pls|kindly|in)(?![a-zA-Z0-9_/@~^-]|\.+[a-zA-Z0-9_/@~^-])))?(?<ref>[a-zA-Z0-9_./@~^-]+)(?![0-9A-Za-z_/@~^-]|\.+[0-9A-Za-z_/@~^-])/i);
|
|
68170
|
+
if (diffToMatch) {
|
|
68171
|
+
let raw = stripSentencePunctuation(diffToMatch.groups?.ref || diffToMatch[1]), lower = raw.toLowerCase();
|
|
68172
|
+
if (!PURPOSE_VERBS.has(lower) && !EXPLICIT_STRUCTURAL_EXCLUDED.has(lower) && !TEMPORAL_WORDS.has(lower) && SAFE_REF_PATTERN.test(raw) && !raw.startsWith("-")) {
|
|
68173
|
+
let isExplicit = !!diffToMatch.groups?.mod ? hasRefSyntax(raw) : hasRefSyntax(raw) || isLastTokenInPrompt(normalized, raw);
|
|
68174
|
+
return makeRefInfo(lower === "head" ? "HEAD" : raw, isExplicit, diffToMatch.index, diffToMatch[0].length, !1);
|
|
68175
|
+
}
|
|
68176
|
+
}
|
|
68177
|
+
let quotedDiffWithMatch = prompt.match(/\b(?:show|view|see)?\s*(?:the\s+)?(?:working\s+(?:tree|copy)\s+)?diff\s+with\s+(?:(?:the\s+)?commit\s+)?([`'"])([^`'"]+)\1/i);
|
|
68178
|
+
if (quotedDiffWithMatch) {
|
|
68179
|
+
let raw = stripSentencePunctuation(quotedDiffWithMatch[2], { preserveRangeDots: !0 }), lower = raw.toLowerCase();
|
|
68180
|
+
if (!EXPLICIT_STRUCTURAL_EXCLUDED.has(lower) && SAFE_REF_PATTERN.test(raw) && !raw.startsWith("-"))
|
|
68181
|
+
return makeRefInfo(lower === "head" ? "HEAD" : raw, !0, quotedDiffWithMatch.index, quotedDiffWithMatch[0].length, !0);
|
|
68182
|
+
}
|
|
68183
|
+
let diffWithMatch = normalized.match(/\bdiff\s+with\s+(?:\b(?:the\s+)?(?<mod>commit)\s+(?!(?:and|or|then|vs|but|so|also|with|to|for|from|please|pls|kindly|in)(?![a-zA-Z0-9_/@~^-]|\.+[a-zA-Z0-9_/@~^-])))?(?!line\s+numbers?\b|numbers?\b|(?:more|full|extra)\s+(?:detail|details|context|info|information)\b)(?<ref>[a-zA-Z0-9_./@~^-]+)(?![0-9A-Za-z_/@~^-]|\.+[0-9A-Za-z_/@~^-])/i) || normalized.match(/\b(?:show|view|see)\s+(?:the\s+)?(?:working\s+(?:tree|copy)\s+)?diff\s+with\s+(?:\b(?:the\s+)?(?<mod>commit)\s+(?!(?:and|or|then|vs|but|so|also|with|to|for|from|please|pls|kindly|in)(?![a-zA-Z0-9_/@~^-]|\.+[a-zA-Z0-9_/@~^-])))?(?!line\s+numbers?\b|numbers?\b|(?:more|full|extra)\s+(?:detail|details|context|info|information)\b)(?<ref>[a-zA-Z0-9_./@~^-]+)(?![0-9A-Za-z_/@~^-]|\.+[0-9A-Za-z_/@~^-])/i);
|
|
68184
|
+
if (diffWithMatch) {
|
|
68185
|
+
let raw = stripSentencePunctuation(diffWithMatch.groups?.ref || diffWithMatch[1]), lower = raw.toLowerCase();
|
|
68186
|
+
if (!PRESENTATION_WORDS.has(lower) && !EXPLICIT_STRUCTURAL_EXCLUDED.has(lower) && !TEMPORAL_WORDS.has(lower) && SAFE_REF_PATTERN.test(raw) && !raw.startsWith("-")) {
|
|
68187
|
+
let isExplicit = !!diffWithMatch.groups?.mod ? hasRefSyntax(raw) : hasRefSyntax(raw) || isLastTokenInPrompt(normalized, raw);
|
|
68188
|
+
return makeRefInfo(lower === "head" ? "HEAD" : raw, isExplicit, diffWithMatch.index, diffWithMatch[0].length, !1);
|
|
68189
|
+
}
|
|
68190
|
+
}
|
|
68191
|
+
let quotedSinceMatch = prompt.match(/\b(?:diff|changes)\s+since\s+(?:(?:the\s+)?commit\s+)?([`'"])([^`'"]+)\1/i), diffSinceMatch = quotedSinceMatch || normalized.match(/\b(?:show|view|see|give|get|display|print)?\s*(?:me\s+)?(?:the\s+|my\s+)?(diff|changes)\s+since\s+(?:\b(?:the\s+)?(?<mod>commit)\s+(?!(?:and|or|then|vs|but|so|also|with|to|for|from|please|pls|kindly|in)(?![a-zA-Z0-9_/@~^-]|\.+[a-zA-Z0-9_/@~^-]|\.\.)))?(?<ref>[a-zA-Z0-9_./@~^-]+)(?![0-9A-Za-z_/@~^-]|\.+[0-9A-Za-z_/@~^-]|\.\.)/i);
|
|
68192
|
+
if (diffSinceMatch && !/\bbreaking\s+changes\b/i.test(normalized)) {
|
|
68193
|
+
let isQuoted = !!quotedSinceMatch, raw = isQuoted ? stripSentencePunctuation(quotedSinceMatch[2].trim(), { preserveRangeDots: !0 }) : stripSentencePunctuation(diffSinceMatch.groups?.ref || diffSinceMatch[2]), lower = raw.toLowerCase(), hasGitContext = /\b(?:repo|repository|branch|commit|head|working\s+(?:tree|copy)|git|diff)\b/i.test(normalized), namedLibraryMatch = NON_GIT_SOFTWARE_LIBRARIES.has(lower), escapedRaw = raw.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"), versionAfterRawMatch = new RegExp(`\\bsince\\s+${escapedRaw}\\s+(?:v?\\d+(?:\\.\\d+)*)\\b(?!\\s+(?:days?|weeks?|months?|years?|hours?|minutes?))`, "i").test(normalized), dottedVersionMatch = /\bsince\s+v?\d+\.\d+(?:\.\d+)*\b/i.test(normalized), isLibraryInquiry = !isQuoted && !hasRefSyntax(raw) && !hasGitContext && (namedLibraryMatch || versionAfterRawMatch || dottedVersionMatch), isCalendarDate = /^\d{4}[-/]\d{1,2}[-/]\d{1,2}$/.test(raw), isFourDigitYear = /^(?:19|20)\d{2}$/.test(raw), isTemporal = !isQuoted && (isCalendarDate || isFourDigitYear || !hasRefSyntax(raw) && (TEMPORAL_WORDS.has(lower) || /\bsince\s+\d+\s+(?:days?|weeks?|months?|years?|hours?|minutes?)\s+ago\b/i.test(normalized) || /\bsince\s+(?:last|this)\s+(?:week|month|year|monday|tuesday|wednesday|thursday|friday|saturday|sunday)\b/i.test(normalized))), isExcluded = !isQuoted && (COMMAND_FUNCTION_EXCLUDED.has(lower) || TEMPORAL_WORDS.has(lower) || PRESENTATION_WORDS.has(lower));
|
|
68194
|
+
if (!isLibraryInquiry && (!isTemporal || isQuoted) && !isExcluded && SAFE_REF_PATTERN.test(raw) && !raw.startsWith("-")) {
|
|
68195
|
+
let isHexHash = /^[0-9a-fA-F]{4,40}$/.test(raw), isAllDigits = /^\d+$/.test(raw), hasMod = !isQuoted && !!diffSinceMatch.groups?.mod, isExplicit = isQuoted ? !0 : hasMod ? hasRefSyntax(raw) : hasRefSyntax(raw) && !isAllDigits || !isHexHash && !isAllDigits && isLastTokenInPrompt(normalized, raw);
|
|
68196
|
+
return makeRefInfo(lower === "head" ? "HEAD" : raw, isExplicit, diffSinceMatch.index, diffSinceMatch[0].length, isQuoted);
|
|
68197
|
+
}
|
|
68198
|
+
}
|
|
68199
|
+
let quotedWholeGitDiffMatch = prompt.match(/([`'"])\s*git\s+diff\b([\s\S]*?)\1/i);
|
|
68200
|
+
if (quotedWholeGitDiffMatch) {
|
|
68201
|
+
let isLiteralStart = /^\s*[`'"]/.test(prompt), innerStr = quotedWholeGitDiffMatch[0].slice(1, -1), innerTokens = tokenizeShellArgs(innerStr);
|
|
68202
|
+
if (innerTokens.length >= 2 && innerTokens[0].token.toLowerCase() === "git" && innerTokens[1].token.toLowerCase() === "diff") {
|
|
68203
|
+
let operand = parseGitDiffTokens(innerTokens.slice(2));
|
|
68204
|
+
if (operand && !/[\s\x00-\x1f\x7f]/.test(operand.token)) {
|
|
68205
|
+
let raw = stripSentencePunctuation(operand.token, { preserveRangeDots: !0 }), lower = raw.toLowerCase();
|
|
68206
|
+
if (!COMMAND_FUNCTION_EXCLUDED.has(lower) && SAFE_REF_PATTERN.test(raw) && !raw.startsWith("-") && raw !== "--") {
|
|
68207
|
+
let isExplicit = isLiteralStart || operand.isQuoted ? !0 : hasRefSyntax(raw);
|
|
68208
|
+
return makeRefInfo(lower === "head" ? "HEAD" : raw, isExplicit, quotedWholeGitDiffMatch.index, quotedWholeGitDiffMatch[0].length, !0);
|
|
68209
|
+
}
|
|
68210
|
+
}
|
|
68211
|
+
}
|
|
68212
|
+
}
|
|
68213
|
+
let literalGitDiffMatch = prompt.match(/^\s*git\s+diff\b([\s\S]*)/i);
|
|
68214
|
+
if (literalGitDiffMatch) {
|
|
68215
|
+
let cmdTokens = tokenizeShellArgs(literalGitDiffMatch[0]);
|
|
68216
|
+
if (cmdTokens.length >= 2 && cmdTokens[0].token.toLowerCase() === "git" && cmdTokens[1].token.toLowerCase() === "diff") {
|
|
68217
|
+
let operand = parseGitDiffTokens(cmdTokens.slice(2));
|
|
68218
|
+
if (operand && !/[\s\x00-\x1f\x7f]/.test(operand.token)) {
|
|
68219
|
+
let raw = stripSentencePunctuation(operand.token, { preserveRangeDots: !0 }), lower = raw.toLowerCase();
|
|
68220
|
+
if (!COMMAND_FUNCTION_EXCLUDED.has(lower) && SAFE_REF_PATTERN.test(raw) && !raw.startsWith("-") && raw !== "--")
|
|
68221
|
+
return makeRefInfo(lower === "head" ? "HEAD" : raw, !0, literalGitDiffMatch.index, operand.end, !0);
|
|
68222
|
+
}
|
|
68223
|
+
}
|
|
68224
|
+
}
|
|
68225
|
+
let openExcluded = /* @__PURE__ */ new Set([
|
|
68226
|
+
...EXPLICIT_STRUCTURAL_EXCLUDED,
|
|
68227
|
+
...PURPOSE_VERBS,
|
|
68228
|
+
...PRESENTATION_WORDS,
|
|
68229
|
+
...COMMAND_FUNCTION_EXCLUDED,
|
|
68230
|
+
"vs",
|
|
68231
|
+
"changes",
|
|
68232
|
+
"files",
|
|
68233
|
+
"file",
|
|
68234
|
+
"code",
|
|
68235
|
+
"workspace",
|
|
68236
|
+
"directory",
|
|
68237
|
+
"folder",
|
|
68238
|
+
"project",
|
|
68239
|
+
"stat",
|
|
68240
|
+
"stats",
|
|
68241
|
+
"cached",
|
|
68242
|
+
"staged",
|
|
68243
|
+
"summary",
|
|
68244
|
+
"details",
|
|
68245
|
+
"detail",
|
|
68246
|
+
"show",
|
|
68247
|
+
"shows",
|
|
68248
|
+
"display",
|
|
68249
|
+
"displays",
|
|
68250
|
+
"view",
|
|
68251
|
+
"see",
|
|
68252
|
+
"check",
|
|
68253
|
+
"inspect",
|
|
68254
|
+
"all",
|
|
68255
|
+
"only",
|
|
68256
|
+
"just"
|
|
68257
|
+
]), conversationalGitDiffMatch = prompt.match(/\bgit\s+diff\b([\s\S]*)/i);
|
|
68258
|
+
if (conversationalGitDiffMatch) {
|
|
68259
|
+
let cmdTokens = tokenizeShellArgs(conversationalGitDiffMatch[0]);
|
|
68260
|
+
if (cmdTokens.length >= 2 && cmdTokens[0].token.toLowerCase() === "git" && cmdTokens[1].token.toLowerCase() === "diff") {
|
|
68261
|
+
let operand = parseGitDiffTokens(cmdTokens.slice(2));
|
|
68262
|
+
if (operand && !/[\s\x00-\x1f\x7f]/.test(operand.token)) {
|
|
68263
|
+
let raw = stripSentencePunctuation(operand.token, { preserveRangeDots: !0 }), lower = raw.toLowerCase();
|
|
68264
|
+
if (operand.isQuoted) {
|
|
68265
|
+
if (SAFE_REF_PATTERN.test(raw) && !raw.startsWith("-") && raw !== "--")
|
|
68266
|
+
return makeRefInfo(lower === "head" ? "HEAD" : raw, !0, conversationalGitDiffMatch.index, operand.end, !0);
|
|
68267
|
+
} else if (!openExcluded.has(lower) && SAFE_REF_PATTERN.test(raw) && !raw.startsWith("-") && raw !== "--")
|
|
68268
|
+
return makeRefInfo(lower === "head" ? "HEAD" : raw, !1, conversationalGitDiffMatch.index, operand.end, !0);
|
|
68269
|
+
}
|
|
68270
|
+
}
|
|
68271
|
+
}
|
|
68272
|
+
let openEndedConversationalMatch = normalized.match(/\b(?:git|repo|working\s+(?:tree|copy)|uncommitted)\s+(?:changes?|diff)\s+(?:since|against)\s+([a-zA-Z0-9_./@~^-]+)(?![0-9A-Za-z_/@~^-]|\.+[0-9A-Za-z_/@~^-]|\.\.)/i) || normalized.match(/\b(?:changes?|diff)\s+in\s+(?:the\s+|my\s+)?(?:working\s+(?:tree|copy)|repo|repository)\s+(?:since|against)\s+([a-zA-Z0-9_./@~^-]+)(?![0-9A-Za-z_/@~^-]|\.+[0-9A-Za-z_/@~^-]|\.\.)/i);
|
|
68273
|
+
if (openEndedConversationalMatch) {
|
|
68274
|
+
let raw = stripSentencePunctuation(openEndedConversationalMatch[1]), lower = raw.toLowerCase();
|
|
68275
|
+
if (!openExcluded.has(lower) && !TEMPORAL_WORDS.has(lower) && SAFE_REF_PATTERN.test(raw) && !raw.startsWith("-") && raw !== "--")
|
|
68276
|
+
return makeRefInfo(lower === "head" ? "HEAD" : raw, !1, openEndedConversationalMatch.index, openEndedConversationalMatch[0].length, !1);
|
|
68277
|
+
}
|
|
68278
|
+
}
|
|
68279
|
+
function extractComparisonBaseRef(prompt) {
|
|
68280
|
+
return extractComparisonBaseRefInfo(prompt)?.ref;
|
|
68281
|
+
}
|
|
68282
|
+
function isConceptualGitQuestion(prompt) {
|
|
68283
|
+
let normalized = prompt.replace(/[\u2018\u2019]/g, "'").replace(/[`'"]/g, "").trim();
|
|
68284
|
+
if (/\b[0-9a-f]{6,40}\b/i.test(normalized) || /^(?:git\s+(?:status|diff|show|log|branch)|(?:check|inspect|examine|look\s+at)\s+(?:my|our|the)\s+(?:repo|repository|working\s+(?:tree|copy)|index|staging|workspace)|(?:show|view|see|display|print)\s+(?:(?:me\s+)?(?:my|our)\s+)?(?:staged\s+(?:changes|diff)|working\s+(?:tree|copy)|untracked))\b/i.test(normalized) || /\b(?:what\s+does|how\s+does)\s+git\s+(?:status|diff)\s+(?:look\s+like|show)\s+(?:right\s+now|currently|in\s+(?:my|our|the)\s+working\s+(?:tree|copy)|in\s+(?:my|our|the)\s+(?:repo|repository)|in\s+my\s+workspace)\b/i.test(normalized))
|
|
68285
|
+
return !1;
|
|
68286
|
+
if (/^(?:(?:can|could|would)\s+you\s+(?:please\s+)?(?:tell|show|explain)\s+(?:to\s+)?me\s+)?(?:please\s+)?(?:how\s+(?:do\s+i|can\s+i|to|should\s+i)|(?:explain|describe|tell\s+me)\s+how\s+to)\s+(?:commit|stage|unstage|discard|add|push|pull|revert|reset|restore|checkout|switch|merge|rebase|stash|tag|diff|use)\b/i.test(normalized) || (/^(?:(?:can|could|would)\s+you\s+(?:please\s+)?(?:tell|show|explain)\s+(?:to\s+)?me\s+)?(?:please\s+)?what\s+does\s+git\s+(?:status|diff|checkout|switch|merge|rebase|commit|branch|log|show|reset|restore|stash)\s+(?:do|mean)\b/i.test(normalized) || /^(?:(?:can|could|would)\s+you\s+)?(?:please\s+)?(?:(?:explain|describe|tell\s+me)\s+)?how\s+(?:does\s+)?git\s+(?:status|diff|checkout|switch|merge|rebase|log|commit|branch)\s+(?:works?|compares?|shows?|handles?|displays?)\b/i.test(normalized) || /^(?:(?:can|could|would)\s+you\s+)?(?:please\s+)?(?:explain|describe)\s+how\s+(?:the\s+|git\s+)?working\s+(?:tree|copy)\s+works?\b/i.test(normalized) || /^(?:(?:can|could|would)\s+you\s+)?(?:please\s+)?(?:explain|describe)\s+(?:the\s+)?concept\s+of\s+(?:the\s+)?(?:git\s+)?(?:working\s+(?:tree|copy)|status|diff|index|staging)\b/i.test(normalized)) && !/\b(?:right\s+now|currently|in\s+my\s+working\s+(?:tree|copy))\b/i.test(normalized))
|
|
68287
|
+
return !0;
|
|
68288
|
+
if (/\b(?:my|our)\s+(?:working\s+(?:tree|copy)|index|staging(?:\s+area)?|staged\s+(?:diff|changes)|repo|repository)\b/i.test(normalized) || /\b(?:staged\s+diff|staged\s+changes|changes\s+in\s+(?:the\s+)?(?:index|staging(?:\s+area)?)|what(?:s|\s+is)\s+in\s+(?:my\s+|the\s+)?staging(?:\s+area)?)\b/i.test(normalized) || /\b(?:my\s+working\s+(?:tree|copy)\s+and\s+(?:head|[a-z0-9_./@~^-]+)|(?:head|[a-z0-9_./@~^-]+)\s+and\s+my\s+working\s+(?:tree|copy))\b/i.test(normalized) || /\b(?:how\s+(?:is|does)\s+my\s+working\s+(?:tree|copy)|what\s+does\s+my\s+working\s+(?:tree|copy)\s+look\s+like|is\s+my\s+working\s+(?:tree|copy)\s+clean)\b/i.test(normalized) || /\b(?:working\s+(?:tree|copy)|repo|repository|git\s+status|status)\s+(?:look\s+like\s+)?after\s+(?:the\s+)?(?:rebase|merge|reset|pull|commit|checkout)\b/i.test(normalized) || /\b(?:changes?\s+in\s+(?:the\s+)?working\s+(?:tree|copy)\s+(?:since|against)\s+HEAD|working\s+(?:tree|copy)\s+diff\s+(?:against|since)\s+HEAD)\b/i.test(normalized) || /\blook\s+like\s+right\s+now\b/i.test(normalized) || /\b(?:right\s+now|currently)\b/i.test(normalized))
|
|
68289
|
+
return !1;
|
|
68290
|
+
let compTargets = "(?:the\\s+)?(?:working\\s+(?:tree|copy)|index|staging(?:\\s+area)?|cache|head)";
|
|
68291
|
+
return !!(new RegExp(
|
|
68292
|
+
`^(?:(?:can|could|would)\\s+you\\s+)?(?:please\\s+)?(?:explain|describe|what(?:s|\\s+is))\\s+(?:(?:the\\s+)?(?:difference|distinction)\\s+between\\s+${compTargets}\\s+and\\s+${compTargets}|how\\s+${compTargets}\\s+(?:differs?|is\\s+different)\\s+from\\s+${compTargets}|${compTargets}\\s+(?:versus|vs\\.?)\\s+${compTargets}|(?:how\\s+to\\s+compare|comparing)\\s+${compTargets}\\s+(?:and|with|to|versus|vs\\.?)\\s+${compTargets})\\b`,
|
|
68293
|
+
"i"
|
|
68294
|
+
).test(normalized) || /^(?:explain|describe|what\s+is\s+(?:the\s+)?difference\s+between|what\s+is)\s+(?:git\s+)?(?:status|diff|log|branch|show|rebase|merge|commit|stash|checkout|switch|reset|restore)\s*[\?.,]?$/i.test(normalized) || /^(?:explain|describe)\s+(?:the\s+)?(?:git\s+)?(?:status|diff|log|branch|show|rebase|merge|commit|stash|checkout|switch|reset|restore)\s+(?:command|concept|operation|workflow)\b/i.test(normalized) || /\b(?:how\s+does\s+git|what\s+does\s+git|what\s+is\s+git|difference\s+between\s+git|explain\s+(?:what\s+|the\s+|how\s+)?git|why\s+does\s+git|how\s+(?:to|do\s+i|can\s+i)\s+use\s+git|tutorial\s+on\s+git|syntax\s+(?:for|of)\s+git)\b/i.test(normalized) || /\b(?:difference\s+between\s+(?:git\s+)?[a-z-]+\s+and\s+(?:git\s+)?[a-z-]+|how\s+does\s+(?:git\s+)?[a-z-]+\s+work)\b/i.test(normalized) || /\b(?:should\s+(?:i|we)\s+use\s+(?:git\s+)?[a-z-]+\s+or\s+(?:git\s+)?[a-z-]+)\b/i.test(normalized) || /\b(?:how\s+(?:do\s+i|to|can\s+i)\s+(?:undo|revert|reset|restore|abort|resolve|cancel)\s+(?:a\s+)?(?:git\s+)?[a-z-]+)\b/i.test(normalized) || /^(?:how|why|should|when|what\s+does)\b.*\b(?:git\s+)?(?:checkout|switch|rebase|merge|commit|stash|reset|restore|cherry-pick)\b/i.test(normalized));
|
|
68295
|
+
}
|
|
68296
|
+
function isStagedDiffIntent(prompt) {
|
|
68297
|
+
if (/^\s*(?:\/|!)?git\s+diff\b/i.test(prompt)) {
|
|
68298
|
+
let [optionsPart2] = prompt.split(/\s+--\s+/);
|
|
68299
|
+
return /(?:^|\s)(?:--cached|--staged)(?:\s|$)/i.test(optionsPart2);
|
|
68300
|
+
}
|
|
68301
|
+
let [optionsPart] = prompt.split(/\s+--\s+/);
|
|
68302
|
+
return !!(/(?:^|\s)(?:--cached|--staged)(?:\s|$)/i.test(optionsPart) || /\b(?:staged\s+diff|cached\s+diff|staged\s+changes|cached\s+changes|changes\s+in\s+the\s+index|in\s+the\s+index|to\s+be\s+committed)\b/i.test(optionsPart) || /\b(?:diff|show|what\s+is)\s+(?:of\s+)?(?:the\s+)?(?:staged|cached)\b/i.test(optionsPart) && !/\b(?:staged|cached)\.[a-z0-9]+\b/i.test(optionsPart));
|
|
68303
|
+
}
|
|
68304
|
+
function isQualifiedAdvisoryRunner(runner) {
|
|
68305
|
+
if (!runner) return !1;
|
|
68306
|
+
if (runner?.opts?.localRunner)
|
|
68307
|
+
return isQualifiedAdvisoryRunner(runner.opts.localRunner);
|
|
68308
|
+
if (runner?.localRunner)
|
|
68309
|
+
return isQualifiedAdvisoryRunner(runner.localRunner);
|
|
68310
|
+
if (runner?.opts?.hostedRunner)
|
|
68311
|
+
return isQualifiedAdvisoryRunner(runner.opts.hostedRunner);
|
|
68312
|
+
if (runner?.hostedRunner)
|
|
68313
|
+
return isQualifiedAdvisoryRunner(runner.hostedRunner);
|
|
68314
|
+
let label = runner.runtimeLabel?.toLowerCase() || "";
|
|
68315
|
+
return label.includes("claude") || label.includes("anthropic") || label.includes("composite") || runner.providerKind === "composite" || label.startsWith("local-gemma-process:") ? !1 : typeof runner.generateAdvisory == "function";
|
|
68316
|
+
}
|
|
68317
|
+
function resolvePreferredAdvisoryRunner(runner) {
|
|
68318
|
+
if (!runner) return null;
|
|
68319
|
+
let isComposite = !!runner?.opts, isFreeTier = runner?.opts?.tier === "FREE";
|
|
68320
|
+
if (isComposite) {
|
|
68321
|
+
let localCandidate = runner?.opts?.localRunner ?? runner?.localRunner ?? null, isLocalHealthy = runner?.localHealthy ?? !0, hostedCandidate = runner?.opts?.hostedRunner ?? runner?.hostedRunner ?? null;
|
|
68322
|
+
return localCandidate && isLocalHealthy && localCandidate.runtimeLabel?.startsWith("local-gemma-process:") ? null : isFreeTier ? localCandidate && isLocalHealthy && isQualifiedAdvisoryRunner(localCandidate) ? localCandidate : null : localCandidate && isLocalHealthy && isQualifiedAdvisoryRunner(localCandidate) ? runner : hostedCandidate && isQualifiedAdvisoryRunner(hostedCandidate) ? hostedCandidate : null;
|
|
68323
|
+
}
|
|
68324
|
+
return (runner.providerKind === "local" || !runner.providerKind && (runner.runtimeLabel?.startsWith("local-gemma-ollama:") || runner.runtimeLabel?.startsWith("local-gemma-process:"))) && isQualifiedAdvisoryRunner(runner) || runner.providerKind === "hosted" && isQualifiedAdvisoryRunner(runner) ? runner : null;
|
|
68325
|
+
}
|
|
68326
|
+
function renderLocalGemmaGitStatusQueryPrompt(args) {
|
|
68327
|
+
let sanitized = sanitizeForTerminal(redactAbsoluteLocalPaths(args.userPrompt)).trim();
|
|
68328
|
+
return [
|
|
68329
|
+
"You are a semantic Git query analyzer for CodeVibe.",
|
|
68330
|
+
"Classify the user prompt to determine if they are asking about Git repository status, diffs, commits, history, branches, or working tree state.",
|
|
68331
|
+
"Respond with STRICT JSON ONLY. Do not emit markdown formatting or conversational text outside the JSON object.",
|
|
68332
|
+
"",
|
|
68333
|
+
"JSON Schema:",
|
|
68334
|
+
"{",
|
|
68335
|
+
' "isGitQuery": boolean, // true if prompt is asking to inspect git status, diffs, log, commit history, branch, or working tree state. false if asking about task progress ("what is the status of the task"), conceptual questions or explanations ("how does git status work", "difference between checkout and switch"), building, coding, or unrelated topics.',
|
|
68336
|
+
' "asksStatus": boolean, // true if asking about working tree state, untracked/modified/staged files, or git status',
|
|
68337
|
+
' "asksDiff": boolean, // true if asking for working tree diffs or uncommitted changes (NOT a commit diff)',
|
|
68338
|
+
' "asksLog": boolean, // true if asking for commit history, recent commits, or git log',
|
|
68339
|
+
' "asksBranch": boolean, // true if asking to list branches or current branch',
|
|
68340
|
+
' "showTarget": string | null, // commit hash, ref, or "HEAD" if asking for diff/details of a specific commit (e.g. "diff of most recent commit" -> "HEAD")',
|
|
68341
|
+
' "targetRepo": string | null // repository name if an explicit sub-repository or sibling repo was mentioned, otherwise null',
|
|
68342
|
+
"}",
|
|
68343
|
+
"",
|
|
68344
|
+
"Examples:",
|
|
68345
|
+
'User: "Show me the diff of the most recent commit on this branch"',
|
|
68346
|
+
'{"isGitQuery":true,"asksStatus":false,"asksDiff":false,"asksLog":false,"asksBranch":false,"showTarget":"HEAD","targetRepo":null}',
|
|
68347
|
+
"",
|
|
68348
|
+
'User: "Are there any untracked or modified files in the working tree right now?"',
|
|
68349
|
+
'{"isGitQuery":true,"asksStatus":true,"asksDiff":false,"asksLog":false,"asksBranch":false,"showTarget":null,"targetRepo":null}',
|
|
68350
|
+
"",
|
|
68351
|
+
`User: "What's changed since my last commit?"`,
|
|
68352
|
+
'{"isGitQuery":true,"asksStatus":true,"asksDiff":true,"asksLog":false,"asksBranch":false,"showTarget":null,"targetRepo":null}',
|
|
68353
|
+
"",
|
|
68354
|
+
'User: "What is the status of the running task?"',
|
|
68355
|
+
'{"isGitQuery":false,"asksStatus":false,"asksDiff":false,"asksLog":false,"asksBranch":false,"showTarget":null,"targetRepo":null}',
|
|
68356
|
+
"",
|
|
68357
|
+
'User: "What\'s the difference between `git checkout` and `git switch`?"',
|
|
68358
|
+
'{"isGitQuery":false,"asksStatus":false,"asksDiff":false,"asksLog":false,"asksBranch":false,"showTarget":null,"targetRepo":null}',
|
|
68359
|
+
"",
|
|
68360
|
+
'User: "How does git status work?"',
|
|
68361
|
+
'{"isGitQuery":false,"asksStatus":false,"asksDiff":false,"asksLog":false,"asksBranch":false,"showTarget":null,"targetRepo":null}',
|
|
68362
|
+
"",
|
|
68363
|
+
'User: "What changed in React 19?"',
|
|
68364
|
+
'{"isGitQuery":false,"asksStatus":false,"asksDiff":false,"asksLog":false,"asksBranch":false,"showTarget":null,"targetRepo":null}',
|
|
68365
|
+
"",
|
|
68366
|
+
'User: "How do I get the current working directory in Python?"',
|
|
68367
|
+
'{"isGitQuery":false,"asksStatus":false,"asksDiff":false,"asksLog":false,"asksBranch":false,"showTarget":null,"targetRepo":null}',
|
|
68368
|
+
"",
|
|
68369
|
+
`User prompt: ${JSON.stringify(sanitized)}`
|
|
68370
|
+
].join(`
|
|
68371
|
+
`);
|
|
68372
|
+
}
|
|
68373
|
+
function parseGemmaGitStatusResponse(raw) {
|
|
68374
|
+
if (!raw || typeof raw != "string") return null;
|
|
68375
|
+
let cleaned = raw.trim();
|
|
68376
|
+
cleaned.startsWith("```") && (cleaned = cleaned.replace(/^```(?:json)?\s*\n?/i, "").replace(/\n?```\s*$/i, "").trim());
|
|
68377
|
+
let parsed;
|
|
68378
|
+
try {
|
|
68379
|
+
parsed = JSON.parse(cleaned);
|
|
68380
|
+
} catch {
|
|
68381
|
+
return null;
|
|
68382
|
+
}
|
|
68383
|
+
if (typeof parsed != "object" || parsed === null || Array.isArray(parsed) || typeof parsed.isGitQuery != "boolean" || typeof parsed.asksStatus != "boolean" || typeof parsed.asksDiff != "boolean" || typeof parsed.asksLog != "boolean" || typeof parsed.asksBranch != "boolean")
|
|
68384
|
+
return null;
|
|
68385
|
+
let isGitQuery = parsed.isGitQuery, asksStatus = parsed.asksStatus, asksDiff = parsed.asksDiff, asksLog = parsed.asksLog, asksBranch = parsed.asksBranch, showTarget = null;
|
|
68386
|
+
if (typeof parsed.showTarget == "string" && parsed.showTarget.trim()) {
|
|
68387
|
+
let candidateTarget = parsed.showTarget.trim();
|
|
68388
|
+
SAFE_REF_PATTERN.test(candidateTarget) && !candidateTarget.startsWith("-") && !candidateTarget.includes("..") && !candidateTarget.endsWith("^!") && !candidateTarget.endsWith("^@") && (showTarget = candidateTarget);
|
|
68389
|
+
}
|
|
68390
|
+
let targetRepo = null;
|
|
68391
|
+
if (typeof parsed.targetRepo == "string" && parsed.targetRepo.trim()) {
|
|
68392
|
+
let candidateRepo = parsed.targetRepo.trim();
|
|
68393
|
+
SAFE_REPO_NAME_PATTERN.test(candidateRepo) && candidateRepo !== "." && candidateRepo !== ".." && !candidateRepo.includes("/") && !candidateRepo.includes("\\") && (targetRepo = candidateRepo);
|
|
68394
|
+
}
|
|
68395
|
+
return {
|
|
68396
|
+
isGitQuery,
|
|
68397
|
+
asksStatus,
|
|
68398
|
+
asksDiff,
|
|
68399
|
+
asksLog,
|
|
68400
|
+
asksBranch,
|
|
68401
|
+
showTarget,
|
|
68402
|
+
targetRepo
|
|
68403
|
+
};
|
|
68404
|
+
}
|
|
68405
|
+
async function parseGitStatusQueryWithGemma(runner, prompt, timeoutMs = 12e3) {
|
|
68406
|
+
let startTime = Date.now(), boundedPrompt = prompt.slice(0, 2e3).trim(), promptText = renderLocalGemmaGitStatusQueryPrompt({ userPrompt: boundedPrompt }), abortController = new AbortController(), timer = null;
|
|
68407
|
+
try {
|
|
68408
|
+
let timeoutPromise = new Promise((_, reject) => {
|
|
68409
|
+
timer = setTimeout(() => {
|
|
68410
|
+
abortController.abort(), reject(new Error(`Gemma status query classification timed out after ${timeoutMs}ms`));
|
|
68411
|
+
}, timeoutMs), timer?.unref?.();
|
|
68412
|
+
}), advisoryPromise = runner.generateAdvisory(promptText, {
|
|
68413
|
+
responseFormat: "json",
|
|
68414
|
+
numPredict: 100,
|
|
68415
|
+
temperature: 0.1,
|
|
68416
|
+
timeoutMs,
|
|
68417
|
+
signal: abortController.signal
|
|
68418
|
+
}), raw = await Promise.race([advisoryPromise, timeoutPromise]);
|
|
68419
|
+
if (!raw || typeof raw != "string")
|
|
68420
|
+
return logger.warn("[git-status-summary] Gemma returned empty or non-string response", {
|
|
68421
|
+
prompt: boundedPrompt,
|
|
68422
|
+
durationMs: Date.now() - startTime
|
|
68423
|
+
}), null;
|
|
68424
|
+
let parsed = parseGemmaGitStatusResponse(raw);
|
|
68425
|
+
return parsed || (logger.warn("[git-status-summary] Gemma response failed schema validation", {
|
|
68426
|
+
prompt: boundedPrompt,
|
|
68427
|
+
raw,
|
|
68428
|
+
durationMs: Date.now() - startTime
|
|
68429
|
+
}), null);
|
|
68430
|
+
} catch (err) {
|
|
68431
|
+
let elapsed = Date.now() - startTime;
|
|
68432
|
+
return logger.warn("[git-status-summary] Gemma status query classification timed out or failed", {
|
|
68433
|
+
prompt: boundedPrompt,
|
|
68434
|
+
durationMs: elapsed,
|
|
68435
|
+
error: err?.message || String(err)
|
|
68436
|
+
}), null;
|
|
68437
|
+
} finally {
|
|
68438
|
+
timer && clearTimeout(timer);
|
|
68439
|
+
}
|
|
68440
|
+
}
|
|
68441
|
+
function parseGitStatusQuerySemantic(prompt) {
|
|
68442
|
+
let trimmed = prompt.trim();
|
|
68443
|
+
if (!trimmed)
|
|
68444
|
+
return {
|
|
68445
|
+
isGitQuery: !1,
|
|
68446
|
+
asksStatus: !1,
|
|
68447
|
+
asksDiff: !1,
|
|
68448
|
+
asksLog: !1,
|
|
68449
|
+
asksBranch: !1,
|
|
68450
|
+
showTarget: null,
|
|
68451
|
+
targetRepo: null
|
|
68452
|
+
};
|
|
68453
|
+
let isExplicitGit = /\b(?:git\s+(?:status|diff|log|branch|show|checkout|switch|restore)|commit\s+history|recent\s+commits)\b/i.test(trimmed);
|
|
68454
|
+
if (!(isExplicitGit || /\b(?:diff|status|log|branch|show|commits?|untracked|modified|working\s+tree|working\s+copy|working\s+directory)\b/i.test(trimmed)) && (/\b(?:task|agent|orchestrat(?:or|ion)|track|run|job|process|build|test|deploy|session)\s+status\b/i.test(trimmed) || /\bstatus\s+of\s+(?:the\s+)?(?:running\s+|active\s+)?(?:task|agent|orchestrat(?:or|ion)|track|run|job|process|team|build|suite)\b/i.test(trimmed) || /\b(?:how\s+many|what)\s+tasks?\s+(?:are\s+)?(?:running|active|pending)\b/i.test(trimmed) || /\b(?:what\s+did\s+)?(?:the\s+)?(?:last|previous|prior)\s+task\b/i.test(trimmed) || /\b(?:has\s+the|is\s+the)\s+(?:git\s+)?build\s+(?:finished|running|done|complete)\b/i.test(trimmed)))
|
|
68455
|
+
return {
|
|
68456
|
+
isGitQuery: !1,
|
|
68457
|
+
asksStatus: !1,
|
|
68458
|
+
asksDiff: !1,
|
|
68459
|
+
asksLog: !1,
|
|
68460
|
+
asksBranch: !1,
|
|
68461
|
+
showTarget: null,
|
|
68462
|
+
targetRepo: null
|
|
68463
|
+
};
|
|
68464
|
+
let isSinceLastCommit = /\b(?:what(?:'s|\s+is|\s+has)?\s+changed|changes?|diff)\s+(?:since|after)\s+(?:the\s+)?(?:most\s+recent|last|latest|current|head|my\s+last)\s+commit\b/i.test(trimmed.replace(/[\u2018\u2019]/g, "'")) || /\b(?:since|after)\s+(?:the\s+)?(?:most\s+recent|last|latest|current|head|my\s+last)\s+commit\b/i.test(trimmed.replace(/[\u2018\u2019]/g, "'")), asksCommitDiff = !isSinceLastCommit && COMMIT_DIFF_PATTERN.test(trimmed), showTarget = null;
|
|
68465
|
+
if (asksCommitDiff) {
|
|
68466
|
+
let commitHexMatch = /\b([0-9a-f]{7,40}(?:[~^][A-Za-z0-9_/@~^-]*)?)'s\s+diff\b/i.exec(trimmed) || /\bdiff\s+of\s+(?:commit\s+)?(?![^\s;,?]*\.\.[a-zA-Z0-9_/@~^-])([0-9a-f]{7,40}(?:[~^][A-Za-z0-9_/@~^-]*)?)(?![0-9a-zA-Z_/@~^-])/i.exec(trimmed);
|
|
68467
|
+
commitHexMatch && !commitHexMatch[1].includes("..") ? showTarget = stripSentencePunctuation(commitHexMatch[1]) : showTarget = extractBranchOrRefTarget(trimmed) ?? "HEAD";
|
|
68468
|
+
}
|
|
68469
|
+
let hasGitOrRepoContext = /\b(?:git|repo|repository)\b/i.test(trimmed), asksStatus = isSinceLastCommit || /\b(?:git\s+status)\b/i.test(trimmed) || /\b(?:status)\b/i.test(trimmed) && /\b(?:repo|repository|git|workspace|working\s+tree|working\s+copy)\b/i.test(trimmed) || /\b(?:dirty|untracked|modified|uncommitted|staged|unstaged)\s+(?:files|changes)\b/i.test(trimmed) || /\b(?:untracked\s+or\s+modified|modified\s+or\s+untracked)\s+(?:files|changes)?\b/i.test(trimmed) || /\b(?:did\s+i\s+leave\s+anything\s+uncommitted|any\s+uncommitted\s+(?:changes|files|work)|anything\s+uncommitted)\b/i.test(trimmed) || /\b(?:any\s+)?(?:dirty|untracked|modified)\s+files\b/i.test(trimmed) || /\bfiles\s+(?:are\s+)?(?:still\s+|currently\s+)?dirty\b/i.test(trimmed) || /\b(?:what|which)\s+files\s+(?:are\s+)?(?:still\s+|currently\s+)?dirty\b/i.test(trimmed) || /\b(?:repo|repository|workspace|working\s+(?:tree|copy))\s+(?:is\s+)?dirty\b/i.test(trimmed) || /\b(?:is\s+(?:my\s+)?)(?:repo|repository|workspace|working\s+(?:tree|copy))\s+dirty\b/i.test(trimmed) || /\b(?:new\s+files\s+)?not\s+tracked(?:\s+by\s+git)?\b/i.test(trimmed) || /\bworking\s+(?:tree|copy)\b/i.test(trimmed) || /\bworking\s+directory\b/i.test(trimmed) && hasGitOrRepoContext || /\bclean\s+working\s+(?:tree|copy)\b/i.test(trimmed) || /\bclean\s+working\s+directory\b/i.test(trimmed) && hasGitOrRepoContext || /\bis\s+(?:my\s+)?working\s+(?:tree|copy)\s+clean\b/i.test(trimmed) || /\bis\s+(?:my\s+)?working\s+directory\s+clean\b/i.test(trimmed) && hasGitOrRepoContext || /\b(?:which|what)\s+files\s+(?:have\s+i|did\s+i|are|were)?\s*(?:edited|modified|changed)\b/i.test(trimmed) || /\bwhat\s+(?:files\s+)?(?:did\s+i|have\s+been|are)\s+(?:changed|modified|edited)\b/i.test(trimmed) || /(?:git.*(?:狀態|status)|(?:工作區|工作副本|版本庫|暫存區).*(?:狀態|變更|修改)|工作目錄.*(?:狀態|變更|修改)|(?:未追蹤|未跟踪|未暫存|未暂存|已修改|有修改).*(?:檔案|文件)|(?:有沒有|有没有).*(?:未追蹤|未跟踪|未暫存|未暂存|已修改).*(?:檔案|文件)?|(?:程式碼|代碼).*(?:差異|變更))/i.test(trimmed) || /(?:mostra(?:mi)?|elenc(?:a|ami))\s+(?:tutti\s+)?(?:i\s+)?file\s+(?:non\s+tracciati|modificati)|(?:file\s+non\s+tracciati|file\s+modificati|stato\s+del\s+repository)/i.test(trimmed) || /(?:archivos?\s+(?:sin\s+seguimiento|modificados?)|unversionierte\s+dateien|fichiers?\s+(?:non\s+suivis?|modifi[eé]s?)|suivi\s+des\s+fichiers)/i.test(trimmed), comparisonBase = extractComparisonBaseRef(trimmed), asksDiff = !asksCommitDiff && (isSinceLastCommit || !!comparisonBase || /\bgit\s+diff\b/i.test(trimmed) || /\b(?:working\s+tree|working\s+copy|uncommitted|staged|unstaged)\s+diff\b/i.test(trimmed) || /\bdiff\s+against\s+(?:working\s+tree|head)\b/i.test(trimmed) || /\b(?:difference|diff)\s+between\s+my\s+working\s+(?:tree|copy)\s+and\s+([a-z0-9_./@~^-]+)\b/i.test(trimmed) || /^(?:please\s+)?(?:show|view|see)\s+(?:me\s+)?(?:the\s+|my\s+)?(?:diff|changes)(?:\s+since\s+(?:yesterday|today|monday|tuesday|wednesday|thursday|friday|saturday|sunday|(?:last|this)\s+\w+|\d+\s+\w+(?:\s+ago)?))?[\s.!?]*$/i.test(trimmed) || /\b(?:give|show|view|see|get|provide|display|print)\s+(?:me\s+)?(?:a\s+|the\s+|my\s+)?diff\b(?!\s+(?:of|between)\b|\s+(?:for\s+)?these\s+two\b)/i.test(trimmed) || /\b(?:show|view|see)\s+(?:the\s+)?(?:diff|changes)\s+(?:in\s+(?:the\s+|my\s+)?(?:working\s+(?:tree|copy)|repo|repository)|locally|uncommitted)\b/i.test(trimmed) || /\b(?:git|repo|working\s+(?:tree|copy)|uncommitted)\s+(?:changes?|diff)\s+(?:since|against)\b/i.test(trimmed)), asksLog = /\b(?:git\s+log|commit\s+history|recent\s+commits)\b/i.test(trimmed) || /\b(?:log\s+of\s+commits|history\s+of\s+commits|past\s+commits|list\s+commits)\b/i.test(trimmed) || /\b(?:most\s+recent|last|latest)\s+commits\b/i.test(trimmed), asksBranch = /\bgit\s+branch\b/i.test(trimmed) || /\b(?:what|which)\s+branch\s+(?:am\s+i|are\s+we)\s+(?:currently\s+|presently\s+|right\s+now\s+)?(?:on|working\s+on)\b/i.test(trimmed) || /\b(?:what|which)\s+branch\s+(?:is\s+(?:currently\s+|presently\s+)?checked\s+out|is\s+this)\b/i.test(trimmed) || /\bcurrent\s+branch\b/i.test(trimmed) || /\blist\s+(?:all\s+)?branches\b/i.test(trimmed), asksShow = !!showTarget || /\bgit\s+show\b/i.test(trimmed) || /\b(?:show|view|see|display|print|inspect|details\s+of)\s+(?:(?:me|us)\s+)?(?:commit\s+)?(?:HEAD|[0-9a-f]{7,40})(?:[~^][A-Za-z0-9_/@~^-]*)?(?![0-9a-zA-Z_/@~^-]|\.[0-9a-zA-Z_/@~^-])/i.test(trimmed);
|
|
68470
|
+
return {
|
|
68471
|
+
isGitQuery: !!(isExplicitGit || GIT_QUERY_PATTERN.test(trimmed) || asksStatus || asksDiff || asksLog || asksBranch || asksShow || asksCommitDiff),
|
|
68472
|
+
asksStatus,
|
|
68473
|
+
asksDiff,
|
|
68474
|
+
asksLog,
|
|
68475
|
+
asksBranch,
|
|
68476
|
+
showTarget,
|
|
68477
|
+
targetRepo: null
|
|
68478
|
+
};
|
|
68479
|
+
}
|
|
68480
|
+
async function resolveGitStatusIntent(options) {
|
|
68481
|
+
let { prompt, advisoryRunner } = options, trimmed = prompt.trim();
|
|
68482
|
+
if (!trimmed)
|
|
68483
|
+
return {
|
|
68484
|
+
isGitQuery: !1,
|
|
68485
|
+
asksStatus: !1,
|
|
68486
|
+
asksDiff: !1,
|
|
68487
|
+
asksLog: !1,
|
|
68488
|
+
asksBranch: !1,
|
|
68489
|
+
showTarget: null,
|
|
68490
|
+
targetRepo: null
|
|
68491
|
+
};
|
|
68492
|
+
if (isConceptualGitQuestion(trimmed))
|
|
68493
|
+
return {
|
|
68494
|
+
isGitQuery: !1,
|
|
68495
|
+
asksStatus: !1,
|
|
68496
|
+
asksDiff: !1,
|
|
68497
|
+
asksLog: !1,
|
|
68498
|
+
asksBranch: !1,
|
|
68499
|
+
showTarget: null,
|
|
68500
|
+
targetRepo: null
|
|
68501
|
+
};
|
|
68502
|
+
if (/^(?:[`'"]?(?:\/|!)?git\s+(?:status|diff|log|branch|show|checkout|switch|restore)\b)/i.test(trimmed))
|
|
68503
|
+
return parseGitStatusQuerySemantic(trimmed);
|
|
68504
|
+
let candidateRunner = resolvePreferredAdvisoryRunner(advisoryRunner);
|
|
68505
|
+
if (candidateRunner)
|
|
68506
|
+
try {
|
|
68507
|
+
let gemmaStart = Date.now(), gemmaIntent = await parseGitStatusQueryWithGemma(candidateRunner, trimmed), gemmaDurationMs = Date.now() - gemmaStart;
|
|
68508
|
+
if (gemmaIntent !== null) {
|
|
68509
|
+
if (gemmaIntent.targetRepo) {
|
|
68510
|
+
let repoCandidate = stripSentencePunctuation(gemmaIntent.targetRepo), candLower = repoCandidate.toLowerCase(), genericStopwords = /* @__PURE__ */ new Set([
|
|
68511
|
+
"work",
|
|
68512
|
+
"working",
|
|
68513
|
+
"tree",
|
|
68514
|
+
"directory",
|
|
68515
|
+
"copy",
|
|
68516
|
+
"repo",
|
|
68517
|
+
"repository",
|
|
68518
|
+
"git",
|
|
68519
|
+
"current",
|
|
68520
|
+
"active",
|
|
68521
|
+
"local",
|
|
68522
|
+
"here",
|
|
68523
|
+
"this",
|
|
68524
|
+
"diff",
|
|
68525
|
+
"status",
|
|
68526
|
+
"log",
|
|
68527
|
+
"branch",
|
|
68528
|
+
"show",
|
|
68529
|
+
"commit",
|
|
68530
|
+
"commits"
|
|
68531
|
+
]), isExplicitRepoSyntax = SAFE_REPO_NAME_PATTERN.test(repoCandidate) && !repoCandidate.includes(".."), designatedTokens = [], afterMatches = trimmed.matchAll(
|
|
68532
|
+
/\b(?:in|for|from|under|at|inside|to)\s+(?:the\s+)?(?:repo|repository|submodule|package|dir|directory|project)\s+["'`]?([A-Za-z0-9_.-]+)["'`]?/gi
|
|
68533
|
+
);
|
|
68534
|
+
for (let m of afterMatches) {
|
|
68535
|
+
let tok = stripSentencePunctuation(m[1]).toLowerCase();
|
|
68536
|
+
tok && designatedTokens.push(tok);
|
|
68537
|
+
}
|
|
68538
|
+
let beforeMatches = trimmed.matchAll(
|
|
68539
|
+
/(?<=^|[\s"'\`(\[{<])([A-Za-z0-9_.-]+)\s+(?:repo|repository|package|project|submodule)\b/gi
|
|
68540
|
+
);
|
|
68541
|
+
for (let m of beforeMatches) {
|
|
68542
|
+
let tok = stripSentencePunctuation(m[1]).toLowerCase();
|
|
68543
|
+
tok && designatedTokens.push(tok);
|
|
68544
|
+
}
|
|
68545
|
+
!designatedTokens.some(
|
|
68546
|
+
(token) => token === candLower && !genericStopwords.has(token)
|
|
68547
|
+
) || !isExplicitRepoSyntax || genericStopwords.has(candLower) ? gemmaIntent.targetRepo = null : gemmaIntent.targetRepo = repoCandidate;
|
|
68548
|
+
}
|
|
68549
|
+
return logger.info("[git-status-summary] Gemma status intent decision", {
|
|
68550
|
+
prompt: trimmed,
|
|
68551
|
+
runner: candidateRunner.runtimeLabel,
|
|
68552
|
+
providerKind: candidateRunner.providerKind,
|
|
68553
|
+
durationMs: gemmaDurationMs,
|
|
68554
|
+
intent: gemmaIntent
|
|
68555
|
+
}), gemmaIntent;
|
|
68556
|
+
} else
|
|
68557
|
+
logger.info("[git-status-summary] Gemma returned null or timed out, falling back to deterministic semantic parser", {
|
|
68558
|
+
prompt: trimmed
|
|
68559
|
+
});
|
|
68560
|
+
} catch (err) {
|
|
68561
|
+
logger.warn("[git-status-summary] Gemma status intent query failed, falling back to deterministic semantic parser", {
|
|
68562
|
+
prompt: trimmed,
|
|
68563
|
+
error: err?.message
|
|
68564
|
+
});
|
|
68565
|
+
}
|
|
68566
|
+
return parseGitStatusQuerySemantic(trimmed);
|
|
68567
|
+
}
|
|
68568
|
+
var IGNORED_TARGET_NAMES = /* @__PURE__ */ new Set([
|
|
67552
68569
|
"git",
|
|
67553
68570
|
"the",
|
|
67554
68571
|
"this",
|
|
@@ -67703,7 +68720,9 @@ var defaultExecFileAsync = (0, import_util3.promisify)(import_child_process5.exe
|
|
|
67703
68720
|
"very"
|
|
67704
68721
|
], STOPWORDS = new Set(FUNCTION_WORDS), NON_SHOW_TARGET_WORDS = new Set(FUNCTION_WORDS);
|
|
67705
68722
|
function extractCandidateRepos(prompt) {
|
|
67706
|
-
let candidates = [], seen = /* @__PURE__ */ new Set(), addCandidate = (
|
|
68723
|
+
let candidates = [], seen = /* @__PURE__ */ new Set(), addCandidate = (rawName, isExplicit) => {
|
|
68724
|
+
let name = stripSentencePunctuation(rawName);
|
|
68725
|
+
if (!name) return;
|
|
67707
68726
|
let lower = name.toLowerCase();
|
|
67708
68727
|
if (IGNORED_TARGET_NAMES.has(lower) || /^[0-9a-f]{7,40}$/i.test(name))
|
|
67709
68728
|
return;
|
|
@@ -67714,13 +68733,20 @@ function extractCandidateRepos(prompt) {
|
|
|
67714
68733
|
let existing = candidates.find((c) => c.name.toLowerCase() === lower);
|
|
67715
68734
|
existing && (existing.isExplicit = !0);
|
|
67716
68735
|
}
|
|
67717
|
-
}, trailingRepoRegex =
|
|
67718
|
-
for (; (match = trailingRepoRegex.exec(prompt)) !== null; )
|
|
67719
|
-
|
|
67720
|
-
|
|
67721
|
-
|
|
67722
|
-
|
|
67723
|
-
|
|
68736
|
+
}, trailingRepoRegex = /(?<=^|[\s"'\`(\[{<])([a-zA-Z0-9_.-]+)\s+(?:repo(?:sitory)?|project|package|submodule)\b/gi, match;
|
|
68737
|
+
for (; (match = trailingRepoRegex.exec(prompt)) !== null; ) {
|
|
68738
|
+
let raw = match[1], isStopword = STOPWORDS.has(raw.toLowerCase());
|
|
68739
|
+
addCandidate(raw, !isStopword);
|
|
68740
|
+
}
|
|
68741
|
+
let leadingRepoRegex = /\b(?:repo(?:sitory)?|project|package|submodule)\s+([a-zA-Z0-9_.-]+)/gi;
|
|
68742
|
+
for (; (match = leadingRepoRegex.exec(prompt)) !== null; ) {
|
|
68743
|
+
let raw = match[1];
|
|
68744
|
+
if (match[0].toLowerCase().startsWith("package") && raw.toLowerCase() === "lock")
|
|
68745
|
+
continue;
|
|
68746
|
+
let isStopword = STOPWORDS.has(raw.toLowerCase());
|
|
68747
|
+
addCandidate(raw, !isStopword);
|
|
68748
|
+
}
|
|
68749
|
+
let casualRegex = /\b(?:in|of|for)\s+(?:the\s+)?([a-zA-Z0-9_.-]+)/gi;
|
|
67724
68750
|
for (; (match = casualRegex.exec(prompt)) !== null; )
|
|
67725
68751
|
addCandidate(match[1], !1);
|
|
67726
68752
|
return candidates;
|
|
@@ -67736,8 +68762,11 @@ ${content}
|
|
|
67736
68762
|
${fence}`;
|
|
67737
68763
|
}
|
|
67738
68764
|
async function executeGitStatusSummary(options) {
|
|
67739
|
-
let { cwd, prompt, hasActiveTask, execFileFn = defaultExecFileAsync } = options;
|
|
67740
|
-
if (
|
|
68765
|
+
let { cwd, prompt, hasActiveTask, advisoryRunner, execFileFn = defaultExecFileAsync } = options;
|
|
68766
|
+
if (hasActiveTask)
|
|
68767
|
+
return null;
|
|
68768
|
+
let intent = await resolveGitStatusIntent({ prompt, advisoryRunner });
|
|
68769
|
+
if (!intent.isGitQuery)
|
|
67741
68770
|
return null;
|
|
67742
68771
|
let gitEnv = scrubSearchApiKeys({ ...process.env, LC_ALL: "C" }), defaultRepoName = sanitizeForTerminal(redactAbsoluteLocalPaths(path64.basename(cwd))), defaultRepoTopLevel = cwd;
|
|
67743
68772
|
try {
|
|
@@ -67749,8 +68778,18 @@ async function executeGitStatusSummary(options) {
|
|
|
67749
68778
|
trimmed && (defaultRepoTopLevel = trimmed, defaultRepoName = sanitizeForTerminal(redactAbsoluteLocalPaths(path64.basename(trimmed))));
|
|
67750
68779
|
} catch {
|
|
67751
68780
|
}
|
|
67752
|
-
let targetCwd = cwd, targetRepoName = defaultRepoName, notePrefix = "", candidates = extractCandidateRepos(prompt)
|
|
68781
|
+
let targetCwd = cwd, targetRepoName = defaultRepoName, notePrefix = "", candidates = extractCandidateRepos(prompt);
|
|
68782
|
+
if (intent.targetRepo) {
|
|
68783
|
+
let rawTarget = stripSentencePunctuation(intent.targetRepo);
|
|
68784
|
+
if (SAFE_REPO_NAME_PATTERN.test(rawTarget) && rawTarget !== "." && rawTarget !== ".." && !rawTarget.includes("/") && !rawTarget.includes("\\")) {
|
|
68785
|
+
let existingIndex = candidates.findIndex((c) => c.name.toLowerCase() === rawTarget.toLowerCase());
|
|
68786
|
+
existingIndex >= 0 && candidates.splice(existingIndex, 1), candidates.unshift({ name: rawTarget, isExplicit: !0 });
|
|
68787
|
+
}
|
|
68788
|
+
}
|
|
68789
|
+
let resolvedRepo = null;
|
|
67753
68790
|
for (let candidate of candidates) {
|
|
68791
|
+
if (!SAFE_REPO_NAME_PATTERN.test(candidate.name) || candidate.name === "." || candidate.name === ".." || candidate.name.includes("/") || candidate.name.includes("\\"))
|
|
68792
|
+
continue;
|
|
67754
68793
|
if (defaultRepoName.toLowerCase() === candidate.name.toLowerCase()) {
|
|
67755
68794
|
resolvedRepo = { cwd, name: defaultRepoName };
|
|
67756
68795
|
break;
|
|
@@ -67809,7 +68848,64 @@ async function executeGitStatusSummary(options) {
|
|
|
67809
68848
|
|
|
67810
68849
|
`), targetCwd = cwd, targetRepoName = defaultRepoName;
|
|
67811
68850
|
}
|
|
67812
|
-
let sections = [],
|
|
68851
|
+
let sections = [], isSinceLastCommit = /\b(?:what(?:'s|\s+is|\s+has)?\s+changed|changes?|diff)\s+(?:since|after)\s+(?:the\s+)?(?:most\s+recent|last|latest|current|head|my\s+last)\s+commit\b/i.test(prompt.replace(/[\u2018\u2019]/g, "'")) || /\b(?:since|after)\s+(?:the\s+)?(?:most\s+recent|last|latest|current|head|my\s+last)\s+commit\b/i.test(prompt.replace(/[\u2018\u2019]/g, "'")), comparisonBaseInfo = isSinceLastCommit ? void 0 : extractComparisonBaseRefInfo(prompt, { includeSpan: !0 });
|
|
68852
|
+
async function isValidGitComparisonRef(ref, targetCwd2, gitEnv2, execFileFn2) {
|
|
68853
|
+
if (ref.includes("..")) {
|
|
68854
|
+
let rangeParts = ref.includes("...") ? ref.split("...") : ref.split("..");
|
|
68855
|
+
if (rangeParts.length !== 2 || !rangeParts[0] && !rangeParts[1])
|
|
68856
|
+
return !1;
|
|
68857
|
+
for (let part of rangeParts) {
|
|
68858
|
+
let endpoint = part || "HEAD";
|
|
68859
|
+
if (!SAFE_REF_PATTERN.test(endpoint) || endpoint.startsWith("-"))
|
|
68860
|
+
return !1;
|
|
68861
|
+
try {
|
|
68862
|
+
await execFileFn2(
|
|
68863
|
+
"git",
|
|
68864
|
+
["--no-optional-locks", "rev-parse", "--verify", "--quiet", `${endpoint}^{commit}`],
|
|
68865
|
+
{ cwd: targetCwd2, env: gitEnv2, timeout: 3e3, encoding: "utf8" }
|
|
68866
|
+
);
|
|
68867
|
+
} catch {
|
|
68868
|
+
return !1;
|
|
68869
|
+
}
|
|
68870
|
+
}
|
|
68871
|
+
return !0;
|
|
68872
|
+
}
|
|
68873
|
+
if (!SAFE_REF_PATTERN.test(ref) || ref.startsWith("-"))
|
|
68874
|
+
return !1;
|
|
68875
|
+
try {
|
|
68876
|
+
return await execFileFn2(
|
|
68877
|
+
"git",
|
|
68878
|
+
["--no-optional-locks", "rev-parse", "--verify", "--quiet", `${ref}^{commit}`],
|
|
68879
|
+
{ cwd: targetCwd2, env: gitEnv2, timeout: 3e3, encoding: "utf8" }
|
|
68880
|
+
), !0;
|
|
68881
|
+
} catch {
|
|
68882
|
+
return !1;
|
|
68883
|
+
}
|
|
68884
|
+
}
|
|
68885
|
+
function occursOutsideComparisonSpan(prompt2, target, span, comparisonRef) {
|
|
68886
|
+
if (!span) {
|
|
68887
|
+
if (comparisonRef) {
|
|
68888
|
+
let lowerComp = comparisonRef.toLowerCase(), lowerTgt = target.toLowerCase();
|
|
68889
|
+
if (lowerComp === lowerTgt || lowerComp.includes(lowerTgt) || lowerTgt.includes(lowerComp))
|
|
68890
|
+
return !1;
|
|
68891
|
+
}
|
|
68892
|
+
return !0;
|
|
68893
|
+
}
|
|
68894
|
+
let lowerPrompt = prompt2.toLowerCase(), lowerTarget = target.toLowerCase(), idx = lowerPrompt.indexOf(lowerTarget);
|
|
68895
|
+
if (idx === -1)
|
|
68896
|
+
return !0;
|
|
68897
|
+
for (; idx !== -1; ) {
|
|
68898
|
+
if (idx + lowerTarget.length <= span.start || idx >= span.end)
|
|
68899
|
+
return !0;
|
|
68900
|
+
idx = lowerPrompt.indexOf(lowerTarget, idx + 1);
|
|
68901
|
+
}
|
|
68902
|
+
return !1;
|
|
68903
|
+
}
|
|
68904
|
+
if (comparisonBaseInfo && !comparisonBaseInfo.isExplicit) {
|
|
68905
|
+
let candidateRef = comparisonBaseInfo.ref;
|
|
68906
|
+
await isValidGitComparisonRef(candidateRef, targetCwd, gitEnv, execFileFn) || (comparisonBaseInfo = void 0);
|
|
68907
|
+
}
|
|
68908
|
+
let promptForShowDetection = comparisonBaseInfo?.span ? prompt.slice(0, comparisonBaseInfo.span.start) + " ".repeat(comparisonBaseInfo.span.end - comparisonBaseInfo.span.start) + prompt.slice(comparisonBaseInfo.span.end) : prompt, isExplicitCommitShowRequest = /\bgit\s+show\b/i.test(promptForShowDetection) || /\b(?:show|view|display|details\s+of|print|inspect)\s+(?:(?:me|us)\s+)?(?:what\s+changed\s+in\s+)?(?:(?:the|my)\s+)?(?:most\s+recent|last|latest|recent|current)\s+commit(?:'s)?(?:\s+(?:diff|details))?\b/i.test(promptForShowDetection) || /\b(?:(?:show|view|see|display|print|inspect|details\s+of|what\s+changed\s+in)\s+(?:(?:me|us)\s+)?(?:(?:the\s+)?diff\s+of\s+(?:commit\s+)?|(?:details\s+of|commit)\s+)?|(?:the\s+)?diff\s+of\s+(?:commit\s+)?)([`'"])((?:HEAD|[0-9a-f]{7,40})(?:[~^][A-Za-z0-9_/@~^-]*)?)\1/i.test(promptForShowDetection) || /\b(?:(?:show|view|see|display|print|inspect|details\s+of|what\s+changed\s+in)\s+(?:(?:me|us)\s+)?(?:(?:the\s+)?diff\s+of\s+(?:commit\s+)?|(?:details\s+of|commit)\s+)?|(?:the\s+)?diff\s+of\s+(?:commit\s+)?)(?![^\s;,?]*\.{2,3}[a-zA-Z0-9_/@~^-])(?:HEAD|[0-9a-f]{7,40})(?:[~^][A-Za-z0-9_/@~^-]*)?(?![0-9a-zA-Z_/@~^-]|\.[0-9a-zA-Z_/@~^-])/i.test(promptForShowDetection) || /(?:^\s*|\b(?:and|also)\s+)commit\s+((?:HEAD|[0-9a-f]{7,40})(?:[~^][A-Za-z0-9_/@~^-]*)?)(?![0-9a-zA-Z_/@~^-]|\.[0-9a-zA-Z_/@~^-])/i.test(promptForShowDetection) || /\b[0-9a-f]{7,40}(?:[~^][A-Za-z0-9_/@~^-]*)?'s\s+diff\b/i.test(promptForShowDetection), isExplicitGitShow = isExplicitCommitShowRequest, hasStrongComparison = !!(comparisonBaseInfo && (comparisonBaseInfo.isExplicit || hasRefSyntax(comparisonBaseInfo.ref))), hasComparison = !!(isSinceLastCommit || comparisonBaseInfo), isCommitDiff = !isSinceLastCommit && !hasComparison && (COMMIT_DIFF_PATTERN.test(prompt) || !intent.asksDiff && !!intent.showTarget) || !isSinceLastCommit && !hasComparison && !intent.asksDiff && !!intent.showTarget, asksDiff = isSinceLastCommit || hasStrongComparison || !!comparisonBaseInfo && !isCommitDiff || intent.asksDiff && !isCommitDiff, hasExplicitBranchListRequest = /\b(?:list|show|view|see|display|all|other)\s+branches\b/i.test(prompt) || /\b(?:and|also)\s+(?:list\s+)?branches\b/i.test(prompt) || /\bgit\s+branch\b/i.test(prompt) || /\b(?:which|what)\s+branch\s+(?:am\s+i|is\s+this)\b/i.test(prompt), asksBranch = isSinceLastCommit ? !1 : isCommitDiff ? !!(hasExplicitBranchListRequest && intent.asksBranch) : intent.asksBranch, asksLog = isSinceLastCommit ? !1 : intent.asksLog, asksStatus = isSinceLastCommit || intent.asksStatus, asksShow = isExplicitCommitShowRequest || !isSinceLastCommit && !hasComparison && isCommitDiff, showTarget = null, openerMatch = /\bgit\s+show\b\s*([`'"“‘«‹「『(\[(《【])/iu.exec(prompt);
|
|
67813
68909
|
if (openerMatch) {
|
|
67814
68910
|
let opener = openerMatch[1], pairRegex = null;
|
|
67815
68911
|
switch (opener) {
|
|
@@ -67881,9 +68977,34 @@ async function executeGitStatusSummary(options) {
|
|
|
67881
68977
|
}
|
|
67882
68978
|
}
|
|
67883
68979
|
}
|
|
67884
|
-
if (!
|
|
67885
|
-
|
|
67886
|
-
|
|
68980
|
+
if (!isExplicitCommitShowRequest && hasComparison)
|
|
68981
|
+
showTarget = null;
|
|
68982
|
+
else if (!showTarget) {
|
|
68983
|
+
let showCommitMatch = /\b(?:(?:show|view|see|display|print|inspect|details\s+of|what\s+changed\s+in)\s+(?:(?:me|us)\s+)?(?:(?:the\s+)?diff\s+of\s+(?:commit\s+)?|(?:details\s+of|commit)\s+)?|(?:the\s+)?diff\s+of\s+(?:commit\s+)?)([`'"])((?:HEAD|[0-9a-f]{7,40})(?:[~^][A-Za-z0-9_/@~^-]*)?)\1/i.exec(promptForShowDetection) || /\b(?:show|view|display|details\s+of|print)\s+(?:(?:me|us)\s+)?(?:commit\s+)?([`'"])((?:HEAD|[0-9a-f]{7,40})(?:[~^][A-Za-z0-9_/@~^-]*)?)\1/i.exec(promptForShowDetection) || /\b([0-9a-f]{7,40}(?:[~^][A-Za-z0-9_/@~^-]*)?)'s\s+diff\b/i.exec(promptForShowDetection) || /\b(?:(?:show|view|see|display|print|inspect|details\s+of|what\s+changed\s+in)\s+(?:(?:me|us)\s+)?(?:(?:the\s+)?diff\s+of\s+(?:commit\s+)?|(?:details\s+of|commit)\s+)?|(?:the\s+)?diff\s+of\s+(?:commit\s+)?)(?![^\s;,?]*\.{2,3}[a-zA-Z0-9_/@~^-])((?:HEAD|[0-9a-f]{7,40})(?:[~^][A-Za-z0-9_/@~^-]*)?)(?![0-9a-zA-Z_/@~^-]|\.[0-9a-zA-Z_/@~^-])/i.exec(promptForShowDetection) || /(?:^\s*|\b(?:and|also)\s+)commit\s+((?:HEAD|[0-9a-f]{7,40})(?:[~^][A-Za-z0-9_/@~^-]*)?)(?![0-9a-zA-Z_/@~^-]|\.[0-9a-zA-Z_/@~^-])/i.exec(promptForShowDetection) || /\b(?:show|view|display|details\s+of|print)\s+(?:(?:me|us)\s+)?(?:commit\s+)?(?![^\s;,?]*\.\.[a-zA-Z0-9_/@~^-])([0-9a-f]{7,40}(?:[~^][A-Za-z0-9_/@~^-]*)?)(?![0-9a-zA-Z_/@~^-]|\.[0-9a-zA-Z_/@~^-])/i.exec(promptForShowDetection), targetRef = showCommitMatch ? showCommitMatch[2] ?? showCommitMatch[1] : null;
|
|
68984
|
+
if (showCommitMatch && targetRef && occursOutsideComparisonSpan(prompt, targetRef, comparisonBaseInfo?.span, comparisonBaseInfo?.ref))
|
|
68985
|
+
showTarget = stripSentencePunctuation(targetRef);
|
|
68986
|
+
else if (asksShow && intent.showTarget && occursOutsideComparisonSpan(prompt, intent.showTarget, comparisonBaseInfo?.span, comparisonBaseInfo?.ref))
|
|
68987
|
+
showTarget = intent.showTarget;
|
|
68988
|
+
else {
|
|
68989
|
+
let nonComparisonHash = null;
|
|
68990
|
+
for (let m of promptForShowDetection.matchAll(/\b(?![^\s;,?]*\.\.[a-zA-Z0-9_/@~^-])([0-9a-f]{7,40}(?:[~^][A-Za-z0-9_/@~^-]*)?)(?![0-9a-zA-Z_/@~^-]|\.\.[a-zA-Z0-9_/@~^-])/gi)) {
|
|
68991
|
+
let matchIndex = m.index, matchEnd = matchIndex + m[0].length;
|
|
68992
|
+
if (comparisonBaseInfo?.span) {
|
|
68993
|
+
if (!(matchEnd <= comparisonBaseInfo.span.start || matchIndex >= comparisonBaseInfo.span.end))
|
|
68994
|
+
continue;
|
|
68995
|
+
} else if (comparisonBaseInfo?.ref) {
|
|
68996
|
+
let compRef = comparisonBaseInfo.ref.toLowerCase(), cand = m[1].toLowerCase();
|
|
68997
|
+
if (compRef === cand || compRef.includes(cand) || cand.includes(compRef))
|
|
68998
|
+
continue;
|
|
68999
|
+
}
|
|
69000
|
+
let candidate = stripSentencePunctuation(m[1]);
|
|
69001
|
+
if (!candidate.includes("..")) {
|
|
69002
|
+
nonComparisonHash = candidate;
|
|
69003
|
+
break;
|
|
69004
|
+
}
|
|
69005
|
+
}
|
|
69006
|
+
nonComparisonHash ? showTarget = nonComparisonHash : asksShow && (showTarget = "HEAD");
|
|
69007
|
+
}
|
|
67887
69008
|
}
|
|
67888
69009
|
let includeStatus = asksStatus || !asksDiff && !asksBranch && !asksShow, includeLog = asksLog || !asksDiff && !asksBranch && !asksShow;
|
|
67889
69010
|
try {
|
|
@@ -67920,24 +69041,27 @@ ${formatFencedCodeBlock(statusContent, "text")}`);
|
|
|
67920
69041
|
${formatFencedCodeBlock(logContent, "text")}`);
|
|
67921
69042
|
}
|
|
67922
69043
|
if (asksDiff) {
|
|
67923
|
-
let diffContent = "No working tree changes";
|
|
67924
|
-
|
|
67925
|
-
|
|
67926
|
-
|
|
67927
|
-
|
|
67928
|
-
{
|
|
67929
|
-
|
|
67930
|
-
|
|
67931
|
-
|
|
67932
|
-
|
|
69044
|
+
let comparisonBase = comparisonBaseInfo?.ref, isExplicitComparison = !!comparisonBaseInfo?.isExplicit, isStaged = !isSinceLastCommit && isStagedDiffIntent(prompt), diffTitle = isStaged ? `### Git Staged Diff (${targetRepoName})` : `### Git Diff (${targetRepoName})`, diffContent = isStaged ? "No staged changes" : isSinceLastCommit || comparisonBase === "HEAD" ? "No changes since last commit" : comparisonBase ? `No differences against ${comparisonBase}` : "No working tree changes";
|
|
69045
|
+
comparisonBase && comparisonBase !== "HEAD" && (await isValidGitComparisonRef(comparisonBase, targetCwd, gitEnv, execFileFn) || (isExplicitComparison ? diffContent = `Commit or reference "${comparisonBase}" was not found` : (comparisonBase = void 0, diffContent = isStaged ? "No staged changes" : "No working tree changes")));
|
|
69046
|
+
let diffArgs = isSinceLastCommit || !isStaged && comparisonBase === "HEAD" ? ["--no-optional-locks", "-c", "color.ui=never", "diff", "--stat", "--end-of-options", "HEAD", "--"] : isStaged && comparisonBase ? ["--no-optional-locks", "-c", "color.ui=never", "diff", "--cached", "--stat", "--end-of-options", comparisonBase, "--"] : isStaged ? ["--no-optional-locks", "-c", "color.ui=never", "diff", "--cached", "--stat"] : comparisonBase ? ["--no-optional-locks", "-c", "color.ui=never", "diff", "--stat", "--end-of-options", comparisonBase, "--"] : ["--no-optional-locks", "-c", "color.ui=never", "diff", "--stat"];
|
|
69047
|
+
if (!diffContent.startsWith("Commit or reference"))
|
|
69048
|
+
try {
|
|
69049
|
+
let { stdout: gitDiff } = await execFileFn(
|
|
69050
|
+
"git",
|
|
69051
|
+
diffArgs,
|
|
69052
|
+
{ cwd: targetCwd, env: gitEnv, timeout: 3e3, encoding: "utf8" }
|
|
69053
|
+
), diffLines = gitDiff.split(/\r?\n/).map((l) => l.trimEnd()).filter((l) => l.length > 0);
|
|
69054
|
+
if (diffLines.length > 0) {
|
|
69055
|
+
let capped = diffLines.slice(0, 20), rem = diffLines.length - 20;
|
|
69056
|
+
diffContent = rem > 0 ? `${capped.join(`
|
|
67933
69057
|
`)}
|
|
67934
69058
|
...and ${rem} more` : capped.join(`
|
|
67935
69059
|
`);
|
|
69060
|
+
}
|
|
69061
|
+
} catch {
|
|
69062
|
+
diffContent = isStaged ? "Staged diff is unavailable" : "Diff is unavailable";
|
|
67936
69063
|
}
|
|
67937
|
-
|
|
67938
|
-
diffContent = "Diff is unavailable";
|
|
67939
|
-
}
|
|
67940
|
-
diffContent = sanitizeForTerminal(redactAbsoluteLocalPaths(diffContent)), sections.push(`### Git Diff (${targetRepoName})
|
|
69064
|
+
diffContent = sanitizeForTerminal(redactAbsoluteLocalPaths(diffContent)), sections.push(`${diffTitle}
|
|
67941
69065
|
${formatFencedCodeBlock(diffContent, "text")}`);
|
|
67942
69066
|
}
|
|
67943
69067
|
if (asksBranch) {
|
|
@@ -67948,15 +69072,19 @@ ${formatFencedCodeBlock(diffContent, "text")}`);
|
|
|
67948
69072
|
["--no-optional-locks", "-c", "color.ui=never", "branch", "--list"],
|
|
67949
69073
|
{ cwd: targetCwd, env: gitEnv, timeout: 3e3, encoding: "utf8" }
|
|
67950
69074
|
), branchLines = gitBranch.split(/\r?\n/).map((l) => l.trimEnd()).filter((l) => l.length > 0);
|
|
67951
|
-
branchLines.length > 0
|
|
67952
|
-
|
|
69075
|
+
if (branchLines.length > 0) {
|
|
69076
|
+
let currentBranchLine = branchLines.find((l) => l.startsWith("* ")), cappedOthers = branchLines.filter((l) => !l.startsWith("* ")).slice(0, currentBranchLine ? 9 : 10);
|
|
69077
|
+
branchContent = (currentBranchLine ? [currentBranchLine, ...cappedOthers] : cappedOthers).join(`
|
|
69078
|
+
`);
|
|
69079
|
+
}
|
|
67953
69080
|
} catch {
|
|
67954
69081
|
branchContent = "Branch listing is unavailable";
|
|
67955
69082
|
}
|
|
67956
69083
|
branchContent = sanitizeForTerminal(redactAbsoluteLocalPaths(branchContent)), sections.push(`### Git Branches (${targetRepoName})
|
|
67957
69084
|
${formatFencedCodeBlock(branchContent, "text")}`);
|
|
67958
69085
|
}
|
|
67959
|
-
if (showTarget) {
|
|
69086
|
+
if (!isSinceLastCommit && showTarget) {
|
|
69087
|
+
(showTarget.startsWith("-") || showTarget.includes("\0")) && (showTarget = "HEAD");
|
|
67960
69088
|
let isHexHash = /^[0-9a-f]{7,40}$/i.test(showTarget), safeTarget = sanitizeForTerminal(redactAbsoluteLocalPaths(showTarget)), title = isHexHash ? `Commit ${safeTarget}` : `Git Show ${safeTarget}`;
|
|
67961
69089
|
try {
|
|
67962
69090
|
let gitShowRef = showTarget.endsWith("^!") || showTarget.endsWith("^@") ? showTarget : `${showTarget}^{commit}`, { stdout: showOut } = await execFileFn(
|
|
@@ -71053,7 +72181,7 @@ async function runOrchestrationShell(args) {
|
|
|
71053
72181
|
let isSlash = isShellSlashCommand(text2), browseController = null;
|
|
71054
72182
|
isSlash || (browseController = new AbortController(), activeBrowseAbortController = browseController);
|
|
71055
72183
|
try {
|
|
71056
|
-
await handleShellUserInput({
|
|
72184
|
+
logger.info("[orchestration-shell] Turn started", { prompt: text2 }), await handleShellUserInput({
|
|
71057
72185
|
text: text2,
|
|
71058
72186
|
store,
|
|
71059
72187
|
args,
|
|
@@ -71087,7 +72215,7 @@ async function runOrchestrationShell(args) {
|
|
|
71087
72215
|
// concurrent slash bypass can't leak its advisory into this mirror
|
|
71088
72216
|
// and vice-versa.
|
|
71089
72217
|
ownEntries
|
|
71090
|
-
});
|
|
72218
|
+
}), logger.info("[orchestration-shell] Turn completed", { prompt: text2 });
|
|
71091
72219
|
});
|
|
71092
72220
|
}
|
|
71093
72221
|
), handleUserInput = (text2, images, options) => {
|
|
@@ -75595,6 +76723,10 @@ async function handleShellUserInput(deps) {
|
|
|
75595
76723
|
if (decision = await dispatchClassify({
|
|
75596
76724
|
...plannerInput,
|
|
75597
76725
|
prompt: classifyPrompt
|
|
76726
|
+
}), logger.info("[orchestration-shell] Planner classified input", {
|
|
76727
|
+
prompt: plannerInput.prompt,
|
|
76728
|
+
action: decision.action,
|
|
76729
|
+
rationale: decision.rationale
|
|
75598
76730
|
}), isLocalPlannerRuntime(args) && decision.action === "browse" && hasFileMutationIntent(plannerInput.prompt) && (decision = {
|
|
75599
76731
|
action: "start_task",
|
|
75600
76732
|
rationale: decision.rationale ? `${decision.rationale} (promoted to start_task due to file mutation intent)` : "web request with file mutation intent"
|
|
@@ -75771,6 +76903,27 @@ async function handleShellUserInput(deps) {
|
|
|
75771
76903
|
return;
|
|
75772
76904
|
}
|
|
75773
76905
|
if (isTextAdvisory) {
|
|
76906
|
+
let hasRunningSingle = store.getState().runningTasks.size > 0, team = store.getState().team, teamActive = team !== null && !team.groupResolved && team.haltReason === null, hasActiveTask = hasRunningSingle || teamActive;
|
|
76907
|
+
if (!isConceptualGitQuestion(dispatchText)) {
|
|
76908
|
+
let gitResponse = await executeGitStatusSummary({
|
|
76909
|
+
cwd: args.cwd || process.cwd(),
|
|
76910
|
+
prompt: dispatchText,
|
|
76911
|
+
hasActiveTask,
|
|
76912
|
+
advisoryRunner: args.localAdvisoryRunner,
|
|
76913
|
+
execFileFn: execFileAsync
|
|
76914
|
+
});
|
|
76915
|
+
if (gitResponse !== null) {
|
|
76916
|
+
logger.info("[orchestration-shell] Dispatched SHELL_ADVISORY for git status", {
|
|
76917
|
+
prompt: dispatchText,
|
|
76918
|
+
responseLength: gitResponse.length
|
|
76919
|
+
}), store.dispatch({
|
|
76920
|
+
type: "SHELL_ADVISORY",
|
|
76921
|
+
source: "shell",
|
|
76922
|
+
text: gitResponse
|
|
76923
|
+
});
|
|
76924
|
+
return;
|
|
76925
|
+
}
|
|
76926
|
+
}
|
|
75774
76927
|
await routeAdvisory({
|
|
75775
76928
|
store,
|
|
75776
76929
|
args,
|
|
@@ -75946,6 +77099,7 @@ async function handleShellUserInput(deps) {
|
|
|
75946
77099
|
cwd: args.cwd || process.cwd(),
|
|
75947
77100
|
prompt: plannerInput.prompt,
|
|
75948
77101
|
hasActiveTask,
|
|
77102
|
+
advisoryRunner: args.localAdvisoryRunner,
|
|
75949
77103
|
execFileFn: execFileAsync
|
|
75950
77104
|
});
|
|
75951
77105
|
if (gitResponse !== null) {
|
|
@@ -76869,7 +78023,7 @@ var import_node_fs28 = require("node:fs"), path69 = __toESM(require("node:path")
|
|
|
76869
78023
|
this.signatureCache = /* @__PURE__ */ new Map();
|
|
76870
78024
|
this.hydrated = /* @__PURE__ */ new Set();
|
|
76871
78025
|
this.mutex = new AsyncMutex();
|
|
76872
|
-
this.cacheRoot = cacheRoot ?? path69.join(os39.homedir(), ".codevibe", "cache");
|
|
78026
|
+
this.cacheRoot = cacheRoot ?? process.env.CODEVIBE_CACHE_ROOT ?? path69.join(os39.homedir(), ".codevibe", "cache");
|
|
76873
78027
|
}
|
|
76874
78028
|
async getWorkflowClassification(userId, prompt) {
|
|
76875
78029
|
await this.hydrateWorkflowIfNeeded(userId);
|
|
@@ -77485,15 +78639,40 @@ var HostedGemmaAdvisoryRunner = class {
|
|
|
77485
78639
|
}
|
|
77486
78640
|
encryptedImages = options.images.map((img) => this.deps.crypto.encryptString(img, sessionKey));
|
|
77487
78641
|
}
|
|
78642
|
+
if (options?.signal?.aborted) {
|
|
78643
|
+
let err = new Error("Hosted Gemma generation aborted by signal");
|
|
78644
|
+
throw err.name = "AbortError", err;
|
|
78645
|
+
}
|
|
77488
78646
|
let maxTokens = options?.numPredict, temperature = options?.temperature, start = Date.now();
|
|
77489
78647
|
try {
|
|
77490
|
-
let
|
|
78648
|
+
let promises2 = [this.deps.transport.generatePlannerAdvisory({
|
|
77491
78649
|
sessionId,
|
|
77492
78650
|
prompt: encryptedPrompt,
|
|
77493
78651
|
...encryptedImages && encryptedImages.length > 0 ? { images: encryptedImages } : {},
|
|
77494
78652
|
...maxTokens !== void 0 ? { maxTokens } : {},
|
|
77495
78653
|
...temperature !== void 0 ? { temperature } : {}
|
|
77496
|
-
});
|
|
78654
|
+
})], timer, abortHandler;
|
|
78655
|
+
options?.timeoutMs && options.timeoutMs > 0 && promises2.push(
|
|
78656
|
+
new Promise((_, reject) => {
|
|
78657
|
+
timer = setTimeout(() => {
|
|
78658
|
+
let err = new Error(`Hosted Gemma advisory generation timed out after ${options.timeoutMs}ms`);
|
|
78659
|
+
err.name = "TimeoutError", reject(err);
|
|
78660
|
+
}, options.timeoutMs);
|
|
78661
|
+
})
|
|
78662
|
+
), options?.signal && promises2.push(
|
|
78663
|
+
new Promise((_, reject) => {
|
|
78664
|
+
abortHandler = () => {
|
|
78665
|
+
let err = new Error("Hosted Gemma generation aborted by signal");
|
|
78666
|
+
err.name = "AbortError", reject(err);
|
|
78667
|
+
}, options.signal.addEventListener("abort", abortHandler, { once: !0 });
|
|
78668
|
+
})
|
|
78669
|
+
);
|
|
78670
|
+
let response;
|
|
78671
|
+
try {
|
|
78672
|
+
response = await Promise.race(promises2);
|
|
78673
|
+
} finally {
|
|
78674
|
+
timer && clearTimeout(timer), abortHandler && options?.signal && options.signal.removeEventListener("abort", abortHandler);
|
|
78675
|
+
}
|
|
77497
78676
|
return this.deps.crypto.decryptString(response.advisoryText, sessionKey);
|
|
77498
78677
|
} catch (err) {
|
|
77499
78678
|
let elapsedMs = Date.now() - start;
|
|
@@ -81452,6 +82631,7 @@ function enforceStrictJsonStdout(raw) {
|
|
|
81452
82631
|
var LocalGemmaProcessRunner = class {
|
|
81453
82632
|
constructor(config) {
|
|
81454
82633
|
this.config = config;
|
|
82634
|
+
this.providerKind = "local";
|
|
81455
82635
|
this.runtimeLabel = `local-gemma-process:${import_path4.default.basename(config.command)}`;
|
|
81456
82636
|
}
|
|
81457
82637
|
async classify(promptText) {
|