@sayknow-cli/coding-agent 0.3.5 → 0.3.7
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/README.md +76 -0
- package/dist/types/capability/mcp.d.ts +2 -0
- package/dist/types/cli/local-provider-smoke.d.ts +59 -0
- package/dist/types/cli/notify-cli.d.ts +1 -1
- package/dist/types/cli/telegram-cli.d.ts +13 -0
- package/dist/types/cli/update-cli.d.ts +24 -1
- package/dist/types/commands/local-provider.d.ts +34 -0
- package/dist/types/commands/telegram.d.ts +22 -0
- package/dist/types/config/keybindings.d.ts +12 -6
- package/dist/types/config/model-registry.d.ts +5 -0
- package/dist/types/config/models-config-schema.d.ts +5 -0
- package/dist/types/config/settings-schema.d.ts +284 -4
- package/dist/types/config/settings.d.ts +7 -0
- package/dist/types/config/telegram-autostart.d.ts +14 -0
- package/dist/types/config/telegram-env-bridge.d.ts +18 -0
- package/dist/types/coordinator-mcp/server.d.ts +8 -0
- package/dist/types/defaults/skc-defaults.d.ts +7 -0
- package/dist/types/discovery/cursor.d.ts +4 -1
- package/dist/types/discovery/index.d.ts +0 -1
- package/dist/types/discovery/windsurf.d.ts +3 -1
- package/dist/types/extensibility/extensions/types.d.ts +11 -0
- package/dist/types/i18n/messages/en.d.ts +1 -0
- package/dist/types/modes/components/custom-editor.d.ts +6 -1
- package/dist/types/modes/components/custom-model-preset-wizard.d.ts +1 -1
- package/dist/types/modes/components/hook-selector.d.ts +5 -0
- package/dist/types/modes/components/model-selector.d.ts +2 -0
- package/dist/types/modes/components/settings-selector.d.ts +5 -1
- package/dist/types/modes/components/skill-message.d.ts +1 -0
- package/dist/types/modes/components/status-line/types.d.ts +5 -7
- package/dist/types/modes/components/status-line.d.ts +15 -3
- package/dist/types/modes/components/two-column-body.d.ts +9 -0
- package/dist/types/modes/components/welcome.d.ts +9 -1
- package/dist/types/modes/controllers/command-controller.d.ts +1 -0
- package/dist/types/modes/controllers/input-controller.d.ts +6 -1
- package/dist/types/modes/controllers/selector-controller.d.ts +10 -1
- package/dist/types/modes/interactive-mode.d.ts +2 -0
- package/dist/types/modes/prompt-action-autocomplete.d.ts +3 -0
- package/dist/types/modes/rpc/rpc-types.d.ts +1 -0
- package/dist/types/modes/shared/agent-wire/deep-interview-gate.d.ts +41 -7
- package/dist/types/modes/slash-command-visibility.d.ts +1 -0
- package/dist/types/modes/theme/theme.d.ts +1 -1
- package/dist/types/modes/tmux-scroll.d.ts +18 -0
- package/dist/types/modes/types.d.ts +5 -1
- package/dist/types/modes/utils/terminal-bell.d.ts +3 -0
- package/dist/types/notifications/daemon-paths.d.ts +9 -0
- package/dist/types/notifications/html-format.d.ts +2 -0
- package/dist/types/notifications/recent-activity.d.ts +5 -1
- package/dist/types/notifications/telegram-daemon-cli.d.ts +21 -4
- package/dist/types/notifications/telegram-daemon-control.d.ts +8 -0
- package/dist/types/notifications/telegram-daemon.d.ts +4 -10
- package/dist/types/notifications/telegram-reference.d.ts +4 -0
- package/dist/types/notifications/threaded-render.d.ts +1 -0
- package/dist/types/runtime-mcp/config-writer.d.ts +9 -0
- package/dist/types/runtime-mcp/config.d.ts +2 -0
- package/dist/types/runtime-mcp/loader.d.ts +2 -0
- package/dist/types/runtime-mcp/manager.d.ts +2 -0
- package/dist/types/runtime-mcp/types.d.ts +6 -0
- package/dist/types/sdk.d.ts +1 -1
- package/dist/types/skc-runtime/launch-tmux.d.ts +2 -2
- package/dist/types/skc-runtime/ralplan-runtime.d.ts +3 -2
- package/dist/types/skc-runtime/restricted-role-agent-bash.d.ts +1 -0
- package/dist/types/skc-runtime/session-state-sidecar.d.ts +5 -0
- package/dist/types/skc-runtime/state-writer.d.ts +1 -0
- package/dist/types/skc-runtime/team-runtime.d.ts +1 -1
- package/dist/types/skc-runtime/tmux-common.d.ts +12 -0
- package/dist/types/skc-runtime/ultragoal-guard.d.ts +7 -1
- package/dist/types/skc-runtime/ultragoal-runtime.d.ts +0 -4
- package/dist/types/slash-commands/types.d.ts +2 -0
- package/dist/types/system-prompt.d.ts +7 -0
- package/dist/types/tools/skill.d.ts +1 -1
- package/dist/types/utils/cmux-workspace.d.ts +52 -0
- package/dist/types/web/search/index.d.ts +4 -2
- package/dist/types/web/search/provider.d.ts +14 -0
- package/dist/types/web/search/providers/utils.d.ts +42 -13
- package/dist/types/web/search/render.d.ts +1 -0
- package/dist/types/workflow/workflow-intent-diff.d.ts +19 -0
- package/package.json +8 -8
- package/scripts/build-binary.ts +3 -0
- package/scripts/verify-insane-vendor.ts +0 -5
- package/src/capability/mcp.ts +2 -0
- package/src/cli/local-provider-smoke.ts +632 -0
- package/src/cli/notify-cli.ts +4 -2
- package/src/cli/telegram-cli.ts +156 -0
- package/src/cli/update-cli.ts +179 -13
- package/src/cli/web-search-cli.ts +5 -7
- package/src/cli.ts +20 -1
- package/src/commands/launch.ts +47 -2
- package/src/commands/local-provider.ts +62 -0
- package/src/commands/notify.ts +1 -1
- package/src/commands/ralplan.ts +1 -0
- package/src/commands/telegram.ts +47 -0
- package/src/config/keybindings.ts +15 -6
- package/src/config/mcp-schema.json +4 -0
- package/src/config/model-registry.ts +55 -1
- package/src/config/models-config-schema.ts +9 -0
- package/src/config/settings-schema.ts +256 -4
- package/src/config/settings.ts +11 -0
- package/src/config/telegram-autostart.ts +107 -0
- package/src/config/telegram-env-bridge.ts +92 -0
- package/src/coordinator-mcp/server.ts +276 -34
- package/src/defaults/skc/skills/ralplan/SKILL.md +29 -20
- package/src/defaults/skc/skills/ultragoal/SKILL.md +37 -112
- package/src/defaults/skc-defaults.ts +16 -0
- package/src/discovery/builtin.ts +12 -0
- package/src/discovery/cursor.ts +5 -84
- package/src/discovery/gemini.ts +3 -89
- package/src/discovery/index.ts +4 -1
- package/src/discovery/mcp-json.ts +11 -0
- package/src/discovery/opencode.ts +5 -122
- package/src/discovery/windsurf.ts +4 -82
- package/src/edit/read-file.ts +9 -1
- package/src/extensibility/extensions/runner.ts +2 -1
- package/src/extensibility/extensions/types.ts +11 -0
- package/src/extensibility/skills.ts +30 -2
- package/src/hooks/skill-state.ts +33 -73
- package/src/i18n/messages/de.ts +1 -0
- package/src/i18n/messages/en.ts +1 -0
- package/src/i18n/messages/es.ts +1 -0
- package/src/i18n/messages/fr.ts +1 -0
- package/src/i18n/messages/ja.settings.ts +28 -0
- package/src/i18n/messages/ja.ts +1 -0
- package/src/i18n/messages/ko.settings.ts +28 -0
- package/src/i18n/messages/ko.ts +1 -0
- package/src/i18n/messages/zh.settings.ts +28 -0
- package/src/i18n/messages/zh.ts +1 -0
- package/src/internal-urls/docs-index.generated.ts +12 -7
- package/src/main.ts +5 -2
- package/src/migrate/executor.ts +23 -6
- package/src/modes/acp/acp-agent.ts +7 -6
- package/src/modes/components/agent-dashboard.ts +3 -35
- package/src/modes/components/custom-editor.ts +26 -0
- package/src/modes/components/custom-model-preset-wizard.ts +30 -189
- package/src/modes/components/extensions/extension-dashboard.ts +2 -48
- package/src/modes/components/hook-selector.ts +21 -3
- package/src/modes/components/model-selector.ts +246 -11
- package/src/modes/components/session-observer-overlay.ts +3 -3
- package/src/modes/components/session-selector.ts +19 -9
- package/src/modes/components/settings-selector.ts +551 -11
- package/src/modes/components/skill-message.ts +18 -10
- package/src/modes/components/status-line/presets.ts +11 -0
- package/src/modes/components/status-line/segments.ts +16 -19
- package/src/modes/components/status-line/types.ts +6 -2
- package/src/modes/components/status-line.ts +281 -117
- package/src/modes/components/tree-selector.ts +28 -8
- package/src/modes/components/two-column-body.ts +36 -0
- package/src/modes/components/welcome.ts +165 -30
- package/src/modes/controllers/command-controller.ts +26 -2
- package/src/modes/controllers/event-controller.ts +102 -4
- package/src/modes/controllers/extension-ui-controller.ts +21 -2
- package/src/modes/controllers/input-controller.ts +214 -47
- package/src/modes/controllers/selector-controller.ts +35 -33
- package/src/modes/interactive-mode.ts +36 -30
- package/src/modes/prompt-action-autocomplete.ts +48 -8
- package/src/modes/rpc/rpc-types.ts +1 -0
- package/src/modes/shared/agent-wire/deep-interview-gate.ts +72 -15
- package/src/modes/shared/agent-wire/workflow-gate-schema.ts +20 -0
- package/src/modes/slash-command-visibility.ts +9 -0
- package/src/modes/theme/theme.ts +5 -1
- package/src/modes/tmux-scroll.ts +92 -0
- package/src/modes/types.ts +8 -1
- package/src/modes/utils/hotkeys-markdown.ts +5 -2
- package/src/modes/utils/terminal-bell.ts +48 -0
- package/src/modes/utils/ui-helpers.ts +76 -3
- package/src/notifications/daemon-paths.ts +22 -0
- package/src/notifications/html-format.ts +75 -1
- package/src/notifications/index.ts +32 -2
- package/src/notifications/lifecycle-control-runtime.ts +12 -3
- package/src/notifications/recent-activity.ts +32 -8
- package/src/notifications/telegram-daemon-cli.ts +125 -13
- package/src/notifications/telegram-daemon-control.ts +9 -0
- package/src/notifications/telegram-daemon.ts +88 -46
- package/src/notifications/telegram-reference.ts +36 -14
- package/src/notifications/threaded-render.ts +14 -6
- package/src/prompts/agents/architect.md +7 -4
- package/src/prompts/agents/critic.md +15 -6
- package/src/prompts/agents/planner.md +8 -3
- package/src/prompts/system/system-prompt.md +20 -2
- package/src/prompts/tools/bash.md +1 -1
- package/src/runtime-mcp/config-writer.ts +28 -0
- package/src/runtime-mcp/config.ts +7 -0
- package/src/runtime-mcp/loader.ts +3 -0
- package/src/runtime-mcp/manager.ts +3 -0
- package/src/runtime-mcp/types.ts +6 -0
- package/src/sdk.ts +10 -11
- package/src/session/agent-session.ts +103 -13
- package/src/session/session-manager.ts +58 -18
- package/src/skc-runtime/launch-tmux.ts +34 -8
- package/src/skc-runtime/launch-worktree.ts +16 -2
- package/src/skc-runtime/ralplan-runtime.ts +22 -6
- package/src/skc-runtime/restricted-role-agent-bash.ts +1 -0
- package/src/skc-runtime/session-state-sidecar.ts +167 -24
- package/src/skc-runtime/state-runtime.ts +8 -5
- package/src/skc-runtime/state-writer.ts +5 -5
- package/src/skc-runtime/team-runtime.ts +21 -6
- package/src/skc-runtime/tmux-common.ts +16 -0
- package/src/skc-runtime/tmux-sessions.ts +13 -9
- package/src/skc-runtime/ultragoal-guard.ts +150 -24
- package/src/skc-runtime/ultragoal-runtime.ts +16 -124
- package/src/skc-runtime/workflow-manifest.generated.json +0 -8
- package/src/skc-runtime/workflow-manifest.ts +0 -1
- package/src/slash-commands/builtin-registry.ts +136 -23
- package/src/slash-commands/types.ts +2 -0
- package/src/system-prompt.ts +8 -0
- package/src/task/executor.ts +5 -0
- package/src/tools/ast-grep.ts +10 -7
- package/src/tools/bash.ts +39 -14
- package/src/tools/index.ts +8 -1
- package/src/tools/skill.ts +1 -1
- package/src/utils/cmux-workspace.ts +233 -0
- package/src/utils/title-generator.ts +2 -0
- package/src/web/kagi.ts +1 -1
- package/src/web/parallel.ts +2 -2
- package/src/web/search/index.ts +137 -52
- package/src/web/search/provider.ts +80 -0
- package/src/web/search/providers/anthropic.ts +1 -1
- package/src/web/search/providers/brave.ts +1 -1
- package/src/web/search/providers/codex.ts +1 -1
- package/src/web/search/providers/duckduckgo.ts +1 -1
- package/src/web/search/providers/exa.ts +1 -1
- package/src/web/search/providers/gemini.ts +7 -3
- package/src/web/search/providers/jina.ts +1 -1
- package/src/web/search/providers/kimi.ts +6 -1
- package/src/web/search/providers/openai-compatible.ts +1 -1
- package/src/web/search/providers/parallel.ts +1 -1
- package/src/web/search/providers/perplexity.ts +2 -2
- package/src/web/search/providers/searxng.ts +1 -1
- package/src/web/search/providers/synthetic.ts +1 -1
- package/src/web/search/providers/tavily.ts +1 -1
- package/src/web/search/providers/utils.ts +67 -17
- package/src/web/search/providers/xai.ts +1 -1
- package/src/web/search/providers/zai.ts +1 -1
- package/src/web/search/render.ts +3 -0
- package/src/workflow/workflow-intent-diff.ts +199 -0
- package/vendor/insane-search/MANIFEST.json +1 -3
- package/vendor/insane-search/engine/tests/test_u1.py +0 -28
- package/vendor/insane-search/engine/transport.py +2 -3
- package/vendor/insane-search/engine/validators.py +0 -14
- package/src/defaults/skc/rules/ponytail.md +0 -68
|
@@ -12,7 +12,12 @@ import {
|
|
|
12
12
|
SKC_MODEL_ASSIGNMENT_TARGETS,
|
|
13
13
|
type SkcModelAssignmentTargetId,
|
|
14
14
|
} from "../config/model-registry";
|
|
15
|
-
import {
|
|
15
|
+
import {
|
|
16
|
+
extractExplicitThinkingSelector,
|
|
17
|
+
formatModelSelectorValue,
|
|
18
|
+
parseModelPattern,
|
|
19
|
+
parseModelString,
|
|
20
|
+
} from "../config/model-resolver";
|
|
16
21
|
import { clearPluginRootsAndCaches, resolveActiveProjectRegistryPath } from "../discovery/helpers.js";
|
|
17
22
|
import { td } from "../i18n";
|
|
18
23
|
import { resolveMemoryBackend } from "../memory-backend";
|
|
@@ -170,11 +175,32 @@ function splitExplicitThinkingSelector(selector: string): { baseSelector: string
|
|
|
170
175
|
return thinkingLevel ? { baseSelector: trimmed.slice(0, colonIndex), thinkingLevel } : { baseSelector: trimmed };
|
|
171
176
|
}
|
|
172
177
|
|
|
173
|
-
|
|
178
|
+
interface ModelCommandSelection {
|
|
179
|
+
model: Model;
|
|
180
|
+
selector: string;
|
|
181
|
+
thinkingLevel?: ThinkingLevel;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
interface ModelCommandResolutionFailure {
|
|
185
|
+
message: string;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
type ModelCommandResolution =
|
|
189
|
+
| { ok: true; selection: ModelCommandSelection }
|
|
190
|
+
| { ok: false; failure: ModelCommandResolutionFailure };
|
|
191
|
+
|
|
192
|
+
function parseProviderQualifiedSelector(selector: string): { provider: string; modelId: string } | undefined {
|
|
193
|
+
const splitSelector = splitExplicitThinkingSelector(selector);
|
|
194
|
+
const parsed = parseModelString(splitSelector.baseSelector);
|
|
195
|
+
if (!parsed) return undefined;
|
|
196
|
+
return { provider: parsed.provider, modelId: parsed.id };
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
function resolveModelCommandSelectionFromAvailable(
|
|
174
200
|
runtime: SlashCommandRuntime,
|
|
175
201
|
selector: string,
|
|
176
|
-
|
|
177
|
-
|
|
202
|
+
availableModels: Model[],
|
|
203
|
+
): ModelCommandSelection | undefined {
|
|
178
204
|
const matchPreferences = { usageOrder: runtime.settings.getStorage()?.getModelUsageOrder() };
|
|
179
205
|
const resolved = parseModelPattern(selector, availableModels, matchPreferences, {
|
|
180
206
|
modelRegistry: runtime.session.modelRegistry,
|
|
@@ -199,6 +225,78 @@ function resolveModelCommandSelection(
|
|
|
199
225
|
};
|
|
200
226
|
}
|
|
201
227
|
|
|
228
|
+
function formatDiscoverableProviderFailure(
|
|
229
|
+
selector: string,
|
|
230
|
+
provider: string,
|
|
231
|
+
modelId: string,
|
|
232
|
+
runtime: SlashCommandRuntime,
|
|
233
|
+
): string {
|
|
234
|
+
const state = runtime.session.modelRegistry.getProviderDiscoveryState?.(provider);
|
|
235
|
+
const discovered = state?.models ?? [];
|
|
236
|
+
const base = `Unknown model: ${selector}.`;
|
|
237
|
+
if (!modelId.trim()) {
|
|
238
|
+
return `${base} Local provider model selectors must use provider/model-id syntax with a non-empty model id.`;
|
|
239
|
+
}
|
|
240
|
+
if (!state) {
|
|
241
|
+
return `${base} Provider ${provider} is configured for discovery but has not reported models yet.`;
|
|
242
|
+
}
|
|
243
|
+
if (state.status === "unavailable") {
|
|
244
|
+
const details = state.error ? ` (${state.error})` : "";
|
|
245
|
+
return `${base} Provider ${provider} discovery is unavailable${details}. Check the local endpoint and run /model again.`;
|
|
246
|
+
}
|
|
247
|
+
if (state.status === "unauthenticated") {
|
|
248
|
+
return `${base} Provider ${provider} requires authentication before model discovery.`;
|
|
249
|
+
}
|
|
250
|
+
if (state.status === "empty") {
|
|
251
|
+
return `${base} Provider ${provider} discovery succeeded but returned no models.`;
|
|
252
|
+
}
|
|
253
|
+
if (discovered.length > 0) {
|
|
254
|
+
const preview = discovered.slice(0, 8).join(", ");
|
|
255
|
+
const suffix = discovered.length > 8 ? ", …" : "";
|
|
256
|
+
return `${base} Provider ${provider} did not report model ${modelId}. Available local models: ${preview}${suffix}.`;
|
|
257
|
+
}
|
|
258
|
+
return `${base} Provider ${provider} did not report model ${modelId}.`;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
async function resolveModelCommandSelection(
|
|
262
|
+
runtime: SlashCommandRuntime,
|
|
263
|
+
selector: string,
|
|
264
|
+
): Promise<ModelCommandResolution> {
|
|
265
|
+
let availableModels = runtime.session.getAvailableModels?.() ?? [];
|
|
266
|
+
const initialSelection = resolveModelCommandSelectionFromAvailable(runtime, selector, availableModels as Model[]);
|
|
267
|
+
if (initialSelection) {
|
|
268
|
+
return { ok: true, selection: initialSelection };
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
const providerRef = parseProviderQualifiedSelector(selector);
|
|
272
|
+
const discoverableProviders = runtime.session.modelRegistry?.getDiscoverableProviders?.() ?? [];
|
|
273
|
+
if (providerRef && discoverableProviders.includes(providerRef.provider)) {
|
|
274
|
+
await runtime.session.modelRegistry.refreshProvider?.(providerRef.provider, "online");
|
|
275
|
+
availableModels = runtime.session.getAvailableModels?.() ?? [];
|
|
276
|
+
const refreshedSelection = resolveModelCommandSelectionFromAvailable(
|
|
277
|
+
runtime,
|
|
278
|
+
selector,
|
|
279
|
+
availableModels as Model[],
|
|
280
|
+
);
|
|
281
|
+
if (refreshedSelection) {
|
|
282
|
+
return { ok: true, selection: refreshedSelection };
|
|
283
|
+
}
|
|
284
|
+
return {
|
|
285
|
+
ok: false,
|
|
286
|
+
failure: {
|
|
287
|
+
message: formatDiscoverableProviderFailure(selector, providerRef.provider, providerRef.modelId, runtime),
|
|
288
|
+
},
|
|
289
|
+
};
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
return {
|
|
293
|
+
ok: false,
|
|
294
|
+
failure: {
|
|
295
|
+
message: `Unknown model: ${selector}. Configure or login to a provider first, then list/select models with /model.`,
|
|
296
|
+
},
|
|
297
|
+
};
|
|
298
|
+
}
|
|
299
|
+
|
|
202
300
|
function modelSelectionUsage(runtime: SlashCommandRuntime, currentModelLine?: string): string {
|
|
203
301
|
return [
|
|
204
302
|
currentModelLine,
|
|
@@ -225,7 +323,8 @@ const shutdownHandlerTui = (_command: ParsedSlashCommand, runtime: TuiSlashComma
|
|
|
225
323
|
const BUILTIN_SLASH_COMMAND_REGISTRY: ReadonlyArray<SlashCommandSpec> = [
|
|
226
324
|
{
|
|
227
325
|
name: "settings",
|
|
228
|
-
|
|
326
|
+
priority: 40,
|
|
327
|
+
description: "Open settings and preferences",
|
|
229
328
|
handleTui: (_command, runtime) => {
|
|
230
329
|
runtime.ctx.showSettingsSelector();
|
|
231
330
|
runtime.ctx.editor.setText("");
|
|
@@ -241,7 +340,8 @@ const BUILTIN_SLASH_COMMAND_REGISTRY: ReadonlyArray<SlashCommandSpec> = [
|
|
|
241
340
|
},
|
|
242
341
|
{
|
|
243
342
|
name: "goal",
|
|
244
|
-
|
|
343
|
+
priority: 84,
|
|
344
|
+
description: "Plan and track an autonomous goal",
|
|
245
345
|
subcommands: [
|
|
246
346
|
{ name: "set", description: "Set or replace the goal", usage: "<objective>" },
|
|
247
347
|
{ name: "show", description: "Show current goal details" },
|
|
@@ -283,16 +383,11 @@ const BUILTIN_SLASH_COMMAND_REGISTRY: ReadonlyArray<SlashCommandSpec> = [
|
|
|
283
383
|
runtime,
|
|
284
384
|
);
|
|
285
385
|
}
|
|
286
|
-
const
|
|
287
|
-
if (!
|
|
288
|
-
return usage(
|
|
289
|
-
modelSelectionUsage(
|
|
290
|
-
runtime,
|
|
291
|
-
`Unknown model: ${modelId}. Configure or login to a provider first, then list/select models with /model.`,
|
|
292
|
-
),
|
|
293
|
-
runtime,
|
|
294
|
-
);
|
|
386
|
+
const resolution = await resolveModelCommandSelection(runtime, modelId);
|
|
387
|
+
if (!resolution.ok) {
|
|
388
|
+
return usage(modelSelectionUsage(runtime, resolution.failure.message), runtime);
|
|
295
389
|
}
|
|
390
|
+
const { selection } = resolution;
|
|
296
391
|
try {
|
|
297
392
|
const persistedSelector = formatModelSelectorValue(selection.selector, selection.thinkingLevel);
|
|
298
393
|
if (parsedArgs.targetId === "default") {
|
|
@@ -449,7 +544,8 @@ const BUILTIN_SLASH_COMMAND_REGISTRY: ReadonlyArray<SlashCommandSpec> = [
|
|
|
449
544
|
},
|
|
450
545
|
{
|
|
451
546
|
name: "export",
|
|
452
|
-
|
|
547
|
+
priority: 50,
|
|
548
|
+
description: "Export this session to an HTML file",
|
|
453
549
|
inlineHint: "[path]",
|
|
454
550
|
allowArgs: true,
|
|
455
551
|
handle: async (command, runtime) => {
|
|
@@ -476,7 +572,8 @@ const BUILTIN_SLASH_COMMAND_REGISTRY: ReadonlyArray<SlashCommandSpec> = [
|
|
|
476
572
|
},
|
|
477
573
|
{
|
|
478
574
|
name: "copy",
|
|
479
|
-
|
|
575
|
+
priority: 55,
|
|
576
|
+
description: "Copy the last response for review or sharing",
|
|
480
577
|
// Public `/copy` is strict zero-argument, but `allowArgs` lets the
|
|
481
578
|
// TUI dispatcher route `/copy <arg>` here so it can be rejected locally
|
|
482
579
|
// instead of falling through as a model prompt.
|
|
@@ -493,7 +590,8 @@ const BUILTIN_SLASH_COMMAND_REGISTRY: ReadonlyArray<SlashCommandSpec> = [
|
|
|
493
590
|
},
|
|
494
591
|
{
|
|
495
592
|
name: "dump",
|
|
496
|
-
|
|
593
|
+
priority: 54,
|
|
594
|
+
description: "Dump the full transcript for review or sharing",
|
|
497
595
|
acpDescription: "Return full transcript as plain text",
|
|
498
596
|
handle: async (_command, runtime) => {
|
|
499
597
|
const text = runtime.session.formatSessionAsText();
|
|
@@ -507,11 +605,12 @@ const BUILTIN_SLASH_COMMAND_REGISTRY: ReadonlyArray<SlashCommandSpec> = [
|
|
|
507
605
|
},
|
|
508
606
|
{
|
|
509
607
|
name: "session",
|
|
510
|
-
|
|
608
|
+
priority: 88,
|
|
609
|
+
description: "Show current session info or delete current session",
|
|
511
610
|
acpDescription: "Show session information",
|
|
512
611
|
acpInputHint: "info|delete",
|
|
513
612
|
subcommands: [
|
|
514
|
-
{ name: "info", description: "Show session
|
|
613
|
+
{ name: "info", description: "Show current session id, title, and workspace" },
|
|
515
614
|
{ name: "delete", description: "Delete current session and return to selector" },
|
|
516
615
|
],
|
|
517
616
|
allowArgs: true,
|
|
@@ -621,6 +720,15 @@ const BUILTIN_SLASH_COMMAND_REGISTRY: ReadonlyArray<SlashCommandSpec> = [
|
|
|
621
720
|
runtime.ctx.editor.setText("");
|
|
622
721
|
},
|
|
623
722
|
},
|
|
723
|
+
{
|
|
724
|
+
name: "help",
|
|
725
|
+
priority: 100,
|
|
726
|
+
description: "Learn commands and beginner workflows",
|
|
727
|
+
handleTui: (_command, runtime) => {
|
|
728
|
+
runtime.ctx.handleHelpCommand();
|
|
729
|
+
runtime.ctx.editor.setText("");
|
|
730
|
+
},
|
|
731
|
+
},
|
|
624
732
|
{
|
|
625
733
|
name: "hotkeys",
|
|
626
734
|
description: "Show all keyboard shortcuts",
|
|
@@ -861,6 +969,7 @@ const BUILTIN_SLASH_COMMAND_REGISTRY: ReadonlyArray<SlashCommandSpec> = [
|
|
|
861
969
|
},
|
|
862
970
|
{
|
|
863
971
|
name: "new",
|
|
972
|
+
priority: 96,
|
|
864
973
|
description: "Start a new session",
|
|
865
974
|
handleTui: async (_command, runtime) => {
|
|
866
975
|
runtime.ctx.editor.setText("");
|
|
@@ -877,7 +986,8 @@ const BUILTIN_SLASH_COMMAND_REGISTRY: ReadonlyArray<SlashCommandSpec> = [
|
|
|
877
986
|
},
|
|
878
987
|
{
|
|
879
988
|
name: "compact",
|
|
880
|
-
|
|
989
|
+
priority: 72,
|
|
990
|
+
description: "Compact context and continue this session",
|
|
881
991
|
acpDescription: "Compact the conversation",
|
|
882
992
|
inlineHint: "[focus instructions]",
|
|
883
993
|
allowArgs: true,
|
|
@@ -934,7 +1044,8 @@ const BUILTIN_SLASH_COMMAND_REGISTRY: ReadonlyArray<SlashCommandSpec> = [
|
|
|
934
1044
|
},
|
|
935
1045
|
{
|
|
936
1046
|
name: "resume",
|
|
937
|
-
|
|
1047
|
+
priority: 92,
|
|
1048
|
+
description: "Resume a previous session",
|
|
938
1049
|
handleTui: (_command, runtime) => {
|
|
939
1050
|
runtime.ctx.showSessionSelector();
|
|
940
1051
|
runtime.ctx.editor.setText("");
|
|
@@ -953,7 +1064,8 @@ const BUILTIN_SLASH_COMMAND_REGISTRY: ReadonlyArray<SlashCommandSpec> = [
|
|
|
953
1064
|
},
|
|
954
1065
|
{
|
|
955
1066
|
name: "retry",
|
|
956
|
-
|
|
1067
|
+
priority: 70,
|
|
1068
|
+
description: "Retry or continue the last interrupted turn",
|
|
957
1069
|
handleTui: async (_command, runtime) => {
|
|
958
1070
|
const didRetry = await runtime.ctx.session.retry();
|
|
959
1071
|
if (!didRetry) {
|
|
@@ -1153,6 +1265,7 @@ export const BUILTIN_SLASH_COMMAND_DEFS: ReadonlyArray<BuiltinSlashCommand> = AC
|
|
|
1153
1265
|
},
|
|
1154
1266
|
subcommands: command.subcommands,
|
|
1155
1267
|
inlineHint: command.inlineHint,
|
|
1268
|
+
priority: command.priority,
|
|
1156
1269
|
}),
|
|
1157
1270
|
);
|
|
1158
1271
|
|
|
@@ -19,6 +19,8 @@ export interface BuiltinSlashCommand {
|
|
|
19
19
|
subcommands?: SubcommandDef[];
|
|
20
20
|
/** Static inline hint when command takes a simple argument (no subcommands). */
|
|
21
21
|
inlineHint?: string;
|
|
22
|
+
/** Higher values sort earlier in TUI slash-command autocomplete. */
|
|
23
|
+
priority?: number;
|
|
22
24
|
}
|
|
23
25
|
|
|
24
26
|
/** Parsed slash-command text after stripping the leading "/". */
|
package/src/system-prompt.ts
CHANGED
|
@@ -356,6 +356,10 @@ export interface BuildSystemPromptOptions {
|
|
|
356
356
|
mcpDiscoveryMode?: boolean;
|
|
357
357
|
/** Discoverable MCP server summaries to advertise when discovery mode is active. */
|
|
358
358
|
mcpDiscoveryServerSummaries?: string[];
|
|
359
|
+
/** Whether built-in tool discovery ("all" mode) is active; enables the tool-discovery prompt block. */
|
|
360
|
+
toolDiscoveryActive?: boolean;
|
|
361
|
+
/** Hidden discoverable tools to advertise (name + one-line summary) when tool discovery is active. */
|
|
362
|
+
discoverableTools?: Array<{ name: string; summary: string }>;
|
|
359
363
|
/** Encourage the agent to delegate via tasks unless changes are trivial. */
|
|
360
364
|
eagerTasks?: boolean;
|
|
361
365
|
/** Rules with alwaysApply=true — their full content is injected into the prompt. */
|
|
@@ -394,6 +398,8 @@ export async function buildSystemPrompt(options: BuildSystemPromptOptions = {}):
|
|
|
394
398
|
intentField,
|
|
395
399
|
mcpDiscoveryMode = false,
|
|
396
400
|
mcpDiscoveryServerSummaries = [],
|
|
401
|
+
toolDiscoveryActive = false,
|
|
402
|
+
discoverableTools = [],
|
|
397
403
|
eagerTasks = false,
|
|
398
404
|
secretsEnabled = false,
|
|
399
405
|
workspaceTree: providedWorkspaceTree,
|
|
@@ -572,6 +578,8 @@ export async function buildSystemPrompt(options: BuildSystemPromptOptions = {}):
|
|
|
572
578
|
mcpDiscoveryMode,
|
|
573
579
|
hasMCPDiscoveryServers: mcpDiscoveryServerSummaries.length > 0,
|
|
574
580
|
mcpDiscoveryServerSummaries,
|
|
581
|
+
toolDiscoveryActive,
|
|
582
|
+
discoverableTools,
|
|
575
583
|
eagerTasks,
|
|
576
584
|
secretsEnabled,
|
|
577
585
|
};
|
package/src/task/executor.ts
CHANGED
|
@@ -1535,6 +1535,11 @@ export async function runSubprocess(options: ExecutorOptions): Promise<SingleRes
|
|
|
1535
1535
|
);
|
|
1536
1536
|
await awaitAbortable(session.waitForIdle());
|
|
1537
1537
|
} catch (err) {
|
|
1538
|
+
// An abort (parent cancel, session shutdown, timeout) rejects
|
|
1539
|
+
// awaitAbortable with ToolAbortError — a cancellation, not a prompt
|
|
1540
|
+
// failure. Mirror the outer catch's `!abortSignal.aborted` guard so
|
|
1541
|
+
// expected cancellations aren't logged at error level.
|
|
1542
|
+
if (abortSignal.aborted || err instanceof ToolAbortError) break;
|
|
1538
1543
|
logger.error("Subagent prompt failed", {
|
|
1539
1544
|
error: err instanceof Error ? err.message : String(err),
|
|
1540
1545
|
});
|
package/src/tools/ast-grep.ts
CHANGED
|
@@ -223,13 +223,16 @@ export class AstGrepTool implements AgentTool<typeof astGrepSchema, AstGrepToolD
|
|
|
223
223
|
const modelOut: string[] = [];
|
|
224
224
|
const displayOut: string[] = [];
|
|
225
225
|
const fileMatches = matchesByFile.get(relativePath) ?? [];
|
|
226
|
-
const
|
|
227
|
-
const
|
|
228
|
-
const endLine = match.startLine +
|
|
229
|
-
return
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
|
|
226
|
+
const preparedMatches = fileMatches.map(match => {
|
|
227
|
+
const lines = match.text.split("\n");
|
|
228
|
+
const endLine = match.startLine + lines.length - 1;
|
|
229
|
+
return { match, lines, endLine };
|
|
230
|
+
});
|
|
231
|
+
const lineNumberWidth = preparedMatches.reduce(
|
|
232
|
+
(width, entry) => Math.max(width, String(entry.match.startLine).length, String(entry.endLine).length),
|
|
233
|
+
0,
|
|
234
|
+
);
|
|
235
|
+
for (const { match, lines: matchLines } of preparedMatches) {
|
|
233
236
|
for (let index = 0; index < matchLines.length; index++) {
|
|
234
237
|
const lineNumber = match.startLine + index;
|
|
235
238
|
const isMatch = index === 0;
|
package/src/tools/bash.ts
CHANGED
|
@@ -14,7 +14,10 @@ import bashDescription from "../prompts/tools/bash.md" with { type: "text" };
|
|
|
14
14
|
import type { ClientBridgeTerminalExitStatus, ClientBridgeTerminalOutput } from "../session/client-bridge";
|
|
15
15
|
import { DEFAULT_MAX_BYTES, streamTailUpdates, TailBuffer } from "../session/streaming-output";
|
|
16
16
|
import { buildSkcRuntimeSessionEnv } from "../skc-runtime/goal-mode-request";
|
|
17
|
-
import {
|
|
17
|
+
import {
|
|
18
|
+
SKC_RALPLAN_ARTIFACT_ENV,
|
|
19
|
+
SKC_RESTRICTED_ROLE_AGENT_BASH_ENV,
|
|
20
|
+
} from "../skc-runtime/restricted-role-agent-bash";
|
|
18
21
|
import { renderStatusLine } from "../tui";
|
|
19
22
|
import { CachedOutputBlock } from "../tui/output-block";
|
|
20
23
|
import { getSixelLineMask } from "../utils/sixel";
|
|
@@ -530,13 +533,24 @@ export class BashTool implements AgentTool<BashToolSchema, BashToolDetails> {
|
|
|
530
533
|
|
|
531
534
|
const rawCommand = input.command;
|
|
532
535
|
const allowedPrefixes = this.session.bashAllowedPrefixes;
|
|
536
|
+
const isRestrictedRalplanArtifactEnv =
|
|
537
|
+
allowedPrefixes &&
|
|
538
|
+
allowedPrefixes.length > 0 &&
|
|
539
|
+
this.session.bashRestrictionProfile !== "read-only" &&
|
|
540
|
+
env &&
|
|
541
|
+
Object.keys(env).length === 1 &&
|
|
542
|
+
Object.hasOwn(env, SKC_RALPLAN_ARTIFACT_ENV) &&
|
|
543
|
+
rawCommand.includes(`--artifact-env ${SKC_RALPLAN_ARTIFACT_ENV}`);
|
|
533
544
|
if (
|
|
534
545
|
(this.session.bashRestrictionProfile === "read-only" || (allowedPrefixes && allowedPrefixes.length > 0)) &&
|
|
535
546
|
env &&
|
|
536
|
-
Object.keys(env).length > 0
|
|
547
|
+
Object.keys(env).length > 0 &&
|
|
548
|
+
!isRestrictedRalplanArtifactEnv
|
|
537
549
|
) {
|
|
538
550
|
const mode = this.session.bashRestrictionProfile === "read-only" ? "Read-only" : "Restricted role-agent";
|
|
539
|
-
throw new ToolError(
|
|
551
|
+
throw new ToolError(
|
|
552
|
+
`${mode} bash only allows the ${SKC_RALPLAN_ARTIFACT_ENV} env override for --artifact-env.`,
|
|
553
|
+
);
|
|
540
554
|
}
|
|
541
555
|
if (allowedPrefixes && allowedPrefixes.length > 0) {
|
|
542
556
|
const commandsToCheck = rawCommand === command ? [command] : [rawCommand, command];
|
|
@@ -597,11 +611,13 @@ export class BashTool implements AgentTool<BashToolSchema, BashToolDetails> {
|
|
|
597
611
|
await Promise.all(
|
|
598
612
|
Object.entries(env).map(async ([key, value]) => [
|
|
599
613
|
key,
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
614
|
+
key === SKC_RALPLAN_ARTIFACT_ENV
|
|
615
|
+
? value
|
|
616
|
+
: await expandInternalUrls(value, {
|
|
617
|
+
...internalUrlOptions,
|
|
618
|
+
ensureLocalParentDirs: true,
|
|
619
|
+
noEscape: true,
|
|
620
|
+
}),
|
|
605
621
|
]),
|
|
606
622
|
),
|
|
607
623
|
)
|
|
@@ -817,9 +833,22 @@ export class BashTool implements AgentTool<BashToolSchema, BashToolDetails> {
|
|
|
817
833
|
});
|
|
818
834
|
}
|
|
819
835
|
|
|
836
|
+
// Route through the client terminal when the client advertises the terminal capability.
|
|
837
|
+
// Skip when pty=true (PTY needs the local terminal UI).
|
|
838
|
+
const clientBridge =
|
|
839
|
+
this.session.bashRestrictionProfile === "read-only" ? undefined : this.session.getClientBridge?.();
|
|
840
|
+
const clientTerminalActive = Boolean(clientBridge?.capabilities.terminal && clientBridge.createTerminal && !pty);
|
|
841
|
+
|
|
820
842
|
const autoBgManager = AsyncJobManager.instance();
|
|
821
|
-
|
|
822
|
-
|
|
843
|
+
// Run non-PTY bash through the managed job path so Ctrl+B-twice fold-on-demand works
|
|
844
|
+
// even when auto-background is disabled. When a client terminal will handle the
|
|
845
|
+
// command, keep the existing bridge path unless auto-background is enabled.
|
|
846
|
+
if (!pty && autoBgManager && (this.#autoBackgroundEnabled || !clientTerminalActive)) {
|
|
847
|
+
// With auto-background off, wait past the command's own timeout so the job only
|
|
848
|
+
// leaves the foreground on an explicit Ctrl+B fold, never on an auto-background timer.
|
|
849
|
+
const autoBackgroundWaitMs = this.#autoBackgroundEnabled
|
|
850
|
+
? this.#resolveAutoBackgroundWaitMs(timeoutMs)
|
|
851
|
+
: timeoutMs + 1_000;
|
|
823
852
|
const startBackgrounded = autoBackgroundWaitMs === 0;
|
|
824
853
|
const job = this.#startManagedBashJob({
|
|
825
854
|
command,
|
|
@@ -875,10 +904,6 @@ export class BashTool implements AgentTool<BashToolSchema, BashToolDetails> {
|
|
|
875
904
|
});
|
|
876
905
|
}
|
|
877
906
|
|
|
878
|
-
// Route through the client terminal when the client advertises the terminal capability.
|
|
879
|
-
// Skip when pty=true (PTY needs the local terminal UI).
|
|
880
|
-
const clientBridge =
|
|
881
|
-
this.session.bashRestrictionProfile === "read-only" ? undefined : this.session.getClientBridge?.();
|
|
882
907
|
if (clientBridge?.capabilities.terminal && clientBridge.createTerminal && !pty) {
|
|
883
908
|
const handle = await clientBridge.createTerminal({
|
|
884
909
|
command,
|
package/src/tools/index.ts
CHANGED
|
@@ -325,7 +325,14 @@ export type ToolFactory = (session: ToolSession) => Tool | null | Promise<Tool |
|
|
|
325
325
|
export type BuiltinToolLoadMode = "essential" | "discoverable";
|
|
326
326
|
|
|
327
327
|
/** Default essential tool names when tools.essentialOverride is empty. */
|
|
328
|
-
export const DEFAULT_ESSENTIAL_TOOL_NAMES: readonly string[] = [
|
|
328
|
+
export const DEFAULT_ESSENTIAL_TOOL_NAMES: readonly string[] = [
|
|
329
|
+
"read",
|
|
330
|
+
"bash",
|
|
331
|
+
"edit",
|
|
332
|
+
"write",
|
|
333
|
+
"search",
|
|
334
|
+
"find",
|
|
335
|
+
] as const;
|
|
329
336
|
|
|
330
337
|
/**
|
|
331
338
|
* Resolve the active essential built-in tool names from settings.
|
package/src/tools/skill.ts
CHANGED
|
@@ -50,7 +50,7 @@ export class SkillTool implements AgentTool<typeof skillSchema, SkillToolDetails
|
|
|
50
50
|
readonly name = "skill";
|
|
51
51
|
readonly label = "Skill";
|
|
52
52
|
readonly summary = "Chain into another available skill in the current turn";
|
|
53
|
-
readonly loadMode = "
|
|
53
|
+
readonly loadMode = "essential";
|
|
54
54
|
readonly description: string;
|
|
55
55
|
readonly parameters = skillSchema;
|
|
56
56
|
readonly strict = true;
|