chainlesschain 0.162.30 → 0.162.32
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +2 -2
- package/src/assets/web-panel/assets/{AIOps-CsNttUU7.js → AIOps-Cg_uWAVl.js} +1 -1
- package/src/assets/web-panel/assets/{ActionButton-lgohjckQ.js → ActionButton-DSFtQ1c2.js} +1 -1
- package/src/assets/web-panel/assets/{Analytics-ccV3LAca.js → Analytics-BMxpkw8y.js} +3 -3
- package/src/assets/web-panel/assets/AppLayout-tgVxlmsx.js +9 -0
- package/src/assets/web-panel/assets/{Audit-B1gFM5U9.js → Audit-DwzGllcp.js} +1 -1
- package/src/assets/web-panel/assets/{Backup-BeWE3ERo.js → Backup-BG28Y2MV.js} +1 -1
- package/src/assets/web-panel/assets/{BaseInput-CDkPsNG2.js → BaseInput-TXthbazl.js} +1 -1
- package/src/assets/web-panel/assets/{Chat-ztb9ia6e.js → Chat-D096SxaD.js} +4 -4
- package/src/assets/web-panel/assets/{ChatBubbleRenderer-Dlw_6n3M.js → ChatBubbleRenderer-PIx0Eu9I.js} +1 -1
- package/src/assets/web-panel/assets/{Checkbox-BcfRBlIY.js → Checkbox-Czttw1JS.js} +1 -1
- package/src/assets/web-panel/assets/{Codegen-DOs99xkr.js → Codegen-DZtMgv4q.js} +1 -1
- package/src/assets/web-panel/assets/{Col-D1X6tYlj.js → Col-D3DnfExY.js} +1 -1
- package/src/assets/web-panel/assets/{Community-DTksIWtz.js → Community-Bj5AdwqY.js} +1 -1
- package/src/assets/web-panel/assets/{Compact-DIJtAYBO.js → Compact-BQ8Zszub.js} +1 -1
- package/src/assets/web-panel/assets/{Compliance-BBf7LF_k.js → Compliance-DXacb34n.js} +1 -1
- package/src/assets/web-panel/assets/{Cowork-UBPXQ40s.js → Cowork-BgMUBTkw.js} +2 -2
- package/src/assets/web-panel/assets/{Cron-CkRm1jPB.js → Cron-fqBWOqlN.js} +2 -2
- package/src/assets/web-panel/assets/{Crosschain-qALlTl7e.js → Crosschain-E4oa1MWy.js} +1 -1
- package/src/assets/web-panel/assets/{DID-CqyqVS6E.js → DID-pwgfYZaV.js} +2 -2
- package/src/assets/web-panel/assets/Dashboard-n8mdLFIR.js +3 -0
- package/src/assets/web-panel/assets/{Dropdown-Cb5UzbSZ.js → Dropdown--6DYqxk7.js} +1 -1
- package/src/assets/web-panel/assets/{EmailListRenderer-CarBq8Fk.js → EmailListRenderer-CkjQluz3.js} +1 -1
- package/src/assets/web-panel/assets/{FamilyGuardDashboard-CSiGXaZz.js → FamilyGuardDashboard-u-QTQ-OC.js} +1 -1
- package/src/assets/web-panel/assets/{Federation-DUxhVoBN.js → Federation-D219M5Qc.js} +1 -1
- package/src/assets/web-panel/assets/{FormItemContext-BoMQpkhx.js → FormItemContext-BBU_aopC.js} +1 -1
- package/src/assets/web-panel/assets/{GenericCardRenderer-DTVqC_CX.js → GenericCardRenderer-pTMCIHcM.js} +1 -1
- package/src/assets/web-panel/assets/{Git-C_XuPtK5.js → Git-ClcCARWt.js} +2 -2
- package/src/assets/web-panel/assets/{Governance-BZyqlqz-.js → Governance-CvUi3I93.js} +1 -1
- package/src/assets/web-panel/assets/{Inference-DdZVUimI.js → Inference-DT-a4pVg.js} +1 -1
- package/src/assets/web-panel/assets/{KnowledgeGraph-IzZ-jnCn.js → KnowledgeGraph-DHMs2LY8.js} +1 -1
- package/src/assets/web-panel/assets/{Logs-koTK6eNc.js → Logs-D2s4eV1N.js} +2 -2
- package/src/assets/web-panel/assets/{Marketplace-6zpJ1L8n.js → Marketplace-YC5-fx-6.js} +1 -1
- package/src/assets/web-panel/assets/{McpTools-Ywc4IVks.js → McpTools-7JHTEC4T.js} +3 -3
- package/src/assets/web-panel/assets/{Memory-C_zB9dUa.js → Memory-BudotVLD.js} +2 -2
- package/src/assets/web-panel/assets/{MobileBridge-Nc05r24L.js → MobileBridge-CAiRyLVU.js} +2 -2
- package/src/assets/web-panel/assets/{MobileProjects-BJGxL526.js → MobileProjects-CrJJOCFw.js} +1 -1
- package/src/assets/web-panel/assets/{Mtc-Im7SIcz1.js → Mtc-d0iY0CeK.js} +5 -5
- package/src/assets/web-panel/assets/{MtcAudit-BFFzvzMD.js → MtcAudit-aI2cG1UP.js} +4 -4
- package/src/assets/web-panel/assets/{Multisig-CcNEbycq.js → Multisig-4bF70khG.js} +3 -3
- package/src/assets/web-panel/assets/{NLProgramming-CDH6OTXN.js → NLProgramming-CwLib1S7.js} +1 -1
- package/src/assets/web-panel/assets/{Notes-Dqg3QXcU.js → Notes-Wt7AuFRU.js} +3 -3
- package/src/assets/web-panel/assets/{NotificationSettings-CDVmK1eU.js → NotificationSettings-D081vV_7.js} +1 -1
- package/src/assets/web-panel/assets/OrderTableRenderer-DCPei1L9.js +1 -0
- package/src/assets/web-panel/assets/{Organization-DJb9bRQS.js → Organization-BNEsUNdP.js} +4 -4
- package/src/assets/web-panel/assets/{Overflow-CK7Q5dje.js → Overflow-B_1iUXDD.js} +1 -1
- package/src/assets/web-panel/assets/{P2P-CJIyYfwc.js → P2P-Dbc-kNwJ.js} +2 -2
- package/src/assets/web-panel/assets/{PdhVaultBrowser-uqRULcuw.js → PdhVaultBrowser-D8Xh289k.js} +3 -3
- package/src/assets/web-panel/assets/{Permissions-Crvwt6bq.js → Permissions-C77mM6-n.js} +4 -4
- package/src/assets/web-panel/assets/{PersonalDataHub-DcN5OWzg.js → PersonalDataHub-Dj0J3r_K.js} +3 -3
- package/src/assets/web-panel/assets/{Pipeline-DfWJvvJW.js → Pipeline-B6F0WQ2C.js} +1 -1
- package/src/assets/web-panel/assets/{Privacy-DepD0S3v.js → Privacy-eDKOkyyq.js} +1 -1
- package/src/assets/web-panel/assets/{ProjectInit-B7OKhH27.js → ProjectInit-DAWwhr5_.js} +2 -2
- package/src/assets/web-panel/assets/{ProjectSettings-BJ4ueRFv.js → ProjectSettings-DwdK8k6I.js} +2 -2
- package/src/assets/web-panel/assets/Projects-Cb3p5QAP.js +1 -0
- package/src/assets/web-panel/assets/{Providers-Dl0FT1S3.js → Providers--DcYxQfN.js} +1 -1
- package/src/assets/web-panel/assets/{QuickAsk-V2hYLhfp.js → QuickAsk-DU268niT.js} +1 -1
- package/src/assets/web-panel/assets/{Recommend-8Kaiodgv.js → Recommend-ChnflhV1.js} +1 -1
- package/src/assets/web-panel/assets/{Reputation-CsxB3JGg.js → Reputation-DSsY3bQG.js} +1 -1
- package/src/assets/web-panel/assets/{Row-6-x7tEYq.js → Row-Zb-EjmgQ.js} +1 -1
- package/src/assets/web-panel/assets/{RssFeed-Buv6f5tw.js → RssFeed-CGLiixZB.js} +3 -3
- package/src/assets/web-panel/assets/{Search-ABrDz84n.js → Search-Dhr_po-U.js} +1 -1
- package/src/assets/web-panel/assets/{Security-DqOJmz18.js → Security-GMYNhGsR.js} +4 -4
- package/src/assets/web-panel/assets/{Services-Cq4Tda3q.js → Services-DiOpnVY0.js} +2 -2
- package/src/assets/web-panel/assets/{Skeleton-n74QlyYq.js → Skeleton-DG3ez6ME.js} +1 -1
- package/src/assets/web-panel/assets/{Skills-CC0iozL5.js → Skills-DZGptytP.js} +1 -1
- package/src/assets/web-panel/assets/{Sla-hwRgJ99Z.js → Sla-CtGpE3xA.js} +1 -1
- package/src/assets/web-panel/assets/{SpeechSettings-B6Bs6_-8.js → SpeechSettings-DQFw6Cf9.js} +1 -1
- package/src/assets/web-panel/assets/{SyncSettings-CTp2dZ0z.js → SyncSettings-C8X78RpX.js} +2 -2
- package/src/assets/web-panel/assets/{Tasks-D70Lis6S.js → Tasks-DtVkhWCV.js} +1 -1
- package/src/assets/web-panel/assets/{Templates-Cags0ssw.js → Templates-SF9_ZWsV.js} +1 -1
- package/src/assets/web-panel/assets/{Tenant-BxCMzzGt.js → Tenant-BbIQSVZz.js} +1 -1
- package/src/assets/web-panel/assets/{Terminal-v05SDqHd.js → Terminal-DKr5zDwu.js} +2 -2
- package/src/assets/web-panel/assets/{TimelineRenderer-BLUDHbBL.js → TimelineRenderer-BtLaNaWr.js} +1 -1
- package/src/assets/web-panel/assets/{Tokens-D-xKLJYv.js → Tokens-CfYbk2NG.js} +1 -1
- package/src/assets/web-panel/assets/{Trigger-B47tVIbH.js → Trigger-BLX_XDP0.js} +1 -1
- package/src/assets/web-panel/assets/{Trust-DmRU9kfs.js → Trust-BWxUv9PR.js} +1 -1
- package/src/assets/web-panel/assets/{UkeySign-DzgSGs-c.js → UkeySign-DRwTyQD4.js} +1 -1
- package/src/assets/web-panel/assets/{VideoEditing-C6qu58up.js → VideoEditing-BsC4VOSo.js} +1 -1
- package/src/assets/web-panel/assets/{Wallet-Dh8ZWx8f.js → Wallet-CSsO1NJU.js} +4 -4
- package/src/assets/web-panel/assets/{WebAuthn-DFHOVuAY.js → WebAuthn-z1MxiFzS.js} +4 -4
- package/src/assets/web-panel/assets/{WorkflowEditor-B_fyQ3Y_.js → WorkflowEditor-B1vV7uuJ.js} +1 -1
- package/src/assets/web-panel/assets/{chat-BR-WxnCQ.js → chat-C0NJRaL2.js} +1 -1
- package/src/assets/web-panel/assets/{colors-C-6RysQe.js → colors-CHRiteWF.js} +1 -1
- package/src/assets/web-panel/assets/{compact-item-B_9_SCKN.js → compact-item-2XmBBKPD.js} +1 -1
- package/src/assets/web-panel/assets/{createContext-D6rklIbE.js → createContext-DkedHC38.js} +1 -1
- package/src/assets/web-panel/assets/devWarning-DmNpkOdC.js +1 -0
- package/src/assets/web-panel/assets/{hasIn-BrotgSvd.js → hasIn-Bpn9Xrlw.js} +1 -1
- package/src/assets/web-panel/assets/index-7nAysteg.js +1 -0
- package/src/assets/web-panel/assets/{index-MCmNzIC7.js → index-B5NGWgHp.js} +1 -1
- package/src/assets/web-panel/assets/{index-GzuCTHVZ.js → index-BItcSqan.js} +3 -3
- package/src/assets/web-panel/assets/index-BKWSQilQ.js +1 -0
- package/src/assets/web-panel/assets/{index-DTCUOKu9.js → index-BN068mCR.js} +1 -1
- package/src/assets/web-panel/assets/{index-Bv9BrnD2.js → index-BOsIgPge.js} +1 -1
- package/src/assets/web-panel/assets/{index-DfqUsPl2.js → index-BYUd69vM.js} +1 -1
- package/src/assets/web-panel/assets/{index-Cn21XmDt.js → index-BYmwEaIk.js} +1 -1
- package/src/assets/web-panel/assets/{index-CWmJukRW.js → index-BZ1gOoiG.js} +1 -1
- package/src/assets/web-panel/assets/{index-Bwkg_EJk.js → index-BfY9U3X5.js} +1 -1
- package/src/assets/web-panel/assets/{index-MBOwmoOi.js → index-BveL_4n3.js} +1 -1
- package/src/assets/web-panel/assets/{index-CJ70GAW2.js → index-CCg6ZY4t.js} +1 -1
- package/src/assets/web-panel/assets/{index-B85rQNYG.js → index-CJOoo72F.js} +1 -1
- package/src/assets/web-panel/assets/{index-Cn5ghmbB.js → index-CToQxpWz.js} +1 -1
- package/src/assets/web-panel/assets/{index-rWiOF7Iu.js → index-CWgWrrWs.js} +1 -1
- package/src/assets/web-panel/assets/{index-PzM_GlKb.js → index-CdR7RfRP.js} +1 -1
- package/src/assets/web-panel/assets/{index-ZehgEQYa.js → index-Cljnfuxu.js} +1 -1
- package/src/assets/web-panel/assets/{index-BsDNNDBN.js → index-CxvA72CP.js} +1 -1
- package/src/assets/web-panel/assets/{index-D6KqyxG1.js → index-CyJpmSHZ.js} +1 -1
- package/src/assets/web-panel/assets/{index-E_5VXq8H.js → index-D7U411hK.js} +1 -1
- package/src/assets/web-panel/assets/{index-CJgp_QFo.js → index-D9mNfpxi.js} +1 -1
- package/src/assets/web-panel/assets/{index-DTpElYJs.js → index-DAFLFMXQ.js} +1 -1
- package/src/assets/web-panel/assets/{index-DMnomft7.js → index-DAeHmElB.js} +1 -1
- package/src/assets/web-panel/assets/{index-B2yXH6vy.js → index-DDy_RDjs.js} +1 -1
- package/src/assets/web-panel/assets/{index-kkjq_hwC.js → index-DE5Qm9UI.js} +1 -1
- package/src/assets/web-panel/assets/{index-DTh0fWI4.js → index-DM9JrnYi.js} +1 -1
- package/src/assets/web-panel/assets/{index-DigjvHuo.js → index-DMbF-Euw.js} +1 -1
- package/src/assets/web-panel/assets/{index-DkpDFJRn.js → index-DUBsq_1G.js} +1 -1
- package/src/assets/web-panel/assets/{index-BIiCIC2j.js → index-De49R7TX.js} +1 -1
- package/src/assets/web-panel/assets/{index-CsWVDOd2.js → index-De5vOO9V.js} +1 -1
- package/src/assets/web-panel/assets/{index-CAfRNHna.js → index-Dk7P-q3n.js} +1 -1
- package/src/assets/web-panel/assets/{index-CdDmzoPE.js → index-DryKGM_t.js} +1 -1
- package/src/assets/web-panel/assets/{index-CTQkYbir.js → index-DtU4qZRF.js} +1 -1
- package/src/assets/web-panel/assets/{index-CK8YwdNd.js → index-NuBsCRaR.js} +1 -1
- package/src/assets/web-panel/assets/{index-BaLhL3Tj.js → index-Sk3-3tKa.js} +1 -1
- package/src/assets/web-panel/assets/{index-CTpxOc5s.js → index-alGjpoM1.js} +1 -1
- package/src/assets/web-panel/assets/{index-CrGp-4E2.js → index-cfSUlOfY.js} +1 -1
- package/src/assets/web-panel/assets/{index-BbRl_gIW.js → index-i4W_EAuh.js} +1 -1
- package/src/assets/web-panel/assets/{index-CCWzUY8K.js → index-uHGxyZtQ.js} +1 -1
- package/src/assets/web-panel/assets/{initDefaultProps-C2v_L5na.js → initDefaultProps-DlDE-QgI.js} +1 -1
- package/src/assets/web-panel/assets/{motion-DNDqGbfr.js → motion-CodUbIRF.js} +1 -1
- package/src/assets/web-panel/assets/{move-xvpQ_6hJ.js → move-DaLwsHeR.js} +1 -1
- package/src/assets/web-panel/assets/{omit-Cb0FsfrO.js → omit-DdVg-3rL.js} +1 -1
- package/src/assets/web-panel/assets/{pickAttrs-BxhYpnum.js → pickAttrs-KLR1EVCo.js} +1 -1
- package/src/assets/web-panel/assets/{placementArrow-B3soaW4h.js → placementArrow-ChV7HvNw.js} +1 -1
- package/src/assets/web-panel/assets/{responsiveObserve-B-eRSLvd.js → responsiveObserve-BB_A8dBt.js} +1 -1
- package/src/assets/web-panel/assets/{slide--cM2ZOx-.js → slide-Bc1tQnIK.js} +1 -1
- package/src/assets/web-panel/assets/{statusUtils-DjBhfi8Q.js → statusUtils-CgrveSb0.js} +1 -1
- package/src/assets/web-panel/assets/{styleChecker-C30mMh8o.js → styleChecker-vXAYhhjz.js} +1 -1
- package/src/assets/web-panel/assets/{useFlexGapSupport-f7y2Qlzs.js → useFlexGapSupport-BCIMPfq9.js} +1 -1
- package/src/assets/web-panel/assets/{useFs-iTCXoLoZ.js → useFs-DMZGdr6G.js} +1 -1
- package/src/assets/web-panel/assets/{usePersonalDataHub-BH0RXmVF.js → usePersonalDataHub-118tWI_Z.js} +1 -1
- package/src/assets/web-panel/assets/{vnode-DQtmeDXM.js → vnode-Z7O2Y7JP.js} +1 -1
- package/src/assets/web-panel/assets/{zoom-vw50zkLZ.js → zoom-BXym6zmD.js} +1 -1
- package/src/assets/web-panel/index.html +1 -1
- package/src/commands/agent.js +333 -1
- package/src/commands/ask.js +35 -1
- package/src/commands/checkpoint.js +439 -0
- package/src/commands/compact.js +150 -0
- package/src/commands/cost.js +114 -0
- package/src/commands/goal.js +417 -0
- package/src/commands/hub.js +7 -0
- package/src/commands/session.js +22 -2
- package/src/harness/prompt-compressor.js +71 -1
- package/src/index.js +8 -0
- package/src/lib/agent-core.js +1 -0
- package/src/lib/checkpoint-store.js +523 -0
- package/src/lib/file-checkpoint.js +300 -0
- package/src/lib/goal-context.js +87 -0
- package/src/lib/goal-store.js +308 -0
- package/src/lib/llm-pricing.js +227 -0
- package/src/lib/personal-data-hub-wiring.js +30 -0
- package/src/lib/recent-session.js +72 -0
- package/src/lib/session-picker.js +68 -0
- package/src/repl/agent-repl.js +101 -9
- package/src/repl/chat-repl.js +16 -1
- package/src/runtime/agent-core.js +313 -32
- package/src/runtime/fallback-model.js +109 -0
- package/src/runtime/file-ref-expander.js +258 -0
- package/src/runtime/headless-runner.js +601 -0
- package/src/runtime/headless-stream.js +315 -0
- package/src/runtime/policies/agent-policy.js +7 -0
- package/src/runtime/quiet-stdout.js +35 -0
- package/src/runtime/system-prompt.js +60 -0
- package/src/assets/web-panel/assets/AppLayout-B0hl5cPk.js +0 -9
- package/src/assets/web-panel/assets/Dashboard-XlMpT7K_.js +0 -3
- package/src/assets/web-panel/assets/OrderTableRenderer-Bg0bkfjR.js +0 -1
- package/src/assets/web-panel/assets/Projects-Dl_hPdhU.js +0 -1
- package/src/assets/web-panel/assets/devWarning-BiN5HELJ.js +0 -1
- package/src/assets/web-panel/assets/index-BhxiT2LJ.js +0 -1
- package/src/assets/web-panel/assets/index-DBNSZ2oz.js +0 -1
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@file` reference expander — Claude-Code-style prompt file injection.
|
|
3
|
+
*
|
|
4
|
+
* Scans a prompt for `@<path>` tokens and, for each one that resolves to a real
|
|
5
|
+
* file/dir under the working directory, appends the file contents (or a dir
|
|
6
|
+
* listing) as a `<referenced-files>` context block. The original `@token` stays
|
|
7
|
+
* in the prose so the message remains readable and the model knows what the
|
|
8
|
+
* user pointed at.
|
|
9
|
+
*
|
|
10
|
+
* Design notes:
|
|
11
|
+
* - A token only matches when `@` is at start-of-input or preceded by
|
|
12
|
+
* whitespace / an opening bracket-quote. That skips email addresses
|
|
13
|
+
* (`foo@bar.com`) and decorative `@` — the `@` there is preceded by a word
|
|
14
|
+
* char and never matches.
|
|
15
|
+
* - Non-existent paths are NOT expanded and are surfaced as warnings (so a
|
|
16
|
+
* typo'd path is visible rather than silently dropped). Decorative `@words`
|
|
17
|
+
* that happen not to be files simply produce no ref and no warning unless
|
|
18
|
+
* they look path-like (contain a slash or a dot-extension).
|
|
19
|
+
* - Files are read as UTF-8 (encoding.md rule). Binary files are skipped with
|
|
20
|
+
* a note. Oversized files are truncated with a marker.
|
|
21
|
+
* - All filesystem access goes through an injectable `deps` seam so unit tests
|
|
22
|
+
* never touch the real disk (mirrors the project's `_deps` philosophy).
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
import fsDefault from "fs";
|
|
26
|
+
import pathDefault from "path";
|
|
27
|
+
|
|
28
|
+
export const DEFAULT_MAX_BYTES = 100 * 1024; // 100 KB per referenced file
|
|
29
|
+
export const DEFAULT_MAX_DIR_ENTRIES = 200;
|
|
30
|
+
|
|
31
|
+
// `@` preceded by start / whitespace / opening bracket-quote, then a path run.
|
|
32
|
+
// We capture greedily up to the next whitespace or a closing bracket-quote and
|
|
33
|
+
// trim trailing sentence punctuation afterwards.
|
|
34
|
+
const TOKEN_RE = /(^|[\s("'`[{])@([^\s"'`)\]}]+)/g;
|
|
35
|
+
|
|
36
|
+
/** A raw token looks path-like if it has a directory separator or a file ext. */
|
|
37
|
+
function looksPathLike(raw) {
|
|
38
|
+
return /[\\/]/.test(raw) || /\.[A-Za-z0-9]+$/.test(raw);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/** Strip trailing sentence punctuation that is unlikely to be part of a path. */
|
|
42
|
+
function trimTrailingPunct(raw) {
|
|
43
|
+
return raw.replace(/[),;:!?'".]+$/g, "");
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Find unique `@path` candidates in the text, in first-seen order.
|
|
48
|
+
* @returns {Array<{raw:string}>}
|
|
49
|
+
*/
|
|
50
|
+
export function findFileRefTokens(text) {
|
|
51
|
+
const seen = new Set();
|
|
52
|
+
const out = [];
|
|
53
|
+
let m;
|
|
54
|
+
TOKEN_RE.lastIndex = 0;
|
|
55
|
+
while ((m = TOKEN_RE.exec(text)) !== null) {
|
|
56
|
+
const raw = m[2];
|
|
57
|
+
if (!raw || seen.has(raw)) continue;
|
|
58
|
+
seen.add(raw);
|
|
59
|
+
out.push({ raw });
|
|
60
|
+
}
|
|
61
|
+
return out;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/** True when a buffer/string looks binary (has a NUL in the sampled prefix). */
|
|
65
|
+
function looksBinary(buf) {
|
|
66
|
+
const sample = buf.slice(0, 8000);
|
|
67
|
+
for (let i = 0; i < sample.length; i++) {
|
|
68
|
+
if (sample[i] === 0) return true;
|
|
69
|
+
}
|
|
70
|
+
return false;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Resolve a single raw token to an injectable ref descriptor, or null when it
|
|
75
|
+
* does not resolve to an existing path. Tries the literal path first, then a
|
|
76
|
+
* trailing-punctuation-stripped variant (handles "see @config.json.").
|
|
77
|
+
*/
|
|
78
|
+
function resolveRef(raw, { cwd, fs, path, maxBytes, maxDirEntries }) {
|
|
79
|
+
const candidates = [raw];
|
|
80
|
+
const trimmed = trimTrailingPunct(raw);
|
|
81
|
+
if (trimmed && trimmed !== raw) candidates.push(trimmed);
|
|
82
|
+
|
|
83
|
+
for (const cand of candidates) {
|
|
84
|
+
const abs = path.resolve(cwd, cand);
|
|
85
|
+
let stat;
|
|
86
|
+
try {
|
|
87
|
+
stat = fs.statSync(abs);
|
|
88
|
+
} catch {
|
|
89
|
+
continue; // not this candidate
|
|
90
|
+
}
|
|
91
|
+
if (stat.isDirectory()) {
|
|
92
|
+
let entries;
|
|
93
|
+
try {
|
|
94
|
+
entries = fs.readdirSync(abs, { withFileTypes: true });
|
|
95
|
+
} catch (err) {
|
|
96
|
+
return {
|
|
97
|
+
kind: "error",
|
|
98
|
+
raw: cand,
|
|
99
|
+
rel: cand,
|
|
100
|
+
message: `cannot read directory: ${err.message}`,
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
const names = entries
|
|
104
|
+
.slice(0, maxDirEntries)
|
|
105
|
+
.map((e) => (e.isDirectory() ? `${e.name}/` : e.name))
|
|
106
|
+
.sort();
|
|
107
|
+
const truncated = entries.length > maxDirEntries;
|
|
108
|
+
return {
|
|
109
|
+
kind: "dir",
|
|
110
|
+
raw: cand,
|
|
111
|
+
rel: cand,
|
|
112
|
+
entries: names,
|
|
113
|
+
total: entries.length,
|
|
114
|
+
truncated,
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
if (stat.isFile()) {
|
|
118
|
+
let buf;
|
|
119
|
+
try {
|
|
120
|
+
buf = fs.readFileSync(abs);
|
|
121
|
+
} catch (err) {
|
|
122
|
+
return {
|
|
123
|
+
kind: "error",
|
|
124
|
+
raw: cand,
|
|
125
|
+
rel: cand,
|
|
126
|
+
message: `cannot read file: ${err.message}`,
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
if (looksBinary(buf)) {
|
|
130
|
+
return {
|
|
131
|
+
kind: "binary",
|
|
132
|
+
raw: cand,
|
|
133
|
+
rel: cand,
|
|
134
|
+
bytes: stat.size,
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
const truncated = buf.length > maxBytes;
|
|
138
|
+
const content = (truncated ? buf.slice(0, maxBytes) : buf).toString(
|
|
139
|
+
"utf-8",
|
|
140
|
+
);
|
|
141
|
+
return {
|
|
142
|
+
kind: "file",
|
|
143
|
+
raw: cand,
|
|
144
|
+
rel: cand,
|
|
145
|
+
bytes: stat.size,
|
|
146
|
+
content,
|
|
147
|
+
truncated,
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
// Something exotic (socket/fifo) — treat as non-expandable.
|
|
151
|
+
return null;
|
|
152
|
+
}
|
|
153
|
+
return null;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
function escapeAttr(s) {
|
|
157
|
+
return String(s).replace(/"/g, """);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/** Render the resolved refs into a single `<referenced-files>` block. */
|
|
161
|
+
function renderBlock(refs) {
|
|
162
|
+
const parts = [
|
|
163
|
+
'<referenced-files note="auto-injected from @path references">',
|
|
164
|
+
];
|
|
165
|
+
for (const ref of refs) {
|
|
166
|
+
if (ref.kind === "file") {
|
|
167
|
+
const attrs =
|
|
168
|
+
`path="${escapeAttr(ref.rel)}" bytes="${ref.bytes}"` +
|
|
169
|
+
(ref.truncated
|
|
170
|
+
? ` truncated="true" shown-bytes="${DEFAULT_MAX_BYTES}"`
|
|
171
|
+
: "");
|
|
172
|
+
parts.push(`<file ${attrs}>`);
|
|
173
|
+
parts.push(ref.content);
|
|
174
|
+
if (ref.truncated) {
|
|
175
|
+
parts.push(`\n… [truncated — file is ${ref.bytes} bytes]`);
|
|
176
|
+
}
|
|
177
|
+
parts.push("</file>");
|
|
178
|
+
} else if (ref.kind === "dir") {
|
|
179
|
+
const attrs =
|
|
180
|
+
`path="${escapeAttr(ref.rel)}" entries="${ref.total}"` +
|
|
181
|
+
(ref.truncated ? ` truncated="true"` : "");
|
|
182
|
+
parts.push(`<dir ${attrs}>`);
|
|
183
|
+
parts.push(ref.entries.join("\n"));
|
|
184
|
+
if (ref.truncated) {
|
|
185
|
+
parts.push(`… [truncated — ${ref.total} entries total]`);
|
|
186
|
+
}
|
|
187
|
+
parts.push("</dir>");
|
|
188
|
+
} else if (ref.kind === "binary") {
|
|
189
|
+
parts.push(
|
|
190
|
+
`<file path="${escapeAttr(ref.rel)}" bytes="${ref.bytes}" binary="true" note="binary file — contents omitted" />`,
|
|
191
|
+
);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
parts.push("</referenced-files>");
|
|
195
|
+
return parts.join("\n");
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* Expand `@file` references in a prompt.
|
|
200
|
+
*
|
|
201
|
+
* @param {string} prompt
|
|
202
|
+
* @param {object} [opts]
|
|
203
|
+
* @param {string} [opts.cwd=process.cwd()]
|
|
204
|
+
* @param {number} [opts.maxBytes]
|
|
205
|
+
* @param {number} [opts.maxDirEntries]
|
|
206
|
+
* @param {object} [opts.deps] Injection seam: { fs, path }.
|
|
207
|
+
* @returns {{ prompt:string, refs:Array, warnings:string[] }}
|
|
208
|
+
* `prompt` is unchanged when nothing resolved; otherwise it is the
|
|
209
|
+
* original text + a trailing `<referenced-files>` block.
|
|
210
|
+
*/
|
|
211
|
+
export function expandFileRefs(prompt, opts = {}) {
|
|
212
|
+
const text = typeof prompt === "string" ? prompt : "";
|
|
213
|
+
if (!text || !text.includes("@")) {
|
|
214
|
+
return { prompt: text, refs: [], warnings: [] };
|
|
215
|
+
}
|
|
216
|
+
const fs = opts.deps?.fs || fsDefault;
|
|
217
|
+
const path = opts.deps?.path || pathDefault;
|
|
218
|
+
const cwd = opts.cwd || process.cwd();
|
|
219
|
+
const maxBytes = Number.isFinite(opts.maxBytes)
|
|
220
|
+
? opts.maxBytes
|
|
221
|
+
: DEFAULT_MAX_BYTES;
|
|
222
|
+
const maxDirEntries = Number.isFinite(opts.maxDirEntries)
|
|
223
|
+
? opts.maxDirEntries
|
|
224
|
+
: DEFAULT_MAX_DIR_ENTRIES;
|
|
225
|
+
|
|
226
|
+
const tokens = findFileRefTokens(text);
|
|
227
|
+
const refs = [];
|
|
228
|
+
const warnings = [];
|
|
229
|
+
|
|
230
|
+
for (const { raw } of tokens) {
|
|
231
|
+
const ref = resolveRef(raw, { cwd, fs, path, maxBytes, maxDirEntries });
|
|
232
|
+
if (!ref) {
|
|
233
|
+
// Only warn for path-like tokens; bare @mentions are left alone.
|
|
234
|
+
if (looksPathLike(raw)) {
|
|
235
|
+
warnings.push(`@${raw} — no such file or directory (left as-is)`);
|
|
236
|
+
}
|
|
237
|
+
continue;
|
|
238
|
+
}
|
|
239
|
+
if (ref.kind === "error") {
|
|
240
|
+
warnings.push(`@${ref.raw} — ${ref.message} (left as-is)`);
|
|
241
|
+
continue;
|
|
242
|
+
}
|
|
243
|
+
refs.push(ref);
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
if (refs.length === 0) {
|
|
247
|
+
return { prompt: text, refs: [], warnings };
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
const block = renderBlock(refs);
|
|
251
|
+
return {
|
|
252
|
+
prompt: `${text}\n\n${block}`,
|
|
253
|
+
refs,
|
|
254
|
+
warnings,
|
|
255
|
+
};
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
export const _deps = { fs: fsDefault, path: pathDefault };
|