@kkelly-offical/kkcode 0.1.7 → 0.2.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.
Files changed (163) hide show
  1. package/LICENSE +674 -674
  2. package/README.md +452 -387
  3. package/package.json +50 -46
  4. package/src/agent/agent.mjs +228 -220
  5. package/src/agent/custom-agent-loader.mjs +6 -3
  6. package/src/agent/generator.mjs +2 -2
  7. package/src/agent/prompt/assistant.txt +12 -0
  8. package/src/agent/prompt/bug-hunter.txt +89 -89
  9. package/src/agent/prompt/frontend-designer.txt +58 -58
  10. package/src/agent/prompt/guide.txt +1 -1
  11. package/src/agent/prompt/longagent-blueprint-agent.txt +83 -83
  12. package/src/agent/prompt/longagent-coding-agent.txt +37 -37
  13. package/src/agent/prompt/longagent-debugging-agent.txt +46 -46
  14. package/src/agent/prompt/longagent-preview-agent.txt +63 -63
  15. package/src/command/custom-commands.mjs +2 -2
  16. package/src/commands/agent.mjs +1 -1
  17. package/src/commands/background.mjs +145 -4
  18. package/src/commands/chat.mjs +117 -76
  19. package/src/commands/config.mjs +148 -1
  20. package/src/commands/doctor.mjs +30 -6
  21. package/src/commands/init.mjs +32 -6
  22. package/src/commands/longagent.mjs +117 -0
  23. package/src/commands/mcp.mjs +275 -43
  24. package/src/commands/permission.mjs +1 -1
  25. package/src/commands/session.mjs +195 -140
  26. package/src/commands/skill.mjs +63 -0
  27. package/src/commands/theme.mjs +1 -1
  28. package/src/config/defaults.mjs +280 -260
  29. package/src/config/import-config.mjs +1 -1
  30. package/src/config/load-config.mjs +61 -4
  31. package/src/config/schema.mjs +591 -574
  32. package/src/context.mjs +4 -1
  33. package/src/core/constants.mjs +97 -91
  34. package/src/core/types.mjs +1 -1
  35. package/src/github/api.mjs +78 -78
  36. package/src/github/auth.mjs +294 -286
  37. package/src/github/flow.mjs +298 -298
  38. package/src/github/workspace.mjs +225 -212
  39. package/src/index.mjs +84 -82
  40. package/src/knowledge/frontend-aesthetics.txt +38 -38
  41. package/src/mcp/client-http.mjs +139 -141
  42. package/src/mcp/client-sse.mjs +297 -288
  43. package/src/mcp/client-stdio.mjs +534 -533
  44. package/src/mcp/constants.mjs +2 -2
  45. package/src/mcp/registry.mjs +498 -479
  46. package/src/mcp/stdio-framing.mjs +135 -133
  47. package/src/mcp/tool-result.mjs +24 -24
  48. package/src/observability/edit-diagnostics.mjs +449 -0
  49. package/src/observability/index.mjs +42 -42
  50. package/src/observability/metrics.mjs +165 -137
  51. package/src/observability/tracer.mjs +137 -137
  52. package/src/onboarding.mjs +209 -0
  53. package/src/orchestration/background-manager.mjs +567 -372
  54. package/src/orchestration/background-worker.mjs +419 -305
  55. package/src/orchestration/interruption-reason.mjs +21 -0
  56. package/src/orchestration/longagent-manager.mjs +197 -171
  57. package/src/orchestration/stage-scheduler.mjs +733 -728
  58. package/src/orchestration/subagent-router.mjs +7 -1
  59. package/src/orchestration/task-scheduler.mjs +219 -7
  60. package/src/permission/engine.mjs +1 -1
  61. package/src/permission/exec-policy.mjs +370 -370
  62. package/src/permission/file-edit-policy.mjs +108 -0
  63. package/src/permission/prompt.mjs +1 -1
  64. package/src/permission/rules.mjs +116 -7
  65. package/src/plugin/builtin-hooks/post-edit-format.mjs +2 -1
  66. package/src/plugin/builtin-hooks/post-edit-typecheck.mjs +104 -40
  67. package/src/plugin/hook-bus.mjs +19 -5
  68. package/src/plugin/manifest-loader.mjs +222 -0
  69. package/src/provider/anthropic.mjs +396 -390
  70. package/src/provider/ollama.mjs +7 -1
  71. package/src/provider/openai.mjs +382 -340
  72. package/src/provider/retry-policy.mjs +74 -68
  73. package/src/provider/router.mjs +242 -241
  74. package/src/provider/sse.mjs +104 -104
  75. package/src/provider/wizard.mjs +556 -0
  76. package/src/repl/capability-facade.mjs +30 -0
  77. package/src/repl/command-surface.mjs +23 -0
  78. package/src/repl/controller-entry.mjs +40 -0
  79. package/src/repl/core-shell.mjs +208 -0
  80. package/src/repl/dialog-router.mjs +87 -0
  81. package/src/repl/input-engine.mjs +76 -0
  82. package/src/repl/keymap.mjs +7 -0
  83. package/src/repl/operator-surface.mjs +15 -0
  84. package/src/repl/permission-flow.mjs +49 -0
  85. package/src/repl/runtime-facade.mjs +36 -0
  86. package/src/repl/slash-router.mjs +62 -0
  87. package/src/repl/state-store.mjs +29 -0
  88. package/src/repl/turn-controller.mjs +58 -0
  89. package/src/repl/verification.mjs +23 -0
  90. package/src/repl.mjs +3368 -2981
  91. package/src/rules/load-rules.mjs +3 -3
  92. package/src/runtime.mjs +1 -1
  93. package/src/session/agent-transaction.mjs +86 -0
  94. package/src/session/checkpoint.mjs +302 -302
  95. package/src/session/compaction.mjs +298 -298
  96. package/src/session/engine.mjs +417 -232
  97. package/src/session/longagent-4stage.mjs +467 -460
  98. package/src/session/longagent-hybrid.mjs +1344 -1097
  99. package/src/session/longagent-plan.mjs +376 -365
  100. package/src/session/longagent-project-memory.mjs +53 -53
  101. package/src/session/longagent-scaffold.mjs +291 -291
  102. package/src/session/longagent-task-bus.mjs +138 -54
  103. package/src/session/longagent-utils.mjs +828 -472
  104. package/src/session/longagent.mjs +911 -900
  105. package/src/session/loop.mjs +1005 -930
  106. package/src/session/prompt/agent.txt +25 -25
  107. package/src/session/prompt/anthropic.txt +150 -150
  108. package/src/session/prompt/beast.txt +1 -1
  109. package/src/session/prompt/plan.txt +31 -31
  110. package/src/session/prompt/qwen.txt +46 -46
  111. package/src/session/recovery.mjs +21 -0
  112. package/src/session/rollback.mjs +196 -195
  113. package/src/session/routing-observability.mjs +72 -0
  114. package/src/session/runtime-state.mjs +47 -0
  115. package/src/session/store.mjs +523 -519
  116. package/src/session/system-prompt.mjs +308 -273
  117. package/src/session/task-validator.mjs +267 -267
  118. package/src/session/usability-gates.mjs +2 -2
  119. package/src/skill/builtin/commit.mjs +64 -64
  120. package/src/skill/builtin/design.mjs +76 -76
  121. package/src/skill/generator.mjs +18 -2
  122. package/src/skill/registry.mjs +642 -390
  123. package/src/storage/audit-store.mjs +18 -11
  124. package/src/storage/event-log.mjs +7 -1
  125. package/src/storage/ghost-commit-store.mjs +243 -245
  126. package/src/storage/paths.mjs +13 -0
  127. package/src/theme/default-theme.mjs +1 -1
  128. package/src/theme/markdown.mjs +4 -0
  129. package/src/theme/schema.mjs +1 -1
  130. package/src/theme/status-bar.mjs +162 -158
  131. package/src/tool/audit-wrapper.mjs +18 -2
  132. package/src/tool/edit-transaction.mjs +23 -0
  133. package/src/tool/executor.mjs +26 -1
  134. package/src/tool/file-read-state.mjs +65 -0
  135. package/src/tool/git-auto.mjs +526 -526
  136. package/src/tool/git-full-auto.mjs +487 -478
  137. package/src/tool/mutation-guard.mjs +54 -0
  138. package/src/tool/prompt/edit.txt +3 -3
  139. package/src/tool/prompt/multiedit.txt +1 -0
  140. package/src/tool/prompt/notebookedit.txt +2 -1
  141. package/src/tool/prompt/patch.txt +25 -24
  142. package/src/tool/prompt/read.txt +3 -3
  143. package/src/tool/prompt/sysinfo.txt +29 -0
  144. package/src/tool/prompt/task.txt +66 -4
  145. package/src/tool/prompt/write.txt +2 -2
  146. package/src/tool/question-prompt.mjs +99 -93
  147. package/src/tool/registry.mjs +1701 -1343
  148. package/src/tool/task-tool.mjs +14 -6
  149. package/src/ui/activity-renderer.mjs +667 -664
  150. package/src/ui/repl-background-panel.mjs +7 -0
  151. package/src/ui/repl-capability-panel.mjs +9 -0
  152. package/src/ui/repl-dashboard.mjs +54 -4
  153. package/src/ui/repl-help.mjs +110 -0
  154. package/src/ui/repl-operator-panel.mjs +12 -0
  155. package/src/ui/repl-route-feedback.mjs +35 -0
  156. package/src/ui/repl-status-view.mjs +76 -0
  157. package/src/ui/repl-task-panel.mjs +5 -0
  158. package/src/ui/repl-transcript-panel.mjs +56 -0
  159. package/src/ui/repl-turn-summary.mjs +135 -0
  160. package/src/usage/pricing.mjs +122 -121
  161. package/src/usage/usage-meter.mjs +1 -0
  162. package/src/util/git.mjs +562 -519
  163. package/src/util/template.mjs +6 -1
