spacecode 2.8.1 → 2.10.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 +2 -2
- package/dist/repl.mjs +537 -119
- 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
|
|
|
@@ -4096,9 +4340,9 @@ function createFileTools(store) {
|
|
|
4096
4340
|
const handlers = {
|
|
4097
4341
|
read_file: async (input) => {
|
|
4098
4342
|
const path12 = input.path;
|
|
4099
|
-
const
|
|
4100
|
-
if (
|
|
4101
|
-
return { output:
|
|
4343
|
+
const cached3 = readCache.get(path12);
|
|
4344
|
+
if (cached3 !== void 0) {
|
|
4345
|
+
return { output: cached3 };
|
|
4102
4346
|
}
|
|
4103
4347
|
const content = await store.readFile(path12);
|
|
4104
4348
|
if (content === null) {
|
|
@@ -4158,12 +4402,12 @@ Include more surrounding context to make old_string unique.`,
|
|
|
4158
4402
|
},
|
|
4159
4403
|
list_directory: async (input) => {
|
|
4160
4404
|
const path12 = input.path;
|
|
4161
|
-
const
|
|
4162
|
-
if (
|
|
4163
|
-
if (
|
|
4405
|
+
const cached3 = listCache.get(path12);
|
|
4406
|
+
if (cached3 !== void 0) {
|
|
4407
|
+
if (cached3.length === 0) {
|
|
4164
4408
|
return { output: `Empty or not found: ${path12}` };
|
|
4165
4409
|
}
|
|
4166
|
-
return { output:
|
|
4410
|
+
return { output: cached3.join("\n") };
|
|
4167
4411
|
}
|
|
4168
4412
|
const entries = await store.listDirectory(path12);
|
|
4169
4413
|
listCache.set(path12, entries);
|
|
@@ -5877,10 +6121,10 @@ async function summarizeConversation(messages, config) {
|
|
|
5877
6121
|
return { decisions: [], workItems: [], summaryText: "", inputTokens: 0, outputTokens: 0 };
|
|
5878
6122
|
}
|
|
5879
6123
|
const transcript = buildTranscriptForSummarization(messages, MAX_TRANSCRIPT_CHARS);
|
|
5880
|
-
const systemPrompt =
|
|
6124
|
+
const systemPrompt = config.templates?.["agent.summarizer.system"] ?? DEFAULT_PROMPTS["agent.summarizer.system"].body;
|
|
5881
6125
|
const userContent = `${transcript}
|
|
5882
6126
|
|
|
5883
|
-
|
|
6127
|
+
${config.templates?.["agent.summarizer.user_suffix"] ?? DEFAULT_PROMPTS["agent.summarizer.user_suffix"].body}`;
|
|
5884
6128
|
const response = await fetch(`${config.apiUrl}/v1/messages`, {
|
|
5885
6129
|
method: "POST",
|
|
5886
6130
|
headers: {
|
|
@@ -5974,6 +6218,7 @@ var DEFAULT_SUMMARIZER_MODEL, MAX_TRANSCRIPT_CHARS, MAX_TOKENS2;
|
|
|
5974
6218
|
var init_summarizer = __esm({
|
|
5975
6219
|
"../agent/src/summarizer.ts"() {
|
|
5976
6220
|
"use strict";
|
|
6221
|
+
init_prompts();
|
|
5977
6222
|
DEFAULT_SUMMARIZER_MODEL = "claude-haiku-4-5";
|
|
5978
6223
|
MAX_TRANSCRIPT_CHARS = 4e4;
|
|
5979
6224
|
MAX_TOKENS2 = 4096;
|
|
@@ -6650,17 +6895,17 @@ var init_memory_tool = __esm({
|
|
|
6650
6895
|
// ../agent/src/import/profile-loader.ts
|
|
6651
6896
|
async function loadProfile(opts) {
|
|
6652
6897
|
const { client, cache: cache4, projectKeys } = opts;
|
|
6653
|
-
let
|
|
6898
|
+
let cached3 = null;
|
|
6654
6899
|
let cacheError;
|
|
6655
6900
|
try {
|
|
6656
|
-
|
|
6901
|
+
cached3 = await cache4.read();
|
|
6657
6902
|
} catch (err) {
|
|
6658
6903
|
cacheError = `profile cache unreadable: ${err instanceof Error ? err.message : String(err)}`;
|
|
6659
6904
|
}
|
|
6660
|
-
const sameProject =
|
|
6905
|
+
const sameProject = cached3 !== null && cached3.projectKey !== null && projectKeys.includes(cached3.projectKey);
|
|
6661
6906
|
try {
|
|
6662
|
-
const index = await client.index(sameProject ?
|
|
6663
|
-
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" };
|
|
6664
6909
|
if (index === null) throw new Error("profile API answered 304 with no usable cached copy");
|
|
6665
6910
|
const has2 = (kind, name) => index.assets.some((a) => a.kind === kind && a.name === name);
|
|
6666
6911
|
const chosen = projectKeys.find((k2) => has2("memory", `${k2}.index`)) ?? null;
|
|
@@ -6682,8 +6927,8 @@ async function loadProfile(opts) {
|
|
|
6682
6927
|
return { profile, source: "live", ...cacheError ? { error: cacheError } : {} };
|
|
6683
6928
|
} catch (err) {
|
|
6684
6929
|
const error = `${err instanceof Error ? err.message : String(err)}${cacheError ? `; ${cacheError}` : ""}`;
|
|
6685
|
-
if (!
|
|
6686
|
-
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 };
|
|
6687
6932
|
}
|
|
6688
6933
|
}
|
|
6689
6934
|
var init_profile_loader = __esm({
|
|
@@ -7007,6 +7252,28 @@ var init_trust = __esm({
|
|
|
7007
7252
|
}
|
|
7008
7253
|
});
|
|
7009
7254
|
|
|
7255
|
+
// ../agent/src/import/source-changes.ts
|
|
7256
|
+
function fingerprintSources(files, hash) {
|
|
7257
|
+
const fingerprint = {};
|
|
7258
|
+
for (const [path12, content] of Object.entries(files)) fingerprint[path12] = hash(content);
|
|
7259
|
+
return fingerprint;
|
|
7260
|
+
}
|
|
7261
|
+
function diffSources(before, after) {
|
|
7262
|
+
const has2 = (o, k2) => Object.hasOwn(o, k2);
|
|
7263
|
+
const added = Object.keys(after).filter((k2) => !has2(before, k2)).sort();
|
|
7264
|
+
const removed = Object.keys(before).filter((k2) => !has2(after, k2)).sort();
|
|
7265
|
+
const modified = Object.keys(after).filter((k2) => has2(before, k2) && before[k2] !== after[k2]).sort();
|
|
7266
|
+
return { added, modified, removed, changed: added.length + modified.length + removed.length > 0 };
|
|
7267
|
+
}
|
|
7268
|
+
function formatSourceChanges(c) {
|
|
7269
|
+
return [...c.added.map((p) => `added: ${p}`), ...c.modified.map((p) => `modified: ${p}`), ...c.removed.map((p) => `removed: ${p}`)];
|
|
7270
|
+
}
|
|
7271
|
+
var init_source_changes = __esm({
|
|
7272
|
+
"../agent/src/import/source-changes.ts"() {
|
|
7273
|
+
"use strict";
|
|
7274
|
+
}
|
|
7275
|
+
});
|
|
7276
|
+
|
|
7010
7277
|
// ../agent/src/import/imports-config.ts
|
|
7011
7278
|
function allOffConfig() {
|
|
7012
7279
|
return {
|
|
@@ -7741,6 +8008,7 @@ __export(src_exports, {
|
|
|
7741
8008
|
createSkillTool: () => createSkillTool,
|
|
7742
8009
|
createTodoTool: () => createTodoTool,
|
|
7743
8010
|
defaultModeFor: () => defaultModeFor,
|
|
8011
|
+
diffSources: () => diffSources,
|
|
7744
8012
|
estimateTokens: () => estimateTokens,
|
|
7745
8013
|
estimateTotalTokens: () => estimateTotalTokens,
|
|
7746
8014
|
expandCommand: () => expandCommand,
|
|
@@ -7748,8 +8016,10 @@ __export(src_exports, {
|
|
|
7748
8016
|
expandServerEnv: () => expandServerEnv,
|
|
7749
8017
|
extractRuleLines: () => extractRuleLines,
|
|
7750
8018
|
findUnsupported: () => findUnsupported,
|
|
8019
|
+
fingerprintSources: () => fingerprintSources,
|
|
7751
8020
|
flattenMessageText: () => flattenMessageText,
|
|
7752
8021
|
formatSkillBody: () => formatSkillBody,
|
|
8022
|
+
formatSourceChanges: () => formatSourceChanges,
|
|
7753
8023
|
formatToolResult: () => formatToolResult,
|
|
7754
8024
|
guardHost: () => guardHost,
|
|
7755
8025
|
isReadOnlyCommand: () => isReadOnlyCommand,
|
|
@@ -7815,6 +8085,7 @@ var init_src = __esm({
|
|
|
7815
8085
|
init_adapt_plan();
|
|
7816
8086
|
init_instructions_tool();
|
|
7817
8087
|
init_trust();
|
|
8088
|
+
init_source_changes();
|
|
7818
8089
|
init_imports_config();
|
|
7819
8090
|
init_permission_rules();
|
|
7820
8091
|
init_command_args();
|
|
@@ -9386,7 +9657,7 @@ var require_signal_exit = __commonJS({
|
|
|
9386
9657
|
}
|
|
9387
9658
|
assert.equal(typeof cb, "function", "a callback must be provided for exit handler");
|
|
9388
9659
|
if (loaded === false) {
|
|
9389
|
-
|
|
9660
|
+
load2();
|
|
9390
9661
|
}
|
|
9391
9662
|
var ev = "exit";
|
|
9392
9663
|
if (opts && opts.alwaysLast) {
|
|
@@ -9446,7 +9717,7 @@ var require_signal_exit = __commonJS({
|
|
|
9446
9717
|
return signals;
|
|
9447
9718
|
};
|
|
9448
9719
|
loaded = false;
|
|
9449
|
-
|
|
9720
|
+
load2 = function load3() {
|
|
9450
9721
|
if (loaded || !processOk(global.process)) {
|
|
9451
9722
|
return;
|
|
9452
9723
|
}
|
|
@@ -9463,7 +9734,7 @@ var require_signal_exit = __commonJS({
|
|
|
9463
9734
|
process13.emit = processEmit;
|
|
9464
9735
|
process13.reallyExit = processReallyExit;
|
|
9465
9736
|
};
|
|
9466
|
-
module.exports.load =
|
|
9737
|
+
module.exports.load = load2;
|
|
9467
9738
|
originalProcessReallyExit = process13.reallyExit;
|
|
9468
9739
|
processReallyExit = function processReallyExit2(code) {
|
|
9469
9740
|
if (!processOk(global.process)) {
|
|
@@ -9499,7 +9770,7 @@ var require_signal_exit = __commonJS({
|
|
|
9499
9770
|
var emit;
|
|
9500
9771
|
var sigListeners;
|
|
9501
9772
|
var loaded;
|
|
9502
|
-
var
|
|
9773
|
+
var load2;
|
|
9503
9774
|
var originalProcessReallyExit;
|
|
9504
9775
|
var processReallyExit;
|
|
9505
9776
|
var originalProcessEmit;
|
|
@@ -44082,7 +44353,7 @@ var require_core = __commonJS({
|
|
|
44082
44353
|
return match && match.index === 0;
|
|
44083
44354
|
}
|
|
44084
44355
|
var BACKREF_RE = /\[(?:[^\\\]]|\\.)*\]|\(\??|\\([1-9][0-9]*)|\\./;
|
|
44085
|
-
function
|
|
44356
|
+
function join14(regexps, separator = "|") {
|
|
44086
44357
|
let numCaptures = 0;
|
|
44087
44358
|
return regexps.map((regex2) => {
|
|
44088
44359
|
numCaptures += 1;
|
|
@@ -44386,7 +44657,7 @@ var require_core = __commonJS({
|
|
|
44386
44657
|
this.exec = () => null;
|
|
44387
44658
|
}
|
|
44388
44659
|
const terminators = this.regexes.map((el) => el[1]);
|
|
44389
|
-
this.matcherRe = langRe(
|
|
44660
|
+
this.matcherRe = langRe(join14(terminators), true);
|
|
44390
44661
|
this.lastIndex = 0;
|
|
44391
44662
|
}
|
|
44392
44663
|
/** @param {string} s */
|
|
@@ -48163,7 +48434,7 @@ var require_bash = __commonJS({
|
|
|
48163
48434
|
return joined;
|
|
48164
48435
|
}
|
|
48165
48436
|
function bash(hljs) {
|
|
48166
|
-
const
|
|
48437
|
+
const VAR2 = {};
|
|
48167
48438
|
const BRACED_VAR = {
|
|
48168
48439
|
begin: /\$\{/,
|
|
48169
48440
|
end: /\}/,
|
|
@@ -48171,12 +48442,12 @@ var require_bash = __commonJS({
|
|
|
48171
48442
|
"self",
|
|
48172
48443
|
{
|
|
48173
48444
|
begin: /:-/,
|
|
48174
|
-
contains: [
|
|
48445
|
+
contains: [VAR2]
|
|
48175
48446
|
}
|
|
48176
48447
|
// default values
|
|
48177
48448
|
]
|
|
48178
48449
|
};
|
|
48179
|
-
Object.assign(
|
|
48450
|
+
Object.assign(VAR2, {
|
|
48180
48451
|
className: "variable",
|
|
48181
48452
|
variants: [
|
|
48182
48453
|
{ begin: concat(
|
|
@@ -48212,7 +48483,7 @@ var require_bash = __commonJS({
|
|
|
48212
48483
|
end: /"/,
|
|
48213
48484
|
contains: [
|
|
48214
48485
|
hljs.BACKSLASH_ESCAPE,
|
|
48215
|
-
|
|
48486
|
+
VAR2,
|
|
48216
48487
|
SUBST
|
|
48217
48488
|
]
|
|
48218
48489
|
};
|
|
@@ -48232,7 +48503,7 @@ var require_bash = __commonJS({
|
|
|
48232
48503
|
contains: [
|
|
48233
48504
|
{ begin: /\d+#[0-9a-f]+/, className: "number" },
|
|
48234
48505
|
hljs.NUMBER_MODE,
|
|
48235
|
-
|
|
48506
|
+
VAR2
|
|
48236
48507
|
]
|
|
48237
48508
|
};
|
|
48238
48509
|
const SH_LIKE_SHELLS = [
|
|
@@ -48282,7 +48553,7 @@ var require_bash = __commonJS({
|
|
|
48282
48553
|
QUOTE_STRING,
|
|
48283
48554
|
ESCAPED_QUOTE,
|
|
48284
48555
|
APOS_STRING,
|
|
48285
|
-
|
|
48556
|
+
VAR2
|
|
48286
48557
|
]
|
|
48287
48558
|
};
|
|
48288
48559
|
}
|
|
@@ -67905,7 +68176,7 @@ var require_perl = __commonJS({
|
|
|
67905
68176
|
end: /\}/
|
|
67906
68177
|
// contains defined later
|
|
67907
68178
|
};
|
|
67908
|
-
const
|
|
68179
|
+
const VAR2 = {
|
|
67909
68180
|
variants: [
|
|
67910
68181
|
{
|
|
67911
68182
|
begin: /\$\d/
|
|
@@ -67927,7 +68198,7 @@ var require_perl = __commonJS({
|
|
|
67927
68198
|
const STRING_CONTAINS = [
|
|
67928
68199
|
hljs.BACKSLASH_ESCAPE,
|
|
67929
68200
|
SUBST,
|
|
67930
|
-
|
|
68201
|
+
VAR2
|
|
67931
68202
|
];
|
|
67932
68203
|
const REGEX_DELIMS = [
|
|
67933
68204
|
/!/,
|
|
@@ -67962,7 +68233,7 @@ var require_perl = __commonJS({
|
|
|
67962
68233
|
);
|
|
67963
68234
|
};
|
|
67964
68235
|
const PERL_DEFAULT_CONTAINS = [
|
|
67965
|
-
|
|
68236
|
+
VAR2,
|
|
67966
68237
|
hljs.HASH_COMMENT_MODE,
|
|
67967
68238
|
hljs.COMMENT(
|
|
67968
68239
|
/^=\w/,
|
|
@@ -68429,7 +68700,7 @@ var require_n1ql = __commonJS({
|
|
|
68429
68700
|
var require_nginx = __commonJS({
|
|
68430
68701
|
"../../node_modules/highlight.js/lib/languages/nginx.js"(exports, module) {
|
|
68431
68702
|
function nginx(hljs) {
|
|
68432
|
-
const
|
|
68703
|
+
const VAR2 = {
|
|
68433
68704
|
className: "variable",
|
|
68434
68705
|
variants: [
|
|
68435
68706
|
{
|
|
@@ -68458,7 +68729,7 @@ var require_nginx = __commonJS({
|
|
|
68458
68729
|
className: "string",
|
|
68459
68730
|
contains: [
|
|
68460
68731
|
hljs.BACKSLASH_ESCAPE,
|
|
68461
|
-
|
|
68732
|
+
VAR2
|
|
68462
68733
|
],
|
|
68463
68734
|
variants: [
|
|
68464
68735
|
{
|
|
@@ -68477,13 +68748,13 @@ var require_nginx = __commonJS({
|
|
|
68477
68748
|
end: "\\s",
|
|
68478
68749
|
endsWithParent: true,
|
|
68479
68750
|
excludeEnd: true,
|
|
68480
|
-
contains: [
|
|
68751
|
+
contains: [VAR2]
|
|
68481
68752
|
},
|
|
68482
68753
|
{
|
|
68483
68754
|
className: "regexp",
|
|
68484
68755
|
contains: [
|
|
68485
68756
|
hljs.BACKSLASH_ESCAPE,
|
|
68486
|
-
|
|
68757
|
+
VAR2
|
|
68487
68758
|
],
|
|
68488
68759
|
variants: [
|
|
68489
68760
|
{
|
|
@@ -68518,7 +68789,7 @@ var require_nginx = __commonJS({
|
|
|
68518
68789
|
begin: "\\b\\d+[kKmMgGdshdwy]*\\b",
|
|
68519
68790
|
relevance: 0
|
|
68520
68791
|
},
|
|
68521
|
-
|
|
68792
|
+
VAR2
|
|
68522
68793
|
]
|
|
68523
68794
|
};
|
|
68524
68795
|
return {
|
|
@@ -69984,7 +70255,7 @@ var require_powershell = __commonJS({
|
|
|
69984
70255
|
begin: "`[\\s\\S]",
|
|
69985
70256
|
relevance: 0
|
|
69986
70257
|
};
|
|
69987
|
-
const
|
|
70258
|
+
const VAR2 = {
|
|
69988
70259
|
className: "variable",
|
|
69989
70260
|
variants: [
|
|
69990
70261
|
{
|
|
@@ -70017,7 +70288,7 @@ var require_powershell = __commonJS({
|
|
|
70017
70288
|
],
|
|
70018
70289
|
contains: [
|
|
70019
70290
|
BACKTICK_ESCAPE,
|
|
70020
|
-
|
|
70291
|
+
VAR2,
|
|
70021
70292
|
{
|
|
70022
70293
|
className: "variable",
|
|
70023
70294
|
begin: /\$[A-z]/,
|
|
@@ -70108,7 +70379,7 @@ var require_powershell = __commonJS({
|
|
|
70108
70379
|
end: /\)/,
|
|
70109
70380
|
className: "params",
|
|
70110
70381
|
relevance: 0,
|
|
70111
|
-
contains: [
|
|
70382
|
+
contains: [VAR2]
|
|
70112
70383
|
}
|
|
70113
70384
|
// CMDLETS
|
|
70114
70385
|
]
|
|
@@ -70179,7 +70450,7 @@ var require_powershell = __commonJS({
|
|
|
70179
70450
|
APOS_STRING,
|
|
70180
70451
|
// PS_NEW_OBJECT_TYPE,
|
|
70181
70452
|
CMDLETS,
|
|
70182
|
-
|
|
70453
|
+
VAR2,
|
|
70183
70454
|
LITERAL,
|
|
70184
70455
|
HASH_SIGNS
|
|
70185
70456
|
];
|
|
@@ -70301,7 +70572,7 @@ var require_prolog = __commonJS({
|
|
|
70301
70572
|
begin: /[a-z][A-Za-z0-9_]*/,
|
|
70302
70573
|
relevance: 0
|
|
70303
70574
|
};
|
|
70304
|
-
const
|
|
70575
|
+
const VAR2 = {
|
|
70305
70576
|
className: "symbol",
|
|
70306
70577
|
variants: [
|
|
70307
70578
|
{
|
|
@@ -70350,7 +70621,7 @@ var require_prolog = __commonJS({
|
|
|
70350
70621
|
};
|
|
70351
70622
|
const inner = [
|
|
70352
70623
|
ATOM,
|
|
70353
|
-
|
|
70624
|
+
VAR2,
|
|
70354
70625
|
PARENTED,
|
|
70355
70626
|
PRED_OP,
|
|
70356
70627
|
LIST,
|
|
@@ -71895,7 +72166,7 @@ var require_routeros = __commonJS({
|
|
|
71895
72166
|
const COMMON_COMMANDS = "add remove enable disable set get print export edit find run debug error info warning";
|
|
71896
72167
|
const LITERALS = "true false yes no nothing nil null";
|
|
71897
72168
|
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";
|
|
71898
|
-
const
|
|
72169
|
+
const VAR2 = {
|
|
71899
72170
|
className: "variable",
|
|
71900
72171
|
variants: [
|
|
71901
72172
|
{
|
|
@@ -71912,7 +72183,7 @@ var require_routeros = __commonJS({
|
|
|
71912
72183
|
end: /"/,
|
|
71913
72184
|
contains: [
|
|
71914
72185
|
hljs.BACKSLASH_ESCAPE,
|
|
71915
|
-
|
|
72186
|
+
VAR2,
|
|
71916
72187
|
{
|
|
71917
72188
|
className: "variable",
|
|
71918
72189
|
begin: /\$\(/,
|
|
@@ -71962,7 +72233,7 @@ var require_routeros = __commonJS({
|
|
|
71962
72233
|
hljs.COMMENT("^#", "$"),
|
|
71963
72234
|
QUOTE_STRING,
|
|
71964
72235
|
APOS_STRING,
|
|
71965
|
-
|
|
72236
|
+
VAR2,
|
|
71966
72237
|
// attribute=value
|
|
71967
72238
|
{
|
|
71968
72239
|
// > is to avoid matches with => in other grammars
|
|
@@ -71981,7 +72252,7 @@ var require_routeros = __commonJS({
|
|
|
71981
72252
|
contains: [
|
|
71982
72253
|
QUOTE_STRING,
|
|
71983
72254
|
APOS_STRING,
|
|
71984
|
-
|
|
72255
|
+
VAR2,
|
|
71985
72256
|
{
|
|
71986
72257
|
className: "literal",
|
|
71987
72258
|
begin: "\\b(" + LITERALS.split(" ").join("|") + ")\\b"
|
|
@@ -78263,7 +78534,7 @@ var require_xquery = __commonJS({
|
|
|
78263
78534
|
begin: /\bxquery version "[13]\.[01]"\s?(?:encoding ".+")?/,
|
|
78264
78535
|
end: /;/
|
|
78265
78536
|
};
|
|
78266
|
-
const
|
|
78537
|
+
const VAR2 = {
|
|
78267
78538
|
className: "variable",
|
|
78268
78539
|
begin: /[$][\w\-:]+/
|
|
78269
78540
|
};
|
|
@@ -78332,7 +78603,7 @@ var require_xquery = __commonJS({
|
|
|
78332
78603
|
]
|
|
78333
78604
|
};
|
|
78334
78605
|
const CONTAINS = [
|
|
78335
|
-
|
|
78606
|
+
VAR2,
|
|
78336
78607
|
BUILT_IN,
|
|
78337
78608
|
STRING,
|
|
78338
78609
|
NUMBER,
|
|
@@ -103199,6 +103470,7 @@ var init_slash_commands = __esm({
|
|
|
103199
103470
|
{ name: "turns", description: "Browse earlier turns and open their steps (shortcut: ctrl+o)" },
|
|
103200
103471
|
{ name: "commands", description: "List the slash commands imported from Claude Code" },
|
|
103201
103472
|
{ name: "skills", description: "List imported skills; /skills show <name> [file], /skills delete <name>" },
|
|
103473
|
+
{ name: "import", description: "Re-check imported Claude Code sources: /import reload shows changes; /import reload trust applies them" },
|
|
103202
103474
|
{ name: "tools", description: "List the tools available to the agent" },
|
|
103203
103475
|
{ name: "exit", description: "Quit the REPL (alias: /quit)" },
|
|
103204
103476
|
{ name: "quit", description: "Quit the REPL" }
|
|
@@ -103855,6 +104127,65 @@ var init_project_card_runtime = __esm({
|
|
|
103855
104127
|
}
|
|
103856
104128
|
});
|
|
103857
104129
|
|
|
104130
|
+
// src/prompt-runtime.ts
|
|
104131
|
+
import { join as join8 } from "node:path";
|
|
104132
|
+
async function load(deps) {
|
|
104133
|
+
if (deps.env.SPACECODE_PROMPTS === "off") return { templates: {}, statusLine: "prompts: built-in defaults (SPACECODE_PROMPTS=off)" };
|
|
104134
|
+
const dir = deps.env.SPACECODE_CONFIG_DIR?.trim() || join8(deps.homedir(), ".spacecode");
|
|
104135
|
+
const file = join8(dir, "prompts-cache.json");
|
|
104136
|
+
const fromDisk = async (why) => {
|
|
104137
|
+
try {
|
|
104138
|
+
const raw = JSON.parse(await deps.readFile(file));
|
|
104139
|
+
const templates = raw.templates ?? {};
|
|
104140
|
+
return { templates, statusLine: `prompts: ${Object.keys(templates).length} tuned (STALE: served from cache; ${why})` };
|
|
104141
|
+
} catch {
|
|
104142
|
+
return { templates: {}, statusLine: `prompts: built-in defaults (${why})` };
|
|
104143
|
+
}
|
|
104144
|
+
};
|
|
104145
|
+
let apiKey;
|
|
104146
|
+
try {
|
|
104147
|
+
apiKey = await resolveApiKey({ env: deps.env, readFile: deps.readFile, homedir: deps.homedir });
|
|
104148
|
+
} catch (err) {
|
|
104149
|
+
return fromDisk(err instanceof Error ? err.message : String(err));
|
|
104150
|
+
}
|
|
104151
|
+
if (!apiKey) return fromDisk("not signed in");
|
|
104152
|
+
try {
|
|
104153
|
+
const res = await deps.fetch(`${backendUrl(deps.env)}/api/prompts`, {
|
|
104154
|
+
headers: { Authorization: `Bearer ${apiKey}`, "x-api-key": apiKey },
|
|
104155
|
+
signal: AbortSignal.timeout(3e3)
|
|
104156
|
+
});
|
|
104157
|
+
if (!res.ok) return fromDisk(`prompt API returned ${res.status}`);
|
|
104158
|
+
const { prompts } = await res.json();
|
|
104159
|
+
const templates = Object.fromEntries(prompts.filter((p) => p.source === "db").map((p) => [p.key, p.body]));
|
|
104160
|
+
try {
|
|
104161
|
+
await deps.mkdir(dir);
|
|
104162
|
+
await deps.writeFile(file, JSON.stringify({ fetchedAt: new Date((deps.now ?? Date.now)()).toISOString(), templates }));
|
|
104163
|
+
} catch (err) {
|
|
104164
|
+
console.error("[prompts] could not write the prompt cache", err instanceof Error ? err.message : String(err));
|
|
104165
|
+
}
|
|
104166
|
+
const n = Object.keys(templates).length;
|
|
104167
|
+
return { templates, statusLine: n ? `prompts: ${n} tuned override(s): ${Object.keys(templates).join(", ")}` : "prompts: built-in defaults (none tuned)" };
|
|
104168
|
+
} catch (err) {
|
|
104169
|
+
return fromDisk(`fetch failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
104170
|
+
}
|
|
104171
|
+
}
|
|
104172
|
+
function loadPromptTemplates(deps) {
|
|
104173
|
+
const now = (deps.now ?? Date.now)();
|
|
104174
|
+
if (cached2 && now - cached2.at < TTL_MS2) return cached2.pending;
|
|
104175
|
+
const pending = load(deps);
|
|
104176
|
+
cached2 = { at: now, pending };
|
|
104177
|
+
return pending;
|
|
104178
|
+
}
|
|
104179
|
+
var TTL_MS2, cached2;
|
|
104180
|
+
var init_prompt_runtime = __esm({
|
|
104181
|
+
"src/prompt-runtime.ts"() {
|
|
104182
|
+
"use strict";
|
|
104183
|
+
init_api_key();
|
|
104184
|
+
init_profile_runtime();
|
|
104185
|
+
TTL_MS2 = 10 * 6e4;
|
|
104186
|
+
}
|
|
104187
|
+
});
|
|
104188
|
+
|
|
103858
104189
|
// src/shell-turn.ts
|
|
103859
104190
|
function shellCommandOf(prompt) {
|
|
103860
104191
|
return prompt.startsWith("!") ? prompt.slice(1).trim() : null;
|
|
@@ -104279,7 +104610,7 @@ var init_recording_chunks = __esm({
|
|
|
104279
104610
|
// src/recording/recorder.ts
|
|
104280
104611
|
import { createHash as createHash4 } from "node:crypto";
|
|
104281
104612
|
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";
|
|
104282
|
-
import { join as
|
|
104613
|
+
import { join as join9 } from "node:path";
|
|
104283
104614
|
function projectHash(root) {
|
|
104284
104615
|
return createHash4("sha256").update(root).digest("hex");
|
|
104285
104616
|
}
|
|
@@ -104290,24 +104621,24 @@ function createRecorder(deps) {
|
|
|
104290
104621
|
let inflight = null;
|
|
104291
104622
|
let retryAttempt = 0;
|
|
104292
104623
|
let timerArmed = false;
|
|
104293
|
-
const stateFile = (sessionId) =>
|
|
104624
|
+
const stateFile = (sessionId) => join9(deps.dir, `${sessionId}.json`);
|
|
104294
104625
|
async function save(sessionId, st) {
|
|
104295
104626
|
await mkdir4(deps.dir, { recursive: true, mode: 448 });
|
|
104296
104627
|
const tmp = `${stateFile(sessionId)}.${deps.randomId()}.tmp`;
|
|
104297
104628
|
await writeFile4(tmp, JSON.stringify(st), { mode: 384 });
|
|
104298
104629
|
await rename4(tmp, stateFile(sessionId));
|
|
104299
104630
|
}
|
|
104300
|
-
async function
|
|
104301
|
-
const
|
|
104302
|
-
if (
|
|
104631
|
+
async function load2(sessionId) {
|
|
104632
|
+
const cached3 = states.get(sessionId);
|
|
104633
|
+
if (cached3) return cached3;
|
|
104303
104634
|
let st;
|
|
104304
104635
|
try {
|
|
104305
104636
|
st = JSON.parse(await readFile6(stateFile(sessionId), "utf8"));
|
|
104306
104637
|
} catch (e) {
|
|
104307
104638
|
if (e.code !== "ENOENT") {
|
|
104308
|
-
const bad =
|
|
104639
|
+
const bad = join9(deps.dir, "bad");
|
|
104309
104640
|
await mkdir4(bad, { recursive: true, mode: 448 });
|
|
104310
|
-
await rename4(stateFile(sessionId),
|
|
104641
|
+
await rename4(stateFile(sessionId), join9(bad, `${sessionId}.${deps.now()}.json`)).catch((err) => deps.log(`recording: could not quarantine ${sessionId}: ${String(err)}`));
|
|
104311
104642
|
lastError = `recording state for ${sessionId} was unreadable and was quarantined`;
|
|
104312
104643
|
deps.log(`recording: ${lastError}`);
|
|
104313
104644
|
}
|
|
@@ -104324,7 +104655,7 @@ function createRecorder(deps) {
|
|
|
104324
104655
|
async function record(sessionId, messages, meta) {
|
|
104325
104656
|
try {
|
|
104326
104657
|
if (off2) return;
|
|
104327
|
-
const st = await
|
|
104658
|
+
const st = await load2(sessionId);
|
|
104328
104659
|
if (st.stopped) return;
|
|
104329
104660
|
if (st.hashes.length === 0 && st.nextSeq === 1 && meta.parentRecordingId) st.parentRecordingId = meta.parentRecordingId;
|
|
104330
104661
|
st.meta = meta;
|
|
@@ -104477,7 +104808,7 @@ function createRecorder(deps) {
|
|
|
104477
104808
|
for (const n of names) {
|
|
104478
104809
|
if (!n.endsWith(".json")) continue;
|
|
104479
104810
|
const id = n.slice(0, -5);
|
|
104480
|
-
const st = await
|
|
104811
|
+
const st = await load2(id);
|
|
104481
104812
|
if (st.queue.length === 0) states.delete(id);
|
|
104482
104813
|
}
|
|
104483
104814
|
if ([...states.values()].some((s) => s.queue.length > 0)) void flush();
|
|
@@ -104498,7 +104829,7 @@ var init_recorder = __esm({
|
|
|
104498
104829
|
|
|
104499
104830
|
// src/recording/recording-runtime.ts
|
|
104500
104831
|
import { mkdir as mkdir5, readFile as readFile7, writeFile as writeFile5, stat as stat4 } from "node:fs/promises";
|
|
104501
|
-
import { join as
|
|
104832
|
+
import { join as join10, sep as sep2 } from "node:path";
|
|
104502
104833
|
function matchesExclude(pattern, root) {
|
|
104503
104834
|
const re3 = pattern.replace(/[.+^${}()|[\]\\]/g, "\\$&").replace(/\*\*/g, "\0").replace(/\*/g, `[^${sep2 === "\\" ? "\\\\" : "/"}]*`).replace(/\u0000/g, ".*");
|
|
104504
104835
|
return new RegExp(`^${re3}(?:[/\\\\].*)?$`).test(root);
|
|
@@ -104513,8 +104844,8 @@ async function exists(path12) {
|
|
|
104513
104844
|
}
|
|
104514
104845
|
}
|
|
104515
104846
|
function createRecordingRuntime(deps) {
|
|
104516
|
-
const dir =
|
|
104517
|
-
const noticeFile =
|
|
104847
|
+
const dir = join10(deps.configDir, "recordings");
|
|
104848
|
+
const noticeFile = join10(dir, ".notice");
|
|
104518
104849
|
let recorder = null;
|
|
104519
104850
|
let standingOff;
|
|
104520
104851
|
let sessionOff = false;
|
|
@@ -104522,7 +104853,7 @@ function createRecordingRuntime(deps) {
|
|
|
104522
104853
|
if (deps.env.SPACECODE_RECORD?.trim().toLowerCase() === "off") return "SPACECODE_RECORD=off";
|
|
104523
104854
|
let cfg = {};
|
|
104524
104855
|
try {
|
|
104525
|
-
cfg = JSON.parse(await readFile7(
|
|
104856
|
+
cfg = JSON.parse(await readFile7(join10(deps.configDir, "config.json"), "utf8"));
|
|
104526
104857
|
} catch (e) {
|
|
104527
104858
|
if (e.code !== "ENOENT") return `~/.spacecode/config.json is unreadable (${e instanceof Error ? e.message : String(e)}); fix it to record`;
|
|
104528
104859
|
}
|
|
@@ -104530,7 +104861,7 @@ function createRecordingRuntime(deps) {
|
|
|
104530
104861
|
const excludes = Array.isArray(cfg.recording?.exclude) ? cfg.recording.exclude.filter((x2) => typeof x2 === "string") : [];
|
|
104531
104862
|
const hit = excludes.find((p) => matchesExclude(p, deps.projectRoot));
|
|
104532
104863
|
if (hit) return `this folder matches recording.exclude (${hit})`;
|
|
104533
|
-
if (await exists(
|
|
104864
|
+
if (await exists(join10(deps.projectRoot, ".spacecode", "norecord"))) return "this repo has .spacecode/norecord";
|
|
104534
104865
|
return null;
|
|
104535
104866
|
}
|
|
104536
104867
|
async function noticeShown() {
|
|
@@ -104672,7 +105003,7 @@ var init_skills_command = __esm({
|
|
|
104672
105003
|
|
|
104673
105004
|
// src/permission-rules-loader.ts
|
|
104674
105005
|
import { readFile as readFile8 } from "node:fs/promises";
|
|
104675
|
-
import { join as
|
|
105006
|
+
import { join as join11 } from "node:path";
|
|
104676
105007
|
async function readOrNull2(path12) {
|
|
104677
105008
|
try {
|
|
104678
105009
|
return await readFile8(path12, "utf8");
|
|
@@ -104683,7 +105014,7 @@ async function readOrNull2(path12) {
|
|
|
104683
105014
|
}
|
|
104684
105015
|
async function loadPermissionRules(deps) {
|
|
104685
105016
|
const none = (line) => ({ rules: void 0, defaultMode: void 0, statusLines: [line] });
|
|
104686
|
-
const configPath =
|
|
105017
|
+
const configPath = join11(deps.configDir, "imports.json");
|
|
104687
105018
|
try {
|
|
104688
105019
|
const loaded = parseImportsConfig(await readOrNull2(configPath), configPath);
|
|
104689
105020
|
if (loaded.error) return none("permission rules: off (imports.json unreadable)");
|
|
@@ -104692,13 +105023,13 @@ async function loadPermissionRules(deps) {
|
|
|
104692
105023
|
return none(`permission rules: off (imports.json not read: ${err instanceof Error ? err.message : String(err)})`);
|
|
104693
105024
|
}
|
|
104694
105025
|
const lines2 = [];
|
|
104695
|
-
const files = [{ scope: "user", path:
|
|
105026
|
+
const files = [{ scope: "user", path: join11(deps.homeDir, ".claude", "settings.json") }];
|
|
104696
105027
|
try {
|
|
104697
105028
|
const sources2 = await readRepoSources(deps.cwd);
|
|
104698
105029
|
if (sources2[".claude/settings.json"] !== void 0 || sources2[".claude/settings.local.json"] !== void 0) {
|
|
104699
105030
|
const status = await createNodeTrustStore(deps.configDir).repoStatus(deps.cwd, sources2);
|
|
104700
105031
|
if (status === "trusted" || status === "session") {
|
|
104701
|
-
files.push({ scope: "repo", path:
|
|
105032
|
+
files.push({ scope: "repo", path: join11(deps.cwd, ".claude", "settings.json") }, { scope: "local", path: join11(deps.cwd, ".claude", "settings.local.json") });
|
|
104702
105033
|
} else lines2.push(`permission rules: repo settings NOT loaded (${status === "never" ? "marked never trust" : "untrusted repo"})`);
|
|
104703
105034
|
}
|
|
104704
105035
|
} catch (err) {
|
|
@@ -104739,8 +105070,43 @@ var init_permission_rules_loader = __esm({
|
|
|
104739
105070
|
}
|
|
104740
105071
|
});
|
|
104741
105072
|
|
|
105073
|
+
// src/import-reload.ts
|
|
105074
|
+
async function checkRepoSources(deps, loaded) {
|
|
105075
|
+
const files = await readRepoSources(deps.cwd);
|
|
105076
|
+
const current = fingerprintSources(files, sha2562);
|
|
105077
|
+
const status = Object.keys(files).length === 0 ? "untrusted" : await createNodeTrustStore(deps.configDir).repoStatus(deps.cwd, files);
|
|
105078
|
+
return { current, changes: diffSources(loaded, current), trusted: status === "trusted" || status === "session" };
|
|
105079
|
+
}
|
|
105080
|
+
async function describeReload(deps, loaded) {
|
|
105081
|
+
const check = await checkRepoSources(deps, loaded);
|
|
105082
|
+
if (!check.changes.changed) return ["No change in the repo import sources since they were loaded."];
|
|
105083
|
+
const files = await readRepoSources(deps.cwd);
|
|
105084
|
+
return [
|
|
105085
|
+
"Repo import sources changed since they were loaded:",
|
|
105086
|
+
...formatSourceChanges(check.changes).map((l) => ` ${l}`),
|
|
105087
|
+
"",
|
|
105088
|
+
"Trusting the new state would load:",
|
|
105089
|
+
...describeRepoSources(files).length ? describeRepoSources(files) : [" (nothing)"],
|
|
105090
|
+
"",
|
|
105091
|
+
"Run /import reload trust to trust it and apply the rules and commands. MCP servers and skills apply on the next start."
|
|
105092
|
+
];
|
|
105093
|
+
}
|
|
105094
|
+
async function trustCurrentSources(deps) {
|
|
105095
|
+
const files = await readRepoSources(deps.cwd);
|
|
105096
|
+
await createNodeTrustStore(deps.configDir).setRepo(deps.cwd, files, "trusted");
|
|
105097
|
+
return fingerprintSources(files, sha2562);
|
|
105098
|
+
}
|
|
105099
|
+
var init_import_reload = __esm({
|
|
105100
|
+
"src/import-reload.ts"() {
|
|
105101
|
+
"use strict";
|
|
105102
|
+
init_src();
|
|
105103
|
+
init_import_gate();
|
|
105104
|
+
init_repo_trust_prompt();
|
|
105105
|
+
}
|
|
105106
|
+
});
|
|
105107
|
+
|
|
104742
105108
|
// src/command-loader.ts
|
|
104743
|
-
import { join as
|
|
105109
|
+
import { join as join12 } from "node:path";
|
|
104744
105110
|
async function userCommands(deps, lines2) {
|
|
104745
105111
|
try {
|
|
104746
105112
|
const apiKey = await resolveApiKey({ env: deps.env, readFile: deps.readFile, homedir: deps.homedir });
|
|
@@ -104795,7 +105161,7 @@ async function repoCommands(deps, lines2) {
|
|
|
104795
105161
|
}
|
|
104796
105162
|
}
|
|
104797
105163
|
async function loadCommands(deps) {
|
|
104798
|
-
const configPath =
|
|
105164
|
+
const configPath = join12(deps.configDir, "imports.json");
|
|
104799
105165
|
try {
|
|
104800
105166
|
const loaded = parseImportsConfig(await deps.readFile(configPath).catch((err) => {
|
|
104801
105167
|
if (err.code === "ENOENT") return null;
|
|
@@ -104830,7 +105196,7 @@ var init_command_loader = __esm({
|
|
|
104830
105196
|
// src/useReplController.ts
|
|
104831
105197
|
import { readFile as readFile9, writeFile as writeFile6, mkdir as mkdir6 } from "node:fs/promises";
|
|
104832
105198
|
import { homedir as homedir2 } from "node:os";
|
|
104833
|
-
import { join as
|
|
105199
|
+
import { join as join13 } from "node:path";
|
|
104834
105200
|
import { execFile as execFile4 } from "node:child_process";
|
|
104835
105201
|
function useReplController({ repoName: repoName2, yolo: yolo2, mentions: mentionsOpt, sessions, resumeLatest: resumeLatest2, onViewTurns, onViewResume, isEscOwned }) {
|
|
104836
105202
|
const { exit } = use_app_default();
|
|
@@ -104852,8 +105218,13 @@ function useReplController({ repoName: repoName2, yolo: yolo2, mentions: mention
|
|
|
104852
105218
|
return () => clearInterval(timer);
|
|
104853
105219
|
}, [turnStartedAt]);
|
|
104854
105220
|
const projectRoot = (0, import_react30.useMemo)(() => process.cwd(), []);
|
|
105221
|
+
const promptTemplates = (0, import_react30.useCallback)(
|
|
105222
|
+
() => 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 }),
|
|
105223
|
+
[]
|
|
105224
|
+
);
|
|
104855
105225
|
(0, import_react30.useEffect)(() => {
|
|
104856
105226
|
void loadProjectCard(projectRoot);
|
|
105227
|
+
void promptTemplates();
|
|
104857
105228
|
}, [projectRoot]);
|
|
104858
105229
|
const sessionIdRef = (0, import_react30.useRef)(null);
|
|
104859
105230
|
const sessionCreatedAtRef = (0, import_react30.useRef)(null);
|
|
@@ -104864,7 +105235,7 @@ function useReplController({ repoName: repoName2, yolo: yolo2, mentions: mention
|
|
|
104864
105235
|
const recordingRef = (0, import_react30.useRef)(null);
|
|
104865
105236
|
const recording = () => recordingRef.current ??= createRecordingRuntime({
|
|
104866
105237
|
env: process.env,
|
|
104867
|
-
configDir: process.env.SPACECODE_CONFIG_DIR?.trim() ||
|
|
105238
|
+
configDir: process.env.SPACECODE_CONFIG_DIR?.trim() || join13(homedir2(), ".spacecode"),
|
|
104868
105239
|
projectRoot,
|
|
104869
105240
|
fetch,
|
|
104870
105241
|
baseUrl: backendUrl(process.env),
|
|
@@ -104887,11 +105258,12 @@ function useReplController({ repoName: repoName2, yolo: yolo2, mentions: mention
|
|
|
104887
105258
|
const pendingRef = (0, import_react30.useRef)(null);
|
|
104888
105259
|
const toolsetRef = (0, import_react30.useRef)(null);
|
|
104889
105260
|
const rulesRef = (0, import_react30.useRef)(void 0);
|
|
105261
|
+
const loadedSourcesRef = (0, import_react30.useRef)(null);
|
|
104890
105262
|
const [commandsLoaded, setCommandsLoaded] = (0, import_react30.useState)({ commands: [], statusLines: [] });
|
|
104891
105263
|
(0, import_react30.useEffect)(() => {
|
|
104892
105264
|
let live2 = true;
|
|
104893
105265
|
loadCommands({
|
|
104894
|
-
configDir: process.env.SPACECODE_CONFIG_DIR?.trim() ||
|
|
105266
|
+
configDir: process.env.SPACECODE_CONFIG_DIR?.trim() || join13(homedir2(), ".spacecode"),
|
|
104895
105267
|
cwd: process.cwd(),
|
|
104896
105268
|
env: process.env,
|
|
104897
105269
|
readFile: (p) => readFile9(p, "utf-8"),
|
|
@@ -105111,6 +105483,29 @@ function useReplController({ repoName: repoName2, yolo: yolo2, mentions: mention
|
|
|
105111
105483
|
case "context":
|
|
105112
105484
|
notice(formatContextReport({ contextTokens: estimateTotalTokens("", history), maxContextTokens: DEFAULT_MAX_CONTEXT_TOKENS }));
|
|
105113
105485
|
return;
|
|
105486
|
+
case "import": {
|
|
105487
|
+
const configDir = process.env.SPACECODE_CONFIG_DIR?.trim() || join13(homedir2(), ".spacecode");
|
|
105488
|
+
const deps = { configDir, cwd: process.cwd() };
|
|
105489
|
+
const [sub, ...rest] = slash.args.split(/\s+/).filter(Boolean);
|
|
105490
|
+
if (sub !== "reload" || rest.length > 1 || rest[0] !== void 0 && rest[0] !== "trust") {
|
|
105491
|
+
notice("Usage: /import reload (show changes to the repo import sources) or /import reload trust (trust the new state and apply it).");
|
|
105492
|
+
return;
|
|
105493
|
+
}
|
|
105494
|
+
try {
|
|
105495
|
+
const baseline = loadedSourcesRef.current ?? fingerprintSources(await readRepoSources(process.cwd()), sha2562);
|
|
105496
|
+
if (rest[0] === "trust") {
|
|
105497
|
+
loadedSourcesRef.current = await trustCurrentSources(deps);
|
|
105498
|
+
const loaded = await loadPermissionRules({ configDir, homeDir: homedir2(), cwd: process.cwd() });
|
|
105499
|
+
rulesRef.current = loaded.rules;
|
|
105500
|
+
const cmds = await loadCommands({ configDir, cwd: process.cwd(), env: process.env, readFile: (p) => readFile9(p, "utf-8"), homedir: homedir2, fetch, builtins: SLASH_COMMANDS.map((c) => c.name) });
|
|
105501
|
+
setCommandsLoaded(cmds);
|
|
105502
|
+
notice(["Trusted the repo import sources as they are now.", ...loaded.statusLines, ...cmds.statusLines, "MCP servers and skills apply on the next start."].join("\n"));
|
|
105503
|
+
} else notice((await describeReload(deps, baseline)).join("\n"));
|
|
105504
|
+
} catch (err) {
|
|
105505
|
+
notice(`/import reload failed (${err instanceof Error ? err.message : String(err)}); nothing was changed.`);
|
|
105506
|
+
}
|
|
105507
|
+
return;
|
|
105508
|
+
}
|
|
105114
105509
|
case "record":
|
|
105115
105510
|
notice(await recording().command(slash.args));
|
|
105116
105511
|
return;
|
|
@@ -105188,7 +105583,7 @@ function useReplController({ repoName: repoName2, yolo: yolo2, mentions: mention
|
|
|
105188
105583
|
return;
|
|
105189
105584
|
}
|
|
105190
105585
|
notice("Compacting conversation\u2026");
|
|
105191
|
-
const summary = await summarizeConversation(history, { apiUrl: apiUrl(), apiKey: apiKey2 });
|
|
105586
|
+
const summary = await summarizeConversation(history, { apiUrl: apiUrl(), apiKey: apiKey2, templates: (await promptTemplates()).templates });
|
|
105192
105587
|
const compacted = buildCompactedHistory(summary.summaryText);
|
|
105193
105588
|
const before = estimateTotalTokens("", history);
|
|
105194
105589
|
const after = estimateTotalTokens("", compacted);
|
|
@@ -105296,6 +105691,22 @@ ${list2.map((c) => ` /${c.name} (${c.scope})${c.description ? ` ${c.descripti
|
|
|
105296
105691
|
let failed = false;
|
|
105297
105692
|
let keepForRetry = false;
|
|
105298
105693
|
try {
|
|
105694
|
+
if (loadedSourcesRef.current) {
|
|
105695
|
+
const configDir = process.env.SPACECODE_CONFIG_DIR?.trim() || join13(homedir2(), ".spacecode");
|
|
105696
|
+
try {
|
|
105697
|
+
const check = await checkRepoSources({ configDir, cwd: process.cwd() }, loadedSourcesRef.current);
|
|
105698
|
+
if (check.changes.changed) {
|
|
105699
|
+
const loaded = await loadPermissionRules({ configDir, homeDir: homedir2(), cwd: process.cwd() });
|
|
105700
|
+
rulesRef.current = loaded.rules;
|
|
105701
|
+
loadedSourcesRef.current = check.current;
|
|
105702
|
+
const lead = check.trusted ? "Repo import sources changed since they were loaded; the new state is already trusted, so its permission rules now apply:" : "Repo import sources changed since they were loaded; repo permission rules are dropped until you trust the new state:";
|
|
105703
|
+
notice([lead, ...formatSourceChanges(check.changes).map((l) => ` ${l}`), ...check.trusted ? [] : ["Run /import reload to review, /import reload trust to apply."]].join("\n"));
|
|
105704
|
+
}
|
|
105705
|
+
} catch (err) {
|
|
105706
|
+
rulesRef.current = void 0;
|
|
105707
|
+
notice(`Repo import source check failed (${err instanceof Error ? err.message : String(err)}); repo permission rules are dropped.`);
|
|
105708
|
+
}
|
|
105709
|
+
}
|
|
105299
105710
|
profilePromiseRef.current ??= prepareProfile({
|
|
105300
105711
|
env: process.env,
|
|
105301
105712
|
readFile: (p) => readFile9(p, "utf-8"),
|
|
@@ -105308,17 +105719,19 @@ ${list2.map((c) => ` /${c.name} (${c.scope})${c.description ? ` ${c.descripti
|
|
|
105308
105719
|
cwd: process.cwd(),
|
|
105309
105720
|
gitRoot: gitTopLevel,
|
|
105310
105721
|
importGate: async () => {
|
|
105311
|
-
const configDir = process.env.SPACECODE_CONFIG_DIR?.trim() ||
|
|
105722
|
+
const configDir = process.env.SPACECODE_CONFIG_DIR?.trim() || join13(homedir2(), ".spacecode");
|
|
105723
|
+
const fingerprint = fingerprintSources(await readRepoSources(process.cwd()), sha2562);
|
|
105312
105724
|
const gate = await importGateStatus({ configDir, cwd: process.cwd(), interactive: Boolean(process.stdin.isTTY) });
|
|
105313
105725
|
const loaded = await loadPermissionRules({ configDir, homeDir: homedir2(), cwd: process.cwd() });
|
|
105314
105726
|
rulesRef.current = loaded.rules;
|
|
105727
|
+
loadedSourcesRef.current = fingerprint;
|
|
105315
105728
|
if (loaded.defaultMode && !yolo2) permissions.set(loaded.defaultMode);
|
|
105316
105729
|
return [...gate, ...loaded.statusLines];
|
|
105317
105730
|
}
|
|
105318
105731
|
});
|
|
105319
105732
|
profileRef.current = await profilePromiseRef.current;
|
|
105320
105733
|
if (mcpRef.current === null && (profileRef.current?.mcpDefs?.length ?? 0) > 0) {
|
|
105321
|
-
const configDir = process.env.SPACECODE_CONFIG_DIR?.trim() ||
|
|
105734
|
+
const configDir = process.env.SPACECODE_CONFIG_DIR?.trim() || join13(homedir2(), ".spacecode");
|
|
105322
105735
|
const trust = createNodeTrustStore(configDir);
|
|
105323
105736
|
const manager = new McpManager({
|
|
105324
105737
|
defs: profileRef.current.mcpDefs,
|
|
@@ -105328,7 +105741,7 @@ ${list2.map((c) => ` /${c.name} (${c.scope})${c.description ? ` ${c.descripti
|
|
|
105328
105741
|
...rulesRef.current ? { rules: rulesRef.current } : {},
|
|
105329
105742
|
permissions,
|
|
105330
105743
|
confirm: askUser,
|
|
105331
|
-
audit: new FileAuditLog(
|
|
105744
|
+
audit: new FileAuditLog(join13(homedir2(), ".spacecode", "audit.jsonl")),
|
|
105332
105745
|
clientVersion: process.env.SPACECODE_VERSION ?? "0"
|
|
105333
105746
|
});
|
|
105334
105747
|
mcpRef.current = manager;
|
|
@@ -105337,6 +105750,7 @@ ${list2.map((c) => ` /${c.name} (${c.scope})${c.description ? ` ${c.descripti
|
|
|
105337
105750
|
const toolset = createToolset();
|
|
105338
105751
|
toolsetRef.current = toolset;
|
|
105339
105752
|
const projectCard = await loadProjectCard(projectRoot);
|
|
105753
|
+
const prompts = await promptTemplates();
|
|
105340
105754
|
const config = {
|
|
105341
105755
|
apiUrl: apiUrl(),
|
|
105342
105756
|
apiKey,
|
|
@@ -105346,7 +105760,8 @@ ${list2.map((c) => ` /${c.name} (${c.scope})${c.description ? ` ${c.descripti
|
|
|
105346
105760
|
localCwd: projectRoot,
|
|
105347
105761
|
commitGuidance: true,
|
|
105348
105762
|
hasGitHubTools: toolset.hasGitHubTools,
|
|
105349
|
-
...projectCard.text ? { projectCard: projectCard.text } : {}
|
|
105763
|
+
...projectCard.text ? { projectCard: projectCard.text } : {},
|
|
105764
|
+
templates: prompts.templates
|
|
105350
105765
|
}) + (profileRef.current?.promptSection ?? ""),
|
|
105351
105766
|
tools: toolset.tools,
|
|
105352
105767
|
maxTurns: 100,
|
|
@@ -105458,6 +105873,7 @@ var init_useReplController = __esm({
|
|
|
105458
105873
|
init_session_commands();
|
|
105459
105874
|
init_local_toolset();
|
|
105460
105875
|
init_project_card_runtime();
|
|
105876
|
+
init_prompt_runtime();
|
|
105461
105877
|
init_shell_turn();
|
|
105462
105878
|
init_node_mentions();
|
|
105463
105879
|
init_api_key();
|
|
@@ -105468,6 +105884,8 @@ var init_useReplController = __esm({
|
|
|
105468
105884
|
init_mcp_manager();
|
|
105469
105885
|
init_import_gate();
|
|
105470
105886
|
init_permission_rules_loader();
|
|
105887
|
+
init_import_reload();
|
|
105888
|
+
init_src();
|
|
105471
105889
|
init_command_loader();
|
|
105472
105890
|
init_slash_commands();
|
|
105473
105891
|
init_useEventAccumulator();
|