@sayknow-cli/coding-agent 0.3.0 → 0.3.2
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/bin/skc.js +4 -0
- package/dist/types/cli/mcp-cli.d.ts +25 -0
- package/dist/types/cli/notify-cli.d.ts +2 -0
- package/dist/types/cli/plugin-cli.d.ts +2 -0
- package/dist/types/cli.d.ts +6 -0
- package/dist/types/commands/mcp.d.ts +70 -0
- package/dist/types/commands/plugin.d.ts +6 -0
- package/dist/types/commands/session.d.ts +6 -0
- package/dist/types/config/keybindings.d.ts +2 -2
- package/dist/types/config/model-profile-activation.d.ts +8 -1
- package/dist/types/config/settings-schema.d.ts +39 -2
- package/dist/types/deep-interview/plaintext-gate-guard.d.ts +11 -0
- package/dist/types/defaults/skc-defaults.d.ts +2 -13
- package/dist/types/extensibility/shared-events.d.ts +1 -0
- package/dist/types/extensibility/skc-plugins/compiler.d.ts +19 -0
- package/dist/types/extensibility/skc-plugins/constrained-hooks.d.ts +29 -0
- package/dist/types/extensibility/skc-plugins/index.d.ts +9 -0
- package/dist/types/extensibility/skc-plugins/injection.d.ts +9 -0
- package/dist/types/extensibility/skc-plugins/installer.d.ts +13 -0
- package/dist/types/extensibility/skc-plugins/mcp-policy.d.ts +26 -0
- package/dist/types/extensibility/skc-plugins/observability.d.ts +27 -0
- package/dist/types/extensibility/skc-plugins/prompt-appendix.d.ts +16 -0
- package/dist/types/extensibility/skc-plugins/registry.d.ts +32 -0
- package/dist/types/extensibility/skc-plugins/runtime-adapters.d.ts +64 -0
- package/dist/types/extensibility/skc-plugins/session-validation.d.ts +42 -0
- package/dist/types/extensibility/skc-plugins/types.d.ts +158 -2
- package/dist/types/extensibility/skc-plugins/validation.d.ts +8 -1
- package/dist/types/lsp/types.d.ts +2 -0
- package/dist/types/main.d.ts +2 -0
- package/dist/types/modes/components/custom-editor.d.ts +1 -1
- package/dist/types/modes/components/model-selector.d.ts +8 -0
- package/dist/types/modes/components/status-line/git-utils.d.ts +6 -0
- package/dist/types/modes/theme/defaults/index.d.ts +99 -0
- package/dist/types/notifications/attachment-registry.d.ts +17 -0
- package/dist/types/notifications/chat-adapters.d.ts +9 -0
- package/dist/types/notifications/config.d.ts +9 -1
- package/dist/types/notifications/engine.d.ts +59 -0
- package/dist/types/notifications/html-format.d.ts +11 -0
- package/dist/types/notifications/index.d.ts +149 -1
- package/dist/types/notifications/lifecycle-commands.d.ts +60 -0
- package/dist/types/notifications/lifecycle-control-runtime.d.ts +98 -0
- package/dist/types/notifications/lifecycle-orchestrator.d.ts +144 -0
- package/dist/types/notifications/managed-daemon.d.ts +48 -0
- package/dist/types/notifications/operator-runtime.d.ts +52 -0
- package/dist/types/notifications/rate-limit-pool.d.ts +2 -0
- package/dist/types/notifications/recent-activity.d.ts +35 -0
- package/dist/types/notifications/telegram-daemon.d.ts +133 -16
- package/dist/types/notifications/telegram-reference.d.ts +3 -1
- package/dist/types/notifications/threaded-inbound.d.ts +19 -0
- package/dist/types/notifications/threaded-render.d.ts +6 -1
- package/dist/types/notifications/topic-registry.d.ts +12 -9
- package/dist/types/runtime-mcp/types.d.ts +7 -0
- package/dist/types/sdk.d.ts +2 -0
- package/dist/types/session/agent-session.d.ts +16 -4
- package/dist/types/session/blob-store.d.ts +25 -0
- package/dist/types/session/session-manager.d.ts +57 -0
- package/dist/types/skc-runtime/launch-tmux.d.ts +1 -0
- package/dist/types/skc-runtime/psmux-detect.d.ts +78 -0
- package/dist/types/skc-runtime/ralplan-runtime.d.ts +1 -1
- package/dist/types/skc-runtime/team-runtime.d.ts +2 -0
- package/dist/types/skc-runtime/tmux-common.d.ts +30 -2
- package/dist/types/skc-runtime/tmux-sessions.d.ts +18 -0
- package/dist/types/slash-commands/helpers/fast-status-report.d.ts +6 -0
- package/dist/types/system-prompt.d.ts +2 -0
- package/dist/types/task/executor.d.ts +9 -1
- package/dist/types/tools/composer-bash-policy.d.ts +14 -0
- package/dist/types/tools/fetch.d.ts +23 -0
- package/dist/types/tools/index.d.ts +4 -1
- package/dist/types/tools/telegram-send.d.ts +32 -0
- package/dist/types/utils/changelog.d.ts +1 -0
- package/dist/types/web/insane/bridge.d.ts +103 -0
- package/dist/types/web/insane/url-guard.d.ts +25 -0
- package/dist/types/web/scrapers/types.d.ts +5 -0
- package/dist/types/web/scrapers/utils.d.ts +7 -1
- package/dist/types/web/search/provider.d.ts +18 -1
- package/dist/types/web/search/providers/insane.d.ts +53 -0
- package/dist/types/web/search/providers/text-citations.d.ts +23 -0
- package/dist/types/web/search/types.d.ts +12 -4
- package/package.json +14 -10
- package/scripts/g004-tmux-smoke.ts +100 -0
- package/scripts/g005-daemon-smoke.ts +180 -0
- package/scripts/g011-daemon-path-smoke.ts +153 -0
- package/scripts/verify-insane-vendor.ts +132 -0
- package/src/cli/args.ts +1 -1
- package/src/cli/fast-help.ts +30 -2
- package/src/cli/mcp-cli.ts +272 -0
- package/src/cli/notify-cli.ts +152 -5
- package/src/cli/plugin-cli.ts +66 -3
- package/src/cli.ts +30 -12
- package/src/commands/mcp.ts +117 -0
- package/src/commands/plugin.ts +4 -0
- package/src/commands/session.ts +18 -0
- package/src/commands/team.ts +1 -1
- package/src/config/keybindings.ts +2 -2
- package/src/config/model-profile-activation.ts +55 -7
- package/src/config/settings-schema.ts +30 -1
- package/src/deep-interview/plaintext-gate-guard.ts +94 -0
- package/src/defaults/skc/extensions/grok-cli-vendor/biome.json +1 -1
- package/src/defaults/skc/skills/deep-interview/SKILL.md +7 -6
- package/src/defaults/skc/skills/ralplan/SKILL.md +11 -4
- package/src/defaults/skc/skills/team/SKILL.md +5 -3
- package/src/defaults/skc/skills/ultragoal/SKILL.md +41 -13
- package/src/defaults/skc-defaults.ts +2 -27
- package/src/export/html/index.ts +2 -2
- package/src/extensibility/extensions/runner.ts +1 -0
- package/src/extensibility/shared-events.ts +1 -0
- package/src/extensibility/skc-plugins/compiler.ts +351 -0
- package/src/extensibility/skc-plugins/constrained-hooks.ts +170 -0
- package/src/extensibility/skc-plugins/index.ts +9 -0
- package/src/extensibility/skc-plugins/injection.ts +109 -0
- package/src/extensibility/skc-plugins/installer.ts +434 -0
- package/src/extensibility/skc-plugins/loader.ts +3 -1
- package/src/extensibility/skc-plugins/mcp-policy.ts +239 -0
- package/src/extensibility/skc-plugins/observability.ts +84 -0
- package/src/extensibility/skc-plugins/paths.ts +1 -1
- package/src/extensibility/skc-plugins/prompt-appendix.ts +109 -0
- package/src/extensibility/skc-plugins/registry.ts +180 -0
- package/src/extensibility/skc-plugins/runtime-adapters.ts +234 -0
- package/src/extensibility/skc-plugins/schema.ts +250 -20
- package/src/extensibility/skc-plugins/session-validation.ts +147 -0
- package/src/extensibility/skc-plugins/types.ts +199 -3
- package/src/extensibility/skc-plugins/validation.ts +80 -0
- package/src/extensibility/skills.ts +15 -0
- package/src/hooks/skill-state.ts +57 -0
- package/src/internal-urls/docs-index.generated.ts +17 -13
- package/src/lsp/config.ts +16 -3
- package/src/lsp/defaults.json +7 -0
- package/src/lsp/types.ts +2 -0
- package/src/main.ts +14 -3
- package/src/modes/bridge/bridge-mode.ts +11 -0
- package/src/modes/components/assistant-message.ts +49 -1
- package/src/modes/components/custom-editor.ts +2 -0
- package/src/modes/components/footer.ts +2 -3
- package/src/modes/components/hook-editor.ts +1 -1
- package/src/modes/components/hook-selector.ts +67 -43
- package/src/modes/components/model-selector.ts +56 -11
- package/src/modes/components/status-line/git-utils.ts +25 -0
- package/src/modes/components/status-line.ts +10 -11
- package/src/modes/components/welcome.ts +2 -3
- package/src/modes/controllers/event-controller.ts +15 -0
- package/src/modes/controllers/extension-ui-controller.ts +0 -27
- package/src/modes/controllers/selector-controller.ts +53 -11
- package/src/modes/interactive-mode.ts +50 -3
- package/src/modes/shared/agent-wire/scopes.ts +1 -1
- package/src/modes/theme/defaults/gruvbox-dark.json +99 -0
- package/src/modes/theme/defaults/index.ts +2 -0
- package/src/modes/utils/context-usage.ts +2 -2
- package/src/modes/utils/hotkeys-markdown.ts +1 -1
- package/src/notifications/attachment-registry.ts +23 -0
- package/src/notifications/chat-adapters.ts +147 -0
- package/src/notifications/config.ts +23 -2
- package/src/notifications/engine.ts +100 -0
- package/src/notifications/html-format.ts +38 -0
- package/src/notifications/index.ts +417 -45
- package/src/notifications/lifecycle-commands.ts +238 -0
- package/src/notifications/lifecycle-control-runtime.ts +405 -0
- package/src/notifications/lifecycle-orchestrator.ts +358 -0
- package/src/notifications/managed-daemon.ts +163 -0
- package/src/notifications/operator-runtime.ts +171 -0
- package/src/notifications/rate-limit-pool.ts +19 -0
- package/src/notifications/recent-activity.ts +132 -0
- package/src/notifications/telegram-daemon.ts +984 -242
- package/src/notifications/telegram-reference.ts +25 -7
- package/src/notifications/threaded-inbound.ts +60 -4
- package/src/notifications/threaded-render.ts +20 -2
- package/src/notifications/topic-registry.ts +23 -9
- package/src/prompts/agents/executor.md +2 -2
- package/src/runtime-mcp/transports/stdio.ts +38 -4
- package/src/runtime-mcp/types.ts +7 -0
- package/src/sdk.ts +157 -10
- package/src/session/agent-session.ts +248 -125
- package/src/session/blob-store.ts +196 -8
- package/src/session/session-manager.ts +762 -12
- package/src/skc-runtime/launch-tmux.ts +85 -22
- package/src/skc-runtime/ledger-event-renderer.ts +1 -0
- package/src/skc-runtime/psmux-detect.ts +239 -0
- package/src/skc-runtime/ralplan-runtime.ts +2 -2
- package/src/skc-runtime/team-runtime.ts +56 -23
- package/src/skc-runtime/tmux-common.ts +88 -4
- package/src/skc-runtime/tmux-sessions.ts +111 -9
- package/src/skc-runtime/ultragoal-guard.ts +25 -8
- package/src/skc-runtime/ultragoal-runtime.ts +75 -15
- package/src/skc-runtime/workflow-manifest.generated.json +29 -0
- package/src/skc-runtime/workflow-manifest.ts +7 -2
- package/src/slash-commands/builtin-registry.ts +23 -3
- package/src/slash-commands/helpers/fast-status-report.ts +13 -3
- package/src/slash-commands/helpers/parse.ts +2 -1
- package/src/system-prompt.ts +9 -0
- package/src/task/executor.ts +31 -7
- package/src/task/index.ts +2 -0
- package/src/tools/ask.ts +5 -1
- package/src/tools/bash.ts +9 -0
- package/src/tools/composer-bash-policy.ts +96 -0
- package/src/tools/fetch.ts +94 -1
- package/src/tools/index.ts +6 -1
- package/src/tools/telegram-send.ts +137 -0
- package/src/utils/changelog.ts +8 -0
- package/src/web/insane/bridge.ts +350 -0
- package/src/web/insane/url-guard.ts +159 -0
- package/src/web/scrapers/types.ts +143 -45
- package/src/web/scrapers/utils.ts +70 -19
- package/src/web/search/provider.ts +77 -18
- package/src/web/search/providers/anthropic.ts +70 -3
- package/src/web/search/providers/codex.ts +1 -119
- package/src/web/search/providers/gemini.ts +99 -0
- package/src/web/search/providers/insane.ts +551 -0
- package/src/web/search/providers/openai-compatible.ts +66 -32
- package/src/web/search/providers/text-citations.ts +111 -0
- package/src/web/search/types.ts +13 -2
- package/vendor/insane-search/LICENSE +21 -0
- package/vendor/insane-search/MANIFEST.json +24 -0
- package/vendor/insane-search/engine/__init__.py +23 -0
- package/vendor/insane-search/engine/__main__.py +128 -0
- package/vendor/insane-search/engine/bias_check.py +183 -0
- package/vendor/insane-search/engine/executor.py +254 -0
- package/vendor/insane-search/engine/fetch_chain.py +725 -0
- package/vendor/insane-search/engine/learning.py +175 -0
- package/vendor/insane-search/engine/phase0.py +214 -0
- package/vendor/insane-search/engine/safety.py +91 -0
- package/vendor/insane-search/engine/templates/package.json +11 -0
- package/vendor/insane-search/engine/templates/playwright_mobile_chrome.js +188 -0
- package/vendor/insane-search/engine/templates/playwright_real_chrome.js +243 -0
- package/vendor/insane-search/engine/tests/test_hardening.py +57 -0
- package/vendor/insane-search/engine/tests/test_smoke.py +152 -0
- package/vendor/insane-search/engine/tests/test_u1.py +200 -0
- package/vendor/insane-search/engine/tests/test_u4.py +131 -0
- package/vendor/insane-search/engine/tests/test_u5.py +163 -0
- package/vendor/insane-search/engine/tests/test_u7.py +124 -0
- package/vendor/insane-search/engine/transport.py +211 -0
- package/vendor/insane-search/engine/url_transforms.py +98 -0
- package/vendor/insane-search/engine/validators.py +331 -0
- package/vendor/insane-search/engine/waf_detector.py +214 -0
- package/vendor/insane-search/engine/waf_profiles.yaml +162 -0
|
@@ -6,6 +6,7 @@ import { getOAuthProviders } from "@sayknow-cli/ai/utils/oauth";
|
|
|
6
6
|
import { Spacer, Text } from "@sayknow-cli/tui";
|
|
7
7
|
import { setProjectDir } from "@sayknow-cli/utils";
|
|
8
8
|
import { jobElapsedMs } from "../async";
|
|
9
|
+
import { materializeActiveModelProfileAssignment } from "../config/model-profile-activation";
|
|
9
10
|
import {
|
|
10
11
|
SKC_MODEL_ASSIGNMENT_TARGET_IDS,
|
|
11
12
|
SKC_MODEL_ASSIGNMENT_TARGETS,
|
|
@@ -299,6 +300,12 @@ const BUILTIN_SLASH_COMMAND_REGISTRY: ReadonlyArray<SlashCommandSpec> = [
|
|
|
299
300
|
selector: selection.selector,
|
|
300
301
|
thinkingLevel: selection.thinkingLevel,
|
|
301
302
|
});
|
|
303
|
+
materializeActiveModelProfileAssignment({
|
|
304
|
+
session: runtime.session,
|
|
305
|
+
settings: runtime.settings,
|
|
306
|
+
role: parsedArgs.targetId,
|
|
307
|
+
selector: persistedSelector,
|
|
308
|
+
});
|
|
302
309
|
if (selection.thinkingLevel) {
|
|
303
310
|
runtime.session.setThinkingLevel(selection.thinkingLevel);
|
|
304
311
|
}
|
|
@@ -317,10 +324,23 @@ const BUILTIN_SLASH_COMMAND_REGISTRY: ReadonlyArray<SlashCommandSpec> = [
|
|
|
317
324
|
selection.thinkingLevel ??
|
|
318
325
|
extractExplicitThinkingSelector(overrides[parsedArgs.targetId], runtime.settings);
|
|
319
326
|
const roleSelector = formatModelSelectorValue(selection.selector, thinkingLevel);
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
327
|
+
const materializedProfile = materializeActiveModelProfileAssignment({
|
|
328
|
+
session: runtime.session,
|
|
329
|
+
settings: runtime.settings,
|
|
330
|
+
role: parsedArgs.targetId,
|
|
331
|
+
selector: roleSelector,
|
|
323
332
|
});
|
|
333
|
+
if (!materializedProfile) {
|
|
334
|
+
const target = SKC_MODEL_ASSIGNMENT_TARGETS[parsedArgs.targetId];
|
|
335
|
+
if (target.settingsPath === "modelRoles") {
|
|
336
|
+
runtime.settings.setModelRole(parsedArgs.targetId, roleSelector);
|
|
337
|
+
} else {
|
|
338
|
+
runtime.settings.set("task.agentModelOverrides", {
|
|
339
|
+
...overrides,
|
|
340
|
+
[parsedArgs.targetId]: roleSelector,
|
|
341
|
+
});
|
|
342
|
+
}
|
|
343
|
+
}
|
|
324
344
|
runtime.settings.getStorage()?.recordModelUsage(`${selection.model.provider}/${selection.model.id}`);
|
|
325
345
|
await runtime.output(`${parsedArgs.targetId} agent model set to ${roleSelector}.`);
|
|
326
346
|
}
|
|
@@ -56,6 +56,12 @@ export interface FastStatusSessionLike {
|
|
|
56
56
|
readonly model?: Model;
|
|
57
57
|
/** Fast predicate against the main session tier (current model + `modelRoles`). */
|
|
58
58
|
isFastForProvider(provider?: string): boolean;
|
|
59
|
+
/**
|
|
60
|
+
* Current-model EFFECTIVE fast state (intent minus any provider auto-disable).
|
|
61
|
+
* Used for the current-model row so it matches what the next request does.
|
|
62
|
+
* Optional so lightweight fakes can omit it; falls back to `isFastForProvider`.
|
|
63
|
+
*/
|
|
64
|
+
isFastModeActive?(): boolean;
|
|
59
65
|
/** Fast predicate against the effective subagent tier (`task.agentModelOverrides` roles). */
|
|
60
66
|
isFastForSubagentProvider(provider?: string): boolean;
|
|
61
67
|
resolveRoleModelWithThinking(role: string): { model?: Model };
|
|
@@ -95,9 +101,13 @@ export interface BuildFastStatusReportArgs {
|
|
|
95
101
|
*/
|
|
96
102
|
export function buildFastStatusReport(args: BuildFastStatusReportArgs): string {
|
|
97
103
|
const { session, roleTargets, iconFast, formatInactive } = args;
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
104
|
+
// Current-model row uses the EFFECTIVE predicate (intent minus any provider
|
|
105
|
+
// auto-disable) so it matches the next request; `modelRoles` rows below stay
|
|
106
|
+
// on pure intent. Fall back to intent when a fake omits `isFastModeActive`.
|
|
107
|
+
const currentFast = session.isFastModeActive
|
|
108
|
+
? session.isFastModeActive()
|
|
109
|
+
: session.isFastForProvider(session.model?.provider);
|
|
110
|
+
const rows: FastStatusRow[] = [{ label: "현재 모델", model: session.model, fast: currentFast }];
|
|
101
111
|
for (const target of roleTargets) {
|
|
102
112
|
const resolved = session.resolveRoleModelWithThinking(target.id);
|
|
103
113
|
if (resolved.model) {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { parseCommandArgs } from "../../utils/command-args";
|
|
1
2
|
import type { ParsedSlashCommand, SlashCommandResult, SlashCommandRuntime } from "../types";
|
|
2
3
|
|
|
3
4
|
export interface ParsedSubcommand {
|
|
@@ -65,7 +66,7 @@ export function errorMessage(error: unknown): string {
|
|
|
65
66
|
* "name required" diagnostics with their own messaging.
|
|
66
67
|
*/
|
|
67
68
|
export function parseNamedScopeArgs(rest: string, invalidScopeMessage: string): NamedScopeArgs {
|
|
68
|
-
const tokens = rest
|
|
69
|
+
const tokens = parseCommandArgs(rest);
|
|
69
70
|
let name: string | undefined;
|
|
70
71
|
let scope: ConfigScope = "project";
|
|
71
72
|
let i = 0;
|
package/src/system-prompt.ts
CHANGED
|
@@ -336,6 +336,8 @@ export interface BuildSystemPromptOptions {
|
|
|
336
336
|
toolNames?: string[];
|
|
337
337
|
/** Text to append to system prompt. */
|
|
338
338
|
appendSystemPrompt?: string;
|
|
339
|
+
/** Rendered SKC plugin system-appendix blocks (lower-authority, appended last). */
|
|
340
|
+
pluginAppendices?: string;
|
|
339
341
|
/** Repeat full tool descriptions in system prompt. Default: false */
|
|
340
342
|
repeatToolDescriptions?: boolean;
|
|
341
343
|
/** Skills settings for discovery. */
|
|
@@ -380,6 +382,7 @@ export async function buildSystemPrompt(options: BuildSystemPromptOptions = {}):
|
|
|
380
382
|
customPrompt,
|
|
381
383
|
tools,
|
|
382
384
|
appendSystemPrompt,
|
|
385
|
+
pluginAppendices,
|
|
383
386
|
repeatToolDescriptions = false,
|
|
384
387
|
skillsSettings,
|
|
385
388
|
toolNames: providedToolNames,
|
|
@@ -579,5 +582,11 @@ export async function buildSystemPrompt(options: BuildSystemPromptOptions = {}):
|
|
|
579
582
|
systemPrompt.push(projectPrompt);
|
|
580
583
|
}
|
|
581
584
|
|
|
585
|
+
// Plugin system appendices are appended last as a lower-authority block; they
|
|
586
|
+
// can never override base/project/developer instructions above them.
|
|
587
|
+
if (pluginAppendices?.trim()) {
|
|
588
|
+
systemPrompt.push(pluginAppendices.trim());
|
|
589
|
+
}
|
|
590
|
+
|
|
582
591
|
return { systemPrompt };
|
|
583
592
|
}
|
package/src/task/executor.ts
CHANGED
|
@@ -9,6 +9,7 @@ import * as fs from "node:fs/promises";
|
|
|
9
9
|
import path from "node:path";
|
|
10
10
|
import type { AgentEvent, AgentIdentity, AgentTelemetryConfig, ThinkingLevel } from "@sayknow-cli/agent-core";
|
|
11
11
|
import { recordHandoff, resolveTelemetry } from "@sayknow-cli/agent-core";
|
|
12
|
+
import type { ServiceTier } from "@sayknow-cli/ai";
|
|
12
13
|
import { type JsonSchemaValidationIssue, validateJsonSchemaValue } from "@sayknow-cli/ai/utils/schema";
|
|
13
14
|
import { logger, prompt, untilAborted } from "@sayknow-cli/utils";
|
|
14
15
|
import { AsyncJobManager } from "../async";
|
|
@@ -19,7 +20,7 @@ import { Settings } from "../config/settings";
|
|
|
19
20
|
import { SETTINGS_SCHEMA, type SettingPath } from "../config/settings-schema";
|
|
20
21
|
import { runExtensionCompact, runExtensionSetModel } from "../extensibility/extensions/compact-handler";
|
|
21
22
|
import { getSessionSlashCommands } from "../extensibility/extensions/get-commands-handler";
|
|
22
|
-
import { buildAgentSubskillInjection } from "../extensibility/skc-plugins";
|
|
23
|
+
import { buildAgentSubskillInjection, renderAgentPromptAdditions } from "../extensibility/skc-plugins";
|
|
23
24
|
import { buildSkillPromptMessage, type Skill } from "../extensibility/skills";
|
|
24
25
|
import type { HindsightSessionState } from "../hindsight/state";
|
|
25
26
|
import type { LocalProtocolOptions } from "../internal-urls";
|
|
@@ -146,6 +147,13 @@ export interface ExecutorOptions {
|
|
|
146
147
|
authStorage?: AuthStorage;
|
|
147
148
|
modelRegistry?: ModelRegistry;
|
|
148
149
|
settings?: Settings;
|
|
150
|
+
/**
|
|
151
|
+
* Live service-tier intent of the parent session (`AgentSession.serviceTier`),
|
|
152
|
+
* used as the inherited tier when `task.serviceTier === "inherit"`. Passing the
|
|
153
|
+
* live value (not the stale settings snapshot) lets a runtime `/fast on` reach
|
|
154
|
+
* subagents, and a main-model fast-mode auto-disable does not clobber it.
|
|
155
|
+
*/
|
|
156
|
+
inheritedServiceTier?: ServiceTier;
|
|
149
157
|
/** Override local:// protocol options so subagent shares parent's local:// root */
|
|
150
158
|
localProtocolOptions?: LocalProtocolOptions;
|
|
151
159
|
/**
|
|
@@ -482,15 +490,19 @@ function getUsageTokens(usage: unknown): number {
|
|
|
482
490
|
return firstNumberField(record, ["totalTokens", "total_tokens"]) ?? 0;
|
|
483
491
|
}
|
|
484
492
|
|
|
485
|
-
export function createSubagentSettings(baseSettings: Settings): Settings {
|
|
493
|
+
export function createSubagentSettings(baseSettings: Settings, inheritedServiceTier?: ServiceTier): Settings {
|
|
486
494
|
const snapshot: Partial<Record<SettingPath, unknown>> = {};
|
|
487
495
|
for (const key of Object.keys(SETTINGS_SCHEMA) as SettingPath[]) {
|
|
488
496
|
snapshot[key] = baseSettings.get(key);
|
|
489
497
|
}
|
|
490
|
-
// Subagent-scoped service-tier override: "inherit"
|
|
491
|
-
//
|
|
498
|
+
// Subagent-scoped service-tier override: "inherit" uses the parent session's
|
|
499
|
+
// LIVE intent (so a runtime `/fast on` reaches subagents and a main-model
|
|
500
|
+
// fast-mode auto-disable never clobbers it); any explicit value applies only
|
|
501
|
+
// to subagent sessions and wins over inherited intent.
|
|
492
502
|
const taskServiceTier = baseSettings.get("task.serviceTier");
|
|
493
|
-
if (taskServiceTier
|
|
503
|
+
if (taskServiceTier === "inherit") {
|
|
504
|
+
snapshot.serviceTier = inheritedServiceTier ?? "none";
|
|
505
|
+
} else {
|
|
494
506
|
snapshot.serviceTier = taskServiceTier;
|
|
495
507
|
}
|
|
496
508
|
return Settings.isolated({
|
|
@@ -571,7 +583,7 @@ export async function runSubprocess(options: ExecutorOptions): Promise<SingleRes
|
|
|
571
583
|
}
|
|
572
584
|
|
|
573
585
|
const settings = options.settings ?? Settings.isolated();
|
|
574
|
-
const subagentSettings = createSubagentSettings(settings);
|
|
586
|
+
const subagentSettings = createSubagentSettings(settings, options.inheritedServiceTier);
|
|
575
587
|
const maxRecursionDepth = settings.get("task.maxRecursionDepth") ?? 2;
|
|
576
588
|
const maxRuntimeMs = Math.max(0, Math.trunc(Number(settings.get("task.maxRuntimeMs") ?? 0) || 0));
|
|
577
589
|
const parentDepth = options.taskDepth ?? 0;
|
|
@@ -1229,6 +1241,13 @@ export async function runSubprocess(options: ExecutorOptions): Promise<SingleRes
|
|
|
1229
1241
|
agentName: agent.name,
|
|
1230
1242
|
});
|
|
1231
1243
|
|
|
1244
|
+
let agentPromptAdditions = { appendix: "", advertisement: "" };
|
|
1245
|
+
try {
|
|
1246
|
+
agentPromptAdditions = await renderAgentPromptAdditions({ cwd, agentName: agent.name });
|
|
1247
|
+
} catch (error) {
|
|
1248
|
+
logger.warn("Failed to render SKC plugin agent prompt additions", { error });
|
|
1249
|
+
}
|
|
1250
|
+
|
|
1232
1251
|
const { session } = await awaitAbortable(
|
|
1233
1252
|
createAgentSession({
|
|
1234
1253
|
cwd: worktree ?? cwd,
|
|
@@ -1259,7 +1278,12 @@ export async function runSubprocess(options: ExecutorOptions): Promise<SingleRes
|
|
|
1259
1278
|
ircSelfId: ircEnabled ? id : "",
|
|
1260
1279
|
forkContext: forkContextNotice,
|
|
1261
1280
|
});
|
|
1262
|
-
|
|
1281
|
+
// Order: base agent prompt -> agent appendix -> Tier-1 advertisement -> Tier-2 body.
|
|
1282
|
+
const appendixPart = agentPromptAdditions.appendix ? `\n\n${agentPromptAdditions.appendix}` : "";
|
|
1283
|
+
const advertPart = agentPromptAdditions.advertisement
|
|
1284
|
+
? `\n\n${agentPromptAdditions.advertisement}`
|
|
1285
|
+
: "";
|
|
1286
|
+
const promptWithSubskills = `${subagentPrompt}${appendixPart}${advertPart}${agentSubskillBlock}`;
|
|
1263
1287
|
return defaultPrompt.length === 0
|
|
1264
1288
|
? [promptWithSubskills]
|
|
1265
1289
|
: [...defaultPrompt.slice(0, -1), promptWithSubskills, defaultPrompt[defaultPrompt.length - 1]];
|
package/src/task/index.ts
CHANGED
|
@@ -1311,6 +1311,7 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
|
|
|
1311
1311
|
authStorage: this.session.authStorage,
|
|
1312
1312
|
modelRegistry: this.session.modelRegistry,
|
|
1313
1313
|
settings: this.session.settings,
|
|
1314
|
+
inheritedServiceTier: this.session.serviceTier,
|
|
1314
1315
|
contextFiles,
|
|
1315
1316
|
skills: availableSkills,
|
|
1316
1317
|
autoloadSkills: resolvedAutoloadSkills,
|
|
@@ -1372,6 +1373,7 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
|
|
|
1372
1373
|
authStorage: this.session.authStorage,
|
|
1373
1374
|
modelRegistry: this.session.modelRegistry,
|
|
1374
1375
|
settings: this.session.settings,
|
|
1376
|
+
inheritedServiceTier: this.session.serviceTier,
|
|
1375
1377
|
contextFiles,
|
|
1376
1378
|
skills: availableSkills,
|
|
1377
1379
|
autoloadSkills: resolvedAutoloadSkills,
|
package/src/tools/ask.ts
CHANGED
|
@@ -260,7 +260,11 @@ async function askSingleQuestion(
|
|
|
260
260
|
? "up/down navigate enter select ←/→ question esc cancel"
|
|
261
261
|
: "up/down navigate enter select esc cancel";
|
|
262
262
|
const helpText =
|
|
263
|
-
scrollTitleRows === undefined
|
|
263
|
+
scrollTitleRows === undefined
|
|
264
|
+
? baseHelpText
|
|
265
|
+
: navigation
|
|
266
|
+
? "↑/↓ select enter ←/→ question esc PgUp/PgDn/Ctrl+u/d: question · Wheel: transcript"
|
|
267
|
+
: "↑/↓ select enter esc PgUp/PgDn/Ctrl+u/d: question · Wheel: transcript";
|
|
264
268
|
const dialogOptions = {
|
|
265
269
|
initialIndex,
|
|
266
270
|
timeout,
|
package/src/tools/bash.ts
CHANGED
|
@@ -25,6 +25,7 @@ import { type BashInteractiveResult, runInteractiveBashPty } from "./bash-intera
|
|
|
25
25
|
import { checkBashInterception } from "./bash-interceptor";
|
|
26
26
|
import { canUseInteractiveBashPty } from "./bash-pty-selection";
|
|
27
27
|
import { expandInternalUrls, type InternalUrlExpansionOptions } from "./bash-skill-urls";
|
|
28
|
+
import { checkComposerBashPolicy } from "./composer-bash-policy";
|
|
28
29
|
import { formatStyledTruncationWarning, type OutputMeta, stripOutputNotice } from "./output-meta";
|
|
29
30
|
import { resolveToCwd } from "./path-utils";
|
|
30
31
|
import { formatToolWorkingDirectory, replaceTabs } from "./render-utils";
|
|
@@ -570,6 +571,14 @@ export class BashTool implements AgentTool<BashToolSchema, BashToolDetails> {
|
|
|
570
571
|
}
|
|
571
572
|
}
|
|
572
573
|
|
|
574
|
+
const composerPolicy = checkComposerBashPolicy({
|
|
575
|
+
modelId: this.session.getActiveModelString?.() ?? this.session.getModelString?.() ?? this.session.model?.id,
|
|
576
|
+
commands: rawCommand === command ? [command] : [rawCommand, command],
|
|
577
|
+
});
|
|
578
|
+
if (!composerPolicy.allowed) {
|
|
579
|
+
throw new ToolError(composerPolicy.message);
|
|
580
|
+
}
|
|
581
|
+
|
|
573
582
|
const internalUrlOptions: InternalUrlExpansionOptions = {
|
|
574
583
|
skills: this.session.skills ?? [],
|
|
575
584
|
internalRouter: InternalUrlRouter.instance(),
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { isComposerHarnessModel } from "@sayknow-cli/ai/providers/composer-discipline";
|
|
2
|
+
|
|
3
|
+
export const COMPOSER_BASH_POLICY_ERROR =
|
|
4
|
+
"Composer bash policy blocked repository file I/O. Use find, search, read, and edit tools for file discovery, file inspection, and file mutation.";
|
|
5
|
+
|
|
6
|
+
type ComposerBashPolicyResult =
|
|
7
|
+
| { allowed: true }
|
|
8
|
+
| {
|
|
9
|
+
allowed: false;
|
|
10
|
+
reason: string;
|
|
11
|
+
message: string;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
const BLOCK_PATTERNS: Array<{ id: string; pattern: RegExp }> = [
|
|
15
|
+
{ id: "pipe", pattern: /\|/ },
|
|
16
|
+
{ id: "process-substitution", pattern: /<[>(]/ },
|
|
17
|
+
{ id: "heredoc", pattern: /<<[-~]?/ },
|
|
18
|
+
{ id: "command-substitution", pattern: /\$\(|`/ },
|
|
19
|
+
{ id: "redirection", pattern: /(^|[^<>])(?:>>?|<)(?!=)/ },
|
|
20
|
+
{ id: "tee", pattern: /(?:^|[;&|\s])tee(?:\s|$)/ },
|
|
21
|
+
{
|
|
22
|
+
id: "shell-file-read-discovery",
|
|
23
|
+
pattern: /(?:^|[;&|()\s])(?:\S*\/)?(?:cat|head|tail|less|more|grep|rg|find|fd|tree|ls)\b/,
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
id: "shell-file-mutation",
|
|
27
|
+
pattern: /(?:^|[;&|()\s])(?:\S*\/)?(?:cp|mv|rm|touch|mkdir|chmod|chown|ln)\b/,
|
|
28
|
+
},
|
|
29
|
+
{ id: "sed-print", pattern: /(?:^|[;&|()\s])sed\s+(?:-[^\s]*n\b|.*\bp\b)/ },
|
|
30
|
+
{ id: "awk-print", pattern: /(?:^|[;&|()\s])awk\b/ },
|
|
31
|
+
{ id: "git-ls-files", pattern: /(?:^|[;&|()\s])git(?:\s+-C\s+\S+)?\s+ls-files\b/ },
|
|
32
|
+
{ id: "git-grep", pattern: /(?:^|[;&|()\s])git(?:\s+-C\s+\S+)?\s+grep\b/ },
|
|
33
|
+
{ id: "git-show-path", pattern: /(?:^|[;&|()\s])git(?:\s+-C\s+\S+)?\s+show\s+\S+:\S+/ },
|
|
34
|
+
{ id: "git-diff", pattern: /(?:^|[;&|()\s])git(?:\s+-C\s+\S+)?\s+diff(?:\s|$)/ },
|
|
35
|
+
{ id: "git-cat-file", pattern: /(?:^|[;&|()\s])git(?:\s+-C\s+\S+)?\s+cat-file\b/ },
|
|
36
|
+
{
|
|
37
|
+
id: "git-show-discovery",
|
|
38
|
+
pattern: /(?:^|[;&|()\s])git(?:\s+-C\s+\S+)?\s+show\b.*(?:--name-only|--name-status|--stat)/,
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
id: "git-log-path-discovery",
|
|
42
|
+
pattern: /(?:^|[;&|()\s])git(?:\s+-C\s+\S+)?\s+log\b.*(?:--name-only|--name-status|--stat)/,
|
|
43
|
+
},
|
|
44
|
+
{ id: "sed-in-place", pattern: /(?:^|[;&|()\s])sed\s+-[^\s]*i\b/ },
|
|
45
|
+
{ id: "perl-in-place", pattern: /(?:^|[;&|()\s])perl\s+-[^\s]*p[^\s]*i\b/ },
|
|
46
|
+
{
|
|
47
|
+
id: "script-file-io",
|
|
48
|
+
pattern:
|
|
49
|
+
/(?:^|[;&|()\s])(?:python3?|node|bun)\s+(?:-\s*<<|-c\b|-e\b|--eval\b).*?(?:read_text|read_bytes|write_text|iterdir|listdir|glob\.glob|readFile|readFileSync|writeFile|writeFileSync|readdir|readdirSync|stat|statSync|cpSync|rmSync|mkdirSync|createReadStream|createWriteStream|Bun\.file|Bun\.write|fs\.readFile|fs\.writeFile|fs\.readdir|fs\.stat|fs\.cp|fs\.rm|fs\.mkdir|open\s*\()/s,
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
id: "contaminated-command",
|
|
53
|
+
pattern: /```|^\s*(?:I\s+(?:will|need|am going)|We\s+(?:need|will)|First[, ]|Now[, ]|Let's)\b/im,
|
|
54
|
+
},
|
|
55
|
+
];
|
|
56
|
+
|
|
57
|
+
const ALLOWED_TERMINAL_PATTERNS: RegExp[] = [
|
|
58
|
+
/^bun\s+test(?:\s+[\w./:@=-]+)*$/,
|
|
59
|
+
/^bun\s+run\s+(?:check(?::[\w-]+)?|test(?::[\w-]+)?|build(?::[\w-]+)?)(?:\s+[\w./:@=-]+)*$/,
|
|
60
|
+
/^bun\s+--version$/,
|
|
61
|
+
/^mise\s+x\s+bun@\d+\.\d+\.\d+\s+--\s+bun\s+test(?:\s+[\w./:@=-]+)*$/,
|
|
62
|
+
/^mise\s+x\s+bun@\d+\.\d+\.\d+\s+--\s+bun\s+run\s+(?:check(?::[\w-]+)?|test(?::[\w-]+)?|build(?::[\w-]+)?)(?:\s+[\w./:@=-]+)*$/,
|
|
63
|
+
/^cargo\s+(?:test|check|build)(?:\s+[\w./:@=-]+)*$/,
|
|
64
|
+
/^git\s+status(?:\s+--short)?(?:\s+--branch)?$/,
|
|
65
|
+
/^git\s+rev-parse\s+HEAD$/,
|
|
66
|
+
/^npm\s+--version$/,
|
|
67
|
+
/^pnpm\s+--version$/,
|
|
68
|
+
/^yarn\s+--version$/,
|
|
69
|
+
];
|
|
70
|
+
|
|
71
|
+
function isAllowedComposerTerminalCommand(command: string): boolean {
|
|
72
|
+
const normalized = command.trim().replace(/\s+/g, " ");
|
|
73
|
+
return ALLOWED_TERMINAL_PATTERNS.some(pattern => pattern.test(normalized));
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export function isComposerBashPolicyModel(modelId: string | undefined): boolean {
|
|
77
|
+
return Boolean(modelId && isComposerHarnessModel(modelId));
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export function checkComposerBashPolicy(input: {
|
|
81
|
+
modelId?: string;
|
|
82
|
+
commands: readonly string[];
|
|
83
|
+
}): ComposerBashPolicyResult {
|
|
84
|
+
if (!isComposerBashPolicyModel(input.modelId)) return { allowed: true };
|
|
85
|
+
for (const command of input.commands) {
|
|
86
|
+
for (const block of BLOCK_PATTERNS) {
|
|
87
|
+
if (block.pattern.test(command)) {
|
|
88
|
+
return { allowed: false, reason: block.id, message: COMPOSER_BASH_POLICY_ERROR };
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
if (!isAllowedComposerTerminalCommand(command)) {
|
|
92
|
+
return { allowed: false, reason: "not-allowlisted", message: COMPOSER_BASH_POLICY_ERROR };
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
return { allowed: true };
|
|
96
|
+
}
|
package/src/tools/fetch.ts
CHANGED
|
@@ -16,6 +16,8 @@ import { renderStatusLine } from "../tui";
|
|
|
16
16
|
import { CachedOutputBlock } from "../tui/output-block";
|
|
17
17
|
import { formatDimensionNote, resizeImage } from "../utils/image-resize";
|
|
18
18
|
import { ensureTool } from "../utils/tools-manager";
|
|
19
|
+
import { INSANE_NOTES, tryInsaneFetch } from "../web/insane/bridge";
|
|
20
|
+
import { validatePublicHttpUrl, validatePublicHttpUrlForInsane } from "../web/insane/url-guard";
|
|
19
21
|
import { extractWithParallel, findParallelApiKey, getParallelExtractContent } from "../web/parallel";
|
|
20
22
|
import { specialHandlers } from "../web/scrapers";
|
|
21
23
|
import type { RenderResult } from "../web/scrapers/types";
|
|
@@ -705,6 +707,55 @@ async function handleSpecialUrls(
|
|
|
705
707
|
// Main Render Function
|
|
706
708
|
// =============================================================================
|
|
707
709
|
|
|
710
|
+
/**
|
|
711
|
+
* Opt-in insane-search fallback for blocked / degraded public URL reads.
|
|
712
|
+
*
|
|
713
|
+
* Returns a finalized `method: "insane"` result on success, or null (so the
|
|
714
|
+
* caller continues with its normal degraded behavior). Fail-closed: no note,
|
|
715
|
+
* guard DNS, dependency probe, or subprocess when raw mode or the opt-in
|
|
716
|
+
* setting is off. The public-URL guard runs BEFORE any probe/spawn.
|
|
717
|
+
*/
|
|
718
|
+
export async function tryInsaneFallback(args: {
|
|
719
|
+
url: string;
|
|
720
|
+
finalUrl: string;
|
|
721
|
+
timeout: number;
|
|
722
|
+
raw: boolean;
|
|
723
|
+
settings: Settings;
|
|
724
|
+
signal: AbortSignal | undefined;
|
|
725
|
+
fetchedAt: string;
|
|
726
|
+
notes: string[];
|
|
727
|
+
}): Promise<FetchRenderResult | null> {
|
|
728
|
+
if (args.raw) return null;
|
|
729
|
+
if (args.settings.get("web.insaneFallback") !== true) return null;
|
|
730
|
+
|
|
731
|
+
const target = args.finalUrl || args.url;
|
|
732
|
+
const guard = await validatePublicHttpUrlForInsane(target);
|
|
733
|
+
if (!guard.ok) {
|
|
734
|
+
args.notes.push(INSANE_NOTES.guardBlocked(guard.reason));
|
|
735
|
+
return null;
|
|
736
|
+
}
|
|
737
|
+
|
|
738
|
+
const result = await tryInsaneFetch(guard.url.toString(), {
|
|
739
|
+
timeoutMs: args.timeout * 1000,
|
|
740
|
+
signal: args.signal,
|
|
741
|
+
});
|
|
742
|
+
if (result.ok) {
|
|
743
|
+
const output = finalizeOutput(result.content);
|
|
744
|
+
return {
|
|
745
|
+
url: args.url,
|
|
746
|
+
finalUrl: target,
|
|
747
|
+
contentType: "text/markdown",
|
|
748
|
+
method: "insane",
|
|
749
|
+
content: output.content,
|
|
750
|
+
fetchedAt: args.fetchedAt,
|
|
751
|
+
truncated: output.truncated,
|
|
752
|
+
notes: [...args.notes, ...result.notes],
|
|
753
|
+
};
|
|
754
|
+
}
|
|
755
|
+
for (const note of result.notes) args.notes.push(note);
|
|
756
|
+
return null;
|
|
757
|
+
}
|
|
758
|
+
|
|
708
759
|
/**
|
|
709
760
|
* Main render function implementing the full pipeline
|
|
710
761
|
*/
|
|
@@ -738,6 +789,21 @@ async function renderUrl(
|
|
|
738
789
|
|
|
739
790
|
// Step 0: Normalize URL (ensure scheme for special handlers)
|
|
740
791
|
url = normalizeUrl(url);
|
|
792
|
+
const publicUrl = await validatePublicHttpUrl(url);
|
|
793
|
+
if (!publicUrl.ok) {
|
|
794
|
+
notes.push(`Blocked URL fetch: target URL is not public HTTP(S): ${publicUrl.reason}`);
|
|
795
|
+
return {
|
|
796
|
+
url,
|
|
797
|
+
finalUrl: url,
|
|
798
|
+
contentType: "unknown",
|
|
799
|
+
method: "failed",
|
|
800
|
+
content: "",
|
|
801
|
+
fetchedAt,
|
|
802
|
+
truncated: false,
|
|
803
|
+
notes,
|
|
804
|
+
};
|
|
805
|
+
}
|
|
806
|
+
url = publicUrl.url.toString();
|
|
741
807
|
|
|
742
808
|
// Step 1: Try special handlers for known sites (unless raw mode)
|
|
743
809
|
if (!raw) {
|
|
@@ -751,6 +817,20 @@ async function renderUrl(
|
|
|
751
817
|
throw new ToolAbortError();
|
|
752
818
|
}
|
|
753
819
|
if (!response.ok) {
|
|
820
|
+
const failureNote =
|
|
821
|
+
response.error ?? (response.status ? `Failed to fetch URL (HTTP ${response.status})` : "Failed to fetch URL");
|
|
822
|
+
notes.push(failureNote);
|
|
823
|
+
const insane = await tryInsaneFallback({
|
|
824
|
+
url,
|
|
825
|
+
finalUrl: response.finalUrl || url,
|
|
826
|
+
timeout,
|
|
827
|
+
raw,
|
|
828
|
+
settings,
|
|
829
|
+
signal,
|
|
830
|
+
fetchedAt,
|
|
831
|
+
notes,
|
|
832
|
+
});
|
|
833
|
+
if (insane) return insane;
|
|
754
834
|
return {
|
|
755
835
|
url,
|
|
756
836
|
finalUrl: response.finalUrl || url,
|
|
@@ -759,7 +839,7 @@ async function renderUrl(
|
|
|
759
839
|
content: "",
|
|
760
840
|
fetchedAt,
|
|
761
841
|
truncated: false,
|
|
762
|
-
notes
|
|
842
|
+
notes,
|
|
763
843
|
};
|
|
764
844
|
}
|
|
765
845
|
|
|
@@ -1062,6 +1142,8 @@ async function renderUrl(
|
|
|
1062
1142
|
const htmlResult = await renderHtmlToText(finalUrl, rawContent, timeout, settings, signal, storage);
|
|
1063
1143
|
if (!htmlResult.ok) {
|
|
1064
1144
|
notes.push("html rendering failed (lynx/html2text unavailable)");
|
|
1145
|
+
const insane = await tryInsaneFallback({ url, finalUrl, timeout, raw, settings, signal, fetchedAt, notes });
|
|
1146
|
+
if (insane) return insane;
|
|
1065
1147
|
const output = finalizeOutput(rawContent);
|
|
1066
1148
|
return {
|
|
1067
1149
|
url,
|
|
@@ -1122,6 +1204,17 @@ async function renderUrl(
|
|
|
1122
1204
|
};
|
|
1123
1205
|
}
|
|
1124
1206
|
|
|
1207
|
+
const insaneLowQuality = await tryInsaneFallback({
|
|
1208
|
+
url,
|
|
1209
|
+
finalUrl,
|
|
1210
|
+
timeout,
|
|
1211
|
+
raw,
|
|
1212
|
+
settings,
|
|
1213
|
+
signal,
|
|
1214
|
+
fetchedAt,
|
|
1215
|
+
notes,
|
|
1216
|
+
});
|
|
1217
|
+
if (insaneLowQuality) return insaneLowQuality;
|
|
1125
1218
|
notes.push("Page appears to require JavaScript or is mostly navigation");
|
|
1126
1219
|
}
|
|
1127
1220
|
|
package/src/tools/index.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { AgentTelemetryConfig, AgentTool } from "@sayknow-cli/agent-core";
|
|
2
|
-
import type { Model, ToolChoice } from "@sayknow-cli/ai";
|
|
2
|
+
import type { Model, ServiceTier, ToolChoice } from "@sayknow-cli/ai";
|
|
3
3
|
import { $env, $flag, logger } from "@sayknow-cli/utils";
|
|
4
4
|
import type { PromptTemplate } from "../config/prompt-templates";
|
|
5
5
|
import type { Settings } from "../config/settings";
|
|
@@ -58,6 +58,7 @@ import { SearchToolBm25Tool } from "./search-tool-bm25";
|
|
|
58
58
|
import { SkillTool } from "./skill";
|
|
59
59
|
import { loadSshTool } from "./ssh";
|
|
60
60
|
import { SubagentTool } from "./subagent";
|
|
61
|
+
import { TelegramSendTool } from "./telegram-send";
|
|
61
62
|
import { type TodoPhase, TodoWriteTool } from "./todo-write";
|
|
62
63
|
import { WriteTool } from "./write";
|
|
63
64
|
import { YieldTool } from "./yield";
|
|
@@ -96,6 +97,7 @@ export * from "./search-tool-bm25";
|
|
|
96
97
|
export * from "./skill";
|
|
97
98
|
export * from "./ssh";
|
|
98
99
|
export * from "./subagent";
|
|
100
|
+
export * from "./telegram-send";
|
|
99
101
|
export * from "./todo-write";
|
|
100
102
|
export * from "./vim";
|
|
101
103
|
export * from "./write";
|
|
@@ -220,6 +222,8 @@ export interface ToolSession {
|
|
|
220
222
|
agentOutputManager?: AgentOutputManager;
|
|
221
223
|
/** Settings instance for passing to subagents */
|
|
222
224
|
settings: Settings;
|
|
225
|
+
/** Live service-tier intent of the parent session, inherited by `inherit` subagents. */
|
|
226
|
+
serviceTier?: ServiceTier;
|
|
223
227
|
/** Plan mode state (if active) */
|
|
224
228
|
getPlanModeState?: () => PlanModeState | undefined;
|
|
225
229
|
/** Goal mode state (if active or paused) */
|
|
@@ -402,6 +406,7 @@ export const BUILTIN_TOOLS: Record<string, ToolFactory> = {
|
|
|
402
406
|
todo_write: s => new TodoWriteTool(s),
|
|
403
407
|
web_search: s => new WebSearchTool(s),
|
|
404
408
|
search_tool_bm25: SearchToolBm25Tool.createIf,
|
|
409
|
+
telegram_send: TelegramSendTool.createIf,
|
|
405
410
|
write: s => new WriteTool(s),
|
|
406
411
|
skill: SkillTool.createIf,
|
|
407
412
|
goal: s => new GoalTool(s),
|