@@ -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 userRoot = process.env.USERPROFILE || process.env.HOME || cwd
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()
@@ -68,4 +68,4 @@ export function createAgentCommand() {
68
68
  })
69
69
 
70
70
  return cmd
71
- }
71
+ }
@@ -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
- .action(async () => {
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
- console.log(JSON.stringify(list, null, 2))
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
- console.log(JSON.stringify(task, null, 2))
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")
@@ -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 { renderStatusBar } from "../theme/status-bar.mjs"
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 ask/plan/agent/longagent mode")
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>", "ask|plan|agent|longagent", "agent")
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
- let prompt = promptParts.join(" ").trim()
26
- if (prompt.startsWith("/")) {
27
- const commands = await loadCustomCommands(process.cwd())
28
- const [name, ...argTokens] = prompt.slice(1).split(/\s+/)
29
- const custom = commands.find((item) => item.name === name)
30
- if (custom) {
31
- const args = argTokens.join(" ").trim()
32
- prompt = applyCommandTemplate(custom.template, args, {
33
- path: process.cwd()
34
- })
35
- }
36
- }
37
-
38
- const mode = resolveMode(options.mode)
39
- const providerType = options.providerType ?? ctx.configState.config.provider.default
40
- const providerDefaults = ctx.configState.config.provider[providerType]
41
- if (!providerDefaults) {
42
- throw new Error(`unknown provider type: ${providerType}`)
43
- }
44
- const model = options.model ?? providerDefaults.default_model
45
- const sessionId = options.session || newSessionId()
46
-
47
- await ToolRegistry.initialize({
48
- config: ctx.configState.config,
49
- cwd: process.cwd()
50
- })
51
-
52
- await initHookBus()
53
- const chatParams = await HookBus.chatParams({
54
- prompt,
55
- mode,
56
- model,
57
- providerType,
58
- sessionId,
59
- baseUrl: options.baseUrl ?? null,
60
- apiKeyEnv: options.apiKeyEnv ?? null
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: chatParams.mode ?? 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: mode === "longagent" ? result.longagent : null
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
+ }