@danya-ai/cli 0.1.1 → 0.1.3
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 +33 -3
- package/dist/REPL-5VRUWUUA.js +42 -0
- package/dist/{acp-XPFY5L23.js → acp-SBV4SUS5.js} +26 -26
- package/dist/{agentsValidate-YP7GA4ER.js → agentsValidate-GBCUUJ37.js} +7 -7
- package/dist/{ask-F53PCNWW.js → ask-A44NOQXG.js} +25 -25
- package/dist/{autoUpdater-PAZTRW74.js → autoUpdater-7XV25FPF.js} +3 -3
- package/dist/{chunk-5GADLAR7.js → chunk-2ZWXQRFX.js} +1 -1
- package/dist/{chunk-EOZSZNKR.js → chunk-3IXSSL3F.js} +3 -3
- package/dist/{chunk-JKRPU66R.js → chunk-5GHO3SUE.js} +4 -4
- package/dist/{chunk-5552MSXN.js → chunk-66P52YYI.js} +1 -1
- package/dist/{chunk-3LC6LWSN.js → chunk-6Z7EGLJB.js} +1 -1
- package/dist/{chunk-QUV2YCUP.js → chunk-AL7YT6CO.js} +1742 -234
- package/dist/chunk-AL7YT6CO.js.map +7 -0
- package/dist/{chunk-NFMXSWNI.js → chunk-CEARH7HF.js} +3 -3
- package/dist/{chunk-CDS5HL6U.js → chunk-CSAIELUO.js} +2 -2
- package/dist/chunk-DKOCP6VD.js.map +7 -0
- package/dist/{chunk-LO3O7WT2.js → chunk-EPA5LFNP.js} +2 -2
- package/dist/{chunk-2ON4OVWS.js → chunk-F4DQYOST.js} +2 -2
- package/dist/{chunk-4FOB6KC5.js → chunk-FCXTZVJG.js} +3 -3
- package/dist/{chunk-UOERQDSJ.js → chunk-HGMX7LUU.js} +1 -1
- package/dist/{chunk-DQ3YBGNC.js → chunk-HPXXYGE5.js} +3 -3
- package/dist/{chunk-WTLJM7O2.js → chunk-KMJTUDQT.js} +3 -3
- package/dist/{chunk-5XPLGRCI.js → chunk-LWSO4XGK.js} +11 -11
- package/dist/{chunk-KS5K2JLY.js → chunk-NWCMSPVL.js} +1 -1
- package/dist/{chunk-UYR5Q3GS.js → chunk-NYT5K544.js} +1 -1
- package/dist/{chunk-UYR5Q3GS.js.map → chunk-NYT5K544.js.map} +1 -1
- package/dist/{chunk-DH6PY5WA.js → chunk-OPC7BAW5.js} +1 -1
- package/dist/{chunk-RIE2FUKS.js → chunk-PFTCTG5X.js} +2 -2
- package/dist/{chunk-7NTVKI6U.js → chunk-PKOEWHPC.js} +1 -1
- package/dist/{chunk-L4IPQYSY.js → chunk-S7FJMZJQ.js} +3 -3
- package/dist/{chunk-QOWU527O.js → chunk-U5SAUK33.js} +4 -4
- package/dist/{chunk-JIBQDOXO.js → chunk-VUWBPLA2.js} +1 -1
- package/dist/{chunk-DVRQKRHN.js → chunk-W5HDZPFZ.js} +2 -2
- package/dist/{chunk-ZS6GNOVF.js → chunk-XQVGT6FI.js} +2 -2
- package/dist/{chunk-TLCZFEI3.js → chunk-YMT4ZP5L.js} +3 -3
- package/dist/{chunk-DYHI3HU4.js → chunk-ZVXACFY4.js} +1 -1
- package/dist/{cli-74WUWFKO.js → cli-7F5UP7H3.js} +78 -78
- package/dist/commands-2B3NLK4I.js +46 -0
- package/dist/{config-KBJLBJ4F.js → config-NUGWMTAD.js} +4 -4
- package/dist/{context-SUQRQHNG.js → context-IU336CQN.js} +5 -5
- package/dist/{customCommands-4H5TDSCI.js → customCommands-H26PZL7C.js} +4 -4
- package/dist/{env-EBAMYGTP.js → env-XZ365TBZ.js} +2 -2
- package/dist/index.js +3 -3
- package/dist/{kodeAgentSessionLoad-OEYEYLKG.js → kodeAgentSessionLoad-3SQDQPTS.js} +4 -4
- package/dist/{kodeAgentSessionResume-53WMZDR6.js → kodeAgentSessionResume-URRDKPNQ.js} +4 -4
- package/dist/{kodeAgentStreamJsonSession-QQV52SDB.js → kodeAgentStreamJsonSession-DATEVTTG.js} +1 -1
- package/dist/{kodeHooks-LXHKYCVC.js → kodeHooks-QQUC3N42.js} +4 -4
- package/dist/{llm-5DSL623J.js → llm-XBH33BXT.js} +28 -28
- package/dist/{llm-5DSL623J.js.map → llm-XBH33BXT.js.map} +2 -2
- package/dist/{llmLazy-EMO4BVVB.js → llmLazy-HBMPPNDL.js} +1 -1
- package/dist/{loader-DSVKWJVQ.js → loader-2RC2FXT3.js} +4 -4
- package/dist/{mcp-3CCDCYYX.js → mcp-FBNQXOUB.js} +7 -7
- package/dist/{mentionProcessor-HRUF4ANP.js → mentionProcessor-S2QYN2CS.js} +5 -5
- package/dist/{messages-KZTRKY2I.js → messages-GOTZDIQV.js} +1 -1
- package/dist/{model-PHL6VTAG.js → model-B5TCGITV.js} +5 -5
- package/dist/{openai-M3RAQFGM.js → openai-HHXFBOUM.js} +5 -5
- package/dist/{outputStyles-6VVYMSWK.js → outputStyles-SER6OXBX.js} +4 -4
- package/dist/{pluginRuntime-TCH3K4F6.js → pluginRuntime-TJ55FZXH.js} +6 -6
- package/dist/{pluginValidation-X4A5NSMU.js → pluginValidation-JIVFSJJI.js} +6 -6
- package/dist/prompts-EL2VO3DH.js +50 -0
- package/dist/query-CMWS2UNL.js +50 -0
- package/dist/{ripgrep-TVXVT4WE.js → ripgrep-LJA652X4.js} +3 -3
- package/dist/{skillMarketplace-AXUCUS3B.js → skillMarketplace-MDN37RZ4.js} +3 -3
- package/dist/{state-SDEP3HY3.js → state-4L5XK2VN.js} +2 -2
- package/dist/{theme-SPQRPQ7O.js → theme-NNMEGAUR.js} +5 -5
- package/dist/{toolPermissionSettings-H6TWVANG.js → toolPermissionSettings-PAIDFMPX.js} +6 -6
- package/dist/tools-AZR4CVVE.js +47 -0
- package/dist/{userInput-QU3SH2SR.js → userInput-KMFH77N4.js} +27 -27
- package/package.json +1 -1
- package/dist/REPL-JPCWUTDB.js +0 -42
- package/dist/chunk-HJCCXED7.js.map +0 -7
- package/dist/chunk-QUV2YCUP.js.map +0 -7
- package/dist/commands-2ZN5PXG5.js +0 -46
- package/dist/prompts-IVLP5KLQ.js +0 -50
- package/dist/query-JIRCNAY5.js +0 -50
- package/dist/tools-G2P3XRE7.js +0 -47
- /package/dist/{REPL-JPCWUTDB.js.map → REPL-5VRUWUUA.js.map} +0 -0
- /package/dist/{acp-XPFY5L23.js.map → acp-SBV4SUS5.js.map} +0 -0
- /package/dist/{agentsValidate-YP7GA4ER.js.map → agentsValidate-GBCUUJ37.js.map} +0 -0
- /package/dist/{ask-F53PCNWW.js.map → ask-A44NOQXG.js.map} +0 -0
- /package/dist/{autoUpdater-PAZTRW74.js.map → autoUpdater-7XV25FPF.js.map} +0 -0
- /package/dist/{chunk-5GADLAR7.js.map → chunk-2ZWXQRFX.js.map} +0 -0
- /package/dist/{chunk-EOZSZNKR.js.map → chunk-3IXSSL3F.js.map} +0 -0
- /package/dist/{chunk-JKRPU66R.js.map → chunk-5GHO3SUE.js.map} +0 -0
- /package/dist/{chunk-5552MSXN.js.map → chunk-66P52YYI.js.map} +0 -0
- /package/dist/{chunk-3LC6LWSN.js.map → chunk-6Z7EGLJB.js.map} +0 -0
- /package/dist/{chunk-NFMXSWNI.js.map → chunk-CEARH7HF.js.map} +0 -0
- /package/dist/{chunk-CDS5HL6U.js.map → chunk-CSAIELUO.js.map} +0 -0
- /package/dist/{chunk-HJCCXED7.js → chunk-DKOCP6VD.js} +0 -0
- /package/dist/{chunk-LO3O7WT2.js.map → chunk-EPA5LFNP.js.map} +0 -0
- /package/dist/{chunk-2ON4OVWS.js.map → chunk-F4DQYOST.js.map} +0 -0
- /package/dist/{chunk-4FOB6KC5.js.map → chunk-FCXTZVJG.js.map} +0 -0
- /package/dist/{chunk-UOERQDSJ.js.map → chunk-HGMX7LUU.js.map} +0 -0
- /package/dist/{chunk-DQ3YBGNC.js.map → chunk-HPXXYGE5.js.map} +0 -0
- /package/dist/{chunk-WTLJM7O2.js.map → chunk-KMJTUDQT.js.map} +0 -0
- /package/dist/{chunk-5XPLGRCI.js.map → chunk-LWSO4XGK.js.map} +0 -0
- /package/dist/{chunk-KS5K2JLY.js.map → chunk-NWCMSPVL.js.map} +0 -0
- /package/dist/{chunk-DH6PY5WA.js.map → chunk-OPC7BAW5.js.map} +0 -0
- /package/dist/{chunk-RIE2FUKS.js.map → chunk-PFTCTG5X.js.map} +0 -0
- /package/dist/{chunk-7NTVKI6U.js.map → chunk-PKOEWHPC.js.map} +0 -0
- /package/dist/{chunk-L4IPQYSY.js.map → chunk-S7FJMZJQ.js.map} +0 -0
- /package/dist/{chunk-QOWU527O.js.map → chunk-U5SAUK33.js.map} +0 -0
- /package/dist/{chunk-JIBQDOXO.js.map → chunk-VUWBPLA2.js.map} +0 -0
- /package/dist/{chunk-DVRQKRHN.js.map → chunk-W5HDZPFZ.js.map} +0 -0
- /package/dist/{chunk-ZS6GNOVF.js.map → chunk-XQVGT6FI.js.map} +0 -0
- /package/dist/{chunk-TLCZFEI3.js.map → chunk-YMT4ZP5L.js.map} +0 -0
- /package/dist/{chunk-DYHI3HU4.js.map → chunk-ZVXACFY4.js.map} +0 -0
- /package/dist/{cli-74WUWFKO.js.map → cli-7F5UP7H3.js.map} +0 -0
- /package/dist/{commands-2ZN5PXG5.js.map → commands-2B3NLK4I.js.map} +0 -0
- /package/dist/{config-KBJLBJ4F.js.map → config-NUGWMTAD.js.map} +0 -0
- /package/dist/{context-SUQRQHNG.js.map → context-IU336CQN.js.map} +0 -0
- /package/dist/{customCommands-4H5TDSCI.js.map → customCommands-H26PZL7C.js.map} +0 -0
- /package/dist/{env-EBAMYGTP.js.map → env-XZ365TBZ.js.map} +0 -0
- /package/dist/{kodeAgentSessionLoad-OEYEYLKG.js.map → kodeAgentSessionLoad-3SQDQPTS.js.map} +0 -0
- /package/dist/{kodeAgentSessionResume-53WMZDR6.js.map → kodeAgentSessionResume-URRDKPNQ.js.map} +0 -0
- /package/dist/{kodeAgentStreamJsonSession-QQV52SDB.js.map → kodeAgentStreamJsonSession-DATEVTTG.js.map} +0 -0
- /package/dist/{kodeHooks-LXHKYCVC.js.map → kodeHooks-QQUC3N42.js.map} +0 -0
- /package/dist/{llmLazy-EMO4BVVB.js.map → llmLazy-HBMPPNDL.js.map} +0 -0
- /package/dist/{loader-DSVKWJVQ.js.map → loader-2RC2FXT3.js.map} +0 -0
- /package/dist/{mcp-3CCDCYYX.js.map → mcp-FBNQXOUB.js.map} +0 -0
- /package/dist/{mentionProcessor-HRUF4ANP.js.map → mentionProcessor-S2QYN2CS.js.map} +0 -0
- /package/dist/{messages-KZTRKY2I.js.map → messages-GOTZDIQV.js.map} +0 -0
- /package/dist/{model-PHL6VTAG.js.map → model-B5TCGITV.js.map} +0 -0
- /package/dist/{openai-M3RAQFGM.js.map → openai-HHXFBOUM.js.map} +0 -0
- /package/dist/{outputStyles-6VVYMSWK.js.map → outputStyles-SER6OXBX.js.map} +0 -0
- /package/dist/{pluginRuntime-TCH3K4F6.js.map → pluginRuntime-TJ55FZXH.js.map} +0 -0
- /package/dist/{pluginValidation-X4A5NSMU.js.map → pluginValidation-JIVFSJJI.js.map} +0 -0
- /package/dist/{prompts-IVLP5KLQ.js.map → prompts-EL2VO3DH.js.map} +0 -0
- /package/dist/{query-JIRCNAY5.js.map → query-CMWS2UNL.js.map} +0 -0
- /package/dist/{ripgrep-TVXVT4WE.js.map → ripgrep-LJA652X4.js.map} +0 -0
- /package/dist/{skillMarketplace-AXUCUS3B.js.map → skillMarketplace-MDN37RZ4.js.map} +0 -0
- /package/dist/{state-SDEP3HY3.js.map → state-4L5XK2VN.js.map} +0 -0
- /package/dist/{theme-SPQRPQ7O.js.map → theme-NNMEGAUR.js.map} +0 -0
- /package/dist/{toolPermissionSettings-H6TWVANG.js.map → toolPermissionSettings-PAIDFMPX.js.map} +0 -0
- /package/dist/{tools-G2P3XRE7.js.map → tools-AZR4CVVE.js.map} +0 -0
- /package/dist/{userInput-QU3SH2SR.js.map → userInput-KMFH77N4.js.map} +0 -0
|
@@ -2,7 +2,7 @@ import { createRequire as __kodeCreateRequire } from "node:module";
|
|
|
2
2
|
const require = __kodeCreateRequire(import.meta.url);
|
|
3
3
|
import {
|
|
4
4
|
listDanyaAgentSessions
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-ZVXACFY4.js";
|
|
6
6
|
import {
|
|
7
7
|
DEFAULT_TIMEOUT_MS,
|
|
8
8
|
FallbackToolUseRejectedMessage,
|
|
@@ -16,11 +16,11 @@ import {
|
|
|
16
16
|
listMCPServers,
|
|
17
17
|
loadMergedSettings,
|
|
18
18
|
normalizeSandboxRuntimeConfigFromSettings
|
|
19
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-U5SAUK33.js";
|
|
20
20
|
import {
|
|
21
21
|
formatValidationResult,
|
|
22
22
|
validatePluginOrMarketplacePath
|
|
23
|
-
} from "./chunk-
|
|
23
|
+
} from "./chunk-KMJTUDQT.js";
|
|
24
24
|
import {
|
|
25
25
|
addMarketplace,
|
|
26
26
|
disableSkillPlugin,
|
|
@@ -33,15 +33,15 @@ import {
|
|
|
33
33
|
refreshMarketplaceAsync,
|
|
34
34
|
removeMarketplace,
|
|
35
35
|
uninstallSkillPlugin
|
|
36
|
-
} from "./chunk-
|
|
36
|
+
} from "./chunk-6Z7EGLJB.js";
|
|
37
37
|
import {
|
|
38
38
|
loadDanyaAgentSessionMessages
|
|
39
|
-
} from "./chunk-
|
|
39
|
+
} from "./chunk-HGMX7LUU.js";
|
|
40
40
|
import {
|
|
41
41
|
appendSessionCustomTitleRecord,
|
|
42
42
|
appendSessionJsonlFromMessage,
|
|
43
43
|
appendSessionTagRecord
|
|
44
|
-
} from "./chunk-
|
|
44
|
+
} from "./chunk-F4DQYOST.js";
|
|
45
45
|
import {
|
|
46
46
|
getRequestStatus,
|
|
47
47
|
setRequestStatus,
|
|
@@ -58,7 +58,7 @@ import {
|
|
|
58
58
|
runStopHooks,
|
|
59
59
|
runUserPromptSubmitHooks,
|
|
60
60
|
updateHookTranscriptForMessages
|
|
61
|
-
} from "./chunk-
|
|
61
|
+
} from "./chunk-HPXXYGE5.js";
|
|
62
62
|
import {
|
|
63
63
|
getDanyaAgentSessionId,
|
|
64
64
|
setDanyaAgentSessionId
|
|
@@ -71,34 +71,34 @@ import {
|
|
|
71
71
|
getOutputStyleSystemPromptAdditions,
|
|
72
72
|
resolveOutputStyleName,
|
|
73
73
|
setCurrentOutputStyle
|
|
74
|
-
} from "./chunk-
|
|
74
|
+
} from "./chunk-CSAIELUO.js";
|
|
75
75
|
import {
|
|
76
76
|
fetchCustomModels,
|
|
77
77
|
getModelFeatures
|
|
78
|
-
} from "./chunk-
|
|
78
|
+
} from "./chunk-W5HDZPFZ.js";
|
|
79
79
|
import {
|
|
80
80
|
queryLLM,
|
|
81
81
|
queryQuick,
|
|
82
82
|
verifyApiKey
|
|
83
|
-
} from "./chunk-
|
|
83
|
+
} from "./chunk-5GHO3SUE.js";
|
|
84
84
|
import {
|
|
85
85
|
listAllContentFiles,
|
|
86
86
|
ripGrep
|
|
87
|
-
} from "./chunk-
|
|
87
|
+
} from "./chunk-66P52YYI.js";
|
|
88
88
|
import {
|
|
89
89
|
getCustomCommandDirectories,
|
|
90
90
|
hasCustomCommands,
|
|
91
91
|
loadCustomCommands,
|
|
92
92
|
reloadCustomCommands
|
|
93
|
-
} from "./chunk-
|
|
93
|
+
} from "./chunk-EPA5LFNP.js";
|
|
94
94
|
import {
|
|
95
95
|
loadToolPermissionContextFromDisk,
|
|
96
96
|
persistToolPermissionUpdateToDisk
|
|
97
|
-
} from "./chunk-
|
|
97
|
+
} from "./chunk-S7FJMZJQ.js";
|
|
98
98
|
import {
|
|
99
99
|
getSettingsFileCandidates,
|
|
100
100
|
loadSettingsWithLegacyFallback
|
|
101
|
-
} from "./chunk-
|
|
101
|
+
} from "./chunk-2ZWXQRFX.js";
|
|
102
102
|
import {
|
|
103
103
|
applyToolPermissionContextUpdate,
|
|
104
104
|
createDefaultToolPermissionContext
|
|
@@ -111,7 +111,7 @@ import {
|
|
|
111
111
|
resetReminderSession,
|
|
112
112
|
setTodos,
|
|
113
113
|
systemReminderService
|
|
114
|
-
} from "./chunk-
|
|
114
|
+
} from "./chunk-XQVGT6FI.js";
|
|
115
115
|
import {
|
|
116
116
|
getSessionState
|
|
117
117
|
} from "./chunk-XEYEKVFT.js";
|
|
@@ -120,7 +120,7 @@ import {
|
|
|
120
120
|
getActiveAgents,
|
|
121
121
|
getAgentByType,
|
|
122
122
|
getAllAgents
|
|
123
|
-
} from "./chunk-
|
|
123
|
+
} from "./chunk-PFTCTG5X.js";
|
|
124
124
|
import {
|
|
125
125
|
getSessionPlugins
|
|
126
126
|
} from "./chunk-2VQWLLDU.js";
|
|
@@ -154,22 +154,22 @@ import {
|
|
|
154
154
|
processUserInput,
|
|
155
155
|
reorderMessages,
|
|
156
156
|
stripSystemMessages
|
|
157
|
-
} from "./chunk-
|
|
157
|
+
} from "./chunk-PKOEWHPC.js";
|
|
158
158
|
import {
|
|
159
159
|
ModelManager,
|
|
160
160
|
getModelManager,
|
|
161
161
|
isDefaultSlowAndCapableModel
|
|
162
|
-
} from "./chunk-
|
|
162
|
+
} from "./chunk-3IXSSL3F.js";
|
|
163
163
|
import {
|
|
164
164
|
getCodeStyle,
|
|
165
165
|
getContext,
|
|
166
166
|
getGitState,
|
|
167
167
|
getIsGit,
|
|
168
168
|
getProjectDocs
|
|
169
|
-
} from "./chunk-
|
|
169
|
+
} from "./chunk-FCXTZVJG.js";
|
|
170
170
|
import {
|
|
171
171
|
getTheme
|
|
172
|
-
} from "./chunk-
|
|
172
|
+
} from "./chunk-NWCMSPVL.js";
|
|
173
173
|
import {
|
|
174
174
|
DEFAULT_GLOBAL_CONFIG,
|
|
175
175
|
enableConfigs,
|
|
@@ -182,7 +182,7 @@ import {
|
|
|
182
182
|
saveGlobalConfig,
|
|
183
183
|
setAllPointersToModel,
|
|
184
184
|
setModelPointer
|
|
185
|
-
} from "./chunk-
|
|
185
|
+
} from "./chunk-CEARH7HF.js";
|
|
186
186
|
import {
|
|
187
187
|
AbortError
|
|
188
188
|
} from "./chunk-HIIHGKXP.js";
|
|
@@ -191,7 +191,7 @@ import {
|
|
|
191
191
|
getCurrentRequest,
|
|
192
192
|
logUserFriendly,
|
|
193
193
|
markPhase
|
|
194
|
-
} from "./chunk-
|
|
194
|
+
} from "./chunk-VUWBPLA2.js";
|
|
195
195
|
import {
|
|
196
196
|
ASCII_LOGO,
|
|
197
197
|
BunShell,
|
|
@@ -236,11 +236,11 @@ import {
|
|
|
236
236
|
renderBashNotification,
|
|
237
237
|
setActivePlanConversationKey,
|
|
238
238
|
setCwd
|
|
239
|
-
} from "./chunk-
|
|
239
|
+
} from "./chunk-OPC7BAW5.js";
|
|
240
240
|
import {
|
|
241
241
|
MACRO,
|
|
242
242
|
init_macros
|
|
243
|
-
} from "./chunk-
|
|
243
|
+
} from "./chunk-NYT5K544.js";
|
|
244
244
|
import {
|
|
245
245
|
formatTotalCost,
|
|
246
246
|
getTotalAPIDuration,
|
|
@@ -251,15 +251,15 @@ import {
|
|
|
251
251
|
import {
|
|
252
252
|
__esm,
|
|
253
253
|
__export,
|
|
254
|
-
|
|
254
|
+
__toCommonJS
|
|
255
255
|
} from "./chunk-M3TKNAUR.js";
|
|
256
256
|
|
|
257
257
|
// src/engine/detect.ts
|
|
258
|
-
import { existsSync as
|
|
259
|
-
import { join as
|
|
258
|
+
import { existsSync as existsSync8, readFileSync as readFileSync6, readdirSync as readdirSync2, statSync as statSync9 } from "fs";
|
|
259
|
+
import { join as join6 } from "path";
|
|
260
260
|
import { globSync } from "glob";
|
|
261
|
-
function detectEngine(projectPath) {
|
|
262
|
-
if (
|
|
261
|
+
function detectEngine(projectPath, depth = 0) {
|
|
262
|
+
if (existsSync8(join6(projectPath, "ProjectSettings")) && existsSync8(join6(projectPath, "Assets"))) {
|
|
263
263
|
return "unity";
|
|
264
264
|
}
|
|
265
265
|
try {
|
|
@@ -269,39 +269,42 @@ function detectEngine(projectPath) {
|
|
|
269
269
|
}
|
|
270
270
|
} catch {
|
|
271
271
|
}
|
|
272
|
-
if (
|
|
272
|
+
if (existsSync8(join6(projectPath, "project.godot"))) {
|
|
273
273
|
return "godot";
|
|
274
274
|
}
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
const
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
275
|
+
if (depth < 1) {
|
|
276
|
+
const subCandidates = ["client", "server", "game-client", "game-server"];
|
|
277
|
+
for (const candidate of subCandidates) {
|
|
278
|
+
const subPath = join6(projectPath, candidate);
|
|
279
|
+
if (existsSync8(subPath)) {
|
|
280
|
+
const subEngine = detectEngine(subPath, depth + 1);
|
|
281
|
+
if (subEngine) return subEngine;
|
|
282
|
+
}
|
|
281
283
|
}
|
|
282
284
|
}
|
|
283
285
|
return null;
|
|
284
286
|
}
|
|
285
|
-
function detectServerLanguage(projectPath) {
|
|
286
|
-
if (
|
|
287
|
+
function detectServerLanguage(projectPath, depth = 0) {
|
|
288
|
+
if (existsSync8(join6(projectPath, "go.mod"))) {
|
|
287
289
|
return "go";
|
|
288
290
|
}
|
|
289
|
-
if (
|
|
291
|
+
if (existsSync8(join6(projectPath, "Makefile"))) {
|
|
290
292
|
try {
|
|
291
|
-
const
|
|
292
|
-
const makefile = readFileSync11(join13(projectPath, "Makefile"), "utf-8");
|
|
293
|
+
const makefile = readFileSync6(join6(projectPath, "Makefile"), "utf-8");
|
|
293
294
|
if (makefile.includes("go build") || makefile.includes("go test")) {
|
|
294
295
|
return "go";
|
|
295
296
|
}
|
|
296
297
|
} catch {
|
|
297
298
|
}
|
|
298
299
|
}
|
|
299
|
-
if (
|
|
300
|
+
if (existsSync8(join6(projectPath, "CMakeLists.txt"))) {
|
|
300
301
|
return "cpp";
|
|
301
302
|
}
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
303
|
+
if (depth < 1) {
|
|
304
|
+
const serverDir = join6(projectPath, "server");
|
|
305
|
+
if (existsSync8(serverDir)) {
|
|
306
|
+
return detectServerLanguage(serverDir, depth + 1);
|
|
307
|
+
}
|
|
305
308
|
}
|
|
306
309
|
return null;
|
|
307
310
|
}
|
|
@@ -316,7 +319,6 @@ function detectLanguages(engine, serverLanguage) {
|
|
|
316
319
|
break;
|
|
317
320
|
case "godot":
|
|
318
321
|
languages.push("GDScript");
|
|
319
|
-
languages.push("C#");
|
|
320
322
|
break;
|
|
321
323
|
}
|
|
322
324
|
switch (serverLanguage) {
|
|
@@ -340,20 +342,405 @@ function detectProject(projectPath) {
|
|
|
340
342
|
const languages = detectLanguages(engine, serverLanguage);
|
|
341
343
|
return { engine, serverLanguage, languages };
|
|
342
344
|
}
|
|
345
|
+
function inferRole(name2, engine, serverLanguage) {
|
|
346
|
+
const lower = name2.toLowerCase();
|
|
347
|
+
if (lower.includes("client") || lower.includes("game-client")) return "client";
|
|
348
|
+
if (lower.includes("server") || lower.includes("game-server")) return "server";
|
|
349
|
+
if (lower.includes("shared") || lower.includes("common")) return "shared";
|
|
350
|
+
if (engine) return "client";
|
|
351
|
+
if (serverLanguage) return "server";
|
|
352
|
+
return "unknown";
|
|
353
|
+
}
|
|
354
|
+
function detectWorkspace(rootPath) {
|
|
355
|
+
const subProjects = [];
|
|
356
|
+
try {
|
|
357
|
+
const entries = readdirSync2(rootPath);
|
|
358
|
+
for (const entry of entries) {
|
|
359
|
+
if (entry.startsWith(".") || entry === "node_modules" || entry === "dist" || entry === "Docs" || entry === "Tools") continue;
|
|
360
|
+
const subPath = join6(rootPath, entry);
|
|
361
|
+
try {
|
|
362
|
+
if (!statSync9(subPath).isDirectory()) continue;
|
|
363
|
+
} catch {
|
|
364
|
+
continue;
|
|
365
|
+
}
|
|
366
|
+
const engine = detectEngine(subPath);
|
|
367
|
+
const serverLanguage = detectServerLanguage(subPath);
|
|
368
|
+
if (engine || serverLanguage) {
|
|
369
|
+
subProjects.push({
|
|
370
|
+
name: entry,
|
|
371
|
+
path: subPath,
|
|
372
|
+
engine,
|
|
373
|
+
serverLanguage,
|
|
374
|
+
role: inferRole(entry, engine, serverLanguage)
|
|
375
|
+
});
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
} catch {
|
|
379
|
+
}
|
|
380
|
+
if (subProjects.length >= 2) {
|
|
381
|
+
return { type: "workspace", rootPath, subProjects };
|
|
382
|
+
}
|
|
383
|
+
return { type: "single-project", rootPath, subProjects: [] };
|
|
384
|
+
}
|
|
343
385
|
var init_detect = __esm({
|
|
344
386
|
"src/engine/detect.ts"() {
|
|
345
387
|
}
|
|
346
388
|
});
|
|
347
389
|
|
|
390
|
+
// src/templates/bundles/common.ts
|
|
391
|
+
var common_exports = {};
|
|
392
|
+
__export(common_exports, {
|
|
393
|
+
CMD_AUTO_BUGFIX: () => CMD_AUTO_BUGFIX,
|
|
394
|
+
CMD_AUTO_WORK: () => CMD_AUTO_WORK,
|
|
395
|
+
CMD_FIX_HARNESS: () => CMD_FIX_HARNESS,
|
|
396
|
+
CMD_PARALLEL_EXECUTE: () => CMD_PARALLEL_EXECUTE,
|
|
397
|
+
CMD_PLAN: () => CMD_PLAN,
|
|
398
|
+
CMD_REVIEW: () => CMD_REVIEW,
|
|
399
|
+
CMD_VERIFY: () => CMD_VERIFY,
|
|
400
|
+
HOOK_CONSTITUTION_GUARD: () => HOOK_CONSTITUTION_GUARD,
|
|
401
|
+
HOOK_HARNESS_EVOLUTION: () => HOOK_HARNESS_EVOLUTION,
|
|
402
|
+
HOOK_POST_COMMIT: () => HOOK_POST_COMMIT,
|
|
403
|
+
HOOK_PRE_COMMIT: () => HOOK_PRE_COMMIT,
|
|
404
|
+
HOOK_PUSH_GATE: () => HOOK_PUSH_GATE,
|
|
405
|
+
MEMORY_INDEX: () => MEMORY_INDEX,
|
|
406
|
+
RULE_ARCHITECTURE_BOUNDARIES: () => RULE_ARCHITECTURE_BOUNDARIES,
|
|
407
|
+
RULE_KNOWN_PITFALLS: () => RULE_KNOWN_PITFALLS
|
|
408
|
+
});
|
|
409
|
+
var CMD_AUTO_WORK, CMD_AUTO_BUGFIX, CMD_REVIEW, CMD_FIX_HARNESS, CMD_PLAN, CMD_VERIFY, CMD_PARALLEL_EXECUTE, RULE_KNOWN_PITFALLS, RULE_ARCHITECTURE_BOUNDARIES, MEMORY_INDEX, HOOK_CONSTITUTION_GUARD, HOOK_PRE_COMMIT, HOOK_POST_COMMIT, HOOK_PUSH_GATE, HOOK_HARNESS_EVOLUTION;
|
|
410
|
+
var init_common = __esm({
|
|
411
|
+
"src/templates/bundles/common.ts"() {
|
|
412
|
+
CMD_AUTO_WORK = `# /auto-work <requirement>
|
|
413
|
+
|
|
414
|
+
Full-auto development pipeline. Walks through the entire cycle without manual intervention.
|
|
415
|
+
|
|
416
|
+
## Stages
|
|
417
|
+
|
|
418
|
+
### Stage 0: Classify
|
|
419
|
+
Determine requirement type: bug | feature | refactor
|
|
420
|
+
|
|
421
|
+
### Stage 1: Plan
|
|
422
|
+
- List all files to modify with 1-line intent per file
|
|
423
|
+
- If >3 tasks and parallelizable \u2192 switch to parallel mode
|
|
424
|
+
|
|
425
|
+
### Stage 2: Code
|
|
426
|
+
- Modify files per plan
|
|
427
|
+
- After each file \u2192 compile check immediately (fail-fast)
|
|
428
|
+
- After all: run /verify
|
|
429
|
+
- Verify fail \u2192 fix (max 3 rounds), else abort
|
|
430
|
+
|
|
431
|
+
### Stage 3: Review
|
|
432
|
+
- Run /review (100-point scoring)
|
|
433
|
+
- CRITICAL \u2192 fail; <80 \u2192 fail
|
|
434
|
+
- Quality ratchet: score must not drop
|
|
435
|
+
- Pass \u2192 write push-approved marker
|
|
436
|
+
|
|
437
|
+
### Stage 4: Commit
|
|
438
|
+
- git add + git commit
|
|
439
|
+
- Pre-commit hook runs lint + test
|
|
440
|
+
- Fail \u2192 fix and retry (max 2 times)
|
|
441
|
+
|
|
442
|
+
### Stage 5: Knowledge Deposit
|
|
443
|
+
- Feature \u2192 Docs/Version/<version>/<feature>/summary.md
|
|
444
|
+
- Bug \u2192 Docs/Bugs/<version>/<bug-name>.md
|
|
445
|
+
- New module \u2192 Docs/Engine/Business/<module>/
|
|
446
|
+
|
|
447
|
+
### Stage 6: Harness Self-Evolution
|
|
448
|
+
- Check for errors fixed in Stages 2-3
|
|
449
|
+
- If found \u2192 update .danya/rules/ to prevent recurrence
|
|
450
|
+
|
|
451
|
+
## Termination Conditions
|
|
452
|
+
- Verify fail after 3 rounds (Stage 2)
|
|
453
|
+
- Review score <80 after 3 rounds (Stage 3)
|
|
454
|
+
- Commit fail after 2 attempts (Stage 4)
|
|
455
|
+
|
|
456
|
+
## Important
|
|
457
|
+
- Do NOT push. Push is manual after human review.
|
|
458
|
+
- Do NOT skip stages. Each stage must complete before next.
|
|
459
|
+
`;
|
|
460
|
+
CMD_AUTO_BUGFIX = `# /auto-bugfix <bug-description>
|
|
461
|
+
|
|
462
|
+
Autonomous bug-fix pipeline. Must reproduce before fixing.
|
|
463
|
+
|
|
464
|
+
## Flow
|
|
465
|
+
|
|
466
|
+
### Step 1: Reproduce
|
|
467
|
+
- Analyze bug description
|
|
468
|
+
- Find reproduction steps
|
|
469
|
+
- Verify the bug exists (compile, run test, check logs)
|
|
470
|
+
- If NOT reproducible \u2192 report and STOP
|
|
471
|
+
|
|
472
|
+
### Step 2: Root Cause Analysis
|
|
473
|
+
- Trace from symptom to root cause
|
|
474
|
+
- Do NOT guess. Read code, check logs, add debug output if needed.
|
|
475
|
+
|
|
476
|
+
### Step 3: Fix (max 5 rounds)
|
|
477
|
+
- Modify code to fix root cause
|
|
478
|
+
- Run /verify after each fix attempt
|
|
479
|
+
- If verify fails \u2192 analyze why and try again
|
|
480
|
+
- If 5 rounds exhausted \u2192 report failure
|
|
481
|
+
|
|
482
|
+
### Step 4: Review + Commit
|
|
483
|
+
- Run /review (must pass \u226580, no CRITICAL)
|
|
484
|
+
- git commit with descriptive message
|
|
485
|
+
|
|
486
|
+
### Step 5: Knowledge Deposit
|
|
487
|
+
- Write to Docs/Bugs/<version>/<bug-name>.md
|
|
488
|
+
- Include: reproduction steps, root cause, fix, lessons learned
|
|
489
|
+
|
|
490
|
+
### Step 6: Harness Evolution
|
|
491
|
+
- If this bug type isn't in known-pitfalls.md \u2192 add it
|
|
492
|
+
`;
|
|
493
|
+
CMD_REVIEW = `# /review
|
|
494
|
+
|
|
495
|
+
Score-based code review. Quantitative, not subjective.
|
|
496
|
+
|
|
497
|
+
## Pre-check
|
|
498
|
+
Run /verify first. If verify fails, fix before reviewing.
|
|
499
|
+
|
|
500
|
+
## Scoring System
|
|
501
|
+
- Initial score: 100
|
|
502
|
+
- CRITICAL: -30 each (any CRITICAL = automatic FAIL)
|
|
503
|
+
- HIGH: -10 each
|
|
504
|
+
- MEDIUM: -3 each
|
|
505
|
+
- Pass threshold: \u226580 AND no CRITICAL
|
|
506
|
+
|
|
507
|
+
## Check Categories
|
|
508
|
+
|
|
509
|
+
### 1. Architecture Compliance (mechanical + AI)
|
|
510
|
+
- Forbidden file edits (constitution)?
|
|
511
|
+
- Cross-layer imports?
|
|
512
|
+
- Package boundary violations?
|
|
513
|
+
|
|
514
|
+
### 2. Coding Standards (mechanical + AI)
|
|
515
|
+
- Engine-specific style violations?
|
|
516
|
+
- Error handling patterns?
|
|
517
|
+
- Naming conventions?
|
|
518
|
+
|
|
519
|
+
### 3. Logic Review (AI only)
|
|
520
|
+
- Intent clarity
|
|
521
|
+
- Error propagation
|
|
522
|
+
- Concurrency safety
|
|
523
|
+
- Edge cases
|
|
524
|
+
- Dead code
|
|
525
|
+
|
|
526
|
+
### 4. Harness Completeness
|
|
527
|
+
- Were errors fixed during development?
|
|
528
|
+
- Did rules get updated to match?
|
|
529
|
+
|
|
530
|
+
## Quality Ratchet
|
|
531
|
+
Score must not drop compared to previous review. If it drops, the fix introduced regressions.
|
|
532
|
+
|
|
533
|
+
## Output
|
|
534
|
+
On PASS: write .danya/push-approved marker (one-time use).
|
|
535
|
+
On FAIL: list all issues with severity, do NOT write marker.
|
|
536
|
+
`;
|
|
537
|
+
CMD_FIX_HARNESS = `# /fix-harness [error-description]
|
|
538
|
+
|
|
539
|
+
Update harness rules after discovering an error pattern.
|
|
540
|
+
|
|
541
|
+
## Process
|
|
542
|
+
|
|
543
|
+
1. Analyze the error that occurred
|
|
544
|
+
2. Route to the correct rule file:
|
|
545
|
+
- Forbidden zone violation \u2192 constitution.md
|
|
546
|
+
- Coding principle violation \u2192 golden-principles.md
|
|
547
|
+
- Known pitfall re-occurrence \u2192 known-pitfalls.md
|
|
548
|
+
- Architecture boundary violation \u2192 architecture-boundaries.md
|
|
549
|
+
- Style issue \u2192 engine-style rule file
|
|
550
|
+
3. Add a concise rule:
|
|
551
|
+
- \u274C What went wrong (with example)
|
|
552
|
+
- \u2705 Correct approach (with example)
|
|
553
|
+
4. If mechanically checkable \u2192 add to /verify checks
|
|
554
|
+
5. Check total rule file lines < 550 (if exceeded, consolidate)
|
|
555
|
+
|
|
556
|
+
## Important
|
|
557
|
+
- Only add NEW patterns not already captured
|
|
558
|
+
- Keep rules minimal: one error = one rule
|
|
559
|
+
- Include correct-usage example, not just prohibition
|
|
560
|
+
`;
|
|
561
|
+
CMD_PLAN = `# /plan <requirement>
|
|
562
|
+
|
|
563
|
+
Analyze requirement and create a development plan.
|
|
564
|
+
|
|
565
|
+
## Output Format
|
|
566
|
+
|
|
567
|
+
### 1. Requirement Analysis
|
|
568
|
+
- What needs to change and why
|
|
569
|
+
- Scope assessment
|
|
570
|
+
|
|
571
|
+
### 2. File Checklist
|
|
572
|
+
For each file to modify:
|
|
573
|
+
- File path
|
|
574
|
+
- 1-line description of changes
|
|
575
|
+
- Risk level (low/medium/high)
|
|
576
|
+
|
|
577
|
+
### 3. Execution Order
|
|
578
|
+
- Dependencies between changes
|
|
579
|
+
- Which files can be modified in parallel
|
|
580
|
+
- Which must be sequential
|
|
581
|
+
|
|
582
|
+
### 4. Verification Strategy
|
|
583
|
+
- How to verify each change works
|
|
584
|
+
- Integration test approach
|
|
585
|
+
|
|
586
|
+
## Rules
|
|
587
|
+
- Read existing code before planning changes
|
|
588
|
+
- Check architecture boundaries before proposing cross-layer changes
|
|
589
|
+
- Flag any forbidden zone files that would need regeneration
|
|
590
|
+
`;
|
|
591
|
+
CMD_VERIFY = `# /verify [level]
|
|
592
|
+
|
|
593
|
+
Mechanical verification checks. Levels: quick | build | full
|
|
594
|
+
|
|
595
|
+
## quick (default)
|
|
596
|
+
- Lint check
|
|
597
|
+
- Syntax check (engine-specific)
|
|
598
|
+
|
|
599
|
+
## build
|
|
600
|
+
- Everything in quick
|
|
601
|
+
- Full compilation/build
|
|
602
|
+
|
|
603
|
+
## full
|
|
604
|
+
- Everything in build
|
|
605
|
+
- Run tests
|
|
606
|
+
- Architecture boundary check
|
|
607
|
+
|
|
608
|
+
## Important
|
|
609
|
+
- Run this BEFORE /review
|
|
610
|
+
- If verify fails, fix issues before reviewing
|
|
611
|
+
- Exit with clear pass/fail and error details
|
|
612
|
+
`;
|
|
613
|
+
CMD_PARALLEL_EXECUTE = `# /parallel-execute <mode> <description>
|
|
614
|
+
|
|
615
|
+
Wave-based parallel task execution.
|
|
616
|
+
|
|
617
|
+
## Modes
|
|
618
|
+
- prepare: Decompose task into sub-tasks with dependency declarations
|
|
619
|
+
- execute: Run prepared tasks in parallel waves
|
|
620
|
+
|
|
621
|
+
## Prepare Mode
|
|
622
|
+
Create task files in .danya/exec-plans/active/:
|
|
623
|
+
- task-01.md, task-02.md, etc.
|
|
624
|
+
- Each has YAML frontmatter with \`depends: []\` field
|
|
625
|
+
- Tasks with no dependencies \u2192 Wave 1
|
|
626
|
+
- Tasks depending on Wave 1 \u2192 Wave 2, etc.
|
|
627
|
+
|
|
628
|
+
## Execute Mode
|
|
629
|
+
- Parse dependency DAG \u2192 compute waves
|
|
630
|
+
- Wave 1: run all independent tasks in parallel (separate worktrees)
|
|
631
|
+
- Collect results, merge successful tasks
|
|
632
|
+
- Wave 2: run next batch
|
|
633
|
+
- Continue until all waves complete
|
|
634
|
+
- Run /verify full on integrated code
|
|
635
|
+
|
|
636
|
+
## Rules
|
|
637
|
+
- Each task must be atomic (can succeed/fail independently)
|
|
638
|
+
- Failed task \u2192 rollback its worktree, don't affect others
|
|
639
|
+
- Cyclic dependencies \u2192 error, re-decompose
|
|
640
|
+
`;
|
|
641
|
+
RULE_KNOWN_PITFALLS = `# Known Pitfalls
|
|
642
|
+
|
|
643
|
+
Real errors encountered during development. Each entry prevents the same mistake.
|
|
644
|
+
|
|
645
|
+
_This file grows through harness self-evolution. Start empty, fill as errors occur._
|
|
646
|
+
`;
|
|
647
|
+
RULE_ARCHITECTURE_BOUNDARIES = `# Architecture Boundaries
|
|
648
|
+
|
|
649
|
+
Dependency direction rules. Higher layers can import lower layers, not vice versa.
|
|
650
|
+
|
|
651
|
+
## General Principle
|
|
652
|
+
- One-way dependencies: lower layers must NOT reference higher layers
|
|
653
|
+
- Cross-module communication through events/interfaces, not direct references
|
|
654
|
+
|
|
655
|
+
_Customize with your project's actual layer structure._
|
|
656
|
+
`;
|
|
657
|
+
MEMORY_INDEX = `# Project Memory
|
|
658
|
+
|
|
659
|
+
Persistent domain knowledge. Updated as the agent learns about this project.
|
|
660
|
+
|
|
661
|
+
_Memory files are auto-loaded each session and survive context compression._
|
|
662
|
+
`;
|
|
663
|
+
HOOK_CONSTITUTION_GUARD = `#!/bin/bash
|
|
664
|
+
# Gate 0: GUARD \u2014 forbidden zone check. Exit 2 = block.
|
|
665
|
+
INPUT=$(cat)
|
|
666
|
+
FILE_PATH=$(echo "$INPUT" | sed -n 's/.*"file_path"[[:space:]]*:[[:space:]]*"\\([^"]*\\)".*/\\1/p' 2>/dev/null)
|
|
667
|
+
[ -z "$FILE_PATH" ] && exit 0
|
|
668
|
+
FILE_PATH=$(echo "$FILE_PATH" | sed 's/\\\\\\\\/\\//g')
|
|
669
|
+
RULES=".danya/guard-rules.json"
|
|
670
|
+
[ ! -f "$RULES" ] && exit 0
|
|
671
|
+
while IFS= read -r p; do
|
|
672
|
+
p=$(echo "$p" | tr -d '"' | tr -d ' ')
|
|
673
|
+
[ -z "$p" ] && continue
|
|
674
|
+
if echo "$FILE_PATH" | grep -qE "$p" 2>/dev/null; then
|
|
675
|
+
echo "{\\"systemMessage\\":\\"\u274C GUARD: $FILE_PATH is in forbidden zone ($p). Edit the source data and regenerate instead.\\"}"
|
|
676
|
+
exit 2
|
|
677
|
+
fi
|
|
678
|
+
done < <(grep '"pattern"' "$RULES" | sed 's/.*"pattern"\\s*:\\s*"//;s/".*//')
|
|
679
|
+
exit 0
|
|
680
|
+
`;
|
|
681
|
+
HOOK_PRE_COMMIT = `#!/bin/bash
|
|
682
|
+
# Gate 3: COMMIT \u2014 pre-commit lint + test. Exit 2 = block.
|
|
683
|
+
INPUT=$(cat)
|
|
684
|
+
CMD=$(echo "$INPUT" | sed -n 's/.*"command"[[:space:]]*:[[:space:]]*"\\([^"]*\\)".*/\\1/p' 2>/dev/null)
|
|
685
|
+
echo "$CMD" | grep -qE 'git\\s+commit' || exit 0
|
|
686
|
+
if [ -f "Makefile" ]; then
|
|
687
|
+
make lint > /tmp/danya-lint.log 2>&1 || { echo "\u274C Lint failed" >&2; tail -10 /tmp/danya-lint.log >&2; exit 2; }
|
|
688
|
+
make test > /tmp/danya-test.log 2>&1 || { echo "\u274C Tests failed" >&2; tail -10 /tmp/danya-test.log >&2; exit 2; }
|
|
689
|
+
fi
|
|
690
|
+
exit 0
|
|
691
|
+
`;
|
|
692
|
+
HOOK_POST_COMMIT = `#!/bin/bash
|
|
693
|
+
# Gate 4: Post-commit review reminder. Always exit 0.
|
|
694
|
+
echo '{"systemMessage":"\u2705 Commit done. Run /review before push (score \u226580, no CRITICAL)."}'
|
|
695
|
+
exit 0
|
|
696
|
+
`;
|
|
697
|
+
HOOK_PUSH_GATE = `#!/bin/bash
|
|
698
|
+
# Gate 5: PUSH \u2014 check push-approved marker. Exit 2 = block.
|
|
699
|
+
INPUT=$(cat)
|
|
700
|
+
CMD=$(echo "$INPUT" | sed -n 's/.*"command"[[:space:]]*:[[:space:]]*"\\([^"]*\\)".*/\\1/p' 2>/dev/null)
|
|
701
|
+
echo "$CMD" | grep -qE 'git[[:space:]]+push' || exit 0
|
|
702
|
+
MARKER=".danya/push-approved"
|
|
703
|
+
[ ! -f "$MARKER" ] && { echo "\u274C PUSH BLOCKED: run /review first" >&2; exit 2; }
|
|
704
|
+
rm -f "$MARKER"
|
|
705
|
+
exit 0
|
|
706
|
+
`;
|
|
707
|
+
HOOK_HARNESS_EVOLUTION = `#!/bin/bash
|
|
708
|
+
# PostToolUse: detect error-then-fix pattern for harness self-evolution.
|
|
709
|
+
# Reads tool result, checks if a previous error was just fixed.
|
|
710
|
+
# If so, injects a system message prompting the agent to update rules.
|
|
711
|
+
INPUT=$(cat)
|
|
712
|
+
TOOL_NAME=$(echo "$INPUT" | sed -n 's/.*"tool_name"[[:space:]]*:[[:space:]]*"\\([^"]*\\)".*/\\1/p' 2>/dev/null)
|
|
713
|
+
EXIT_CODE=$(echo "$INPUT" | sed -n 's/.*"exit_code"[[:space:]]*:[[:space:]]*\\([0-9]*\\).*/\\1/p' 2>/dev/null)
|
|
714
|
+
|
|
715
|
+
# Track error state using project-scoped file (stable across hook invocations)
|
|
716
|
+
STATE_FILE=".danya/.error-state"
|
|
717
|
+
|
|
718
|
+
case "$TOOL_NAME" in
|
|
719
|
+
Bash)
|
|
720
|
+
if [ "$EXIT_CODE" != "0" ] && [ -n "$EXIT_CODE" ]; then
|
|
721
|
+
# Error occurred \u2014 record it
|
|
722
|
+
echo "error" > "$STATE_FILE" 2>/dev/null
|
|
723
|
+
elif [ -f "$STATE_FILE" ] && [ "$(cat "$STATE_FILE" 2>/dev/null)" = "error" ]; then
|
|
724
|
+
# Previous error, now success \u2014 fix confirmed
|
|
725
|
+
rm -f "$STATE_FILE"
|
|
726
|
+
echo '{"systemMessage":"Error was fixed. Consider running /fix-harness to update rules and prevent this error pattern in the future."}'
|
|
727
|
+
fi
|
|
728
|
+
;;
|
|
729
|
+
esac
|
|
730
|
+
exit 0
|
|
731
|
+
`;
|
|
732
|
+
}
|
|
733
|
+
});
|
|
734
|
+
|
|
348
735
|
// src/constants/prompts.ts
|
|
349
736
|
init_env();
|
|
350
737
|
init_state();
|
|
351
738
|
init_product();
|
|
352
739
|
|
|
353
740
|
// src/tools/system/BashTool/BashTool.tsx
|
|
354
|
-
import { statSync as
|
|
741
|
+
import { statSync as statSync15 } from "fs";
|
|
355
742
|
import { EOL as EOL3 } from "os";
|
|
356
|
-
import { isAbsolute as isAbsolute10, relative as
|
|
743
|
+
import { isAbsolute as isAbsolute10, relative as relative15, resolve as resolve10 } from "path";
|
|
357
744
|
import * as React108 from "react";
|
|
358
745
|
import { z as z16 } from "zod";
|
|
359
746
|
init_product();
|
|
@@ -527,7 +914,7 @@ var getCommandSubcommandPrefix = memoize(
|
|
|
527
914
|
var getCommandPrefix = memoize(
|
|
528
915
|
async (command4, abortSignal) => {
|
|
529
916
|
const { systemPrompt, userPrompt } = buildBashCommandPrefixDetectionPrompt(command4);
|
|
530
|
-
const { API_ERROR_MESSAGE_PREFIX: API_ERROR_MESSAGE_PREFIX2, queryQuick: queryQuick2 } = await import("./llm-
|
|
917
|
+
const { API_ERROR_MESSAGE_PREFIX: API_ERROR_MESSAGE_PREFIX2, queryQuick: queryQuick2 } = await import("./llm-XBH33BXT.js");
|
|
531
918
|
const response = await queryQuick2({
|
|
532
919
|
systemPrompt,
|
|
533
920
|
userPrompt,
|
|
@@ -1623,11 +2010,11 @@ function isSensitiveFilePath(inputPath) {
|
|
|
1623
2010
|
if (p.startsWith("\\\\") || p.startsWith("//")) return true;
|
|
1624
2011
|
const absolutePath = resolveLikeCliPath(p);
|
|
1625
2012
|
const parts = toPosixPath(absolutePath).split(POSIX_SEP);
|
|
1626
|
-
const
|
|
2013
|
+
const basename9 = parts[parts.length - 1] ?? "";
|
|
1627
2014
|
for (const part of parts) {
|
|
1628
2015
|
if (SENSITIVE_DIR_NAMES.has(toLower(part))) return true;
|
|
1629
2016
|
}
|
|
1630
|
-
if (
|
|
2017
|
+
if (basename9 && SENSITIVE_FILE_NAMES.has(toLower(basename9))) return true;
|
|
1631
2018
|
return false;
|
|
1632
2019
|
}
|
|
1633
2020
|
function getSettingsPathsForWriteProtection(options) {
|
|
@@ -1708,13 +2095,13 @@ function isPathInWorkingDirectories(inputPath, context) {
|
|
|
1708
2095
|
toPosixPath(resolvedCandidate)
|
|
1709
2096
|
);
|
|
1710
2097
|
const rootPosix = normalizeMacPrivatePrefix(toPosixPath(resolvedRoot));
|
|
1711
|
-
const
|
|
2098
|
+
const relative16 = posixRelative(
|
|
1712
2099
|
toLower(rootPosix),
|
|
1713
2100
|
toLower(candidatePosix)
|
|
1714
2101
|
);
|
|
1715
|
-
if (
|
|
1716
|
-
if (hasParentTraversalSegment(
|
|
1717
|
-
if (POSIX.isAbsolute(
|
|
2102
|
+
if (relative16 === "") return true;
|
|
2103
|
+
if (hasParentTraversalSegment(relative16)) return false;
|
|
2104
|
+
if (POSIX.isAbsolute(relative16)) return false;
|
|
1718
2105
|
return true;
|
|
1719
2106
|
});
|
|
1720
2107
|
});
|
|
@@ -1817,9 +2204,9 @@ function matchPermissionRuleForPath(args) {
|
|
|
1817
2204
|
}
|
|
1818
2205
|
for (const [root, patternsMap] of grouped.entries()) {
|
|
1819
2206
|
const baseRoot = root ?? getCwd();
|
|
1820
|
-
const
|
|
1821
|
-
if (
|
|
1822
|
-
if (!
|
|
2207
|
+
const relative16 = posixRelative(baseRoot, targetPosix);
|
|
2208
|
+
if (relative16.startsWith(`..${POSIX_SEP}`)) continue;
|
|
2209
|
+
if (!relative16) continue;
|
|
1823
2210
|
const matchAll = patternsMap.get("/**")?.ruleString ?? patternsMap.get("**")?.ruleString ?? null;
|
|
1824
2211
|
if (matchAll) return matchAll;
|
|
1825
2212
|
const patterns = Array.from(patternsMap.keys()).map((pattern) => {
|
|
@@ -1833,7 +2220,7 @@ function matchPermissionRuleForPath(args) {
|
|
|
1833
2220
|
return candidate;
|
|
1834
2221
|
});
|
|
1835
2222
|
const matcher = buildIgnoreMatcher(patterns);
|
|
1836
|
-
const result = matcher.test(
|
|
2223
|
+
const result = matcher.test(relative16);
|
|
1837
2224
|
if (!result.ignored || !result.rule) continue;
|
|
1838
2225
|
let matched = result.rule.pattern;
|
|
1839
2226
|
const matchedWithGlob = `${matched}/**`;
|
|
@@ -4596,7 +4983,7 @@ function formatParseError(error) {
|
|
|
4596
4983
|
return error instanceof Error ? error.message : String(error);
|
|
4597
4984
|
}
|
|
4598
4985
|
async function defaultGateQuery(args) {
|
|
4599
|
-
const { API_ERROR_MESSAGE_PREFIX: API_ERROR_MESSAGE_PREFIX2, queryLLM: queryLLM2 } = await import("./llm-
|
|
4986
|
+
const { API_ERROR_MESSAGE_PREFIX: API_ERROR_MESSAGE_PREFIX2, queryLLM: queryLLM2 } = await import("./llm-XBH33BXT.js");
|
|
4600
4987
|
const messages = [
|
|
4601
4988
|
{
|
|
4602
4989
|
type: "user",
|
|
@@ -10539,8 +10926,8 @@ var help_default = help;
|
|
|
10539
10926
|
import * as React28 from "react";
|
|
10540
10927
|
import { OrderedList } from "@inkjs/ui";
|
|
10541
10928
|
import { Box as Box21, Text as Text24 } from "ink";
|
|
10542
|
-
import { existsSync as
|
|
10543
|
-
import { join as
|
|
10929
|
+
import { existsSync as existsSync13 } from "fs";
|
|
10930
|
+
import { join as join11 } from "path";
|
|
10544
10931
|
import { homedir as homedir6 } from "os";
|
|
10545
10932
|
|
|
10546
10933
|
// src/constants/releaseNotes.ts
|
|
@@ -10554,6 +10941,871 @@ var RELEASE_NOTES = {
|
|
|
10554
10941
|
import { gt } from "semver";
|
|
10555
10942
|
init_macros();
|
|
10556
10943
|
init_product();
|
|
10944
|
+
|
|
10945
|
+
// src/ui/screens/autoInitHarness.ts
|
|
10946
|
+
import { existsSync as existsSync12 } from "fs";
|
|
10947
|
+
import { join as join10 } from "path";
|
|
10948
|
+
|
|
10949
|
+
// src/commands/initProject.ts
|
|
10950
|
+
init_detect();
|
|
10951
|
+
import { writeFileSync as writeFileSync6, existsSync as existsSync11 } from "fs";
|
|
10952
|
+
import { join as join9, basename as basename4 } from "path";
|
|
10953
|
+
|
|
10954
|
+
// src/templates/templateEngine.ts
|
|
10955
|
+
function renderTemplate(content, ctx) {
|
|
10956
|
+
return content.replace(/\{\{PROJECT_NAME\}\}/g, ctx.projectName).replace(/\{\{ENGINE\}\}/g, ctx.engine ?? "unknown").replace(/\{\{SERVER_LANG\}\}/g, ctx.serverLanguage ?? "none").replace(/\{\{CONFIG_GEN_PATH\}\}/g, ctx.configGenPath).replace(/\{\{FRAMEWORK_PATH\}\}/g, ctx.frameworkPath).replace(/\{\{PROTO_PATH\}\}/g, ctx.protoPath).replace(/\{\{ORM_PATH\}\}/g, ctx.ormPath).replace(/\{\{INSTRUCTIONS_FILE\}\}/g, ctx.instructionsFile);
|
|
10957
|
+
}
|
|
10958
|
+
function buildTemplateContext(projectName, engine, serverLanguage, instructionsFile) {
|
|
10959
|
+
let configGenPath = "Config/Gen/";
|
|
10960
|
+
let frameworkPath = "Scripts/Framework/";
|
|
10961
|
+
let protoPath = "Proto/";
|
|
10962
|
+
let ormPath = "orm/";
|
|
10963
|
+
if (engine === "unity") {
|
|
10964
|
+
configGenPath = "Assets/Scripts/Gameplay/Config/Gen/";
|
|
10965
|
+
frameworkPath = "Assets/Scripts/Framework/";
|
|
10966
|
+
protoPath = "Assets/Scripts/Proto/";
|
|
10967
|
+
} else if (engine === "unreal") {
|
|
10968
|
+
configGenPath = "Source/Generated/";
|
|
10969
|
+
frameworkPath = "Source/Core/";
|
|
10970
|
+
protoPath = "Source/Proto/";
|
|
10971
|
+
} else if (engine === "godot") {
|
|
10972
|
+
configGenPath = "scripts/generated/";
|
|
10973
|
+
frameworkPath = "scripts/core/";
|
|
10974
|
+
protoPath = "proto/";
|
|
10975
|
+
}
|
|
10976
|
+
if (serverLanguage === "go" && !engine) {
|
|
10977
|
+
configGenPath = "common/config/cfg_*.go";
|
|
10978
|
+
ormPath = "orm/(golang|redis|mongo)/";
|
|
10979
|
+
protoPath = "resources/proto/";
|
|
10980
|
+
}
|
|
10981
|
+
return { projectName, engine, serverLanguage, configGenPath, frameworkPath, protoPath, ormPath, instructionsFile };
|
|
10982
|
+
}
|
|
10983
|
+
|
|
10984
|
+
// src/templates/bundleInstaller.ts
|
|
10985
|
+
import { mkdirSync as mkdirSync5, writeFileSync as writeFileSync4, existsSync as existsSync9 } from "fs";
|
|
10986
|
+
import { join as join7, dirname as dirname6 } from "path";
|
|
10987
|
+
function installBundle(targetDir, bundleContent, ctx, options = {}) {
|
|
10988
|
+
const installed = [];
|
|
10989
|
+
for (const [relativePath, content] of Object.entries(bundleContent)) {
|
|
10990
|
+
const isTemplate = relativePath.endsWith(".tmpl");
|
|
10991
|
+
const finalRelPath = isTemplate ? relativePath.replace(/\.tmpl$/, "") : relativePath;
|
|
10992
|
+
const finalPath = join7(targetDir, finalRelPath);
|
|
10993
|
+
const dir = dirname6(finalPath);
|
|
10994
|
+
if (!existsSync9(finalPath) || options.force) {
|
|
10995
|
+
mkdirSync5(dir, { recursive: true });
|
|
10996
|
+
const rendered = isTemplate ? renderTemplate(content, ctx) : content;
|
|
10997
|
+
writeFileSync4(finalPath, rendered, { encoding: "utf-8", mode: relativePath.includes("hooks/") ? 493 : 420 });
|
|
10998
|
+
installed.push(finalRelPath);
|
|
10999
|
+
}
|
|
11000
|
+
}
|
|
11001
|
+
return installed;
|
|
11002
|
+
}
|
|
11003
|
+
|
|
11004
|
+
// src/templates/bundles/unity.ts
|
|
11005
|
+
init_common();
|
|
11006
|
+
var UNITY_RULES_CONSTITUTION = `# Forbidden Zone Constitution
|
|
11007
|
+
|
|
11008
|
+
## Auto-Generated Code (DO NOT edit manually)
|
|
11009
|
+
- \`{{CONFIG_GEN_PATH}}\` \u2014 Generated config. Edit Excel/data source \u2192 run ConfigGenerate.
|
|
11010
|
+
- \`*_pb.cs\` \u2014 Protobuf generated. Edit .proto \u2192 regenerate.
|
|
11011
|
+
|
|
11012
|
+
## Framework Layer (requires approval)
|
|
11013
|
+
- \`{{FRAMEWORK_PATH}}\` \u2014 Core framework code. Modifying without understanding impacts all systems.
|
|
11014
|
+
|
|
11015
|
+
## Art & Resource Directories
|
|
11016
|
+
- \`ArtResources/\`, \`PackResources/\` \u2014 Managed by art pipeline, not code.
|
|
11017
|
+
- \`.unity\` scene files \u2014 Binary, merge-unfriendly. Coordinate with team.
|
|
11018
|
+
|
|
11019
|
+
## Third-Party Plugins
|
|
11020
|
+
- \`Assets/Plugins/\`, \`Assets/3rd/\` \u2014 No modification unless marked with [CUSTOM_MOD].
|
|
11021
|
+
`;
|
|
11022
|
+
var UNITY_RULES_GOLDEN_PRINCIPLES = `# Golden Principles \u2014 Unity/C#
|
|
11023
|
+
|
|
11024
|
+
Non-negotiable coding rules for this project.
|
|
11025
|
+
|
|
11026
|
+
## Logging
|
|
11027
|
+
- \u274C \`Debug.Log\`, \`Debug.LogWarning\`, \`Debug.LogError\`
|
|
11028
|
+
- \u2705 Use project logger (MLog or equivalent)
|
|
11029
|
+
|
|
11030
|
+
## Async
|
|
11031
|
+
- \u274C \`System.Threading.Tasks.Task\`, \`async/await\` with Task
|
|
11032
|
+
- \u2705 \`UniTask\` for all async operations
|
|
11033
|
+
|
|
11034
|
+
## Object Lifecycle
|
|
11035
|
+
- \u274C \`Destroy()\` on pooled objects
|
|
11036
|
+
- \u2705 \`ObjectPoolUtility.Return()\` or equivalent pool API
|
|
11037
|
+
|
|
11038
|
+
## Events
|
|
11039
|
+
- Subscribe in \`OnEnable()\` / initialization
|
|
11040
|
+
- Unsubscribe in \`OnDisable()\` / cleanup
|
|
11041
|
+
- \u274C Unmatched Subscribe without Unsubscribe \u2192 memory leak
|
|
11042
|
+
|
|
11043
|
+
## Architecture
|
|
11044
|
+
- One-way dependencies: Framework \u2190 Gameplay \u2190 Renderer \u2190 Tools
|
|
11045
|
+
- \u274C Lower layer referencing higher layer
|
|
11046
|
+
- \u2705 Cross-module communication through EventManager/interfaces
|
|
11047
|
+
|
|
11048
|
+
## Null Safety
|
|
11049
|
+
- Always null-check GetComponent<T>() results
|
|
11050
|
+
- Use TryGetComponent<T>() where possible
|
|
11051
|
+
- Never assume Find() returns non-null
|
|
11052
|
+
`;
|
|
11053
|
+
var UNITY_RULES_STYLE = `# Unity C# Style Guide
|
|
11054
|
+
|
|
11055
|
+
## Naming
|
|
11056
|
+
- Classes/Structs: PascalCase
|
|
11057
|
+
- Methods: PascalCase
|
|
11058
|
+
- Private fields: _camelCase with underscore prefix
|
|
11059
|
+
- Public properties: PascalCase
|
|
11060
|
+
- Constants: UPPER_SNAKE_CASE
|
|
11061
|
+
- Enums: PascalCase (members too)
|
|
11062
|
+
|
|
11063
|
+
## File Organization
|
|
11064
|
+
- One primary class per file
|
|
11065
|
+
- File name matches class name
|
|
11066
|
+
- Namespace matches directory structure
|
|
11067
|
+
|
|
11068
|
+
## MonoBehaviour
|
|
11069
|
+
- Lifecycle order: Awake \u2192 OnEnable \u2192 Start \u2192 Update \u2192 OnDisable \u2192 OnDestroy
|
|
11070
|
+
- Heavy init in Awake, subscriptions in OnEnable
|
|
11071
|
+
- Never call Destroy() in Awake or OnEnable
|
|
11072
|
+
`;
|
|
11073
|
+
var UNITY_MEMORY_ARCHITECTURE = `---
|
|
11074
|
+
name: architecture-layers
|
|
11075
|
+
description: Unity project layer structure and dependencies
|
|
11076
|
+
type: project
|
|
11077
|
+
---
|
|
11078
|
+
|
|
11079
|
+
## Layer Structure
|
|
11080
|
+
|
|
11081
|
+
| Layer | Responsibility | Can Reference |
|
|
11082
|
+
|-------|---------------|---------------|
|
|
11083
|
+
| Framework | Core systems, managers, utilities | Nothing above |
|
|
11084
|
+
| Gameplay | Game logic, features, handlers | Framework |
|
|
11085
|
+
| Renderer | Visual, UI, effects | Framework, Gameplay |
|
|
11086
|
+
| Tools | Editor tools, debug utilities | All layers |
|
|
11087
|
+
|
|
11088
|
+
_Update this with your project's actual architecture as you learn it._
|
|
11089
|
+
`;
|
|
11090
|
+
var UNITY_HOOK_SYNTAX = `#!/bin/bash
|
|
11091
|
+
# Gate 1: SYNTAX \u2014 post-edit C# syntax check.
|
|
11092
|
+
INPUT=$(cat)
|
|
11093
|
+
FILE_PATH=$(echo "$INPUT" | sed -n 's/.*"file_path"[[:space:]]*:[[:space:]]*"\\([^"]*\\)".*/\\1/p' 2>/dev/null)
|
|
11094
|
+
[ -z "$FILE_PATH" ] && exit 0
|
|
11095
|
+
echo "$FILE_PATH" | grep -qE '\\.cs$' || exit 0
|
|
11096
|
+
# If dotnet-csharp-syntax-check is available, use it
|
|
11097
|
+
if command -v dotnet-csharp-syntax-check &>/dev/null; then
|
|
11098
|
+
dotnet-csharp-syntax-check "$FILE_PATH" 2>&1 || true
|
|
11099
|
+
fi
|
|
11100
|
+
exit 0
|
|
11101
|
+
`;
|
|
11102
|
+
function getUnityBundle() {
|
|
11103
|
+
return {
|
|
11104
|
+
"rules/constitution.md.tmpl": UNITY_RULES_CONSTITUTION,
|
|
11105
|
+
"rules/golden-principles.md": UNITY_RULES_GOLDEN_PRINCIPLES,
|
|
11106
|
+
"rules/unity-csharp.md": UNITY_RULES_STYLE,
|
|
11107
|
+
"rules/known-pitfalls.md": RULE_KNOWN_PITFALLS,
|
|
11108
|
+
"rules/architecture-boundaries.md": RULE_ARCHITECTURE_BOUNDARIES,
|
|
11109
|
+
"commands/auto-work.md": CMD_AUTO_WORK,
|
|
11110
|
+
"commands/auto-bugfix.md": CMD_AUTO_BUGFIX,
|
|
11111
|
+
"commands/review.md": CMD_REVIEW,
|
|
11112
|
+
"commands/fix-harness.md": CMD_FIX_HARNESS,
|
|
11113
|
+
"commands/plan.md": CMD_PLAN,
|
|
11114
|
+
"commands/verify.md": CMD_VERIFY,
|
|
11115
|
+
"commands/parallel-execute.md": CMD_PARALLEL_EXECUTE,
|
|
11116
|
+
"memory/MEMORY.md": MEMORY_INDEX,
|
|
11117
|
+
"memory/architecture-layers.md": UNITY_MEMORY_ARCHITECTURE,
|
|
11118
|
+
"hooks/constitution-guard.sh": HOOK_CONSTITUTION_GUARD,
|
|
11119
|
+
"hooks/syntax-check.sh": UNITY_HOOK_SYNTAX,
|
|
11120
|
+
"hooks/pre-commit.sh": HOOK_PRE_COMMIT,
|
|
11121
|
+
"hooks/post-commit.sh": HOOK_POST_COMMIT,
|
|
11122
|
+
"hooks/push-gate.sh": HOOK_PUSH_GATE,
|
|
11123
|
+
"hooks/harness-evolution.sh": HOOK_HARNESS_EVOLUTION
|
|
11124
|
+
};
|
|
11125
|
+
}
|
|
11126
|
+
|
|
11127
|
+
// src/templates/bundles/goServer.ts
|
|
11128
|
+
init_common();
|
|
11129
|
+
var GO_RULES_CONSTITUTION = `# Forbidden Zone Constitution
|
|
11130
|
+
|
|
11131
|
+
## Auto-Generated Code (DO NOT edit manually)
|
|
11132
|
+
- \`{{ORM_PATH}}\` \u2014 ORM generated from XML. Edit XML \u2192 run ORM generator.
|
|
11133
|
+
- \`{{CONFIG_GEN_PATH}}\` \u2014 Config generated from game data. Edit data source \u2192 regenerate.
|
|
11134
|
+
- \`*_service.go\`, \`*_client.go\` \u2014 Protobuf RPC wrappers. Edit .proto \u2192 protoc.
|
|
11135
|
+
|
|
11136
|
+
## Git Submodules (edit in upstream repo)
|
|
11137
|
+
- \`base/\` \u2014 Shared base library. Edit in the base repo, then update submodule.
|
|
11138
|
+
- \`{{PROTO_PATH}}\` \u2014 Proto definitions. Edit in proto repo.
|
|
11139
|
+
|
|
11140
|
+
## Important
|
|
11141
|
+
When you see these files, tell the user HOW to regenerate instead of editing directly.
|
|
11142
|
+
`;
|
|
11143
|
+
var GO_RULES_GOLDEN_PRINCIPLES = `# Golden Principles \u2014 Go Server
|
|
11144
|
+
|
|
11145
|
+
Non-negotiable coding rules.
|
|
11146
|
+
|
|
11147
|
+
## Error Handling
|
|
11148
|
+
- \u274C \`_ = err\` (errcheck enforced)
|
|
11149
|
+
- \u274C \`fmt.Errorf("...")\` without %w
|
|
11150
|
+
- \u2705 \`fmt.Errorf("context: %w", err)\` \u2014 always wrap errors
|
|
11151
|
+
|
|
11152
|
+
## RPC Handlers
|
|
11153
|
+
- \u274C Log error + return error (double reporting)
|
|
11154
|
+
- \u2705 RPC handler: catch error \u2192 return RpcError, no log
|
|
11155
|
+
- \u2705 Internal logic: log.Errorf + return err
|
|
11156
|
+
|
|
11157
|
+
## Goroutines
|
|
11158
|
+
- \u274C Bare \`go func() { ... }()\`
|
|
11159
|
+
- \u2705 \`safego.Go(func() { ... })\` \u2014 panic recovery built-in
|
|
11160
|
+
|
|
11161
|
+
## Atomics
|
|
11162
|
+
- \u274C \`sync/atomic\`
|
|
11163
|
+
- \u2705 \`go.uber.org/atomic\`
|
|
11164
|
+
|
|
11165
|
+
## UUID
|
|
11166
|
+
- \u274C \`pborman/uuid\`
|
|
11167
|
+
- \u2705 \`google/uuid\`
|
|
11168
|
+
|
|
11169
|
+
## Database Operations
|
|
11170
|
+
- \u274C Direct DB access from game logic
|
|
11171
|
+
- \u2705 All DB operations through db_server RPC
|
|
11172
|
+
|
|
11173
|
+
## ECS (if applicable)
|
|
11174
|
+
- Components: data only, no logic
|
|
11175
|
+
- Systems: logic only, operate on components
|
|
11176
|
+
- \u274C Logic in components, data mutation outside systems
|
|
11177
|
+
|
|
11178
|
+
## Workflow
|
|
11179
|
+
- Plan first for multi-file changes
|
|
11180
|
+
- Use TaskCreate for progress tracking
|
|
11181
|
+
- Use subagent for 5+ file searches
|
|
11182
|
+
`;
|
|
11183
|
+
var GO_RULES_STYLE = `# Go Style Guide
|
|
11184
|
+
|
|
11185
|
+
## File Naming
|
|
11186
|
+
- snake_case for all .go files
|
|
11187
|
+
- _test.go suffix for tests
|
|
11188
|
+
- Group by feature, not by type
|
|
11189
|
+
|
|
11190
|
+
## Error Handling
|
|
11191
|
+
- Check errors immediately after function call
|
|
11192
|
+
- Wrap with context: fmt.Errorf("operation: %w", err)
|
|
11193
|
+
- Don't ignore errors silently
|
|
11194
|
+
|
|
11195
|
+
## Logging
|
|
11196
|
+
- log.Debugf \u2014 development only, verbose
|
|
11197
|
+
- log.Infof \u2014 normal operations
|
|
11198
|
+
- log.Warnf \u2014 recoverable issues
|
|
11199
|
+
- log.Errorf \u2014 errors that need attention
|
|
11200
|
+
- \u274C fmt.Println, fmt.Printf for logging
|
|
11201
|
+
|
|
11202
|
+
## Testing
|
|
11203
|
+
- Table-driven tests preferred
|
|
11204
|
+
- go test ./... must pass before commit
|
|
11205
|
+
`;
|
|
11206
|
+
var GO_MEMORY_ARCHITECTURE = `---
|
|
11207
|
+
name: cluster-architecture
|
|
11208
|
+
description: Go microservices cluster structure
|
|
11209
|
+
type: project
|
|
11210
|
+
---
|
|
11211
|
+
|
|
11212
|
+
## Service Architecture
|
|
11213
|
+
|
|
11214
|
+
_Update this with your project's actual services as you learn them._
|
|
11215
|
+
|
|
11216
|
+
| Service | Role |
|
|
11217
|
+
|---------|------|
|
|
11218
|
+
| gate_server | Client connection, protocol decode |
|
|
11219
|
+
| logic_server | Game logic, state management |
|
|
11220
|
+
| scene_server | Scene/combat, ECS-based |
|
|
11221
|
+
| db_server | Database operations (all DB access goes here) |
|
|
11222
|
+
|
|
11223
|
+
## Startup Order
|
|
11224
|
+
Services have dependency order. Check project docs or startup scripts.
|
|
11225
|
+
|
|
11226
|
+
## RPC Call Chain
|
|
11227
|
+
Typical request flow: client \u2192 gate \u2192 logic \u2192 scene \u2192 db
|
|
11228
|
+
`;
|
|
11229
|
+
var GO_HOOK_VERIFY = `#!/bin/bash
|
|
11230
|
+
# Leveled verification for Go server.
|
|
11231
|
+
LEVEL=\${1:-quick}
|
|
11232
|
+
case "$LEVEL" in
|
|
11233
|
+
quick)
|
|
11234
|
+
go vet ./... 2>&1 || exit 1
|
|
11235
|
+
;;
|
|
11236
|
+
build)
|
|
11237
|
+
go vet ./... 2>&1 || exit 1
|
|
11238
|
+
go build ./... 2>&1 || exit 1
|
|
11239
|
+
;;
|
|
11240
|
+
full)
|
|
11241
|
+
go vet ./... 2>&1 || exit 1
|
|
11242
|
+
go build ./... 2>&1 || exit 1
|
|
11243
|
+
go test ./... 2>&1 || exit 1
|
|
11244
|
+
;;
|
|
11245
|
+
esac
|
|
11246
|
+
exit 0
|
|
11247
|
+
`;
|
|
11248
|
+
function getGoServerBundle() {
|
|
11249
|
+
return {
|
|
11250
|
+
"rules/constitution.md.tmpl": GO_RULES_CONSTITUTION,
|
|
11251
|
+
"rules/golden-principles.md": GO_RULES_GOLDEN_PRINCIPLES,
|
|
11252
|
+
"rules/go-style.md": GO_RULES_STYLE,
|
|
11253
|
+
"rules/known-pitfalls.md": RULE_KNOWN_PITFALLS,
|
|
11254
|
+
"rules/architecture-boundaries.md": RULE_ARCHITECTURE_BOUNDARIES,
|
|
11255
|
+
"commands/auto-work.md": CMD_AUTO_WORK,
|
|
11256
|
+
"commands/auto-bugfix.md": CMD_AUTO_BUGFIX,
|
|
11257
|
+
"commands/review.md": CMD_REVIEW,
|
|
11258
|
+
"commands/fix-harness.md": CMD_FIX_HARNESS,
|
|
11259
|
+
"commands/plan.md": CMD_PLAN,
|
|
11260
|
+
"commands/verify.md": CMD_VERIFY,
|
|
11261
|
+
"commands/parallel-execute.md": CMD_PARALLEL_EXECUTE,
|
|
11262
|
+
"memory/MEMORY.md": MEMORY_INDEX,
|
|
11263
|
+
"memory/cluster-architecture.md": GO_MEMORY_ARCHITECTURE,
|
|
11264
|
+
"hooks/constitution-guard.sh": HOOK_CONSTITUTION_GUARD,
|
|
11265
|
+
"hooks/verify-server.sh": GO_HOOK_VERIFY,
|
|
11266
|
+
"hooks/pre-commit.sh": HOOK_PRE_COMMIT,
|
|
11267
|
+
"hooks/post-commit.sh": HOOK_POST_COMMIT,
|
|
11268
|
+
"hooks/push-gate.sh": HOOK_PUSH_GATE,
|
|
11269
|
+
"hooks/harness-evolution.sh": HOOK_HARNESS_EVOLUTION
|
|
11270
|
+
};
|
|
11271
|
+
}
|
|
11272
|
+
|
|
11273
|
+
// src/templates/bundles/unreal.ts
|
|
11274
|
+
init_common();
|
|
11275
|
+
var UE_RULES_CONSTITUTION = `# Forbidden Zone Constitution
|
|
11276
|
+
|
|
11277
|
+
## Auto-Generated Code
|
|
11278
|
+
- \`{{CONFIG_GEN_PATH}}\` \u2014 Generated code. Do not edit manually.
|
|
11279
|
+
- \`Intermediate/\` \u2014 Build intermediates. Never commit or edit.
|
|
11280
|
+
- \`*.generated.h\` \u2014 UHT generated headers.
|
|
11281
|
+
|
|
11282
|
+
## Engine Source
|
|
11283
|
+
- \`Engine/\` \u2014 Unreal Engine source. Modify only in engine fork.
|
|
11284
|
+
`;
|
|
11285
|
+
var UE_RULES_GOLDEN_PRINCIPLES = `# Golden Principles \u2014 Unreal C++
|
|
11286
|
+
|
|
11287
|
+
## Memory Management
|
|
11288
|
+
- \u274C Raw \`new\` for UObjects
|
|
11289
|
+
- \u2705 \`NewObject<T>()\`, \`CreateDefaultSubobject<T>()\`
|
|
11290
|
+
- All UObject* references must have UPROPERTY()
|
|
11291
|
+
|
|
11292
|
+
## Logging
|
|
11293
|
+
- \u274C printf, cout, std::cerr
|
|
11294
|
+
- \u2705 UE_LOG(LogCategory, Verbosity, TEXT("..."))
|
|
11295
|
+
|
|
11296
|
+
## Threading
|
|
11297
|
+
- \u274C std::thread
|
|
11298
|
+
- \u2705 FRunnable, AsyncTask, FGraphEvent
|
|
11299
|
+
|
|
11300
|
+
## Naming Conventions
|
|
11301
|
+
- F = Struct (FVector, FTransform)
|
|
11302
|
+
- U = UObject-derived (UActorComponent)
|
|
11303
|
+
- A = AActor-derived (ACharacter)
|
|
11304
|
+
- E = Enum (EMovementMode)
|
|
11305
|
+
- I = Interface (IInteractable)
|
|
11306
|
+
- b prefix for booleans (bIsActive)
|
|
11307
|
+
|
|
11308
|
+
## Garbage Collection
|
|
11309
|
+
- Pointers in containers must be UPROPERTY() or AddToRoot()
|
|
11310
|
+
- Use TWeakObjectPtr for non-owning references
|
|
11311
|
+
- Never cache raw pointers to UObjects across frames
|
|
11312
|
+
`;
|
|
11313
|
+
var UE_RULES_STYLE = `# Unreal C++ Style Guide
|
|
11314
|
+
|
|
11315
|
+
## Headers
|
|
11316
|
+
- #pragma once (not include guards)
|
|
11317
|
+
- Engine headers before project headers
|
|
11318
|
+
- Minimal includes in headers, forward-declare where possible
|
|
11319
|
+
|
|
11320
|
+
## Code Organization
|
|
11321
|
+
- .h in Public/, .cpp in Private/
|
|
11322
|
+
- One class per file pair
|
|
11323
|
+
- Module boundaries respected
|
|
11324
|
+
`;
|
|
11325
|
+
function getUnrealBundle() {
|
|
11326
|
+
return {
|
|
11327
|
+
"rules/constitution.md.tmpl": UE_RULES_CONSTITUTION,
|
|
11328
|
+
"rules/golden-principles.md": UE_RULES_GOLDEN_PRINCIPLES,
|
|
11329
|
+
"rules/unreal-cpp.md": UE_RULES_STYLE,
|
|
11330
|
+
"rules/known-pitfalls.md": RULE_KNOWN_PITFALLS,
|
|
11331
|
+
"rules/architecture-boundaries.md": RULE_ARCHITECTURE_BOUNDARIES,
|
|
11332
|
+
"commands/auto-work.md": CMD_AUTO_WORK,
|
|
11333
|
+
"commands/auto-bugfix.md": CMD_AUTO_BUGFIX,
|
|
11334
|
+
"commands/review.md": CMD_REVIEW,
|
|
11335
|
+
"commands/fix-harness.md": CMD_FIX_HARNESS,
|
|
11336
|
+
"commands/plan.md": CMD_PLAN,
|
|
11337
|
+
"commands/verify.md": CMD_VERIFY,
|
|
11338
|
+
"commands/parallel-execute.md": CMD_PARALLEL_EXECUTE,
|
|
11339
|
+
"memory/MEMORY.md": MEMORY_INDEX,
|
|
11340
|
+
"hooks/constitution-guard.sh": HOOK_CONSTITUTION_GUARD,
|
|
11341
|
+
"hooks/pre-commit.sh": HOOK_PRE_COMMIT,
|
|
11342
|
+
"hooks/post-commit.sh": HOOK_POST_COMMIT,
|
|
11343
|
+
"hooks/push-gate.sh": HOOK_PUSH_GATE,
|
|
11344
|
+
"hooks/harness-evolution.sh": HOOK_HARNESS_EVOLUTION
|
|
11345
|
+
};
|
|
11346
|
+
}
|
|
11347
|
+
|
|
11348
|
+
// src/templates/bundles/godot.ts
|
|
11349
|
+
init_common();
|
|
11350
|
+
var GODOT_RULES_CONSTITUTION = `# Forbidden Zone Constitution
|
|
11351
|
+
|
|
11352
|
+
## Auto-Generated Code
|
|
11353
|
+
- \`{{CONFIG_GEN_PATH}}\` \u2014 Generated scripts. Edit source data \u2192 regenerate.
|
|
11354
|
+
- \`.import/\` \u2014 Godot import cache. Never edit or commit.
|
|
11355
|
+
|
|
11356
|
+
## Addons
|
|
11357
|
+
- \`addons/\` \u2014 Third-party plugins. Do not modify unless forked.
|
|
11358
|
+
`;
|
|
11359
|
+
var GODOT_RULES_GOLDEN_PRINCIPLES = `# Golden Principles \u2014 Godot/GDScript
|
|
11360
|
+
|
|
11361
|
+
## Type Hints
|
|
11362
|
+
- \u2705 All function parameters and return types must have type hints
|
|
11363
|
+
- \u274C Untyped \`func process(delta)\`
|
|
11364
|
+
- \u2705 \`func _process(delta: float) -> void\`
|
|
11365
|
+
|
|
11366
|
+
## Signals
|
|
11367
|
+
- Connect in \`_ready()\`
|
|
11368
|
+
- Disconnect in \`_exit_tree()\`
|
|
11369
|
+
- \u274C Unmatched connect without disconnect
|
|
11370
|
+
|
|
11371
|
+
## Physics
|
|
11372
|
+
- \u274C Movement in \`_process()\`
|
|
11373
|
+
- \u2705 Movement in \`_physics_process()\`
|
|
11374
|
+
|
|
11375
|
+
## Node References
|
|
11376
|
+
- \u274C Hardcoded paths: \`get_node("../Player/Sprite")\`
|
|
11377
|
+
- \u2705 @onready var + @export for configurable references
|
|
11378
|
+
|
|
11379
|
+
## Resource Loading
|
|
11380
|
+
- \u274C \`load()\` at runtime for large resources
|
|
11381
|
+
- \u2705 \`preload()\` for small, always-needed resources
|
|
11382
|
+
- \u2705 \`ResourceLoader.load_threaded_request()\` for large resources
|
|
11383
|
+
`;
|
|
11384
|
+
var GODOT_RULES_STYLE = `# GDScript Style Guide
|
|
11385
|
+
|
|
11386
|
+
## Naming
|
|
11387
|
+
- Classes: PascalCase
|
|
11388
|
+
- Functions/variables: snake_case
|
|
11389
|
+
- Constants: UPPER_SNAKE_CASE
|
|
11390
|
+
- Signals: snake_case (past tense: health_changed, item_picked_up)
|
|
11391
|
+
- Private: underscore prefix (_internal_method)
|
|
11392
|
+
|
|
11393
|
+
## File Organization
|
|
11394
|
+
- One script per node/scene where possible
|
|
11395
|
+
- Autoloads for global systems
|
|
11396
|
+
- Class name matches file name
|
|
11397
|
+
`;
|
|
11398
|
+
function getGodotBundle() {
|
|
11399
|
+
return {
|
|
11400
|
+
"rules/constitution.md.tmpl": GODOT_RULES_CONSTITUTION,
|
|
11401
|
+
"rules/golden-principles.md": GODOT_RULES_GOLDEN_PRINCIPLES,
|
|
11402
|
+
"rules/godot-gdscript.md": GODOT_RULES_STYLE,
|
|
11403
|
+
"rules/known-pitfalls.md": RULE_KNOWN_PITFALLS,
|
|
11404
|
+
"rules/architecture-boundaries.md": RULE_ARCHITECTURE_BOUNDARIES,
|
|
11405
|
+
"commands/auto-work.md": CMD_AUTO_WORK,
|
|
11406
|
+
"commands/auto-bugfix.md": CMD_AUTO_BUGFIX,
|
|
11407
|
+
"commands/review.md": CMD_REVIEW,
|
|
11408
|
+
"commands/fix-harness.md": CMD_FIX_HARNESS,
|
|
11409
|
+
"commands/plan.md": CMD_PLAN,
|
|
11410
|
+
"commands/verify.md": CMD_VERIFY,
|
|
11411
|
+
"commands/parallel-execute.md": CMD_PARALLEL_EXECUTE,
|
|
11412
|
+
"memory/MEMORY.md": MEMORY_INDEX,
|
|
11413
|
+
"hooks/constitution-guard.sh": HOOK_CONSTITUTION_GUARD,
|
|
11414
|
+
"hooks/pre-commit.sh": HOOK_PRE_COMMIT,
|
|
11415
|
+
"hooks/post-commit.sh": HOOK_POST_COMMIT,
|
|
11416
|
+
"hooks/push-gate.sh": HOOK_PUSH_GATE,
|
|
11417
|
+
"hooks/harness-evolution.sh": HOOK_HARNESS_EVOLUTION
|
|
11418
|
+
};
|
|
11419
|
+
}
|
|
11420
|
+
|
|
11421
|
+
// src/templates/bundles/workspace.ts
|
|
11422
|
+
init_common();
|
|
11423
|
+
var WORKSPACE_MEMORY_CROSS_PROJECT = `---
|
|
11424
|
+
name: cross-project-protocol
|
|
11425
|
+
description: Cross-project protocol and data sync rules
|
|
11426
|
+
type: project
|
|
11427
|
+
---
|
|
11428
|
+
|
|
11429
|
+
## Cross-Project Sync Points
|
|
11430
|
+
|
|
11431
|
+
_Update as you discover sync boundaries between sub-projects._
|
|
11432
|
+
|
|
11433
|
+
### Protobuf
|
|
11434
|
+
- Proto definitions are shared between client and server
|
|
11435
|
+
- Edit .proto \u2192 regenerate both sides
|
|
11436
|
+
- Check field number compatibility when adding fields
|
|
11437
|
+
|
|
11438
|
+
### Config Tables
|
|
11439
|
+
- Config data flows: Data Source \u2192 Generator \u2192 Client code + Server code
|
|
11440
|
+
- Both sides must regenerate when schema changes
|
|
11441
|
+
|
|
11442
|
+
### Version Compatibility
|
|
11443
|
+
- Client and server versions must match on protocol level
|
|
11444
|
+
- Breaking changes require coordinated release
|
|
11445
|
+
`;
|
|
11446
|
+
var WORKSPACE_MEMORY_PITFALLS = `---
|
|
11447
|
+
name: cross-project-pitfalls
|
|
11448
|
+
description: Common mistakes when working across sub-projects
|
|
11449
|
+
type: project
|
|
11450
|
+
---
|
|
11451
|
+
|
|
11452
|
+
## Cross-Project Pitfalls
|
|
11453
|
+
|
|
11454
|
+
_This file grows through harness self-evolution._
|
|
11455
|
+
|
|
11456
|
+
### Proto Field Number Conflicts
|
|
11457
|
+
- \u274C Reusing deleted field numbers
|
|
11458
|
+
- \u2705 Reserve deleted field numbers, always use new ones
|
|
11459
|
+
|
|
11460
|
+
### Config Schema Drift
|
|
11461
|
+
- \u274C Changing config format on one side only
|
|
11462
|
+
- \u2705 Update generator, regenerate both client and server
|
|
11463
|
+
`;
|
|
11464
|
+
function getWorkspaceBundle() {
|
|
11465
|
+
return {
|
|
11466
|
+
"commands/fix-harness.md": CMD_FIX_HARNESS,
|
|
11467
|
+
"commands/plan.md": CMD_PLAN,
|
|
11468
|
+
"memory/MEMORY.md": MEMORY_INDEX,
|
|
11469
|
+
"memory/cross-project-protocol.md": WORKSPACE_MEMORY_CROSS_PROJECT,
|
|
11470
|
+
"memory/cross-project-pitfalls.md": WORKSPACE_MEMORY_PITFALLS
|
|
11471
|
+
};
|
|
11472
|
+
}
|
|
11473
|
+
|
|
11474
|
+
// src/templates/index.ts
|
|
11475
|
+
function getBundleForEngine(engine, serverLanguage) {
|
|
11476
|
+
if (engine === "unity") return getUnityBundle();
|
|
11477
|
+
if (engine === "unreal") return getUnrealBundle();
|
|
11478
|
+
if (engine === "godot") return getGodotBundle();
|
|
11479
|
+
if (serverLanguage === "go") return getGoServerBundle();
|
|
11480
|
+
const common = (init_common(), __toCommonJS(common_exports));
|
|
11481
|
+
return {
|
|
11482
|
+
"rules/known-pitfalls.md": common.RULE_KNOWN_PITFALLS,
|
|
11483
|
+
"rules/architecture-boundaries.md": common.RULE_ARCHITECTURE_BOUNDARIES,
|
|
11484
|
+
"commands/auto-work.md": common.CMD_AUTO_WORK,
|
|
11485
|
+
"commands/auto-bugfix.md": common.CMD_AUTO_BUGFIX,
|
|
11486
|
+
"commands/review.md": common.CMD_REVIEW,
|
|
11487
|
+
"commands/fix-harness.md": common.CMD_FIX_HARNESS,
|
|
11488
|
+
"commands/plan.md": common.CMD_PLAN,
|
|
11489
|
+
"commands/verify.md": common.CMD_VERIFY,
|
|
11490
|
+
"commands/parallel-execute.md": common.CMD_PARALLEL_EXECUTE,
|
|
11491
|
+
"memory/MEMORY.md": common.MEMORY_INDEX,
|
|
11492
|
+
"hooks/constitution-guard.sh": common.HOOK_CONSTITUTION_GUARD,
|
|
11493
|
+
"hooks/pre-commit.sh": common.HOOK_PRE_COMMIT,
|
|
11494
|
+
"hooks/post-commit.sh": common.HOOK_POST_COMMIT,
|
|
11495
|
+
"hooks/push-gate.sh": common.HOOK_PUSH_GATE,
|
|
11496
|
+
"hooks/harness-evolution.sh": common.HOOK_HARNESS_EVOLUTION
|
|
11497
|
+
};
|
|
11498
|
+
}
|
|
11499
|
+
|
|
11500
|
+
// src/services/harness/consolidate.ts
|
|
11501
|
+
import { existsSync as existsSync10, readdirSync as readdirSync4, readFileSync as readFileSync8, writeFileSync as writeFileSync5, mkdirSync as mkdirSync6, statSync as statSync11 } from "fs";
|
|
11502
|
+
import { join as join8 } from "path";
|
|
11503
|
+
var CONSOLIDATION_DIRS = ["rules", "commands", "memory", "skills", "hooks"];
|
|
11504
|
+
var LEGACY_DIRS = [".claude", ".codex"];
|
|
11505
|
+
function consolidateLegacyIntoDanya(projectDir) {
|
|
11506
|
+
const danyaDir = join8(projectDir, ".danya");
|
|
11507
|
+
const result = { merged: [], skipped: [], sources: [] };
|
|
11508
|
+
for (const legacyName of LEGACY_DIRS) {
|
|
11509
|
+
const legacyDir = join8(projectDir, legacyName);
|
|
11510
|
+
if (!existsSync10(legacyDir)) continue;
|
|
11511
|
+
result.sources.push(legacyName);
|
|
11512
|
+
for (const subDir of CONSOLIDATION_DIRS) {
|
|
11513
|
+
const legacySub = join8(legacyDir, subDir);
|
|
11514
|
+
if (!existsSync10(legacySub)) continue;
|
|
11515
|
+
const danyaSub = join8(danyaDir, subDir);
|
|
11516
|
+
mkdirSync6(danyaSub, { recursive: true });
|
|
11517
|
+
copyMissing(legacySub, danyaSub, subDir, result);
|
|
11518
|
+
}
|
|
11519
|
+
mergeSettings(legacyDir, danyaDir, result);
|
|
11520
|
+
}
|
|
11521
|
+
return result;
|
|
11522
|
+
}
|
|
11523
|
+
function copyMissing(legacyDir, danyaDir, prefix, result) {
|
|
11524
|
+
let entries;
|
|
11525
|
+
try {
|
|
11526
|
+
entries = readdirSync4(legacyDir);
|
|
11527
|
+
} catch {
|
|
11528
|
+
return;
|
|
11529
|
+
}
|
|
11530
|
+
for (const entry of entries) {
|
|
11531
|
+
const legacyPath = join8(legacyDir, entry);
|
|
11532
|
+
const danyaPath = join8(danyaDir, entry);
|
|
11533
|
+
try {
|
|
11534
|
+
if (statSync11(legacyPath).isDirectory()) {
|
|
11535
|
+
mkdirSync6(danyaPath, { recursive: true });
|
|
11536
|
+
copyMissing(legacyPath, danyaPath, `${prefix}/${entry}`, result);
|
|
11537
|
+
continue;
|
|
11538
|
+
}
|
|
11539
|
+
} catch {
|
|
11540
|
+
continue;
|
|
11541
|
+
}
|
|
11542
|
+
const relPath = `${prefix}/${entry}`;
|
|
11543
|
+
if (existsSync10(danyaPath)) {
|
|
11544
|
+
result.skipped.push(relPath);
|
|
11545
|
+
} else {
|
|
11546
|
+
try {
|
|
11547
|
+
const content = readFileSync8(legacyPath);
|
|
11548
|
+
writeFileSync5(danyaPath, content, {
|
|
11549
|
+
mode: prefix === "hooks" ? 493 : 420
|
|
11550
|
+
});
|
|
11551
|
+
result.merged.push(relPath);
|
|
11552
|
+
} catch {
|
|
11553
|
+
}
|
|
11554
|
+
}
|
|
11555
|
+
}
|
|
11556
|
+
}
|
|
11557
|
+
function mergeSettings(legacyDir, danyaDir, result) {
|
|
11558
|
+
const legacySettings = join8(legacyDir, "settings.json");
|
|
11559
|
+
const danyaSettings = join8(danyaDir, "settings.json");
|
|
11560
|
+
if (!existsSync10(legacySettings)) return;
|
|
11561
|
+
let legacyConfig;
|
|
11562
|
+
let danyaConfig;
|
|
11563
|
+
try {
|
|
11564
|
+
legacyConfig = JSON.parse(readFileSync8(legacySettings, "utf-8"));
|
|
11565
|
+
} catch {
|
|
11566
|
+
return;
|
|
11567
|
+
}
|
|
11568
|
+
try {
|
|
11569
|
+
danyaConfig = existsSync10(danyaSettings) ? JSON.parse(readFileSync8(danyaSettings, "utf-8")) : {};
|
|
11570
|
+
} catch {
|
|
11571
|
+
danyaConfig = {};
|
|
11572
|
+
}
|
|
11573
|
+
if (legacyConfig.hooks) {
|
|
11574
|
+
if (!danyaConfig.hooks) danyaConfig.hooks = {};
|
|
11575
|
+
for (const [event, handlers] of Object.entries(legacyConfig.hooks)) {
|
|
11576
|
+
if (!danyaConfig.hooks[event]) {
|
|
11577
|
+
danyaConfig.hooks[event] = handlers;
|
|
11578
|
+
result.merged.push(`settings.json:hooks.${event}`);
|
|
11579
|
+
}
|
|
11580
|
+
}
|
|
11581
|
+
writeFileSync5(danyaSettings, JSON.stringify(danyaConfig, null, 2), "utf-8");
|
|
11582
|
+
}
|
|
11583
|
+
}
|
|
11584
|
+
|
|
11585
|
+
// src/commands/initProject.ts
|
|
11586
|
+
async function initDanyaProject(cwd2, force = false) {
|
|
11587
|
+
const danyaDir = join9(cwd2, ".danya");
|
|
11588
|
+
if (existsSync11(danyaDir) && !force) {
|
|
11589
|
+
return "\u26A0\uFE0F .danya/ already exists. Skipping initialization. Use --force to overwrite.";
|
|
11590
|
+
}
|
|
11591
|
+
const workspace = detectWorkspace(cwd2);
|
|
11592
|
+
const instructionsFile = isClaudeModel() ? "CLAUDE.md" : "AGENTS.md";
|
|
11593
|
+
if (workspace.type === "workspace") {
|
|
11594
|
+
return initWorkspace(cwd2, workspace.subProjects, instructionsFile, force);
|
|
11595
|
+
}
|
|
11596
|
+
return initSingleProject(cwd2, instructionsFile, force);
|
|
11597
|
+
}
|
|
11598
|
+
function initSingleProject(cwd2, instructionsFile, force) {
|
|
11599
|
+
const danyaDir = join9(cwd2, ".danya");
|
|
11600
|
+
const detection = detectProject(cwd2);
|
|
11601
|
+
const projectName = basename4(cwd2);
|
|
11602
|
+
const bundle = getBundleForEngine(detection.engine, detection.serverLanguage);
|
|
11603
|
+
const ctx = buildTemplateContext(projectName, detection.engine, detection.serverLanguage, instructionsFile);
|
|
11604
|
+
const installed = installBundle(danyaDir, bundle, ctx, { force });
|
|
11605
|
+
const guardRules = generateGuardRules(detection.engine, detection.serverLanguage);
|
|
11606
|
+
writeFileSync6(join9(danyaDir, "guard-rules.json"), JSON.stringify(guardRules, null, 2), "utf-8");
|
|
11607
|
+
writeFileSync6(join9(danyaDir, "gate-chain.json"), JSON.stringify({
|
|
11608
|
+
gates: {
|
|
11609
|
+
guard: { enabled: true },
|
|
11610
|
+
syntax: { enabled: true },
|
|
11611
|
+
verify: { enabled: true, default_level: "build" },
|
|
11612
|
+
commit: { enabled: true },
|
|
11613
|
+
review: { enabled: true },
|
|
11614
|
+
push: { enabled: true, require_review: true }
|
|
11615
|
+
}
|
|
11616
|
+
}, null, 2), "utf-8");
|
|
11617
|
+
writeFileSync6(join9(danyaDir, "settings.json"), JSON.stringify(generateSettings(), null, 2), "utf-8");
|
|
11618
|
+
const consolidation = consolidateLegacyIntoDanya(cwd2);
|
|
11619
|
+
writeInstructionsFile(cwd2, instructionsFile, detection.engine, detection.serverLanguage);
|
|
11620
|
+
const legacyMsg = consolidation.sources.length > 0 ? [` Legacy integrated: ${consolidation.sources.join(", ")} \u2192 .danya/ (${consolidation.merged.length} merged, ${consolidation.skipped.length} skipped)`] : [];
|
|
11621
|
+
return [
|
|
11622
|
+
"\u2705 Danya project initialized! (single-project mode)",
|
|
11623
|
+
"",
|
|
11624
|
+
`Detected: engine=${detection.engine ?? "none"}, server=${detection.serverLanguage ?? "none"}`,
|
|
11625
|
+
`Guard rules: ${guardRules.length} forbidden zone patterns`,
|
|
11626
|
+
`Harness files: ${installed.length} files installed`,
|
|
11627
|
+
"",
|
|
11628
|
+
"Created:",
|
|
11629
|
+
` .danya/rules/ \u2014 ${countFiles(installed, "rules/")} constraint files`,
|
|
11630
|
+
` .danya/commands/ \u2014 ${countFiles(installed, "commands/")} workflow commands`,
|
|
11631
|
+
` .danya/memory/ \u2014 ${countFiles(installed, "memory/")} knowledge files`,
|
|
11632
|
+
` .danya/hooks/ \u2014 ${countFiles(installed, "hooks/")} hook scripts`,
|
|
11633
|
+
" .danya/gate-chain.json \u2014 Gate chain configuration",
|
|
11634
|
+
" .danya/guard-rules.json \u2014 Forbidden zone patterns",
|
|
11635
|
+
" .danya/settings.json \u2014 Hook registration",
|
|
11636
|
+
...legacyMsg,
|
|
11637
|
+
"",
|
|
11638
|
+
"Gate chain: Edit \u2192 Guard \u2192 Syntax \u2192 Verify \u2192 Commit \u2192 Review \u2192 Push",
|
|
11639
|
+
"",
|
|
11640
|
+
"Available commands:",
|
|
11641
|
+
" /auto-work <req> \u2014 Full-auto pipeline (plan\u2192code\u2192verify\u2192review\u2192commit\u2192sediment\u2192evolve)",
|
|
11642
|
+
" /auto-bugfix <bug> \u2014 Bug reproduction + auto-fix (max 5 rounds)",
|
|
11643
|
+
" /review \u2014 100-point scoring code review",
|
|
11644
|
+
" /fix-harness \u2014 Update rules after error pattern",
|
|
11645
|
+
" /plan <req> \u2014 Analysis and planning",
|
|
11646
|
+
" /verify [level] \u2014 Mechanical verification (quick|build|full)",
|
|
11647
|
+
"",
|
|
11648
|
+
"Next steps:",
|
|
11649
|
+
` 1. Customize ${instructionsFile} with your project-specific rules`,
|
|
11650
|
+
" 2. Review .danya/rules/ and adjust to your project",
|
|
11651
|
+
" 3. Start developing: danya"
|
|
11652
|
+
].join("\n");
|
|
11653
|
+
}
|
|
11654
|
+
function initWorkspace(rootPath, subProjects, instructionsFile, force) {
|
|
11655
|
+
const rootDanyaDir = join9(rootPath, ".danya");
|
|
11656
|
+
const rootName = basename4(rootPath);
|
|
11657
|
+
const wsBundle = getWorkspaceBundle();
|
|
11658
|
+
const wsCtx = buildTemplateContext(rootName, null, null, instructionsFile);
|
|
11659
|
+
const wsInstalled = installBundle(rootDanyaDir, wsBundle, wsCtx, { force });
|
|
11660
|
+
writeFileSync6(join9(rootDanyaDir, "guard-rules.json"), "[]", "utf-8");
|
|
11661
|
+
writeFileSync6(join9(rootDanyaDir, "gate-chain.json"), JSON.stringify({
|
|
11662
|
+
gates: { guard: { enabled: true }, review: { enabled: true }, push: { enabled: true } }
|
|
11663
|
+
}, null, 2), "utf-8");
|
|
11664
|
+
const subResults = [];
|
|
11665
|
+
for (const sub of subProjects) {
|
|
11666
|
+
const subDanyaDir = join9(sub.path, ".danya");
|
|
11667
|
+
const bundle = getBundleForEngine(sub.engine, sub.serverLanguage);
|
|
11668
|
+
const ctx = buildTemplateContext(sub.name, sub.engine, sub.serverLanguage, instructionsFile);
|
|
11669
|
+
const installed = installBundle(subDanyaDir, bundle, ctx, { force });
|
|
11670
|
+
const guardRules = generateGuardRules(sub.engine, sub.serverLanguage);
|
|
11671
|
+
writeFileSync6(join9(subDanyaDir, "guard-rules.json"), JSON.stringify(guardRules, null, 2), "utf-8");
|
|
11672
|
+
writeFileSync6(join9(subDanyaDir, "gate-chain.json"), JSON.stringify({
|
|
11673
|
+
gates: { guard: { enabled: true }, syntax: { enabled: true }, verify: { enabled: true }, commit: { enabled: true }, review: { enabled: true }, push: { enabled: true, require_review: true } }
|
|
11674
|
+
}, null, 2), "utf-8");
|
|
11675
|
+
writeFileSync6(join9(subDanyaDir, "settings.json"), JSON.stringify(generateSettings(), null, 2), "utf-8");
|
|
11676
|
+
consolidateLegacyIntoDanya(sub.path);
|
|
11677
|
+
writeInstructionsFile(sub.path, instructionsFile, sub.engine, sub.serverLanguage);
|
|
11678
|
+
subResults.push(` ${sub.name}/ (${sub.role}): engine=${sub.engine ?? "none"}, server=${sub.serverLanguage ?? "none"}, ${installed.length} files`);
|
|
11679
|
+
}
|
|
11680
|
+
consolidateLegacyIntoDanya(rootPath);
|
|
11681
|
+
writeInstructionsFile(rootPath, instructionsFile, null, null);
|
|
11682
|
+
return [
|
|
11683
|
+
"\u2705 Danya workspace initialized! (multi-project mode)",
|
|
11684
|
+
"",
|
|
11685
|
+
"Workspace structure:",
|
|
11686
|
+
` ${rootName}/.danya/ \u2014 Cross-project (${wsInstalled.length} files)`,
|
|
11687
|
+
...subResults,
|
|
11688
|
+
"",
|
|
11689
|
+
"Three-layer isolation:",
|
|
11690
|
+
" Layer 1: Workspace \u2014 cross-project rules, memory, commands",
|
|
11691
|
+
" Layer 2: Sub-projects \u2014 engine-specific rules, hooks, commands",
|
|
11692
|
+
" Layer 3: Session \u2014 git worktree isolation for parallel tasks",
|
|
11693
|
+
"",
|
|
11694
|
+
"Gate chain per sub-project: Edit \u2192 Guard \u2192 Syntax \u2192 Verify \u2192 Commit \u2192 Review \u2192 Push"
|
|
11695
|
+
].join("\n");
|
|
11696
|
+
}
|
|
11697
|
+
function generateSettings() {
|
|
11698
|
+
return {
|
|
11699
|
+
hooks: {
|
|
11700
|
+
PreToolUse: [
|
|
11701
|
+
{ matcher: "Edit|Write", hooks: [{ type: "command", command: "bash .danya/hooks/constitution-guard.sh", timeout: 5e3 }] },
|
|
11702
|
+
{ matcher: "Bash", commandPattern: "git\\s+commit", hooks: [{ type: "command", command: "bash .danya/hooks/pre-commit.sh", timeout: 3e5 }] },
|
|
11703
|
+
{ matcher: "Bash", commandPattern: "git\\s+push", hooks: [{ type: "command", command: "bash .danya/hooks/push-gate.sh", timeout: 5e3 }] }
|
|
11704
|
+
],
|
|
11705
|
+
PostToolUse: [
|
|
11706
|
+
{ matcher: "Bash", hooks: [{ type: "command", command: "bash .danya/hooks/harness-evolution.sh", timeout: 5e3 }] },
|
|
11707
|
+
{ matcher: "Bash", commandPattern: "git\\s+commit", hooks: [{ type: "command", command: "bash .danya/hooks/post-commit.sh", timeout: 5e3 }] }
|
|
11708
|
+
]
|
|
11709
|
+
}
|
|
11710
|
+
};
|
|
11711
|
+
}
|
|
11712
|
+
function writeInstructionsFile(dir, instructionsFile, engine, serverLanguage) {
|
|
11713
|
+
const path5 = join9(dir, instructionsFile);
|
|
11714
|
+
const altFile = instructionsFile === "CLAUDE.md" ? "AGENTS.md" : "CLAUDE.md";
|
|
11715
|
+
if (existsSync11(path5) || existsSync11(join9(dir, altFile))) return;
|
|
11716
|
+
writeFileSync6(path5, generateInstructionsTemplate(engine, serverLanguage), "utf-8");
|
|
11717
|
+
}
|
|
11718
|
+
function generateInstructionsTemplate(engine, serverLanguage) {
|
|
11719
|
+
const lines = ["# Project Instructions", ""];
|
|
11720
|
+
lines.push("## Build & Test");
|
|
11721
|
+
if (engine === "unity") {
|
|
11722
|
+
lines.push("- Build: Unity Editor \u2192 File > Build Settings");
|
|
11723
|
+
lines.push("- Test: Window > General > Test Runner");
|
|
11724
|
+
} else if (engine === "unreal") {
|
|
11725
|
+
lines.push("- Build: UnrealBuildTool or IDE build");
|
|
11726
|
+
lines.push("- Test: Automation tab in Session Frontend");
|
|
11727
|
+
} else if (engine === "godot") {
|
|
11728
|
+
lines.push("- Build: godot --export-release <preset>");
|
|
11729
|
+
lines.push("- Test: GUT or custom test framework");
|
|
11730
|
+
}
|
|
11731
|
+
if (serverLanguage === "go") {
|
|
11732
|
+
lines.push("- Server build: make build");
|
|
11733
|
+
lines.push("- Server test: make test");
|
|
11734
|
+
lines.push("- Server lint: make lint");
|
|
11735
|
+
}
|
|
11736
|
+
if (!engine && !serverLanguage) {
|
|
11737
|
+
lines.push("- Build: <your build command>");
|
|
11738
|
+
lines.push("- Test: <your test command>");
|
|
11739
|
+
}
|
|
11740
|
+
lines.push("");
|
|
11741
|
+
lines.push("## Harness");
|
|
11742
|
+
lines.push("This project uses Danya harness. See .danya/ for:");
|
|
11743
|
+
lines.push("- rules/ \u2014 Coding constraints (auto-loaded every session)");
|
|
11744
|
+
lines.push("- commands/ \u2014 Workflow commands (/auto-work, /review, /fix-harness, etc.)");
|
|
11745
|
+
lines.push("- memory/ \u2014 Persistent domain knowledge");
|
|
11746
|
+
lines.push("- hooks/ \u2014 Mechanical enforcement scripts");
|
|
11747
|
+
lines.push("");
|
|
11748
|
+
lines.push("## Forbidden Zones");
|
|
11749
|
+
lines.push("See .danya/guard-rules.json. Hook enforced \u2014 Agent cannot bypass.");
|
|
11750
|
+
lines.push("");
|
|
11751
|
+
return lines.join("\n");
|
|
11752
|
+
}
|
|
11753
|
+
function generateGuardRules(engine, serverLanguage) {
|
|
11754
|
+
const rules = [];
|
|
11755
|
+
if (engine === "unity") {
|
|
11756
|
+
rules.push(
|
|
11757
|
+
{ pattern: "Config/Gen/", description: "Auto-generated config", fix_hint: "Edit Excel \u2192 run ConfigGenerate" },
|
|
11758
|
+
{ pattern: "Scripts/Framework/", description: "Core framework", fix_hint: "Needs programmer approval" }
|
|
11759
|
+
);
|
|
11760
|
+
}
|
|
11761
|
+
if (engine === "unreal") {
|
|
11762
|
+
rules.push(
|
|
11763
|
+
{ pattern: "Generated/", description: "UE generated code", fix_hint: "Regenerate via UBT" },
|
|
11764
|
+
{ pattern: "Intermediate/", description: "Build intermediates", fix_hint: "Do not edit" }
|
|
11765
|
+
);
|
|
11766
|
+
}
|
|
11767
|
+
if (engine === "godot") {
|
|
11768
|
+
rules.push(
|
|
11769
|
+
{ pattern: "\\.import/", description: "Godot import cache", fix_hint: "Do not edit" }
|
|
11770
|
+
);
|
|
11771
|
+
}
|
|
11772
|
+
if (serverLanguage === "go") {
|
|
11773
|
+
rules.push(
|
|
11774
|
+
{ pattern: "orm/(golang|redis|mongo)/", description: "ORM generated code", fix_hint: "Edit XML \u2192 make orm" },
|
|
11775
|
+
{ pattern: "cfg_.*\\.go$", description: "Config generated code", fix_hint: "Edit data source \u2192 regenerate" },
|
|
11776
|
+
{ pattern: ".*_pb\\.go$", description: "Protobuf generated", fix_hint: "Edit .proto \u2192 protoc" }
|
|
11777
|
+
);
|
|
11778
|
+
}
|
|
11779
|
+
return rules;
|
|
11780
|
+
}
|
|
11781
|
+
function countFiles(installed, prefix) {
|
|
11782
|
+
return installed.filter((f) => f.startsWith(prefix)).length;
|
|
11783
|
+
}
|
|
11784
|
+
function isClaudeModel() {
|
|
11785
|
+
try {
|
|
11786
|
+
const modelManager = getModelManager();
|
|
11787
|
+
const modelName = modelManager.getCurrentModel();
|
|
11788
|
+
return Boolean(modelName && modelName.startsWith("claude"));
|
|
11789
|
+
} catch {
|
|
11790
|
+
return false;
|
|
11791
|
+
}
|
|
11792
|
+
}
|
|
11793
|
+
|
|
11794
|
+
// src/ui/screens/autoInitHarness.ts
|
|
11795
|
+
var hasRun = false;
|
|
11796
|
+
function autoInitHarness(cwd2) {
|
|
11797
|
+
if (hasRun) return;
|
|
11798
|
+
hasRun = true;
|
|
11799
|
+
const danyaDir = join10(cwd2, ".danya");
|
|
11800
|
+
if (existsSync12(danyaDir)) return;
|
|
11801
|
+
try {
|
|
11802
|
+
initDanyaProject(cwd2, false).catch(() => {
|
|
11803
|
+
});
|
|
11804
|
+
} catch {
|
|
11805
|
+
}
|
|
11806
|
+
}
|
|
11807
|
+
|
|
11808
|
+
// src/ui/components/ProjectOnboarding.tsx
|
|
10557
11809
|
function markProjectOnboardingComplete() {
|
|
10558
11810
|
const projectConfig = getCurrentProjectConfig();
|
|
10559
11811
|
if (!projectConfig.hasCompletedProjectOnboarding) {
|
|
@@ -10590,9 +11842,14 @@ function ProjectOnboarding({
|
|
|
10590
11842
|
if (!showOnboarding && !hasReleaseNotes) {
|
|
10591
11843
|
return null;
|
|
10592
11844
|
}
|
|
10593
|
-
const workspaceHasProjectGuide =
|
|
11845
|
+
const workspaceHasProjectGuide = existsSync13(join11(workspaceDir, PROJECT_FILE));
|
|
10594
11846
|
const isWorkspaceDirEmpty = isDirEmpty(workspaceDir);
|
|
10595
11847
|
const shouldRecommendProjectGuide = !workspaceHasProjectGuide && !isWorkspaceDirEmpty;
|
|
11848
|
+
React28.useEffect(() => {
|
|
11849
|
+
if (!isWorkspaceDirEmpty) {
|
|
11850
|
+
autoInitHarness(workspaceDir);
|
|
11851
|
+
}
|
|
11852
|
+
}, [workspaceDir, isWorkspaceDirEmpty]);
|
|
10596
11853
|
const theme = getTheme();
|
|
10597
11854
|
return /* @__PURE__ */ React28.createElement(Box21, { flexDirection: "column", gap: 1, padding: 1, paddingBottom: 0 }, showOnboarding && /* @__PURE__ */ React28.createElement(React28.Fragment, null, /* @__PURE__ */ React28.createElement(Text24, { color: theme.secondaryText }, "Tips for getting started:"), /* @__PURE__ */ React28.createElement(OrderedList, null, (() => {
|
|
10598
11855
|
const items = [];
|
|
@@ -10626,31 +11883,44 @@ function ProjectOnboarding({
|
|
|
10626
11883
|
|
|
10627
11884
|
// src/commands/init.ts
|
|
10628
11885
|
init_product();
|
|
11886
|
+
init_state();
|
|
10629
11887
|
var command2 = {
|
|
10630
11888
|
type: "prompt",
|
|
10631
11889
|
name: "init",
|
|
10632
|
-
description: `Initialize
|
|
11890
|
+
description: `Initialize Danya harness + ${PROJECT_FILE} for this project`,
|
|
10633
11891
|
isEnabled: true,
|
|
10634
11892
|
isHidden: false,
|
|
10635
|
-
progressMessage: "analyzing
|
|
11893
|
+
progressMessage: "initializing harness and analyzing codebase",
|
|
10636
11894
|
userFacingName() {
|
|
10637
11895
|
return "init";
|
|
10638
11896
|
},
|
|
10639
11897
|
async getPromptForCommand(_args) {
|
|
10640
11898
|
markProjectOnboardingComplete();
|
|
11899
|
+
let harnessResult = "";
|
|
11900
|
+
try {
|
|
11901
|
+
const force = _args.includes("--force");
|
|
11902
|
+
harnessResult = await initDanyaProject(getCwd(), force);
|
|
11903
|
+
} catch (e) {
|
|
11904
|
+
harnessResult = `\u26A0\uFE0F Harness init failed: ${e.message}`;
|
|
11905
|
+
}
|
|
10641
11906
|
return [
|
|
10642
11907
|
{
|
|
10643
11908
|
role: "user",
|
|
10644
11909
|
content: [
|
|
10645
11910
|
{
|
|
10646
11911
|
type: "text",
|
|
10647
|
-
text:
|
|
11912
|
+
text: `${harnessResult}
|
|
11913
|
+
|
|
11914
|
+
---
|
|
11915
|
+
|
|
11916
|
+
Now please analyze this codebase and create a ${PROJECT_FILE} file containing:
|
|
10648
11917
|
1. Build/lint/test commands - especially for running a single test
|
|
10649
11918
|
2. Code style guidelines including imports, formatting, types, naming conventions, error handling, etc.
|
|
10650
11919
|
|
|
10651
11920
|
The file you create will be given to agentic coding agents (such as yourself) that operate in this repository. Make it about 20 lines long.
|
|
10652
11921
|
If there's already a ${PROJECT_FILE}, improve it.
|
|
10653
|
-
If there are Cursor rules (in .cursor/rules/ or .cursorrules) or Copilot rules (in .github/copilot-instructions.md), make sure to include them
|
|
11922
|
+
If there are Cursor rules (in .cursor/rules/ or .cursorrules) or Copilot rules (in .github/copilot-instructions.md), make sure to include them.
|
|
11923
|
+
Also review the .danya/rules/ files and customize them based on what you learn about this codebase.`
|
|
10654
11924
|
}
|
|
10655
11925
|
]
|
|
10656
11926
|
}
|
|
@@ -10740,8 +12010,8 @@ function getReplStaticPrefixLength(orderedMessages, allMessages, unresolvedToolU
|
|
|
10740
12010
|
|
|
10741
12011
|
// src/commands/messages-debug.ts
|
|
10742
12012
|
init_log();
|
|
10743
|
-
import { existsSync as
|
|
10744
|
-
import { join as
|
|
12013
|
+
import { existsSync as existsSync14, readdirSync as readdirSync5, readFileSync as readFileSync9, statSync as statSync12 } from "fs";
|
|
12014
|
+
import { join as join12 } from "path";
|
|
10745
12015
|
function isDebugMode() {
|
|
10746
12016
|
return process.argv.includes("--debug") || process.argv.includes("--debug-verbose");
|
|
10747
12017
|
}
|
|
@@ -10772,15 +12042,15 @@ function getProgressText(message) {
|
|
|
10772
12042
|
}
|
|
10773
12043
|
function getLatestMessagesLogFile() {
|
|
10774
12044
|
const dir = CACHE_PATHS.messages();
|
|
10775
|
-
if (!
|
|
10776
|
-
const files =
|
|
12045
|
+
if (!existsSync14(dir)) return null;
|
|
12046
|
+
const files = readdirSync5(dir).filter((f) => f.endsWith(".json"));
|
|
10777
12047
|
if (files.length === 0) return null;
|
|
10778
12048
|
let best = null;
|
|
10779
12049
|
for (const file of files) {
|
|
10780
|
-
const fullPath =
|
|
12050
|
+
const fullPath = join12(dir, file);
|
|
10781
12051
|
let mtimeMs = 0;
|
|
10782
12052
|
try {
|
|
10783
|
-
mtimeMs =
|
|
12053
|
+
mtimeMs = statSync12(fullPath).mtimeMs;
|
|
10784
12054
|
} catch {
|
|
10785
12055
|
continue;
|
|
10786
12056
|
}
|
|
@@ -10891,9 +12161,9 @@ var command3 = {
|
|
|
10891
12161
|
);
|
|
10892
12162
|
const { toolUseIDs, duplicates, byID } = summarizeToolUses(normalized);
|
|
10893
12163
|
const latestLog = getLatestMessagesLogFile();
|
|
10894
|
-
const latestLogContent = latestLog &&
|
|
12164
|
+
const latestLogContent = latestLog && existsSync14(latestLog.path) ? (() => {
|
|
10895
12165
|
try {
|
|
10896
|
-
return JSON.parse(
|
|
12166
|
+
return JSON.parse(readFileSync9(latestLog.path, "utf8"));
|
|
10897
12167
|
} catch {
|
|
10898
12168
|
return null;
|
|
10899
12169
|
}
|
|
@@ -11172,7 +12442,7 @@ async function createAndStoreApiKey(accessToken) {
|
|
|
11172
12442
|
}
|
|
11173
12443
|
saveGlobalConfig(config2);
|
|
11174
12444
|
try {
|
|
11175
|
-
const { resetAnthropicClient } = await import("./llm-
|
|
12445
|
+
const { resetAnthropicClient } = await import("./llm-XBH33BXT.js");
|
|
11176
12446
|
resetAnthropicClient();
|
|
11177
12447
|
} catch {
|
|
11178
12448
|
}
|
|
@@ -15523,7 +16793,7 @@ async function refreshPluginRuntimeFromInstalls() {
|
|
|
15523
16793
|
const existingRoots = getSessionPlugins().map((p) => p.rootDir);
|
|
15524
16794
|
const dirs = Array.from(/* @__PURE__ */ new Set([...existingRoots, ...installedRoots]));
|
|
15525
16795
|
if (dirs.length === 0) return [];
|
|
15526
|
-
const { configureSessionPlugins } = await import("./pluginRuntime-
|
|
16796
|
+
const { configureSessionPlugins } = await import("./pluginRuntime-TJ55FZXH.js");
|
|
15527
16797
|
const { errors } = await configureSessionPlugins({ pluginDirs: dirs });
|
|
15528
16798
|
return errors;
|
|
15529
16799
|
}
|
|
@@ -16192,7 +17462,7 @@ async function call(onDone, context) {
|
|
|
16192
17462
|
ModelConfig,
|
|
16193
17463
|
{
|
|
16194
17464
|
onClose: () => {
|
|
16195
|
-
import("./model-
|
|
17465
|
+
import("./model-B5TCGITV.js").then(({ reloadModelManager: reloadModelManager2 }) => {
|
|
16196
17466
|
reloadModelManager2();
|
|
16197
17467
|
triggerModelConfigChange();
|
|
16198
17468
|
onDone();
|
|
@@ -16880,6 +18150,69 @@ var parallel_execute_default = {
|
|
|
16880
18150
|
}
|
|
16881
18151
|
};
|
|
16882
18152
|
|
|
18153
|
+
// src/commands/fix-harness.ts
|
|
18154
|
+
var fixHarnessCommand = {
|
|
18155
|
+
name: "fix-harness",
|
|
18156
|
+
description: "Update harness rules after an error pattern is found",
|
|
18157
|
+
isEnabled: true,
|
|
18158
|
+
isHidden: false,
|
|
18159
|
+
type: "prompt",
|
|
18160
|
+
progressMessage: "Analyzing error and updating harness rules...",
|
|
18161
|
+
argumentHint: "[error-description]",
|
|
18162
|
+
userFacingName() {
|
|
18163
|
+
return "fix-harness";
|
|
18164
|
+
},
|
|
18165
|
+
async getPromptForCommand(args) {
|
|
18166
|
+
return [
|
|
18167
|
+
{
|
|
18168
|
+
role: "user",
|
|
18169
|
+
content: [
|
|
18170
|
+
{
|
|
18171
|
+
type: "text",
|
|
18172
|
+
text: buildFixHarnessPrompt(args)
|
|
18173
|
+
}
|
|
18174
|
+
]
|
|
18175
|
+
}
|
|
18176
|
+
];
|
|
18177
|
+
}
|
|
18178
|
+
};
|
|
18179
|
+
function buildFixHarnessPrompt(errorDescription) {
|
|
18180
|
+
return `You are performing harness self-evolution. An error pattern was discovered during development.
|
|
18181
|
+
|
|
18182
|
+
Error description: ${errorDescription || "(Analyze recent errors in this session)"}
|
|
18183
|
+
|
|
18184
|
+
## Process
|
|
18185
|
+
|
|
18186
|
+
1. **Identify the error pattern**: What went wrong? What type of error is it?
|
|
18187
|
+
|
|
18188
|
+
2. **Route to correct rule file**:
|
|
18189
|
+
- Forbidden zone violation \u2192 .danya/rules/constitution.md
|
|
18190
|
+
- Coding principle violation \u2192 .danya/rules/golden-principles.md
|
|
18191
|
+
- Known pitfall re-occurrence \u2192 .danya/rules/known-pitfalls.md
|
|
18192
|
+
- Architecture boundary violation \u2192 .danya/rules/architecture-boundaries.md
|
|
18193
|
+
- Style issue \u2192 engine-specific style rule file
|
|
18194
|
+
|
|
18195
|
+
3. **Add a concise rule**:
|
|
18196
|
+
- \u274C What went wrong (with example)
|
|
18197
|
+
- \u2705 Correct approach (with example)
|
|
18198
|
+
|
|
18199
|
+
4. **Check constraints**:
|
|
18200
|
+
- Is this error pattern already captured in rules? If yes, skip.
|
|
18201
|
+
- Total rule file lines must stay under 550. If exceeded, consolidate.
|
|
18202
|
+
- If mechanically checkable, note it for /verify checks.
|
|
18203
|
+
|
|
18204
|
+
5. **Write the update**: Edit the appropriate rule file.
|
|
18205
|
+
|
|
18206
|
+
6. **Report**: State which file was updated and what rule was added.
|
|
18207
|
+
|
|
18208
|
+
## Important
|
|
18209
|
+
- Only add NEW patterns not already captured
|
|
18210
|
+
- Keep rules minimal: one error = one rule
|
|
18211
|
+
- Include correct-usage example, not just prohibition
|
|
18212
|
+
- Do NOT modify code files \u2014 only update .danya/rules/`;
|
|
18213
|
+
}
|
|
18214
|
+
var fix_harness_default = fixHarnessCommand;
|
|
18215
|
+
|
|
16883
18216
|
// src/commands/rename.ts
|
|
16884
18217
|
var rename = {
|
|
16885
18218
|
type: "local",
|
|
@@ -18523,7 +19856,7 @@ import * as React89 from "react";
|
|
|
18523
19856
|
// src/ui/components/permissions/file-edit-permission-request/FileEditPermissionRequest.tsx
|
|
18524
19857
|
import chalk7 from "chalk";
|
|
18525
19858
|
import { Box as Box55, Text as Text60, useInput as useInput19 } from "ink";
|
|
18526
|
-
import { basename as
|
|
19859
|
+
import { basename as basename5, dirname as dirname7, extname as extname8 } from "path";
|
|
18527
19860
|
import React74, { useCallback as useCallback8, useMemo as useMemo13 } from "react";
|
|
18528
19861
|
|
|
18529
19862
|
// src/ui/hooks/usePermissionRequestLogging.ts
|
|
@@ -18603,11 +19936,11 @@ function PermissionRequestTitle({
|
|
|
18603
19936
|
|
|
18604
19937
|
// src/ui/components/permissions/file-edit-permission-request/FileEditToolDiff.tsx
|
|
18605
19938
|
import * as React73 from "react";
|
|
18606
|
-
import { existsSync as
|
|
19939
|
+
import { existsSync as existsSync15, readFileSync as readFileSync10 } from "fs";
|
|
18607
19940
|
import { useMemo as useMemo12 } from "react";
|
|
18608
19941
|
import { Box as Box54, Text as Text59 } from "ink";
|
|
18609
19942
|
init_state();
|
|
18610
|
-
import { relative as
|
|
19943
|
+
import { relative as relative13 } from "path";
|
|
18611
19944
|
function FileEditToolDiff({
|
|
18612
19945
|
file_path,
|
|
18613
19946
|
new_string,
|
|
@@ -18617,7 +19950,7 @@ function FileEditToolDiff({
|
|
|
18617
19950
|
width
|
|
18618
19951
|
}) {
|
|
18619
19952
|
const file = useMemo12(
|
|
18620
|
-
() =>
|
|
19953
|
+
() => existsSync15(file_path) ? readFileSync10(file_path, "utf8") : "",
|
|
18621
19954
|
[file_path]
|
|
18622
19955
|
);
|
|
18623
19956
|
const patch = useMemo12(
|
|
@@ -18637,7 +19970,7 @@ function FileEditToolDiff({
|
|
|
18637
19970
|
flexDirection: "column",
|
|
18638
19971
|
paddingX: 1
|
|
18639
19972
|
},
|
|
18640
|
-
/* @__PURE__ */ React73.createElement(Box54, { paddingBottom: 1 }, /* @__PURE__ */ React73.createElement(Text59, { bold: true }, verbose ? file_path :
|
|
19973
|
+
/* @__PURE__ */ React73.createElement(Box54, { paddingBottom: 1 }, /* @__PURE__ */ React73.createElement(Text59, { bold: true }, verbose ? file_path : relative13(getCwd(), file_path))),
|
|
18641
19974
|
intersperse(
|
|
18642
19975
|
patch.map((_) => /* @__PURE__ */ React73.createElement(
|
|
18643
19976
|
StructuredDiff,
|
|
@@ -18694,8 +20027,8 @@ function getPermissionModeCycleShortcut() {
|
|
|
18694
20027
|
|
|
18695
20028
|
// src/ui/components/permissions/file-edit-permission-request/FileEditPermissionRequest.tsx
|
|
18696
20029
|
function getOptions(args) {
|
|
18697
|
-
const dirPath =
|
|
18698
|
-
const dirName =
|
|
20030
|
+
const dirPath = dirname7(args.path);
|
|
20031
|
+
const dirName = basename5(dirPath) || "this directory";
|
|
18699
20032
|
const options = [
|
|
18700
20033
|
{
|
|
18701
20034
|
label: "Yes",
|
|
@@ -18726,7 +20059,7 @@ function FileEditPermissionRequest({
|
|
|
18726
20059
|
const modeCycleShortcut = useMemo13(() => getPermissionModeCycleShortcut(), []);
|
|
18727
20060
|
const hasSessionSuggestion = (toolUseConfirm.suggestions?.length ?? 0) > 0;
|
|
18728
20061
|
const isInWorkingDir = isPathInWorkingDirectories(
|
|
18729
|
-
|
|
20062
|
+
dirname7(file_path),
|
|
18730
20063
|
toolPermissionContext
|
|
18731
20064
|
);
|
|
18732
20065
|
const unaryEvent = useMemo13(
|
|
@@ -18836,7 +20169,7 @@ function FileEditPermissionRequest({
|
|
|
18836
20169
|
width: columns - 12
|
|
18837
20170
|
}
|
|
18838
20171
|
),
|
|
18839
|
-
/* @__PURE__ */ React74.createElement(Box55, { flexDirection: "column" }, /* @__PURE__ */ React74.createElement(Text60, null, "Do you want to make this edit to", " ", /* @__PURE__ */ React74.createElement(Text60, { bold: true },
|
|
20172
|
+
/* @__PURE__ */ React74.createElement(Box55, { flexDirection: "column" }, /* @__PURE__ */ React74.createElement(Text60, null, "Do you want to make this edit to", " ", /* @__PURE__ */ React74.createElement(Text60, { bold: true }, basename5(file_path)), "?"), /* @__PURE__ */ React74.createElement(
|
|
18840
20173
|
Select,
|
|
18841
20174
|
{
|
|
18842
20175
|
options: getOptions({
|
|
@@ -18851,7 +20184,7 @@ function FileEditPermissionRequest({
|
|
|
18851
20184
|
);
|
|
18852
20185
|
}
|
|
18853
20186
|
async function extractLanguageName(file_path) {
|
|
18854
|
-
const ext =
|
|
20187
|
+
const ext = extname8(file_path);
|
|
18855
20188
|
if (!ext) {
|
|
18856
20189
|
return "unknown";
|
|
18857
20190
|
}
|
|
@@ -19217,31 +20550,31 @@ function useNotifyAfterTimeout(message, timeout = DEFAULT_INTERACTION_THRESHOLD_
|
|
|
19217
20550
|
// src/ui/components/permissions/file-write-permission-request/FileWritePermissionRequest.tsx
|
|
19218
20551
|
import { Box as Box59, Text as Text64, useInput as useInput20 } from "ink";
|
|
19219
20552
|
import React78, { useCallback as useCallback9, useMemo as useMemo17 } from "react";
|
|
19220
|
-
import { basename as
|
|
20553
|
+
import { basename as basename6, dirname as dirname8, extname as extname10 } from "path";
|
|
19221
20554
|
init_env();
|
|
19222
|
-
import { existsSync as
|
|
20555
|
+
import { existsSync as existsSync17 } from "fs";
|
|
19223
20556
|
import chalk10 from "chalk";
|
|
19224
20557
|
|
|
19225
20558
|
// src/ui/components/permissions/file-write-permission-request/FileWriteToolDiff.tsx
|
|
19226
20559
|
import * as React77 from "react";
|
|
19227
|
-
import { existsSync as
|
|
20560
|
+
import { existsSync as existsSync16, readFileSync as readFileSync11 } from "fs";
|
|
19228
20561
|
import { useMemo as useMemo16 } from "react";
|
|
19229
20562
|
import { Box as Box58, Text as Text63 } from "ink";
|
|
19230
20563
|
init_state();
|
|
19231
|
-
import { extname as
|
|
20564
|
+
import { extname as extname9, relative as relative14 } from "path";
|
|
19232
20565
|
function FileWriteToolDiff({
|
|
19233
20566
|
file_path,
|
|
19234
20567
|
content,
|
|
19235
20568
|
verbose,
|
|
19236
20569
|
width
|
|
19237
20570
|
}) {
|
|
19238
|
-
const fileExists = useMemo16(() =>
|
|
20571
|
+
const fileExists = useMemo16(() => existsSync16(file_path), [file_path]);
|
|
19239
20572
|
const oldContent = useMemo16(() => {
|
|
19240
20573
|
if (!fileExists) {
|
|
19241
20574
|
return "";
|
|
19242
20575
|
}
|
|
19243
20576
|
const enc = detectFileEncoding(file_path);
|
|
19244
|
-
return
|
|
20577
|
+
return readFileSync11(file_path, enc);
|
|
19245
20578
|
}, [file_path, fileExists]);
|
|
19246
20579
|
const hunks = useMemo16(() => {
|
|
19247
20580
|
if (!fileExists) {
|
|
@@ -19262,7 +20595,7 @@ function FileWriteToolDiff({
|
|
|
19262
20595
|
flexDirection: "column",
|
|
19263
20596
|
paddingX: 1
|
|
19264
20597
|
},
|
|
19265
|
-
/* @__PURE__ */ React77.createElement(Box58, { paddingBottom: 1 }, /* @__PURE__ */ React77.createElement(Text63, { bold: true }, verbose ? file_path :
|
|
20598
|
+
/* @__PURE__ */ React77.createElement(Box58, { paddingBottom: 1 }, /* @__PURE__ */ React77.createElement(Text63, { bold: true }, verbose ? file_path : relative14(getCwd(), file_path))),
|
|
19266
20599
|
hunks ? intersperse(
|
|
19267
20600
|
hunks.map((_) => /* @__PURE__ */ React77.createElement(
|
|
19268
20601
|
StructuredDiff,
|
|
@@ -19278,7 +20611,7 @@ function FileWriteToolDiff({
|
|
|
19278
20611
|
HighlightedCode,
|
|
19279
20612
|
{
|
|
19280
20613
|
code: content || "(No content)",
|
|
19281
|
-
language:
|
|
20614
|
+
language: extname9(file_path).slice(1)
|
|
19282
20615
|
}
|
|
19283
20616
|
)
|
|
19284
20617
|
);
|
|
@@ -19295,18 +20628,18 @@ function FileWritePermissionRequest({
|
|
|
19295
20628
|
const modeCycleShortcut = useMemo17(() => getPermissionModeCycleShortcut(), []);
|
|
19296
20629
|
const hasSessionSuggestion = (toolUseConfirm.suggestions?.length ?? 0) > 0;
|
|
19297
20630
|
const isInWorkingDir = isPathInWorkingDirectories(
|
|
19298
|
-
|
|
20631
|
+
dirname8(file_path),
|
|
19299
20632
|
toolPermissionContext
|
|
19300
20633
|
);
|
|
19301
20634
|
const sessionLabel = useMemo17(() => {
|
|
19302
|
-
const dirPath =
|
|
19303
|
-
const dirName =
|
|
20635
|
+
const dirPath = dirname8(file_path);
|
|
20636
|
+
const dirName = basename6(dirPath) || "this directory";
|
|
19304
20637
|
const shortcutHint = chalk10.bold.hex(getTheme().warning)(
|
|
19305
20638
|
`(${modeCycleShortcut.displayText})`
|
|
19306
20639
|
);
|
|
19307
20640
|
return isInWorkingDir ? `Yes, allow all edits during this session ${shortcutHint}` : `Yes, allow all edits in ${chalk10.bold(`${dirName}/`)} during this session ${shortcutHint}`;
|
|
19308
20641
|
}, [file_path, isInWorkingDir, modeCycleShortcut.displayText]);
|
|
19309
|
-
const fileExists = useMemo17(() =>
|
|
20642
|
+
const fileExists = useMemo17(() => existsSync17(file_path), [file_path]);
|
|
19310
20643
|
const unaryEvent = useMemo17(
|
|
19311
20644
|
() => ({
|
|
19312
20645
|
completion_type: "write_file_single",
|
|
@@ -19414,7 +20747,7 @@ function FileWritePermissionRequest({
|
|
|
19414
20747
|
width: columns - 12
|
|
19415
20748
|
}
|
|
19416
20749
|
)),
|
|
19417
|
-
/* @__PURE__ */ React78.createElement(Box59, { flexDirection: "column" }, /* @__PURE__ */ React78.createElement(Text64, null, "Do you want to ", fileExists ? "make this edit to" : "create", " ", /* @__PURE__ */ React78.createElement(Text64, { bold: true },
|
|
20750
|
+
/* @__PURE__ */ React78.createElement(Box59, { flexDirection: "column" }, /* @__PURE__ */ React78.createElement(Text64, null, "Do you want to ", fileExists ? "make this edit to" : "create", " ", /* @__PURE__ */ React78.createElement(Text64, { bold: true }, basename6(file_path)), "?"), /* @__PURE__ */ React78.createElement(
|
|
19418
20751
|
Select,
|
|
19419
20752
|
{
|
|
19420
20753
|
options: [
|
|
@@ -19439,7 +20772,7 @@ function FileWritePermissionRequest({
|
|
|
19439
20772
|
);
|
|
19440
20773
|
}
|
|
19441
20774
|
async function extractLanguageName2(file_path) {
|
|
19442
|
-
const ext =
|
|
20775
|
+
const ext = extname10(file_path);
|
|
19443
20776
|
if (!ext) {
|
|
19444
20777
|
return "unknown";
|
|
19445
20778
|
}
|
|
@@ -19453,8 +20786,8 @@ import React79, { useCallback as useCallback10, useMemo as useMemo18 } from "rea
|
|
|
19453
20786
|
init_env();
|
|
19454
20787
|
import chalk11 from "chalk";
|
|
19455
20788
|
init_state();
|
|
19456
|
-
import { basename as
|
|
19457
|
-
import { statSync as
|
|
20789
|
+
import { basename as basename7, dirname as dirname9 } from "path";
|
|
20790
|
+
import { statSync as statSync13 } from "fs";
|
|
19458
20791
|
function pathArgNameForToolUse(toolUseConfirm) {
|
|
19459
20792
|
switch (toolUseConfirm.tool) {
|
|
19460
20793
|
case FileWriteTool:
|
|
@@ -19483,11 +20816,11 @@ function isMultiFile(toolUseConfirm) {
|
|
|
19483
20816
|
}
|
|
19484
20817
|
function pathToPermissionDirectory2(path5) {
|
|
19485
20818
|
try {
|
|
19486
|
-
const stats =
|
|
20819
|
+
const stats = statSync13(path5);
|
|
19487
20820
|
if (stats.isDirectory()) return path5;
|
|
19488
20821
|
} catch {
|
|
19489
20822
|
}
|
|
19490
|
-
return
|
|
20823
|
+
return dirname9(path5);
|
|
19491
20824
|
}
|
|
19492
20825
|
function pathFromToolUse(toolUseConfirm) {
|
|
19493
20826
|
const pathArgName = pathArgNameForToolUse(toolUseConfirm);
|
|
@@ -19530,7 +20863,7 @@ function FilesystemPermissionRequest({
|
|
|
19530
20863
|
function getDontAskAgainOptions(toolUseConfirm, path5, modeCycleShortcut, isInWorkingDir, hasSessionSuggestion) {
|
|
19531
20864
|
if (!hasSessionSuggestion) return [];
|
|
19532
20865
|
const permissionDirPath = pathToPermissionDirectory2(path5);
|
|
19533
|
-
const permissionDirName =
|
|
20866
|
+
const permissionDirName = basename7(permissionDirPath) || "this directory";
|
|
19534
20867
|
if (toolUseConfirm.tool.isReadOnly(toolUseConfirm.input)) {
|
|
19535
20868
|
const label2 = isInWorkingDir ? "Yes, during this session" : `Yes, allow reading from ${chalk11.bold(`${permissionDirName}/`)} during this session`;
|
|
19536
20869
|
return [{ label: label2, value: "yes-session" }];
|
|
@@ -20565,9 +21898,9 @@ init_planMode();
|
|
|
20565
21898
|
|
|
20566
21899
|
// src/utils/system/externalEditor.ts
|
|
20567
21900
|
import { spawn, spawnSync } from "child_process";
|
|
20568
|
-
import { mkdtempSync, readFileSync as
|
|
21901
|
+
import { mkdtempSync, readFileSync as readFileSync12, rmSync, writeFileSync as writeFileSync7 } from "fs";
|
|
20569
21902
|
import { tmpdir } from "os";
|
|
20570
|
-
import { join as
|
|
21903
|
+
import { join as join13 } from "path";
|
|
20571
21904
|
var isWindows = process.platform === "win32";
|
|
20572
21905
|
function isCommandAvailable(command4) {
|
|
20573
21906
|
const checker = isWindows ? "where" : "which";
|
|
@@ -20643,9 +21976,9 @@ async function launchExternalEditor(initialText) {
|
|
|
20643
21976
|
)
|
|
20644
21977
|
};
|
|
20645
21978
|
}
|
|
20646
|
-
const dir = mkdtempSync(
|
|
20647
|
-
const filePath =
|
|
20648
|
-
|
|
21979
|
+
const dir = mkdtempSync(join13(tmpdir(), "kode-edit-"));
|
|
21980
|
+
const filePath = join13(dir, "message.txt");
|
|
21981
|
+
writeFileSync7(filePath, initialText, "utf-8");
|
|
20649
21982
|
const wasRaw = Boolean(process.stdin.isTTY && process.stdin.isRaw);
|
|
20650
21983
|
if (process.stdin.isTTY) {
|
|
20651
21984
|
process.stdin.pause();
|
|
@@ -20687,7 +22020,7 @@ async function launchExternalEditor(initialText) {
|
|
|
20687
22020
|
}
|
|
20688
22021
|
restoreStdinState(wasRaw);
|
|
20689
22022
|
try {
|
|
20690
|
-
const edited = normalizeNewlines(
|
|
22023
|
+
const edited = normalizeNewlines(readFileSync12(filePath, "utf-8"));
|
|
20691
22024
|
rmSync(dir, { recursive: true, force: true });
|
|
20692
22025
|
return { text: edited, editorLabel: editorCommand.displayName };
|
|
20693
22026
|
} catch (error) {
|
|
@@ -20752,7 +22085,7 @@ async function launchExternalEditorForFilePath(filePath) {
|
|
|
20752
22085
|
}
|
|
20753
22086
|
|
|
20754
22087
|
// src/ui/components/permissions/plan-mode-permission-request/ExitPlanModePermissionRequest.tsx
|
|
20755
|
-
import { writeFileSync as
|
|
22088
|
+
import { writeFileSync as writeFileSync8 } from "fs";
|
|
20756
22089
|
function getExitPlanModeOptions(args) {
|
|
20757
22090
|
const options = [];
|
|
20758
22091
|
options.push(
|
|
@@ -20838,7 +22171,7 @@ function ExitPlanModePermissionRequest({
|
|
|
20838
22171
|
if (!planExists) {
|
|
20839
22172
|
const initial = planText === planPlaceholder() ? "# Plan\n" : planText;
|
|
20840
22173
|
try {
|
|
20841
|
-
|
|
22174
|
+
writeFileSync8(planFilePath, initial, "utf-8");
|
|
20842
22175
|
} catch {
|
|
20843
22176
|
const edited = await launchExternalEditor(initial);
|
|
20844
22177
|
if (edited.text !== null) {
|
|
@@ -21708,8 +23041,8 @@ function getCompletionContext(args) {
|
|
|
21708
23041
|
}
|
|
21709
23042
|
|
|
21710
23043
|
// src/utils/completion/fileSuggestions.ts
|
|
21711
|
-
import { existsSync as
|
|
21712
|
-
import { basename as
|
|
23044
|
+
import { existsSync as existsSync18, readdirSync as readdirSync6, statSync as statSync14 } from "fs";
|
|
23045
|
+
import { basename as basename8, dirname as dirname10, join as join14, resolve as resolve9 } from "path";
|
|
21713
23046
|
function generateFileSuggestions(args) {
|
|
21714
23047
|
const { prefix, cwd: cwd2 } = args;
|
|
21715
23048
|
try {
|
|
@@ -21725,35 +23058,35 @@ function generateFileSuggestions(args) {
|
|
|
21725
23058
|
searchPath = resolve9(cwd2, userPath);
|
|
21726
23059
|
}
|
|
21727
23060
|
const endsWithSlash = userPath.endsWith("/");
|
|
21728
|
-
const searchStat =
|
|
23061
|
+
const searchStat = existsSync18(searchPath) ? statSync14(searchPath) : null;
|
|
21729
23062
|
let searchDir;
|
|
21730
23063
|
let nameFilter;
|
|
21731
23064
|
if (endsWithSlash || searchStat?.isDirectory()) {
|
|
21732
23065
|
searchDir = searchPath;
|
|
21733
23066
|
nameFilter = "";
|
|
21734
23067
|
} else {
|
|
21735
|
-
searchDir =
|
|
21736
|
-
nameFilter =
|
|
23068
|
+
searchDir = dirname10(searchPath);
|
|
23069
|
+
nameFilter = basename8(searchPath);
|
|
21737
23070
|
}
|
|
21738
|
-
if (!
|
|
23071
|
+
if (!existsSync18(searchDir)) return [];
|
|
21739
23072
|
const showHidden = nameFilter.startsWith(".") || userPath.includes("/.");
|
|
21740
|
-
const entries =
|
|
23073
|
+
const entries = readdirSync6(searchDir).filter((entry) => {
|
|
21741
23074
|
if (!showHidden && entry.startsWith(".")) return false;
|
|
21742
23075
|
if (nameFilter && !entry.toLowerCase().startsWith(nameFilter.toLowerCase()))
|
|
21743
23076
|
return false;
|
|
21744
23077
|
return true;
|
|
21745
23078
|
}).sort((a, b) => {
|
|
21746
|
-
const aPath =
|
|
21747
|
-
const bPath =
|
|
21748
|
-
const aIsDir =
|
|
21749
|
-
const bIsDir =
|
|
23079
|
+
const aPath = join14(searchDir, a);
|
|
23080
|
+
const bPath = join14(searchDir, b);
|
|
23081
|
+
const aIsDir = statSync14(aPath).isDirectory();
|
|
23082
|
+
const bIsDir = statSync14(bPath).isDirectory();
|
|
21750
23083
|
if (aIsDir && !bIsDir) return -1;
|
|
21751
23084
|
if (!aIsDir && bIsDir) return 1;
|
|
21752
23085
|
return a.toLowerCase().localeCompare(b.toLowerCase());
|
|
21753
23086
|
}).slice(0, 25);
|
|
21754
23087
|
return entries.map((entry) => {
|
|
21755
|
-
const entryPath =
|
|
21756
|
-
const isDir =
|
|
23088
|
+
const entryPath = join14(searchDir, entry);
|
|
23089
|
+
const isDir = statSync14(entryPath).isDirectory();
|
|
21757
23090
|
const icon = isDir ? "\u{1F4C1}" : "\u{1F4C4}";
|
|
21758
23091
|
let value;
|
|
21759
23092
|
if (userPath.includes("/")) {
|
|
@@ -23086,19 +24419,19 @@ function useUnifiedCompletion({
|
|
|
23086
24419
|
if (systemCommands.length > 0 || isLoadingCommands) return;
|
|
23087
24420
|
setIsLoadingCommands(true);
|
|
23088
24421
|
try {
|
|
23089
|
-
const { readdirSync:
|
|
24422
|
+
const { readdirSync: readdirSync7, statSync: statSync16 } = await import("fs");
|
|
23090
24423
|
const pathDirs = (process.env.PATH || "").split(":").filter(Boolean);
|
|
23091
24424
|
const commandSet = /* @__PURE__ */ new Set();
|
|
23092
24425
|
const essentialCommands = getEssentialCommands();
|
|
23093
24426
|
essentialCommands.forEach((cmd) => commandSet.add(cmd));
|
|
23094
24427
|
for (const dir of pathDirs) {
|
|
23095
24428
|
try {
|
|
23096
|
-
if (
|
|
23097
|
-
const entries =
|
|
24429
|
+
if (readdirSync7 && statSync16) {
|
|
24430
|
+
const entries = readdirSync7(dir);
|
|
23098
24431
|
for (const entry of entries) {
|
|
23099
24432
|
try {
|
|
23100
24433
|
const fullPath = `${dir}/${entry}`;
|
|
23101
|
-
const stats =
|
|
24434
|
+
const stats = statSync16(fullPath);
|
|
23102
24435
|
if (stats.isFile() && (stats.mode & 73) !== 0) {
|
|
23103
24436
|
commandSet.add(entry);
|
|
23104
24437
|
}
|
|
@@ -23632,17 +24965,17 @@ function TokenWarning({ tokenUsage }) {
|
|
|
23632
24965
|
|
|
23633
24966
|
// src/utils/commands/hashCommand.ts
|
|
23634
24967
|
init_log();
|
|
23635
|
-
import { join as
|
|
23636
|
-
import { readFileSync as
|
|
24968
|
+
import { join as join15 } from "path";
|
|
24969
|
+
import { readFileSync as readFileSync13, writeFileSync as writeFileSync9 } from "fs";
|
|
23637
24970
|
function handleHashCommand(interpreted) {
|
|
23638
24971
|
try {
|
|
23639
24972
|
const cwd2 = process.cwd();
|
|
23640
|
-
const agentsPath =
|
|
23641
|
-
const legacyPath =
|
|
24973
|
+
const agentsPath = join15(cwd2, "AGENTS.md");
|
|
24974
|
+
const legacyPath = join15(cwd2, "CLAUDE.md");
|
|
23642
24975
|
const filesToUpdate = [];
|
|
23643
24976
|
filesToUpdate.push({ path: agentsPath, name: "AGENTS.md" });
|
|
23644
24977
|
try {
|
|
23645
|
-
|
|
24978
|
+
readFileSync13(legacyPath, "utf-8");
|
|
23646
24979
|
filesToUpdate.push({ path: legacyPath, name: "CLAUDE.md" });
|
|
23647
24980
|
} catch {
|
|
23648
24981
|
}
|
|
@@ -23657,12 +24990,12 @@ _Added on ${now.toLocaleString()} ${timezone}_`;
|
|
|
23657
24990
|
try {
|
|
23658
24991
|
let existingContent = "";
|
|
23659
24992
|
try {
|
|
23660
|
-
existingContent =
|
|
24993
|
+
existingContent = readFileSync13(file.path, "utf-8").trim();
|
|
23661
24994
|
} catch {
|
|
23662
24995
|
}
|
|
23663
24996
|
const separator = existingContent ? "\n\n" : "";
|
|
23664
24997
|
const newContent = `${existingContent}${separator}${interpreted}${timestamp}`;
|
|
23665
|
-
|
|
24998
|
+
writeFileSync9(file.path, newContent, "utf-8");
|
|
23666
24999
|
updatedFiles.push(file.name);
|
|
23667
25000
|
} catch (error) {
|
|
23668
25001
|
logError(error);
|
|
@@ -23862,7 +25195,7 @@ function useStatusLine() {
|
|
|
23862
25195
|
// src/ui/components/PromptInput.tsx
|
|
23863
25196
|
async function interpretHashCommand(input) {
|
|
23864
25197
|
try {
|
|
23865
|
-
const { queryQuick: queryQuick2 } = await import("./llm-
|
|
25198
|
+
const { queryQuick: queryQuick2 } = await import("./llm-XBH33BXT.js");
|
|
23866
25199
|
const systemPrompt = [
|
|
23867
25200
|
"You're helping the user structure notes that will be added to their KODING.md file.",
|
|
23868
25201
|
"Format the user's input into a well-structured note that will be useful for later reference.",
|
|
@@ -24175,7 +25508,7 @@ function PromptInput({
|
|
|
24175
25508
|
if (messages2.length) {
|
|
24176
25509
|
if (mode === "bash") {
|
|
24177
25510
|
onQuery(messages2, newAbortController).then(async () => {
|
|
24178
|
-
const { getCwd: getCwd2 } = await import("./state-
|
|
25511
|
+
const { getCwd: getCwd2 } = await import("./state-4L5XK2VN.js");
|
|
24179
25512
|
setCurrentPwd(getCwd2());
|
|
24180
25513
|
});
|
|
24181
25514
|
} else {
|
|
@@ -24894,35 +26227,121 @@ async function selectAndReadFiles() {
|
|
|
24894
26227
|
|
|
24895
26228
|
// src/utils/session/autoCompactCore.ts
|
|
24896
26229
|
init_log();
|
|
24897
|
-
|
|
24898
|
-
|
|
24899
|
-
|
|
24900
|
-
|
|
24901
|
-
|
|
24902
|
-
|
|
24903
|
-
|
|
26230
|
+
|
|
26231
|
+
// src/services/compact/compact.ts
|
|
26232
|
+
var DEFAULT_COMPACTION_CONFIG = {
|
|
26233
|
+
triggerThresholdPercent: 90,
|
|
26234
|
+
targetPercent: 60,
|
|
26235
|
+
preserveRecentMessages: 4,
|
|
26236
|
+
enabled: true
|
|
26237
|
+
};
|
|
26238
|
+
function groupMessages(messages, preserveCount) {
|
|
26239
|
+
const groups = [];
|
|
26240
|
+
const preserveStartIdx = Math.max(0, messages.length - preserveCount);
|
|
26241
|
+
let currentGroup = null;
|
|
26242
|
+
for (let i = 0; i < messages.length; i++) {
|
|
26243
|
+
const msg = messages[i];
|
|
26244
|
+
const isPreserved = i >= preserveStartIdx;
|
|
26245
|
+
if (isPreserved) {
|
|
26246
|
+
if (currentGroup) {
|
|
26247
|
+
groups.push(currentGroup);
|
|
26248
|
+
currentGroup = null;
|
|
26249
|
+
}
|
|
26250
|
+
groups.push({
|
|
26251
|
+
type: "preserved",
|
|
26252
|
+
messages: [msg],
|
|
26253
|
+
totalTokens: msg.tokens
|
|
26254
|
+
});
|
|
26255
|
+
continue;
|
|
26256
|
+
}
|
|
26257
|
+
if (msg.type === "tool_result") {
|
|
26258
|
+
if (currentGroup?.type === "tool_use") {
|
|
26259
|
+
currentGroup.messages.push(msg);
|
|
26260
|
+
currentGroup.totalTokens += msg.tokens;
|
|
26261
|
+
} else {
|
|
26262
|
+
if (currentGroup) groups.push(currentGroup);
|
|
26263
|
+
currentGroup = {
|
|
26264
|
+
type: "tool_use",
|
|
26265
|
+
messages: [msg],
|
|
26266
|
+
totalTokens: msg.tokens
|
|
26267
|
+
};
|
|
26268
|
+
}
|
|
26269
|
+
} else if (msg.type === "system") {
|
|
26270
|
+
if (currentGroup) groups.push(currentGroup);
|
|
26271
|
+
groups.push({
|
|
26272
|
+
type: "system",
|
|
26273
|
+
messages: [msg],
|
|
26274
|
+
totalTokens: msg.tokens
|
|
26275
|
+
});
|
|
26276
|
+
currentGroup = null;
|
|
26277
|
+
} else {
|
|
26278
|
+
if (currentGroup?.type === "conversation") {
|
|
26279
|
+
currentGroup.messages.push(msg);
|
|
26280
|
+
currentGroup.totalTokens += msg.tokens;
|
|
26281
|
+
} else {
|
|
26282
|
+
if (currentGroup) groups.push(currentGroup);
|
|
26283
|
+
currentGroup = {
|
|
26284
|
+
type: msg.type === "assistant" ? "tool_use" : "conversation",
|
|
26285
|
+
messages: [msg],
|
|
26286
|
+
totalTokens: msg.tokens
|
|
26287
|
+
};
|
|
26288
|
+
}
|
|
26289
|
+
}
|
|
26290
|
+
}
|
|
26291
|
+
if (currentGroup) groups.push(currentGroup);
|
|
26292
|
+
return groups;
|
|
26293
|
+
}
|
|
26294
|
+
function calculateCompactionTarget(currentTokens, contextWindowSize, config2 = DEFAULT_COMPACTION_CONFIG) {
|
|
26295
|
+
const targetTokens = Math.floor(contextWindowSize * (config2.targetPercent / 100));
|
|
26296
|
+
return Math.max(0, currentTokens - targetTokens);
|
|
26297
|
+
}
|
|
26298
|
+
function selectGroupsForCompaction(groups, tokensToFree) {
|
|
26299
|
+
const toCompact = [];
|
|
26300
|
+
const toKeep = [];
|
|
26301
|
+
let freed = 0;
|
|
26302
|
+
for (const group of groups) {
|
|
26303
|
+
if (group.type === "preserved") {
|
|
26304
|
+
toKeep.push(group);
|
|
26305
|
+
continue;
|
|
26306
|
+
}
|
|
26307
|
+
if (freed < tokensToFree) {
|
|
26308
|
+
toCompact.push(group);
|
|
26309
|
+
freed += group.totalTokens;
|
|
26310
|
+
} else {
|
|
26311
|
+
toKeep.push(group);
|
|
24904
26312
|
}
|
|
24905
|
-
return 2e5;
|
|
24906
|
-
} catch (error) {
|
|
24907
|
-
return 2e5;
|
|
24908
26313
|
}
|
|
26314
|
+
return { toCompact, toKeep };
|
|
26315
|
+
}
|
|
26316
|
+
function buildCompactionPrompt(groups) {
|
|
26317
|
+
const lines = [];
|
|
26318
|
+
for (const group of groups) {
|
|
26319
|
+
for (const msg of group.messages) {
|
|
26320
|
+
const prefix = msg.type === "user" ? "User" : msg.type === "assistant" ? "Assistant" : "System";
|
|
26321
|
+
const content = msg.content.length > 2e3 ? msg.content.slice(0, 2e3) + "... (truncated)" : msg.content;
|
|
26322
|
+
lines.push(`[${prefix}]: ${content}`);
|
|
26323
|
+
}
|
|
26324
|
+
}
|
|
26325
|
+
return lines.join("\n\n");
|
|
24909
26326
|
}
|
|
24910
|
-
|
|
26327
|
+
|
|
26328
|
+
// src/utils/session/autoCompactCore.ts
|
|
26329
|
+
var COMPRESSION_PROMPT2 = `Please provide a comprehensive summary of the following conversation history, structured as follows:
|
|
24911
26330
|
|
|
24912
26331
|
## Technical Context
|
|
24913
26332
|
Development environment, tools, frameworks, and configurations in use. Programming languages, libraries, and technical constraints. File structure, directory organization, and project architecture.
|
|
24914
26333
|
|
|
24915
|
-
## Project Overview
|
|
26334
|
+
## Project Overview
|
|
24916
26335
|
Main project goals, features, and scope. Key components, modules, and their relationships. Data models, APIs, and integration patterns.
|
|
24917
26336
|
|
|
24918
26337
|
## Code Changes
|
|
24919
|
-
Files created, modified, or analyzed during
|
|
26338
|
+
Files created, modified, or analyzed during the conversation. Specific code implementations, functions, and algorithms added. Configuration changes and structural modifications.
|
|
24920
26339
|
|
|
24921
26340
|
## Debugging & Issues
|
|
24922
26341
|
Problems encountered and their root causes. Solutions implemented and their effectiveness. Error messages, logs, and diagnostic information.
|
|
24923
26342
|
|
|
24924
26343
|
## Current Status
|
|
24925
|
-
What
|
|
26344
|
+
What was most recently completed. Current state of the codebase and any ongoing work. Test results, validation steps, and verification performed.
|
|
24926
26345
|
|
|
24927
26346
|
## Pending Tasks
|
|
24928
26347
|
Immediate next steps and priorities. Planned features, improvements, and refactoring. Known issues, technical debt, and areas needing attention.
|
|
@@ -24934,14 +26353,22 @@ Coding style, formatting, and organizational preferences. Communication patterns
|
|
|
24934
26353
|
Important technical decisions made and their rationale. Alternative approaches considered and why they were rejected. Trade-offs accepted and their implications.
|
|
24935
26354
|
|
|
24936
26355
|
Focus on information essential for continuing the conversation effectively, including specific details about code, files, errors, and plans.`;
|
|
24937
|
-
async function
|
|
24938
|
-
|
|
24939
|
-
|
|
26356
|
+
async function getMainConversationContextLimit() {
|
|
26357
|
+
try {
|
|
26358
|
+
const modelManager = getModelManager();
|
|
26359
|
+
const resolution = modelManager.resolveModelWithInfo("main");
|
|
26360
|
+
const modelProfile = resolution.success ? resolution.profile : null;
|
|
26361
|
+
if (modelProfile?.contextLength) return modelProfile.contextLength;
|
|
26362
|
+
return 2e5;
|
|
26363
|
+
} catch {
|
|
26364
|
+
return 2e5;
|
|
26365
|
+
}
|
|
24940
26366
|
}
|
|
24941
26367
|
async function shouldAutoCompact(messages) {
|
|
24942
26368
|
if (messages.length < 3) return false;
|
|
24943
26369
|
const tokenCount = countTokens(messages);
|
|
24944
|
-
const
|
|
26370
|
+
const contextLimit = await getMainConversationContextLimit();
|
|
26371
|
+
const { isAboveAutoCompactThreshold } = calculateAutoCompactThresholds(tokenCount, contextLimit);
|
|
24945
26372
|
return isAboveAutoCompactThreshold;
|
|
24946
26373
|
}
|
|
24947
26374
|
async function checkAutoCompact(messages, toolUseContext) {
|
|
@@ -24950,10 +26377,7 @@ async function checkAutoCompact(messages, toolUseContext) {
|
|
|
24950
26377
|
}
|
|
24951
26378
|
try {
|
|
24952
26379
|
const compactedMessages = await executeAutoCompact(messages, toolUseContext);
|
|
24953
|
-
return {
|
|
24954
|
-
messages: compactedMessages,
|
|
24955
|
-
wasCompacted: true
|
|
24956
|
-
};
|
|
26380
|
+
return { messages: compactedMessages, wasCompacted: true };
|
|
24957
26381
|
} catch (error) {
|
|
24958
26382
|
logError(error);
|
|
24959
26383
|
debug.warn("AUTO_COMPACT_FAILED", {
|
|
@@ -24963,30 +26387,53 @@ async function checkAutoCompact(messages, toolUseContext) {
|
|
|
24963
26387
|
}
|
|
24964
26388
|
}
|
|
24965
26389
|
async function executeAutoCompact(messages, toolUseContext) {
|
|
24966
|
-
const summaryRequest = createUserMessage(COMPRESSION_PROMPT2);
|
|
24967
26390
|
const tokenCount = countTokens(messages);
|
|
24968
|
-
const
|
|
24969
|
-
const
|
|
24970
|
-
const
|
|
24971
|
-
|
|
24972
|
-
|
|
24973
|
-
if (
|
|
24974
|
-
|
|
24975
|
-
compressionNotice = compactResolution.error || "Compression model pointer 'compact' is not configured.";
|
|
24976
|
-
} else {
|
|
24977
|
-
const compactBudget = Math.floor(
|
|
24978
|
-
compactResolution.profile.contextLength * 0.9
|
|
24979
|
-
);
|
|
24980
|
-
if (compactBudget > 0 && tokenCount > compactBudget) {
|
|
24981
|
-
compressionModelPointer = "main";
|
|
24982
|
-
compressionNotice = `Compression model '${compactResolution.profile.name}' does not fit current context (~${Math.round(tokenCount / 1e3)}k tokens).`;
|
|
24983
|
-
}
|
|
26391
|
+
const contextLimit = await getMainConversationContextLimit();
|
|
26392
|
+
const compactableMessages = messagesToCompactable(messages);
|
|
26393
|
+
const groups = groupMessages(compactableMessages, DEFAULT_COMPACTION_CONFIG.preserveRecentMessages);
|
|
26394
|
+
const tokensToFree = calculateCompactionTarget(tokenCount, contextLimit);
|
|
26395
|
+
const { toCompact, toKeep } = selectGroupsForCompaction(groups, tokensToFree);
|
|
26396
|
+
if (toCompact.length === 0) {
|
|
26397
|
+
return executeFullCompact(messages, toolUseContext, tokenCount);
|
|
24984
26398
|
}
|
|
24985
|
-
|
|
24986
|
-
|
|
24987
|
-
|
|
24988
|
-
|
|
26399
|
+
const conversationToSummarize = buildCompactionPrompt(toCompact);
|
|
26400
|
+
const { modelPointer, notice } = resolveCompressionModel(tokenCount);
|
|
26401
|
+
const summaryPrompt = `${COMPRESSION_PROMPT2}
|
|
26402
|
+
|
|
26403
|
+
---
|
|
26404
|
+
|
|
26405
|
+
Conversation to summarize:
|
|
26406
|
+
|
|
26407
|
+
${conversationToSummarize}`;
|
|
26408
|
+
const summaryRequest = createUserMessage(summaryPrompt);
|
|
26409
|
+
const summaryResponse = await queryLLM(
|
|
26410
|
+
normalizeMessagesForAPI([summaryRequest]),
|
|
26411
|
+
[
|
|
26412
|
+
"You are a helpful AI assistant tasked with creating comprehensive conversation summaries that preserve all essential context for continuing development work."
|
|
26413
|
+
],
|
|
26414
|
+
0,
|
|
26415
|
+
[],
|
|
26416
|
+
toolUseContext.abortController.signal,
|
|
26417
|
+
{
|
|
26418
|
+
safeMode: false,
|
|
26419
|
+
model: modelPointer,
|
|
26420
|
+
prependCLISysprompt: true
|
|
26421
|
+
}
|
|
26422
|
+
);
|
|
26423
|
+
const noticeText = notice ? `Context selectively compressed (${toCompact.length} groups summarized, ${toKeep.length} preserved). ${notice}` : `Context selectively compressed (${toCompact.length} groups summarized, ${toKeep.length} preserved).`;
|
|
26424
|
+
const result = await finalizeSummary(summaryResponse, noticeText);
|
|
26425
|
+
for (const group of toKeep) {
|
|
26426
|
+
for (const msg of group.messages) {
|
|
26427
|
+
if (msg.original) {
|
|
26428
|
+
result.push(msg.original);
|
|
26429
|
+
}
|
|
26430
|
+
}
|
|
24989
26431
|
}
|
|
26432
|
+
return result;
|
|
26433
|
+
}
|
|
26434
|
+
async function executeFullCompact(messages, toolUseContext, tokenCount) {
|
|
26435
|
+
const { modelPointer, notice } = resolveCompressionModel(tokenCount);
|
|
26436
|
+
const summaryRequest = createUserMessage(COMPRESSION_PROMPT2);
|
|
24990
26437
|
const summaryResponse = await queryLLM(
|
|
24991
26438
|
normalizeMessagesForAPI([...messages, summaryRequest]),
|
|
24992
26439
|
[
|
|
@@ -24997,16 +26444,17 @@ async function executeAutoCompact(messages, toolUseContext) {
|
|
|
24997
26444
|
toolUseContext.abortController.signal,
|
|
24998
26445
|
{
|
|
24999
26446
|
safeMode: false,
|
|
25000
|
-
model:
|
|
26447
|
+
model: modelPointer,
|
|
25001
26448
|
prependCLISysprompt: true
|
|
25002
26449
|
}
|
|
25003
26450
|
);
|
|
25004
|
-
const
|
|
25005
|
-
|
|
26451
|
+
const noticeText = notice ? `Context fully compressed due to token limit. ${notice}` : `Context fully compressed due to token limit.`;
|
|
26452
|
+
return finalizeSummary(summaryResponse, noticeText);
|
|
26453
|
+
}
|
|
26454
|
+
async function finalizeSummary(summaryResponse, noticeText) {
|
|
26455
|
+
const summary = extractSummaryText(summaryResponse);
|
|
25006
26456
|
if (!summary) {
|
|
25007
|
-
throw new Error(
|
|
25008
|
-
"Failed to generate conversation summary - response did not contain valid text content"
|
|
25009
|
-
);
|
|
26457
|
+
throw new Error("Failed to generate conversation summary");
|
|
25010
26458
|
}
|
|
25011
26459
|
summaryResponse.message.usage = {
|
|
25012
26460
|
input_tokens: 0,
|
|
@@ -25015,19 +26463,14 @@ async function executeAutoCompact(messages, toolUseContext) {
|
|
|
25015
26463
|
cache_read_input_tokens: 0
|
|
25016
26464
|
};
|
|
25017
26465
|
const recoveredFiles = await selectAndReadFiles();
|
|
25018
|
-
const
|
|
25019
|
-
createUserMessage(
|
|
25020
|
-
compressionNotice ? `Context automatically compressed due to token limit. ${compressionNotice} Using '${compressionModelPointer}' for compression.` : `Context automatically compressed due to token limit. Using '${compressionModelPointer}' for compression.`
|
|
25021
|
-
),
|
|
26466
|
+
const result = [
|
|
26467
|
+
createUserMessage(noticeText),
|
|
25022
26468
|
summaryResponse
|
|
25023
26469
|
];
|
|
25024
|
-
|
|
25025
|
-
|
|
25026
|
-
|
|
25027
|
-
|
|
25028
|
-
startLine: 1
|
|
25029
|
-
});
|
|
25030
|
-
const recoveryMessage = createUserMessage(
|
|
26470
|
+
for (const file of recoveredFiles) {
|
|
26471
|
+
const contentWithLines = addLineNumbers({ content: file.content, startLine: 1 });
|
|
26472
|
+
result.push(
|
|
26473
|
+
createUserMessage(
|
|
25031
26474
|
`**Recovered File: ${file.path}**
|
|
25032
26475
|
|
|
25033
26476
|
\`\`\`
|
|
@@ -25035,15 +26478,62 @@ ${contentWithLines}
|
|
|
25035
26478
|
\`\`\`
|
|
25036
26479
|
|
|
25037
26480
|
*Automatically recovered (${file.tokens} tokens)${file.truncated ? " [truncated]" : ""}*`
|
|
25038
|
-
)
|
|
25039
|
-
|
|
25040
|
-
}
|
|
26481
|
+
)
|
|
26482
|
+
);
|
|
25041
26483
|
}
|
|
25042
26484
|
getMessagesSetter()([]);
|
|
25043
26485
|
getContext.cache.clear?.();
|
|
25044
26486
|
getCodeStyle.cache.clear?.();
|
|
25045
26487
|
resetFileFreshnessSession();
|
|
25046
|
-
return
|
|
26488
|
+
return result;
|
|
26489
|
+
}
|
|
26490
|
+
function resolveCompressionModel(tokenCount) {
|
|
26491
|
+
const modelManager = getModelManager();
|
|
26492
|
+
const compactResolution = modelManager.resolveModelWithInfo("compact");
|
|
26493
|
+
const mainResolution = modelManager.resolveModelWithInfo("main");
|
|
26494
|
+
let modelPointer = "compact";
|
|
26495
|
+
let notice = null;
|
|
26496
|
+
if (!compactResolution.success || !compactResolution.profile) {
|
|
26497
|
+
modelPointer = "main";
|
|
26498
|
+
notice = compactResolution.error || "Compression model 'compact' not configured.";
|
|
26499
|
+
} else {
|
|
26500
|
+
const compactBudget = Math.floor(compactResolution.profile.contextLength * 0.9);
|
|
26501
|
+
if (compactBudget > 0 && tokenCount > compactBudget) {
|
|
26502
|
+
modelPointer = "main";
|
|
26503
|
+
notice = `Compression model '${compactResolution.profile.name}' can't fit context (~${Math.round(tokenCount / 1e3)}k tokens).`;
|
|
26504
|
+
}
|
|
26505
|
+
}
|
|
26506
|
+
if (modelPointer === "main" && (!mainResolution.success || !mainResolution.profile)) {
|
|
26507
|
+
throw new Error(mainResolution.error || "Compression fallback failed: 'main' not configured.");
|
|
26508
|
+
}
|
|
26509
|
+
return { modelPointer, notice };
|
|
26510
|
+
}
|
|
26511
|
+
function extractSummaryText(response) {
|
|
26512
|
+
const content = response.message.content;
|
|
26513
|
+
if (typeof content === "string") return content;
|
|
26514
|
+
if (Array.isArray(content)) {
|
|
26515
|
+
for (const block of content) {
|
|
26516
|
+
if (block?.type === "text" && block.text) return block.text;
|
|
26517
|
+
}
|
|
26518
|
+
}
|
|
26519
|
+
return null;
|
|
26520
|
+
}
|
|
26521
|
+
function messagesToCompactable(messages) {
|
|
26522
|
+
return messages.map((msg) => {
|
|
26523
|
+
let content = "";
|
|
26524
|
+
let type2 = "user";
|
|
26525
|
+
if (msg.type === "user") {
|
|
26526
|
+
type2 = "user";
|
|
26527
|
+
const rawContent = msg.message?.content;
|
|
26528
|
+
content = typeof rawContent === "string" ? rawContent : Array.isArray(rawContent) ? rawContent.map((c) => c.text || "").join("\n") : "";
|
|
26529
|
+
} else if (msg.type === "assistant") {
|
|
26530
|
+
type2 = "assistant";
|
|
26531
|
+
const rawContent = msg.message?.content;
|
|
26532
|
+
content = typeof rawContent === "string" ? rawContent : Array.isArray(rawContent) ? rawContent.map((c) => c.text || "").join("\n") : "";
|
|
26533
|
+
}
|
|
26534
|
+
const tokens = Math.ceil(content.length * 0.25);
|
|
26535
|
+
return { type: type2, content, tokens, original: msg };
|
|
26536
|
+
});
|
|
25047
26537
|
}
|
|
25048
26538
|
|
|
25049
26539
|
// src/app/query.ts
|
|
@@ -26911,7 +28401,7 @@ import React102, { useCallback as useCallback17, useEffect as useEffect26, useMe
|
|
|
26911
28401
|
import { Box as Box76, Text as Text80, useInput as useInput30 } from "ink";
|
|
26912
28402
|
import figures8 from "figures";
|
|
26913
28403
|
import chalk15 from "chalk";
|
|
26914
|
-
import { join as
|
|
28404
|
+
import { join as join17 } from "path";
|
|
26915
28405
|
import { spawn as spawn2 } from "child_process";
|
|
26916
28406
|
|
|
26917
28407
|
// src/commands/agents/tooling.ts
|
|
@@ -26953,13 +28443,13 @@ async function getAvailableTools() {
|
|
|
26953
28443
|
// src/commands/agents/storage.ts
|
|
26954
28444
|
init_state();
|
|
26955
28445
|
import {
|
|
26956
|
-
existsSync as
|
|
26957
|
-
mkdirSync as
|
|
28446
|
+
existsSync as existsSync19,
|
|
28447
|
+
mkdirSync as mkdirSync8,
|
|
26958
28448
|
renameSync as renameSync2,
|
|
26959
28449
|
unlinkSync as unlinkSync2,
|
|
26960
|
-
writeFileSync as
|
|
28450
|
+
writeFileSync as writeFileSync10
|
|
26961
28451
|
} from "fs";
|
|
26962
|
-
import { join as
|
|
28452
|
+
import { join as join16 } from "path";
|
|
26963
28453
|
import { homedir as homedir7 } from "os";
|
|
26964
28454
|
init_log();
|
|
26965
28455
|
|
|
@@ -26967,7 +28457,7 @@ init_log();
|
|
|
26967
28457
|
import { randomUUID as randomUUID5 } from "crypto";
|
|
26968
28458
|
init_log();
|
|
26969
28459
|
async function generateAgentWithClaude(prompt) {
|
|
26970
|
-
const { queryModel } = await import("./llm-
|
|
28460
|
+
const { queryModel } = await import("./llm-XBH33BXT.js");
|
|
26971
28461
|
const systemPrompt = `You are an expert at creating AI agent configurations. Based on the user's description, generate a specialized agent configuration.
|
|
26972
28462
|
|
|
26973
28463
|
Return your response as a JSON object with exactly these fields:
|
|
@@ -27151,26 +28641,26 @@ var LEGACY_FOLDER = ".kode";
|
|
|
27151
28641
|
var AGENTS_DIR = "agents";
|
|
27152
28642
|
function getAgentDirectory(location) {
|
|
27153
28643
|
if (location === "user") {
|
|
27154
|
-
return
|
|
28644
|
+
return join16(homedir7(), PRIMARY_FOLDER, AGENTS_DIR);
|
|
27155
28645
|
}
|
|
27156
|
-
return
|
|
28646
|
+
return join16(getCwd(), PRIMARY_FOLDER, AGENTS_DIR);
|
|
27157
28647
|
}
|
|
27158
28648
|
function getLegacyAgentDirectory(location) {
|
|
27159
28649
|
if (location === "user") {
|
|
27160
|
-
return
|
|
28650
|
+
return join16(homedir7(), LEGACY_FOLDER, AGENTS_DIR);
|
|
27161
28651
|
}
|
|
27162
|
-
return
|
|
28652
|
+
return join16(getCwd(), LEGACY_FOLDER, AGENTS_DIR);
|
|
27163
28653
|
}
|
|
27164
28654
|
function getPrimaryAgentFilePath(location, agentType) {
|
|
27165
|
-
return
|
|
28655
|
+
return join16(getAgentDirectory(location), `${agentType}.md`);
|
|
27166
28656
|
}
|
|
27167
28657
|
function getLegacyAgentFilePath(location, agentType) {
|
|
27168
|
-
return
|
|
28658
|
+
return join16(getLegacyAgentDirectory(location), `${agentType}.md`);
|
|
27169
28659
|
}
|
|
27170
28660
|
function ensureDirectoryExists(location) {
|
|
27171
28661
|
const dir = getAgentDirectory(location);
|
|
27172
|
-
if (!
|
|
27173
|
-
|
|
28662
|
+
if (!existsSync19(dir)) {
|
|
28663
|
+
mkdirSync8(dir, { recursive: true });
|
|
27174
28664
|
}
|
|
27175
28665
|
return dir;
|
|
27176
28666
|
}
|
|
@@ -27178,7 +28668,7 @@ async function saveAgent(location, agentType, description2, tools, systemPrompt,
|
|
|
27178
28668
|
ensureDirectoryExists(location);
|
|
27179
28669
|
const filePath = getPrimaryAgentFilePath(location, agentType);
|
|
27180
28670
|
const legacyPath = getLegacyAgentFilePath(location, agentType);
|
|
27181
|
-
if (throwIfExists && (
|
|
28671
|
+
if (throwIfExists && (existsSync19(filePath) || existsSync19(legacyPath))) {
|
|
27182
28672
|
throw new Error(`Agent file already exists: ${filePath}`);
|
|
27183
28673
|
}
|
|
27184
28674
|
const tempFile = `${filePath}.tmp.${Date.now()}.${Math.random().toString(36).substr(2, 9)}`;
|
|
@@ -27192,8 +28682,8 @@ async function saveAgent(location, agentType, description2, tools, systemPrompt,
|
|
|
27192
28682
|
color
|
|
27193
28683
|
);
|
|
27194
28684
|
try {
|
|
27195
|
-
|
|
27196
|
-
if (throwIfExists && (
|
|
28685
|
+
writeFileSync10(tempFile, content, { encoding: "utf-8", flag: "wx" });
|
|
28686
|
+
if (throwIfExists && (existsSync19(filePath) || existsSync19(legacyPath))) {
|
|
27197
28687
|
try {
|
|
27198
28688
|
unlinkSync2(tempFile);
|
|
27199
28689
|
} catch {
|
|
@@ -27203,7 +28693,7 @@ async function saveAgent(location, agentType, description2, tools, systemPrompt,
|
|
|
27203
28693
|
renameSync2(tempFile, filePath);
|
|
27204
28694
|
} catch (error) {
|
|
27205
28695
|
try {
|
|
27206
|
-
if (
|
|
28696
|
+
if (existsSync19(tempFile)) {
|
|
27207
28697
|
unlinkSync2(tempFile);
|
|
27208
28698
|
}
|
|
27209
28699
|
} catch (cleanupError) {
|
|
@@ -27231,9 +28721,9 @@ async function updateAgent(agent, description2, tools, systemPrompt, color, mode
|
|
|
27231
28721
|
const location = agent.location;
|
|
27232
28722
|
const primaryPath = getPrimaryAgentFilePath(location, agent.agentType);
|
|
27233
28723
|
const legacyPath = getLegacyAgentFilePath(location, agent.agentType);
|
|
27234
|
-
const filePath =
|
|
28724
|
+
const filePath = existsSync19(primaryPath) ? primaryPath : existsSync19(legacyPath) ? legacyPath : primaryPath;
|
|
27235
28725
|
ensureDirectoryExists(location);
|
|
27236
|
-
|
|
28726
|
+
writeFileSync10(filePath, content, { encoding: "utf-8", flag: "w" });
|
|
27237
28727
|
}
|
|
27238
28728
|
async function deleteAgent(agent) {
|
|
27239
28729
|
if (agent.location === "built-in" || agent.location === "plugin") {
|
|
@@ -27242,10 +28732,10 @@ async function deleteAgent(agent) {
|
|
|
27242
28732
|
const location = agent.location;
|
|
27243
28733
|
const primaryPath = getPrimaryAgentFilePath(location, agent.agentType);
|
|
27244
28734
|
const legacyPath = getLegacyAgentFilePath(location, agent.agentType);
|
|
27245
|
-
if (
|
|
28735
|
+
if (existsSync19(primaryPath)) {
|
|
27246
28736
|
unlinkSync2(primaryPath);
|
|
27247
28737
|
}
|
|
27248
|
-
if (
|
|
28738
|
+
if (existsSync19(legacyPath)) {
|
|
27249
28739
|
unlinkSync2(legacyPath);
|
|
27250
28740
|
}
|
|
27251
28741
|
}
|
|
@@ -28261,8 +29751,8 @@ function ViewAgent(props) {
|
|
|
28261
29751
|
if (props.agent.source === "plugin") return `Plugin: ${props.agent.baseDir ?? "Unknown"}`;
|
|
28262
29752
|
const baseDir = props.agent.baseDir;
|
|
28263
29753
|
const file = `${props.agent.filename ?? props.agent.agentType}.md`;
|
|
28264
|
-
if (props.agent.source === "projectSettings") return
|
|
28265
|
-
if (baseDir) return
|
|
29754
|
+
if (props.agent.source === "projectSettings") return join17(".claude", "agents", file);
|
|
29755
|
+
if (baseDir) return join17(baseDir, file);
|
|
28266
29756
|
return props.agent.source;
|
|
28267
29757
|
})();
|
|
28268
29758
|
const toolsSummary = () => {
|
|
@@ -28610,6 +30100,7 @@ var COMMANDS = memoize3(() => [
|
|
|
28610
30100
|
auto_work_default,
|
|
28611
30101
|
auto_bugfix_default,
|
|
28612
30102
|
parallel_execute_default,
|
|
30103
|
+
fix_harness_default,
|
|
28613
30104
|
todos_default,
|
|
28614
30105
|
...isAnthropicAuthEnabled() ? [logout_default, login_default()] : [],
|
|
28615
30106
|
...INTERNAL_ONLY_COMMANDS
|
|
@@ -30229,8 +31720,8 @@ var BashTool = {
|
|
|
30229
31720
|
const targetDir = parts[1].replace(/^['"]|['"]$/g, "");
|
|
30230
31721
|
const fullTargetDir = isAbsolute10(targetDir) ? targetDir : resolve10(getCwd(), targetDir);
|
|
30231
31722
|
if (!isInDirectory(
|
|
30232
|
-
|
|
30233
|
-
|
|
31723
|
+
relative15(getOriginalCwd(), fullTargetDir),
|
|
31724
|
+
relative15(getCwd(), getOriginalCwd())
|
|
30234
31725
|
)) {
|
|
30235
31726
|
return {
|
|
30236
31727
|
result: false,
|
|
@@ -30636,7 +32127,7 @@ ${footerParts.join(" ")}`;
|
|
|
30636
32127
|
for (const filePath of filePaths) {
|
|
30637
32128
|
const fullFilePath = isAbsolute10(filePath) ? filePath : resolve10(getCwd(), filePath);
|
|
30638
32129
|
try {
|
|
30639
|
-
readFileTimestamps[fullFilePath] =
|
|
32130
|
+
readFileTimestamps[fullFilePath] = statSync15(fullFilePath).mtimeMs;
|
|
30640
32131
|
} catch (e) {
|
|
30641
32132
|
logError(e);
|
|
30642
32133
|
}
|
|
@@ -31051,8 +32542,25 @@ Game project changes must pass through verification layers before being committe
|
|
|
31051
32542
|
## Harness Self-Evolution
|
|
31052
32543
|
When your changes cause an error and you fix it:
|
|
31053
32544
|
1. Analyze the root cause
|
|
31054
|
-
2. Determine which rule file should be updated to prevent the same class of error
|
|
31055
|
-
3.
|
|
32545
|
+
2. Determine which rule file should be updated (.danya/rules/) to prevent the same class of error
|
|
32546
|
+
3. Route to the correct file:
|
|
32547
|
+
- Forbidden zone violation \u2192 constitution.md
|
|
32548
|
+
- Coding principle violation \u2192 golden-principles.md
|
|
32549
|
+
- Known pitfall \u2192 known-pitfalls.md
|
|
32550
|
+
- Architecture boundary \u2192 architecture-boundaries.md
|
|
32551
|
+
4. Add a rule: \u274C what went wrong + \u2705 correct approach
|
|
32552
|
+
5. Keep total lines per rule file under 550
|
|
32553
|
+
The system will prompt you when it detects an error-then-fix pattern. Cooperate by writing the rule update.
|
|
32554
|
+
You can also manually run /fix-harness at any time.
|
|
32555
|
+
|
|
32556
|
+
## Subagent Dispatch
|
|
32557
|
+
Use subagents to avoid polluting the main context with large search/analysis results:
|
|
32558
|
+
- Searching 5+ files \u2192 dispatch to subagent, get back a file list
|
|
32559
|
+
- Analyzing large compilation output \u2192 dispatch to subagent, get back a summary
|
|
32560
|
+
- Exploring unfamiliar codebase area \u2192 dispatch to subagent, get back structure overview
|
|
32561
|
+
- Checking all event subscriptions/references \u2192 dispatch to subagent, get back unmatched pairs
|
|
32562
|
+
Rule of thumb: if the task needs 5+ tool calls and you only need the final result, use a subagent.
|
|
32563
|
+
Do NOT use subagents for: single file edits, single command execution, reading 2-3 files.`;
|
|
31056
32564
|
}
|
|
31057
32565
|
function getExecutingWithCareSection() {
|
|
31058
32566
|
return `# Executing Actions with Care
|