@kkelly-offical/kkcode 0.1.7 → 0.2.3-preview.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +674 -674
- package/README.md +474 -387
- package/package.json +50 -46
- package/src/agent/agent.mjs +228 -220
- package/src/agent/custom-agent-loader.mjs +6 -3
- package/src/agent/generator.mjs +2 -2
- package/src/agent/prompt/assistant.txt +12 -0
- package/src/agent/prompt/bug-hunter.txt +89 -89
- package/src/agent/prompt/frontend-designer.txt +58 -58
- package/src/agent/prompt/guide.txt +1 -1
- package/src/agent/prompt/longagent-blueprint-agent.txt +83 -83
- package/src/agent/prompt/longagent-coding-agent.txt +37 -37
- package/src/agent/prompt/longagent-debugging-agent.txt +46 -46
- package/src/agent/prompt/longagent-preview-agent.txt +63 -63
- package/src/command/custom-commands.mjs +2 -2
- package/src/commands/agent.mjs +1 -1
- package/src/commands/background.mjs +145 -4
- package/src/commands/chat.mjs +117 -76
- package/src/commands/config.mjs +148 -1
- package/src/commands/doctor.mjs +30 -6
- package/src/commands/init.mjs +32 -6
- package/src/commands/longagent.mjs +117 -0
- package/src/commands/mcp.mjs +275 -43
- package/src/commands/permission.mjs +1 -1
- package/src/commands/session.mjs +195 -140
- package/src/commands/skill.mjs +63 -0
- package/src/commands/theme.mjs +1 -1
- package/src/commands/update.mjs +32 -0
- package/src/config/defaults.mjs +289 -260
- package/src/config/import-config.mjs +1 -1
- package/src/config/load-config.mjs +61 -4
- package/src/config/schema.mjs +604 -574
- package/src/context.mjs +4 -1
- package/src/core/constants.mjs +97 -91
- package/src/core/types.mjs +1 -1
- package/src/github/api.mjs +78 -78
- package/src/github/auth.mjs +294 -286
- package/src/github/flow.mjs +298 -298
- package/src/github/workspace.mjs +225 -212
- package/src/index.mjs +87 -82
- package/src/knowledge/frontend-aesthetics.txt +38 -38
- package/src/mcp/client-http.mjs +139 -141
- package/src/mcp/client-sse.mjs +297 -288
- package/src/mcp/client-stdio.mjs +534 -533
- package/src/mcp/constants.mjs +4 -2
- package/src/mcp/registry.mjs +498 -479
- package/src/mcp/stdio-framing.mjs +135 -133
- package/src/mcp/tool-result.mjs +24 -24
- package/src/observability/edit-diagnostics.mjs +449 -0
- package/src/observability/index.mjs +42 -42
- package/src/observability/metrics.mjs +165 -137
- package/src/observability/tracer.mjs +137 -137
- package/src/onboarding.mjs +209 -0
- package/src/orchestration/background-manager.mjs +567 -372
- package/src/orchestration/background-worker.mjs +419 -305
- package/src/orchestration/interruption-reason.mjs +21 -0
- package/src/orchestration/longagent-manager.mjs +197 -171
- package/src/orchestration/stage-scheduler.mjs +733 -728
- package/src/orchestration/subagent-router.mjs +7 -1
- package/src/orchestration/task-scheduler.mjs +219 -7
- package/src/permission/engine.mjs +1 -1
- package/src/permission/exec-policy.mjs +370 -370
- package/src/permission/file-edit-policy.mjs +108 -0
- package/src/permission/prompt.mjs +1 -1
- package/src/permission/rules.mjs +116 -7
- package/src/plugin/builtin-hooks/post-edit-format.mjs +2 -1
- package/src/plugin/builtin-hooks/post-edit-typecheck.mjs +104 -40
- package/src/plugin/hook-bus.mjs +19 -5
- package/src/plugin/manifest-loader.mjs +222 -0
- package/src/provider/anthropic.mjs +396 -390
- package/src/provider/ollama.mjs +7 -1
- package/src/provider/openai.mjs +382 -340
- package/src/provider/retry-policy.mjs +74 -68
- package/src/provider/router.mjs +242 -241
- package/src/provider/sse.mjs +104 -104
- package/src/provider/wizard.mjs +556 -0
- package/src/repl/capability-facade.mjs +30 -0
- package/src/repl/command-surface.mjs +23 -0
- package/src/repl/controller-entry.mjs +40 -0
- package/src/repl/core-shell.mjs +208 -0
- package/src/repl/dialog-router.mjs +87 -0
- package/src/repl/input-engine.mjs +76 -0
- package/src/repl/keymap.mjs +7 -0
- package/src/repl/operator-surface.mjs +15 -0
- package/src/repl/permission-flow.mjs +49 -0
- package/src/repl/runtime-facade.mjs +36 -0
- package/src/repl/slash-router.mjs +62 -0
- package/src/repl/state-store.mjs +29 -0
- package/src/repl/turn-controller.mjs +58 -0
- package/src/repl/verification.mjs +23 -0
- package/src/repl.mjs +3371 -2981
- package/src/rules/load-rules.mjs +3 -3
- package/src/runtime.mjs +1 -1
- package/src/session/agent-transaction.mjs +86 -0
- package/src/session/checkpoint.mjs +302 -302
- package/src/session/compaction.mjs +298 -298
- package/src/session/engine.mjs +417 -232
- package/src/session/longagent-4stage.mjs +467 -460
- package/src/session/longagent-hybrid.mjs +1344 -1097
- package/src/session/longagent-plan.mjs +376 -365
- package/src/session/longagent-project-memory.mjs +53 -53
- package/src/session/longagent-scaffold.mjs +291 -291
- package/src/session/longagent-task-bus.mjs +138 -54
- package/src/session/longagent-utils.mjs +828 -472
- package/src/session/longagent.mjs +911 -900
- package/src/session/loop.mjs +1005 -930
- package/src/session/prompt/agent.txt +25 -25
- package/src/session/prompt/anthropic.txt +150 -150
- package/src/session/prompt/beast.txt +1 -1
- package/src/session/prompt/plan.txt +31 -31
- package/src/session/prompt/qwen.txt +46 -46
- package/src/session/recovery.mjs +21 -0
- package/src/session/rollback.mjs +196 -195
- package/src/session/routing-observability.mjs +72 -0
- package/src/session/runtime-state.mjs +47 -0
- package/src/session/store.mjs +523 -519
- package/src/session/system-prompt.mjs +308 -273
- package/src/session/task-validator.mjs +267 -267
- package/src/session/usability-gates.mjs +2 -2
- package/src/skill/builtin/commit.mjs +64 -64
- package/src/skill/builtin/design.mjs +76 -76
- package/src/skill/generator.mjs +18 -2
- package/src/skill/registry.mjs +642 -390
- package/src/storage/audit-store.mjs +18 -11
- package/src/storage/event-log.mjs +7 -1
- package/src/storage/ghost-commit-store.mjs +243 -245
- package/src/storage/paths.mjs +17 -0
- package/src/theme/default-theme.mjs +1 -1
- package/src/theme/markdown.mjs +4 -0
- package/src/theme/schema.mjs +1 -1
- package/src/theme/status-bar.mjs +162 -158
- package/src/tool/audit-wrapper.mjs +18 -2
- package/src/tool/edit-transaction.mjs +23 -0
- package/src/tool/executor.mjs +26 -1
- package/src/tool/file-read-state.mjs +65 -0
- package/src/tool/git-auto.mjs +526 -526
- package/src/tool/git-full-auto.mjs +487 -478
- package/src/tool/mutation-guard.mjs +54 -0
- package/src/tool/prompt/edit.txt +3 -3
- package/src/tool/prompt/multiedit.txt +1 -0
- package/src/tool/prompt/notebookedit.txt +2 -1
- package/src/tool/prompt/patch.txt +25 -24
- package/src/tool/prompt/read.txt +3 -3
- package/src/tool/prompt/sysinfo.txt +29 -0
- package/src/tool/prompt/task.txt +66 -4
- package/src/tool/prompt/write.txt +2 -2
- package/src/tool/question-prompt.mjs +99 -93
- package/src/tool/registry.mjs +1701 -1343
- package/src/tool/task-tool.mjs +14 -6
- package/src/ui/activity-renderer.mjs +667 -664
- package/src/ui/repl-background-panel.mjs +7 -0
- package/src/ui/repl-capability-panel.mjs +9 -0
- package/src/ui/repl-dashboard.mjs +54 -4
- package/src/ui/repl-help.mjs +110 -0
- package/src/ui/repl-operator-panel.mjs +12 -0
- package/src/ui/repl-route-feedback.mjs +35 -0
- package/src/ui/repl-status-view.mjs +76 -0
- package/src/ui/repl-task-panel.mjs +5 -0
- package/src/ui/repl-transcript-panel.mjs +56 -0
- package/src/ui/repl-turn-summary.mjs +135 -0
- package/src/update/checker.mjs +184 -0
- package/src/usage/pricing.mjs +122 -121
- package/src/usage/usage-meter.mjs +1 -0
- package/src/util/git.mjs +562 -519
- package/src/util/template.mjs +6 -1
- package/src/version.mjs +3 -0
|
@@ -1,63 +1,63 @@
|
|
|
1
|
-
=== LONGAGENT STAGE 1/4: PREVIEWING AGENT ===
|
|
2
|
-
|
|
3
|
-
You are the Previewing Agent in the four-stage LongAgent architecture.
|
|
4
|
-
|
|
5
|
-
# YOUR ROLE
|
|
6
|
-
You are responsible for understanding the task, exploring the codebase, and extracting critical information.
|
|
7
|
-
|
|
8
|
-
# STAGE 1: PREVIEW MODE - READ-ONLY
|
|
9
|
-
IMPORTANT: You are in READ-ONLY mode. NO EDITING ALLOWED.
|
|
10
|
-
|
|
11
|
-
CRITICAL CONSTRAINTS:
|
|
12
|
-
- NO file editing (edit, write, multiedit, patch)
|
|
13
|
-
- NO commands that modify filesystem or system state
|
|
14
|
-
- NO git operations (commit, push, etc.)
|
|
15
|
-
- ONLY use: read, glob, grep, list, bash (read-only)
|
|
16
|
-
- This is ZERO-EXCEPTION rule
|
|
17
|
-
|
|
18
|
-
# EXPLORATION OBJECTIVES
|
|
19
|
-
|
|
20
|
-
## 1. Understand User Request
|
|
21
|
-
- Extract core requirements from user input
|
|
22
|
-
- Identify key constraints, goals, and expected outcomes
|
|
23
|
-
- Note any specific files, functions, or patterns mentioned
|
|
24
|
-
|
|
25
|
-
## 2. Explore Project Structure
|
|
26
|
-
- Use `glob` to map the entire codebase
|
|
27
|
-
- Understand directory organization and file naming conventions
|
|
28
|
-
- Identify project type (e.g., Node.js, Python, React, etc.)
|
|
29
|
-
- Locate configuration files (package.json, tsconfig.json, etc.)
|
|
30
|
-
|
|
31
|
-
## 3. Analyze Existing Code
|
|
32
|
-
- Search for relevant existing code using `grep`
|
|
33
|
-
- Read critical files to understand current implementation
|
|
34
|
-
- Identify patterns, utilities, and functions that can be reused
|
|
35
|
-
- Look for tests to understand expected behavior
|
|
36
|
-
- Trace dependencies and import relationships
|
|
37
|
-
|
|
38
|
-
## 4. Extract Key Information
|
|
39
|
-
- Project structure summary
|
|
40
|
-
- Relevant file paths
|
|
41
|
-
- Existing patterns and utilities
|
|
42
|
-
- Potential challenges or constraints
|
|
43
|
-
- Dependencies and their versions
|
|
44
|
-
|
|
45
|
-
# OUTPUT FORMAT
|
|
46
|
-
|
|
47
|
-
Present findings structurally:
|
|
48
|
-
- Project Overview (type, stack, config)
|
|
49
|
-
- Critical Files Identified (to modify/create/reference)
|
|
50
|
-
- Reusable Assets (existing functions, patterns, dependencies)
|
|
51
|
-
- Constraints & Considerations
|
|
52
|
-
|
|
53
|
-
# WORKFLOW
|
|
54
|
-
1. Explore thoroughly - don't rush
|
|
55
|
-
2. Use parallel tool calls for efficiency
|
|
56
|
-
3. Focus on understanding, not solving
|
|
57
|
-
4. Document everything clearly
|
|
58
|
-
5. NO EDITING - STAY IN READ-ONLY MODE
|
|
59
|
-
|
|
60
|
-
End your response with:
|
|
61
|
-
```
|
|
62
|
-
[STAGE 1/4: PREVIEW - COMPLETE]
|
|
63
|
-
```
|
|
1
|
+
=== LONGAGENT STAGE 1/4: PREVIEWING AGENT ===
|
|
2
|
+
|
|
3
|
+
You are the Previewing Agent in the four-stage LongAgent architecture.
|
|
4
|
+
|
|
5
|
+
# YOUR ROLE
|
|
6
|
+
You are responsible for understanding the task, exploring the codebase, and extracting critical information.
|
|
7
|
+
|
|
8
|
+
# STAGE 1: PREVIEW MODE - READ-ONLY
|
|
9
|
+
IMPORTANT: You are in READ-ONLY mode. NO EDITING ALLOWED.
|
|
10
|
+
|
|
11
|
+
CRITICAL CONSTRAINTS:
|
|
12
|
+
- NO file editing (edit, write, multiedit, patch)
|
|
13
|
+
- NO commands that modify filesystem or system state
|
|
14
|
+
- NO git operations (commit, push, etc.)
|
|
15
|
+
- ONLY use: read, glob, grep, list, bash (read-only)
|
|
16
|
+
- This is ZERO-EXCEPTION rule
|
|
17
|
+
|
|
18
|
+
# EXPLORATION OBJECTIVES
|
|
19
|
+
|
|
20
|
+
## 1. Understand User Request
|
|
21
|
+
- Extract core requirements from user input
|
|
22
|
+
- Identify key constraints, goals, and expected outcomes
|
|
23
|
+
- Note any specific files, functions, or patterns mentioned
|
|
24
|
+
|
|
25
|
+
## 2. Explore Project Structure
|
|
26
|
+
- Use `glob` to map the entire codebase
|
|
27
|
+
- Understand directory organization and file naming conventions
|
|
28
|
+
- Identify project type (e.g., Node.js, Python, React, etc.)
|
|
29
|
+
- Locate configuration files (package.json, tsconfig.json, etc.)
|
|
30
|
+
|
|
31
|
+
## 3. Analyze Existing Code
|
|
32
|
+
- Search for relevant existing code using `grep`
|
|
33
|
+
- Read critical files to understand current implementation
|
|
34
|
+
- Identify patterns, utilities, and functions that can be reused
|
|
35
|
+
- Look for tests to understand expected behavior
|
|
36
|
+
- Trace dependencies and import relationships
|
|
37
|
+
|
|
38
|
+
## 4. Extract Key Information
|
|
39
|
+
- Project structure summary
|
|
40
|
+
- Relevant file paths
|
|
41
|
+
- Existing patterns and utilities
|
|
42
|
+
- Potential challenges or constraints
|
|
43
|
+
- Dependencies and their versions
|
|
44
|
+
|
|
45
|
+
# OUTPUT FORMAT
|
|
46
|
+
|
|
47
|
+
Present findings structurally:
|
|
48
|
+
- Project Overview (type, stack, config)
|
|
49
|
+
- Critical Files Identified (to modify/create/reference)
|
|
50
|
+
- Reusable Assets (existing functions, patterns, dependencies)
|
|
51
|
+
- Constraints & Considerations
|
|
52
|
+
|
|
53
|
+
# WORKFLOW
|
|
54
|
+
1. Explore thoroughly - don't rush
|
|
55
|
+
2. Use parallel tool calls for efficiency
|
|
56
|
+
3. Focus on understanding, not solving
|
|
57
|
+
4. Document everything clearly
|
|
58
|
+
5. NO EDITING - STAY IN READ-ONLY MODE
|
|
59
|
+
|
|
60
|
+
End your response with:
|
|
61
|
+
```
|
|
62
|
+
[STAGE 1/4: PREVIEW - COMPLETE]
|
|
63
|
+
```
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import path from "node:path"
|
|
2
2
|
import { access, readdir, readFile } from "node:fs/promises"
|
|
3
3
|
import { renderTemplate } from "../util/template.mjs"
|
|
4
|
+
import { userRootDir } from "../storage/paths.mjs"
|
|
4
5
|
|
|
5
6
|
async function exists(target) {
|
|
6
7
|
try {
|
|
@@ -34,8 +35,7 @@ async function loadDir(dir, scope) {
|
|
|
34
35
|
}
|
|
35
36
|
|
|
36
37
|
export async function loadCustomCommands(cwd = process.cwd()) {
|
|
37
|
-
const
|
|
38
|
-
const userDir = path.join(userRoot, ".kkcode", "commands")
|
|
38
|
+
const userDir = path.join(userRootDir(), "commands")
|
|
39
39
|
const projectDir = path.join(cwd, ".kkcode", "commands")
|
|
40
40
|
const [globalCommands, projectCommands] = await Promise.all([loadDir(userDir, "global"), loadDir(projectDir, "project")])
|
|
41
41
|
const map = new Map()
|
package/src/commands/agent.mjs
CHANGED
|
@@ -9,16 +9,100 @@ async function withContext(action) {
|
|
|
9
9
|
return action(ctx)
|
|
10
10
|
}
|
|
11
11
|
|
|
12
|
+
function printTaskSummary(task) {
|
|
13
|
+
const summary = BackgroundManager.summarize(task)
|
|
14
|
+
if (!summary) return
|
|
15
|
+
console.log(`[${summary.status}] ${summary.id} :: ${summary.description}`)
|
|
16
|
+
console.log(` attempt=${summary.attempt} subagent=${summary.subagent || "-"} execution_mode=${summary.execution_mode || "-"} session=${summary.session_id || "-"}`)
|
|
17
|
+
if (summary.interruption_reason) {
|
|
18
|
+
console.log(` interruption=${summary.interruption_reason}`)
|
|
19
|
+
}
|
|
20
|
+
if (summary.result_preview) {
|
|
21
|
+
console.log(` preview=${summary.result_preview}`)
|
|
22
|
+
}
|
|
23
|
+
console.log(` next=${summary.next_action}`)
|
|
24
|
+
}
|
|
25
|
+
|
|
12
26
|
export function createBackgroundCommand() {
|
|
13
27
|
const cmd = new Command("background").description("inspect background delegated tasks")
|
|
14
28
|
|
|
15
29
|
cmd
|
|
16
30
|
.command("list")
|
|
17
31
|
.description("list background tasks")
|
|
18
|
-
.
|
|
32
|
+
.option("--json", "print raw JSON")
|
|
33
|
+
.option("--status <status>", "filter by status")
|
|
34
|
+
.action(async (options) => {
|
|
19
35
|
await withContext(async () => {
|
|
20
|
-
const list = await BackgroundManager.list()
|
|
21
|
-
|
|
36
|
+
const list = (await BackgroundManager.list()).filter((task) => {
|
|
37
|
+
if (!options.status) return true
|
|
38
|
+
return String(task.status || "") === String(options.status || "")
|
|
39
|
+
})
|
|
40
|
+
if (options.json) {
|
|
41
|
+
console.log(JSON.stringify(list, null, 2))
|
|
42
|
+
return
|
|
43
|
+
}
|
|
44
|
+
const aggregate = BackgroundManager.summarizeList(list)
|
|
45
|
+
console.log(`summary: total=${aggregate.total} active=${aggregate.active} pending=${aggregate.counts.pending} running=${aggregate.counts.running} completed=${aggregate.counts.completed} interrupted=${aggregate.counts.interrupted} error=${aggregate.counts.error}`)
|
|
46
|
+
if (aggregate.recent_terminal.length) {
|
|
47
|
+
console.log(`recent terminal: ${aggregate.recent_terminal.map((item) => `${item.id}:${item.status}`).join(" | ")}`)
|
|
48
|
+
}
|
|
49
|
+
if (!list.length) {
|
|
50
|
+
console.log("no background tasks")
|
|
51
|
+
return
|
|
52
|
+
}
|
|
53
|
+
for (const task of list) {
|
|
54
|
+
printTaskSummary(task)
|
|
55
|
+
}
|
|
56
|
+
})
|
|
57
|
+
})
|
|
58
|
+
|
|
59
|
+
cmd
|
|
60
|
+
.command("output")
|
|
61
|
+
.description("print the terminal result payload for one background task")
|
|
62
|
+
.requiredOption("--id <id>", "task id")
|
|
63
|
+
.action(async (options) => {
|
|
64
|
+
await withContext(async () => {
|
|
65
|
+
const task = await BackgroundManager.get(options.id)
|
|
66
|
+
if (!task) {
|
|
67
|
+
console.error(`not found: ${options.id}`)
|
|
68
|
+
process.exitCode = 1
|
|
69
|
+
return
|
|
70
|
+
}
|
|
71
|
+
if (!task.result) {
|
|
72
|
+
console.log(JSON.stringify(BackgroundManager.summarize(task), null, 2))
|
|
73
|
+
return
|
|
74
|
+
}
|
|
75
|
+
console.log(JSON.stringify(task.result, null, 2))
|
|
76
|
+
})
|
|
77
|
+
})
|
|
78
|
+
|
|
79
|
+
cmd
|
|
80
|
+
.command("wait")
|
|
81
|
+
.description("wait for one background task to reach a terminal state")
|
|
82
|
+
.requiredOption("--id <id>", "task id")
|
|
83
|
+
.option("--timeout <ms>", "wait timeout in milliseconds", "30000")
|
|
84
|
+
.option("--json", "print raw JSON")
|
|
85
|
+
.action(async (options) => {
|
|
86
|
+
await withContext(async (ctx) => {
|
|
87
|
+
const task = await BackgroundManager.waitForTask(options.id, {
|
|
88
|
+
timeoutMs: Number(options.timeout || 30000),
|
|
89
|
+
config: ctx.configState.config
|
|
90
|
+
})
|
|
91
|
+
if (!task) {
|
|
92
|
+
console.error(`not found: ${options.id}`)
|
|
93
|
+
process.exitCode = 1
|
|
94
|
+
return
|
|
95
|
+
}
|
|
96
|
+
if (!["completed", "cancelled", "error", "interrupted"].includes(task.status)) {
|
|
97
|
+
console.error(`timeout waiting for task: ${options.id} (status=${task.status})`)
|
|
98
|
+
process.exitCode = 1
|
|
99
|
+
return
|
|
100
|
+
}
|
|
101
|
+
if (options.json) {
|
|
102
|
+
console.log(JSON.stringify(task, null, 2))
|
|
103
|
+
return
|
|
104
|
+
}
|
|
105
|
+
printTaskSummary(task)
|
|
22
106
|
})
|
|
23
107
|
})
|
|
24
108
|
|
|
@@ -26,6 +110,7 @@ export function createBackgroundCommand() {
|
|
|
26
110
|
.command("show")
|
|
27
111
|
.description("show one background task")
|
|
28
112
|
.requiredOption("--id <id>", "task id")
|
|
113
|
+
.option("--json", "print raw JSON")
|
|
29
114
|
.action(async (options) => {
|
|
30
115
|
await withContext(async () => {
|
|
31
116
|
const task = await BackgroundManager.get(options.id)
|
|
@@ -34,7 +119,47 @@ export function createBackgroundCommand() {
|
|
|
34
119
|
process.exitCode = 1
|
|
35
120
|
return
|
|
36
121
|
}
|
|
37
|
-
|
|
122
|
+
if (options.json) {
|
|
123
|
+
console.log(JSON.stringify(task, null, 2))
|
|
124
|
+
return
|
|
125
|
+
}
|
|
126
|
+
printTaskSummary(task)
|
|
127
|
+
const summary = BackgroundManager.summarize(task)
|
|
128
|
+
if (summary?.log_tail?.length) {
|
|
129
|
+
console.log(" log tail:")
|
|
130
|
+
for (const line of summary.log_tail) {
|
|
131
|
+
console.log(` ${line}`)
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
if (task.result) {
|
|
135
|
+
console.log(" result:")
|
|
136
|
+
console.log(JSON.stringify(task.result, null, 2))
|
|
137
|
+
}
|
|
138
|
+
})
|
|
139
|
+
})
|
|
140
|
+
|
|
141
|
+
cmd
|
|
142
|
+
.command("logs")
|
|
143
|
+
.description("show recent log lines for one background task")
|
|
144
|
+
.requiredOption("--id <id>", "task id")
|
|
145
|
+
.option("--tail <n>", "number of lines to show", "20")
|
|
146
|
+
.action(async (options) => {
|
|
147
|
+
await withContext(async () => {
|
|
148
|
+
const task = await BackgroundManager.get(options.id)
|
|
149
|
+
if (!task) {
|
|
150
|
+
console.error(`not found: ${options.id}`)
|
|
151
|
+
process.exitCode = 1
|
|
152
|
+
return
|
|
153
|
+
}
|
|
154
|
+
const tailCount = Math.max(1, Number(options.tail || 20))
|
|
155
|
+
const lines = Array.isArray(task.logs) ? task.logs.slice(-tailCount) : []
|
|
156
|
+
if (!lines.length) {
|
|
157
|
+
console.log(`no logs yet: ${options.id}`)
|
|
158
|
+
return
|
|
159
|
+
}
|
|
160
|
+
for (const line of lines) {
|
|
161
|
+
console.log(line)
|
|
162
|
+
}
|
|
38
163
|
})
|
|
39
164
|
})
|
|
40
165
|
|
|
@@ -54,6 +179,22 @@ export function createBackgroundCommand() {
|
|
|
54
179
|
})
|
|
55
180
|
})
|
|
56
181
|
|
|
182
|
+
cmd
|
|
183
|
+
.command("stop")
|
|
184
|
+
.description("alias for cancel")
|
|
185
|
+
.requiredOption("--id <id>", "task id")
|
|
186
|
+
.action(async (options) => {
|
|
187
|
+
await withContext(async () => {
|
|
188
|
+
const ok = await BackgroundManager.cancel(options.id)
|
|
189
|
+
if (!ok) {
|
|
190
|
+
console.error(`not found: ${options.id}`)
|
|
191
|
+
process.exitCode = 1
|
|
192
|
+
return
|
|
193
|
+
}
|
|
194
|
+
console.log(`cancel requested: ${options.id}`)
|
|
195
|
+
})
|
|
196
|
+
})
|
|
197
|
+
|
|
57
198
|
cmd
|
|
58
199
|
.command("retry")
|
|
59
200
|
.description("retry one interrupted/error background task")
|
package/src/commands/chat.mjs
CHANGED
|
@@ -1,68 +1,109 @@
|
|
|
1
|
-
import { Command } from "commander"
|
|
2
|
-
import { buildContext, printContextWarnings } from "../context.mjs"
|
|
3
|
-
import { executeTurn, newSessionId, resolveMode } from "../session/engine.mjs"
|
|
4
|
-
import {
|
|
1
|
+
import { Command } from "commander"
|
|
2
|
+
import { buildContext, printContextWarnings } from "../context.mjs"
|
|
3
|
+
import { ensureEventSinks, executeTurn, formatPublicModeSummary, getPublicModeContract, newSessionId, resolveMode, resolvePromptMode, summarizeRouteDecision } from "../session/engine.mjs"
|
|
4
|
+
import { emitRouteDecisionEvent } from "../session/routing-observability.mjs"
|
|
5
|
+
import { renderStatusBar } from "../theme/status-bar.mjs"
|
|
5
6
|
import { applyCommandTemplate, loadCustomCommands } from "../command/custom-commands.mjs"
|
|
6
7
|
import { ToolRegistry } from "../tool/registry.mjs"
|
|
8
|
+
import { SkillRegistry } from "../skill/registry.mjs"
|
|
9
|
+
import { PermissionEngine } from "../permission/engine.mjs"
|
|
7
10
|
import { HookBus, initHookBus } from "../plugin/hook-bus.mjs"
|
|
8
11
|
import { listProviders } from "../provider/router.mjs"
|
|
12
|
+
import { EventBus } from "../core/events.mjs"
|
|
13
|
+
import { EVENT_TYPES } from "../core/constants.mjs"
|
|
14
|
+
|
|
15
|
+
export function resolveChatExecutionMode(prompt, requestedMode) {
|
|
16
|
+
return resolvePromptMode(prompt, requestedMode)
|
|
17
|
+
}
|
|
9
18
|
|
|
10
19
|
export function createChatCommand() {
|
|
11
20
|
const providers = listProviders()
|
|
12
21
|
return new Command("chat")
|
|
13
|
-
.description("run one prompt in
|
|
22
|
+
.description("run one prompt in assistant/plan/agent/code/longagent mode (assistant = default personal lane)")
|
|
14
23
|
.argument("<prompt...>", "prompt text")
|
|
15
|
-
.option("--mode <mode>", "
|
|
24
|
+
.option("--mode <mode>", "assistant|plan|agent|code|coding|longagent", "assistant")
|
|
16
25
|
.option("--model <model>", "model id")
|
|
17
26
|
.option("--provider-type <type>", `provider type (${providers.join("|")})`)
|
|
18
|
-
.option("--base-url <url>", "provider base url override")
|
|
19
|
-
.option("--api-key-env <name>", "api key env override")
|
|
20
|
-
.option("--max-iterations <n>", "longagent max iterations (0 = unlimited)")
|
|
21
|
-
.option("--session <id>", "session id")
|
|
22
|
-
.action(async (promptParts, options) => {
|
|
23
|
-
const ctx = await buildContext()
|
|
24
|
-
printContextWarnings(ctx)
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
const
|
|
29
|
-
const
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
const
|
|
40
|
-
const
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
const
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
await
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
27
|
+
.option("--base-url <url>", "provider base url override")
|
|
28
|
+
.option("--api-key-env <name>", "api key env override")
|
|
29
|
+
.option("--max-iterations <n>", "longagent max iterations (0 = unlimited)")
|
|
30
|
+
.option("--session <id>", "session id")
|
|
31
|
+
.action(async (promptParts, options) => {
|
|
32
|
+
const ctx = await buildContext()
|
|
33
|
+
printContextWarnings(ctx)
|
|
34
|
+
PermissionEngine.setTrusted(ctx.trustState?.trusted !== false)
|
|
35
|
+
let prompt = promptParts.join(" ").trim()
|
|
36
|
+
if (prompt.startsWith("/")) {
|
|
37
|
+
const commands = await loadCustomCommands(process.cwd())
|
|
38
|
+
const [name, ...argTokens] = prompt.slice(1).split(/\s+/)
|
|
39
|
+
const custom = commands.find((item) => item.name === name)
|
|
40
|
+
if (custom) {
|
|
41
|
+
const args = argTokens.join(" ").trim()
|
|
42
|
+
prompt = applyCommandTemplate(custom.template, args, {
|
|
43
|
+
path: process.cwd()
|
|
44
|
+
})
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const mode = resolveMode(options.mode)
|
|
49
|
+
const providerType = options.providerType ?? ctx.configState.config.provider.default
|
|
50
|
+
const providerDefaults = ctx.configState.config.provider[providerType]
|
|
51
|
+
if (!providerDefaults) {
|
|
52
|
+
throw new Error(`unknown provider type: ${providerType}`)
|
|
53
|
+
}
|
|
54
|
+
const model = options.model ?? providerDefaults.default_model
|
|
55
|
+
const sessionId = options.session || newSessionId()
|
|
56
|
+
|
|
57
|
+
await ToolRegistry.initialize({
|
|
58
|
+
config: ctx.configState.config,
|
|
59
|
+
cwd: process.cwd()
|
|
60
|
+
})
|
|
61
|
+
await SkillRegistry.initialize(ctx.configState.config, process.cwd())
|
|
62
|
+
|
|
63
|
+
await initHookBus()
|
|
64
|
+
const chatParams = await HookBus.chatParams({
|
|
65
|
+
prompt,
|
|
66
|
+
mode,
|
|
67
|
+
model,
|
|
68
|
+
providerType,
|
|
69
|
+
sessionId,
|
|
70
|
+
baseUrl: options.baseUrl ?? null,
|
|
71
|
+
apiKeyEnv: options.apiKeyEnv ?? null
|
|
72
|
+
})
|
|
73
|
+
|
|
74
|
+
const routedMode = resolveChatExecutionMode(chatParams.prompt ?? prompt, chatParams.mode ?? mode)
|
|
75
|
+
const effectiveMode = routedMode.effectiveMode
|
|
76
|
+
const effectiveExplanation = routedMode.route.explanation || routedMode.route.reason
|
|
77
|
+
const requestedContract = getPublicModeContract(routedMode.requestedMode)
|
|
78
|
+
const effectiveContract = routedMode.effectiveContract || getPublicModeContract(effectiveMode)
|
|
79
|
+
ensureEventSinks()
|
|
80
|
+
await emitRouteDecisionEvent({
|
|
81
|
+
sessionId,
|
|
82
|
+
source: "chat",
|
|
83
|
+
requestedMode: routedMode.requestedMode,
|
|
84
|
+
route: routedMode.route,
|
|
85
|
+
prompt: chatParams.prompt ?? prompt
|
|
86
|
+
})
|
|
87
|
+
|
|
88
|
+
if (routedMode.route.changed) {
|
|
89
|
+
console.log(`mode routed: ${routedMode.requestedMode} -> ${effectiveMode} (${effectiveExplanation})`)
|
|
90
|
+
} else if (routedMode.route.forced && routedMode.route.suggestion) {
|
|
91
|
+
console.log(`mode kept: ${effectiveMode} (${effectiveExplanation}; suggested ${routedMode.route.suggestion})`)
|
|
92
|
+
} else if (routedMode.route.suggestion === "longagent" && (routedMode.requestedMode === "assistant" || routedMode.requestedMode === "agent")) {
|
|
93
|
+
console.log(`mode note: ${effectiveMode} (${effectiveExplanation}; consider --mode longagent)`)
|
|
94
|
+
} else {
|
|
95
|
+
console.log(`mode: ${effectiveMode} (${effectiveExplanation})`)
|
|
96
|
+
}
|
|
97
|
+
if (routedMode.requestedMode !== effectiveMode) {
|
|
98
|
+
console.log(`requested lane: ${requestedContract.summary}`)
|
|
99
|
+
}
|
|
100
|
+
console.log(`effective lane: ${formatPublicModeSummary(effectiveMode)}`)
|
|
101
|
+
console.log(`lane guarantee: ${effectiveContract.guarantee}`)
|
|
102
|
+
console.log(`route summary: ${summarizeRouteDecision(routedMode.route)}`)
|
|
103
|
+
|
|
63
104
|
const result = await executeTurn({
|
|
64
105
|
prompt: chatParams.prompt ?? prompt,
|
|
65
|
-
mode:
|
|
106
|
+
mode: effectiveMode,
|
|
66
107
|
model: chatParams.model ?? model,
|
|
67
108
|
sessionId,
|
|
68
109
|
configState: ctx.configState,
|
|
@@ -74,41 +115,41 @@ export function createChatCommand() {
|
|
|
74
115
|
? { write: (chunk) => process.stdout.write(String(chunk || "")) }
|
|
75
116
|
: null
|
|
76
117
|
})
|
|
77
|
-
|
|
118
|
+
|
|
78
119
|
const status = renderStatusBar({
|
|
79
|
-
mode,
|
|
120
|
+
mode: effectiveMode,
|
|
80
121
|
model: result.model,
|
|
81
|
-
permission: ctx.configState.config.permission.default_policy,
|
|
122
|
+
permission: ctx.configState.config.permission.mode || ctx.configState.config.permission.default_policy,
|
|
82
123
|
tokenMeter: result.tokenMeter,
|
|
83
|
-
aggregation: ctx.configState.config.usage.aggregation,
|
|
84
|
-
cost: result.cost,
|
|
124
|
+
aggregation: ctx.configState.config.usage.aggregation,
|
|
125
|
+
cost: result.cost,
|
|
85
126
|
showCost: ctx.configState.config.ui.status.show_cost,
|
|
86
127
|
showTokenMeter: ctx.configState.config.ui.status.show_token_meter,
|
|
87
128
|
theme: ctx.themeState.theme,
|
|
88
129
|
layout: ctx.configState.config.ui.layout,
|
|
89
|
-
longagentState:
|
|
130
|
+
longagentState: effectiveMode === "longagent" ? result.longagent : null
|
|
90
131
|
})
|
|
91
|
-
|
|
132
|
+
|
|
92
133
|
console.log(status)
|
|
93
134
|
console.log("")
|
|
94
135
|
const streamEnabled = ctx.configState.config.provider[chatParams.providerType ?? providerType]?.stream !== false
|
|
95
136
|
if (!streamEnabled || !result.emittedText) {
|
|
96
137
|
console.log(result.reply)
|
|
97
138
|
}
|
|
98
|
-
console.log("")
|
|
99
|
-
if (result.toolEvents.length) {
|
|
100
|
-
console.log(`tool events: ${result.toolEvents.length}`)
|
|
101
|
-
}
|
|
102
|
-
if (result.pricingWarnings.length) {
|
|
103
|
-
for (const warning of result.pricingWarnings) {
|
|
104
|
-
console.log(`pricing warning: ${warning}`)
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
if (result.budgetWarnings.length) {
|
|
108
|
-
for (const warning of result.budgetWarnings) {
|
|
109
|
-
console.log(`budget warning: ${warning}`)
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
console.log(`session: ${sessionId}`)
|
|
113
|
-
})
|
|
114
|
-
}
|
|
139
|
+
console.log("")
|
|
140
|
+
if (result.toolEvents.length) {
|
|
141
|
+
console.log(`tool events: ${result.toolEvents.length}`)
|
|
142
|
+
}
|
|
143
|
+
if (result.pricingWarnings.length) {
|
|
144
|
+
for (const warning of result.pricingWarnings) {
|
|
145
|
+
console.log(`pricing warning: ${warning}`)
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
if (result.budgetWarnings.length) {
|
|
149
|
+
for (const warning of result.budgetWarnings) {
|
|
150
|
+
console.log(`budget warning: ${warning}`)
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
console.log(`session: ${sessionId}`)
|
|
154
|
+
})
|
|
155
|
+
}
|