spacecode 2.8.0 → 2.9.0
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/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/repl.mjs +480 -142
- package/package.json +1 -1
package/dist/repl.mjs
CHANGED
|
@@ -3825,50 +3825,193 @@ var init_bash = __esm({
|
|
|
3825
3825
|
}
|
|
3826
3826
|
});
|
|
3827
3827
|
|
|
3828
|
-
// ../
|
|
3829
|
-
|
|
3830
|
-
|
|
3831
|
-
|
|
3832
|
-
|
|
3833
|
-
|
|
3834
|
-
|
|
3835
|
-
|
|
3836
|
-
|
|
3837
|
-
|
|
3838
|
-
|
|
3839
|
-
|
|
3840
|
-
|
|
3841
|
-
|
|
3842
|
-
|
|
3843
|
-
|
|
3844
|
-
|
|
3845
|
-
|
|
3846
|
-
|
|
3847
|
-
|
|
3828
|
+
// ../shared/src/prompts/defaults-core.ts
|
|
3829
|
+
var DEFAULT_PROMPT_LIST;
|
|
3830
|
+
var init_defaults_core = __esm({
|
|
3831
|
+
"../shared/src/prompts/defaults-core.ts"() {
|
|
3832
|
+
"use strict";
|
|
3833
|
+
DEFAULT_PROMPT_LIST = [
|
|
3834
|
+
{
|
|
3835
|
+
key: "pipeline.decompose.system",
|
|
3836
|
+
description: "Splits a request into sub-tasks and enhances each (pipeline decomposer).",
|
|
3837
|
+
vars: [],
|
|
3838
|
+
body: `You are a task decomposition and prompt enhancement engine.
|
|
3839
|
+
|
|
3840
|
+
## Decomposition Rules
|
|
3841
|
+
Analyze user requests and determine if they contain multiple independent tasks.
|
|
3842
|
+
- Numbered lists, bullet points, or requests joined by "and"/"also" are decomposable
|
|
3843
|
+
- Each sub-task should be independently executable
|
|
3844
|
+
|
|
3845
|
+
## Prompt Enhancement Principles (MiniMax Best Practices)
|
|
3846
|
+
|
|
3847
|
+
1. **Be Specific and Detailed**
|
|
3848
|
+
- Transform vague requests into rich, detailed specifications
|
|
3849
|
+
- Less: "Create a visualization website"
|
|
3850
|
+
- More: "Create an enterprise-grade data visualization website with interactive charts, filtering capabilities, export functionality, and responsive design"
|
|
3851
|
+
|
|
3852
|
+
2. **Explain Intent ("Why")**
|
|
3853
|
+
- Add context about why this task matters
|
|
3854
|
+
- Example: "Your code will be reviewed for security vulnerabilities, so validate all inputs"
|
|
3855
|
+
- This helps the agent understand the purpose and provide more accurate results
|
|
3856
|
+
|
|
3857
|
+
3. **Provide Examples**
|
|
3858
|
+
- Show good patterns to follow and bad patterns to avoid
|
|
3859
|
+
- Example: "Good: Handle errors with specific messages like 'User not found'. Bad: Use generic try/catch with no message."
|
|
3860
|
+
|
|
3861
|
+
4. **Define Success Criteria**
|
|
3862
|
+
- What does "done" look like?
|
|
3863
|
+
- Example: "Complete when: tests pass, no linting errors, and manual verification in browser"
|
|
3864
|
+
|
|
3865
|
+
5. **Specify Constraints**
|
|
3866
|
+
- What to avoid, what not to do
|
|
3867
|
+
- Example: "Do not use external dependencies beyond the existing package.json"
|
|
3868
|
+
|
|
3869
|
+
For each sub-task, enhance the description following these principles. Call the decompose_tasks function with your analysis.`
|
|
3870
|
+
},
|
|
3871
|
+
{
|
|
3872
|
+
key: "pipeline.enhance.system",
|
|
3873
|
+
description: "Rewrites a coding request into a richer prompt (pipeline optimizer).",
|
|
3874
|
+
vars: [],
|
|
3875
|
+
body: `You are a prompt enhancement engine. Transform coding requests into rich, detailed prompts following these principles:
|
|
3876
|
+
|
|
3877
|
+
## Enhancement Principles (MiniMax Best Practices)
|
|
3878
|
+
|
|
3879
|
+
1. **Be Specific and Detailed**
|
|
3880
|
+
- Transform vague requests into rich specifications
|
|
3881
|
+
- Less: "Create a visualization website"
|
|
3882
|
+
- More: "Create an enterprise-grade data visualization website with interactive charts, filtering capabilities, export functionality, and responsive design"
|
|
3883
|
+
|
|
3884
|
+
2. **Explain Intent ("Why")**
|
|
3885
|
+
- Add context about why this task matters
|
|
3886
|
+
- Example: "Your code will be reviewed for security vulnerabilities, so validate all inputs"
|
|
3887
|
+
|
|
3888
|
+
3. **Provide Examples**
|
|
3889
|
+
- Show good patterns to follow and bad patterns to avoid
|
|
3890
|
+
- Example: "Good: Handle errors with specific messages. Bad: Use generic try/catch"
|
|
3891
|
+
|
|
3892
|
+
4. **Define Success Criteria**
|
|
3893
|
+
- What does "done" look like?
|
|
3894
|
+
- Example: "Complete when: tests pass, no linting errors"
|
|
3895
|
+
|
|
3896
|
+
5. **Specify Constraints**
|
|
3897
|
+
- What to avoid
|
|
3898
|
+
- Example: "Do not use external dependencies beyond existing packages"
|
|
3899
|
+
|
|
3900
|
+
Call the enhance_prompt function with your analysis.`
|
|
3901
|
+
},
|
|
3902
|
+
{
|
|
3903
|
+
key: "context.summary",
|
|
3904
|
+
description: "Short conversation summary stored for context reuse.",
|
|
3905
|
+
vars: [],
|
|
3906
|
+
body: `Summarize this conversation concisely in 2-4 sentences. Focus on:
|
|
3907
|
+
- What the user asked for
|
|
3908
|
+
- Key decisions made
|
|
3909
|
+
- Current state of the work
|
|
3910
|
+
- Any important context (file names, technologies, error messages)
|
|
3911
|
+
|
|
3912
|
+
Do NOT include greetings or meta-commentary. Just the facts.`
|
|
3913
|
+
},
|
|
3914
|
+
{
|
|
3915
|
+
key: "context.reasoning_summary",
|
|
3916
|
+
description: "Detailed summary of the earlier conversation for the reasoning tier.",
|
|
3917
|
+
vars: [],
|
|
3918
|
+
body: `Summarize the earlier part of this conversation for a senior AI assistant that will continue the work. Be detailed and preserve:
|
|
3919
|
+
- Specific file paths, function names, and code snippets mentioned
|
|
3920
|
+
- Decisions made and their rationale
|
|
3921
|
+
- Error messages, stack traces, or debugging steps taken
|
|
3922
|
+
- Current state of the task (what's done, what remains)
|
|
3923
|
+
- User preferences or constraints expressed
|
|
3924
|
+
|
|
3925
|
+
Write 3-8 sentences. Be concrete and technical, not vague.`
|
|
3926
|
+
},
|
|
3927
|
+
{
|
|
3928
|
+
key: "profile.adapter.system",
|
|
3929
|
+
description: "Classifies imported instruction sections as keep / on_demand / drop.",
|
|
3930
|
+
vars: [],
|
|
3931
|
+
body: `You prepare a user's personal instruction file (written for the Claude Code CLI) to be used by SpaceCode, a different coding agent that runs locally with these tools: read_file, write_file, edit_file, list_directory, search, bash, todo_write, memory_read, instructions_read. SpaceCode does NOT have: Claude Code hooks, ToolSearch/deferred tools, subagents (Task/Agent), skills or slash commands (/ship etc.), MCP tools (mcp__*), plan mode or worktrees.
|
|
3932
|
+
|
|
3933
|
+
For EACH section decide:
|
|
3934
|
+
- "keep": a short, general standing rule that applies to nearly every task (always loaded). Keep this set small: the total of all kept sections must stay under about 5000 characters.
|
|
3935
|
+
- "on_demand": useful only when working in a specific area (a tool, vendor, workflow). Give a one-line "summary" saying when to read it.
|
|
3936
|
+
- "drop": (the text is kept and stored on demand anyway; this only flags it) only meaningful inside Claude Code (describes its hooks, skills, subagents, ToolSearch, MCP tool names or its own settings) or is obsolete for SpaceCode. Give a short "reason".
|
|
3937
|
+
|
|
3938
|
+
You never rewrite or shorten text; you only classify. When unsure between drop and on_demand choose on_demand. When unsure between keep and on_demand choose on_demand.
|
|
3939
|
+
|
|
3940
|
+
Reply with ONLY a JSON array, one object per input section, in the same order: {"slug": string, "decision": "keep"|"on_demand"|"drop", "reason"?: string, "summary"?: string}. No prose, no code fences.`
|
|
3941
|
+
},
|
|
3942
|
+
{
|
|
3943
|
+
key: "route.code.system",
|
|
3944
|
+
description: 'System prompt of the "code" dynamic route (pipeline helper calls).',
|
|
3945
|
+
vars: [],
|
|
3946
|
+
body: `You are an expert software engineer. Write clean, correct, well-structured code with proper error handling.`
|
|
3947
|
+
},
|
|
3948
|
+
{
|
|
3949
|
+
key: "route.code-review.system",
|
|
3950
|
+
description: 'System prompt of the "code-review" dynamic route (pipeline helper calls).',
|
|
3951
|
+
vars: [],
|
|
3952
|
+
body: `You are a senior code reviewer. Analyze code for bugs, security issues, performance problems, and maintainability. Be specific and actionable.`
|
|
3953
|
+
},
|
|
3954
|
+
{
|
|
3955
|
+
key: "route.debugging.system",
|
|
3956
|
+
description: 'System prompt of the "debugging" dynamic route (pipeline helper calls).',
|
|
3957
|
+
vars: [],
|
|
3958
|
+
body: `You are an expert debugger. Diagnose issues methodically: identify symptoms, trace root causes, and provide concrete fixes. Explain your reasoning step by step.`
|
|
3959
|
+
},
|
|
3960
|
+
{
|
|
3961
|
+
key: "route.architecture.system",
|
|
3962
|
+
description: 'System prompt of the "architecture" dynamic route (pipeline helper calls).',
|
|
3963
|
+
vars: [],
|
|
3964
|
+
body: `You are a software architect. Focus on system design, scalability, trade-offs, and infrastructure decisions. Be concrete and practical.`
|
|
3965
|
+
},
|
|
3966
|
+
{
|
|
3967
|
+
key: "route.planning.system",
|
|
3968
|
+
description: 'System prompt of the "planning" dynamic route (pipeline helper calls).',
|
|
3969
|
+
vars: [],
|
|
3970
|
+
body: `You are a technical project manager. Create structured plans, roadmaps, and specifications. Use clear headings and actionable items.`
|
|
3971
|
+
},
|
|
3972
|
+
{
|
|
3973
|
+
key: "agent.summarizer.system",
|
|
3974
|
+
description: "Extracts decisions and work items from a session transcript (resume summary, /compact).",
|
|
3975
|
+
vars: [],
|
|
3976
|
+
body: `You are extracting structured information from a coding-agent conversation transcript. Identify (a) concrete DECISIONS made during the conversation (architectural choices, approach selections, explicit tradeoffs accepted) and (b) WORK ITEMS \u2014 discrete pieces of work mentioned as done, in-progress, or still needed, each classified as "open" or "done" based on the transcript. Respond with ONLY a JSON object matching exactly this shape, no prose before or after, no markdown code fences: {"decisions": [{"description": string}], "workItems": [{"description": string, "status": "open"|"done"}]}`
|
|
3977
|
+
},
|
|
3978
|
+
{
|
|
3979
|
+
key: "agent.summarizer.user_suffix",
|
|
3980
|
+
description: "Reminder appended after the transcript for the summarizer.",
|
|
3981
|
+
vars: [],
|
|
3982
|
+
body: `Respond with ONLY the JSON object described above \u2014 no prose, no markdown code fences.`
|
|
3983
|
+
}
|
|
3984
|
+
];
|
|
3848
3985
|
}
|
|
3849
|
-
|
|
3986
|
+
});
|
|
3987
|
+
|
|
3988
|
+
// ../shared/src/prompts/defaults-agent.ts
|
|
3989
|
+
var AGENT_PROMPT_LIST;
|
|
3990
|
+
var init_defaults_agent = __esm({
|
|
3991
|
+
"../shared/src/prompts/defaults-agent.ts"() {
|
|
3992
|
+
"use strict";
|
|
3993
|
+
AGENT_PROMPT_LIST = [
|
|
3994
|
+
{
|
|
3995
|
+
key: "agent.system.core",
|
|
3996
|
+
description: "Core system prompt of the SpaceCode agent (REPL and cloud).",
|
|
3997
|
+
vars: ["where", "tool_lines", "orient_line", "finish_line", "codegen_section", "commit_section", "working_dir", "project_card_section", "resume_section"],
|
|
3998
|
+
body: `You are SpaceCode Agent, a coding assistant running {{where}}.
|
|
3850
3999
|
|
|
3851
4000
|
## Tools
|
|
3852
|
-
|
|
4001
|
+
{{tool_lines}}
|
|
3853
4002
|
|
|
3854
4003
|
## Tool usage
|
|
3855
|
-
|
|
4004
|
+
{{orient_line}}
|
|
3856
4005
|
- Use search to find files by concept ("auth middleware", "billing webhook").
|
|
3857
4006
|
- Use bash for running commands, not for reading files. Use read_file instead.
|
|
3858
4007
|
- Prefer read_file + edit_file over write_file for existing files.
|
|
3859
|
-
|
|
4008
|
+
{{finish_line}}
|
|
3860
4009
|
|
|
3861
4010
|
## Editing
|
|
3862
4011
|
- Always read_file before edit_file \u2014 you need the current content.
|
|
3863
4012
|
- old_string must match exactly once. Include surrounding lines for uniqueness.
|
|
3864
4013
|
- Make small, targeted edits. Avoid rewriting entire files with write_file.
|
|
3865
|
-
|
|
3866
|
-
## Feature generation
|
|
3867
|
-
- For multi-file features (3+ new files), prefer build_feature over writing files manually.
|
|
3868
|
-
- build_feature leverages a component library \u2014 it reuses existing implementations when possible.
|
|
3869
|
-
- After build_feature, always run tests and review the generated code before committing.
|
|
3870
|
-
- For single-file changes, bug fixes, or config edits, use edit_file directly.
|
|
3871
|
-
` : ""}
|
|
4014
|
+
{{codegen_section}}
|
|
3872
4015
|
## Error recovery
|
|
3873
4016
|
- If edit_file fails (old_string not found), re-read the file \u2014 it may have changed \u2014 then retry with corrected old_string.
|
|
3874
4017
|
- If bash fails, read the error output and try a different approach. Never repeat the same failing command.
|
|
@@ -3879,24 +4022,125 @@ ${options.hasCodegenTools ? `
|
|
|
3879
4022
|
- For an audit or plan request, finish with the audit or plan itself (findings, then ordered next steps). Do not end by asking what to work on next.
|
|
3880
4023
|
- After changes, run relevant tests (bash: npm test, pytest, etc.) to verify.
|
|
3881
4024
|
- Commit logical units of work with descriptive messages.
|
|
3882
|
-
|
|
3883
|
-
|
|
4025
|
+
{{commit_section}}
|
|
4026
|
+
{{working_dir}}
|
|
4027
|
+
{{project_card_section}}{{resume_section}}
|
|
4028
|
+
Complete the user's task, then stop. Be concise in responses.`
|
|
4029
|
+
},
|
|
4030
|
+
{
|
|
4031
|
+
key: "agent.fragment.orient_card",
|
|
4032
|
+
description: "Tool-usage line when a project card is present.",
|
|
4033
|
+
vars: [],
|
|
4034
|
+
body: `- A project card below already holds the layout, commands, doc titles and excerpts, recent commits, branch and uncommitted changes. Do not re-list directories, re-run git status/log/diff, or re-read a doc just to see what the card shows; open a file only to go beyond its excerpt.`
|
|
4035
|
+
},
|
|
4036
|
+
{
|
|
4037
|
+
key: "agent.fragment.orient_default",
|
|
4038
|
+
description: "Tool-usage line when there is no project card.",
|
|
4039
|
+
vars: [],
|
|
4040
|
+
body: `- Use list_directory to orient yourself in the codebase before diving in.`
|
|
4041
|
+
},
|
|
4042
|
+
{
|
|
4043
|
+
key: "agent.fragment.finish_github",
|
|
4044
|
+
description: "Closing instruction when GitHub tools are available.",
|
|
4045
|
+
vars: [],
|
|
4046
|
+
body: `- After completing work, create a PR with create_pull_request. Commit and push changes first.`
|
|
4047
|
+
},
|
|
4048
|
+
{
|
|
4049
|
+
key: "agent.fragment.finish_commit",
|
|
4050
|
+
description: "Closing instruction without GitHub tools.",
|
|
4051
|
+
vars: [],
|
|
4052
|
+
body: `- After completing work, commit your changes with bash (git add + git commit).`
|
|
4053
|
+
},
|
|
4054
|
+
{
|
|
4055
|
+
key: "agent.fragment.codegen",
|
|
4056
|
+
description: "Feature-generation section (only when build_feature is registered).",
|
|
4057
|
+
vars: [],
|
|
4058
|
+
body: `## Feature generation
|
|
4059
|
+
- For multi-file features (3+ new files), prefer build_feature over writing files manually.
|
|
4060
|
+
- build_feature leverages a component library \u2014 it reuses existing implementations when possible.
|
|
4061
|
+
- After build_feature, always run tests and review the generated code before committing.
|
|
4062
|
+
- For single-file changes, bug fixes, or config edits, use edit_file directly.`
|
|
4063
|
+
},
|
|
4064
|
+
{
|
|
4065
|
+
key: "agent.fragment.commit",
|
|
4066
|
+
description: "Committing section (only when commit guidance is on).",
|
|
4067
|
+
vars: [],
|
|
4068
|
+
body: `## Committing
|
|
3884
4069
|
- After completing a logical unit of work, commit changes with a descriptive message using bash (git add + git commit).
|
|
3885
4070
|
- Use conventional commit format: feat:, fix:, refactor:, test:, docs:
|
|
3886
|
-
- Don't commit after every single file change \u2014 group related changes
|
|
3887
|
-
|
|
3888
|
-
|
|
3889
|
-
|
|
3890
|
-
|
|
3891
|
-
|
|
3892
|
-
|
|
3893
|
-
|
|
3894
|
-
|
|
3895
|
-
|
|
4071
|
+
- Don't commit after every single file change \u2014 group related changes.`
|
|
4072
|
+
},
|
|
4073
|
+
{
|
|
4074
|
+
key: "agent.fragment.resume",
|
|
4075
|
+
description: "Prior-turn summary injected on resume.",
|
|
4076
|
+
vars: ["summary"],
|
|
4077
|
+
body: `## Previously in this session
|
|
4078
|
+
{{summary}}`
|
|
4079
|
+
}
|
|
4080
|
+
];
|
|
4081
|
+
}
|
|
4082
|
+
});
|
|
4083
|
+
|
|
4084
|
+
// ../shared/src/prompts/index.ts
|
|
4085
|
+
function renderPrompt(body, vars = {}) {
|
|
4086
|
+
return body.replace(VAR, (_m, name) => {
|
|
4087
|
+
if (!(name in vars)) throw new Error(`prompt variable {{${name}}} was not provided`);
|
|
4088
|
+
return vars[name];
|
|
4089
|
+
});
|
|
4090
|
+
}
|
|
4091
|
+
var DEFAULT_PROMPTS, VAR;
|
|
4092
|
+
var init_prompts = __esm({
|
|
4093
|
+
"../shared/src/prompts/index.ts"() {
|
|
4094
|
+
init_defaults_core();
|
|
4095
|
+
init_defaults_agent();
|
|
4096
|
+
DEFAULT_PROMPTS = Object.freeze(
|
|
4097
|
+
Object.fromEntries([...DEFAULT_PROMPT_LIST, ...AGENT_PROMPT_LIST].map((p) => [p.key, p]))
|
|
4098
|
+
);
|
|
4099
|
+
VAR = /\{\{\s*([a-zA-Z_][a-zA-Z0-9_]*)\s*\}\}/g;
|
|
4100
|
+
}
|
|
4101
|
+
});
|
|
4102
|
+
|
|
4103
|
+
// ../agent/src/prompt.ts
|
|
4104
|
+
function buildSystemPrompt(options) {
|
|
4105
|
+
const workingDir = options.localCwd ? `Working directory: ${options.localCwd}` : options.repoName ? `Working directory: /home/user/${options.repoName}` : "Working directory: empty workspace";
|
|
4106
|
+
const where = options.localCwd ? "on the user's machine" : "in the cloud";
|
|
4107
|
+
const toolLines = [
|
|
4108
|
+
"- read_file / write_file / edit_file / list_directory \u2014 instant file operations",
|
|
4109
|
+
"- search \u2014 semantic code search by concept or keyword",
|
|
4110
|
+
"- bash \u2014 shell commands (tests, builds, git, installs)"
|
|
4111
|
+
];
|
|
4112
|
+
if (options.hasPreviewTool) {
|
|
4113
|
+
toolLines.push("- preview \u2014 start or check a live preview of the app (front-end projects only)");
|
|
4114
|
+
}
|
|
4115
|
+
if (options.hasGitHubTools) {
|
|
4116
|
+
toolLines.push("- create_pull_request \u2014 create a GitHub PR from the current branch");
|
|
4117
|
+
}
|
|
4118
|
+
if (options.hasSentryTools) {
|
|
4119
|
+
toolLines.push("- sentry_list_issues / sentry_get_issue \u2014 view production errors (when connected)");
|
|
4120
|
+
}
|
|
4121
|
+
if (options.hasCodegenTools) {
|
|
4122
|
+
toolLines.push("- build_feature \u2014 generate a complete feature with tests using the platform codegen service. Use for multi-file features or new modules. Files are written to workspace; run tests afterwards.");
|
|
4123
|
+
}
|
|
4124
|
+
const t = (key) => options.templates?.[key] ?? DEFAULT_PROMPTS[key].body;
|
|
4125
|
+
const wrap = (body) => `
|
|
4126
|
+
${body}
|
|
4127
|
+
`;
|
|
4128
|
+
return renderPrompt(t("agent.system.core"), {
|
|
4129
|
+
where,
|
|
4130
|
+
tool_lines: toolLines.join("\n"),
|
|
4131
|
+
orient_line: options.projectCard ? t("agent.fragment.orient_card") : t("agent.fragment.orient_default"),
|
|
4132
|
+
finish_line: options.hasGitHubTools ? t("agent.fragment.finish_github") : t("agent.fragment.finish_commit"),
|
|
4133
|
+
codegen_section: options.hasCodegenTools ? wrap(t("agent.fragment.codegen")) : "",
|
|
4134
|
+
commit_section: options.commitGuidance ? wrap(t("agent.fragment.commit")) : "",
|
|
4135
|
+
working_dir: workingDir,
|
|
4136
|
+
project_card_section: options.projectCard ? wrap(options.projectCard) : "",
|
|
4137
|
+
resume_section: options.resumeSummary ? wrap(renderPrompt(t("agent.fragment.resume"), { summary: options.resumeSummary })) : ""
|
|
4138
|
+
});
|
|
3896
4139
|
}
|
|
3897
4140
|
var init_prompt = __esm({
|
|
3898
4141
|
"../agent/src/prompt.ts"() {
|
|
3899
4142
|
"use strict";
|
|
4143
|
+
init_prompts();
|
|
3900
4144
|
}
|
|
3901
4145
|
});
|
|
3902
4146
|
|
|
@@ -3921,13 +4165,17 @@ function sections(i) {
|
|
|
3921
4165
|
if (docs.length) out.push({ key: "docs", lines: docs });
|
|
3922
4166
|
const commits = i.recentCommits.slice(0, 8).map((c) => `- ${c}`);
|
|
3923
4167
|
if (commits.length) out.push({ key: "commits", lines: commits });
|
|
4168
|
+
const changeLines = [...i.changes?.vsMain ? [`- vs main: ${cut(i.changes.vsMain, 160)}`] : [], ...(i.changes?.files ?? []).slice(0, 15).map((f) => `- ${cut(f, 120)}`)];
|
|
4169
|
+
if (changeLines.length) out.push({ key: "changes", lines: changeLines });
|
|
4170
|
+
const digests = (i.digests ?? []).slice(0, 5).flatMap((d) => [`#### ${d.path}`, ...d.lines.slice(0, 6).map((l) => `- ${cut(l, 110)}`)]);
|
|
4171
|
+
if (digests.length) out.push({ key: "digests", lines: digests });
|
|
3924
4172
|
const backlog = i.backlog.slice(0, 6).map((b2) => `- ${cut(b2, 160)}`);
|
|
3925
4173
|
if (backlog.length) out.push({ key: "backlog", lines: backlog });
|
|
3926
4174
|
return out;
|
|
3927
4175
|
}
|
|
3928
|
-
function renderProjectCard(input, budgetChars =
|
|
4176
|
+
function renderProjectCard(input, budgetChars = 7e3) {
|
|
3929
4177
|
let secs = sections(input);
|
|
3930
|
-
for (const drop of ["backlog", "docs", "commits", "commands"]) {
|
|
4178
|
+
for (const drop of ["backlog", "digests", "changes", "docs", "commits", "commands"]) {
|
|
3931
4179
|
if (render(secs).length <= budgetChars) return render(secs);
|
|
3932
4180
|
secs = secs.filter((s) => s.key !== drop);
|
|
3933
4181
|
}
|
|
@@ -3953,6 +4201,8 @@ var init_project_card = __esm({
|
|
|
3953
4201
|
commands: "Commands",
|
|
3954
4202
|
docs: "Docs",
|
|
3955
4203
|
commits: "Recent commits",
|
|
4204
|
+
changes: "Uncommitted changes and branch vs main",
|
|
4205
|
+
digests: "Doc excerpts (opening lines; read the file for the rest)",
|
|
3956
4206
|
backlog: "Open work noted in repo files (context, NOT tasks to start)"
|
|
3957
4207
|
};
|
|
3958
4208
|
render = (secs) => [HEADER, ...secs.map((s) => `### ${TITLES[s.key]}
|
|
@@ -4090,9 +4340,9 @@ function createFileTools(store) {
|
|
|
4090
4340
|
const handlers = {
|
|
4091
4341
|
read_file: async (input) => {
|
|
4092
4342
|
const path12 = input.path;
|
|
4093
|
-
const
|
|
4094
|
-
if (
|
|
4095
|
-
return { output:
|
|
4343
|
+
const cached3 = readCache.get(path12);
|
|
4344
|
+
if (cached3 !== void 0) {
|
|
4345
|
+
return { output: cached3 };
|
|
4096
4346
|
}
|
|
4097
4347
|
const content = await store.readFile(path12);
|
|
4098
4348
|
if (content === null) {
|
|
@@ -4152,12 +4402,12 @@ Include more surrounding context to make old_string unique.`,
|
|
|
4152
4402
|
},
|
|
4153
4403
|
list_directory: async (input) => {
|
|
4154
4404
|
const path12 = input.path;
|
|
4155
|
-
const
|
|
4156
|
-
if (
|
|
4157
|
-
if (
|
|
4405
|
+
const cached3 = listCache.get(path12);
|
|
4406
|
+
if (cached3 !== void 0) {
|
|
4407
|
+
if (cached3.length === 0) {
|
|
4158
4408
|
return { output: `Empty or not found: ${path12}` };
|
|
4159
4409
|
}
|
|
4160
|
-
return { output:
|
|
4410
|
+
return { output: cached3.join("\n") };
|
|
4161
4411
|
}
|
|
4162
4412
|
const entries = await store.listDirectory(path12);
|
|
4163
4413
|
listCache.set(path12, entries);
|
|
@@ -5050,13 +5300,13 @@ function createCodegenTools(fileStore, config) {
|
|
|
5050
5300
|
if (!buildRes.ok) {
|
|
5051
5301
|
throw new Error(`Failed to fetch build result: ${buildRes.status}`);
|
|
5052
5302
|
}
|
|
5053
|
-
const
|
|
5054
|
-
if (!
|
|
5303
|
+
const build2 = await buildRes.json();
|
|
5304
|
+
if (!build2.result) {
|
|
5055
5305
|
throw new Error("Build completed but no files in result");
|
|
5056
5306
|
}
|
|
5057
5307
|
let files;
|
|
5058
5308
|
try {
|
|
5059
|
-
const parsed = JSON.parse(
|
|
5309
|
+
const parsed = JSON.parse(build2.result);
|
|
5060
5310
|
files = parsed.files ?? [];
|
|
5061
5311
|
} catch {
|
|
5062
5312
|
throw new Error("Failed to parse build result");
|
|
@@ -5871,10 +6121,10 @@ async function summarizeConversation(messages, config) {
|
|
|
5871
6121
|
return { decisions: [], workItems: [], summaryText: "", inputTokens: 0, outputTokens: 0 };
|
|
5872
6122
|
}
|
|
5873
6123
|
const transcript = buildTranscriptForSummarization(messages, MAX_TRANSCRIPT_CHARS);
|
|
5874
|
-
const systemPrompt =
|
|
6124
|
+
const systemPrompt = config.templates?.["agent.summarizer.system"] ?? DEFAULT_PROMPTS["agent.summarizer.system"].body;
|
|
5875
6125
|
const userContent = `${transcript}
|
|
5876
6126
|
|
|
5877
|
-
|
|
6127
|
+
${config.templates?.["agent.summarizer.user_suffix"] ?? DEFAULT_PROMPTS["agent.summarizer.user_suffix"].body}`;
|
|
5878
6128
|
const response = await fetch(`${config.apiUrl}/v1/messages`, {
|
|
5879
6129
|
method: "POST",
|
|
5880
6130
|
headers: {
|
|
@@ -5968,6 +6218,7 @@ var DEFAULT_SUMMARIZER_MODEL, MAX_TRANSCRIPT_CHARS, MAX_TOKENS2;
|
|
|
5968
6218
|
var init_summarizer = __esm({
|
|
5969
6219
|
"../agent/src/summarizer.ts"() {
|
|
5970
6220
|
"use strict";
|
|
6221
|
+
init_prompts();
|
|
5971
6222
|
DEFAULT_SUMMARIZER_MODEL = "claude-haiku-4-5";
|
|
5972
6223
|
MAX_TRANSCRIPT_CHARS = 4e4;
|
|
5973
6224
|
MAX_TOKENS2 = 4096;
|
|
@@ -6644,17 +6895,17 @@ var init_memory_tool = __esm({
|
|
|
6644
6895
|
// ../agent/src/import/profile-loader.ts
|
|
6645
6896
|
async function loadProfile(opts) {
|
|
6646
6897
|
const { client, cache: cache4, projectKeys } = opts;
|
|
6647
|
-
let
|
|
6898
|
+
let cached3 = null;
|
|
6648
6899
|
let cacheError;
|
|
6649
6900
|
try {
|
|
6650
|
-
|
|
6901
|
+
cached3 = await cache4.read();
|
|
6651
6902
|
} catch (err) {
|
|
6652
6903
|
cacheError = `profile cache unreadable: ${err instanceof Error ? err.message : String(err)}`;
|
|
6653
6904
|
}
|
|
6654
|
-
const sameProject =
|
|
6905
|
+
const sameProject = cached3 !== null && cached3.projectKey !== null && projectKeys.includes(cached3.projectKey);
|
|
6655
6906
|
try {
|
|
6656
|
-
const index = await client.index(sameProject ?
|
|
6657
|
-
if (index === null && sameProject) return { profile:
|
|
6907
|
+
const index = await client.index(sameProject ? cached3.version : void 0);
|
|
6908
|
+
if (index === null && sameProject) return { profile: cached3, source: "live" };
|
|
6658
6909
|
if (index === null) throw new Error("profile API answered 304 with no usable cached copy");
|
|
6659
6910
|
const has2 = (kind, name) => index.assets.some((a) => a.kind === kind && a.name === name);
|
|
6660
6911
|
const chosen = projectKeys.find((k2) => has2("memory", `${k2}.index`)) ?? null;
|
|
@@ -6676,8 +6927,8 @@ async function loadProfile(opts) {
|
|
|
6676
6927
|
return { profile, source: "live", ...cacheError ? { error: cacheError } : {} };
|
|
6677
6928
|
} catch (err) {
|
|
6678
6929
|
const error = `${err instanceof Error ? err.message : String(err)}${cacheError ? `; ${cacheError}` : ""}`;
|
|
6679
|
-
if (!
|
|
6680
|
-
return { profile: sameProject ?
|
|
6930
|
+
if (!cached3) return { profile: null, source: "none", error };
|
|
6931
|
+
return { profile: sameProject ? cached3 : { ...cached3, memoryIndex: null, projectKey: null }, source: "cache", error };
|
|
6681
6932
|
}
|
|
6682
6933
|
}
|
|
6683
6934
|
var init_profile_loader = __esm({
|
|
@@ -9188,11 +9439,11 @@ var init_base = __esm({
|
|
|
9188
9439
|
}
|
|
9189
9440
|
const parts = os.release().split(".");
|
|
9190
9441
|
const major = Number(parts[0]);
|
|
9191
|
-
const
|
|
9442
|
+
const build2 = Number(parts[2] ?? 0);
|
|
9192
9443
|
if (major < 10) {
|
|
9193
9444
|
return true;
|
|
9194
9445
|
}
|
|
9195
|
-
if (major === 10 &&
|
|
9446
|
+
if (major === 10 && build2 < 10586) {
|
|
9196
9447
|
return true;
|
|
9197
9448
|
}
|
|
9198
9449
|
return false;
|
|
@@ -9380,7 +9631,7 @@ var require_signal_exit = __commonJS({
|
|
|
9380
9631
|
}
|
|
9381
9632
|
assert.equal(typeof cb, "function", "a callback must be provided for exit handler");
|
|
9382
9633
|
if (loaded === false) {
|
|
9383
|
-
|
|
9634
|
+
load2();
|
|
9384
9635
|
}
|
|
9385
9636
|
var ev = "exit";
|
|
9386
9637
|
if (opts && opts.alwaysLast) {
|
|
@@ -9440,7 +9691,7 @@ var require_signal_exit = __commonJS({
|
|
|
9440
9691
|
return signals;
|
|
9441
9692
|
};
|
|
9442
9693
|
loaded = false;
|
|
9443
|
-
|
|
9694
|
+
load2 = function load3() {
|
|
9444
9695
|
if (loaded || !processOk(global.process)) {
|
|
9445
9696
|
return;
|
|
9446
9697
|
}
|
|
@@ -9457,7 +9708,7 @@ var require_signal_exit = __commonJS({
|
|
|
9457
9708
|
process13.emit = processEmit;
|
|
9458
9709
|
process13.reallyExit = processReallyExit;
|
|
9459
9710
|
};
|
|
9460
|
-
module.exports.load =
|
|
9711
|
+
module.exports.load = load2;
|
|
9461
9712
|
originalProcessReallyExit = process13.reallyExit;
|
|
9462
9713
|
processReallyExit = function processReallyExit2(code) {
|
|
9463
9714
|
if (!processOk(global.process)) {
|
|
@@ -9493,7 +9744,7 @@ var require_signal_exit = __commonJS({
|
|
|
9493
9744
|
var emit;
|
|
9494
9745
|
var sigListeners;
|
|
9495
9746
|
var loaded;
|
|
9496
|
-
var
|
|
9747
|
+
var load2;
|
|
9497
9748
|
var originalProcessReallyExit;
|
|
9498
9749
|
var processReallyExit;
|
|
9499
9750
|
var originalProcessEmit;
|
|
@@ -42998,7 +43249,7 @@ var require_colors = __commonJS({
|
|
|
42998
43249
|
}
|
|
42999
43250
|
return str.replace(matchOperatorsRe, "\\$&");
|
|
43000
43251
|
};
|
|
43001
|
-
function
|
|
43252
|
+
function build2(_styles) {
|
|
43002
43253
|
var builder = function builder2() {
|
|
43003
43254
|
return applyStyle2.apply(builder2, arguments);
|
|
43004
43255
|
};
|
|
@@ -43013,7 +43264,7 @@ var require_colors = __commonJS({
|
|
|
43013
43264
|
ansiStyles3[key].closeRe = new RegExp(escapeStringRegexp(ansiStyles3[key].close), "g");
|
|
43014
43265
|
ret[key] = {
|
|
43015
43266
|
get: function() {
|
|
43016
|
-
return
|
|
43267
|
+
return build2(this._styles.concat(key));
|
|
43017
43268
|
}
|
|
43018
43269
|
};
|
|
43019
43270
|
});
|
|
@@ -43072,7 +43323,7 @@ var require_colors = __commonJS({
|
|
|
43072
43323
|
Object.keys(styles5).forEach(function(name) {
|
|
43073
43324
|
ret[name] = {
|
|
43074
43325
|
get: function() {
|
|
43075
|
-
return
|
|
43326
|
+
return build2([name]);
|
|
43076
43327
|
}
|
|
43077
43328
|
};
|
|
43078
43329
|
});
|
|
@@ -44076,7 +44327,7 @@ var require_core = __commonJS({
|
|
|
44076
44327
|
return match && match.index === 0;
|
|
44077
44328
|
}
|
|
44078
44329
|
var BACKREF_RE = /\[(?:[^\\\]]|\\.)*\]|\(\??|\\([1-9][0-9]*)|\\./;
|
|
44079
|
-
function
|
|
44330
|
+
function join14(regexps, separator = "|") {
|
|
44080
44331
|
let numCaptures = 0;
|
|
44081
44332
|
return regexps.map((regex2) => {
|
|
44082
44333
|
numCaptures += 1;
|
|
@@ -44380,7 +44631,7 @@ var require_core = __commonJS({
|
|
|
44380
44631
|
this.exec = () => null;
|
|
44381
44632
|
}
|
|
44382
44633
|
const terminators = this.regexes.map((el) => el[1]);
|
|
44383
|
-
this.matcherRe = langRe(
|
|
44634
|
+
this.matcherRe = langRe(join14(terminators), true);
|
|
44384
44635
|
this.lastIndex = 0;
|
|
44385
44636
|
}
|
|
44386
44637
|
/** @param {string} s */
|
|
@@ -48157,7 +48408,7 @@ var require_bash = __commonJS({
|
|
|
48157
48408
|
return joined;
|
|
48158
48409
|
}
|
|
48159
48410
|
function bash(hljs) {
|
|
48160
|
-
const
|
|
48411
|
+
const VAR2 = {};
|
|
48161
48412
|
const BRACED_VAR = {
|
|
48162
48413
|
begin: /\$\{/,
|
|
48163
48414
|
end: /\}/,
|
|
@@ -48165,12 +48416,12 @@ var require_bash = __commonJS({
|
|
|
48165
48416
|
"self",
|
|
48166
48417
|
{
|
|
48167
48418
|
begin: /:-/,
|
|
48168
|
-
contains: [
|
|
48419
|
+
contains: [VAR2]
|
|
48169
48420
|
}
|
|
48170
48421
|
// default values
|
|
48171
48422
|
]
|
|
48172
48423
|
};
|
|
48173
|
-
Object.assign(
|
|
48424
|
+
Object.assign(VAR2, {
|
|
48174
48425
|
className: "variable",
|
|
48175
48426
|
variants: [
|
|
48176
48427
|
{ begin: concat(
|
|
@@ -48206,7 +48457,7 @@ var require_bash = __commonJS({
|
|
|
48206
48457
|
end: /"/,
|
|
48207
48458
|
contains: [
|
|
48208
48459
|
hljs.BACKSLASH_ESCAPE,
|
|
48209
|
-
|
|
48460
|
+
VAR2,
|
|
48210
48461
|
SUBST
|
|
48211
48462
|
]
|
|
48212
48463
|
};
|
|
@@ -48226,7 +48477,7 @@ var require_bash = __commonJS({
|
|
|
48226
48477
|
contains: [
|
|
48227
48478
|
{ begin: /\d+#[0-9a-f]+/, className: "number" },
|
|
48228
48479
|
hljs.NUMBER_MODE,
|
|
48229
|
-
|
|
48480
|
+
VAR2
|
|
48230
48481
|
]
|
|
48231
48482
|
};
|
|
48232
48483
|
const SH_LIKE_SHELLS = [
|
|
@@ -48276,7 +48527,7 @@ var require_bash = __commonJS({
|
|
|
48276
48527
|
QUOTE_STRING,
|
|
48277
48528
|
ESCAPED_QUOTE,
|
|
48278
48529
|
APOS_STRING,
|
|
48279
|
-
|
|
48530
|
+
VAR2
|
|
48280
48531
|
]
|
|
48281
48532
|
};
|
|
48282
48533
|
}
|
|
@@ -67899,7 +68150,7 @@ var require_perl = __commonJS({
|
|
|
67899
68150
|
end: /\}/
|
|
67900
68151
|
// contains defined later
|
|
67901
68152
|
};
|
|
67902
|
-
const
|
|
68153
|
+
const VAR2 = {
|
|
67903
68154
|
variants: [
|
|
67904
68155
|
{
|
|
67905
68156
|
begin: /\$\d/
|
|
@@ -67921,7 +68172,7 @@ var require_perl = __commonJS({
|
|
|
67921
68172
|
const STRING_CONTAINS = [
|
|
67922
68173
|
hljs.BACKSLASH_ESCAPE,
|
|
67923
68174
|
SUBST,
|
|
67924
|
-
|
|
68175
|
+
VAR2
|
|
67925
68176
|
];
|
|
67926
68177
|
const REGEX_DELIMS = [
|
|
67927
68178
|
/!/,
|
|
@@ -67956,7 +68207,7 @@ var require_perl = __commonJS({
|
|
|
67956
68207
|
);
|
|
67957
68208
|
};
|
|
67958
68209
|
const PERL_DEFAULT_CONTAINS = [
|
|
67959
|
-
|
|
68210
|
+
VAR2,
|
|
67960
68211
|
hljs.HASH_COMMENT_MODE,
|
|
67961
68212
|
hljs.COMMENT(
|
|
67962
68213
|
/^=\w/,
|
|
@@ -68423,7 +68674,7 @@ var require_n1ql = __commonJS({
|
|
|
68423
68674
|
var require_nginx = __commonJS({
|
|
68424
68675
|
"../../node_modules/highlight.js/lib/languages/nginx.js"(exports, module) {
|
|
68425
68676
|
function nginx(hljs) {
|
|
68426
|
-
const
|
|
68677
|
+
const VAR2 = {
|
|
68427
68678
|
className: "variable",
|
|
68428
68679
|
variants: [
|
|
68429
68680
|
{
|
|
@@ -68452,7 +68703,7 @@ var require_nginx = __commonJS({
|
|
|
68452
68703
|
className: "string",
|
|
68453
68704
|
contains: [
|
|
68454
68705
|
hljs.BACKSLASH_ESCAPE,
|
|
68455
|
-
|
|
68706
|
+
VAR2
|
|
68456
68707
|
],
|
|
68457
68708
|
variants: [
|
|
68458
68709
|
{
|
|
@@ -68471,13 +68722,13 @@ var require_nginx = __commonJS({
|
|
|
68471
68722
|
end: "\\s",
|
|
68472
68723
|
endsWithParent: true,
|
|
68473
68724
|
excludeEnd: true,
|
|
68474
|
-
contains: [
|
|
68725
|
+
contains: [VAR2]
|
|
68475
68726
|
},
|
|
68476
68727
|
{
|
|
68477
68728
|
className: "regexp",
|
|
68478
68729
|
contains: [
|
|
68479
68730
|
hljs.BACKSLASH_ESCAPE,
|
|
68480
|
-
|
|
68731
|
+
VAR2
|
|
68481
68732
|
],
|
|
68482
68733
|
variants: [
|
|
68483
68734
|
{
|
|
@@ -68512,7 +68763,7 @@ var require_nginx = __commonJS({
|
|
|
68512
68763
|
begin: "\\b\\d+[kKmMgGdshdwy]*\\b",
|
|
68513
68764
|
relevance: 0
|
|
68514
68765
|
},
|
|
68515
|
-
|
|
68766
|
+
VAR2
|
|
68516
68767
|
]
|
|
68517
68768
|
};
|
|
68518
68769
|
return {
|
|
@@ -69978,7 +70229,7 @@ var require_powershell = __commonJS({
|
|
|
69978
70229
|
begin: "`[\\s\\S]",
|
|
69979
70230
|
relevance: 0
|
|
69980
70231
|
};
|
|
69981
|
-
const
|
|
70232
|
+
const VAR2 = {
|
|
69982
70233
|
className: "variable",
|
|
69983
70234
|
variants: [
|
|
69984
70235
|
{
|
|
@@ -70011,7 +70262,7 @@ var require_powershell = __commonJS({
|
|
|
70011
70262
|
],
|
|
70012
70263
|
contains: [
|
|
70013
70264
|
BACKTICK_ESCAPE,
|
|
70014
|
-
|
|
70265
|
+
VAR2,
|
|
70015
70266
|
{
|
|
70016
70267
|
className: "variable",
|
|
70017
70268
|
begin: /\$[A-z]/,
|
|
@@ -70102,7 +70353,7 @@ var require_powershell = __commonJS({
|
|
|
70102
70353
|
end: /\)/,
|
|
70103
70354
|
className: "params",
|
|
70104
70355
|
relevance: 0,
|
|
70105
|
-
contains: [
|
|
70356
|
+
contains: [VAR2]
|
|
70106
70357
|
}
|
|
70107
70358
|
// CMDLETS
|
|
70108
70359
|
]
|
|
@@ -70173,7 +70424,7 @@ var require_powershell = __commonJS({
|
|
|
70173
70424
|
APOS_STRING,
|
|
70174
70425
|
// PS_NEW_OBJECT_TYPE,
|
|
70175
70426
|
CMDLETS,
|
|
70176
|
-
|
|
70427
|
+
VAR2,
|
|
70177
70428
|
LITERAL,
|
|
70178
70429
|
HASH_SIGNS
|
|
70179
70430
|
];
|
|
@@ -70295,7 +70546,7 @@ var require_prolog = __commonJS({
|
|
|
70295
70546
|
begin: /[a-z][A-Za-z0-9_]*/,
|
|
70296
70547
|
relevance: 0
|
|
70297
70548
|
};
|
|
70298
|
-
const
|
|
70549
|
+
const VAR2 = {
|
|
70299
70550
|
className: "symbol",
|
|
70300
70551
|
variants: [
|
|
70301
70552
|
{
|
|
@@ -70344,7 +70595,7 @@ var require_prolog = __commonJS({
|
|
|
70344
70595
|
};
|
|
70345
70596
|
const inner = [
|
|
70346
70597
|
ATOM,
|
|
70347
|
-
|
|
70598
|
+
VAR2,
|
|
70348
70599
|
PARENTED,
|
|
70349
70600
|
PRED_OP,
|
|
70350
70601
|
LIST,
|
|
@@ -71889,7 +72140,7 @@ var require_routeros = __commonJS({
|
|
|
71889
72140
|
const COMMON_COMMANDS = "add remove enable disable set get print export edit find run debug error info warning";
|
|
71890
72141
|
const LITERALS = "true false yes no nothing nil null";
|
|
71891
72142
|
const OBJECTS = "traffic-flow traffic-generator firewall scheduler aaa accounting address-list address align area bandwidth-server bfd bgp bridge client clock community config connection console customer default dhcp-client dhcp-server discovery dns e-mail ethernet filter firmware gps graphing group hardware health hotspot identity igmp-proxy incoming instance interface ip ipsec ipv6 irq l2tp-server lcd ldp logging mac-server mac-winbox mangle manual mirror mme mpls nat nd neighbor network note ntp ospf ospf-v3 ovpn-server page peer pim ping policy pool port ppp pppoe-client pptp-server prefix profile proposal proxy queue radius resource rip ripng route routing screen script security-profiles server service service-port settings shares smb sms sniffer snmp snooper socks sstp-server system tool tracking type upgrade upnp user-manager users user vlan secret vrrp watchdog web-access wireless pptp pppoe lan wan layer7-protocol lease simple raw";
|
|
71892
|
-
const
|
|
72143
|
+
const VAR2 = {
|
|
71893
72144
|
className: "variable",
|
|
71894
72145
|
variants: [
|
|
71895
72146
|
{
|
|
@@ -71906,7 +72157,7 @@ var require_routeros = __commonJS({
|
|
|
71906
72157
|
end: /"/,
|
|
71907
72158
|
contains: [
|
|
71908
72159
|
hljs.BACKSLASH_ESCAPE,
|
|
71909
|
-
|
|
72160
|
+
VAR2,
|
|
71910
72161
|
{
|
|
71911
72162
|
className: "variable",
|
|
71912
72163
|
begin: /\$\(/,
|
|
@@ -71956,7 +72207,7 @@ var require_routeros = __commonJS({
|
|
|
71956
72207
|
hljs.COMMENT("^#", "$"),
|
|
71957
72208
|
QUOTE_STRING,
|
|
71958
72209
|
APOS_STRING,
|
|
71959
|
-
|
|
72210
|
+
VAR2,
|
|
71960
72211
|
// attribute=value
|
|
71961
72212
|
{
|
|
71962
72213
|
// > is to avoid matches with => in other grammars
|
|
@@ -71975,7 +72226,7 @@ var require_routeros = __commonJS({
|
|
|
71975
72226
|
contains: [
|
|
71976
72227
|
QUOTE_STRING,
|
|
71977
72228
|
APOS_STRING,
|
|
71978
|
-
|
|
72229
|
+
VAR2,
|
|
71979
72230
|
{
|
|
71980
72231
|
className: "literal",
|
|
71981
72232
|
begin: "\\b(" + LITERALS.split(" ").join("|") + ")\\b"
|
|
@@ -78257,7 +78508,7 @@ var require_xquery = __commonJS({
|
|
|
78257
78508
|
begin: /\bxquery version "[13]\.[01]"\s?(?:encoding ".+")?/,
|
|
78258
78509
|
end: /;/
|
|
78259
78510
|
};
|
|
78260
|
-
const
|
|
78511
|
+
const VAR2 = {
|
|
78261
78512
|
className: "variable",
|
|
78262
78513
|
begin: /[$][\w\-:]+/
|
|
78263
78514
|
};
|
|
@@ -78326,7 +78577,7 @@ var require_xquery = __commonJS({
|
|
|
78326
78577
|
]
|
|
78327
78578
|
};
|
|
78328
78579
|
const CONTAINS = [
|
|
78329
|
-
|
|
78580
|
+
VAR2,
|
|
78330
78581
|
BUILT_IN,
|
|
78331
78582
|
STRING,
|
|
78332
78583
|
NUMBER,
|
|
@@ -103698,6 +103949,9 @@ var init_local_toolset = __esm({
|
|
|
103698
103949
|
import { execFile as execFile3 } from "node:child_process";
|
|
103699
103950
|
import { readdir as readdir3, readFile as readFile4 } from "node:fs/promises";
|
|
103700
103951
|
import { join as join7 } from "node:path";
|
|
103952
|
+
function digestLines(md) {
|
|
103953
|
+
return md.split("\n").map((l) => l.trim()).filter((l) => l && !/^#\s/.test(l) && !/^[|\s:-]+$/.test(l) && !/^\|\s*(area|task|priority|date|issue|id)\b/i.test(l)).slice(0, 12);
|
|
103954
|
+
}
|
|
103701
103955
|
function firstHeading(md) {
|
|
103702
103956
|
for (const line of md.split("\n", 40)) {
|
|
103703
103957
|
const m2 = /^#{1,3}\s+(.+?)\s*$/.exec(line);
|
|
@@ -103755,10 +104009,19 @@ async function scanProject(cwd2, io = nodeScanIo) {
|
|
|
103755
104009
|
const title = text ? firstHeading(text) : null;
|
|
103756
104010
|
if (title) docs.push({ path: e.path, title });
|
|
103757
104011
|
}
|
|
104012
|
+
const digests = [];
|
|
104013
|
+
for (const name of DIGEST_FILES.filter((n) => topLevel.some((t) => t.path === n))) {
|
|
104014
|
+
const text = await attempt(`read ${name}`, () => io.readFile(join7(cwd2, name)), null);
|
|
104015
|
+
const lines2 = text ? digestLines(text) : [];
|
|
104016
|
+
if (lines2.length) digests.push({ path: name, lines: lines2 });
|
|
104017
|
+
}
|
|
103758
104018
|
const todo = await attempt("read TODO.md", () => io.readFile(join7(cwd2, "TODO.md")), null);
|
|
103759
104019
|
const log = await io.git(cwd2, ["log", "--oneline", "-8"]);
|
|
103760
104020
|
const status = await io.git(cwd2, ["status", "--porcelain"]);
|
|
103761
104021
|
const branch = await io.git(cwd2, ["rev-parse", "--abbrev-ref", "HEAD"]);
|
|
104022
|
+
const onBranch = branch?.trim();
|
|
104023
|
+
const vsMainRaw = onBranch && onBranch !== "main" && onBranch !== "HEAD" ? await io.git(cwd2, ["diff", "--shortstat", "main...HEAD"]) : null;
|
|
104024
|
+
const vsMain = vsMainRaw?.trim() ? `${vsMainRaw.trim()} (branch ${onBranch})` : void 0;
|
|
103762
104025
|
return {
|
|
103763
104026
|
problems,
|
|
103764
104027
|
input: {
|
|
@@ -103770,17 +104033,20 @@ async function scanProject(cwd2, io = nodeScanIo) {
|
|
|
103770
104033
|
childDirs,
|
|
103771
104034
|
recentCommits: (log ?? "").split("\n").filter(Boolean),
|
|
103772
104035
|
docs,
|
|
103773
|
-
backlog: todo ? backlogLines(todo) : []
|
|
104036
|
+
backlog: todo ? backlogLines(todo) : [],
|
|
104037
|
+
changes: { files: (status ?? "").split("\n").filter(Boolean), ...vsMain ? { vsMain } : {} },
|
|
104038
|
+
digests
|
|
103774
104039
|
}
|
|
103775
104040
|
};
|
|
103776
104041
|
}
|
|
103777
|
-
var SKIP, MAX_DOCS, MAX_BACKLOG, nodeScanIo;
|
|
104042
|
+
var SKIP, MAX_DOCS, MAX_BACKLOG, DIGEST_FILES, nodeScanIo;
|
|
103778
104043
|
var init_project_card_scan = __esm({
|
|
103779
104044
|
"src/project-card-scan.ts"() {
|
|
103780
104045
|
"use strict";
|
|
103781
104046
|
SKIP = /* @__PURE__ */ new Set(["node_modules", ".git", "dist", "build", ".next", ".wrangler", ".turbo", "coverage", ".worktrees", ".superpowers", ".remember"]);
|
|
103782
104047
|
MAX_DOCS = 15;
|
|
103783
104048
|
MAX_BACKLOG = 6;
|
|
104049
|
+
DIGEST_FILES = ["CLAUDE.md", "TODO.md", "BUGS.md", "ISSUES.md", "CHANGELOG.md", "README.md"];
|
|
103784
104050
|
nodeScanIo = {
|
|
103785
104051
|
async readdir(path12) {
|
|
103786
104052
|
const entries = await readdir3(path12, { withFileTypes: true });
|
|
@@ -103802,25 +104068,27 @@ var init_project_card_scan = __esm({
|
|
|
103802
104068
|
});
|
|
103803
104069
|
|
|
103804
104070
|
// src/project-card-runtime.ts
|
|
103805
|
-
async function
|
|
103806
|
-
const env3 = deps.env ?? process.env;
|
|
103807
|
-
const now = deps.now ?? Date.now;
|
|
103808
|
-
if (env3.SPACECODE_PROJECT_CARD === "off") return { text: "", statusLine: "project card: disabled (SPACECODE_PROJECT_CARD=off)" };
|
|
103809
|
-
if (cached && cached.cwd === cwd2 && now() - cached.at < TTL_MS) return cached.state;
|
|
103810
|
-
let state;
|
|
104071
|
+
async function build(cwd2, io) {
|
|
103811
104072
|
try {
|
|
103812
|
-
const { input, problems } = await scanProject(cwd2,
|
|
104073
|
+
const { input, problems } = await scanProject(cwd2, io);
|
|
103813
104074
|
const text = renderProjectCard(input);
|
|
103814
|
-
|
|
104075
|
+
return {
|
|
103815
104076
|
text,
|
|
103816
104077
|
statusLine: `project card: ${text.length} chars, ${input.topLevel.length} top-level entries${problems.length ? `, ${problems.length} scan problem(s): ${problems.join("; ")}` : ""}`
|
|
103817
104078
|
};
|
|
103818
104079
|
} catch (err) {
|
|
103819
104080
|
console.error("[project-card] scan failed; the REPL runs without a card", err instanceof Error ? err.message : String(err));
|
|
103820
|
-
|
|
104081
|
+
return { text: "", statusLine: `project card: not built (${err instanceof Error ? err.message : String(err)})` };
|
|
103821
104082
|
}
|
|
103822
|
-
|
|
103823
|
-
|
|
104083
|
+
}
|
|
104084
|
+
function loadProjectCard(cwd2, deps = {}) {
|
|
104085
|
+
const env3 = deps.env ?? process.env;
|
|
104086
|
+
const now = deps.now ?? Date.now;
|
|
104087
|
+
if (env3.SPACECODE_PROJECT_CARD === "off") return Promise.resolve({ text: "", statusLine: "project card: disabled (SPACECODE_PROJECT_CARD=off)" });
|
|
104088
|
+
if (cached && cached.cwd === cwd2 && now() - cached.at < TTL_MS) return cached.pending;
|
|
104089
|
+
const pending = build(cwd2, deps.io ?? nodeScanIo);
|
|
104090
|
+
cached = { cwd: cwd2, at: now(), pending };
|
|
104091
|
+
return pending;
|
|
103824
104092
|
}
|
|
103825
104093
|
var TTL_MS, cached;
|
|
103826
104094
|
var init_project_card_runtime = __esm({
|
|
@@ -103832,6 +104100,65 @@ var init_project_card_runtime = __esm({
|
|
|
103832
104100
|
}
|
|
103833
104101
|
});
|
|
103834
104102
|
|
|
104103
|
+
// src/prompt-runtime.ts
|
|
104104
|
+
import { join as join8 } from "node:path";
|
|
104105
|
+
async function load(deps) {
|
|
104106
|
+
if (deps.env.SPACECODE_PROMPTS === "off") return { templates: {}, statusLine: "prompts: built-in defaults (SPACECODE_PROMPTS=off)" };
|
|
104107
|
+
const dir = deps.env.SPACECODE_CONFIG_DIR?.trim() || join8(deps.homedir(), ".spacecode");
|
|
104108
|
+
const file = join8(dir, "prompts-cache.json");
|
|
104109
|
+
const fromDisk = async (why) => {
|
|
104110
|
+
try {
|
|
104111
|
+
const raw = JSON.parse(await deps.readFile(file));
|
|
104112
|
+
const templates = raw.templates ?? {};
|
|
104113
|
+
return { templates, statusLine: `prompts: ${Object.keys(templates).length} tuned (STALE: served from cache; ${why})` };
|
|
104114
|
+
} catch {
|
|
104115
|
+
return { templates: {}, statusLine: `prompts: built-in defaults (${why})` };
|
|
104116
|
+
}
|
|
104117
|
+
};
|
|
104118
|
+
let apiKey;
|
|
104119
|
+
try {
|
|
104120
|
+
apiKey = await resolveApiKey({ env: deps.env, readFile: deps.readFile, homedir: deps.homedir });
|
|
104121
|
+
} catch (err) {
|
|
104122
|
+
return fromDisk(err instanceof Error ? err.message : String(err));
|
|
104123
|
+
}
|
|
104124
|
+
if (!apiKey) return fromDisk("not signed in");
|
|
104125
|
+
try {
|
|
104126
|
+
const res = await deps.fetch(`${backendUrl(deps.env)}/api/prompts`, {
|
|
104127
|
+
headers: { Authorization: `Bearer ${apiKey}`, "x-api-key": apiKey },
|
|
104128
|
+
signal: AbortSignal.timeout(3e3)
|
|
104129
|
+
});
|
|
104130
|
+
if (!res.ok) return fromDisk(`prompt API returned ${res.status}`);
|
|
104131
|
+
const { prompts } = await res.json();
|
|
104132
|
+
const templates = Object.fromEntries(prompts.filter((p) => p.source === "db").map((p) => [p.key, p.body]));
|
|
104133
|
+
try {
|
|
104134
|
+
await deps.mkdir(dir);
|
|
104135
|
+
await deps.writeFile(file, JSON.stringify({ fetchedAt: new Date((deps.now ?? Date.now)()).toISOString(), templates }));
|
|
104136
|
+
} catch (err) {
|
|
104137
|
+
console.error("[prompts] could not write the prompt cache", err instanceof Error ? err.message : String(err));
|
|
104138
|
+
}
|
|
104139
|
+
const n = Object.keys(templates).length;
|
|
104140
|
+
return { templates, statusLine: n ? `prompts: ${n} tuned override(s): ${Object.keys(templates).join(", ")}` : "prompts: built-in defaults (none tuned)" };
|
|
104141
|
+
} catch (err) {
|
|
104142
|
+
return fromDisk(`fetch failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
104143
|
+
}
|
|
104144
|
+
}
|
|
104145
|
+
function loadPromptTemplates(deps) {
|
|
104146
|
+
const now = (deps.now ?? Date.now)();
|
|
104147
|
+
if (cached2 && now - cached2.at < TTL_MS2) return cached2.pending;
|
|
104148
|
+
const pending = load(deps);
|
|
104149
|
+
cached2 = { at: now, pending };
|
|
104150
|
+
return pending;
|
|
104151
|
+
}
|
|
104152
|
+
var TTL_MS2, cached2;
|
|
104153
|
+
var init_prompt_runtime = __esm({
|
|
104154
|
+
"src/prompt-runtime.ts"() {
|
|
104155
|
+
"use strict";
|
|
104156
|
+
init_api_key();
|
|
104157
|
+
init_profile_runtime();
|
|
104158
|
+
TTL_MS2 = 10 * 6e4;
|
|
104159
|
+
}
|
|
104160
|
+
});
|
|
104161
|
+
|
|
103835
104162
|
// src/shell-turn.ts
|
|
103836
104163
|
function shellCommandOf(prompt) {
|
|
103837
104164
|
return prompt.startsWith("!") ? prompt.slice(1).trim() : null;
|
|
@@ -104256,7 +104583,7 @@ var init_recording_chunks = __esm({
|
|
|
104256
104583
|
// src/recording/recorder.ts
|
|
104257
104584
|
import { createHash as createHash4 } from "node:crypto";
|
|
104258
104585
|
import { mkdir as mkdir4, readFile as readFile6, rename as rename4, rm as rm2, writeFile as writeFile4, readdir as readdir5, stat as stat3 } from "node:fs/promises";
|
|
104259
|
-
import { join as
|
|
104586
|
+
import { join as join9 } from "node:path";
|
|
104260
104587
|
function projectHash(root) {
|
|
104261
104588
|
return createHash4("sha256").update(root).digest("hex");
|
|
104262
104589
|
}
|
|
@@ -104267,24 +104594,24 @@ function createRecorder(deps) {
|
|
|
104267
104594
|
let inflight = null;
|
|
104268
104595
|
let retryAttempt = 0;
|
|
104269
104596
|
let timerArmed = false;
|
|
104270
|
-
const stateFile = (sessionId) =>
|
|
104597
|
+
const stateFile = (sessionId) => join9(deps.dir, `${sessionId}.json`);
|
|
104271
104598
|
async function save(sessionId, st) {
|
|
104272
104599
|
await mkdir4(deps.dir, { recursive: true, mode: 448 });
|
|
104273
104600
|
const tmp = `${stateFile(sessionId)}.${deps.randomId()}.tmp`;
|
|
104274
104601
|
await writeFile4(tmp, JSON.stringify(st), { mode: 384 });
|
|
104275
104602
|
await rename4(tmp, stateFile(sessionId));
|
|
104276
104603
|
}
|
|
104277
|
-
async function
|
|
104278
|
-
const
|
|
104279
|
-
if (
|
|
104604
|
+
async function load2(sessionId) {
|
|
104605
|
+
const cached3 = states.get(sessionId);
|
|
104606
|
+
if (cached3) return cached3;
|
|
104280
104607
|
let st;
|
|
104281
104608
|
try {
|
|
104282
104609
|
st = JSON.parse(await readFile6(stateFile(sessionId), "utf8"));
|
|
104283
104610
|
} catch (e) {
|
|
104284
104611
|
if (e.code !== "ENOENT") {
|
|
104285
|
-
const bad =
|
|
104612
|
+
const bad = join9(deps.dir, "bad");
|
|
104286
104613
|
await mkdir4(bad, { recursive: true, mode: 448 });
|
|
104287
|
-
await rename4(stateFile(sessionId),
|
|
104614
|
+
await rename4(stateFile(sessionId), join9(bad, `${sessionId}.${deps.now()}.json`)).catch((err) => deps.log(`recording: could not quarantine ${sessionId}: ${String(err)}`));
|
|
104288
104615
|
lastError = `recording state for ${sessionId} was unreadable and was quarantined`;
|
|
104289
104616
|
deps.log(`recording: ${lastError}`);
|
|
104290
104617
|
}
|
|
@@ -104301,7 +104628,7 @@ function createRecorder(deps) {
|
|
|
104301
104628
|
async function record(sessionId, messages, meta) {
|
|
104302
104629
|
try {
|
|
104303
104630
|
if (off2) return;
|
|
104304
|
-
const st = await
|
|
104631
|
+
const st = await load2(sessionId);
|
|
104305
104632
|
if (st.stopped) return;
|
|
104306
104633
|
if (st.hashes.length === 0 && st.nextSeq === 1 && meta.parentRecordingId) st.parentRecordingId = meta.parentRecordingId;
|
|
104307
104634
|
st.meta = meta;
|
|
@@ -104454,7 +104781,7 @@ function createRecorder(deps) {
|
|
|
104454
104781
|
for (const n of names) {
|
|
104455
104782
|
if (!n.endsWith(".json")) continue;
|
|
104456
104783
|
const id = n.slice(0, -5);
|
|
104457
|
-
const st = await
|
|
104784
|
+
const st = await load2(id);
|
|
104458
104785
|
if (st.queue.length === 0) states.delete(id);
|
|
104459
104786
|
}
|
|
104460
104787
|
if ([...states.values()].some((s) => s.queue.length > 0)) void flush();
|
|
@@ -104475,7 +104802,7 @@ var init_recorder = __esm({
|
|
|
104475
104802
|
|
|
104476
104803
|
// src/recording/recording-runtime.ts
|
|
104477
104804
|
import { mkdir as mkdir5, readFile as readFile7, writeFile as writeFile5, stat as stat4 } from "node:fs/promises";
|
|
104478
|
-
import { join as
|
|
104805
|
+
import { join as join10, sep as sep2 } from "node:path";
|
|
104479
104806
|
function matchesExclude(pattern, root) {
|
|
104480
104807
|
const re3 = pattern.replace(/[.+^${}()|[\]\\]/g, "\\$&").replace(/\*\*/g, "\0").replace(/\*/g, `[^${sep2 === "\\" ? "\\\\" : "/"}]*`).replace(/\u0000/g, ".*");
|
|
104481
104808
|
return new RegExp(`^${re3}(?:[/\\\\].*)?$`).test(root);
|
|
@@ -104490,8 +104817,8 @@ async function exists(path12) {
|
|
|
104490
104817
|
}
|
|
104491
104818
|
}
|
|
104492
104819
|
function createRecordingRuntime(deps) {
|
|
104493
|
-
const dir =
|
|
104494
|
-
const noticeFile =
|
|
104820
|
+
const dir = join10(deps.configDir, "recordings");
|
|
104821
|
+
const noticeFile = join10(dir, ".notice");
|
|
104495
104822
|
let recorder = null;
|
|
104496
104823
|
let standingOff;
|
|
104497
104824
|
let sessionOff = false;
|
|
@@ -104499,7 +104826,7 @@ function createRecordingRuntime(deps) {
|
|
|
104499
104826
|
if (deps.env.SPACECODE_RECORD?.trim().toLowerCase() === "off") return "SPACECODE_RECORD=off";
|
|
104500
104827
|
let cfg = {};
|
|
104501
104828
|
try {
|
|
104502
|
-
cfg = JSON.parse(await readFile7(
|
|
104829
|
+
cfg = JSON.parse(await readFile7(join10(deps.configDir, "config.json"), "utf8"));
|
|
104503
104830
|
} catch (e) {
|
|
104504
104831
|
if (e.code !== "ENOENT") return `~/.spacecode/config.json is unreadable (${e instanceof Error ? e.message : String(e)}); fix it to record`;
|
|
104505
104832
|
}
|
|
@@ -104507,7 +104834,7 @@ function createRecordingRuntime(deps) {
|
|
|
104507
104834
|
const excludes = Array.isArray(cfg.recording?.exclude) ? cfg.recording.exclude.filter((x2) => typeof x2 === "string") : [];
|
|
104508
104835
|
const hit = excludes.find((p) => matchesExclude(p, deps.projectRoot));
|
|
104509
104836
|
if (hit) return `this folder matches recording.exclude (${hit})`;
|
|
104510
|
-
if (await exists(
|
|
104837
|
+
if (await exists(join10(deps.projectRoot, ".spacecode", "norecord"))) return "this repo has .spacecode/norecord";
|
|
104511
104838
|
return null;
|
|
104512
104839
|
}
|
|
104513
104840
|
async function noticeShown() {
|
|
@@ -104649,7 +104976,7 @@ var init_skills_command = __esm({
|
|
|
104649
104976
|
|
|
104650
104977
|
// src/permission-rules-loader.ts
|
|
104651
104978
|
import { readFile as readFile8 } from "node:fs/promises";
|
|
104652
|
-
import { join as
|
|
104979
|
+
import { join as join11 } from "node:path";
|
|
104653
104980
|
async function readOrNull2(path12) {
|
|
104654
104981
|
try {
|
|
104655
104982
|
return await readFile8(path12, "utf8");
|
|
@@ -104660,7 +104987,7 @@ async function readOrNull2(path12) {
|
|
|
104660
104987
|
}
|
|
104661
104988
|
async function loadPermissionRules(deps) {
|
|
104662
104989
|
const none = (line) => ({ rules: void 0, defaultMode: void 0, statusLines: [line] });
|
|
104663
|
-
const configPath =
|
|
104990
|
+
const configPath = join11(deps.configDir, "imports.json");
|
|
104664
104991
|
try {
|
|
104665
104992
|
const loaded = parseImportsConfig(await readOrNull2(configPath), configPath);
|
|
104666
104993
|
if (loaded.error) return none("permission rules: off (imports.json unreadable)");
|
|
@@ -104669,13 +104996,13 @@ async function loadPermissionRules(deps) {
|
|
|
104669
104996
|
return none(`permission rules: off (imports.json not read: ${err instanceof Error ? err.message : String(err)})`);
|
|
104670
104997
|
}
|
|
104671
104998
|
const lines2 = [];
|
|
104672
|
-
const files = [{ scope: "user", path:
|
|
104999
|
+
const files = [{ scope: "user", path: join11(deps.homeDir, ".claude", "settings.json") }];
|
|
104673
105000
|
try {
|
|
104674
105001
|
const sources2 = await readRepoSources(deps.cwd);
|
|
104675
105002
|
if (sources2[".claude/settings.json"] !== void 0 || sources2[".claude/settings.local.json"] !== void 0) {
|
|
104676
105003
|
const status = await createNodeTrustStore(deps.configDir).repoStatus(deps.cwd, sources2);
|
|
104677
105004
|
if (status === "trusted" || status === "session") {
|
|
104678
|
-
files.push({ scope: "repo", path:
|
|
105005
|
+
files.push({ scope: "repo", path: join11(deps.cwd, ".claude", "settings.json") }, { scope: "local", path: join11(deps.cwd, ".claude", "settings.local.json") });
|
|
104679
105006
|
} else lines2.push(`permission rules: repo settings NOT loaded (${status === "never" ? "marked never trust" : "untrusted repo"})`);
|
|
104680
105007
|
}
|
|
104681
105008
|
} catch (err) {
|
|
@@ -104717,7 +105044,7 @@ var init_permission_rules_loader = __esm({
|
|
|
104717
105044
|
});
|
|
104718
105045
|
|
|
104719
105046
|
// src/command-loader.ts
|
|
104720
|
-
import { join as
|
|
105047
|
+
import { join as join12 } from "node:path";
|
|
104721
105048
|
async function userCommands(deps, lines2) {
|
|
104722
105049
|
try {
|
|
104723
105050
|
const apiKey = await resolveApiKey({ env: deps.env, readFile: deps.readFile, homedir: deps.homedir });
|
|
@@ -104772,7 +105099,7 @@ async function repoCommands(deps, lines2) {
|
|
|
104772
105099
|
}
|
|
104773
105100
|
}
|
|
104774
105101
|
async function loadCommands(deps) {
|
|
104775
|
-
const configPath =
|
|
105102
|
+
const configPath = join12(deps.configDir, "imports.json");
|
|
104776
105103
|
try {
|
|
104777
105104
|
const loaded = parseImportsConfig(await deps.readFile(configPath).catch((err) => {
|
|
104778
105105
|
if (err.code === "ENOENT") return null;
|
|
@@ -104807,7 +105134,7 @@ var init_command_loader = __esm({
|
|
|
104807
105134
|
// src/useReplController.ts
|
|
104808
105135
|
import { readFile as readFile9, writeFile as writeFile6, mkdir as mkdir6 } from "node:fs/promises";
|
|
104809
105136
|
import { homedir as homedir2 } from "node:os";
|
|
104810
|
-
import { join as
|
|
105137
|
+
import { join as join13 } from "node:path";
|
|
104811
105138
|
import { execFile as execFile4 } from "node:child_process";
|
|
104812
105139
|
function useReplController({ repoName: repoName2, yolo: yolo2, mentions: mentionsOpt, sessions, resumeLatest: resumeLatest2, onViewTurns, onViewResume, isEscOwned }) {
|
|
104813
105140
|
const { exit } = use_app_default();
|
|
@@ -104829,6 +105156,14 @@ function useReplController({ repoName: repoName2, yolo: yolo2, mentions: mention
|
|
|
104829
105156
|
return () => clearInterval(timer);
|
|
104830
105157
|
}, [turnStartedAt]);
|
|
104831
105158
|
const projectRoot = (0, import_react30.useMemo)(() => process.cwd(), []);
|
|
105159
|
+
const promptTemplates = (0, import_react30.useCallback)(
|
|
105160
|
+
() => loadPromptTemplates({ env: process.env, readFile: (p) => readFile9(p, "utf-8"), writeFile: (p, d) => writeFile6(p, d, "utf-8"), mkdir: (p) => mkdir6(p, { recursive: true }).then(() => void 0), homedir: homedir2, fetch }),
|
|
105161
|
+
[]
|
|
105162
|
+
);
|
|
105163
|
+
(0, import_react30.useEffect)(() => {
|
|
105164
|
+
void loadProjectCard(projectRoot);
|
|
105165
|
+
void promptTemplates();
|
|
105166
|
+
}, [projectRoot]);
|
|
104832
105167
|
const sessionIdRef = (0, import_react30.useRef)(null);
|
|
104833
105168
|
const sessionCreatedAtRef = (0, import_react30.useRef)(null);
|
|
104834
105169
|
const sessionTokensRef = (0, import_react30.useRef)({ input: 0, output: 0 });
|
|
@@ -104838,7 +105173,7 @@ function useReplController({ repoName: repoName2, yolo: yolo2, mentions: mention
|
|
|
104838
105173
|
const recordingRef = (0, import_react30.useRef)(null);
|
|
104839
105174
|
const recording = () => recordingRef.current ??= createRecordingRuntime({
|
|
104840
105175
|
env: process.env,
|
|
104841
|
-
configDir: process.env.SPACECODE_CONFIG_DIR?.trim() ||
|
|
105176
|
+
configDir: process.env.SPACECODE_CONFIG_DIR?.trim() || join13(homedir2(), ".spacecode"),
|
|
104842
105177
|
projectRoot,
|
|
104843
105178
|
fetch,
|
|
104844
105179
|
baseUrl: backendUrl(process.env),
|
|
@@ -104865,7 +105200,7 @@ function useReplController({ repoName: repoName2, yolo: yolo2, mentions: mention
|
|
|
104865
105200
|
(0, import_react30.useEffect)(() => {
|
|
104866
105201
|
let live2 = true;
|
|
104867
105202
|
loadCommands({
|
|
104868
|
-
configDir: process.env.SPACECODE_CONFIG_DIR?.trim() ||
|
|
105203
|
+
configDir: process.env.SPACECODE_CONFIG_DIR?.trim() || join13(homedir2(), ".spacecode"),
|
|
104869
105204
|
cwd: process.cwd(),
|
|
104870
105205
|
env: process.env,
|
|
104871
105206
|
readFile: (p) => readFile9(p, "utf-8"),
|
|
@@ -105162,7 +105497,7 @@ function useReplController({ repoName: repoName2, yolo: yolo2, mentions: mention
|
|
|
105162
105497
|
return;
|
|
105163
105498
|
}
|
|
105164
105499
|
notice("Compacting conversation\u2026");
|
|
105165
|
-
const summary = await summarizeConversation(history, { apiUrl: apiUrl(), apiKey: apiKey2 });
|
|
105500
|
+
const summary = await summarizeConversation(history, { apiUrl: apiUrl(), apiKey: apiKey2, templates: (await promptTemplates()).templates });
|
|
105166
105501
|
const compacted = buildCompactedHistory(summary.summaryText);
|
|
105167
105502
|
const before = estimateTotalTokens("", history);
|
|
105168
105503
|
const after = estimateTotalTokens("", compacted);
|
|
@@ -105282,7 +105617,7 @@ ${list2.map((c) => ` /${c.name} (${c.scope})${c.description ? ` ${c.descripti
|
|
|
105282
105617
|
cwd: process.cwd(),
|
|
105283
105618
|
gitRoot: gitTopLevel,
|
|
105284
105619
|
importGate: async () => {
|
|
105285
|
-
const configDir = process.env.SPACECODE_CONFIG_DIR?.trim() ||
|
|
105620
|
+
const configDir = process.env.SPACECODE_CONFIG_DIR?.trim() || join13(homedir2(), ".spacecode");
|
|
105286
105621
|
const gate = await importGateStatus({ configDir, cwd: process.cwd(), interactive: Boolean(process.stdin.isTTY) });
|
|
105287
105622
|
const loaded = await loadPermissionRules({ configDir, homeDir: homedir2(), cwd: process.cwd() });
|
|
105288
105623
|
rulesRef.current = loaded.rules;
|
|
@@ -105292,7 +105627,7 @@ ${list2.map((c) => ` /${c.name} (${c.scope})${c.description ? ` ${c.descripti
|
|
|
105292
105627
|
});
|
|
105293
105628
|
profileRef.current = await profilePromiseRef.current;
|
|
105294
105629
|
if (mcpRef.current === null && (profileRef.current?.mcpDefs?.length ?? 0) > 0) {
|
|
105295
|
-
const configDir = process.env.SPACECODE_CONFIG_DIR?.trim() ||
|
|
105630
|
+
const configDir = process.env.SPACECODE_CONFIG_DIR?.trim() || join13(homedir2(), ".spacecode");
|
|
105296
105631
|
const trust = createNodeTrustStore(configDir);
|
|
105297
105632
|
const manager = new McpManager({
|
|
105298
105633
|
defs: profileRef.current.mcpDefs,
|
|
@@ -105302,7 +105637,7 @@ ${list2.map((c) => ` /${c.name} (${c.scope})${c.description ? ` ${c.descripti
|
|
|
105302
105637
|
...rulesRef.current ? { rules: rulesRef.current } : {},
|
|
105303
105638
|
permissions,
|
|
105304
105639
|
confirm: askUser,
|
|
105305
|
-
audit: new FileAuditLog(
|
|
105640
|
+
audit: new FileAuditLog(join13(homedir2(), ".spacecode", "audit.jsonl")),
|
|
105306
105641
|
clientVersion: process.env.SPACECODE_VERSION ?? "0"
|
|
105307
105642
|
});
|
|
105308
105643
|
mcpRef.current = manager;
|
|
@@ -105311,6 +105646,7 @@ ${list2.map((c) => ` /${c.name} (${c.scope})${c.description ? ` ${c.descripti
|
|
|
105311
105646
|
const toolset = createToolset();
|
|
105312
105647
|
toolsetRef.current = toolset;
|
|
105313
105648
|
const projectCard = await loadProjectCard(projectRoot);
|
|
105649
|
+
const prompts = await promptTemplates();
|
|
105314
105650
|
const config = {
|
|
105315
105651
|
apiUrl: apiUrl(),
|
|
105316
105652
|
apiKey,
|
|
@@ -105320,7 +105656,8 @@ ${list2.map((c) => ` /${c.name} (${c.scope})${c.description ? ` ${c.descripti
|
|
|
105320
105656
|
localCwd: projectRoot,
|
|
105321
105657
|
commitGuidance: true,
|
|
105322
105658
|
hasGitHubTools: toolset.hasGitHubTools,
|
|
105323
|
-
...projectCard.text ? { projectCard: projectCard.text } : {}
|
|
105659
|
+
...projectCard.text ? { projectCard: projectCard.text } : {},
|
|
105660
|
+
templates: prompts.templates
|
|
105324
105661
|
}) + (profileRef.current?.promptSection ?? ""),
|
|
105325
105662
|
tools: toolset.tools,
|
|
105326
105663
|
maxTurns: 100,
|
|
@@ -105432,6 +105769,7 @@ var init_useReplController = __esm({
|
|
|
105432
105769
|
init_session_commands();
|
|
105433
105770
|
init_local_toolset();
|
|
105434
105771
|
init_project_card_runtime();
|
|
105772
|
+
init_prompt_runtime();
|
|
105435
105773
|
init_shell_turn();
|
|
105436
105774
|
init_node_mentions();
|
|
105437
105775
|
init_api_key();
|