token-goat 2.9.30 → 2.9.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 +24 -7
- package/SECURITY.md +10 -2
- package/THIRD_PARTY_NOTICES.md +1 -1
- package/dist/native/linux-arm64/tg-hook +0 -0
- package/dist/native/linux-x64/tg-hook +0 -0
- package/dist/native/win32-arm64/tg-hook.exe +0 -0
- package/dist/native/win32-x64/tg-hook.exe +0 -0
- package/dist/{token-goat-chunk-QSBRTGM2.mjs → token-goat-chunk-25TRAWET.mjs} +17 -7
- package/dist/token-goat-chunk-2KXO6V2B.mjs +203 -0
- package/dist/{token-goat-chunk-IVKIZWAB.mjs → token-goat-chunk-2M7E4PF7.mjs} +41 -12
- package/dist/{token-goat-chunk-SMVRN2HU.mjs → token-goat-chunk-2UPZGKKY.mjs} +2 -2
- package/dist/token-goat-chunk-2WLPWKHV.mjs +135 -0
- package/dist/token-goat-chunk-2XBMMDBD.mjs +126 -0
- package/dist/token-goat-chunk-32ZOY4N5.mjs +23 -0
- package/dist/token-goat-chunk-3EZRNKTK.mjs +188 -0
- package/dist/token-goat-chunk-4ADZHI7J.mjs +63 -0
- package/dist/token-goat-chunk-4GBVPH3D.mjs +242 -0
- package/dist/{token-goat-chunk-KWPNJBDH.mjs → token-goat-chunk-4GILLLWY.mjs} +7 -4
- package/dist/{token-goat-chunk-67TQJ76B.mjs → token-goat-chunk-4NAPX7BA.mjs} +36 -3
- package/dist/{token-goat-chunk-PU7V3FD6.mjs → token-goat-chunk-4SC7UJYV.mjs} +3354 -2553
- package/dist/token-goat-chunk-4SMRO4TO.mjs +366 -0
- package/dist/{token-goat-chunk-AFLYLHDH.mjs → token-goat-chunk-4ZBFWLXF.mjs} +283 -427
- package/dist/{token-goat-chunk-JDWCRD6M.mjs → token-goat-chunk-57BIAXJL.mjs} +73 -40
- package/dist/token-goat-chunk-5AC66HNP.mjs +115 -0
- package/dist/token-goat-chunk-5IMLKSOP.mjs +145 -0
- package/dist/token-goat-chunk-646E6U44.mjs +398 -0
- package/dist/token-goat-chunk-65N4RHP4.mjs +33 -0
- package/dist/{token-goat-chunk-JN4XMLSD.mjs → token-goat-chunk-6DG6HWP3.mjs} +8 -2
- package/dist/token-goat-chunk-6ENQSNRZ.mjs +573 -0
- package/dist/token-goat-chunk-6ZY4GNF2.mjs +91 -0
- package/dist/{token-goat-chunk-VPBBTSJR.mjs → token-goat-chunk-76FGDLRO.mjs} +262 -255
- package/dist/{token-goat-chunk-7IN2MKDS.mjs → token-goat-chunk-7EZTZOMC.mjs} +121 -289
- package/dist/{token-goat-chunk-OJBNYTJP.mjs → token-goat-chunk-7MAOA6X4.mjs} +640 -80
- package/dist/token-goat-chunk-7R2ZVVAX.mjs +218 -0
- package/dist/{token-goat-chunk-PD5VKH46.mjs → token-goat-chunk-AUNGYYQX.mjs} +2 -2
- package/dist/{token-goat-chunk-HG45AF2B.mjs → token-goat-chunk-AUQYRMMH.mjs} +794 -37
- package/dist/token-goat-chunk-B3PEKBYG.mjs +128 -0
- package/dist/{token-goat-chunk-A3CK6N5Z.mjs → token-goat-chunk-BA4HI6BW.mjs} +1309 -110
- package/dist/{token-goat-chunk-JB6QN6VF.mjs → token-goat-chunk-BFCWY73P.mjs} +59 -23
- package/dist/{token-goat-chunk-B45VMIIH.mjs → token-goat-chunk-BWGFUZZE.mjs} +7 -5
- package/dist/{token-goat-chunk-P4QMM4WK.mjs → token-goat-chunk-C75NA7PL.mjs} +50 -23
- package/dist/token-goat-chunk-CBIQ7WTD.mjs +87 -0
- package/dist/token-goat-chunk-CETM74KC.mjs +307 -0
- package/dist/{token-goat-chunk-H2PHHGM5.mjs → token-goat-chunk-CIMQ2BB3.mjs} +57 -12
- package/dist/{token-goat-chunk-N2NMER56.mjs → token-goat-chunk-CJLS3CDL.mjs} +46 -4
- package/dist/{token-goat-chunk-VES7EL7O.mjs → token-goat-chunk-CO3UYX6G.mjs} +1 -1
- package/dist/token-goat-chunk-COPNXRJM.mjs +154 -0
- package/dist/token-goat-chunk-CSJ5L3NL.mjs +479 -0
- package/dist/{token-goat-chunk-4LCCNRTG.mjs → token-goat-chunk-CVCEVUGK.mjs} +8 -6
- package/dist/{token-goat-chunk-B2RZZCSS.mjs → token-goat-chunk-CXHOFN7R.mjs} +37 -20
- package/dist/token-goat-chunk-D735C4QM.mjs +603 -0
- package/dist/{token-goat-chunk-APGZXSPS.mjs → token-goat-chunk-DGS2LVNA.mjs} +47 -30
- package/dist/{token-goat-chunk-54K3EUV3.mjs → token-goat-chunk-DOWRSMWO.mjs} +1 -1
- package/dist/token-goat-chunk-E45INMY3.mjs +71 -0
- package/dist/token-goat-chunk-EC5F37F4.mjs +244 -0
- package/dist/{token-goat-chunk-XTQAOTSO.mjs → token-goat-chunk-EDBDRVH5.mjs} +4 -1
- package/dist/{token-goat-chunk-5BCIJXMO.mjs → token-goat-chunk-EELTBKDM.mjs} +14 -10
- package/dist/{token-goat-chunk-W3QCJS6G.mjs → token-goat-chunk-F4HYL64R.mjs} +8 -6
- package/dist/token-goat-chunk-F6PAUIEK.mjs +624 -0
- package/dist/token-goat-chunk-FDSREWLX.mjs +692 -0
- package/dist/token-goat-chunk-GGGG7RWB.mjs +236 -0
- package/dist/{token-goat-chunk-C63JQV5K.mjs → token-goat-chunk-GL3ETKSC.mjs} +233 -15
- package/dist/token-goat-chunk-GVB2MUST.mjs +1298 -0
- package/dist/token-goat-chunk-GWFLAUMQ.mjs +307 -0
- package/dist/{token-goat-chunk-ZEJVMUQH.mjs → token-goat-chunk-HLPW63A7.mjs} +2 -2
- package/dist/{token-goat-chunk-GOLEOXZP.mjs → token-goat-chunk-HU4TORC5.mjs} +44 -26
- package/dist/{token-goat-chunk-Z57YODA2.mjs → token-goat-chunk-I7VKZZAW.mjs} +2 -2
- package/dist/{token-goat-chunk-NYKZLXMK.mjs → token-goat-chunk-IA6XSPE3.mjs} +6 -6
- package/dist/{token-goat-chunk-E3OQX2XT.mjs → token-goat-chunk-IAGXMHIK.mjs} +81 -42
- package/dist/{token-goat-chunk-HYBFA5X3.mjs → token-goat-chunk-IK2DRMFX.mjs} +24 -68
- package/dist/{token-goat-chunk-COBQGL5S.mjs → token-goat-chunk-INNPTRUX.mjs} +249 -299
- package/dist/{token-goat-chunk-7NADEDKJ.mjs → token-goat-chunk-JJ5BX4F4.mjs} +6 -1
- package/dist/{token-goat-chunk-PEPTHRFF.mjs → token-goat-chunk-JVFSHVFJ.mjs} +6 -6
- package/dist/token-goat-chunk-KGEFFSHD.mjs +50 -0
- package/dist/token-goat-chunk-KQBLRPBN.mjs +433 -0
- package/dist/{token-goat-chunk-Q5VTGRH7.mjs → token-goat-chunk-LCNQ2CNN.mjs} +55 -319
- package/dist/token-goat-chunk-M3LFJDPU.mjs +58 -0
- package/dist/token-goat-chunk-M52KPT3C.mjs +87 -0
- package/dist/token-goat-chunk-MBEG42H7.mjs +150 -0
- package/dist/{token-goat-chunk-EVC4TOLE.mjs → token-goat-chunk-METECDOH.mjs} +3 -12
- package/dist/{token-goat-chunk-T4FK7VOV.mjs → token-goat-chunk-MHX7XCC3.mjs} +2 -1
- package/dist/token-goat-chunk-N5LSOVSU.mjs +137 -0
- package/dist/{token-goat-chunk-LOBGHXPB.mjs → token-goat-chunk-N5MMR2IW.mjs} +1 -1
- package/dist/token-goat-chunk-N7B3JQ2C.mjs +160 -0
- package/dist/{token-goat-chunk-RHXKCZX3.mjs → token-goat-chunk-NISNMD7T.mjs} +2182 -2959
- package/dist/token-goat-chunk-NMD42SFQ.mjs +434 -0
- package/dist/token-goat-chunk-NOSS5VWY.mjs +174 -0
- package/dist/{token-goat-chunk-KQNZDCBD.mjs → token-goat-chunk-NSNSPPBG.mjs} +25 -3
- package/dist/token-goat-chunk-OBOFIHKN.mjs +38 -0
- package/dist/token-goat-chunk-OBRFJ5O5.mjs +76 -0
- package/dist/{token-goat-chunk-JTQQGXZH.mjs → token-goat-chunk-ODBT2USM.mjs} +124 -57
- package/dist/token-goat-chunk-OS5EM5PP.mjs +107 -0
- package/dist/token-goat-chunk-OUKDTVNU.mjs +1178 -0
- package/dist/token-goat-chunk-OXFMP75N.mjs +566 -0
- package/dist/{token-goat-chunk-DZX2YDPT.mjs → token-goat-chunk-OYIYKDDT.mjs} +2 -2
- package/dist/{token-goat-chunk-QCLDAQTS.mjs → token-goat-chunk-P6HQSWQ3.mjs} +50 -53
- package/dist/token-goat-chunk-P6VGNTQT.mjs +71 -0
- package/dist/{token-goat-chunk-7BXSNBY5.mjs → token-goat-chunk-PFWIMH2E.mjs} +23 -15
- package/dist/token-goat-chunk-PJZXIS3G.mjs +39 -0
- package/dist/token-goat-chunk-PUO5INXP.mjs +606 -0
- package/dist/{token-goat-chunk-GFBSN7BD.mjs → token-goat-chunk-PX5PQWTY.mjs} +22 -250
- package/dist/token-goat-chunk-Q5QDBC6O.mjs +111 -0
- package/dist/token-goat-chunk-QFNQXSDT.mjs +40 -0
- package/dist/{token-goat-chunk-FBNQNSJK.mjs → token-goat-chunk-QH7YVYOY.mjs} +2198 -2782
- package/dist/{token-goat-chunk-64FBPDTK.mjs → token-goat-chunk-QLMUHEPB.mjs} +12 -9
- package/dist/{token-goat-chunk-RZRTDST7.mjs → token-goat-chunk-QQOJIHL3.mjs} +37 -11
- package/dist/{token-goat-chunk-XKI4SEMX.mjs → token-goat-chunk-QQTWJY2O.mjs} +19 -0
- package/dist/{token-goat-chunk-U4N3BN2W.mjs → token-goat-chunk-QYHO5CPH.mjs} +3 -2
- package/dist/token-goat-chunk-RELAVWAD.mjs +27 -0
- package/dist/{token-goat-chunk-ETBHVDB6.mjs → token-goat-chunk-RSLPOBKQ.mjs} +22 -11
- package/dist/token-goat-chunk-SAMFDIS2.mjs +712 -0
- package/dist/token-goat-chunk-SDELXLDM.mjs +48 -0
- package/dist/{token-goat-chunk-4JJS54TR.mjs → token-goat-chunk-SOAFZNNZ.mjs} +161 -38
- package/dist/{token-goat-chunk-664RTTUV.mjs → token-goat-chunk-SRTHT7KV.mjs} +21 -16
- package/dist/{token-goat-chunk-4FVIAHSI.mjs → token-goat-chunk-T5P5ACNQ.mjs} +7 -6
- package/dist/token-goat-chunk-T5YGG4V3.mjs +45 -0
- package/dist/token-goat-chunk-TAUZ4OFS.mjs +110 -0
- package/dist/{token-goat-chunk-COTXZHTS.mjs → token-goat-chunk-TM6MC754.mjs} +4 -3
- package/dist/token-goat-chunk-TWUKBOMP.mjs +72 -0
- package/dist/{token-goat-chunk-3CHUNJ2O.mjs → token-goat-chunk-U2KSB4SG.mjs} +8 -5
- package/dist/{token-goat-chunk-3Z5S4KGM.mjs → token-goat-chunk-U4WHMG6Y.mjs} +29 -49
- package/dist/{token-goat-chunk-PY533T7F.mjs → token-goat-chunk-UGJHGR5A.mjs} +21 -15
- package/dist/{token-goat-chunk-CYCEYAEO.mjs → token-goat-chunk-UOUDVA5U.mjs} +1 -1
- package/dist/{token-goat-chunk-JDHE26RP.mjs → token-goat-chunk-URRJ33GR.mjs} +16 -5
- package/dist/{token-goat-chunk-56EIMS3E.mjs → token-goat-chunk-UZOROKIS.mjs} +23 -17
- package/dist/{token-goat-chunk-CZ3LUXYZ.mjs → token-goat-chunk-VIHGGGEI.mjs} +427 -308
- package/dist/token-goat-chunk-VTJLAA7P.mjs +21 -0
- package/dist/token-goat-chunk-VWDXLT4F.mjs +678 -0
- package/dist/{token-goat-chunk-YARZFCZS.mjs → token-goat-chunk-VWZA2H4P.mjs} +62 -53
- package/dist/{token-goat-chunk-SQSSNQPE.mjs → token-goat-chunk-VXEXMJDL.mjs} +3979 -4745
- package/dist/token-goat-chunk-WBA5SKT4.mjs +547 -0
- package/dist/{token-goat-chunk-SJHWVNDQ.mjs → token-goat-chunk-WDH44VAU.mjs} +7 -4
- package/dist/token-goat-chunk-X2SUP3EI.mjs +107 -0
- package/dist/token-goat-chunk-X3BELZSJ.mjs +125 -0
- package/dist/{token-goat-chunk-FZ3NEW5O.mjs → token-goat-chunk-XLRBNZCC.mjs} +13 -8
- package/dist/{token-goat-chunk-Z44YO3QZ.mjs → token-goat-chunk-XRKUX6CM.mjs} +1 -1
- package/dist/token-goat-chunk-XX6O25RN.mjs +82 -0
- package/dist/token-goat-chunk-XZSUHBVS.mjs +65 -0
- package/dist/{token-goat-chunk-WY3L4DVT.mjs → token-goat-chunk-Y2ZTQOCL.mjs} +13 -8
- package/dist/{token-goat-chunk-UQ5UK2T7.mjs → token-goat-chunk-YB4VMGK2.mjs} +1 -1
- package/dist/token-goat-chunk-YBIIY3HR.mjs +51 -0
- package/dist/{token-goat-chunk-ZQSJMO2R.mjs → token-goat-chunk-YHVDKQBR.mjs} +105 -105
- package/dist/{token-goat-chunk-H2K3QP6H.mjs → token-goat-chunk-YJB5XLWI.mjs} +8 -6
- package/dist/{token-goat-chunk-ZCDTCVIS.mjs → token-goat-chunk-YKB6AQG3.mjs} +5 -2
- package/dist/token-goat-chunk-YMTG2YA5.mjs +35 -0
- package/dist/token-goat-chunk-YPBZYQRV.mjs +40 -0
- package/dist/{token-goat-chunk-HOJLCGDP.mjs → token-goat-chunk-YY6AVUFL.mjs} +2033 -2251
- package/dist/token-goat-chunk-Z7N5OMMP.mjs +98 -0
- package/dist/token-goat-chunk-ZNMNUPAZ.mjs +938 -0
- package/dist/token-goat-hook-client.cjs +1 -1
- package/dist/token-goat-hook-client.mjs +3 -3
- package/dist/token-goat-hook.mjs +67 -38
- package/dist/token-goat.core.mjs +4 -4
- package/docs/C4_RUNTIME_ARCHITECTURE.md +1 -1
- package/docs/cli.md +40 -21
- package/docs/install.md +19 -9
- package/docs/security.md +5 -3
- package/package.json +2 -1
- package/dist/token-goat-chunk-5KDMCMF2.mjs +0 -362
- package/dist/token-goat-chunk-6QMAS7AB.mjs +0 -42
- package/dist/token-goat-chunk-7F2UBPD3.mjs +0 -397
- package/dist/token-goat-chunk-ARDNEC2U.mjs +0 -248
- package/dist/token-goat-chunk-ATCPY7EQ.mjs +0 -134
- package/dist/token-goat-chunk-EFHMMIGP.mjs +0 -68
- package/dist/token-goat-chunk-IVALLT3S.mjs +0 -48
- package/dist/token-goat-chunk-JDU3EXSU.mjs +0 -65
- package/dist/token-goat-chunk-MKPF4CL5.mjs +0 -37
- package/dist/token-goat-chunk-RC35RBUL.mjs +0 -312
- package/dist/token-goat-chunk-USILZ3T3.mjs +0 -53
- package/dist/token-goat-chunk-VL3YIFHZ.mjs +0 -2975
- package/dist/token-goat-chunk-XU4P6Z24.mjs +0 -133
- package/dist/token-goat-chunk-Y776AENC.mjs +0 -1597
|
@@ -0,0 +1,606 @@
|
|
|
1
|
+
import { createRequire as __cjsRequire } from 'node:module';
|
|
2
|
+
const require = __cjsRequire(import.meta.url);
|
|
3
|
+
import {
|
|
4
|
+
buildCommandManifest,
|
|
5
|
+
buildReminder,
|
|
6
|
+
checkSymbolBodySize,
|
|
7
|
+
flattenCommandNames
|
|
8
|
+
} from "./token-goat-chunk-2XBMMDBD.mjs";
|
|
9
|
+
import {
|
|
10
|
+
DEFAULT_RECONCILE_BUDGET_MS,
|
|
11
|
+
isReconcileClean,
|
|
12
|
+
reconcileProject
|
|
13
|
+
} from "./token-goat-chunk-PFWIMH2E.mjs";
|
|
14
|
+
import {
|
|
15
|
+
projectNotesFor
|
|
16
|
+
} from "./token-goat-chunk-GWFLAUMQ.mjs";
|
|
17
|
+
import {
|
|
18
|
+
dropsPreCompactContext,
|
|
19
|
+
dropsPromptSubmitContext,
|
|
20
|
+
resumesCompactionOnPrompt,
|
|
21
|
+
sessionStartMayBeDeferred
|
|
22
|
+
} from "./token-goat-chunk-PJZXIS3G.mjs";
|
|
23
|
+
import {
|
|
24
|
+
buildDeltaCapsule
|
|
25
|
+
} from "./token-goat-chunk-NOSS5VWY.mjs";
|
|
26
|
+
import {
|
|
27
|
+
sessionSidecarPath
|
|
28
|
+
} from "./token-goat-chunk-WBA5SKT4.mjs";
|
|
29
|
+
import {
|
|
30
|
+
accumulateResidentLines,
|
|
31
|
+
lineMayCarryResidentSignal,
|
|
32
|
+
readTranscriptTail,
|
|
33
|
+
repeatedSkillBodyHint,
|
|
34
|
+
summarizeResidentContext,
|
|
35
|
+
taskListPruneHint
|
|
36
|
+
} from "./token-goat-chunk-WDH44VAU.mjs";
|
|
37
|
+
import {
|
|
38
|
+
registerHook,
|
|
39
|
+
sessionStateKey
|
|
40
|
+
} from "./token-goat-chunk-C75NA7PL.mjs";
|
|
41
|
+
import {
|
|
42
|
+
contextOutput,
|
|
43
|
+
getCwd,
|
|
44
|
+
passOutput
|
|
45
|
+
} from "./token-goat-chunk-76FGDLRO.mjs";
|
|
46
|
+
import {
|
|
47
|
+
markHintShown,
|
|
48
|
+
recordScheduledPrompt,
|
|
49
|
+
wasHintShown
|
|
50
|
+
} from "./token-goat-chunk-GL3ETKSC.mjs";
|
|
51
|
+
import {
|
|
52
|
+
claimFirstSavingsReceipt,
|
|
53
|
+
recordStat
|
|
54
|
+
} from "./token-goat-chunk-U4WHMG6Y.mjs";
|
|
55
|
+
import {
|
|
56
|
+
getDb
|
|
57
|
+
} from "./token-goat-chunk-GVB2MUST.mjs";
|
|
58
|
+
import {
|
|
59
|
+
loadConfig
|
|
60
|
+
} from "./token-goat-chunk-7EZTZOMC.mjs";
|
|
61
|
+
import {
|
|
62
|
+
detectHarness,
|
|
63
|
+
getHarnessName
|
|
64
|
+
} from "./token-goat-chunk-QYHO5CPH.mjs";
|
|
65
|
+
import {
|
|
66
|
+
envBool,
|
|
67
|
+
envInt
|
|
68
|
+
} from "./token-goat-chunk-IVE6U7KV.mjs";
|
|
69
|
+
import {
|
|
70
|
+
countNoun,
|
|
71
|
+
ensureDirSync,
|
|
72
|
+
extractErrorMessage,
|
|
73
|
+
runGit
|
|
74
|
+
} from "./token-goat-chunk-HU4TORC5.mjs";
|
|
75
|
+
import {
|
|
76
|
+
stripUnsafeSuggestions
|
|
77
|
+
} from "./token-goat-chunk-GGGG7RWB.mjs";
|
|
78
|
+
import {
|
|
79
|
+
ENV_KEYS,
|
|
80
|
+
VERSION,
|
|
81
|
+
globalDbPath
|
|
82
|
+
} from "./token-goat-chunk-CO3UYX6G.mjs";
|
|
83
|
+
import {
|
|
84
|
+
init_define_import_meta_env
|
|
85
|
+
} from "./token-goat-chunk-A37V4PBF.mjs";
|
|
86
|
+
|
|
87
|
+
// src/pending_context.ts
|
|
88
|
+
init_define_import_meta_env();
|
|
89
|
+
import { readFileSync, rmSync, writeFileSync } from "node:fs";
|
|
90
|
+
import { dirname } from "node:path";
|
|
91
|
+
var PENDING_SUFFIX = ".pending-context.txt";
|
|
92
|
+
var MAX_PENDING_CONTEXT_BYTES = 4096;
|
|
93
|
+
function queuePendingContext(stateKey, text) {
|
|
94
|
+
const trimmed = text.trim();
|
|
95
|
+
if (trimmed === "") return;
|
|
96
|
+
const target = sessionSidecarPath(stateKey, PENDING_SUFFIX);
|
|
97
|
+
if (target === null) return;
|
|
98
|
+
try {
|
|
99
|
+
const capped = fitPending(readPending(target), trimmed);
|
|
100
|
+
ensureDirSync(dirname(target));
|
|
101
|
+
writeFileSync(target, capped, "utf8");
|
|
102
|
+
} catch {
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
function replacePendingContextBlock(stateKey, text, blockStart) {
|
|
106
|
+
const target = sessionSidecarPath(stateKey, PENDING_SUFFIX);
|
|
107
|
+
if (target === null) return;
|
|
108
|
+
try {
|
|
109
|
+
const existing = readPending(target);
|
|
110
|
+
const at = existing === null ? -1 : existing.indexOf(blockStart);
|
|
111
|
+
if (existing !== null && at >= 0) {
|
|
112
|
+
const kept = existing.slice(0, at).trim();
|
|
113
|
+
if (kept === "") rmSync(target, { force: true });
|
|
114
|
+
else writeFileSync(target, kept, "utf8");
|
|
115
|
+
}
|
|
116
|
+
} catch {
|
|
117
|
+
}
|
|
118
|
+
queuePendingContext(stateKey, text);
|
|
119
|
+
}
|
|
120
|
+
function peekPendingContext(stateKey) {
|
|
121
|
+
const target = sessionSidecarPath(stateKey, PENDING_SUFFIX);
|
|
122
|
+
return target === null ? null : readPending(target);
|
|
123
|
+
}
|
|
124
|
+
function peekPendingContextWith(stateKey, carried) {
|
|
125
|
+
const target = sessionSidecarPath(stateKey, PENDING_SUFFIX);
|
|
126
|
+
const existing = target === null ? null : readPending(target);
|
|
127
|
+
const text = fitPending(existing, carried.trim());
|
|
128
|
+
if (target !== null && existing !== null && !text.includes(existing)) {
|
|
129
|
+
try {
|
|
130
|
+
rmSync(target, { force: true });
|
|
131
|
+
} catch {
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
return text;
|
|
135
|
+
}
|
|
136
|
+
function commitPendingContext(stateKey, delivered) {
|
|
137
|
+
if (delivered === null || delivered === "") return;
|
|
138
|
+
const target = sessionSidecarPath(stateKey, PENDING_SUFFIX);
|
|
139
|
+
if (target === null) return;
|
|
140
|
+
const queued = readPending(target);
|
|
141
|
+
if (queued === null) return;
|
|
142
|
+
if (!delivered.includes(queued) && !delivered.includes(stripUnsafeSuggestions(queued))) return;
|
|
143
|
+
try {
|
|
144
|
+
rmSync(target, { force: true });
|
|
145
|
+
} catch {
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
function fitPending(existing, text) {
|
|
149
|
+
if (existing !== null) {
|
|
150
|
+
const merged = `${existing}
|
|
151
|
+
${text}`;
|
|
152
|
+
if (merged.length <= MAX_PENDING_CONTEXT_BYTES) return merged;
|
|
153
|
+
}
|
|
154
|
+
if (text.length <= MAX_PENDING_CONTEXT_BYTES) return text;
|
|
155
|
+
const head = text.slice(0, MAX_PENDING_CONTEXT_BYTES);
|
|
156
|
+
const lineEnd = head.lastIndexOf("\n");
|
|
157
|
+
if (lineEnd > 0) return head.slice(0, lineEnd).trimEnd();
|
|
158
|
+
return /[\uD800-\uDBFF]$/.test(head) ? head.slice(0, -1) : head;
|
|
159
|
+
}
|
|
160
|
+
function readPending(target) {
|
|
161
|
+
try {
|
|
162
|
+
const raw = readFileSync(target, "utf8").trim();
|
|
163
|
+
return raw === "" ? null : raw;
|
|
164
|
+
} catch {
|
|
165
|
+
return null;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
// src/session_start_owed.ts
|
|
170
|
+
init_define_import_meta_env();
|
|
171
|
+
import { readFileSync as readFileSync2, rmSync as rmSync2, writeFileSync as writeFileSync2 } from "node:fs";
|
|
172
|
+
import { dirname as dirname2 } from "node:path";
|
|
173
|
+
var SETTLED_SUFFIX = ".session-start";
|
|
174
|
+
var OWED_CLAIM_SUFFIX = ".session-start-owed";
|
|
175
|
+
var OWED_RESERVE_MS = 1e3;
|
|
176
|
+
function parseMarker(raw) {
|
|
177
|
+
if (raw === null || typeof raw !== "object" || Array.isArray(raw)) return null;
|
|
178
|
+
const { finishedAtMs, deadlineEpoch } = raw;
|
|
179
|
+
if (typeof finishedAtMs !== "number" || !Number.isFinite(finishedAtMs)) return null;
|
|
180
|
+
if (deadlineEpoch === null) return { finishedAtMs, deadlineEpoch: null };
|
|
181
|
+
if (typeof deadlineEpoch !== "number" || !Number.isFinite(deadlineEpoch)) return null;
|
|
182
|
+
return { finishedAtMs, deadlineEpoch };
|
|
183
|
+
}
|
|
184
|
+
function recordSessionStartSettled(event, marker) {
|
|
185
|
+
const target = sessionSidecarPath(sessionStateKey(event), SETTLED_SUFFIX);
|
|
186
|
+
if (target === null) return;
|
|
187
|
+
try {
|
|
188
|
+
ensureDirSync(dirname2(target));
|
|
189
|
+
writeFileSync2(target, JSON.stringify(marker), "utf8");
|
|
190
|
+
} catch {
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
function removeSidecar(event, suffix) {
|
|
194
|
+
const target = sessionSidecarPath(sessionStateKey(event), suffix);
|
|
195
|
+
if (target === null) return;
|
|
196
|
+
try {
|
|
197
|
+
rmSync2(target, { force: true });
|
|
198
|
+
} catch {
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
function recordSessionStartBegun(event) {
|
|
202
|
+
const target = sessionSidecarPath(sessionStateKey(event), SETTLED_SUFFIX);
|
|
203
|
+
if (target === null) return;
|
|
204
|
+
try {
|
|
205
|
+
ensureDirSync(dirname2(target));
|
|
206
|
+
writeFileSync2(target, JSON.stringify({ begunAtMs: Date.now() }), "utf8");
|
|
207
|
+
} catch {
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
function releaseOwedSessionStart(event) {
|
|
211
|
+
removeSidecar(event, OWED_CLAIM_SUFFIX);
|
|
212
|
+
}
|
|
213
|
+
function readSessionStartRecord(event) {
|
|
214
|
+
const target = sessionSidecarPath(sessionStateKey(event), SETTLED_SUFFIX);
|
|
215
|
+
if (target === null) return null;
|
|
216
|
+
let raw;
|
|
217
|
+
try {
|
|
218
|
+
raw = readFileSync2(target, "utf8");
|
|
219
|
+
} catch {
|
|
220
|
+
return null;
|
|
221
|
+
}
|
|
222
|
+
try {
|
|
223
|
+
return parseMarker(JSON.parse(raw)) ?? "begun";
|
|
224
|
+
} catch {
|
|
225
|
+
return "begun";
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
function sessionStartOwed(record, _now) {
|
|
229
|
+
if (record === null) return false;
|
|
230
|
+
if (record === "begun") return true;
|
|
231
|
+
if (record.deadlineEpoch === null) return false;
|
|
232
|
+
return record.finishedAtMs > record.deadlineEpoch - OWED_RESERVE_MS;
|
|
233
|
+
}
|
|
234
|
+
function claimOwedSessionStart(event) {
|
|
235
|
+
const target = sessionSidecarPath(sessionStateKey(event), OWED_CLAIM_SUFFIX);
|
|
236
|
+
if (target === null) return false;
|
|
237
|
+
try {
|
|
238
|
+
ensureDirSync(dirname2(target));
|
|
239
|
+
writeFileSync2(target, JSON.stringify({ claimedAtMs: Date.now() }), { encoding: "utf8", flag: "wx" });
|
|
240
|
+
return true;
|
|
241
|
+
} catch {
|
|
242
|
+
return false;
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
var carriedOwed = /* @__PURE__ */ new WeakMap();
|
|
246
|
+
var offeredOwed = /* @__PURE__ */ new WeakMap();
|
|
247
|
+
function carryOwedSessionStart(event, text) {
|
|
248
|
+
carriedOwed.set(event, text.trim());
|
|
249
|
+
}
|
|
250
|
+
function offerOwedSessionStart(event, offered) {
|
|
251
|
+
offeredOwed.set(event, offered);
|
|
252
|
+
}
|
|
253
|
+
function carriedOwedSessionStart(event) {
|
|
254
|
+
return carriedOwed.get(event);
|
|
255
|
+
}
|
|
256
|
+
function requeueUndeliveredOwedSessionStart(event, delivered) {
|
|
257
|
+
const carried = carriedOwed.get(event);
|
|
258
|
+
if (carried === void 0) return;
|
|
259
|
+
carriedOwed.delete(event);
|
|
260
|
+
const offered = offeredOwed.get(event) ?? carried;
|
|
261
|
+
offeredOwed.delete(event);
|
|
262
|
+
if (carried === "") return;
|
|
263
|
+
try {
|
|
264
|
+
if (delivered !== null && (delivered.includes(offered) || delivered.includes(stripUnsafeSuggestions(offered)))) return;
|
|
265
|
+
queuePendingContext(sessionStateKey(event), carried);
|
|
266
|
+
} catch {
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
// src/hooks_session_start.ts
|
|
271
|
+
init_define_import_meta_env();
|
|
272
|
+
function reconcileNote(cwd, indexed) {
|
|
273
|
+
if (!indexed) return null;
|
|
274
|
+
if (!envBool(ENV_KEYS.RECONCILE, true)) return null;
|
|
275
|
+
try {
|
|
276
|
+
const budgetMs = envInt(ENV_KEYS.RECONCILE_BUDGET_MS, DEFAULT_RECONCILE_BUDGET_MS, 0, 6e4);
|
|
277
|
+
const result = reconcileProject({ cwd, budgetMs });
|
|
278
|
+
if (isReconcileClean(result) && !result.budgetExhausted) return null;
|
|
279
|
+
const upgraded = result.parserStale + result.embedStale;
|
|
280
|
+
const edited = result.changed.length - upgraded;
|
|
281
|
+
const parts = [];
|
|
282
|
+
if (edited > 0) parts.push(`${edited} changed`);
|
|
283
|
+
if (result.added.length > 0) parts.push(`${result.added.length} new`);
|
|
284
|
+
if (result.removed.length > 0) parts.push(`${result.removed.length} removed`);
|
|
285
|
+
const breakdown = parts.length > 1 ? ` (${parts.join(", ")})` : "";
|
|
286
|
+
const truncated = result.budgetExhausted ? ` (sweep stopped at its time budget with ${countNoun(result.unscanned, "file")} unchecked, so there may be more)` : "";
|
|
287
|
+
const total = result.changed.length + result.added.length + result.removed.length;
|
|
288
|
+
if (total === 0) {
|
|
289
|
+
return `token-goat: index drift check${truncated} found nothing in the part it had time to scan. Symbol lookups may be briefly stale.`;
|
|
290
|
+
}
|
|
291
|
+
const drifted = total - upgraded;
|
|
292
|
+
const clauses = [];
|
|
293
|
+
if (drifted > 0) clauses.push(`${countNoun(drifted, "file")} that changed outside this session${breakdown}`);
|
|
294
|
+
if (upgraded > 0) clauses.push(`${countNoun(upgraded, "file")} unchanged on disk but indexed by an older version of token-goat`);
|
|
295
|
+
const unqueued = total - result.enqueued;
|
|
296
|
+
if (unqueued > 0) {
|
|
297
|
+
const refused = unqueued < total ? `${unqueued} of them` : total === 1 ? "it" : "they";
|
|
298
|
+
return `token-goat: found ${clauses.join(" and ")}${truncated}, but ${refused} could not be queued for reindexing, so symbol lookups may stay stale until token-goat index runs here.`;
|
|
299
|
+
}
|
|
300
|
+
return `token-goat: reindexing ${clauses.join(" and ")}${truncated}. Symbol lookups may be briefly stale.`;
|
|
301
|
+
} catch (e) {
|
|
302
|
+
recordStat("reconcile_note_failed", 0, 0, void 0, extractErrorMessage(e));
|
|
303
|
+
return null;
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
async function postCompactRecovery(event) {
|
|
307
|
+
if (event.raw["source"] !== "compact" || event.sessionId === void 0) return null;
|
|
308
|
+
if (!loadConfig().compact_assist.enabled) return null;
|
|
309
|
+
try {
|
|
310
|
+
const { buildResumePacket } = await import("./token-goat-chunk-T5YGG4V3.mjs");
|
|
311
|
+
return await buildResumePacket(event.sessionId);
|
|
312
|
+
} catch {
|
|
313
|
+
return null;
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
async function sessionStartHandler(event) {
|
|
317
|
+
recordSessionStartBegun(event);
|
|
318
|
+
const output = withSavingsReceipt(await sessionStartOutput(event));
|
|
319
|
+
recordSessionStartSettled(event, { finishedAtMs: Date.now(), deadlineEpoch: shimDeadlineEpoch() });
|
|
320
|
+
return output;
|
|
321
|
+
}
|
|
322
|
+
function shimDeadlineEpoch() {
|
|
323
|
+
const raw = process.env["TG_SESSION_START_DEADLINE_EPOCH"];
|
|
324
|
+
if (raw === void 0 || raw.trim() === "") return null;
|
|
325
|
+
const value = Number(raw);
|
|
326
|
+
return Number.isFinite(value) && value > 0 ? value : null;
|
|
327
|
+
}
|
|
328
|
+
function savingsReceiptText(tokens) {
|
|
329
|
+
return `token-goat has saved about ${tokens.toLocaleString("en-US")} tokens so far. Run \`token-goat stats\` for the detail.`;
|
|
330
|
+
}
|
|
331
|
+
function withSavingsReceipt(output, homeDir) {
|
|
332
|
+
if (output.hookType !== "pass" && output.hookType !== "context") return output;
|
|
333
|
+
if (detectHarness() !== "claudecode") return output;
|
|
334
|
+
const saved = claimFirstSavingsReceipt(void 0, homeDir);
|
|
335
|
+
return saved === null ? output : { ...output, notice: savingsReceiptText(saved) };
|
|
336
|
+
}
|
|
337
|
+
async function sessionStartOutput(event, options = {}) {
|
|
338
|
+
const recovery = options.skipRecovery === true ? null : await postCompactRecovery(event);
|
|
339
|
+
const cwd = getCwd(event);
|
|
340
|
+
const { anchorStatus } = await import("./token-goat-chunk-TWUKBOMP.mjs");
|
|
341
|
+
const tail = [projectNotesFor(cwd, anchorStatus), recovery].filter((part) => part !== null).join("\n\n");
|
|
342
|
+
const tailOnly = () => tail === "" ? passOutput() : contextOutput(tail);
|
|
343
|
+
try {
|
|
344
|
+
if (!loadConfig().hints.session_start_reminder) return tailOnly();
|
|
345
|
+
const { isIndexedRoot } = await import("./token-goat-chunk-VTJLAA7P.mjs");
|
|
346
|
+
const indexed = isIndexedRoot(cwd);
|
|
347
|
+
let context = buildReminder(indexed);
|
|
348
|
+
if (cwd !== void 0) {
|
|
349
|
+
const drift = reconcileNote(cwd, indexed);
|
|
350
|
+
if (drift !== null) context += `
|
|
351
|
+
|
|
352
|
+
${drift}`;
|
|
353
|
+
const capsule = buildDeltaCapsule(cwd);
|
|
354
|
+
if (capsule !== null) context += `
|
|
355
|
+
|
|
356
|
+
${capsule}`;
|
|
357
|
+
}
|
|
358
|
+
try {
|
|
359
|
+
const dbHealth = checkSymbolBodySize(globalDbPath());
|
|
360
|
+
if (dbHealth.status === "warn") {
|
|
361
|
+
context += ` token-goat: ${dbHealth.message}`;
|
|
362
|
+
}
|
|
363
|
+
} catch {
|
|
364
|
+
}
|
|
365
|
+
try {
|
|
366
|
+
const { currentUpgradeDecision, getCachedUpdateStatus, updateAdvice } = await import("./token-goat-chunk-U2KSB4SG.mjs");
|
|
367
|
+
const update = getCachedUpdateStatus();
|
|
368
|
+
const advice = update === null ? null : updateAdvice(currentUpgradeDecision(update));
|
|
369
|
+
if (update?.latest && advice !== null) {
|
|
370
|
+
context += `
|
|
371
|
+
[token-goat update available: v${update.current} -> v${update.latest}. ${advice}]`;
|
|
372
|
+
}
|
|
373
|
+
} catch {
|
|
374
|
+
}
|
|
375
|
+
if (tail !== "") context += `
|
|
376
|
+
|
|
377
|
+
${tail}`;
|
|
378
|
+
return contextOutput(context);
|
|
379
|
+
} catch {
|
|
380
|
+
return tailOnly();
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
registerHook("session_start", sessionStartHandler);
|
|
384
|
+
|
|
385
|
+
// src/hooks_session.ts
|
|
386
|
+
init_define_import_meta_env();
|
|
387
|
+
import crypto from "node:crypto";
|
|
388
|
+
|
|
389
|
+
// src/skill_version_drift.ts
|
|
390
|
+
init_define_import_meta_env();
|
|
391
|
+
var TRACKED_SKILL = "token-goat";
|
|
392
|
+
var MAX_COMMANDS_SHOWN = 8;
|
|
393
|
+
async function currentCommandNames() {
|
|
394
|
+
const { buildProgram } = await import("./token-goat-chunk-YY6AVUFL.mjs");
|
|
395
|
+
return flattenCommandNames(buildCommandManifest(buildProgram()));
|
|
396
|
+
}
|
|
397
|
+
async function recordSkillVersionSnapshot(sessionId, skillName) {
|
|
398
|
+
if (skillName !== TRACKED_SKILL || !sessionId) return;
|
|
399
|
+
try {
|
|
400
|
+
const db = getDb(globalDbPath());
|
|
401
|
+
const commands = JSON.stringify(await currentCommandNames());
|
|
402
|
+
db.prepare(
|
|
403
|
+
`INSERT INTO skill_version_snapshots (session_id, skill_name, loaded_version, loaded_commands_json, notified_at)
|
|
404
|
+
VALUES (@sessionId, @skillName, @version, @commands, NULL)
|
|
405
|
+
ON CONFLICT(session_id) DO UPDATE SET
|
|
406
|
+
skill_name = @skillName, loaded_version = @version, loaded_commands_json = @commands, notified_at = NULL`
|
|
407
|
+
).run({ sessionId, skillName, version: VERSION, commands });
|
|
408
|
+
} catch {
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
async function checkSkillVersionDrift(sessionId) {
|
|
412
|
+
if (!sessionId) return null;
|
|
413
|
+
try {
|
|
414
|
+
const db = getDb(globalDbPath());
|
|
415
|
+
const row = db.prepare(
|
|
416
|
+
`SELECT skill_name, loaded_version, loaded_commands_json, notified_at
|
|
417
|
+
FROM skill_version_snapshots WHERE session_id = ?`
|
|
418
|
+
).get(sessionId);
|
|
419
|
+
if (!row || row.skill_name !== TRACKED_SKILL) return null;
|
|
420
|
+
if (row.notified_at !== null) return null;
|
|
421
|
+
if (row.loaded_version === VERSION) return null;
|
|
422
|
+
db.prepare(`UPDATE skill_version_snapshots SET notified_at = @now WHERE session_id = @sessionId`).run({
|
|
423
|
+
now: Date.now() / 1e3,
|
|
424
|
+
sessionId
|
|
425
|
+
});
|
|
426
|
+
let loadedCommands = [];
|
|
427
|
+
try {
|
|
428
|
+
const parsed = JSON.parse(row.loaded_commands_json);
|
|
429
|
+
if (Array.isArray(parsed)) loadedCommands = parsed;
|
|
430
|
+
} catch {
|
|
431
|
+
loadedCommands = [];
|
|
432
|
+
}
|
|
433
|
+
const loadedSet = new Set(loadedCommands);
|
|
434
|
+
const newCommands = (await currentCommandNames()).filter((c) => !loadedSet.has(c));
|
|
435
|
+
if (newCommands.length === 0) {
|
|
436
|
+
return `[token-goat: upgraded v${row.loaded_version} -> v${VERSION} since you loaded this skill -- run \`token-goat commands\` if anything seems missing]`;
|
|
437
|
+
}
|
|
438
|
+
const shown = newCommands.slice(0, MAX_COMMANDS_SHOWN);
|
|
439
|
+
const more = newCommands.length > shown.length ? ` (+${newCommands.length - shown.length} more)` : "";
|
|
440
|
+
return `[token-goat: upgraded v${row.loaded_version} -> v${VERSION} since you loaded this skill -- ${countNoun(newCommands.length, "new command")} available: ${shown.join(", ")}${more}. Run \`token-goat commands\` for full details.]`;
|
|
441
|
+
} catch {
|
|
442
|
+
return null;
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
// src/hooks_session.ts
|
|
447
|
+
async function deliverOwedSessionStart(event) {
|
|
448
|
+
try {
|
|
449
|
+
if (event.agentId !== void 0 || !sessionStartMayBeDeferred(getHarnessName())) return;
|
|
450
|
+
if (!sessionStartOwed(readSessionStartRecord(event), Date.now()) || !claimOwedSessionStart(event)) return;
|
|
451
|
+
try {
|
|
452
|
+
const owed = await sessionStartOutput(event, { skipRecovery: true });
|
|
453
|
+
if (owed.hookType === "context") carryOwedSessionStart(event, owed.context);
|
|
454
|
+
} catch (error) {
|
|
455
|
+
releaseOwedSessionStart(event);
|
|
456
|
+
throw error;
|
|
457
|
+
}
|
|
458
|
+
recordStat("session_start_deferred", 0, 0);
|
|
459
|
+
} catch {
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
async function pendingContextHandler(event) {
|
|
463
|
+
try {
|
|
464
|
+
if (event.sessionId) await deliverOwedSessionStart(event);
|
|
465
|
+
if (!event.sessionId || !dropsPromptSubmitContext() && !dropsPreCompactContext() && !sessionStartMayBeDeferred(getHarnessName())) return passOutput();
|
|
466
|
+
const carried = carriedOwedSessionStart(event);
|
|
467
|
+
if (carried !== void 0) {
|
|
468
|
+
const offered = peekPendingContextWith(sessionStateKey(event), carried);
|
|
469
|
+
offerOwedSessionStart(event, offered);
|
|
470
|
+
return contextOutput(offered);
|
|
471
|
+
}
|
|
472
|
+
const pending = peekPendingContext(sessionStateKey(event));
|
|
473
|
+
return pending === null ? passOutput() : contextOutput(pending);
|
|
474
|
+
} catch {
|
|
475
|
+
return passOutput();
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
var EMBEDDED_SKILL_CONTEXT_RE = /^\s*<skill-context\b/i;
|
|
479
|
+
var CONTINUATION_PROMPT_RE = /^(?:continue|resume|next|go on)$/i;
|
|
480
|
+
var SCHEDULED_PROMPT_RE = /^\[Scheduled prompt #(\d+)\]/i;
|
|
481
|
+
var SCHEDULED_PROMPT_PRESSURE_THRESHOLDS = /* @__PURE__ */ new Set([25, 100, 250]);
|
|
482
|
+
function promptFingerprint(prompt) {
|
|
483
|
+
return crypto.createHash("sha256").update(prompt).digest("hex").slice(0, 16);
|
|
484
|
+
}
|
|
485
|
+
function residentContextHints(event) {
|
|
486
|
+
const transcriptPath = event.raw["transcript_path"];
|
|
487
|
+
if (typeof transcriptPath !== "string" || transcriptPath === "") return [];
|
|
488
|
+
const taskKey = `resident-task-list:${event.sessionId}`;
|
|
489
|
+
const skillKey = `resident-skill-body:${event.sessionId}`;
|
|
490
|
+
const wantTask = !wasHintShown(taskKey);
|
|
491
|
+
const wantSkill = !wasHintShown(skillKey);
|
|
492
|
+
if (!wantTask && !wantSkill) return [];
|
|
493
|
+
const lines = readTranscriptTail(transcriptPath).filter(lineMayCarryResidentSignal);
|
|
494
|
+
if (lines.length === 0) return [];
|
|
495
|
+
const summary = summarizeResidentContext(accumulateResidentLines(lines));
|
|
496
|
+
const hints = [];
|
|
497
|
+
if (wantTask) {
|
|
498
|
+
const hint = taskListPruneHint(summary.latestTaskList);
|
|
499
|
+
if (hint !== null) {
|
|
500
|
+
markHintShown(taskKey);
|
|
501
|
+
hints.push(hint);
|
|
502
|
+
}
|
|
503
|
+
}
|
|
504
|
+
if (wantSkill) {
|
|
505
|
+
const hint = repeatedSkillBodyHint(summary.repeatedSkillBodies);
|
|
506
|
+
if (hint !== null) {
|
|
507
|
+
markHintShown(skillKey);
|
|
508
|
+
hints.push(hint);
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
if (hints.length > 0) recordStat("session_hint", 0, 0);
|
|
512
|
+
return hints;
|
|
513
|
+
}
|
|
514
|
+
async function userPromptSubmitHandler(event) {
|
|
515
|
+
try {
|
|
516
|
+
const rawPrompt = event.raw["prompt"] || "";
|
|
517
|
+
if (!event.sessionId) {
|
|
518
|
+
return passOutput();
|
|
519
|
+
}
|
|
520
|
+
const parts = [];
|
|
521
|
+
const prompt = rawPrompt.trim();
|
|
522
|
+
if (EMBEDDED_SKILL_CONTEXT_RE.test(prompt)) {
|
|
523
|
+
const key = `embedded-skill:${event.sessionId}:${promptFingerprint(prompt)}`;
|
|
524
|
+
if (wasHintShown(key)) {
|
|
525
|
+
parts.push("This identical embedded skill payload was already provided in this session; treat it as loaded and do not re-read its full body.");
|
|
526
|
+
} else {
|
|
527
|
+
markHintShown(key);
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
if (CONTINUATION_PROMPT_RE.test(prompt)) {
|
|
531
|
+
const key = `continuation-checkpoint:${event.sessionId}`;
|
|
532
|
+
if (!wasHintShown(key)) {
|
|
533
|
+
markHintShown(key);
|
|
534
|
+
parts.push("Before a long continuation loop, checkpoint the current goal and evidence; start a fresh session when earlier context is no longer needed.");
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
const scheduledPrompt = SCHEDULED_PROMPT_RE.exec(prompt);
|
|
538
|
+
if (scheduledPrompt !== null) {
|
|
539
|
+
const occurrence = recordScheduledPrompt(event.sessionId);
|
|
540
|
+
if (SCHEDULED_PROMPT_PRESSURE_THRESHOLDS.has(occurrence)) {
|
|
541
|
+
const key = `scheduled-prompt-pressure:${event.sessionId}:${occurrence}`;
|
|
542
|
+
if (!wasHintShown(key)) {
|
|
543
|
+
markHintShown(key);
|
|
544
|
+
parts.push(`This is scheduled prompt delivery #${occurrence} (schedule #${scheduledPrompt[1]}). Checkpoint the current objective and start a fresh session before continuing if earlier context is no longer needed; this cannot reclaim tokens already injected.`);
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
}
|
|
548
|
+
if (prompt.length >= 8) {
|
|
549
|
+
const cwd = getCwd(event);
|
|
550
|
+
if (cwd) {
|
|
551
|
+
try {
|
|
552
|
+
const result = runGit(["rev-parse", "--abbrev-ref", "HEAD"], { cwd, timeoutMs: loadConfig().hints.git_hint_max_ms });
|
|
553
|
+
if (result.exitCode === 0 && result.stdout) {
|
|
554
|
+
const branch = result.stdout.trim();
|
|
555
|
+
if (branch) {
|
|
556
|
+
parts.push(`branch: ${branch}`);
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
} catch {
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
const driftNudge = await checkSkillVersionDrift(event.sessionId);
|
|
564
|
+
const residentHints = residentContextHints(event);
|
|
565
|
+
const resumed = resumesCompactionOnPrompt() ? peekPendingContext(sessionStateKey(event)) : null;
|
|
566
|
+
if (parts.length === 0 && !driftNudge && residentHints.length === 0 && resumed === null) {
|
|
567
|
+
return passOutput();
|
|
568
|
+
}
|
|
569
|
+
const lines = [];
|
|
570
|
+
if (resumed !== null) {
|
|
571
|
+
lines.push(resumed);
|
|
572
|
+
}
|
|
573
|
+
if (parts.length > 0) {
|
|
574
|
+
lines.push("[" + parts.join(" | ") + "]");
|
|
575
|
+
}
|
|
576
|
+
if (driftNudge) {
|
|
577
|
+
lines.push(driftNudge);
|
|
578
|
+
}
|
|
579
|
+
for (const hint of residentHints) {
|
|
580
|
+
lines.push(hint);
|
|
581
|
+
}
|
|
582
|
+
const text = lines.join("\n");
|
|
583
|
+
if (dropsPromptSubmitContext()) {
|
|
584
|
+
queuePendingContext(sessionStateKey(event), text);
|
|
585
|
+
return passOutput();
|
|
586
|
+
}
|
|
587
|
+
return contextOutput(text);
|
|
588
|
+
} catch {
|
|
589
|
+
return passOutput();
|
|
590
|
+
}
|
|
591
|
+
}
|
|
592
|
+
var CLAIMED_COMMIT_VERBS_RE = /\b(commit(?:ted|s|ting)?|push(?:ed|es|ing)?)\b/i;
|
|
593
|
+
function claimsCommittedChange(message) {
|
|
594
|
+
return CLAIMED_COMMIT_VERBS_RE.test(message);
|
|
595
|
+
}
|
|
596
|
+
registerHook("user_prompt_submit", userPromptSubmitHandler);
|
|
597
|
+
registerHook("post_tool_use", pendingContextHandler, { advisory: true, followsMatcher: true });
|
|
598
|
+
|
|
599
|
+
export {
|
|
600
|
+
MAX_PENDING_CONTEXT_BYTES,
|
|
601
|
+
replacePendingContextBlock,
|
|
602
|
+
commitPendingContext,
|
|
603
|
+
requeueUndeliveredOwedSessionStart,
|
|
604
|
+
recordSkillVersionSnapshot,
|
|
605
|
+
claimsCommittedChange
|
|
606
|
+
};
|