wave-agent-sdk 0.18.7 → 0.19.1
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/builtin/skills/settings/ENV.md +0 -1
- package/builtin/skills/settings/HOOKS.md +10 -0
- package/builtin/skills/settings/MODELS.md +55 -10
- package/builtin/skills/settings/SKILL.md +8 -4
- package/builtin/skills/settings/SKILLS.md +6 -4
- package/dist/agent.d.ts.map +1 -1
- package/dist/agent.js +12 -5
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/managers/aiManager.d.ts.map +1 -1
- package/dist/managers/aiManager.js +20 -4
- package/dist/managers/mcpManager.d.ts.map +1 -1
- package/dist/managers/mcpManager.js +7 -2
- package/dist/managers/messageManager.d.ts +3 -5
- package/dist/managers/messageManager.d.ts.map +1 -1
- package/dist/managers/messageManager.js +17 -77
- package/dist/managers/skillManager.d.ts +1 -0
- package/dist/managers/skillManager.d.ts.map +1 -1
- package/dist/managers/skillManager.js +11 -2
- package/dist/prompts/index.d.ts +3 -2
- package/dist/prompts/index.d.ts.map +1 -1
- package/dist/prompts/index.js +5 -1
- package/dist/services/aiService.d.ts.map +1 -1
- package/dist/services/aiService.js +16 -47
- package/dist/services/configurationService.d.ts.map +1 -1
- package/dist/services/configurationService.js +25 -19
- package/dist/services/hook.d.ts.map +1 -1
- package/dist/services/hook.js +6 -0
- package/dist/services/initializationService.d.ts.map +1 -1
- package/dist/services/initializationService.js +1 -1
- package/dist/services/interactionService.js +1 -1
- package/dist/services/reversionService.d.ts +5 -1
- package/dist/services/reversionService.d.ts.map +1 -1
- package/dist/services/reversionService.js +50 -22
- package/dist/services/session.d.ts +4 -13
- package/dist/services/session.d.ts.map +1 -1
- package/dist/services/session.js +59 -215
- package/dist/telemetry/sessionTracing.d.ts +14 -4
- package/dist/telemetry/sessionTracing.d.ts.map +1 -1
- package/dist/telemetry/sessionTracing.js +134 -8
- package/dist/tools/bashTool.d.ts.map +1 -1
- package/dist/tools/bashTool.js +16 -1
- package/dist/types/config.d.ts +11 -2
- package/dist/types/config.d.ts.map +1 -1
- package/dist/types/hooks.d.ts +1 -0
- package/dist/types/hooks.d.ts.map +1 -1
- package/dist/types/messaging.d.ts +0 -1
- package/dist/types/messaging.d.ts.map +1 -1
- package/dist/types/skills.d.ts +1 -0
- package/dist/types/skills.d.ts.map +1 -1
- package/dist/types/telemetry.d.ts +14 -1
- package/dist/types/telemetry.d.ts.map +1 -1
- package/dist/utils/atomicWrite.d.ts +15 -0
- package/dist/utils/atomicWrite.d.ts.map +1 -0
- package/dist/utils/atomicWrite.js +59 -0
- package/dist/utils/cacheControlUtils.d.ts +3 -15
- package/dist/utils/cacheControlUtils.d.ts.map +1 -1
- package/dist/utils/cacheControlUtils.js +4 -35
- package/dist/utils/containerSetup.d.ts.map +1 -1
- package/dist/utils/containerSetup.js +5 -1
- package/dist/utils/convertMessagesForAPI.d.ts +9 -1
- package/dist/utils/convertMessagesForAPI.d.ts.map +1 -1
- package/dist/utils/convertMessagesForAPI.js +74 -55
- package/dist/utils/mcpUtils.d.ts.map +1 -1
- package/dist/utils/mcpUtils.js +2 -1
- package/dist/utils/modelCapabilities.d.ts +22 -0
- package/dist/utils/modelCapabilities.d.ts.map +1 -0
- package/dist/utils/modelCapabilities.js +24 -0
- package/dist/utils/skillParser.d.ts.map +1 -1
- package/dist/utils/skillParser.js +3 -1
- package/package.json +1 -1
- package/src/agent.ts +11 -5
- package/src/index.ts +1 -0
- package/src/managers/aiManager.ts +22 -2
- package/src/managers/mcpManager.ts +8 -2
- package/src/managers/messageManager.ts +22 -104
- package/src/managers/skillManager.ts +16 -2
- package/src/prompts/index.ts +6 -1
- package/src/services/aiService.ts +15 -85
- package/src/services/configurationService.ts +27 -41
- package/src/services/hook.ts +7 -0
- package/src/services/initializationService.ts +1 -3
- package/src/services/interactionService.ts +1 -1
- package/src/services/reversionService.ts +50 -27
- package/src/services/session.ts +63 -262
- package/src/telemetry/sessionTracing.ts +167 -12
- package/src/tools/bashTool.ts +23 -1
- package/src/types/config.ts +12 -2
- package/src/types/hooks.ts +1 -0
- package/src/types/messaging.ts +0 -1
- package/src/types/skills.ts +1 -0
- package/src/types/telemetry.ts +17 -1
- package/src/utils/atomicWrite.ts +61 -0
- package/src/utils/cacheControlUtils.ts +5 -38
- package/src/utils/containerSetup.ts +5 -1
- package/src/utils/convertMessagesForAPI.ts +87 -57
- package/src/utils/mcpUtils.ts +2 -1
- package/src/utils/modelCapabilities.ts +30 -0
- package/src/utils/skillParser.ts +3 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"skillManager.d.ts","sourceRoot":"","sources":["../../src/managers/skillManager.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAEtC,OAAO,KAAK,EACV,mBAAmB,EACnB,aAAa,EACb,KAAK,EAGL,aAAa,EACb,sBAAsB,EACvB,MAAM,mBAAmB,CAAC;AAU3B,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAGlD;;GAEG;AACH,qBAAa,YAAa,SAAQ,YAAY;
|
|
1
|
+
{"version":3,"file":"skillManager.d.ts","sourceRoot":"","sources":["../../src/managers/skillManager.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAEtC,OAAO,KAAK,EACV,mBAAmB,EACnB,aAAa,EACb,KAAK,EAGL,aAAa,EACb,sBAAsB,EACvB,MAAM,mBAAmB,CAAC;AAU3B,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAGlD;;GAEG;AACH,qBAAa,YAAa,SAAQ,YAAY;IAgB1C,OAAO,CAAC,SAAS;IAfnB,OAAO,CAAC,kBAAkB,CAAS;IACnC,OAAO,CAAC,wBAAwB,CAAS;IACzC,OAAO,CAAC,wBAAwB,CAAS;IACzC,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,OAAO,CAAS;IAExB,OAAO,CAAC,aAAa,CAAoC;IACzD,OAAO,CAAC,YAAY,CAA4B;IAChD,OAAO,CAAC,mBAAmB,CAAoC;IAC/D,OAAO,CAAC,kBAAkB,CAA4B;IACtD,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,WAAW,CAAmC;IACtD,OAAO,CAAC,YAAY,CAAU;gBAGpB,SAAS,EAAE,SAAS,EAC5B,OAAO,GAAE,mBAAwB;IAcnC;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAoBjC;;OAEG;YACW,aAAa;IAqC3B;;OAEG;YACW,YAAY;IAsC1B;;OAEG;IACG,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAO9B;;OAEG;IACH,aAAa,IAAI,OAAO;IAIxB;;OAEG;IACH,kBAAkB,IAAI,aAAa,EAAE;IAQrC;;OAEG;IACH,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,aAAa,GAAG,SAAS;IAQzD;;;OAGG;IACG,SAAS,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,GAAG,IAAI,CAAC;IAgBzD;;OAEG;YACW,cAAc;IA4C5B;;OAEG;YACW,uBAAuB;YA0BvB,aAAa;YAiBb,gBAAgB;IAsD9B;;OAEG;YACW,oBAAoB;IA4BlC;;OAEG;IACG,YAAY,CAAC,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC;QAC/C,OAAO,EAAE,MAAM,CAAC;QAChB,OAAO,CAAC,EAAE,sBAAsB,CAAC;QACjC,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;KACzB,CAAC;IA8BF;;OAEG;IACG,YAAY,CAAC,IAAI,EAAE,aAAa,GAAG,OAAO,CAC5C;QACE,OAAO,EAAE,MAAM,CAAC;QAChB,KAAK,EAAE,KAAK,CAAC;KACd,GACD;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,SAAS,CAAA;KAAE,CACzC;IA6BD;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAkC3B;;OAEG;YACW,yBAAyB;IAWvC;;OAEG;IACH,OAAO,CAAC,qBAAqB;IAc7B;;OAEG;IACH,oBAAoB,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,IAAI;CA8BhE"}
|
|
@@ -25,6 +25,8 @@ export class SkillManager extends EventEmitter {
|
|
|
25
25
|
options.personalSkillsPath || join(homedir(), ".wave", "skills");
|
|
26
26
|
this.personalClaudeSkillsPath =
|
|
27
27
|
options.personalClaudeSkillsPath || join(homedir(), ".claude", "skills");
|
|
28
|
+
this.personalAgentsSkillsPath =
|
|
29
|
+
options.personalAgentsSkillsPath || join(homedir(), ".agents", "skills");
|
|
28
30
|
this.scanTimeout = options.scanTimeout || 5000;
|
|
29
31
|
this.workdir = options.workdir || process.cwd();
|
|
30
32
|
this.watchEnabled = options.watch ?? false;
|
|
@@ -92,8 +94,10 @@ export class SkillManager extends EventEmitter {
|
|
|
92
94
|
const pathsToWatch = [
|
|
93
95
|
this.personalSkillsPath,
|
|
94
96
|
this.personalClaudeSkillsPath,
|
|
97
|
+
this.personalAgentsSkillsPath,
|
|
95
98
|
join(this.workdir, ".wave", "skills"),
|
|
96
99
|
join(this.workdir, ".claude", "skills"),
|
|
100
|
+
join(this.workdir, ".agents", "skills"),
|
|
97
101
|
];
|
|
98
102
|
logger?.debug(`Setting up skill watcher for: ${pathsToWatch.join(", ")}`);
|
|
99
103
|
for (const pathToWatch of pathsToWatch) {
|
|
@@ -167,18 +171,21 @@ export class SkillManager extends EventEmitter {
|
|
|
167
171
|
*/
|
|
168
172
|
async discoverSkills() {
|
|
169
173
|
const builtinCollection = await this.discoverSkillCollection(getBuiltinSkillsDir(), "builtin");
|
|
174
|
+
const personalAgentsCollection = await this.discoverSkillCollection(this.personalAgentsSkillsPath, "personal");
|
|
170
175
|
const personalClaudeCollection = await this.discoverSkillCollection(this.personalClaudeSkillsPath, "personal");
|
|
171
176
|
const personalCollection = await this.discoverSkillCollection(this.personalSkillsPath, "personal");
|
|
172
177
|
const projectCollection = await this.discoverSkillCollection(this.workdir, "project");
|
|
173
178
|
return {
|
|
174
179
|
builtinSkills: builtinCollection.skills,
|
|
175
180
|
personalSkills: new Map([
|
|
176
|
-
...
|
|
181
|
+
...personalAgentsCollection.skills, // lowest priority
|
|
182
|
+
...personalClaudeCollection.skills, // overrides .agents
|
|
177
183
|
...personalCollection.skills, // .wave overrides .claude
|
|
178
184
|
]),
|
|
179
185
|
projectSkills: projectCollection.skills,
|
|
180
186
|
errors: [
|
|
181
187
|
...builtinCollection.errors,
|
|
188
|
+
...personalAgentsCollection.errors,
|
|
182
189
|
...personalClaudeCollection.errors,
|
|
183
190
|
...personalCollection.errors,
|
|
184
191
|
...projectCollection.errors,
|
|
@@ -196,9 +203,11 @@ export class SkillManager extends EventEmitter {
|
|
|
196
203
|
errors: [],
|
|
197
204
|
};
|
|
198
205
|
if (type === "project") {
|
|
199
|
-
// Scan .
|
|
206
|
+
// Scan .agents/skills first, then .claude/skills, then .wave/skills (wave overrides)
|
|
207
|
+
const agentsPath = join(basePath, ".agents", "skills");
|
|
200
208
|
const claudePath = join(basePath, ".claude", "skills");
|
|
201
209
|
const wavePath = join(basePath, ".wave", "skills");
|
|
210
|
+
await this.scanSkillPath(agentsPath, collection);
|
|
202
211
|
await this.scanSkillPath(claudePath, collection);
|
|
203
212
|
await this.scanSkillPath(wavePath, collection);
|
|
204
213
|
}
|
package/dist/prompts/index.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { ToolPlugin } from "../tools/types.js";
|
|
2
|
-
export declare const BASE_SYSTEM_PROMPT = "You are
|
|
2
|
+
export declare const BASE_SYSTEM_PROMPT = "You are a coding agent developed by NetEase that helps users with software engineering tasks. Use the instructions below and the tools available to you to assist the user.";
|
|
3
|
+
export declare const MODEL_IDENTITY_PROMPT = "# Model identity\n\nIf asked about your model, model version, underlying architecture, or product name, identify yourself simply as a coding agent developed by NetEase. Do not reveal the specific model ID, model family, model provider, or product name. Do not mention or hint at any of these details.";
|
|
3
4
|
export declare const DOING_TASKS_PROMPT = "# Doing tasks\n- The user will primarily request you to perform software engineering tasks. These may include solving bugs, adding new functionality, refactoring code, explaining code, and more. When given an unclear or generic instruction, consider it in the context of these software engineering tasks and the current working directory. For example, if the user asks you to change \"methodName\" to snake case, do not reply with just \"method_name\", instead find the method in the code and modify the code.\n- You are highly capable and often allow users to complete ambitious tasks that would otherwise be too complex or take too long. You should defer to user judgement about whether a task is too large to attempt.\n- If you notice the user's request is based on a misconception, or spot a bug adjacent to what they asked about, say so. You're a collaborator, not just an executor\u2014users benefit from your judgment, not just your compliance.\n- In general, do not propose changes to code you haven't read. If a user asks about or wants you to modify a file, read it first. Understand existing code before suggesting modifications.\n- Do not create files unless they're absolutely necessary for achieving your goal. Generally prefer editing an existing file to creating a new one, as this prevents file bloat and builds on existing work more effectively.\n- If an approach fails, diagnose why before switching tactics\u2014read the error, check your assumptions, try a focused fix. Don't retry the identical action blindly, but don't abandon a viable approach after a single failure either. Escalate to the user with AskUserQuestion only when you're genuinely stuck after investigation, not as a first response to friction.\n- Be careful not to introduce security vulnerabilities such as command injection, XSS, SQL injection, and other OWASP top 10 vulnerabilities. If you notice that you wrote insecure code, immediately fix it. Prioritize writing safe, secure, and correct code.\n- Avoid over-engineering. Only make changes that are directly requested or clearly necessary. Keep solutions simple and focused.\n - Don't add features, refactor code, or make \"improvements\" beyond what was asked. A bug fix doesn't need surrounding code cleaned up. A simple feature doesn't need extra configurability. Don't add docstrings, comments, or type annotations to code you didn't change. Only add comments where the logic isn't self-evident.\n - Don't add error handling, fallbacks, or validation for scenarios that can't happen. Trust internal code and framework guarantees. Only validate at system boundaries (user input, external APIs). Don't use feature flags or backwards-compatibility shims when you can just change the code.\n - Don't create helpers, utilities, or abstractions for one-time operations. Don't design for hypothetical future requirements. The right amount of complexity is what the task actually requires\u2014no speculative abstractions, but no half-finished implementations either. Three similar lines of code is better than a premature abstraction.\n- Avoid backwards-compatibility hacks like renaming unused _vars, re-exporting types, adding // removed comments for removed code, etc. If you are certain that something is unused, you can delete it completely.\n- Report outcomes faithfully: if tests fail, say so with the relevant output; if you did not run a verification step, say that rather than implying it succeeded. Never claim \"all tests pass\" when output shows failures, never suppress or simplify failing checks (tests, lints, type errors) to manufacture a green result, and never characterize incomplete or broken work as done. Equally, when a check did pass or a task is complete, state it plainly \u2014 do not hedge confirmed results with unnecessary disclaimers, downgrade finished work to \"partial,\" or re-verify things you already checked. The goal is an accurate report, not a defensive one.\n- Before reporting a task complete, verify it actually works: run the test, execute the script, check the output. Minimum complexity means no gold-plating, not skipping the finish line. If you can't verify (no test exists, can't run the code), say so explicitly rather than claiming success.";
|
|
4
5
|
export declare const EXECUTING_ACTIONS_PROMPT = "# Executing actions with care\n\nCarefully consider the reversibility and blast radius of actions. Generally you can freely take local, reversible actions like editing files or running tests. But for actions that are hard to reverse, affect shared systems beyond your local environment, or could otherwise be risky or destructive, check with the user before proceeding. The cost of pausing to confirm is low, while the cost of an unwanted action (lost work, unintended messages sent, deleted branches) can be very high. For actions like these, consider the context, the action, and user instructions, and by default transparently communicate the action and ask for confirmation before proceeding.\n\nExamples of the kind of risky actions that warrant user confirmation:\n- Destructive operations: deleting files/branches, dropping database tables, killing processes, rm -rf, overwriting uncommitted changes\n- Hard-to-reverse operations: force-pushing (can also overwrite upstream), git reset --hard, amending published commits, removing or downgrading packages/dependencies, modifying CI/CD pipelines\n- Actions visible to others or that affect shared state: pushing code, creating/closing/commenting on PRs or issues, sending messages (Slack, email, GitHub), posting to external services\n\nWhen you encounter an obstacle, do not use destructive actions as a shortcut to simply make it go away. For instance, try to identify root causes and fix underlying issues rather than bypassing safety checks (e.g. --no-verify). If you discover unexpected state like unfamiliar files, branches, or configuration, investigate before deleting or overwriting, as it may represent the user's in-progress work. For example, typically resolve merge conflicts rather than discarding changes. In short: only take risky actions carefully, and when in doubt, ask before acting. Follow both the spirit and letter of these instructions - measure twice, cut once.";
|
|
5
6
|
export declare const TOOL_POLICY = "# Using your tools\n\n- Do NOT use the Bash to run commands when a relevant dedicated tool is provided. Using dedicated tools allows the user to better understand and review your work. This is CRITICAL to assisting the user:\n - To read files use Read instead of cat, head, tail, or sed\n - To edit files use Edit instead of sed or awk\n - To create files use Write instead of cat or echo redirection\n - To search for files use Glob instead of find or ls\n - To search the content of files, use Grep instead of grep or rg\n - Reserve using the Bash exclusively for system commands and terminal operations that require shell execution. If you are unsure and there is a relevant dedicated tool, default to using the dedicated tool and only fallback on using the Bash tool for these if it is absolutely necessary.\n- You can call multiple tools in a single response. If you intend to call multiple tools and there are no dependencies between them, make all independent tool calls in parallel. Maximize use of parallel tool calls where possible to increase efficiency.\n- However, if some tool calls depend on previous calls to inform dependent values, do NOT call these tools in parallel and instead call them sequentially. For instance, if one operation must complete before another starts, run these operations sequentially instead. Never use placeholders or guess missing parameters in tool calls.\n- If the user specifies that they want you to run tools \"in parallel\", you MUST send a single message with multiple tool use content blocks.";
|
|
@@ -9,7 +10,7 @@ export declare const TOOL_POLICY = "# Using your tools\n\n- Do NOT use the Bash
|
|
|
9
10
|
export declare const OUTPUT_EFFICIENCY_PROMPT = "# Output efficiency\n\nIMPORTANT: Go straight to the point. Try the simplest approach first without going in circles. Do not overdo it. Be extra concise.\n\nKeep your text output brief and direct. Lead with the answer or action, not the reasoning. Skip filler words, preamble, and unnecessary transitions. Do not restate what the user said \u2014 just do it. When explaining, include only what is necessary for the user to understand.\n\nFocus text output on:\n- Decisions that need the user's input\n- High-level status updates at natural milestones\n- Errors or blockers that change the plan\n\nIf you can say it in one sentence, don't use three. Prefer short, direct sentences over long explanations. This does not apply to code or tool calls.";
|
|
10
11
|
export declare const TONE_AND_STYLE_PROMPT = "# Tone and style\n\n- Only use emojis if the user explicitly requests it. Avoid using emojis in all communication unless asked.\n- Your responses should be short and concise.\n- When referencing specific functions or pieces of code include the pattern file_path:line_number to allow the user to easily navigate to the source code location.\n- When referencing GitHub issues or pull requests, use the owner/repo#123 format (e.g. anthropics/claude-code#100) so they render as clickable links.\n- Do not use a colon before tool calls. Your tool calls may not be shown directly in the output, so text like \"Let me read the file:\" followed by a read tool call should just be \"Let me read the file.\" with a period.";
|
|
11
12
|
export declare function buildPlanModePrompt(planFilePath: string, planExists: boolean, isSubagent?: boolean): string;
|
|
12
|
-
export declare const DEFAULT_SYSTEM_PROMPT = "You are
|
|
13
|
+
export declare const DEFAULT_SYSTEM_PROMPT = "You are a coding agent developed by NetEase that helps users with software engineering tasks. Use the instructions below and the tools available to you to assist the user.";
|
|
13
14
|
/**
|
|
14
15
|
* A block of the system prompt with cacheability metadata.
|
|
15
16
|
* Static blocks (cacheable: true) get cache_control markers for Claude models.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/prompts/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAoB/C,eAAO,MAAM,kBAAkB,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/prompts/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAoB/C,eAAO,MAAM,kBAAkB,gLAAgL,CAAC;AAEhN,eAAO,MAAM,qBAAqB,iTAEuP,CAAC;AAE1R,eAAO,MAAM,kBAAkB,opIAcqQ,CAAC;AAErS,eAAO,MAAM,wBAAwB,25DASqmB,CAAC;AAE3oB,eAAO,MAAM,WAAW,ihDAWqH,CAAC;AAE9I;;GAEG;AACH,eAAO,MAAM,wBAAwB,+uBAWiH,CAAC;AAEvJ,eAAO,MAAM,qBAAqB,6sBAMuL,CAAC;AAE1N,wBAAgB,mBAAmB,CACjC,YAAY,EAAE,MAAM,EACpB,UAAU,EAAE,OAAO,EACnB,UAAU,GAAE,OAAe,GAC1B,MAAM,CAmFR;AAED,eAAO,MAAM,qBAAqB,gLAAqB,CAAC;AAExD;;;;GAIG;AACH,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,OAAO,CAAC;CACpB;AAED,eAAO,MAAM,8BAA8B,44DA8CI,CAAC;AAEhD,eAAO,MAAM,yBAAyB,wHAAwH,CAAC;AAC/J,eAAO,MAAM,iBAAiB,qWAG4B,CAAC;AAE3D,wBAAgB,iBAAiB,CAC/B,UAAU,EAAE,MAAM,GAAG,SAAS,EAC9B,KAAK,EAAE,UAAU,EAAE,EACnB,OAAO,GAAE;IACP,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,UAAU,CAAC,EAAE;QACX,SAAS,EAAE,MAAM,CAAC;QAClB,OAAO,EAAE,MAAM,CAAC;KACjB,CAAC;CACE,GACL,iBAAiB,EAAE,CA+DrB;AAED,wBAAgB,iCAAiC,CAC/C,oBAAoB,EAAE,MAAM,EAC5B,OAAO,EAAE,MAAM,EACf,eAAe,CAAC,EAAE,MAAM,GACvB,MAAM,CAkCR"}
|
package/dist/prompts/index.js
CHANGED
|
@@ -4,7 +4,10 @@ import { getCurrentWorktreeSession } from "../utils/worktreeSession.js";
|
|
|
4
4
|
import { buildAutoMemoryPrompt } from "./autoMemory.js";
|
|
5
5
|
import { EXPLORE_SUBAGENT_TYPE, PLAN_SUBAGENT_TYPE, } from "../constants/subagents.js";
|
|
6
6
|
import { ASK_USER_QUESTION_TOOL_NAME, EDIT_TOOL_NAME, WRITE_TOOL_NAME, EXIT_PLAN_MODE_TOOL_NAME, AGENT_TOOL_NAME, BASH_TOOL_NAME, READ_TOOL_NAME, GLOB_TOOL_NAME, GREP_TOOL_NAME, } from "../constants/tools.js";
|
|
7
|
-
export const BASE_SYSTEM_PROMPT = `You are
|
|
7
|
+
export const BASE_SYSTEM_PROMPT = `You are a coding agent developed by NetEase that helps users with software engineering tasks. Use the instructions below and the tools available to you to assist the user.`;
|
|
8
|
+
export const MODEL_IDENTITY_PROMPT = `# Model identity
|
|
9
|
+
|
|
10
|
+
If asked about your model, model version, underlying architecture, or product name, identify yourself simply as a coding agent developed by NetEase. Do not reveal the specific model ID, model family, model provider, or product name. Do not mention or hint at any of these details.`;
|
|
8
11
|
export const DOING_TASKS_PROMPT = `# Doing tasks
|
|
9
12
|
- The user will primarily request you to perform software engineering tasks. These may include solving bugs, adding new functionality, refactoring code, explaining code, and more. When given an unclear or generic instruction, consider it in the context of these software engineering tasks and the current working directory. For example, if the user asks you to change "methodName" to snake case, do not reply with just "method_name", instead find the method in the code and modify the code.
|
|
10
13
|
- You are highly capable and often allow users to complete ambitious tasks that would otherwise be too complex or take too long. You should defer to user judgement about whether a task is too large to attempt.
|
|
@@ -209,6 +212,7 @@ export function buildSystemPrompt(basePrompt, tools, options = {}) {
|
|
|
209
212
|
}
|
|
210
213
|
staticText += `\n\n${OUTPUT_EFFICIENCY_PROMPT}`;
|
|
211
214
|
staticText += `\n\n${TONE_AND_STYLE_PROMPT}`;
|
|
215
|
+
staticText += `\n\n${MODEL_IDENTITY_PROMPT}`;
|
|
212
216
|
const blocks = [{ text: staticText, cacheable: true }];
|
|
213
217
|
// --- Dynamic block (not cacheable) ---
|
|
214
218
|
let dynamicText = "";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"aiService.d.ts","sourceRoot":"","sources":["../../src/services/aiService.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,6BAA6B,EAAE,MAAM,kBAAkB,CAAC;AACjE,OAAO,EAGL,0BAA0B,EAC1B,0BAA0B,EAE3B,MAAM,qBAAqB,CAAC;AAI7B,OAAO,KAAK,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAEpE,OAAO,
|
|
1
|
+
{"version":3,"file":"aiService.d.ts","sourceRoot":"","sources":["../../src/services/aiService.ts"],"names":[],"mappings":"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"}
|
|
@@ -2,7 +2,8 @@ import { OpenAIClient } from "../utils/openaiClient.js";
|
|
|
2
2
|
import { logger } from "../utils/globalLogger.js";
|
|
3
3
|
import { addOnceAbortListener } from "../utils/abortUtils.js";
|
|
4
4
|
import { ConfigurationError, CONFIG_ERRORS } from "../types/index.js";
|
|
5
|
-
import { transformMessagesForExplicitCache,
|
|
5
|
+
import { transformMessagesForExplicitCache, extendUsageWithCacheMetrics, } from "../utils/cacheControlUtils.js";
|
|
6
|
+
import { supportsPromptCaching } from "../utils/modelCapabilities.js";
|
|
6
7
|
import * as os from "os";
|
|
7
8
|
import * as fs from "fs";
|
|
8
9
|
import * as path from "path";
|
|
@@ -102,12 +103,11 @@ export async function callAgent(options) {
|
|
|
102
103
|
fetch: gatewayConfig.fetch,
|
|
103
104
|
});
|
|
104
105
|
// Determine model early (needed for system prompt construction)
|
|
105
|
-
const currentModel = model || modelConfig.model;
|
|
106
106
|
const resolvedMaxTokens = options.maxTokens ?? modelConfig.maxTokens;
|
|
107
107
|
// Build system message content
|
|
108
108
|
let systemMessage;
|
|
109
109
|
if (Array.isArray(systemPrompt)) {
|
|
110
|
-
if (supportsPromptCaching(
|
|
110
|
+
if (supportsPromptCaching(modelConfig.capabilities)) {
|
|
111
111
|
// For Claude models, map blocks to content parts with cache_control on cacheable blocks
|
|
112
112
|
const contentParts = systemPrompt.map((block) => {
|
|
113
113
|
const part = {
|
|
@@ -141,18 +141,12 @@ export async function callAgent(options) {
|
|
|
141
141
|
// ChatCompletionMessageParam[] is already in OpenAI format, add system prompt to the beginning
|
|
142
142
|
openaiMessages = [systemMessage, ...messages];
|
|
143
143
|
processedTools = tools;
|
|
144
|
-
if (supportsPromptCaching(
|
|
145
|
-
openaiMessages = transformMessagesForExplicitCache(openaiMessages,
|
|
144
|
+
if (supportsPromptCaching(modelConfig.capabilities)) {
|
|
145
|
+
openaiMessages = transformMessagesForExplicitCache(openaiMessages, modelConfig.capabilities);
|
|
146
146
|
}
|
|
147
|
-
// Get model configuration - use injected modelConfig with optional override
|
|
148
|
-
const { model: _model, fastModel: _fastModel, maxTokens: _maxTokens, permissionMode: _permissionMode, ...extraParams } = modelConfig;
|
|
149
|
-
void _model;
|
|
150
|
-
void _fastModel;
|
|
151
|
-
void _maxTokens;
|
|
152
|
-
void _permissionMode;
|
|
153
147
|
const openaiModelConfig = getModelConfig(model || modelConfig.model, {
|
|
154
148
|
max_tokens: resolvedMaxTokens,
|
|
155
|
-
...
|
|
149
|
+
...(modelConfig.options || {}),
|
|
156
150
|
});
|
|
157
151
|
// Determine if streaming is needed
|
|
158
152
|
const isStreaming = !!(onContentUpdate ||
|
|
@@ -521,17 +515,11 @@ export async function compactMessages(options) {
|
|
|
521
515
|
fetchOptions: gatewayConfig.fetchOptions,
|
|
522
516
|
fetch: gatewayConfig.fetch,
|
|
523
517
|
});
|
|
524
|
-
//
|
|
525
|
-
|
|
526
|
-
void _model;
|
|
527
|
-
void _fastModel;
|
|
528
|
-
void _maxTokens;
|
|
529
|
-
void _permissionMode;
|
|
530
|
-
// When a fast model override is provided, use the fast model's hyperparams
|
|
531
|
-
// (if configured); otherwise fall back to the agent model's extraParams.
|
|
518
|
+
// When a fast model override is provided, use the fast model's options
|
|
519
|
+
// (if configured); otherwise fall back to the agent model's options.
|
|
532
520
|
const activeExtraParams = options.model
|
|
533
|
-
?
|
|
534
|
-
:
|
|
521
|
+
? modelConfig.fastModelOptions || {}
|
|
522
|
+
: modelConfig.options || {};
|
|
535
523
|
const openaiModelConfig = getModelConfig(options.model || modelConfig.model, {
|
|
536
524
|
temperature: 0.1,
|
|
537
525
|
max_tokens: 8192,
|
|
@@ -598,17 +586,11 @@ export async function processWebContent(options) {
|
|
|
598
586
|
fetchOptions: gatewayConfig.fetchOptions,
|
|
599
587
|
fetch: gatewayConfig.fetch,
|
|
600
588
|
});
|
|
601
|
-
//
|
|
602
|
-
|
|
603
|
-
void _model;
|
|
604
|
-
void _fastModel;
|
|
605
|
-
void _maxTokens;
|
|
606
|
-
void _permissionMode;
|
|
607
|
-
// When a fast model override is provided, use the fast model's hyperparams
|
|
608
|
-
// (if configured); otherwise fall back to the agent model's extraParams.
|
|
589
|
+
// When a fast model override is provided, use the fast model's options
|
|
590
|
+
// (if configured); otherwise fall back to the agent model's options.
|
|
609
591
|
const activeExtraParams = options.model
|
|
610
|
-
?
|
|
611
|
-
:
|
|
592
|
+
? modelConfig.fastModelOptions || {}
|
|
593
|
+
: modelConfig.options || {};
|
|
612
594
|
const openaiModelConfig = getModelConfig(options.model || modelConfig.model, {
|
|
613
595
|
temperature: 0.1,
|
|
614
596
|
max_tokens: 4096,
|
|
@@ -672,16 +654,10 @@ export async function btw(options) {
|
|
|
672
654
|
fetchOptions: gatewayConfig.fetchOptions,
|
|
673
655
|
fetch: gatewayConfig.fetch,
|
|
674
656
|
});
|
|
675
|
-
// Get model configuration - use injected agent model
|
|
676
|
-
const { model: _model, fastModel: _fastModel, maxTokens: _maxTokens, permissionMode: _permissionMode, ...extraParams } = modelConfig;
|
|
677
|
-
void _model;
|
|
678
|
-
void _fastModel;
|
|
679
|
-
void _maxTokens;
|
|
680
|
-
void _permissionMode;
|
|
681
657
|
const openaiModelConfig = getModelConfig(options.model || modelConfig.model, {
|
|
682
658
|
temperature: 0.1,
|
|
683
659
|
max_tokens: 4096,
|
|
684
|
-
...
|
|
660
|
+
...(modelConfig.options || {}),
|
|
685
661
|
});
|
|
686
662
|
try {
|
|
687
663
|
const response = await openai.chat.completions.create({
|
|
@@ -735,17 +711,10 @@ export async function evaluateGoal(options) {
|
|
|
735
711
|
fetchOptions: gatewayConfig.fetchOptions,
|
|
736
712
|
fetch: gatewayConfig.fetch,
|
|
737
713
|
});
|
|
738
|
-
const { model: _model, fastModel: _fastModel, maxTokens: _maxTokens, permissionMode: _permissionMode, fastModelConfig: _fastModelConfig, } = modelConfig;
|
|
739
|
-
void _model;
|
|
740
|
-
void _fastModel;
|
|
741
|
-
void _maxTokens;
|
|
742
|
-
void _permissionMode;
|
|
743
|
-
// evaluateGoal always uses the fast model; use its hyperparams if configured.
|
|
744
|
-
const activeExtraParams = _fastModelConfig || {};
|
|
745
714
|
const openaiModelConfig = getModelConfig(model, {
|
|
746
715
|
temperature: 0,
|
|
747
716
|
max_tokens: 200,
|
|
748
|
-
...
|
|
717
|
+
...(modelConfig.fastModelOptions || {}),
|
|
749
718
|
});
|
|
750
719
|
// Strip images from messages to reduce token usage (same as compact)
|
|
751
720
|
const cleanedMessages = messages.map((msg) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"configurationService.d.ts","sourceRoot":"","sources":["../../src/services/configurationService.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAOH,OAAO,KAAK,EACV,uBAAuB,EACvB,gBAAgB,EAChB,kBAAkB,EAClB,iBAAiB,EACjB,KAAK,EACL,iBAAiB,EAClB,MAAM,2BAA2B,CAAC;AAOnC,OAAO,EACL,KAAK,2BAA2B,EAChC,KAAK,wBAAwB,EAC7B,KAAK,uBAAuB,EAE7B,MAAM,yBAAyB,CAAC;AACjC,OAAO,EACL,aAAa,EACb,WAAW,EACX,cAAc,EACd,YAAY,EACb,MAAM,mBAAmB,CAAC;AAK3B,OAAO,EAAE,aAAa,EAAE,MAAM,QAAQ,CAAC;
|
|
1
|
+
{"version":3,"file":"configurationService.d.ts","sourceRoot":"","sources":["../../src/services/configurationService.ts"],"names":[],"mappings":"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"}
|
|
@@ -16,6 +16,7 @@ import { parseCustomHeaders } from "../utils/stringUtils.js";
|
|
|
16
16
|
import { getRemoteSettingsSync, mergeRemoteSettings, } from "./remoteSettingsService.js";
|
|
17
17
|
import { createAuthAwareFetch } from "./authService.js";
|
|
18
18
|
import { ensureWaveRuntimeFilesExcluded } from "../utils/gitUtils.js";
|
|
19
|
+
import { atomicWriteFile } from "../utils/atomicWrite.js";
|
|
19
20
|
/**
|
|
20
21
|
* Default ConfigurationService implementation
|
|
21
22
|
*
|
|
@@ -419,18 +420,12 @@ export class ConfigurationService {
|
|
|
419
420
|
maxTokens: resolvedMaxTokens,
|
|
420
421
|
permissionMode: permissionMode ?? this.options.permissionMode,
|
|
421
422
|
};
|
|
422
|
-
// Resolve fast model
|
|
423
|
-
//
|
|
424
|
-
|
|
425
|
-
const fastModelConfigSource = resolvedFastModel &&
|
|
423
|
+
// Resolve fast model generation params from models[fastModel].options.
|
|
424
|
+
// Set on baseConfig before the modelSpecificConfig spread so it isn't overwritten.
|
|
425
|
+
const fastModelSource = resolvedFastModel &&
|
|
426
426
|
this.currentConfiguration?.models?.[resolvedFastModel];
|
|
427
|
-
if (
|
|
428
|
-
|
|
429
|
-
void _fm;
|
|
430
|
-
void _ffm;
|
|
431
|
-
void _fmt;
|
|
432
|
-
void _fpm;
|
|
433
|
-
baseConfig.fastModelConfig = fastHyperparams;
|
|
427
|
+
if (fastModelSource && fastModelSource.options) {
|
|
428
|
+
baseConfig.fastModelOptions = fastModelSource.options;
|
|
434
429
|
}
|
|
435
430
|
// Merge model-specific settings from configuration
|
|
436
431
|
const modelSpecificConfig = resolvedAgentModel &&
|
|
@@ -581,7 +576,7 @@ export class ConfigurationService {
|
|
|
581
576
|
}
|
|
582
577
|
}
|
|
583
578
|
config.model = model;
|
|
584
|
-
await
|
|
579
|
+
await atomicWriteFile(configPath, JSON.stringify(config, null, 2));
|
|
585
580
|
}
|
|
586
581
|
/**
|
|
587
582
|
* Get all configured models from settings.json and environment
|
|
@@ -654,7 +649,7 @@ export class ConfigurationService {
|
|
|
654
649
|
}
|
|
655
650
|
if (!config.permissions.allow.includes(rule)) {
|
|
656
651
|
config.permissions.allow.push(rule);
|
|
657
|
-
await
|
|
652
|
+
await atomicWriteFile(localConfigPath, JSON.stringify(config, null, 2));
|
|
658
653
|
}
|
|
659
654
|
}
|
|
660
655
|
/**
|
|
@@ -693,7 +688,7 @@ export class ConfigurationService {
|
|
|
693
688
|
config.enabledPlugins = {};
|
|
694
689
|
}
|
|
695
690
|
config.enabledPlugins[pluginId] = enabled;
|
|
696
|
-
await
|
|
691
|
+
await atomicWriteFile(configPath, JSON.stringify(config, null, 2));
|
|
697
692
|
}
|
|
698
693
|
/**
|
|
699
694
|
* Get merged marketplaces from all scopes
|
|
@@ -754,7 +749,7 @@ export class ConfigurationService {
|
|
|
754
749
|
fileConfig.marketplaces = {};
|
|
755
750
|
}
|
|
756
751
|
fileConfig.marketplaces[name] = config;
|
|
757
|
-
await
|
|
752
|
+
await atomicWriteFile(configPath, JSON.stringify(fileConfig, null, 2));
|
|
758
753
|
}
|
|
759
754
|
/**
|
|
760
755
|
* Remove a marketplace from the specified scope
|
|
@@ -781,7 +776,7 @@ export class ConfigurationService {
|
|
|
781
776
|
const fileConfig = JSON.parse(content);
|
|
782
777
|
if (fileConfig.marketplaces && name in fileConfig.marketplaces) {
|
|
783
778
|
delete fileConfig.marketplaces[name];
|
|
784
|
-
await
|
|
779
|
+
await atomicWriteFile(configPath, JSON.stringify(fileConfig, null, 2));
|
|
785
780
|
}
|
|
786
781
|
}
|
|
787
782
|
catch {
|
|
@@ -813,7 +808,7 @@ export class ConfigurationService {
|
|
|
813
808
|
const config = JSON.parse(content);
|
|
814
809
|
if (config.enabledPlugins && pluginId in config.enabledPlugins) {
|
|
815
810
|
delete config.enabledPlugins[pluginId];
|
|
816
|
-
await
|
|
811
|
+
await atomicWriteFile(configPath, JSON.stringify(config, null, 2));
|
|
817
812
|
}
|
|
818
813
|
}
|
|
819
814
|
catch {
|
|
@@ -927,6 +922,13 @@ export function loadWaveConfigFromFile(filePath) {
|
|
|
927
922
|
}
|
|
928
923
|
try {
|
|
929
924
|
const content = readFileSync(filePath, "utf-8");
|
|
925
|
+
// Tolerate empty/whitespace-only files: a concurrent writer may have the
|
|
926
|
+
// file truncated mid-write. Returning null lets callers skip this source
|
|
927
|
+
// instead of crashing (consistent with the "file not found" path).
|
|
928
|
+
if (content.trim() === "") {
|
|
929
|
+
logger.warn(`Empty configuration file (likely mid-write): ${filePath}`);
|
|
930
|
+
return null;
|
|
931
|
+
}
|
|
930
932
|
const config = JSON.parse(content);
|
|
931
933
|
return {
|
|
932
934
|
hooks: config.hooks || undefined,
|
|
@@ -944,9 +946,13 @@ export function loadWaveConfigFromFile(filePath) {
|
|
|
944
946
|
}
|
|
945
947
|
catch (error) {
|
|
946
948
|
if (error instanceof SyntaxError) {
|
|
947
|
-
|
|
949
|
+
// Tolerate corrupt JSON: a concurrent writer may leave the file in a
|
|
950
|
+
// partially-written state. Warn and return null so callers skip this
|
|
951
|
+
// source instead of crashing.
|
|
952
|
+
logger.warn(`Invalid JSON syntax in ${filePath}: ${error.message}`);
|
|
953
|
+
return null;
|
|
948
954
|
}
|
|
949
|
-
// Re-throw
|
|
955
|
+
// Re-throw other errors as-is
|
|
950
956
|
throw error;
|
|
951
957
|
}
|
|
952
958
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hook.d.ts","sourceRoot":"","sources":["../../src/services/hook.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,EACL,KAAK,oBAAoB,EACzB,KAAK,mBAAmB,EACxB,KAAK,oBAAoB,EACzB,KAAK,4BAA4B,EAElC,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"hook.d.ts","sourceRoot":"","sources":["../../src/services/hook.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,EACL,KAAK,oBAAoB,EACzB,KAAK,mBAAmB,EACxB,KAAK,oBAAoB,EACzB,KAAK,4BAA4B,EAElC,MAAM,mBAAmB,CAAC;AAuG3B;;GAEG;AACH,wBAAsB,cAAc,CAClC,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,oBAAoB,GAAG,4BAA4B,EAC5D,OAAO,CAAC,EAAE,oBAAoB,GAC7B,OAAO,CAAC,mBAAmB,CAAC,CA6I9B;AAED;;GAEG;AACH,wBAAsB,eAAe,CACnC,QAAQ,EAAE,MAAM,EAAE,EAClB,OAAO,EAAE,oBAAoB,GAAG,4BAA4B,EAC5D,OAAO,CAAC,EAAE,oBAAoB,GAC7B,OAAO,CAAC,mBAAmB,EAAE,CAAC,CAchC;AAED;;GAEG;AACH,wBAAsB,sBAAsB,CAC1C,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,4BAA4B,GACpC,OAAO,CAAC,mBAAmB,EAAE,CAAC,CAMhC;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAsBtD"}
|
package/dist/services/hook.js
CHANGED
|
@@ -62,6 +62,12 @@ async function buildHookJsonInput(context) {
|
|
|
62
62
|
jsonInput.name = context.worktreeName;
|
|
63
63
|
}
|
|
64
64
|
}
|
|
65
|
+
// Add worktree_path field for WorktreeRemove events
|
|
66
|
+
if (context.event === "WorktreeRemove") {
|
|
67
|
+
if (context.worktreePath !== undefined) {
|
|
68
|
+
jsonInput.worktree_path = context.worktreePath;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
65
71
|
// Add SessionStart-specific fields
|
|
66
72
|
if (context.event === "SessionStart") {
|
|
67
73
|
if (context.source !== undefined) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"initializationService.d.ts","sourceRoot":"","sources":["../../src/services/initializationService.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EACV,OAAO,EACP,MAAM,EACN,YAAY,EACZ,WAAW,EACZ,MAAM,mBAAmB,CAAC;AAC3B,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAChE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC;AACtE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AAC9D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAClE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,oCAAoC,CAAC;AAC9E,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AAC5D,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AACtE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AAC9D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AACpE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,kCAAkC,CAAC;AAC1E,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,kCAAkC,CAAC;AAC1E,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAIpD,MAAM,WAAW,qBAAqB;IACpC,YAAY,EAAE,YAAY,CAAC;IAC3B,eAAe,EAAE,eAAe,CAAC;IACjC,SAAS,EAAE,SAAS,CAAC;IACrB,WAAW,EAAE,WAAW,CAAC;IACzB,aAAa,EAAE,aAAa,CAAC;IAC7B,OAAO,EAAE,YAAY,CAAC;IACtB,mBAAmB,EAAE,mBAAmB,CAAC;IACzC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,UAAU,CAAC;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,WAAW,CAAC;IACxB,oBAAoB,EAAE,oBAAoB,CAAC;IAC3C,WAAW,EAAE,WAAW,CAAC;IACzB,cAAc,EAAE,cAAc,CAAC;IAC/B,iBAAiB,EAAE,iBAAiB,CAAC;IACrC,iBAAiB,EAAE,iBAAiB,CAAC;IACrC,WAAW,EAAE,WAAW,CAAC;IACzB,wBAAwB,EAAE,MAAM,IAAI,CAAC;CACtC;AAED,qBAAa,qBAAqB;WACZ,UAAU,CAC5B,OAAO,EAAE,qBAAqB,EAC9B,OAAO,CAAC,EAAE;QACR,gBAAgB,CAAC,EAAE,MAAM,CAAC;QAC1B,mBAAmB,CAAC,EAAE,OAAO,CAAC;QAC9B,QAAQ,CAAC,EAAE,OAAO,EAAE,CAAC;KACtB,GACA,OAAO,CAAC,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"initializationService.d.ts","sourceRoot":"","sources":["../../src/services/initializationService.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EACV,OAAO,EACP,MAAM,EACN,YAAY,EACZ,WAAW,EACZ,MAAM,mBAAmB,CAAC;AAC3B,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAChE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC;AACtE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AAC9D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAClE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,oCAAoC,CAAC;AAC9E,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AAC5D,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AACtE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AAC9D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AACpE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,kCAAkC,CAAC;AAC1E,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,kCAAkC,CAAC;AAC1E,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAIpD,MAAM,WAAW,qBAAqB;IACpC,YAAY,EAAE,YAAY,CAAC;IAC3B,eAAe,EAAE,eAAe,CAAC;IACjC,SAAS,EAAE,SAAS,CAAC;IACrB,WAAW,EAAE,WAAW,CAAC;IACzB,aAAa,EAAE,aAAa,CAAC;IAC7B,OAAO,EAAE,YAAY,CAAC;IACtB,mBAAmB,EAAE,mBAAmB,CAAC;IACzC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,UAAU,CAAC;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,WAAW,CAAC;IACxB,oBAAoB,EAAE,oBAAoB,CAAC;IAC3C,WAAW,EAAE,WAAW,CAAC;IACzB,cAAc,EAAE,cAAc,CAAC;IAC/B,iBAAiB,EAAE,iBAAiB,CAAC;IACrC,iBAAiB,EAAE,iBAAiB,CAAC;IACrC,WAAW,EAAE,WAAW,CAAC;IACzB,wBAAwB,EAAE,MAAM,IAAI,CAAC;CACtC;AAED,qBAAa,qBAAqB;WACZ,UAAU,CAC5B,OAAO,EAAE,qBAAqB,EAC9B,OAAO,CAAC,EAAE;QACR,gBAAgB,CAAC,EAAE,MAAM,CAAC;QAC1B,mBAAmB,CAAC,EAAE,OAAO,CAAC;QAC9B,QAAQ,CAAC,EAAE,OAAO,EAAE,CAAC;KACtB,GACA,OAAO,CAAC,IAAI,CAAC;CAgSjB"}
|
|
@@ -192,7 +192,7 @@ export class InitializationService {
|
|
|
192
192
|
if (sessionToRestore) {
|
|
193
193
|
messageManager.initializeFromSession(sessionToRestore);
|
|
194
194
|
// Update task manager with the root session ID to ensure continuity across compactions
|
|
195
|
-
taskManager.setTaskListId(sessionToRestore.
|
|
195
|
+
taskManager.setTaskListId(sessionToRestore.id);
|
|
196
196
|
// After session is initialized, load tasks for the session
|
|
197
197
|
const tasks = await taskManager.listTasks();
|
|
198
198
|
agentOptions.callbacks?.onTasksChange?.(tasks);
|
|
@@ -92,7 +92,7 @@ export class InteractionService {
|
|
|
92
92
|
// 6. Initialize session state last
|
|
93
93
|
messageManager.initializeFromSession(sessionData);
|
|
94
94
|
// Update task manager with the root session ID to ensure continuity across compactions
|
|
95
|
-
taskManager.setTaskListId(sessionData.
|
|
95
|
+
taskManager.setTaskListId(sessionData.id);
|
|
96
96
|
// 7. Load tasks for the restored session
|
|
97
97
|
const tasks = await taskManager.listTasks();
|
|
98
98
|
options.callbacks?.onTasksChange?.(tasks);
|
|
@@ -5,7 +5,6 @@ export declare class ReversionService {
|
|
|
5
5
|
constructor(rootSessionId: string);
|
|
6
6
|
private getFilePathHash;
|
|
7
7
|
private getNextVersion;
|
|
8
|
-
private updateVersionsFile;
|
|
9
8
|
/**
|
|
10
9
|
* Saves a single snapshot to the file history directory.
|
|
11
10
|
* Returns the snapshot path.
|
|
@@ -19,6 +18,11 @@ export declare class ReversionService {
|
|
|
19
18
|
* Deletes all snapshots for this session.
|
|
20
19
|
*/
|
|
21
20
|
deleteSessionHistory(): Promise<void>;
|
|
21
|
+
/**
|
|
22
|
+
* Cleans up session directories older than the given number of days.
|
|
23
|
+
* Skips the current session.
|
|
24
|
+
*/
|
|
25
|
+
cleanupOldSessions(days?: number): Promise<void>;
|
|
22
26
|
private ensureDirectory;
|
|
23
27
|
}
|
|
24
28
|
//# sourceMappingURL=reversionService.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reversionService.d.ts","sourceRoot":"","sources":["../../src/services/reversionService.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAErD,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,cAAc,CAAS;IAC/B,OAAO,CAAC,aAAa,CAAS;gBAElB,aAAa,EAAE,MAAM;IAUjC,OAAO,CAAC,eAAe;YAIT,cAAc;
|
|
1
|
+
{"version":3,"file":"reversionService.d.ts","sourceRoot":"","sources":["../../src/services/reversionService.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAErD,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,cAAc,CAAS;IAC/B,OAAO,CAAC,aAAa,CAAS;gBAElB,aAAa,EAAE,MAAM;IAUjC,OAAO,CAAC,eAAe;YAIT,cAAc;IAoB5B;;;OAGG;IACG,YAAY,CAAC,QAAQ,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC;IAqB3D;;OAEG;IACG,mBAAmB,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAWvE;;OAEG;IACG,oBAAoB,IAAI,OAAO,CAAC,IAAI,CAAC;IAI3C;;;OAGG;IACG,kBAAkB,CAAC,IAAI,GAAE,MAAW,GAAG,OAAO,CAAC,IAAI,CAAC;YAwB5C,eAAe;CAG9B"}
|
|
@@ -1,41 +1,44 @@
|
|
|
1
|
-
import { readFile, writeFile, mkdir, rm } from "fs/promises";
|
|
2
|
-
import { join } from "path";
|
|
1
|
+
import { readFile, writeFile, mkdir, rm, readdir, stat } from "fs/promises";
|
|
2
|
+
import { join, dirname } from "path";
|
|
3
3
|
import { homedir } from "os";
|
|
4
4
|
import { createHash } from "crypto";
|
|
5
5
|
export class ReversionService {
|
|
6
6
|
constructor(rootSessionId) {
|
|
7
|
-
this.rootSessionId = rootSessionId;
|
|
8
|
-
this.historyBaseDir = join(homedir(), ".wave", "file-history", rootSessionId
|
|
7
|
+
this.rootSessionId = rootSessionId || "default";
|
|
8
|
+
this.historyBaseDir = join(homedir(), ".wave", "file-history", this.rootSessionId);
|
|
9
9
|
}
|
|
10
10
|
getFilePathHash(filePath) {
|
|
11
|
-
return createHash("
|
|
11
|
+
return createHash("sha256").update(filePath).digest("hex").slice(0, 16);
|
|
12
12
|
}
|
|
13
|
-
async getNextVersion(
|
|
13
|
+
async getNextVersion(filePath) {
|
|
14
|
+
const hash = this.getFilePathHash(filePath);
|
|
15
|
+
const prefix = `${hash}@v`;
|
|
14
16
|
try {
|
|
15
|
-
const files = await
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
.
|
|
19
|
-
|
|
20
|
-
|
|
17
|
+
const files = await readdir(this.historyBaseDir);
|
|
18
|
+
let maxVersion = 0;
|
|
19
|
+
for (const file of files) {
|
|
20
|
+
if (file.startsWith(prefix)) {
|
|
21
|
+
const v = parseInt(file.slice(prefix.length), 10);
|
|
22
|
+
if (!isNaN(v) && v > maxVersion) {
|
|
23
|
+
maxVersion = v;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
return maxVersion + 1;
|
|
21
28
|
}
|
|
22
29
|
catch {
|
|
23
30
|
return 1;
|
|
24
31
|
}
|
|
25
32
|
}
|
|
26
|
-
async updateVersionsFile(fileHashDir, version) {
|
|
27
|
-
await appendFile(join(fileHashDir, "versions"), `${version}\n`, "utf-8");
|
|
28
|
-
}
|
|
29
33
|
/**
|
|
30
34
|
* Saves a single snapshot to the file history directory.
|
|
31
35
|
* Returns the snapshot path.
|
|
32
36
|
*/
|
|
33
37
|
async saveSnapshot(snapshot) {
|
|
34
38
|
const fileHash = this.getFilePathHash(snapshot.filePath);
|
|
35
|
-
|
|
36
|
-
await this.
|
|
37
|
-
const
|
|
38
|
-
const snapshotPath = join(fileHashDir, `v${version}`);
|
|
39
|
+
await this.ensureDirectory(this.historyBaseDir);
|
|
40
|
+
const version = await this.getNextVersion(snapshot.filePath);
|
|
41
|
+
const snapshotPath = join(this.historyBaseDir, `${fileHash}@v${version}`);
|
|
39
42
|
const snapshotWithContent = snapshot;
|
|
40
43
|
if (snapshotWithContent.content !== null) {
|
|
41
44
|
await writeFile(snapshotPath, snapshotWithContent.content, "utf-8");
|
|
@@ -45,7 +48,6 @@ export class ReversionService {
|
|
|
45
48
|
// The absence of the file at snapshotPath will indicate it should be deleted on reversion.
|
|
46
49
|
return ""; // Return empty string to indicate no snapshot file
|
|
47
50
|
}
|
|
48
|
-
await this.updateVersionsFile(fileHashDir, version);
|
|
49
51
|
return snapshotPath;
|
|
50
52
|
}
|
|
51
53
|
/**
|
|
@@ -68,9 +70,35 @@ export class ReversionService {
|
|
|
68
70
|
async deleteSessionHistory() {
|
|
69
71
|
await rm(this.historyBaseDir, { recursive: true, force: true });
|
|
70
72
|
}
|
|
73
|
+
/**
|
|
74
|
+
* Cleans up session directories older than the given number of days.
|
|
75
|
+
* Skips the current session.
|
|
76
|
+
*/
|
|
77
|
+
async cleanupOldSessions(days = 30) {
|
|
78
|
+
const threshold = Date.now() - days * 24 * 60 * 60 * 1000;
|
|
79
|
+
const parentDir = dirname(this.historyBaseDir);
|
|
80
|
+
try {
|
|
81
|
+
const entries = await readdir(parentDir);
|
|
82
|
+
await Promise.all(entries.map(async (entry) => {
|
|
83
|
+
if (entry === this.rootSessionId)
|
|
84
|
+
return;
|
|
85
|
+
const dirPath = join(parentDir, entry);
|
|
86
|
+
try {
|
|
87
|
+
const stats = await stat(dirPath);
|
|
88
|
+
if (stats.isDirectory() && stats.mtimeMs < threshold) {
|
|
89
|
+
await rm(dirPath, { recursive: true, force: true });
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
catch {
|
|
93
|
+
// ENOENT — concurrently deleted, skip
|
|
94
|
+
}
|
|
95
|
+
}));
|
|
96
|
+
}
|
|
97
|
+
catch {
|
|
98
|
+
// parent dir doesn't exist — nothing to clean
|
|
99
|
+
}
|
|
100
|
+
}
|
|
71
101
|
async ensureDirectory(dirPath) {
|
|
72
102
|
await mkdir(dirPath, { recursive: true });
|
|
73
103
|
}
|
|
74
104
|
}
|
|
75
|
-
// Helper to avoid appendFile import error if not imported
|
|
76
|
-
import { appendFile } from "fs/promises";
|