@quantiya/codevibe-codex-plugin 2.0.61 → 2.0.62
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 +1219 -43
- 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,1007 @@ 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
|
+
if (!!runner?.opts) {
|
|
68320
|
+
let localCandidate = runner?.opts?.localRunner ?? runner?.localRunner ?? null;
|
|
68321
|
+
return localCandidate && isQualifiedAdvisoryRunner(localCandidate) ? localCandidate : null;
|
|
68322
|
+
}
|
|
68323
|
+
return (runner.providerKind === "local" || !runner.providerKind && (runner.runtimeLabel?.startsWith("local-gemma-ollama:") || runner.runtimeLabel?.startsWith("local-gemma-process:"))) && isQualifiedAdvisoryRunner(runner) ? runner : null;
|
|
68324
|
+
}
|
|
68325
|
+
function renderLocalGemmaGitStatusQueryPrompt(args) {
|
|
68326
|
+
let sanitized = sanitizeForTerminal(redactAbsoluteLocalPaths(args.userPrompt)).trim();
|
|
68327
|
+
return [
|
|
68328
|
+
"You are a semantic Git query analyzer for CodeVibe.",
|
|
68329
|
+
"Classify the user prompt to determine if they are asking about Git repository status, diffs, commits, history, branches, or working tree state.",
|
|
68330
|
+
"Respond with STRICT JSON ONLY. Do not emit markdown formatting or conversational text outside the JSON object.",
|
|
68331
|
+
"",
|
|
68332
|
+
"JSON Schema:",
|
|
68333
|
+
"{",
|
|
68334
|
+
' "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.',
|
|
68335
|
+
' "asksStatus": boolean, // true if asking about working tree state, untracked/modified/staged files, or git status',
|
|
68336
|
+
' "asksDiff": boolean, // true if asking for working tree diffs or uncommitted changes (NOT a commit diff)',
|
|
68337
|
+
' "asksLog": boolean, // true if asking for commit history, recent commits, or git log',
|
|
68338
|
+
' "asksBranch": boolean, // true if asking to list branches or current branch',
|
|
68339
|
+
' "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")',
|
|
68340
|
+
' "targetRepo": string | null // repository name if an explicit sub-repository or sibling repo was mentioned, otherwise null',
|
|
68341
|
+
"}",
|
|
68342
|
+
"",
|
|
68343
|
+
"Examples:",
|
|
68344
|
+
'User: "Show me the diff of the most recent commit on this branch"',
|
|
68345
|
+
'{"isGitQuery":true,"asksStatus":false,"asksDiff":false,"asksLog":false,"asksBranch":false,"showTarget":"HEAD","targetRepo":null}',
|
|
68346
|
+
"",
|
|
68347
|
+
'User: "Are there any untracked or modified files in the working tree right now?"',
|
|
68348
|
+
'{"isGitQuery":true,"asksStatus":true,"asksDiff":false,"asksLog":false,"asksBranch":false,"showTarget":null,"targetRepo":null}',
|
|
68349
|
+
"",
|
|
68350
|
+
`User: "What's changed since my last commit?"`,
|
|
68351
|
+
'{"isGitQuery":true,"asksStatus":true,"asksDiff":true,"asksLog":false,"asksBranch":false,"showTarget":null,"targetRepo":null}',
|
|
68352
|
+
"",
|
|
68353
|
+
'User: "What is the status of the running task?"',
|
|
68354
|
+
'{"isGitQuery":false,"asksStatus":false,"asksDiff":false,"asksLog":false,"asksBranch":false,"showTarget":null,"targetRepo":null}',
|
|
68355
|
+
"",
|
|
68356
|
+
'User: "What\'s the difference between `git checkout` and `git switch`?"',
|
|
68357
|
+
'{"isGitQuery":false,"asksStatus":false,"asksDiff":false,"asksLog":false,"asksBranch":false,"showTarget":null,"targetRepo":null}',
|
|
68358
|
+
"",
|
|
68359
|
+
'User: "How does git status work?"',
|
|
68360
|
+
'{"isGitQuery":false,"asksStatus":false,"asksDiff":false,"asksLog":false,"asksBranch":false,"showTarget":null,"targetRepo":null}',
|
|
68361
|
+
"",
|
|
68362
|
+
'User: "What changed in React 19?"',
|
|
68363
|
+
'{"isGitQuery":false,"asksStatus":false,"asksDiff":false,"asksLog":false,"asksBranch":false,"showTarget":null,"targetRepo":null}',
|
|
68364
|
+
"",
|
|
68365
|
+
'User: "How do I get the current working directory in Python?"',
|
|
68366
|
+
'{"isGitQuery":false,"asksStatus":false,"asksDiff":false,"asksLog":false,"asksBranch":false,"showTarget":null,"targetRepo":null}',
|
|
68367
|
+
"",
|
|
68368
|
+
`User prompt: ${JSON.stringify(sanitized)}`
|
|
68369
|
+
].join(`
|
|
68370
|
+
`);
|
|
68371
|
+
}
|
|
68372
|
+
function parseGemmaGitStatusResponse(raw) {
|
|
68373
|
+
if (!raw || typeof raw != "string") return null;
|
|
68374
|
+
let cleaned = raw.trim();
|
|
68375
|
+
cleaned.startsWith("```") && (cleaned = cleaned.replace(/^```(?:json)?\s*\n?/i, "").replace(/\n?```\s*$/i, "").trim());
|
|
68376
|
+
let parsed;
|
|
68377
|
+
try {
|
|
68378
|
+
parsed = JSON.parse(cleaned);
|
|
68379
|
+
} catch {
|
|
68380
|
+
return null;
|
|
68381
|
+
}
|
|
68382
|
+
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")
|
|
68383
|
+
return null;
|
|
68384
|
+
let isGitQuery = parsed.isGitQuery, asksStatus = parsed.asksStatus, asksDiff = parsed.asksDiff, asksLog = parsed.asksLog, asksBranch = parsed.asksBranch, showTarget = null;
|
|
68385
|
+
if (typeof parsed.showTarget == "string" && parsed.showTarget.trim()) {
|
|
68386
|
+
let candidateTarget = parsed.showTarget.trim();
|
|
68387
|
+
SAFE_REF_PATTERN.test(candidateTarget) && !candidateTarget.startsWith("-") && !candidateTarget.includes("..") && !candidateTarget.endsWith("^!") && !candidateTarget.endsWith("^@") && (showTarget = candidateTarget);
|
|
68388
|
+
}
|
|
68389
|
+
let targetRepo = null;
|
|
68390
|
+
if (typeof parsed.targetRepo == "string" && parsed.targetRepo.trim()) {
|
|
68391
|
+
let candidateRepo = parsed.targetRepo.trim();
|
|
68392
|
+
SAFE_REPO_NAME_PATTERN.test(candidateRepo) && candidateRepo !== "." && candidateRepo !== ".." && !candidateRepo.includes("/") && !candidateRepo.includes("\\") && (targetRepo = candidateRepo);
|
|
68393
|
+
}
|
|
68394
|
+
return {
|
|
68395
|
+
isGitQuery,
|
|
68396
|
+
asksStatus,
|
|
68397
|
+
asksDiff,
|
|
68398
|
+
asksLog,
|
|
68399
|
+
asksBranch,
|
|
68400
|
+
showTarget,
|
|
68401
|
+
targetRepo
|
|
68402
|
+
};
|
|
68403
|
+
}
|
|
68404
|
+
async function parseGitStatusQueryWithGemma(runner, prompt, timeoutMs = 12e3) {
|
|
68405
|
+
let startTime = Date.now(), boundedPrompt = prompt.slice(0, 2e3).trim(), promptText = renderLocalGemmaGitStatusQueryPrompt({ userPrompt: boundedPrompt }), abortController = new AbortController(), timer = null;
|
|
68406
|
+
try {
|
|
68407
|
+
let timeoutPromise = new Promise((_, reject) => {
|
|
68408
|
+
timer = setTimeout(() => {
|
|
68409
|
+
abortController.abort(), reject(new Error(`Gemma status query classification timed out after ${timeoutMs}ms`));
|
|
68410
|
+
}, timeoutMs), timer?.unref?.();
|
|
68411
|
+
}), advisoryPromise = runner.generateAdvisory(promptText, {
|
|
68412
|
+
responseFormat: "json",
|
|
68413
|
+
numPredict: 100,
|
|
68414
|
+
temperature: 0.1,
|
|
68415
|
+
timeoutMs,
|
|
68416
|
+
signal: abortController.signal
|
|
68417
|
+
}), raw = await Promise.race([advisoryPromise, timeoutPromise]);
|
|
68418
|
+
if (!raw || typeof raw != "string")
|
|
68419
|
+
return logger.warn("[git-status-summary] Gemma returned empty or non-string response", {
|
|
68420
|
+
prompt: boundedPrompt,
|
|
68421
|
+
durationMs: Date.now() - startTime
|
|
68422
|
+
}), null;
|
|
68423
|
+
let parsed = parseGemmaGitStatusResponse(raw);
|
|
68424
|
+
return parsed || (logger.warn("[git-status-summary] Gemma response failed schema validation", {
|
|
68425
|
+
prompt: boundedPrompt,
|
|
68426
|
+
raw,
|
|
68427
|
+
durationMs: Date.now() - startTime
|
|
68428
|
+
}), null);
|
|
68429
|
+
} catch (err) {
|
|
68430
|
+
let elapsed = Date.now() - startTime;
|
|
68431
|
+
return logger.warn("[git-status-summary] Gemma status query classification timed out or failed", {
|
|
68432
|
+
prompt: boundedPrompt,
|
|
68433
|
+
durationMs: elapsed,
|
|
68434
|
+
error: err?.message || String(err)
|
|
68435
|
+
}), null;
|
|
68436
|
+
} finally {
|
|
68437
|
+
timer && clearTimeout(timer);
|
|
68438
|
+
}
|
|
68439
|
+
}
|
|
68440
|
+
function parseGitStatusQuerySemantic(prompt) {
|
|
68441
|
+
let trimmed = prompt.trim();
|
|
68442
|
+
if (!trimmed)
|
|
68443
|
+
return {
|
|
68444
|
+
isGitQuery: !1,
|
|
68445
|
+
asksStatus: !1,
|
|
68446
|
+
asksDiff: !1,
|
|
68447
|
+
asksLog: !1,
|
|
68448
|
+
asksBranch: !1,
|
|
68449
|
+
showTarget: null,
|
|
68450
|
+
targetRepo: null
|
|
68451
|
+
};
|
|
68452
|
+
let isExplicitGit = /\b(?:git\s+(?:status|diff|log|branch|show|checkout|switch|restore)|commit\s+history|recent\s+commits)\b/i.test(trimmed);
|
|
68453
|
+
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)))
|
|
68454
|
+
return {
|
|
68455
|
+
isGitQuery: !1,
|
|
68456
|
+
asksStatus: !1,
|
|
68457
|
+
asksDiff: !1,
|
|
68458
|
+
asksLog: !1,
|
|
68459
|
+
asksBranch: !1,
|
|
68460
|
+
showTarget: null,
|
|
68461
|
+
targetRepo: null
|
|
68462
|
+
};
|
|
68463
|
+
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;
|
|
68464
|
+
if (asksCommitDiff) {
|
|
68465
|
+
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);
|
|
68466
|
+
commitHexMatch && !commitHexMatch[1].includes("..") ? showTarget = stripSentencePunctuation(commitHexMatch[1]) : showTarget = extractBranchOrRefTarget(trimmed) ?? "HEAD";
|
|
68467
|
+
}
|
|
68468
|
+
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(?: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+)?(?:untracked|modified)\s+files\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\s+on|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);
|
|
68469
|
+
return {
|
|
68470
|
+
isGitQuery: !!(isExplicitGit || GIT_QUERY_PATTERN.test(trimmed) || asksStatus || asksDiff || asksLog || asksBranch || asksShow || asksCommitDiff),
|
|
68471
|
+
asksStatus,
|
|
68472
|
+
asksDiff,
|
|
68473
|
+
asksLog,
|
|
68474
|
+
asksBranch,
|
|
68475
|
+
showTarget,
|
|
68476
|
+
targetRepo: null
|
|
68477
|
+
};
|
|
68478
|
+
}
|
|
68479
|
+
async function resolveGitStatusIntent(options) {
|
|
68480
|
+
let { prompt, advisoryRunner } = options, trimmed = prompt.trim();
|
|
68481
|
+
if (!trimmed)
|
|
68482
|
+
return {
|
|
68483
|
+
isGitQuery: !1,
|
|
68484
|
+
asksStatus: !1,
|
|
68485
|
+
asksDiff: !1,
|
|
68486
|
+
asksLog: !1,
|
|
68487
|
+
asksBranch: !1,
|
|
68488
|
+
showTarget: null,
|
|
68489
|
+
targetRepo: null
|
|
68490
|
+
};
|
|
68491
|
+
if (isConceptualGitQuestion(trimmed))
|
|
68492
|
+
return {
|
|
68493
|
+
isGitQuery: !1,
|
|
68494
|
+
asksStatus: !1,
|
|
68495
|
+
asksDiff: !1,
|
|
68496
|
+
asksLog: !1,
|
|
68497
|
+
asksBranch: !1,
|
|
68498
|
+
showTarget: null,
|
|
68499
|
+
targetRepo: null
|
|
68500
|
+
};
|
|
68501
|
+
if (/^(?:[`'"]?(?:\/|!)?git\s+(?:status|diff|log|branch|show|checkout|switch|restore)\b)/i.test(trimmed))
|
|
68502
|
+
return parseGitStatusQuerySemantic(trimmed);
|
|
68503
|
+
let candidateRunner = resolvePreferredAdvisoryRunner(advisoryRunner);
|
|
68504
|
+
if (candidateRunner)
|
|
68505
|
+
try {
|
|
68506
|
+
let gemmaStart = Date.now(), gemmaIntent = await parseGitStatusQueryWithGemma(candidateRunner, trimmed), gemmaDurationMs = Date.now() - gemmaStart;
|
|
68507
|
+
if (gemmaIntent !== null) {
|
|
68508
|
+
if (gemmaIntent.targetRepo) {
|
|
68509
|
+
let repoCandidate = stripSentencePunctuation(gemmaIntent.targetRepo), candLower = repoCandidate.toLowerCase(), genericStopwords = /* @__PURE__ */ new Set([
|
|
68510
|
+
"work",
|
|
68511
|
+
"working",
|
|
68512
|
+
"tree",
|
|
68513
|
+
"directory",
|
|
68514
|
+
"copy",
|
|
68515
|
+
"repo",
|
|
68516
|
+
"repository",
|
|
68517
|
+
"git",
|
|
68518
|
+
"current",
|
|
68519
|
+
"active",
|
|
68520
|
+
"local",
|
|
68521
|
+
"here",
|
|
68522
|
+
"this",
|
|
68523
|
+
"diff",
|
|
68524
|
+
"status",
|
|
68525
|
+
"log",
|
|
68526
|
+
"branch",
|
|
68527
|
+
"show",
|
|
68528
|
+
"commit",
|
|
68529
|
+
"commits"
|
|
68530
|
+
]), isExplicitRepoSyntax = SAFE_REPO_NAME_PATTERN.test(repoCandidate) && !repoCandidate.includes(".."), designatedTokens = [], afterMatches = trimmed.matchAll(
|
|
68531
|
+
/\b(?:in|for|from|under|at|inside|to)\s+(?:the\s+)?(?:repo|repository|submodule|package|dir|directory|project)\s+["'`]?([A-Za-z0-9_.-]+)["'`]?/gi
|
|
68532
|
+
);
|
|
68533
|
+
for (let m of afterMatches) {
|
|
68534
|
+
let tok = stripSentencePunctuation(m[1]).toLowerCase();
|
|
68535
|
+
tok && designatedTokens.push(tok);
|
|
68536
|
+
}
|
|
68537
|
+
let beforeMatches = trimmed.matchAll(
|
|
68538
|
+
/(?<=^|[\s"'\`(\[{<])([A-Za-z0-9_.-]+)\s+(?:repo|repository|package|project|submodule)\b/gi
|
|
68539
|
+
);
|
|
68540
|
+
for (let m of beforeMatches) {
|
|
68541
|
+
let tok = stripSentencePunctuation(m[1]).toLowerCase();
|
|
68542
|
+
tok && designatedTokens.push(tok);
|
|
68543
|
+
}
|
|
68544
|
+
!designatedTokens.some(
|
|
68545
|
+
(token) => token === candLower && !genericStopwords.has(token)
|
|
68546
|
+
) || !isExplicitRepoSyntax || genericStopwords.has(candLower) ? gemmaIntent.targetRepo = null : gemmaIntent.targetRepo = repoCandidate;
|
|
68547
|
+
}
|
|
68548
|
+
return logger.info("[git-status-summary] Gemma status intent decision", {
|
|
68549
|
+
prompt: trimmed,
|
|
68550
|
+
runner: candidateRunner.runtimeLabel,
|
|
68551
|
+
providerKind: candidateRunner.providerKind,
|
|
68552
|
+
durationMs: gemmaDurationMs,
|
|
68553
|
+
intent: gemmaIntent
|
|
68554
|
+
}), gemmaIntent;
|
|
68555
|
+
} else
|
|
68556
|
+
logger.info("[git-status-summary] Gemma returned null or timed out, falling back to deterministic semantic parser", {
|
|
68557
|
+
prompt: trimmed
|
|
68558
|
+
});
|
|
68559
|
+
} catch (err) {
|
|
68560
|
+
logger.warn("[git-status-summary] Gemma status intent query failed, falling back to deterministic semantic parser", {
|
|
68561
|
+
prompt: trimmed,
|
|
68562
|
+
error: err?.message
|
|
68563
|
+
});
|
|
68564
|
+
}
|
|
68565
|
+
return parseGitStatusQuerySemantic(trimmed);
|
|
68566
|
+
}
|
|
68567
|
+
var IGNORED_TARGET_NAMES = /* @__PURE__ */ new Set([
|
|
67552
68568
|
"git",
|
|
67553
68569
|
"the",
|
|
67554
68570
|
"this",
|
|
@@ -67703,7 +68719,9 @@ var defaultExecFileAsync = (0, import_util3.promisify)(import_child_process5.exe
|
|
|
67703
68719
|
"very"
|
|
67704
68720
|
], STOPWORDS = new Set(FUNCTION_WORDS), NON_SHOW_TARGET_WORDS = new Set(FUNCTION_WORDS);
|
|
67705
68721
|
function extractCandidateRepos(prompt) {
|
|
67706
|
-
let candidates = [], seen = /* @__PURE__ */ new Set(), addCandidate = (
|
|
68722
|
+
let candidates = [], seen = /* @__PURE__ */ new Set(), addCandidate = (rawName, isExplicit) => {
|
|
68723
|
+
let name = stripSentencePunctuation(rawName);
|
|
68724
|
+
if (!name) return;
|
|
67707
68725
|
let lower = name.toLowerCase();
|
|
67708
68726
|
if (IGNORED_TARGET_NAMES.has(lower) || /^[0-9a-f]{7,40}$/i.test(name))
|
|
67709
68727
|
return;
|
|
@@ -67714,13 +68732,20 @@ function extractCandidateRepos(prompt) {
|
|
|
67714
68732
|
let existing = candidates.find((c) => c.name.toLowerCase() === lower);
|
|
67715
68733
|
existing && (existing.isExplicit = !0);
|
|
67716
68734
|
}
|
|
67717
|
-
}, trailingRepoRegex =
|
|
67718
|
-
for (; (match = trailingRepoRegex.exec(prompt)) !== null; )
|
|
67719
|
-
|
|
67720
|
-
|
|
67721
|
-
|
|
67722
|
-
|
|
67723
|
-
|
|
68735
|
+
}, trailingRepoRegex = /(?<=^|[\s"'\`(\[{<])([a-zA-Z0-9_.-]+)\s+(?:repo(?:sitory)?|project|package|submodule)\b/gi, match;
|
|
68736
|
+
for (; (match = trailingRepoRegex.exec(prompt)) !== null; ) {
|
|
68737
|
+
let raw = match[1], isStopword = STOPWORDS.has(raw.toLowerCase());
|
|
68738
|
+
addCandidate(raw, !isStopword);
|
|
68739
|
+
}
|
|
68740
|
+
let leadingRepoRegex = /\b(?:repo(?:sitory)?|project|package|submodule)\s+([a-zA-Z0-9_.-]+)/gi;
|
|
68741
|
+
for (; (match = leadingRepoRegex.exec(prompt)) !== null; ) {
|
|
68742
|
+
let raw = match[1];
|
|
68743
|
+
if (match[0].toLowerCase().startsWith("package") && raw.toLowerCase() === "lock")
|
|
68744
|
+
continue;
|
|
68745
|
+
let isStopword = STOPWORDS.has(raw.toLowerCase());
|
|
68746
|
+
addCandidate(raw, !isStopword);
|
|
68747
|
+
}
|
|
68748
|
+
let casualRegex = /\b(?:in|of|for)\s+(?:the\s+)?([a-zA-Z0-9_.-]+)/gi;
|
|
67724
68749
|
for (; (match = casualRegex.exec(prompt)) !== null; )
|
|
67725
68750
|
addCandidate(match[1], !1);
|
|
67726
68751
|
return candidates;
|
|
@@ -67736,8 +68761,11 @@ ${content}
|
|
|
67736
68761
|
${fence}`;
|
|
67737
68762
|
}
|
|
67738
68763
|
async function executeGitStatusSummary(options) {
|
|
67739
|
-
let { cwd, prompt, hasActiveTask, execFileFn = defaultExecFileAsync } = options;
|
|
67740
|
-
if (
|
|
68764
|
+
let { cwd, prompt, hasActiveTask, advisoryRunner, execFileFn = defaultExecFileAsync } = options;
|
|
68765
|
+
if (hasActiveTask)
|
|
68766
|
+
return null;
|
|
68767
|
+
let intent = await resolveGitStatusIntent({ prompt, advisoryRunner });
|
|
68768
|
+
if (!intent.isGitQuery)
|
|
67741
68769
|
return null;
|
|
67742
68770
|
let gitEnv = scrubSearchApiKeys({ ...process.env, LC_ALL: "C" }), defaultRepoName = sanitizeForTerminal(redactAbsoluteLocalPaths(path64.basename(cwd))), defaultRepoTopLevel = cwd;
|
|
67743
68771
|
try {
|
|
@@ -67749,8 +68777,18 @@ async function executeGitStatusSummary(options) {
|
|
|
67749
68777
|
trimmed && (defaultRepoTopLevel = trimmed, defaultRepoName = sanitizeForTerminal(redactAbsoluteLocalPaths(path64.basename(trimmed))));
|
|
67750
68778
|
} catch {
|
|
67751
68779
|
}
|
|
67752
|
-
let targetCwd = cwd, targetRepoName = defaultRepoName, notePrefix = "", candidates = extractCandidateRepos(prompt)
|
|
68780
|
+
let targetCwd = cwd, targetRepoName = defaultRepoName, notePrefix = "", candidates = extractCandidateRepos(prompt);
|
|
68781
|
+
if (intent.targetRepo) {
|
|
68782
|
+
let rawTarget = stripSentencePunctuation(intent.targetRepo);
|
|
68783
|
+
if (SAFE_REPO_NAME_PATTERN.test(rawTarget) && rawTarget !== "." && rawTarget !== ".." && !rawTarget.includes("/") && !rawTarget.includes("\\")) {
|
|
68784
|
+
let existingIndex = candidates.findIndex((c) => c.name.toLowerCase() === rawTarget.toLowerCase());
|
|
68785
|
+
existingIndex >= 0 && candidates.splice(existingIndex, 1), candidates.unshift({ name: rawTarget, isExplicit: !0 });
|
|
68786
|
+
}
|
|
68787
|
+
}
|
|
68788
|
+
let resolvedRepo = null;
|
|
67753
68789
|
for (let candidate of candidates) {
|
|
68790
|
+
if (!SAFE_REPO_NAME_PATTERN.test(candidate.name) || candidate.name === "." || candidate.name === ".." || candidate.name.includes("/") || candidate.name.includes("\\"))
|
|
68791
|
+
continue;
|
|
67754
68792
|
if (defaultRepoName.toLowerCase() === candidate.name.toLowerCase()) {
|
|
67755
68793
|
resolvedRepo = { cwd, name: defaultRepoName };
|
|
67756
68794
|
break;
|
|
@@ -67809,7 +68847,64 @@ async function executeGitStatusSummary(options) {
|
|
|
67809
68847
|
|
|
67810
68848
|
`), targetCwd = cwd, targetRepoName = defaultRepoName;
|
|
67811
68849
|
}
|
|
67812
|
-
let sections = [],
|
|
68850
|
+
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 });
|
|
68851
|
+
async function isValidGitComparisonRef(ref, targetCwd2, gitEnv2, execFileFn2) {
|
|
68852
|
+
if (ref.includes("..")) {
|
|
68853
|
+
let rangeParts = ref.includes("...") ? ref.split("...") : ref.split("..");
|
|
68854
|
+
if (rangeParts.length !== 2 || !rangeParts[0] && !rangeParts[1])
|
|
68855
|
+
return !1;
|
|
68856
|
+
for (let part of rangeParts) {
|
|
68857
|
+
let endpoint = part || "HEAD";
|
|
68858
|
+
if (!SAFE_REF_PATTERN.test(endpoint) || endpoint.startsWith("-"))
|
|
68859
|
+
return !1;
|
|
68860
|
+
try {
|
|
68861
|
+
await execFileFn2(
|
|
68862
|
+
"git",
|
|
68863
|
+
["--no-optional-locks", "rev-parse", "--verify", "--quiet", `${endpoint}^{commit}`],
|
|
68864
|
+
{ cwd: targetCwd2, env: gitEnv2, timeout: 3e3, encoding: "utf8" }
|
|
68865
|
+
);
|
|
68866
|
+
} catch {
|
|
68867
|
+
return !1;
|
|
68868
|
+
}
|
|
68869
|
+
}
|
|
68870
|
+
return !0;
|
|
68871
|
+
}
|
|
68872
|
+
if (!SAFE_REF_PATTERN.test(ref) || ref.startsWith("-"))
|
|
68873
|
+
return !1;
|
|
68874
|
+
try {
|
|
68875
|
+
return await execFileFn2(
|
|
68876
|
+
"git",
|
|
68877
|
+
["--no-optional-locks", "rev-parse", "--verify", "--quiet", `${ref}^{commit}`],
|
|
68878
|
+
{ cwd: targetCwd2, env: gitEnv2, timeout: 3e3, encoding: "utf8" }
|
|
68879
|
+
), !0;
|
|
68880
|
+
} catch {
|
|
68881
|
+
return !1;
|
|
68882
|
+
}
|
|
68883
|
+
}
|
|
68884
|
+
function occursOutsideComparisonSpan(prompt2, target, span, comparisonRef) {
|
|
68885
|
+
if (!span) {
|
|
68886
|
+
if (comparisonRef) {
|
|
68887
|
+
let lowerComp = comparisonRef.toLowerCase(), lowerTgt = target.toLowerCase();
|
|
68888
|
+
if (lowerComp === lowerTgt || lowerComp.includes(lowerTgt) || lowerTgt.includes(lowerComp))
|
|
68889
|
+
return !1;
|
|
68890
|
+
}
|
|
68891
|
+
return !0;
|
|
68892
|
+
}
|
|
68893
|
+
let lowerPrompt = prompt2.toLowerCase(), lowerTarget = target.toLowerCase(), idx = lowerPrompt.indexOf(lowerTarget);
|
|
68894
|
+
if (idx === -1)
|
|
68895
|
+
return !0;
|
|
68896
|
+
for (; idx !== -1; ) {
|
|
68897
|
+
if (idx + lowerTarget.length <= span.start || idx >= span.end)
|
|
68898
|
+
return !0;
|
|
68899
|
+
idx = lowerPrompt.indexOf(lowerTarget, idx + 1);
|
|
68900
|
+
}
|
|
68901
|
+
return !1;
|
|
68902
|
+
}
|
|
68903
|
+
if (comparisonBaseInfo && !comparisonBaseInfo.isExplicit) {
|
|
68904
|
+
let candidateRef = comparisonBaseInfo.ref;
|
|
68905
|
+
await isValidGitComparisonRef(candidateRef, targetCwd, gitEnv, execFileFn) || (comparisonBaseInfo = void 0);
|
|
68906
|
+
}
|
|
68907
|
+
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
68908
|
if (openerMatch) {
|
|
67814
68909
|
let opener = openerMatch[1], pairRegex = null;
|
|
67815
68910
|
switch (opener) {
|
|
@@ -67881,9 +68976,34 @@ async function executeGitStatusSummary(options) {
|
|
|
67881
68976
|
}
|
|
67882
68977
|
}
|
|
67883
68978
|
}
|
|
67884
|
-
if (!
|
|
67885
|
-
|
|
67886
|
-
|
|
68979
|
+
if (!isExplicitCommitShowRequest && hasComparison)
|
|
68980
|
+
showTarget = null;
|
|
68981
|
+
else if (!showTarget) {
|
|
68982
|
+
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;
|
|
68983
|
+
if (showCommitMatch && targetRef && occursOutsideComparisonSpan(prompt, targetRef, comparisonBaseInfo?.span, comparisonBaseInfo?.ref))
|
|
68984
|
+
showTarget = stripSentencePunctuation(targetRef);
|
|
68985
|
+
else if (asksShow && intent.showTarget && occursOutsideComparisonSpan(prompt, intent.showTarget, comparisonBaseInfo?.span, comparisonBaseInfo?.ref))
|
|
68986
|
+
showTarget = intent.showTarget;
|
|
68987
|
+
else {
|
|
68988
|
+
let nonComparisonHash = null;
|
|
68989
|
+
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)) {
|
|
68990
|
+
let matchIndex = m.index, matchEnd = matchIndex + m[0].length;
|
|
68991
|
+
if (comparisonBaseInfo?.span) {
|
|
68992
|
+
if (!(matchEnd <= comparisonBaseInfo.span.start || matchIndex >= comparisonBaseInfo.span.end))
|
|
68993
|
+
continue;
|
|
68994
|
+
} else if (comparisonBaseInfo?.ref) {
|
|
68995
|
+
let compRef = comparisonBaseInfo.ref.toLowerCase(), cand = m[1].toLowerCase();
|
|
68996
|
+
if (compRef === cand || compRef.includes(cand) || cand.includes(compRef))
|
|
68997
|
+
continue;
|
|
68998
|
+
}
|
|
68999
|
+
let candidate = stripSentencePunctuation(m[1]);
|
|
69000
|
+
if (!candidate.includes("..")) {
|
|
69001
|
+
nonComparisonHash = candidate;
|
|
69002
|
+
break;
|
|
69003
|
+
}
|
|
69004
|
+
}
|
|
69005
|
+
nonComparisonHash ? showTarget = nonComparisonHash : asksShow && (showTarget = "HEAD");
|
|
69006
|
+
}
|
|
67887
69007
|
}
|
|
67888
69008
|
let includeStatus = asksStatus || !asksDiff && !asksBranch && !asksShow, includeLog = asksLog || !asksDiff && !asksBranch && !asksShow;
|
|
67889
69009
|
try {
|
|
@@ -67920,24 +69040,27 @@ ${formatFencedCodeBlock(statusContent, "text")}`);
|
|
|
67920
69040
|
${formatFencedCodeBlock(logContent, "text")}`);
|
|
67921
69041
|
}
|
|
67922
69042
|
if (asksDiff) {
|
|
67923
|
-
let diffContent = "No working tree changes";
|
|
67924
|
-
|
|
67925
|
-
|
|
67926
|
-
|
|
67927
|
-
|
|
67928
|
-
{
|
|
67929
|
-
|
|
67930
|
-
|
|
67931
|
-
|
|
67932
|
-
|
|
69043
|
+
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";
|
|
69044
|
+
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")));
|
|
69045
|
+
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"];
|
|
69046
|
+
if (!diffContent.startsWith("Commit or reference"))
|
|
69047
|
+
try {
|
|
69048
|
+
let { stdout: gitDiff } = await execFileFn(
|
|
69049
|
+
"git",
|
|
69050
|
+
diffArgs,
|
|
69051
|
+
{ cwd: targetCwd, env: gitEnv, timeout: 3e3, encoding: "utf8" }
|
|
69052
|
+
), diffLines = gitDiff.split(/\r?\n/).map((l) => l.trimEnd()).filter((l) => l.length > 0);
|
|
69053
|
+
if (diffLines.length > 0) {
|
|
69054
|
+
let capped = diffLines.slice(0, 20), rem = diffLines.length - 20;
|
|
69055
|
+
diffContent = rem > 0 ? `${capped.join(`
|
|
67933
69056
|
`)}
|
|
67934
69057
|
...and ${rem} more` : capped.join(`
|
|
67935
69058
|
`);
|
|
69059
|
+
}
|
|
69060
|
+
} catch {
|
|
69061
|
+
diffContent = isStaged ? "Staged diff is unavailable" : "Diff is unavailable";
|
|
67936
69062
|
}
|
|
67937
|
-
|
|
67938
|
-
diffContent = "Diff is unavailable";
|
|
67939
|
-
}
|
|
67940
|
-
diffContent = sanitizeForTerminal(redactAbsoluteLocalPaths(diffContent)), sections.push(`### Git Diff (${targetRepoName})
|
|
69063
|
+
diffContent = sanitizeForTerminal(redactAbsoluteLocalPaths(diffContent)), sections.push(`${diffTitle}
|
|
67941
69064
|
${formatFencedCodeBlock(diffContent, "text")}`);
|
|
67942
69065
|
}
|
|
67943
69066
|
if (asksBranch) {
|
|
@@ -67956,7 +69079,8 @@ ${formatFencedCodeBlock(diffContent, "text")}`);
|
|
|
67956
69079
|
branchContent = sanitizeForTerminal(redactAbsoluteLocalPaths(branchContent)), sections.push(`### Git Branches (${targetRepoName})
|
|
67957
69080
|
${formatFencedCodeBlock(branchContent, "text")}`);
|
|
67958
69081
|
}
|
|
67959
|
-
if (showTarget) {
|
|
69082
|
+
if (!isSinceLastCommit && showTarget) {
|
|
69083
|
+
(showTarget.startsWith("-") || showTarget.includes("\0")) && (showTarget = "HEAD");
|
|
67960
69084
|
let isHexHash = /^[0-9a-f]{7,40}$/i.test(showTarget), safeTarget = sanitizeForTerminal(redactAbsoluteLocalPaths(showTarget)), title = isHexHash ? `Commit ${safeTarget}` : `Git Show ${safeTarget}`;
|
|
67961
69085
|
try {
|
|
67962
69086
|
let gitShowRef = showTarget.endsWith("^!") || showTarget.endsWith("^@") ? showTarget : `${showTarget}^{commit}`, { stdout: showOut } = await execFileFn(
|
|
@@ -71053,7 +72177,7 @@ async function runOrchestrationShell(args) {
|
|
|
71053
72177
|
let isSlash = isShellSlashCommand(text2), browseController = null;
|
|
71054
72178
|
isSlash || (browseController = new AbortController(), activeBrowseAbortController = browseController);
|
|
71055
72179
|
try {
|
|
71056
|
-
await handleShellUserInput({
|
|
72180
|
+
logger.info("[orchestration-shell] Turn started", { prompt: text2 }), await handleShellUserInput({
|
|
71057
72181
|
text: text2,
|
|
71058
72182
|
store,
|
|
71059
72183
|
args,
|
|
@@ -71087,7 +72211,7 @@ async function runOrchestrationShell(args) {
|
|
|
71087
72211
|
// concurrent slash bypass can't leak its advisory into this mirror
|
|
71088
72212
|
// and vice-versa.
|
|
71089
72213
|
ownEntries
|
|
71090
|
-
});
|
|
72214
|
+
}), logger.info("[orchestration-shell] Turn completed", { prompt: text2 });
|
|
71091
72215
|
});
|
|
71092
72216
|
}
|
|
71093
72217
|
), handleUserInput = (text2, images, options) => {
|
|
@@ -75595,6 +76719,10 @@ async function handleShellUserInput(deps) {
|
|
|
75595
76719
|
if (decision = await dispatchClassify({
|
|
75596
76720
|
...plannerInput,
|
|
75597
76721
|
prompt: classifyPrompt
|
|
76722
|
+
}), logger.info("[orchestration-shell] Planner classified input", {
|
|
76723
|
+
prompt: plannerInput.prompt,
|
|
76724
|
+
action: decision.action,
|
|
76725
|
+
rationale: decision.rationale
|
|
75598
76726
|
}), isLocalPlannerRuntime(args) && decision.action === "browse" && hasFileMutationIntent(plannerInput.prompt) && (decision = {
|
|
75599
76727
|
action: "start_task",
|
|
75600
76728
|
rationale: decision.rationale ? `${decision.rationale} (promoted to start_task due to file mutation intent)` : "web request with file mutation intent"
|
|
@@ -75771,6 +76899,27 @@ async function handleShellUserInput(deps) {
|
|
|
75771
76899
|
return;
|
|
75772
76900
|
}
|
|
75773
76901
|
if (isTextAdvisory) {
|
|
76902
|
+
let hasRunningSingle = store.getState().runningTasks.size > 0, team = store.getState().team, teamActive = team !== null && !team.groupResolved && team.haltReason === null, hasActiveTask = hasRunningSingle || teamActive;
|
|
76903
|
+
if (!isConceptualGitQuestion(dispatchText)) {
|
|
76904
|
+
let gitResponse = await executeGitStatusSummary({
|
|
76905
|
+
cwd: args.cwd || process.cwd(),
|
|
76906
|
+
prompt: dispatchText,
|
|
76907
|
+
hasActiveTask,
|
|
76908
|
+
advisoryRunner: args.localAdvisoryRunner,
|
|
76909
|
+
execFileFn: execFileAsync
|
|
76910
|
+
});
|
|
76911
|
+
if (gitResponse !== null) {
|
|
76912
|
+
logger.info("[orchestration-shell] Dispatched SHELL_ADVISORY for git status", {
|
|
76913
|
+
prompt: dispatchText,
|
|
76914
|
+
responseLength: gitResponse.length
|
|
76915
|
+
}), store.dispatch({
|
|
76916
|
+
type: "SHELL_ADVISORY",
|
|
76917
|
+
source: "shell",
|
|
76918
|
+
text: gitResponse
|
|
76919
|
+
});
|
|
76920
|
+
return;
|
|
76921
|
+
}
|
|
76922
|
+
}
|
|
75774
76923
|
await routeAdvisory({
|
|
75775
76924
|
store,
|
|
75776
76925
|
args,
|
|
@@ -75946,6 +77095,7 @@ async function handleShellUserInput(deps) {
|
|
|
75946
77095
|
cwd: args.cwd || process.cwd(),
|
|
75947
77096
|
prompt: plannerInput.prompt,
|
|
75948
77097
|
hasActiveTask,
|
|
77098
|
+
advisoryRunner: args.localAdvisoryRunner,
|
|
75949
77099
|
execFileFn: execFileAsync
|
|
75950
77100
|
});
|
|
75951
77101
|
if (gitResponse !== null) {
|
|
@@ -77485,15 +78635,40 @@ var HostedGemmaAdvisoryRunner = class {
|
|
|
77485
78635
|
}
|
|
77486
78636
|
encryptedImages = options.images.map((img) => this.deps.crypto.encryptString(img, sessionKey));
|
|
77487
78637
|
}
|
|
78638
|
+
if (options?.signal?.aborted) {
|
|
78639
|
+
let err = new Error("Hosted Gemma generation aborted by signal");
|
|
78640
|
+
throw err.name = "AbortError", err;
|
|
78641
|
+
}
|
|
77488
78642
|
let maxTokens = options?.numPredict, temperature = options?.temperature, start = Date.now();
|
|
77489
78643
|
try {
|
|
77490
|
-
let
|
|
78644
|
+
let promises2 = [this.deps.transport.generatePlannerAdvisory({
|
|
77491
78645
|
sessionId,
|
|
77492
78646
|
prompt: encryptedPrompt,
|
|
77493
78647
|
...encryptedImages && encryptedImages.length > 0 ? { images: encryptedImages } : {},
|
|
77494
78648
|
...maxTokens !== void 0 ? { maxTokens } : {},
|
|
77495
78649
|
...temperature !== void 0 ? { temperature } : {}
|
|
77496
|
-
});
|
|
78650
|
+
})], timer, abortHandler;
|
|
78651
|
+
options?.timeoutMs && options.timeoutMs > 0 && promises2.push(
|
|
78652
|
+
new Promise((_, reject) => {
|
|
78653
|
+
timer = setTimeout(() => {
|
|
78654
|
+
let err = new Error(`Hosted Gemma advisory generation timed out after ${options.timeoutMs}ms`);
|
|
78655
|
+
err.name = "TimeoutError", reject(err);
|
|
78656
|
+
}, options.timeoutMs);
|
|
78657
|
+
})
|
|
78658
|
+
), options?.signal && promises2.push(
|
|
78659
|
+
new Promise((_, reject) => {
|
|
78660
|
+
abortHandler = () => {
|
|
78661
|
+
let err = new Error("Hosted Gemma generation aborted by signal");
|
|
78662
|
+
err.name = "AbortError", reject(err);
|
|
78663
|
+
}, options.signal.addEventListener("abort", abortHandler, { once: !0 });
|
|
78664
|
+
})
|
|
78665
|
+
);
|
|
78666
|
+
let response;
|
|
78667
|
+
try {
|
|
78668
|
+
response = await Promise.race(promises2);
|
|
78669
|
+
} finally {
|
|
78670
|
+
timer && clearTimeout(timer), abortHandler && options?.signal && options.signal.removeEventListener("abort", abortHandler);
|
|
78671
|
+
}
|
|
77497
78672
|
return this.deps.crypto.decryptString(response.advisoryText, sessionKey);
|
|
77498
78673
|
} catch (err) {
|
|
77499
78674
|
let elapsedMs = Date.now() - start;
|
|
@@ -81452,6 +82627,7 @@ function enforceStrictJsonStdout(raw) {
|
|
|
81452
82627
|
var LocalGemmaProcessRunner = class {
|
|
81453
82628
|
constructor(config) {
|
|
81454
82629
|
this.config = config;
|
|
82630
|
+
this.providerKind = "local";
|
|
81455
82631
|
this.runtimeLabel = `local-gemma-process:${import_path4.default.basename(config.command)}`;
|
|
81456
82632
|
}
|
|
81457
82633
|
async classify(promptText) {
|