thincoder 0.12.28 → 0.12.29
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/agent/setup.mjs +29 -15
- package/src/skills.mjs +4 -0
package/package.json
CHANGED
package/src/agent/setup.mjs
CHANGED
|
@@ -80,12 +80,20 @@ export async function prepareRun(agent, input, callbacks, {
|
|
|
80
80
|
const platform = { win32: 'Windows', darwin: 'macOS', linux: 'Linux' }[process.platform] ?? process.platform
|
|
81
81
|
const wasRestored = agent._sessionStart != null
|
|
82
82
|
agent._sessionStart ??= new Date().toISOString()
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
83
|
+
// Inject OS/cwd + cwd-tree only ONCE per process (restored sessionStart keeps the
|
|
84
|
+
// content byte-identical across restarts — 2026-08-16 cache audit). Without the guard
|
|
85
|
+
// every run re-pushed the same reminder (history bloat, wasted tokens).
|
|
86
|
+
if (!agent._osReminderInjected) {
|
|
87
|
+
agent._osReminderInjected = true
|
|
88
|
+
if (tree) {
|
|
89
|
+
agent.history.push({ role: "user", content: `[System reminder: OS: ${platform}. Working directory: ${agent.cwd}. Session start: ${agent._sessionStart}. Working directory snapshot:\n<untrusted_cwd_listing>\n${escapeXml(tree)}\n</untrusted_cwd_listing>]`, transient: true })
|
|
90
|
+
} else {
|
|
91
|
+
agent.history.push({ role: "user", content: `[System reminder: OS: ${platform}. Working directory: ${agent.cwd}. Session start: ${agent._sessionStart}.]`, transient: true })
|
|
92
|
+
}
|
|
93
|
+
|
|
87
94
|
}
|
|
88
|
-
if (wasRestored) {
|
|
95
|
+
if (wasRestored && !agent._restartReminderInjected) {
|
|
96
|
+
agent._restartReminderInjected = true
|
|
89
97
|
agent.history.push({ role: "user", content: `[System reminder: process restarted at ${new Date().toISOString()}.]`, transient: true })
|
|
90
98
|
}
|
|
91
99
|
if (agent.memory && !agent.history.some((m) => typeof m.content === "string" && m.content.startsWith(OUTLINE_INJECT_PREFIX))) {
|
|
@@ -139,16 +147,16 @@ export async function prepareRun(agent, input, callbacks, {
|
|
|
139
147
|
} catch { /* checklist not available — suppress error */ }
|
|
140
148
|
}
|
|
141
149
|
pushReal(agent, { role: "user", content: input })
|
|
142
|
-
// Time grounding for EVERY agent depth, pushed LAST (after the user input): transient,
|
|
143
|
-
// dropped on persist, fresh at every run start. Tail position keeps the second-precision
|
|
144
|
-
// content out of any prefix — caches stay hit (plugin hit a position-drift regression
|
|
145
|
-
// when the reminder was interleaved before the input; CLI is aligned preemptively).
|
|
146
|
-
agent.history.push({
|
|
147
|
-
role: "user",
|
|
148
|
-
content: `[System reminder: current time is ${timeNowLocal()} (local; timezone ${Intl.DateTimeFormat().resolvedOptions().timeZone || "local"}).]`,
|
|
149
|
-
transient: true,
|
|
150
|
-
})
|
|
151
150
|
}
|
|
151
|
+
// Time grounding for EVERY agent depth AND every resume, pushed LAST (after the user
|
|
152
|
+
// input): transient, dropped on persist, fresh at every run start — including resumes
|
|
153
|
+
// (an interrupt-continuation must know NOW, not the pre-interrupt time; 2026-08-16).
|
|
154
|
+
// Tail position keeps the second-precision content out of any prefix — caches stay hit.
|
|
155
|
+
agent.history.push({
|
|
156
|
+
role: "user",
|
|
157
|
+
content: `[System reminder: current time is ${timeNowLocal()} (local; timezone ${Intl.DateTimeFormat().resolvedOptions().timeZone || "local"}).`,
|
|
158
|
+
transient: true,
|
|
159
|
+
})
|
|
152
160
|
|
|
153
161
|
if (agent._pendingReminders.length > 0) {
|
|
154
162
|
for (const reminder of agent._pendingReminders) {
|
|
@@ -185,7 +193,13 @@ export async function prepareRun(agent, input, callbacks, {
|
|
|
185
193
|
} : subagentTool
|
|
186
194
|
|
|
187
195
|
const depthOnly = depth === 0 ? [filteredSubagent, skillTool, goalTool, engTool, verifyTool, recentChangesTool, advisorTool]
|
|
188
|
-
|
|
196
|
+
// Write-permission coder sub-agents (subagent role="coder" + escalate surgeon): the
|
|
197
|
+
// system prompt names verify (system.md) and advisor (discipline.md) — without them a
|
|
198
|
+
// surgeon hit "unknown tool" and fell back to bash node --check / npm test to
|
|
199
|
+
// self-verify (2026-08-16 deepseek surgeon diagnosis; plugin parity).
|
|
200
|
+
: agent._role === "eng-coder" ? [advisorTool, verifyTool]
|
|
201
|
+
: agent._role === "coder" ? [verifyTool, advisorTool]
|
|
202
|
+
: []
|
|
189
203
|
const tools = [...agent.tools, taskTool, planTool, timerTool, ...depthOnly]
|
|
190
204
|
const toolSchemas = tools.map(toOpenAISchema)
|
|
191
205
|
const toolByName = new Map(tools.map((t) => [t.name, t]))
|
package/src/skills.mjs
CHANGED
|
@@ -52,6 +52,10 @@ async function loadSkillsFromDir(dir) {
|
|
|
52
52
|
let entries
|
|
53
53
|
try {
|
|
54
54
|
entries = await readdir(dir, { withFileTypes: true })
|
|
55
|
+
// Deterministic order: readdir order is filesystem-dependent; an unsorted scan would
|
|
56
|
+
// reshuffle the skills listing → system prompt byte change with zero content change
|
|
57
|
+
// (2026-08-16 cache audit — that silently misses the provider prefix cache).
|
|
58
|
+
entries.sort((a, b) => a.name.localeCompare(b.name))
|
|
55
59
|
} catch {
|
|
56
60
|
return []
|
|
57
61
|
}
|