@gaunt-sloth/core 2.0.0-alpha.3 → 2.0.0-alpha.31
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/README.md +52 -20
- package/dist/config/colour.d.ts +38 -0
- package/dist/config/colour.js +36 -0
- package/dist/config/colour.js.map +1 -0
- package/dist/config/defaults.d.ts +84 -0
- package/dist/config/defaults.js +99 -0
- package/dist/config/defaults.js.map +1 -0
- package/dist/config/filesystem-tools.d.ts +41 -0
- package/dist/config/filesystem-tools.js +56 -0
- package/dist/config/filesystem-tools.js.map +1 -0
- package/dist/config/jsonc.d.ts +12 -0
- package/dist/config/jsonc.js +41 -0
- package/dist/config/jsonc.js.map +1 -0
- package/dist/config/loader.d.ts +246 -0
- package/dist/config/loader.js +1321 -0
- package/dist/config/loader.js.map +1 -0
- package/dist/config/mouse.d.ts +50 -0
- package/dist/config/mouse.js +44 -0
- package/dist/config/mouse.js.map +1 -0
- package/dist/config/profiles.d.ts +68 -0
- package/dist/config/profiles.js +93 -0
- package/dist/config/profiles.js.map +1 -0
- package/dist/config/providerKeys.d.ts +69 -0
- package/dist/config/providerKeys.js +69 -0
- package/dist/config/providerKeys.js.map +1 -0
- package/dist/config/schema.d.ts +2999 -0
- package/dist/config/schema.js +1519 -0
- package/dist/config/schema.js.map +1 -0
- package/dist/config/shell-policy.d.ts +896 -0
- package/dist/config/shell-policy.js +750 -0
- package/dist/config/shell-policy.js.map +1 -0
- package/dist/config/tool-descriptions.d.ts +211 -0
- package/dist/config/tool-descriptions.js +272 -0
- package/dist/config/tool-descriptions.js.map +1 -0
- package/dist/config/types.d.ts +760 -0
- package/dist/config/types.js +13 -0
- package/dist/config/types.js.map +1 -0
- package/dist/config.d.ts +34 -827
- package/dist/config.js +25 -657
- package/dist/config.js.map +1 -1
- package/dist/constants.d.ts +46 -0
- package/dist/constants.js +46 -0
- package/dist/constants.js.map +1 -1
- package/dist/core/GthAbstractAgent.d.ts +135 -2
- package/dist/core/GthAbstractAgent.js +496 -30
- package/dist/core/GthAbstractAgent.js.map +1 -1
- package/dist/core/GthAgentRunner.d.ts +568 -54
- package/dist/core/GthAgentRunner.js +1537 -136
- package/dist/core/GthAgentRunner.js.map +1 -1
- package/dist/core/GthLangChainAgent.d.ts +115 -0
- package/dist/core/GthLangChainAgent.js +644 -17
- package/dist/core/GthLangChainAgent.js.map +1 -1
- package/dist/core/approvals/annotations.d.ts +122 -0
- package/dist/core/approvals/annotations.js +137 -0
- package/dist/core/approvals/annotations.js.map +1 -0
- package/dist/core/approvals/grants.d.ts +216 -0
- package/dist/core/approvals/grants.js +469 -0
- package/dist/core/approvals/grants.js.map +1 -0
- package/dist/core/approvals/matcher.d.ts +202 -0
- package/dist/core/approvals/matcher.js +267 -0
- package/dist/core/approvals/matcher.js.map +1 -0
- package/dist/core/approvals/mcpSubjects.d.ts +40 -0
- package/dist/core/approvals/mcpSubjects.js +99 -0
- package/dist/core/approvals/mcpSubjects.js.map +1 -0
- package/dist/core/approvals/toolAnnotationSources.d.ts +105 -0
- package/dist/core/approvals/toolAnnotationSources.js +277 -0
- package/dist/core/approvals/toolAnnotationSources.js.map +1 -0
- package/dist/core/approvals/toolHost.d.ts +46 -0
- package/dist/core/approvals/toolHost.js +108 -0
- package/dist/core/approvals/toolHost.js.map +1 -0
- package/dist/core/debugCapture.d.ts +75 -0
- package/dist/core/debugCapture.js +101 -0
- package/dist/core/debugCapture.js.map +1 -0
- package/dist/core/gthLeanAgentFactory.d.ts +9 -0
- package/dist/core/gthLeanAgentFactory.js +10 -0
- package/dist/core/gthLeanAgentFactory.js.map +1 -0
- package/dist/core/launchBanner.d.ts +120 -0
- package/dist/core/launchBanner.js +418 -0
- package/dist/core/launchBanner.js.map +1 -0
- package/dist/core/plainToolIndication.d.ts +15 -0
- package/dist/core/plainToolIndication.js +174 -0
- package/dist/core/plainToolIndication.js.map +1 -0
- package/dist/core/reasoningBlocks.d.ts +60 -0
- package/dist/core/reasoningBlocks.js +98 -0
- package/dist/core/reasoningBlocks.js.map +1 -0
- package/dist/core/refusal.d.ts +53 -0
- package/dist/core/refusal.js +133 -0
- package/dist/core/refusal.js.map +1 -0
- package/dist/core/runStats.d.ts +52 -0
- package/dist/core/runStats.js +118 -0
- package/dist/core/runStats.js.map +1 -0
- package/dist/core/shell/ShellCommandFailedError.d.ts +54 -0
- package/dist/core/shell/ShellCommandFailedError.js +68 -0
- package/dist/core/shell/ShellCommandFailedError.js.map +1 -0
- package/dist/core/shell/abstention.d.ts +88 -0
- package/dist/core/shell/abstention.js +184 -0
- package/dist/core/shell/abstention.js.map +1 -0
- package/dist/core/shell/approvalCapture.d.ts +271 -0
- package/dist/core/shell/approvalCapture.js +108 -0
- package/dist/core/shell/approvalCapture.js.map +1 -0
- package/dist/core/shell/approvalStop.d.ts +84 -0
- package/dist/core/shell/approvalStop.js +119 -0
- package/dist/core/shell/approvalStop.js.map +1 -0
- package/dist/core/shell/arity.d.ts +6 -0
- package/dist/core/shell/arity.js +20 -6
- package/dist/core/shell/arity.js.map +1 -1
- package/dist/core/shell/denylist.d.ts +11 -0
- package/dist/core/shell/denylist.js +37 -0
- package/dist/core/shell/denylist.js.map +1 -0
- package/dist/core/shell/escalationSeverity.d.ts +141 -0
- package/dist/core/shell/escalationSeverity.js +89 -0
- package/dist/core/shell/escalationSeverity.js.map +1 -0
- package/dist/core/shell/framing.d.ts +190 -0
- package/dist/core/shell/framing.js +633 -0
- package/dist/core/shell/framing.js.map +1 -0
- package/dist/core/shell/hardline.d.ts +81 -0
- package/dist/core/shell/hardline.js +607 -0
- package/dist/core/shell/hardline.js.map +1 -0
- package/dist/core/shell/negotiation.d.ts +249 -0
- package/dist/core/shell/negotiation.js +355 -0
- package/dist/core/shell/negotiation.js.map +1 -0
- package/dist/core/shell/normalize.d.ts +44 -4
- package/dist/core/shell/normalize.js +61 -7
- package/dist/core/shell/normalize.js.map +1 -1
- package/dist/core/shell/openWorld.d.ts +263 -0
- package/dist/core/shell/openWorld.js +1188 -0
- package/dist/core/shell/openWorld.js.map +1 -0
- package/dist/core/shell/rater.d.ts +935 -0
- package/dist/core/shell/rater.js +1473 -0
- package/dist/core/shell/rater.js.map +1 -0
- package/dist/core/shell/raterModel.d.ts +41 -0
- package/dist/core/shell/raterModel.js +51 -0
- package/dist/core/shell/raterModel.js.map +1 -0
- package/dist/core/shell/rejection.d.ts +69 -0
- package/dist/core/shell/rejection.js +38 -0
- package/dist/core/shell/rejection.js.map +1 -0
- package/dist/core/toolCallRepair/grammar.d.ts +41 -0
- package/dist/core/toolCallRepair/grammar.js +116 -0
- package/dist/core/toolCallRepair/grammar.js.map +1 -0
- package/dist/core/toolCallRepair/index.d.ts +2 -0
- package/dist/core/toolCallRepair/index.js +7 -0
- package/dist/core/toolCallRepair/index.js.map +1 -0
- package/dist/core/toolCallRepair/payload.d.ts +36 -0
- package/dist/core/toolCallRepair/payload.js +341 -0
- package/dist/core/toolCallRepair/payload.js.map +1 -0
- package/dist/core/toolCallRepair/promote.d.ts +45 -0
- package/dist/core/toolCallRepair/promote.js +90 -0
- package/dist/core/toolCallRepair/promote.js.map +1 -0
- package/dist/core/toolDisplay.d.ts +123 -0
- package/dist/core/toolDisplay.js +451 -0
- package/dist/core/toolDisplay.js.map +1 -0
- package/dist/core/toolOutputChannel.d.ts +95 -0
- package/dist/core/toolOutputChannel.js +165 -0
- package/dist/core/toolOutputChannel.js.map +1 -0
- package/dist/core/types.d.ts +294 -12
- package/dist/core/types.js.map +1 -1
- package/dist/history/historyFormat.d.ts +28 -0
- package/dist/history/historyFormat.js +127 -0
- package/dist/history/historyFormat.js.map +1 -0
- package/dist/history/historyStore.d.ts +198 -0
- package/dist/history/historyStore.js +482 -0
- package/dist/history/historyStore.js.map +1 -0
- package/dist/history/recordSession.d.ts +37 -0
- package/dist/history/recordSession.js +56 -0
- package/dist/history/recordSession.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/dist/providers/anthropic.d.ts +1 -1
- package/dist/providers/anthropic.js +5 -10
- package/dist/providers/anthropic.js.map +1 -1
- package/dist/providers/deepseek.d.ts +1 -1
- package/dist/providers/deepseek.js +5 -10
- package/dist/providers/deepseek.js.map +1 -1
- package/dist/providers/geminiSchemaSanitizer.d.ts +55 -0
- package/dist/providers/geminiSchemaSanitizer.js +347 -0
- package/dist/providers/geminiSchemaSanitizer.js.map +1 -0
- package/dist/providers/geminiThinking.d.ts +52 -0
- package/dist/providers/geminiThinking.js +72 -0
- package/dist/providers/geminiThinking.js.map +1 -0
- package/dist/providers/google-genai.d.ts +1 -1
- package/dist/providers/google-genai.js +12 -11
- package/dist/providers/google-genai.js.map +1 -1
- package/dist/providers/groq.d.ts +1 -1
- package/dist/providers/groq.js +5 -10
- package/dist/providers/groq.js.map +1 -1
- package/dist/providers/huggingface.d.ts +25 -0
- package/dist/providers/huggingface.js +69 -0
- package/dist/providers/huggingface.js.map +1 -0
- package/dist/providers/modelCatalog.d.ts +109 -0
- package/dist/providers/modelCatalog.js +245 -0
- package/dist/providers/modelCatalog.js.map +1 -0
- package/dist/providers/modelDiscovery.d.ts +153 -6
- package/dist/providers/modelDiscovery.js +295 -41
- package/dist/providers/modelDiscovery.js.map +1 -1
- package/dist/providers/ollama.d.ts +19 -5
- package/dist/providers/ollama.js +60 -52
- package/dist/providers/ollama.js.map +1 -1
- package/dist/providers/openai.d.ts +1 -1
- package/dist/providers/openai.js +39 -10
- package/dist/providers/openai.js.map +1 -1
- package/dist/providers/openrouter.d.ts +4 -5
- package/dist/providers/openrouter.js +20 -35
- package/dist/providers/openrouter.js.map +1 -1
- package/dist/providers/vertexai.d.ts +1 -1
- package/dist/providers/vertexai.js +12 -11
- package/dist/providers/vertexai.js.map +1 -1
- package/dist/providers/xai.d.ts +1 -1
- package/dist/providers/xai.js +5 -10
- package/dist/providers/xai.js.map +1 -1
- package/dist/runtime/askStructured.d.ts +105 -0
- package/dist/runtime/askStructured.js +120 -0
- package/dist/runtime/askStructured.js.map +1 -0
- package/dist/runtime/conversation.d.ts +60 -0
- package/dist/runtime/conversation.js +151 -0
- package/dist/runtime/conversation.js.map +1 -0
- package/dist/runtime/singleShot.d.ts +25 -5
- package/dist/runtime/singleShot.js +95 -36
- package/dist/runtime/singleShot.js.map +1 -1
- package/dist/runtime/structuredOutput.d.ts +104 -0
- package/dist/runtime/structuredOutput.js +393 -0
- package/dist/runtime/structuredOutput.js.map +1 -0
- package/dist/utils/ProgressIndicator.d.ts +21 -0
- package/dist/utils/ProgressIndicator.js +30 -3
- package/dist/utils/ProgressIndicator.js.map +1 -1
- package/dist/utils/aiignoreUtils.js.map +1 -1
- package/dist/utils/binaryOutputUtils.js.map +1 -1
- package/dist/utils/consoleUtils.d.ts +52 -0
- package/dist/utils/consoleUtils.js +72 -2
- package/dist/utils/consoleUtils.js.map +1 -1
- package/dist/utils/crashHandler.d.ts +87 -0
- package/dist/utils/crashHandler.js +128 -0
- package/dist/utils/crashHandler.js.map +1 -0
- package/dist/utils/debugDump.d.ts +134 -0
- package/dist/utils/debugDump.js +381 -0
- package/dist/utils/debugDump.js.map +1 -0
- package/dist/utils/debugUtils.d.ts +13 -4
- package/dist/utils/debugUtils.js +36 -13
- package/dist/utils/debugUtils.js.map +1 -1
- package/dist/utils/displayWidth.d.ts +53 -0
- package/dist/utils/displayWidth.js +195 -0
- package/dist/utils/displayWidth.js.map +1 -0
- package/dist/utils/fileUtils.d.ts +24 -2
- package/dist/utils/fileUtils.js +54 -12
- package/dist/utils/fileUtils.js.map +1 -1
- package/dist/utils/llmUtils.d.ts +39 -8
- package/dist/utils/llmUtils.js +76 -8
- package/dist/utils/llmUtils.js.map +1 -1
- package/dist/utils/redactSecrets.d.ts +63 -0
- package/dist/utils/redactSecrets.js +286 -0
- package/dist/utils/redactSecrets.js.map +1 -0
- package/dist/utils/systemPromptNotes.d.ts +225 -0
- package/dist/utils/systemPromptNotes.js +340 -0
- package/dist/utils/systemPromptNotes.js.map +1 -0
- package/dist/utils/systemUtils.d.ts +49 -1
- package/dist/utils/systemUtils.js +67 -3
- package/dist/utils/systemUtils.js.map +1 -1
- package/dist/utils/toolMatching.d.ts +30 -0
- package/dist/utils/toolMatching.js +44 -0
- package/dist/utils/toolMatching.js.map +1 -0
- package/dist/utils/untrustedText.d.ts +66 -0
- package/dist/utils/untrustedText.js +80 -0
- package/dist/utils/untrustedText.js.map +1 -0
- package/package.json +22 -6
- package/schema/gsloth-config.schema.json +3134 -0
- package/dist/core/shell/allowlist.d.ts +0 -75
- package/dist/core/shell/allowlist.js +0 -187
- package/dist/core/shell/allowlist.js.map +0 -1
- package/dist/core/shell/judge.d.ts +0 -161
- package/dist/core/shell/judge.js +0 -261
- package/dist/core/shell/judge.js.map +0 -1
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module displayWidth
|
|
3
|
+
* The one place this repo answers "how many terminal COLUMNS does this string occupy, and where
|
|
4
|
+
* may I cut it". Everything that fits text to a terminal — the launch banner's field budgets, the
|
|
5
|
+
* tool-display caps — measures and slices through here.
|
|
6
|
+
*
|
|
7
|
+
* ## Why a code-point count is not a width
|
|
8
|
+
*
|
|
9
|
+
* `[...text].length` counts code points, which is right for UTF-16 safety and wrong for layout: a
|
|
10
|
+
* CJK ideograph or an emoji is ONE code point occupying TWO columns. Text measured that way reads
|
|
11
|
+
* as shorter than it renders, escapes whatever budget it was given, and wraps — and a wrapped
|
|
12
|
+
* continuation line starts back at column 0, which is precisely the failure the budgets exist to
|
|
13
|
+
* prevent. So the rule is: a value destined for a fixed column budget is measured with
|
|
14
|
+
* {@link displayWidth} and cut with {@link sliceToWidth} / {@link sliceEndToWidth}, never with
|
|
15
|
+
* `.length`, a spread, or `String.prototype.slice`.
|
|
16
|
+
*
|
|
17
|
+
* ## Why grapheme clusters are the cutting unit
|
|
18
|
+
*
|
|
19
|
+
* Slicing by code point is safe against halving a surrogate pair but not against halving a
|
|
20
|
+
* CLUSTER: a flag, a skin-toned or ZWJ-joined emoji, or a base letter plus its combining mark are
|
|
21
|
+
* several code points that a terminal draws as one glyph, and cutting between them produces
|
|
22
|
+
* mojibake or an orphaned mark. `Intl.Segmenter` gives the same cluster boundaries the width
|
|
23
|
+
* rules below are defined over, so the two agree by construction and a sliced string's width is
|
|
24
|
+
* exactly the sum of the widths of the clusters kept.
|
|
25
|
+
*
|
|
26
|
+
* ## What the slices expect: PLAIN text
|
|
27
|
+
*
|
|
28
|
+
* {@link displayWidth} is ANSI-aware and the slices are NOT, and that asymmetry is a contract
|
|
29
|
+
* rather than an oversight. An escape sequence is not one cluster — the terminal swallows it
|
|
30
|
+
* whole, but `ESC`, `[`, `3`, `5`, `m` segment as five, four of them printable — so the two
|
|
31
|
+
* disagree on an escape-bearing string and a slice can both under-fill its budget and cut inside
|
|
32
|
+
* a sequence. Feed the slices the text a user will read, and colour it afterwards; that is what
|
|
33
|
+
* every caller here does, since both render surfaces map a style tag to their own escapes at the
|
|
34
|
+
* very end. Making the slices ANSI-aware would change what a coloured preview line renders as,
|
|
35
|
+
* which is a decision for whoever needs it and not a silent detail of this module.
|
|
36
|
+
*
|
|
37
|
+
* That asymmetry is also why a slice decides "does the whole string fit?" two different ways. For
|
|
38
|
+
* plain text the cluster walk decides it: the widths of the clusters sum to the width of the
|
|
39
|
+
* string, so walking until the budget is blown answers the question and answers it WITHOUT
|
|
40
|
+
* touching the rest of the input — which is what keeps a megabyte-long preview line from being
|
|
41
|
+
* measured end to end before it is cut at column 200. Only escape-bearing text is measured whole
|
|
42
|
+
* first, because there the two rulers disagree and a coloured string that MEASURES as fitting must
|
|
43
|
+
* be handed back whole rather than cut short by the bytes of its own escapes.
|
|
44
|
+
*
|
|
45
|
+
* ## Why ambiguous-width characters stay NARROW — and the one place they must not
|
|
46
|
+
*
|
|
47
|
+
* `string-width` defaults to treating East-Asian "Ambiguous" characters as one column, and that
|
|
48
|
+
* default is load-bearing here rather than incidental: the sloth face is block elements, the
|
|
49
|
+
* wordmark is box-drawing, and `…` is U+2026 — all Ambiguous. Counting them as two columns would
|
|
50
|
+
* measure the 16-column face at 32 and shatter the layout it anchors. So {@link displayWidth} and
|
|
51
|
+
* {@link sliceToWidth} keep the default, and the specs pin the face at 16 and the wordmark at 19 so
|
|
52
|
+
* a change of that policy fails loudly instead of quietly doubling the art.
|
|
53
|
+
*
|
|
54
|
+
* That default is an **assumption about the reader's terminal**, and it is one this process cannot
|
|
55
|
+
* check: an Ambiguous character occupies one cell or two depending on how the terminal is
|
|
56
|
+
* configured, and several CJK locales — plus an option in xterm, urxvt and mlterm — choose two.
|
|
57
|
+
* For layout art that assumption is free, because being wrong only makes the art look wrong.
|
|
58
|
+
*
|
|
59
|
+
* It is **not** free where a budget is a security boundary. {@link maxDisplayWidth} and
|
|
60
|
+
* {@link sliceToMaxWidth} are the sanctioned exception: they measure Ambiguous as **two** columns,
|
|
61
|
+
* i.e. the widest a terminal can render the string, so text fitted with them fits under *either*
|
|
62
|
+
* policy. Use them wherever a row that overruns its budget would be wrapped by the terminal into a
|
|
63
|
+
* consequence rather than into an untidy screen — `core/shell/framing` frames untrusted text this
|
|
64
|
+
* way, because there a wrapped continuation line starts at column 0 and can forge a dialog's chrome.
|
|
65
|
+
* The cost is under-fill: on a terminal that does render Ambiguous narrow, such a row can stop short
|
|
66
|
+
* of its budget. Under-fill is cosmetic; overrun is not. True Wide characters (CJK ideographs,
|
|
67
|
+
* emoji, fullwidth forms) measure 2 under both, so the common CJK case is unaffected either way.
|
|
68
|
+
*/
|
|
69
|
+
import stringWidth from 'string-width';
|
|
70
|
+
/**
|
|
71
|
+
* Grapheme-cluster boundaries, i.e. what a terminal draws as one glyph. Built once: constructing
|
|
72
|
+
* an `Intl.Segmenter` is expensive relative to the short strings this module handles.
|
|
73
|
+
*/
|
|
74
|
+
const GRAPHEME_SEGMENTER = new Intl.Segmenter(undefined, { granularity: 'grapheme' });
|
|
75
|
+
/**
|
|
76
|
+
* Terminal columns `text` occupies. Zero-width clusters (combining marks, default-ignorables)
|
|
77
|
+
* count 0, wide clusters (CJK, emoji, fullwidth forms) count 2, everything else 1. ANSI escape
|
|
78
|
+
* sequences are not counted, so a pre-coloured string measures as what the user sees — but the
|
|
79
|
+
* slices below do not share that awareness, so do not read this as a licence to feed them one.
|
|
80
|
+
*/
|
|
81
|
+
export function displayWidth(text) {
|
|
82
|
+
return stringWidth(text);
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Terminal columns `text` occupies **at most** — the same measurement as {@link displayWidth} but
|
|
86
|
+
* counting East-Asian Ambiguous characters as two columns rather than one, which is the widest any
|
|
87
|
+
* terminal will render them.
|
|
88
|
+
*
|
|
89
|
+
* For a budget that must hold on a terminal whose ambiguous-width policy is unknown, this is the
|
|
90
|
+
* only sound ruler: it is the supremum over the policies a terminal can be configured with, so a
|
|
91
|
+
* string that fits under it fits under all of them. See the module docblock for when to reach for
|
|
92
|
+
* this rather than {@link displayWidth}.
|
|
93
|
+
*/
|
|
94
|
+
export function maxDisplayWidth(text) {
|
|
95
|
+
return stringWidth(text, { ambiguousIsNarrow: false });
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* The first grapheme cluster of `text`, or `''` when it is empty — i.e. the smallest piece a cut
|
|
99
|
+
* can leave behind, for a caller that has to make progress through a string one drawable glyph at
|
|
100
|
+
* a time.
|
|
101
|
+
*/
|
|
102
|
+
export function firstCluster(text) {
|
|
103
|
+
for (const { segment } of GRAPHEME_SEGMENTER.segment(text))
|
|
104
|
+
return segment;
|
|
105
|
+
return '';
|
|
106
|
+
}
|
|
107
|
+
/** The clusters of `text`, in order — the only unit either slice is allowed to cut between. */
|
|
108
|
+
function clusters(text) {
|
|
109
|
+
const out = [];
|
|
110
|
+
for (const { segment } of GRAPHEME_SEGMENTER.segment(text))
|
|
111
|
+
out.push(segment);
|
|
112
|
+
return out;
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Whether the whole-string measurement is the only ruler that can answer "does this fit" for
|
|
116
|
+
* `text` — true exactly when it carries an escape introducer (`ESC`, or the one-byte `CSI`), the
|
|
117
|
+
* two characters `string-width` itself strips on. On anything else the cluster widths sum to the
|
|
118
|
+
* whole-string width, so the walk decides the same question incrementally and a pre-measurement
|
|
119
|
+
* would be a second full pass over the input for nothing.
|
|
120
|
+
*/
|
|
121
|
+
function needsWholeStringMeasure(text) {
|
|
122
|
+
return text.includes('\u001B') || text.includes('\u009B');
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* The longest LEADING run of whole clusters whose total width is at most `maxWidth` — i.e. keep
|
|
126
|
+
* the head, lose the tail. Total (never throws): a non-positive `maxWidth` yields `''`.
|
|
127
|
+
*
|
|
128
|
+
* A cluster is kept only if it fits ENTIRELY, so the result can come back one column short of
|
|
129
|
+
* `maxWidth` when the next cluster is two columns wide. That is the point: half a wide glyph
|
|
130
|
+
* cannot be drawn, and spending the column anyway is how text over-runs its budget.
|
|
131
|
+
*
|
|
132
|
+
* The clusters are produced one at a time and the walk stops at the budget, so the cost is the
|
|
133
|
+
* length of the RESULT rather than the length of the input — the input here is a whole tool-output
|
|
134
|
+
* line, which is unbounded.
|
|
135
|
+
*/
|
|
136
|
+
export function sliceToWidth(text, maxWidth) {
|
|
137
|
+
return sliceHeadToWidth(text, maxWidth, displayWidth);
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* {@link sliceToWidth} measured by {@link maxDisplayWidth} — the head that fits the budget on any
|
|
141
|
+
* terminal, whatever it does with Ambiguous characters. The cut for a budget that must hold rather
|
|
142
|
+
* than merely look right.
|
|
143
|
+
*/
|
|
144
|
+
export function sliceToMaxWidth(text, maxWidth) {
|
|
145
|
+
return sliceHeadToWidth(text, maxWidth, maxDisplayWidth);
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* The head-slice both public cuts are made of, given the ruler to measure with. The ruler is passed
|
|
149
|
+
* rather than chosen here so the whole-string shortcut and the cluster walk can never end up on
|
|
150
|
+
* different ones — measuring the shortcut narrow and the walk wide would hand back a string that
|
|
151
|
+
* overruns the very budget the caller asked to be held to.
|
|
152
|
+
*/
|
|
153
|
+
function sliceHeadToWidth(text, maxWidth, measure) {
|
|
154
|
+
if (maxWidth <= 0)
|
|
155
|
+
return '';
|
|
156
|
+
if (needsWholeStringMeasure(text) && measure(text) <= maxWidth)
|
|
157
|
+
return text;
|
|
158
|
+
let width = 0;
|
|
159
|
+
let kept = '';
|
|
160
|
+
for (const { segment } of GRAPHEME_SEGMENTER.segment(text)) {
|
|
161
|
+
const clusterWidth = measure(segment);
|
|
162
|
+
if (width + clusterWidth > maxWidth)
|
|
163
|
+
break;
|
|
164
|
+
width += clusterWidth;
|
|
165
|
+
kept += segment;
|
|
166
|
+
}
|
|
167
|
+
return kept;
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* The longest TRAILING run of whole clusters whose total width is at most `maxWidth` — i.e. keep
|
|
171
|
+
* the tail, lose the head. The mirror of {@link sliceToWidth}, for values whose end is the
|
|
172
|
+
* informative part (a path's leaf directory).
|
|
173
|
+
*
|
|
174
|
+
* This one materialises the clusters: it walks backwards, and cluster boundaries are only
|
|
175
|
+
* derivable from the front. Its callers pass a path or a model id, so the input is a line rather
|
|
176
|
+
* than a file.
|
|
177
|
+
*/
|
|
178
|
+
export function sliceEndToWidth(text, maxWidth) {
|
|
179
|
+
if (maxWidth <= 0)
|
|
180
|
+
return '';
|
|
181
|
+
if (needsWholeStringMeasure(text) && displayWidth(text) <= maxWidth)
|
|
182
|
+
return text;
|
|
183
|
+
const all = clusters(text);
|
|
184
|
+
let width = 0;
|
|
185
|
+
let kept = '';
|
|
186
|
+
for (let index = all.length - 1; index >= 0; index--) {
|
|
187
|
+
const clusterWidth = displayWidth(all[index]);
|
|
188
|
+
if (width + clusterWidth > maxWidth)
|
|
189
|
+
break;
|
|
190
|
+
width += clusterWidth;
|
|
191
|
+
kept = all[index] + kept;
|
|
192
|
+
}
|
|
193
|
+
return kept;
|
|
194
|
+
}
|
|
195
|
+
//# sourceMappingURL=displayWidth.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"displayWidth.js","sourceRoot":"","sources":["../../src/utils/displayWidth.ts"],"names":[],"mappings":"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"}
|
|
@@ -60,11 +60,33 @@ export declare function readMultipleFilesFromProjectDir(fileNames: string | stri
|
|
|
60
60
|
* package dir.
|
|
61
61
|
*/
|
|
62
62
|
export declare function readFileFromInstallDir(filePath: string, packageDir?: string): string;
|
|
63
|
-
|
|
63
|
+
/**
|
|
64
|
+
* No-clobber write: writes `content` only when `filePath` does not already exist.
|
|
65
|
+
* @returns `true` when the file was written, `false` when it was skipped because it
|
|
66
|
+
* already existed. Callers use the return value to avoid claiming success on a skip.
|
|
67
|
+
*/
|
|
68
|
+
export declare function writeFileIfNotExistsWithMessages(filePath: string, content: string): boolean;
|
|
69
|
+
/**
|
|
70
|
+
* Unconditional write: writes (or overwrites) `content` at `filePath`, creating parent
|
|
71
|
+
* directories as needed. Use this only for the config-overwrite path (an explicit user /
|
|
72
|
+
* `--force` decision); the no-clobber {@link writeFileIfNotExistsWithMessages} still guards
|
|
73
|
+
* user-editable preamble files (guidelines / review).
|
|
74
|
+
*/
|
|
75
|
+
export declare function writeFileWithMessages(filePath: string, content: string): void;
|
|
76
|
+
/**
|
|
77
|
+
* Config-file write that honours an overwrite flag.
|
|
78
|
+
* - `force === true` → always (over)writes.
|
|
79
|
+
* - `force === false` → no-clobber (skips + warns when the file already exists).
|
|
80
|
+
* @returns `true` when a write happened, `false` when it was skipped.
|
|
81
|
+
*/
|
|
82
|
+
export declare function writeConfigFileWithMessages(filePath: string, content: string, force?: boolean): boolean;
|
|
64
83
|
export declare function appendToFile(filePath: string, content: string): void;
|
|
65
84
|
export declare function readFileSyncWithMessages(filePath: string, errorMessageIn?: string, noFileMessage?: string): string;
|
|
66
85
|
/**
|
|
67
|
-
* Dynamically imports a module from a file path from the outside of the installation dir
|
|
86
|
+
* Dynamically imports a module from a file path from the outside of the installation dir.
|
|
87
|
+
* `.ts` modules are loaded through jiti (Node's native dynamic `import()` cannot load
|
|
88
|
+
* TypeScript), so `.gsloth.config.ts` honours the same async `configure()` contract as
|
|
89
|
+
* `.js`/`.mjs`. All other extensions use native dynamic import.
|
|
68
90
|
* @returns A promise that resolves to the imported module
|
|
69
91
|
*/
|
|
70
92
|
export declare function importExternalFile(filePath: string): Promise<Record<string, any>>;
|
package/dist/utils/fileUtils.js
CHANGED
|
@@ -1,17 +1,18 @@
|
|
|
1
1
|
import { appendFileSync, existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
2
2
|
import { dirname, resolve } from 'node:path';
|
|
3
3
|
import { fileURLToPath } from 'node:url';
|
|
4
|
-
import {
|
|
4
|
+
import { getProjectDir } from '#src/utils/systemUtils.js';
|
|
5
5
|
import { GSLOTH_DIR, GSLOTH_SETTINGS_DIR } from '#src/constants.js';
|
|
6
6
|
import { displayError, displayInfo, displaySuccess, displayWarning, } from '#src/utils/consoleUtils.js';
|
|
7
7
|
import { wrapContent } from '#src/utils/llmUtils.js';
|
|
8
8
|
import url from 'node:url';
|
|
9
|
+
import { createJiti } from 'jiti';
|
|
9
10
|
/**
|
|
10
11
|
* Checks if .gsloth directory exists in the project root
|
|
11
12
|
* @returns Boolean indicating whether .gsloth directory exists
|
|
12
13
|
*/
|
|
13
14
|
export function gslothDirExists() {
|
|
14
|
-
const currentDir =
|
|
15
|
+
const currentDir = getProjectDir();
|
|
15
16
|
const gslothDirPath = resolve(currentDir, GSLOTH_DIR);
|
|
16
17
|
return existsSync(gslothDirPath);
|
|
17
18
|
}
|
|
@@ -21,7 +22,7 @@ export function gslothDirExists() {
|
|
|
21
22
|
* @returns The resolved path where the file should be written
|
|
22
23
|
*/
|
|
23
24
|
export function getGslothFilePath(filename) {
|
|
24
|
-
const currentDir =
|
|
25
|
+
const currentDir = getProjectDir();
|
|
25
26
|
if (gslothDirExists()) {
|
|
26
27
|
const gslothDirPath = resolve(currentDir, GSLOTH_DIR);
|
|
27
28
|
return resolve(gslothDirPath, filename);
|
|
@@ -40,7 +41,7 @@ export function getGslothFilePath(filename) {
|
|
|
40
41
|
* @returns The resolved path where the configuration file should be written
|
|
41
42
|
*/
|
|
42
43
|
export function getGslothConfigWritePath(filename) {
|
|
43
|
-
const currentDir =
|
|
44
|
+
const currentDir = getProjectDir();
|
|
44
45
|
if (gslothDirExists()) {
|
|
45
46
|
const gslothDirPath = resolve(currentDir, GSLOTH_DIR);
|
|
46
47
|
const gslothSettingsPath = resolve(gslothDirPath, GSLOTH_SETTINGS_DIR);
|
|
@@ -59,10 +60,10 @@ export function getGslothConfigWritePath(filename) {
|
|
|
59
60
|
* @returns The resolved path where the configuration file should be found
|
|
60
61
|
*/
|
|
61
62
|
export function getGslothConfigReadPath(filename, identityProfileRaw) {
|
|
62
|
-
const
|
|
63
|
+
const baseDir = getProjectDir();
|
|
63
64
|
const identityProfile = identityProfileRaw?.trim();
|
|
64
65
|
if (gslothDirExists()) {
|
|
65
|
-
const gslothDirPath = resolve(
|
|
66
|
+
const gslothDirPath = resolve(baseDir, GSLOTH_DIR);
|
|
66
67
|
const gslothSettingsPath = resolve(gslothDirPath, GSLOTH_SETTINGS_DIR);
|
|
67
68
|
const configPath = identityProfile
|
|
68
69
|
? resolve(gslothSettingsPath, identityProfile, filename)
|
|
@@ -71,7 +72,7 @@ export function getGslothConfigReadPath(filename, identityProfileRaw) {
|
|
|
71
72
|
return configPath;
|
|
72
73
|
}
|
|
73
74
|
}
|
|
74
|
-
return resolve(
|
|
75
|
+
return resolve(baseDir, filename);
|
|
75
76
|
}
|
|
76
77
|
/**
|
|
77
78
|
* Resolve an explicit output path string to an absolute file path.
|
|
@@ -80,7 +81,7 @@ export function getGslothConfigReadPath(filename, identityProfileRaw) {
|
|
|
80
81
|
* - If it's a bare filename, place it under .gsloth/ when present, otherwise project root.
|
|
81
82
|
*/
|
|
82
83
|
export function resolveOutputPath(writeOutputToFile) {
|
|
83
|
-
const currentDir =
|
|
84
|
+
const currentDir = getProjectDir();
|
|
84
85
|
const provided = String(writeOutputToFile).trim();
|
|
85
86
|
// Detect if provided path contains path separators (cross-platform)
|
|
86
87
|
const hasSeparator = provided.includes('/') || provided.includes('\\');
|
|
@@ -125,7 +126,7 @@ export function generateStandardFileName(command) {
|
|
|
125
126
|
return `gth_${dateTimeStr}_${commandStr}.md`;
|
|
126
127
|
}
|
|
127
128
|
export function readFileFromProjectDir(fileName) {
|
|
128
|
-
const currentDir =
|
|
129
|
+
const currentDir = getProjectDir();
|
|
129
130
|
const filePath = resolve(currentDir, fileName);
|
|
130
131
|
displayInfo(`Reading file ${filePath}...`);
|
|
131
132
|
return readFileSyncWithMessages(filePath);
|
|
@@ -162,6 +163,11 @@ export function readFileFromInstallDir(filePath, packageDir = corePackageDir) {
|
|
|
162
163
|
throw readFromInstallDirError;
|
|
163
164
|
}
|
|
164
165
|
}
|
|
166
|
+
/**
|
|
167
|
+
* No-clobber write: writes `content` only when `filePath` does not already exist.
|
|
168
|
+
* @returns `true` when the file was written, `false` when it was skipped because it
|
|
169
|
+
* already existed. Callers use the return value to avoid claiming success on a skip.
|
|
170
|
+
*/
|
|
165
171
|
export function writeFileIfNotExistsWithMessages(filePath, content) {
|
|
166
172
|
displayInfo(`checking ${filePath} existence`);
|
|
167
173
|
if (!existsSync(filePath)) {
|
|
@@ -172,10 +178,38 @@ export function writeFileIfNotExistsWithMessages(filePath, content) {
|
|
|
172
178
|
}
|
|
173
179
|
writeFileSync(filePath, content);
|
|
174
180
|
displaySuccess(`Created ${filePath}`);
|
|
181
|
+
return true;
|
|
182
|
+
}
|
|
183
|
+
displayWarning(`${filePath} already exists`);
|
|
184
|
+
return false;
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Unconditional write: writes (or overwrites) `content` at `filePath`, creating parent
|
|
188
|
+
* directories as needed. Use this only for the config-overwrite path (an explicit user /
|
|
189
|
+
* `--force` decision); the no-clobber {@link writeFileIfNotExistsWithMessages} still guards
|
|
190
|
+
* user-editable preamble files (guidelines / review).
|
|
191
|
+
*/
|
|
192
|
+
export function writeFileWithMessages(filePath, content) {
|
|
193
|
+
const parentDir = dirname(filePath);
|
|
194
|
+
if (!existsSync(parentDir)) {
|
|
195
|
+
mkdirSync(parentDir, { recursive: true });
|
|
175
196
|
}
|
|
176
|
-
|
|
177
|
-
|
|
197
|
+
const existed = existsSync(filePath);
|
|
198
|
+
writeFileSync(filePath, content);
|
|
199
|
+
displaySuccess(existed ? `Overwrote ${filePath}` : `Created ${filePath}`);
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* Config-file write that honours an overwrite flag.
|
|
203
|
+
* - `force === true` → always (over)writes.
|
|
204
|
+
* - `force === false` → no-clobber (skips + warns when the file already exists).
|
|
205
|
+
* @returns `true` when a write happened, `false` when it was skipped.
|
|
206
|
+
*/
|
|
207
|
+
export function writeConfigFileWithMessages(filePath, content, force = false) {
|
|
208
|
+
if (force) {
|
|
209
|
+
writeFileWithMessages(filePath, content);
|
|
210
|
+
return true;
|
|
178
211
|
}
|
|
212
|
+
return writeFileIfNotExistsWithMessages(filePath, content);
|
|
179
213
|
}
|
|
180
214
|
export function appendToFile(filePath, content) {
|
|
181
215
|
try {
|
|
@@ -206,11 +240,19 @@ export function readFileSyncWithMessages(filePath, errorMessageIn, noFileMessage
|
|
|
206
240
|
}
|
|
207
241
|
}
|
|
208
242
|
/**
|
|
209
|
-
* Dynamically imports a module from a file path from the outside of the installation dir
|
|
243
|
+
* Dynamically imports a module from a file path from the outside of the installation dir.
|
|
244
|
+
* `.ts` modules are loaded through jiti (Node's native dynamic `import()` cannot load
|
|
245
|
+
* TypeScript), so `.gsloth.config.ts` honours the same async `configure()` contract as
|
|
246
|
+
* `.js`/`.mjs`. All other extensions use native dynamic import.
|
|
210
247
|
* @returns A promise that resolves to the imported module
|
|
211
248
|
*/
|
|
212
249
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
213
250
|
export function importExternalFile(filePath) {
|
|
251
|
+
if (filePath.endsWith('.ts')) {
|
|
252
|
+
const jiti = createJiti(import.meta.url);
|
|
253
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
254
|
+
return jiti.import(filePath);
|
|
255
|
+
}
|
|
214
256
|
const configFileUrl = url.pathToFileURL(filePath).toString();
|
|
215
257
|
return import(configFileUrl);
|
|
216
258
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fileUtils.js","sourceRoot":"","sources":["../../src/utils/fileUtils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC7F,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"fileUtils.js","sourceRoot":"","sources":["../../src/utils/fileUtils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC7F,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAC1D,OAAO,EAAE,UAAU,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AACpE,OAAO,EACL,YAAY,EACZ,WAAW,EACX,cAAc,EACd,cAAc,GACf,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACrD,OAAO,GAAG,MAAM,UAAU,CAAC;AAC3B,OAAO,EAAE,UAAU,EAAE,MAAM,MAAM,CAAC;AAElC;;;GAGG;AACH,MAAM,UAAU,eAAe;IAC7B,MAAM,UAAU,GAAG,aAAa,EAAE,CAAC;IACnC,MAAM,aAAa,GAAG,OAAO,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC;IACtD,OAAO,UAAU,CAAC,aAAa,CAAC,CAAC;AACnC,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,iBAAiB,CAAC,QAAgB;IAChD,MAAM,UAAU,GAAG,aAAa,EAAE,CAAC;IAEnC,IAAI,eAAe,EAAE,EAAE,CAAC;QACtB,MAAM,aAAa,GAAG,OAAO,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC;QACtD,OAAO,OAAO,CAAC,aAAa,EAAE,QAAQ,CAAC,CAAC;IAC1C,CAAC;IAED,OAAO,OAAO,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;AACvC,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,wBAAwB,CAAC,QAAgB;IACvD,MAAM,UAAU,GAAG,aAAa,EAAE,CAAC;IAEnC,IAAI,eAAe,EAAE,EAAE,CAAC;QACtB,MAAM,aAAa,GAAG,OAAO,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC;QACtD,MAAM,kBAAkB,GAAG,OAAO,CAAC,aAAa,EAAE,mBAAmB,CAAC,CAAC;QAEvE,wDAAwD;QACxD,IAAI,CAAC,UAAU,CAAC,kBAAkB,CAAC,EAAE,CAAC;YACpC,SAAS,CAAC,kBAAkB,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACrD,CAAC;QAED,OAAO,OAAO,CAAC,kBAAkB,EAAE,QAAQ,CAAC,CAAC;IAC/C,CAAC;IAED,OAAO,OAAO,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;AACvC,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,uBAAuB,CACrC,QAAgB,EAChB,kBAAsC;IAEtC,MAAM,OAAO,GAAG,aAAa,EAAE,CAAC;IAChC,MAAM,eAAe,GAAG,kBAAkB,EAAE,IAAI,EAAE,CAAC;IACnD,IAAI,eAAe,EAAE,EAAE,CAAC;QACtB,MAAM,aAAa,GAAG,OAAO,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;QACnD,MAAM,kBAAkB,GAAG,OAAO,CAAC,aAAa,EAAE,mBAAmB,CAAC,CAAC;QACvE,MAAM,UAAU,GAAG,eAAe;YAChC,CAAC,CAAC,OAAO,CAAC,kBAAkB,EAAE,eAAe,EAAE,QAAQ,CAAC;YACxD,CAAC,CAAC,OAAO,CAAC,kBAAkB,EAAE,QAAQ,CAAC,CAAC;QAE1C,IAAI,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;YAC3B,OAAO,UAAU,CAAC;QACpB,CAAC;IACH,CAAC;IAED,OAAO,OAAO,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;AACpC,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,iBAAiB,CAAC,iBAAyB;IACzD,MAAM,UAAU,GAAG,aAAa,EAAE,CAAC;IACnC,MAAM,QAAQ,GAAG,MAAM,CAAC,iBAAiB,CAAC,CAAC,IAAI,EAAE,CAAC;IAElD,oEAAoE;IACpE,MAAM,YAAY,GAAG,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;IAEvE,yEAAyE;IACzE,IAAI,CAAC,YAAY,EAAE,CAAC;QAClB,OAAO,iBAAiB,CAAC,QAAQ,CAAC,CAAC;IACrC,CAAC;IAED,qEAAqE;IACrE,MAAM,YAAY,GAAG,OAAO,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;IACnD,MAAM,SAAS,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC;IACxC,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;QAC3B,SAAS,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC5C,CAAC;IACD,OAAO,YAAY,CAAC;AACtB,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,MAAc;IAC7C,OAAO,MAAM,CAAC,OAAO,CAAC,eAAe,EAAE,GAAG,CAAC,CAAC;AAC9C,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,iBAAiB;IAC/B,MAAM,IAAI,GAAG,IAAI,IAAI,EAAE,CAAC;IAExB,wDAAwD;IACxD,MAAM,IAAI,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;IAChC,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IAC3D,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IACpD,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IACvD,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IAC3D,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IAE3D,OAAO,GAAG,IAAI,IAAI,KAAK,IAAI,GAAG,IAAI,KAAK,IAAI,OAAO,IAAI,OAAO,EAAE,CAAC;AAClE,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,wBAAwB,CAAC,OAAe;IACtD,MAAM,WAAW,GAAG,iBAAiB,EAAE,CAAC;IACxC,MAAM,UAAU,GAAG,gBAAgB,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC;IAE3D,OAAO,OAAO,WAAW,IAAI,UAAU,KAAK,CAAC;AAC/C,CAAC;AAED,MAAM,UAAU,sBAAsB,CAAC,QAAgB;IACrD,MAAM,UAAU,GAAG,aAAa,EAAE,CAAC;IACnC,MAAM,QAAQ,GAAG,OAAO,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;IAC/C,WAAW,CAAC,gBAAgB,QAAQ,KAAK,CAAC,CAAC;IAC3C,OAAO,wBAAwB,CAAC,QAAQ,CAAC,CAAC;AAC5C,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,+BAA+B,CAAC,SAA4B;IAC1E,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,CAAC;QAC9B,OAAO,WAAW,CAAC,sBAAsB,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,QAAQ,SAAS,EAAE,EAAE,IAAI,CAAC,CAAC;IAC3F,CAAC;IAED,OAAO,SAAS;SACb,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE;QAChB,MAAM,OAAO,GAAG,sBAAsB,CAAC,QAAQ,CAAC,CAAC;QACjD,OAAO,GAAG,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,QAAQ,EAAE,EAAE,IAAI,CAAC,EAAE,CAAC;IACrE,CAAC,CAAC;SACD,IAAI,CAAC,MAAM,CAAC,CAAC;AAClB,CAAC;AAED,MAAM,cAAc,GAAG,OAAO,CAAC,OAAO,CAAC,aAAa,CAAC,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;AAEpF;;;;GAIG;AACH,MAAM,UAAU,sBAAsB,CACpC,QAAgB,EAChB,UAAU,GAAW,cAAc;IAEnC,MAAM,eAAe,GAAG,OAAO,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;IACtD,IAAI,CAAC;QACH,OAAO,YAAY,CAAC,eAAe,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAC;IAC7D,CAAC;IAAC,OAAO,uBAAuB,EAAE,CAAC;QACjC,YAAY,CAAC,OAAO,eAAe,+BAA+B,CAAC,CAAC;QACpE,MAAM,uBAAuB,CAAC;IAChC,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,gCAAgC,CAAC,QAAgB,EAAE,OAAe;IAChF,WAAW,CAAC,YAAY,QAAQ,YAAY,CAAC,CAAC;IAC9C,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC1B,gDAAgD;QAChD,MAAM,SAAS,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;QACpC,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;YAC3B,SAAS,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC5C,CAAC;QACD,aAAa,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QACjC,cAAc,CAAC,WAAW,QAAQ,EAAE,CAAC,CAAC;QACtC,OAAO,IAAI,CAAC;IACd,CAAC;IACD,cAAc,CAAC,GAAG,QAAQ,iBAAiB,CAAC,CAAC;IAC7C,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,qBAAqB,CAAC,QAAgB,EAAE,OAAe;IACrE,MAAM,SAAS,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;IACpC,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;QAC3B,SAAS,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC5C,CAAC;IACD,MAAM,OAAO,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC;IACrC,aAAa,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IACjC,cAAc,CAAC,OAAO,CAAC,CAAC,CAAC,aAAa,QAAQ,EAAE,CAAC,CAAC,CAAC,WAAW,QAAQ,EAAE,CAAC,CAAC;AAC5E,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,2BAA2B,CACzC,QAAgB,EAChB,OAAe,EACf,KAAK,GAAG,KAAK;IAEb,IAAI,KAAK,EAAE,CAAC;QACV,qBAAqB,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QACzC,OAAO,IAAI,CAAC;IACd,CAAC;IACD,OAAO,gCAAgC,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;AAC7D,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,QAAgB,EAAE,OAAe;IAC5D,IAAI,CAAC;QACH,MAAM,SAAS,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;QACpC,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;YAC3B,SAAS,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC5C,CAAC;QACD,cAAc,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IACpC,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,YAAY,CAAC,4BAA4B,QAAQ,KAAM,CAAW,CAAC,OAAO,EAAE,CAAC,CAAC;IAChF,CAAC;AACH,CAAC;AAED,MAAM,UAAU,wBAAwB,CACtC,QAAgB,EAChB,cAAuB,EACvB,aAAsB;IAEtB,MAAM,YAAY,GAAG,cAAc,IAAI,yBAAyB,CAAC;IACjE,IAAI,CAAC;QACH,OAAO,YAAY,CAAC,QAAQ,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAC;IACtD,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,YAAY,CAAC,YAAY,GAAG,QAAQ,CAAC,CAAC;QACtC,IAAK,KAA+B,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YACvD,cAAc,CAAC,aAAa,IAAI,gCAAgC,CAAC,CAAC;QACpE,CAAC;aAAM,CAAC;YACN,YAAY,CAAE,KAAe,CAAC,OAAO,CAAC,CAAC;QACzC,CAAC;QACD,MAAM,KAAK,CAAC;IACd,CAAC;AACH,CAAC;AAED;;;;;;GAMG;AACH,8DAA8D;AAC9D,MAAM,UAAU,kBAAkB,CAAC,QAAgB;IACjD,IAAI,QAAQ,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;QAC7B,MAAM,IAAI,GAAG,UAAU,CAAC,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC;QACzC,8DAA8D;QAC9D,OAAO,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAiC,CAAC;IAC/D,CAAC;IACD,MAAM,aAAa,GAAG,GAAG,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC,QAAQ,EAAE,CAAC;IAC7D,OAAO,MAAM,CAAC,aAAa,CAAC,CAAC;AAC/B,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,wBAAwB,CACtC,MAA+C,EAC/C,MAAc;IAEd,MAAM,OAAO,GAAG,MAAM,CAAC,iBAAiB,CAAC;IAEzC,IAAI,OAAO,KAAK,KAAK,EAAE,CAAC;QACtB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;QAChC,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC;QAC/B,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,IAAI,CAAC;QACtC,OAAO,iBAAiB,CAAC,OAAO,CAAC,CAAC;IACpC,CAAC;IAED,6EAA6E;IAC7E,MAAM,QAAQ,GAAG,wBAAwB,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC,CAAC;IAChE,OAAO,iBAAiB,CAAC,QAAQ,CAAC,CAAC;AACrC,CAAC"}
|
package/dist/utils/llmUtils.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { RunnableConfig } from '@langchain/core/runnables';
|
|
2
|
-
import { GthConfig } from '#src/config.js';
|
|
2
|
+
import { GthConfig, PromptSegmentName } from '#src/config.js';
|
|
3
|
+
import type { GthCommand } from '#src/core/types.js';
|
|
3
4
|
import { SystemMessage } from '@langchain/core/messages';
|
|
4
5
|
/**
|
|
5
6
|
* Creates new runnable config.
|
|
@@ -8,14 +9,43 @@ import { SystemMessage } from '@langchain/core/messages';
|
|
|
8
9
|
* and in another prototype project where I was importing Gaunt Sloth.
|
|
9
10
|
*/
|
|
10
11
|
export declare function getNewRunnableConfig(recursionLimit?: number): RunnableConfig;
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
12
|
+
/** The config slice every prompt-segment read needs. */
|
|
13
|
+
type PromptReadConfig = Pick<GthConfig, 'prompts' | 'identityProfile' | 'noDefaultPrompts'>;
|
|
14
|
+
/**
|
|
15
|
+
* GS2-43 — the single composition point for one prompt segment, honouring the segment's
|
|
16
|
+
* `prompts.<segment>` config:
|
|
17
|
+
* - no setting → the segment's default-named file ({@link PROMPT_SEGMENT_FILES}), falling back
|
|
18
|
+
* to the bundled default unless `noDefaultPrompts` — exactly the pre-GS2-43 behaviour;
|
|
19
|
+
* - a `string` → shorthand for `{ path }`;
|
|
20
|
+
* - `enabled: false` → the segment is dropped entirely (returns `''`), even its bundled default;
|
|
21
|
+
* - `path` + `mode: 'replace'` (default) → the file replaces the built-in segment content;
|
|
22
|
+
* - `path` + `mode: 'append'` → the file content is appended after the built-in content.
|
|
23
|
+
*/
|
|
24
|
+
export declare function readPromptSegment(segment: PromptSegmentName, config: PromptReadConfig): string;
|
|
25
|
+
export declare function readBackstory(config: PromptReadConfig): string;
|
|
26
|
+
export declare function readGuidelines(config: Pick<GthConfig, 'prompts' | 'includeCurrentDateAfterGuidelines' | 'organization' | 'identityProfile' | 'noDefaultPrompts'> | string): string;
|
|
27
|
+
export declare function readReviewInstructions(config: PromptReadConfig | string): string;
|
|
28
|
+
export declare function readSystemPrompt(config: PromptReadConfig): string;
|
|
29
|
+
export declare function readChatPrompt(config: PromptReadConfig): string;
|
|
16
30
|
export declare function buildSystemMessages(config: GthConfig, modePrompt?: string | null): SystemMessage[];
|
|
17
|
-
export declare function readCodePrompt(config:
|
|
18
|
-
export declare function readExecPrompt(config:
|
|
31
|
+
export declare function readCodePrompt(config: PromptReadConfig): string;
|
|
32
|
+
export declare function readExecPrompt(config: PromptReadConfig): string;
|
|
33
|
+
/**
|
|
34
|
+
* GS2-79 — the SINGLE place a command's mode prompt is chosen, for every site that composes a
|
|
35
|
+
* system prompt via {@link buildSystemMessages}: both agent backends and the subagent profiles.
|
|
36
|
+
*
|
|
37
|
+
* It exists because the selection used to be an inline three-branch ternary copied to each of
|
|
38
|
+
* those sites, and a command missing from one copy is silently served the CHAT prompt — the
|
|
39
|
+
* default branch — rather than failing. That is how `review`/`pr` came to compose the chat prompt
|
|
40
|
+
* while the review instructions were smuggled in as a caller-side leading `SystemMessage`, which
|
|
41
|
+
* Anthropic rejects outright ("System messages are only permitted as the first passed message").
|
|
42
|
+
* One function means a new command is wired once, and `review`/`pr` cannot silently fall back to
|
|
43
|
+
* chat again.
|
|
44
|
+
*
|
|
45
|
+
* `review`/`pr` resolve to the REVIEW INSTRUCTIONS (`.gsloth.review.md`), which is what makes a
|
|
46
|
+
* review a review; every command without a mode prompt of its own keeps the chat prompt.
|
|
47
|
+
*/
|
|
48
|
+
export declare function readModePrompt(command: GthCommand | undefined, config: PromptReadConfig): string;
|
|
19
49
|
/**
|
|
20
50
|
* Read a prompt file from the project config dir (honouring identity profiles), falling back
|
|
21
51
|
* to a packaged default unless `noDefaultPrompts` is set. Downstream packages owning their own
|
|
@@ -45,3 +75,4 @@ export declare function formatToolCalls(toolCalls: Array<{
|
|
|
45
75
|
name: string;
|
|
46
76
|
args?: Record<string, unknown>;
|
|
47
77
|
}>, maxLength?: number): string;
|
|
78
|
+
export {};
|
package/dist/utils/llmUtils.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { randomUUID } from 'node:crypto';
|
|
2
|
-
import { GSLOTH_BACKSTORY, GSLOTH_CHAT_PROMPT, GSLOTH_CODE_PROMPT, GSLOTH_EXEC_PROMPT, GSLOTH_SYSTEM_PROMPT, } from '#src/constants.js';
|
|
2
|
+
import { GSLOTH_BACKSTORY, GSLOTH_CHAT_PROMPT, GSLOTH_CODE_PROMPT, GSLOTH_EXEC_PROMPT, GSLOTH_SYSTEM_PROMPT, PROJECT_GUIDELINES, PROJECT_REVIEW_INSTRUCTIONS, } from '#src/constants.js';
|
|
3
3
|
import { getGslothConfigReadPath, readFileFromInstallDir } from '#src/utils/fileUtils.js';
|
|
4
4
|
import { existsSync, readFileSync } from 'node:fs';
|
|
5
5
|
import { debugLog } from '#src/utils/debugUtils.js';
|
|
@@ -17,14 +17,54 @@ export function getNewRunnableConfig(recursionLimit = 1000) {
|
|
|
17
17
|
configurable: { thread_id: randomUUID() },
|
|
18
18
|
};
|
|
19
19
|
}
|
|
20
|
+
/**
|
|
21
|
+
* GS2-43 — each prompt segment's default-named file. The `prompts.<segment>` config retargets,
|
|
22
|
+
* disables, or composes against these; with no config the segment resolves exactly as before
|
|
23
|
+
* (config-dir/project file of this name, else the bundled default).
|
|
24
|
+
*/
|
|
25
|
+
const PROMPT_SEGMENT_FILES = {
|
|
26
|
+
backstory: GSLOTH_BACKSTORY,
|
|
27
|
+
guidelines: PROJECT_GUIDELINES,
|
|
28
|
+
system: GSLOTH_SYSTEM_PROMPT,
|
|
29
|
+
chat: GSLOTH_CHAT_PROMPT,
|
|
30
|
+
code: GSLOTH_CODE_PROMPT,
|
|
31
|
+
exec: GSLOTH_EXEC_PROMPT,
|
|
32
|
+
review: PROJECT_REVIEW_INSTRUCTIONS,
|
|
33
|
+
};
|
|
34
|
+
/**
|
|
35
|
+
* GS2-43 — the single composition point for one prompt segment, honouring the segment's
|
|
36
|
+
* `prompts.<segment>` config:
|
|
37
|
+
* - no setting → the segment's default-named file ({@link PROMPT_SEGMENT_FILES}), falling back
|
|
38
|
+
* to the bundled default unless `noDefaultPrompts` — exactly the pre-GS2-43 behaviour;
|
|
39
|
+
* - a `string` → shorthand for `{ path }`;
|
|
40
|
+
* - `enabled: false` → the segment is dropped entirely (returns `''`), even its bundled default;
|
|
41
|
+
* - `path` + `mode: 'replace'` (default) → the file replaces the built-in segment content;
|
|
42
|
+
* - `path` + `mode: 'append'` → the file content is appended after the built-in content.
|
|
43
|
+
*/
|
|
44
|
+
export function readPromptSegment(segment, config) {
|
|
45
|
+
const setting = config.prompts?.[segment];
|
|
46
|
+
const segmentConfig = typeof setting === 'string' ? { path: setting } : (setting ?? {});
|
|
47
|
+
if (segmentConfig.enabled === false) {
|
|
48
|
+
return '';
|
|
49
|
+
}
|
|
50
|
+
const readBuiltIn = () => readPromptFile(PROMPT_SEGMENT_FILES[segment], config.identityProfile, config.noDefaultPrompts);
|
|
51
|
+
if (!segmentConfig.path) {
|
|
52
|
+
return readBuiltIn();
|
|
53
|
+
}
|
|
54
|
+
const fileContent = readPromptFile(segmentConfig.path, config.identityProfile, config.noDefaultPrompts);
|
|
55
|
+
if (segmentConfig.mode === 'append') {
|
|
56
|
+
return [readBuiltIn(), fileContent].filter(Boolean).join('\n');
|
|
57
|
+
}
|
|
58
|
+
return fileContent;
|
|
59
|
+
}
|
|
20
60
|
export function readBackstory(config) {
|
|
21
|
-
return
|
|
61
|
+
return readPromptSegment('backstory', config);
|
|
22
62
|
}
|
|
23
63
|
export function readGuidelines(config) {
|
|
24
64
|
if (typeof config === 'string') {
|
|
25
65
|
return readPromptFile(config, undefined);
|
|
26
66
|
}
|
|
27
|
-
const guidelines =
|
|
67
|
+
const guidelines = readPromptSegment('guidelines', config);
|
|
28
68
|
if (config.includeCurrentDateAfterGuidelines) {
|
|
29
69
|
const currentDate = new Date();
|
|
30
70
|
const orgName = config.organization?.name;
|
|
@@ -51,13 +91,13 @@ export function readReviewInstructions(config) {
|
|
|
51
91
|
if (typeof config === 'string') {
|
|
52
92
|
return readPromptFile(config, undefined);
|
|
53
93
|
}
|
|
54
|
-
return
|
|
94
|
+
return readPromptSegment('review', config);
|
|
55
95
|
}
|
|
56
96
|
export function readSystemPrompt(config) {
|
|
57
|
-
return
|
|
97
|
+
return readPromptSegment('system', config);
|
|
58
98
|
}
|
|
59
99
|
export function readChatPrompt(config) {
|
|
60
|
-
return
|
|
100
|
+
return readPromptSegment('chat', config);
|
|
61
101
|
}
|
|
62
102
|
export function buildSystemMessages(config, modePrompt) {
|
|
63
103
|
const parts = [readBackstory(config), readGuidelines(config)];
|
|
@@ -70,10 +110,38 @@ export function buildSystemMessages(config, modePrompt) {
|
|
|
70
110
|
return content.trim() ? [new SystemMessage(content)] : [];
|
|
71
111
|
}
|
|
72
112
|
export function readCodePrompt(config) {
|
|
73
|
-
return
|
|
113
|
+
return readPromptSegment('code', config);
|
|
74
114
|
}
|
|
75
115
|
export function readExecPrompt(config) {
|
|
76
|
-
return
|
|
116
|
+
return readPromptSegment('exec', config);
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* GS2-79 — the SINGLE place a command's mode prompt is chosen, for every site that composes a
|
|
120
|
+
* system prompt via {@link buildSystemMessages}: both agent backends and the subagent profiles.
|
|
121
|
+
*
|
|
122
|
+
* It exists because the selection used to be an inline three-branch ternary copied to each of
|
|
123
|
+
* those sites, and a command missing from one copy is silently served the CHAT prompt — the
|
|
124
|
+
* default branch — rather than failing. That is how `review`/`pr` came to compose the chat prompt
|
|
125
|
+
* while the review instructions were smuggled in as a caller-side leading `SystemMessage`, which
|
|
126
|
+
* Anthropic rejects outright ("System messages are only permitted as the first passed message").
|
|
127
|
+
* One function means a new command is wired once, and `review`/`pr` cannot silently fall back to
|
|
128
|
+
* chat again.
|
|
129
|
+
*
|
|
130
|
+
* `review`/`pr` resolve to the REVIEW INSTRUCTIONS (`.gsloth.review.md`), which is what makes a
|
|
131
|
+
* review a review; every command without a mode prompt of its own keeps the chat prompt.
|
|
132
|
+
*/
|
|
133
|
+
export function readModePrompt(command, config) {
|
|
134
|
+
switch (command) {
|
|
135
|
+
case 'code':
|
|
136
|
+
return readCodePrompt(config);
|
|
137
|
+
case 'exec':
|
|
138
|
+
return readExecPrompt(config);
|
|
139
|
+
case 'review':
|
|
140
|
+
case 'pr':
|
|
141
|
+
return readReviewInstructions(config);
|
|
142
|
+
default:
|
|
143
|
+
return readChatPrompt(config);
|
|
144
|
+
}
|
|
77
145
|
}
|
|
78
146
|
/**
|
|
79
147
|
* Read a prompt file from the project config dir (honouring identity profiles), falling back
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"llmUtils.js","sourceRoot":"","sources":["../../src/utils/llmUtils.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EACL,gBAAgB,EAChB,kBAAkB,EAClB,kBAAkB,EAClB,kBAAkB,EAClB,oBAAoB,
|
|
1
|
+
{"version":3,"file":"llmUtils.js","sourceRoot":"","sources":["../../src/utils/llmUtils.ts"],"names":[],"mappings":"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"}
|