mirror of
https://github.com/deepseek-ai/deepseek-harness.git
synced 2026-09-13 04:03:30 +00:00
feat(sdk): disable str_replace_editor by default
This commit is contained in:
+2
-2
@@ -2,5 +2,5 @@
|
||||
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
||||
# after editing either side, bring the other along and re-record with:
|
||||
# pnpm run verify-translation-pairing --write .agents/notes/implemented/architecture/2026-08-22-single-dsh-application-launcher.md
|
||||
2026-08-22-single-dsh-application-launcher.md: 5729ed770b1d26969079e6341d2d2da4b17d0b90
|
||||
2026-08-22-single-dsh-application-launcher.zh.md: 45d5b9758fd1f01057de0f34e580249b63f9877e
|
||||
2026-08-22-single-dsh-application-launcher.md: 7fcb33d8d5c0a9979f3cc5724c2211bf9a1e55a1
|
||||
2026-08-22-single-dsh-application-launcher.zh.md: ac91a7b854042b5f974931aa69fffc91fd91319d
|
||||
|
||||
+1
-1
@@ -34,7 +34,7 @@ Profile manifests own patch reload:
|
||||
|
||||
Custom profiles default to `live`. A startup profile still applies its bundle, profile, home-level, and invocation `--patch` layers, but it does not watch them after boot. `dsh-base` inserts the module-HMR row disabled; a profile with a tested source-module reload lifecycle must enable it explicitly. None of the shipped profiles enable server module HMR: `patchReload: live` uses the launcher's config-only watcher while the startup profiles install no watcher. SDK and ACP cannot safely replace their server, agents, persistence, or tool registry inside one owned stdio connection.
|
||||
|
||||
The shipped protocol profiles reserve stdout for protocol frames, expose help without starting transport, and route stdin EOF and signals through bounded root disposal. ACP remains automation-only. The SDK JSON-RPC methods, notification fields, and `initialize.serverInfo.name` remain stable. Full-profile model-visible tool and persistence defaults come from `dsh-base`; `sdk-minimal` owns its explicit defaults. Runnable snapshots own the assembled application outputs.
|
||||
The shipped protocol profiles reserve stdout for protocol frames, expose help without starting transport, and route stdin EOF and signals through bounded root disposal. ACP remains automation-only. The SDK JSON-RPC methods, notification fields, and `initialize.serverInfo.name` remain stable. Full-profile model-visible tool and persistence defaults start from `dsh-base`; the SDK application applies its [default editor selection](../simplification/2026-09-05-sdk-default-file-editor.md), while `sdk-minimal` owns its explicit defaults. Runnable snapshots own the assembled application outputs.
|
||||
|
||||
### TypeScript SDK customization
|
||||
|
||||
|
||||
+1
-1
@@ -34,7 +34,7 @@ Profile manifest 负责 patch 重载:
|
||||
|
||||
自定义 profile 默认为 `live`。`startup` profile 仍会应用组合包、profile、home 级与调用时 `--patch` 各层,但启动后不会监视这些文件。`dsh-base` 插入的模块 HMR(热模块替换)配置项默认禁用;具有经过验证的源码模块重载生命周期的 profile 必须显式启用它。随附 profile 均不启用服务器模块 HMR:`patchReload: live` 使用启动器的仅配置 watcher,`startup` profile 则不安装 watcher。SDK 与 ACP 无法在一个自有 stdio 连接内安全替换其服务器、agent、持久化或工具注册表。
|
||||
|
||||
随附协议 profile 将 stdout 保留给协议帧,显示帮助时不启动 transport,并通过有界根节点 dispose(资源释放)处理 stdin EOF 与信号。ACP 继续仅用于自动化。SDK JSON-RPC 方法、通知字段与 `initialize.serverInfo.name` 保持稳定。完整 profile 的模型可见工具与持久化默认值来自 `dsh-base`;`sdk-minimal` 拥有自己的显式默认值。可运行快照负责固定已组装的应用输出。
|
||||
随附协议 profile 将 stdout 保留给协议帧,显示帮助时不启动 transport,并通过有界根节点 dispose(资源释放)处理 stdin EOF 与信号。ACP 继续仅用于自动化。SDK JSON-RPC 方法、通知字段与 `initialize.serverInfo.name` 保持稳定。完整 profile 的模型可见工具与持久化默认值以 `dsh-base` 为基础;SDK 应用采用其[默认编辑器选择](../simplification/2026-09-05-sdk-default-file-editor.zh.md),而 `sdk-minimal` 拥有自己的显式默认值。可运行快照负责固定已组装的应用输出。
|
||||
|
||||
### TypeScript SDK 自定义
|
||||
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
|
||||
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
||||
# after editing either side, bring the other along and re-record with:
|
||||
# pnpm run verify-translation-pairing --write .agents/notes/implemented/simplification/2026-09-05-sdk-default-file-editor.md
|
||||
2026-09-05-sdk-default-file-editor.md: ca1d321fb3562f0ea06fca6e4a4a146f922996d3
|
||||
2026-09-05-sdk-default-file-editor.zh.md: 9d54e839953f430826622681ab17bc56664e7dff
|
||||
@@ -0,0 +1,29 @@
|
||||
# Agent Note: SDK default file editor selection
|
||||
|
||||
Status: implemented
|
||||
|
||||
English | [中文](2026-09-05-sdk-default-file-editor.zh.md)
|
||||
|
||||
## Problem
|
||||
|
||||
The standard SDK profile inherits both `read`/`write`/`edit` and `str_replace_editor` from the shared base. These offer overlapping file editing interfaces, while the Web standard preset selects the former. [Issue #3599](https://github.com/deepseek-harness/deepseek-harness/issues/3599) requests the same editor choice for the standard SDK without making all SDK and Web behavior identical.
|
||||
|
||||
## Decision
|
||||
|
||||
The [SDK application patch](../../../../packages/bundle/sdk-app/cordis.patch.yml) disables the inherited `tool-str-replace-editor` row. The SDK retains `read`, `write`, and `edit`; the shared base, reusable editor package, and standalone `sdk-minimal` composition retain their own defaults. A trusted profile, home, or invocation patch can explicitly enable the row.
|
||||
|
||||
This narrows the SDK tool default described by [one dsh launcher](../architecture/2026-08-22-single-dsh-application-launcher.md). That decision remains active for launch ownership, shared services, and patch precedence; no active note is fully superseded.
|
||||
|
||||
## Alternatives considered
|
||||
|
||||
**Keep both editors enabled.** Shared base composition explains their availability, but the standard SDK does not need two default interfaces for the same file editing operations. Callers requiring this editor can select it explicitly.
|
||||
|
||||
**Remove the shared registration or reuse the entire Web preset.** Either changes more than the requested SDK default. Keeping the change in the SDK bundle preserves other profiles and the existing application architecture.
|
||||
|
||||
## Consequences
|
||||
|
||||
Default SDK requests omit the editor schema. Callers that select `str_replace_editor` by name need an explicit patch or their existing dedicated composition. This decision makes no claim of complete SDK/Web tool parity.
|
||||
|
||||
## Verification
|
||||
|
||||
The [SDK profile process test](../../../../apps/cli/tests/profiles/sdk/keyless-smoke.e2e.ts) captures actual model requests for the default roster, explicit editor enablement, and standalone minimal roster. [SDK recorded sessions](../../../../snapshots/sdk/sdk.snapshot.ts) pin the resulting schemas; shared cross-profile and persistent-editor recordings explicitly retain their required editor.
|
||||
@@ -0,0 +1,29 @@
|
||||
# Agent Note: SDK 默认文件编辑器选择
|
||||
|
||||
Status: implemented
|
||||
|
||||
[English](2026-09-05-sdk-default-file-editor.md) | 中文
|
||||
|
||||
## Problem
|
||||
|
||||
标准 SDK profile 从共享 base 同时继承 `read`/`write`/`edit` 和 `str_replace_editor`。这些工具提供重叠的文件编辑接口,而 Web standard preset 选择前者。[Issue #3599](https://github.com/deepseek-harness/deepseek-harness/issues/3599) 要求标准 SDK 采用相同的编辑器选择,不要求 SDK 与 Web 的全部行为一致。
|
||||
|
||||
## Decision
|
||||
|
||||
[SDK 应用 patch](../../../../packages/bundle/sdk-app/cordis.patch.yml) 禁用继承的 `tool-str-replace-editor` 配置项。SDK 保留 `read`、`write` 和 `edit`;共享 base、可复用编辑器包及独立 `sdk-minimal` 组合保留各自的默认值。受信任的 profile、home 或逐次调用 patch 可以显式启用该配置项。
|
||||
|
||||
本决策收窄了[统一 dsh 启动器](../architecture/2026-08-22-single-dsh-application-launcher.zh.md)所述的 SDK 工具默认值。该决策对启动所有权、共享服务和 patch 优先级仍然有效;没有被完全取代的活跃 Agent Note。
|
||||
|
||||
## Alternatives considered
|
||||
|
||||
**继续默认启用两个编辑器。** 共享 base 组合解释了它们为何可用,但标准 SDK 无需为相同的文件编辑操作默认提供两套接口。需要此编辑器的调用方可以显式选择它。
|
||||
|
||||
**移除共享注册或复用整个 Web preset。** 两者都会扩大 SDK 默认值调整的范围。将改动放在 SDK bundle 中可以保留其他 profile 和现有应用架构。
|
||||
|
||||
## Consequences
|
||||
|
||||
默认 SDK 请求省略该编辑器 schema。按名称选择 `str_replace_editor` 的调用方需要显式 patch 或其现有专用组合。本决策不承诺 SDK/Web 的全部工具一致。
|
||||
|
||||
## Verification
|
||||
|
||||
[SDK profile 进程测试](../../../../apps/cli/tests/profiles/sdk/keyless-smoke.e2e.ts) 捕获默认工具清单、显式启用编辑器和独立极简工具清单的实际模型请求。[SDK 录制会话](../../../../snapshots/sdk/sdk.snapshot.ts) 固定最终 schema;跨 profile 共享录制与持久编辑器录制显式保留其所需的编辑器。
|
||||
@@ -1,5 +1,5 @@
|
||||
import { createServer } from 'node:http'
|
||||
import { mkdtemp, readFile, readdir, rm } from 'node:fs/promises'
|
||||
import { mkdtemp, readFile, readdir, rm, writeFile } from 'node:fs/promises'
|
||||
import { tmpdir } from 'node:os'
|
||||
import { join } from 'node:path'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
@@ -46,11 +46,14 @@ function waitForLine(
|
||||
|
||||
describe('Python SDK dsh profile keyless smoke', () => {
|
||||
it.each([
|
||||
{ label: 'reports max-token turns with the default mapping config', envValue: undefined },
|
||||
{ label: 'reports max-token turns with mapping enabled through env', envValue: 'true' },
|
||||
{ label: 'reports max-token turns with mapping disabled through env', envValue: 'false' },
|
||||
])('$label', async ({ envValue }) => {
|
||||
{ label: 'reports max-token turns with the default mapping config', envValue: undefined, editorEnabled: false },
|
||||
{ label: 'reports max-token turns with mapping enabled through env', envValue: 'true', editorEnabled: false },
|
||||
{ label: 'reports max-token turns with mapping disabled through env', envValue: 'false', editorEnabled: false },
|
||||
{ label: 'allows an explicit patch to enable str_replace_editor', envValue: undefined, editorEnabled: true },
|
||||
])('$label', async ({ envValue, editorEnabled }) => {
|
||||
const root = await mkdtemp(join(tmpdir(), 'dsh-python-sdk-runtime-smoke-'))
|
||||
const editorPatch = join(root, 'editor.patch.yml')
|
||||
if (editorEnabled) await writeFile(editorPatch, '- id: tool-str-replace-editor\n disabled: false\n')
|
||||
const modelRequests: Record<string, unknown>[] = []
|
||||
const modelServer = createServer((request, response) => {
|
||||
let body = ''
|
||||
@@ -76,6 +79,7 @@ describe('Python SDK dsh profile keyless smoke', () => {
|
||||
binScript,
|
||||
'--profile',
|
||||
'sdk',
|
||||
...(editorEnabled ? ['--patch', editorPatch] : []),
|
||||
], {
|
||||
cwd: repoRoot,
|
||||
env: {
|
||||
@@ -154,7 +158,8 @@ describe('Python SDK dsh profile keyless smoke', () => {
|
||||
const toolNames = tools.map(tool => tool.function?.name)
|
||||
expect(modelRequests[0]?.reasoning_effort).toBe('max')
|
||||
expect(modelRequests[0]?.max_tokens).toBe(1234)
|
||||
expect(toolNames).toEqual(expect.arrayContaining(['web_fetch', 'web_search']))
|
||||
expect(toolNames).toEqual(expect.arrayContaining(['read', 'write', 'edit', 'web_fetch', 'web_search']))
|
||||
expect(toolNames.includes('str_replace_editor')).toBe(editorEnabled)
|
||||
expect(toolNames).not.toContain('list_subagent_models')
|
||||
|
||||
child.stdin.write(`${JSON.stringify({ jsonrpc: '2.0', id: 3, method: 'shutdown' })}\n`)
|
||||
@@ -180,9 +185,13 @@ describe('Python SDK dsh profile keyless smoke', () => {
|
||||
|
||||
it('boots the standalone minimal profile through its generated manifest', async () => {
|
||||
const root = await mkdtemp(join(tmpdir(), 'dsh-python-sdk-minimal-'))
|
||||
const modelRequests: Record<string, unknown>[] = []
|
||||
const modelServer = createServer((request, response) => {
|
||||
request.resume()
|
||||
let body = ''
|
||||
request.setEncoding('utf8')
|
||||
request.on('data', (chunk: string) => { body += chunk })
|
||||
request.on('end', () => {
|
||||
modelRequests.push(JSON.parse(body) as Record<string, unknown>)
|
||||
response.writeHead(200, { 'content-type': 'text/event-stream' })
|
||||
response.write('data: {"choices":[{"delta":{"role":"assistant","content":null}}]}\n\n')
|
||||
response.write('data: {"choices":[{"delta":{"content":"done"}}]}\n\n')
|
||||
@@ -249,6 +258,10 @@ describe('Python SDK dsh profile keyless smoke', () => {
|
||||
bundles: ['@deepseek-ai/dsh-sdk-minimal'],
|
||||
patchReload: 'startup',
|
||||
})
|
||||
const tools = modelRequests[0]?.tools as { function?: { name?: string } }[]
|
||||
expect(tools.map(tool => tool.function?.name).sort()).toEqual(
|
||||
[process.platform === 'win32' ? 'pwsh' : 'bash', 'str_replace_editor'].sort(),
|
||||
)
|
||||
|
||||
child.stdin.write(`${JSON.stringify({ jsonrpc: '2.0', id: 3, method: 'shutdown' })}\n`)
|
||||
await waitForLine(lines, value => value.id === 3, () => stderr)
|
||||
|
||||
@@ -2,5 +2,5 @@
|
||||
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
||||
# after editing either side, bring the other along and re-record with:
|
||||
# pnpm run verify-translation-pairing --write packages/bundle/sdk-app/README.md
|
||||
README.md: c83ff2178ebc3dd059c926270564306af0828b72
|
||||
README.zh.md: 9b25cbfde70f23309b2dc78a237043d0e8101528
|
||||
README.md: c00409984ca627897a54bd68d249a29a7856b91d
|
||||
README.zh.md: 5d5713d8e452c0a1ee550306f62967711c5fcdcc
|
||||
|
||||
@@ -31,6 +31,8 @@ The startup provider binds stdin EOF to the launcher's bounded successful shutdo
|
||||
|
||||
`DSH_MAX_TOKENS_AS_SUCCESS` retains the SDK deployment mapping: unset or JSON `true` reports token-limited subagent completion as accepted, while JSON `false` reports it as an error. Provider/model and workspace cwd arrive through the SDK initialization request; the base profile owns adapters, tools, persistence, policy, settings, and credentials.
|
||||
|
||||
A profile, home, or invocation patch can set `tool-str-replace-editor` to `disabled: false` to enable it explicitly. The standalone `sdk-minimal` profile owns its separate tool selection.
|
||||
|
||||
-----
|
||||
|
||||
<a id="model-experience"></a>
|
||||
@@ -40,7 +42,7 @@ The startup provider binds stdin EOF to the launcher's bounded successful shutdo
|
||||
|
||||
#### What the model sees
|
||||
|
||||
The profile supplies `You are a coding agent powered by the {{model}} model. Your working directory is {{cwd}}.` before the base tool and context contributions. The exact SDK initialization route and session cwd resolve the placeholders.
|
||||
The profile supplies `You are a coding agent powered by the {{model}} model. Your working directory is {{cwd}}.` before the base tool and context contributions. The exact SDK initialization route and session cwd resolve the placeholders. Default file tool schemas include `read`, `write`, and `edit`; they omit `str_replace_editor`.
|
||||
|
||||
#### Token effect
|
||||
|
||||
|
||||
@@ -31,6 +31,8 @@ kind: "package-bundle"
|
||||
|
||||
`DSH_MAX_TOKENS_AS_SUCCESS` 保留 SDK 部署映射:未设置或 JSON `true` 把 token 达限的 subagent 完成报告为已接受,JSON `false` 则报告为错误。模型提供方/模型与工作区 cwd 通过 SDK 初始化请求传入;base profile 拥有适配器、工具、持久化、策略、settings 与 credentials。
|
||||
|
||||
profile、home 或逐次调用 patch 可以把 `tool-str-replace-editor` 设置为 `disabled: false`,显式启用它。独立的 `sdk-minimal` profile 自行决定其工具选择。
|
||||
|
||||
-----
|
||||
|
||||
<a id="model-experience"></a>
|
||||
@@ -40,7 +42,7 @@ kind: "package-bundle"
|
||||
|
||||
#### 模型看到什么
|
||||
|
||||
profile 会在 base 工具与上下文贡献之前提供 `You are a coding agent powered by the {{model}} model. Your working directory is {{cwd}}.`。确切的 SDK 初始化路由与会话 cwd 会解析其中的占位符。
|
||||
profile 会在 base 工具与上下文贡献之前提供 `You are a coding agent powered by the {{model}} model. Your working directory is {{cwd}}.`。确切的 SDK 初始化路由与会话 cwd 会解析其中的占位符。默认文件工具 schema 包含 `read`、`write` 和 `edit`,不包含 `str_replace_editor`。
|
||||
|
||||
#### Token 影响
|
||||
|
||||
|
||||
@@ -8,6 +8,9 @@
|
||||
- id: session-title-llm
|
||||
disabled: true
|
||||
|
||||
- id: tool-str-replace-editor
|
||||
disabled: true
|
||||
|
||||
- insert:
|
||||
- id: sdk-app-startup
|
||||
name: '@deepseek-ai/dsh-sdk-app'
|
||||
|
||||
@@ -357,91 +357,6 @@
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "str_replace_editor",
|
||||
"description": "Custom editing tool for viewing, creating and editing files\n* State is persistent across command calls and discussions with the user\n* If `path` is a file, `view` displays the result of applying `cat -n`. If `path` is a directory, `view` lists non-hidden files and directories up to 2 levels deep\n* The `create` command cannot be used if the specified `path` already exists as a file\n* If a `command` generates a long output, it will be truncated and marked with `<response clipped>`\n* A null placeholder for a parameter unused by the selected command is treated as omitted. Required parameters still need values; omit `str_replace.new_str` rather than setting it to null when deleting a match\n\nNotes for using the `str_replace` command:\n* The `old_str` parameter should match EXACTLY one or more consecutive lines from the original file. Be mindful of whitespaces!\n* If the `old_str` parameter is not unique in the file, the replacement will not be performed. Make sure to include enough context in `old_str` to make it unique\n* The `new_str` parameter should contain the edited lines that should replace the `old_str`",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"command": {
|
||||
"type": "string",
|
||||
"description": "The commands to run. Allowed options are: `view`, `create`, `str_replace`, `insert`.",
|
||||
"enum": [
|
||||
"view",
|
||||
"create",
|
||||
"str_replace",
|
||||
"insert"
|
||||
]
|
||||
},
|
||||
"path": {
|
||||
"type": "string",
|
||||
"description": "Absolute path to file or directory, e.g. `/repo/file.py` or `/repo`."
|
||||
},
|
||||
"file_text": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"description": "Required string parameter of `create` command, with the content of the file to be created. A null placeholder is treated as omitted by commands that do not use this parameter."
|
||||
},
|
||||
"insert_line": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "integer"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"description": "Required integer parameter of `insert` command. The `new_str` will be inserted AFTER the line `insert_line` of `path`. A null placeholder is treated as omitted by commands that do not use this parameter."
|
||||
},
|
||||
"new_str": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"description": "Optional string parameter of `str_replace` command containing the new string (if omitted, no string will be added). Required string parameter of `insert` command containing the string to insert. A null placeholder is accepted only by commands that do not use this parameter."
|
||||
},
|
||||
"old_str": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"description": "Required string parameter of `str_replace` command containing the string in `path` to replace. A null placeholder is treated as omitted by commands that do not use this parameter."
|
||||
},
|
||||
"view_range": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "integer"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"description": "Optional parameter of `view` command when `path` points to a file. If omitted or null, the full file is shown. If provided, the file will be shown in the indicated line number range, e.g. [11, 12] will show lines 11 and 12. Indexing at 1 to start. Setting `[start_line, -1]` shows all lines from `start_line` to the end of the file."
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"command",
|
||||
"path"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "subagent",
|
||||
"description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. Give it a complete, standalone prompt: it does not see this conversation. This call waits for the subagent and returns its result.",
|
||||
|
||||
@@ -2,6 +2,9 @@
|
||||
# editor as model-facing tools, with process-local providers and an explicit
|
||||
# danger-full-access / never-ask policy.
|
||||
|
||||
- id: tool-str-replace-editor
|
||||
disabled: false
|
||||
|
||||
- id: llm-deepseek
|
||||
name: '@deepseek-ai/dsh-llm-deepseek'
|
||||
config:
|
||||
|
||||
@@ -357,91 +357,6 @@
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "str_replace_editor",
|
||||
"description": "Custom editing tool for viewing, creating and editing files\n* State is persistent across command calls and discussions with the user\n* If `path` is a file, `view` displays the result of applying `cat -n`. If `path` is a directory, `view` lists non-hidden files and directories up to 2 levels deep\n* The `create` command cannot be used if the specified `path` already exists as a file\n* If a `command` generates a long output, it will be truncated and marked with `<response clipped>`\n* A null placeholder for a parameter unused by the selected command is treated as omitted. Required parameters still need values; omit `str_replace.new_str` rather than setting it to null when deleting a match\n\nNotes for using the `str_replace` command:\n* The `old_str` parameter should match EXACTLY one or more consecutive lines from the original file. Be mindful of whitespaces!\n* If the `old_str` parameter is not unique in the file, the replacement will not be performed. Make sure to include enough context in `old_str` to make it unique\n* The `new_str` parameter should contain the edited lines that should replace the `old_str`",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"command": {
|
||||
"type": "string",
|
||||
"description": "The commands to run. Allowed options are: `view`, `create`, `str_replace`, `insert`.",
|
||||
"enum": [
|
||||
"view",
|
||||
"create",
|
||||
"str_replace",
|
||||
"insert"
|
||||
]
|
||||
},
|
||||
"path": {
|
||||
"type": "string",
|
||||
"description": "Absolute path to file or directory, e.g. `/repo/file.py` or `/repo`."
|
||||
},
|
||||
"file_text": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"description": "Required string parameter of `create` command, with the content of the file to be created. A null placeholder is treated as omitted by commands that do not use this parameter."
|
||||
},
|
||||
"insert_line": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "integer"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"description": "Required integer parameter of `insert` command. The `new_str` will be inserted AFTER the line `insert_line` of `path`. A null placeholder is treated as omitted by commands that do not use this parameter."
|
||||
},
|
||||
"new_str": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"description": "Optional string parameter of `str_replace` command containing the new string (if omitted, no string will be added). Required string parameter of `insert` command containing the string to insert. A null placeholder is accepted only by commands that do not use this parameter."
|
||||
},
|
||||
"old_str": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"description": "Required string parameter of `str_replace` command containing the string in `path` to replace. A null placeholder is treated as omitted by commands that do not use this parameter."
|
||||
},
|
||||
"view_range": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "integer"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"description": "Optional parameter of `view` command when `path` points to a file. If omitted or null, the full file is shown. If provided, the file will be shown in the indicated line number range, e.g. [11, 12] will show lines 11 and 12. Indexing at 1 to start. Setting `[start_line, -1]` shows all lines from `start_line` to the end of the file."
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"command",
|
||||
"path"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "subagent",
|
||||
"description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. Give it a complete, standalone prompt: it does not see this conversation. This tool runs in the background by default, immediately returns a durable subagent id, and keeps the child conversation available for later turns. When that run settles, the runtime sends the parent a notice containing its outcome and any final assistant message; `send_message` steers the child's nearest step while it is running and starts a turn while it is idle. Set `run_in_background: false` only when your next action depends on receiving the result.",
|
||||
|
||||
@@ -357,91 +357,6 @@
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "str_replace_editor",
|
||||
"description": "Custom editing tool for viewing, creating and editing files\n* State is persistent across command calls and discussions with the user\n* If `path` is a file, `view` displays the result of applying `cat -n`. If `path` is a directory, `view` lists non-hidden files and directories up to 2 levels deep\n* The `create` command cannot be used if the specified `path` already exists as a file\n* If a `command` generates a long output, it will be truncated and marked with `<response clipped>`\n* A null placeholder for a parameter unused by the selected command is treated as omitted. Required parameters still need values; omit `str_replace.new_str` rather than setting it to null when deleting a match\n\nNotes for using the `str_replace` command:\n* The `old_str` parameter should match EXACTLY one or more consecutive lines from the original file. Be mindful of whitespaces!\n* If the `old_str` parameter is not unique in the file, the replacement will not be performed. Make sure to include enough context in `old_str` to make it unique\n* The `new_str` parameter should contain the edited lines that should replace the `old_str`",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"command": {
|
||||
"type": "string",
|
||||
"description": "The commands to run. Allowed options are: `view`, `create`, `str_replace`, `insert`.",
|
||||
"enum": [
|
||||
"view",
|
||||
"create",
|
||||
"str_replace",
|
||||
"insert"
|
||||
]
|
||||
},
|
||||
"path": {
|
||||
"type": "string",
|
||||
"description": "Absolute path to file or directory, e.g. `/repo/file.py` or `/repo`."
|
||||
},
|
||||
"file_text": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"description": "Required string parameter of `create` command, with the content of the file to be created. A null placeholder is treated as omitted by commands that do not use this parameter."
|
||||
},
|
||||
"insert_line": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "integer"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"description": "Required integer parameter of `insert` command. The `new_str` will be inserted AFTER the line `insert_line` of `path`. A null placeholder is treated as omitted by commands that do not use this parameter."
|
||||
},
|
||||
"new_str": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"description": "Optional string parameter of `str_replace` command containing the new string (if omitted, no string will be added). Required string parameter of `insert` command containing the string to insert. A null placeholder is accepted only by commands that do not use this parameter."
|
||||
},
|
||||
"old_str": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"description": "Required string parameter of `str_replace` command containing the string in `path` to replace. A null placeholder is treated as omitted by commands that do not use this parameter."
|
||||
},
|
||||
"view_range": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "integer"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"description": "Optional parameter of `view` command when `path` points to a file. If omitted or null, the full file is shown. If provided, the file will be shown in the indicated line number range, e.g. [11, 12] will show lines 11 and 12. Indexing at 1 to start. Setting `[start_line, -1]` shows all lines from `start_line` to the end of the file."
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"command",
|
||||
"path"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "subagent",
|
||||
"description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. Give it a complete, standalone prompt: it does not see this conversation. This tool runs in the background by default, immediately returns a durable subagent id, and keeps the child conversation available for later turns. When that run settles, the runtime sends the parent a notice containing its outcome and any final assistant message; `send_message` steers the child's nearest step while it is running and starts a turn while it is idle. Set `run_in_background: false` only when your next action depends on receiving the result.",
|
||||
|
||||
@@ -374,91 +374,6 @@
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "str_replace_editor",
|
||||
"description": "Custom editing tool for viewing, creating and editing files\n* State is persistent across command calls and discussions with the user\n* If `path` is a file, `view` displays the result of applying `cat -n`. If `path` is a directory, `view` lists non-hidden files and directories up to 2 levels deep\n* The `create` command cannot be used if the specified `path` already exists as a file\n* If a `command` generates a long output, it will be truncated and marked with `<response clipped>`\n* A null placeholder for a parameter unused by the selected command is treated as omitted. Required parameters still need values; omit `str_replace.new_str` rather than setting it to null when deleting a match\n\nNotes for using the `str_replace` command:\n* The `old_str` parameter should match EXACTLY one or more consecutive lines from the original file. Be mindful of whitespaces!\n* If the `old_str` parameter is not unique in the file, the replacement will not be performed. Make sure to include enough context in `old_str` to make it unique\n* The `new_str` parameter should contain the edited lines that should replace the `old_str`",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"command": {
|
||||
"type": "string",
|
||||
"description": "The commands to run. Allowed options are: `view`, `create`, `str_replace`, `insert`.",
|
||||
"enum": [
|
||||
"view",
|
||||
"create",
|
||||
"str_replace",
|
||||
"insert"
|
||||
]
|
||||
},
|
||||
"path": {
|
||||
"type": "string",
|
||||
"description": "Absolute path to file or directory, e.g. `/repo/file.py` or `/repo`."
|
||||
},
|
||||
"file_text": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"description": "Required string parameter of `create` command, with the content of the file to be created. A null placeholder is treated as omitted by commands that do not use this parameter."
|
||||
},
|
||||
"insert_line": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "integer"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"description": "Required integer parameter of `insert` command. The `new_str` will be inserted AFTER the line `insert_line` of `path`. A null placeholder is treated as omitted by commands that do not use this parameter."
|
||||
},
|
||||
"new_str": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"description": "Optional string parameter of `str_replace` command containing the new string (if omitted, no string will be added). Required string parameter of `insert` command containing the string to insert. A null placeholder is accepted only by commands that do not use this parameter."
|
||||
},
|
||||
"old_str": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"description": "Required string parameter of `str_replace` command containing the string in `path` to replace. A null placeholder is treated as omitted by commands that do not use this parameter."
|
||||
},
|
||||
"view_range": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "integer"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"description": "Optional parameter of `view` command when `path` points to a file. If omitted or null, the full file is shown. If provided, the file will be shown in the indicated line number range, e.g. [11, 12] will show lines 11 and 12. Indexing at 1 to start. Setting `[start_line, -1]` shows all lines from `start_line` to the end of the file."
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"command",
|
||||
"path"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "subagent",
|
||||
"description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. Give it a complete, standalone prompt: it does not see this conversation. This call waits for the subagent and returns its result. Child LLM selection is optional. Omit `provider`, `model`, and `reasoning_effort` to use configured child defaults and this provider's route defaults. Supply `provider` and `model` together after using `list_subagent_models` to inspect advertised routes and efforts. Changing the effective route without naming an effort uses the selected model's default effort.",
|
||||
|
||||
@@ -357,91 +357,6 @@
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "str_replace_editor",
|
||||
"description": "Custom editing tool for viewing, creating and editing files\n* State is persistent across command calls and discussions with the user\n* If `path` is a file, `view` displays the result of applying `cat -n`. If `path` is a directory, `view` lists non-hidden files and directories up to 2 levels deep\n* The `create` command cannot be used if the specified `path` already exists as a file\n* If a `command` generates a long output, it will be truncated and marked with `<response clipped>`\n* A null placeholder for a parameter unused by the selected command is treated as omitted. Required parameters still need values; omit `str_replace.new_str` rather than setting it to null when deleting a match\n\nNotes for using the `str_replace` command:\n* The `old_str` parameter should match EXACTLY one or more consecutive lines from the original file. Be mindful of whitespaces!\n* If the `old_str` parameter is not unique in the file, the replacement will not be performed. Make sure to include enough context in `old_str` to make it unique\n* The `new_str` parameter should contain the edited lines that should replace the `old_str`",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"command": {
|
||||
"type": "string",
|
||||
"description": "The commands to run. Allowed options are: `view`, `create`, `str_replace`, `insert`.",
|
||||
"enum": [
|
||||
"view",
|
||||
"create",
|
||||
"str_replace",
|
||||
"insert"
|
||||
]
|
||||
},
|
||||
"path": {
|
||||
"type": "string",
|
||||
"description": "Absolute path to file or directory, e.g. `/repo/file.py` or `/repo`."
|
||||
},
|
||||
"file_text": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"description": "Required string parameter of `create` command, with the content of the file to be created. A null placeholder is treated as omitted by commands that do not use this parameter."
|
||||
},
|
||||
"insert_line": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "integer"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"description": "Required integer parameter of `insert` command. The `new_str` will be inserted AFTER the line `insert_line` of `path`. A null placeholder is treated as omitted by commands that do not use this parameter."
|
||||
},
|
||||
"new_str": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"description": "Optional string parameter of `str_replace` command containing the new string (if omitted, no string will be added). Required string parameter of `insert` command containing the string to insert. A null placeholder is accepted only by commands that do not use this parameter."
|
||||
},
|
||||
"old_str": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"description": "Required string parameter of `str_replace` command containing the string in `path` to replace. A null placeholder is treated as omitted by commands that do not use this parameter."
|
||||
},
|
||||
"view_range": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "integer"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"description": "Optional parameter of `view` command when `path` points to a file. If omitted or null, the full file is shown. If provided, the file will be shown in the indicated line number range, e.g. [11, 12] will show lines 11 and 12. Indexing at 1 to start. Setting `[start_line, -1]` shows all lines from `start_line` to the end of the file."
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"command",
|
||||
"path"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "subagent",
|
||||
"description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. Give it a complete, standalone prompt: it does not see this conversation. This call waits for the subagent and returns its result.",
|
||||
|
||||
@@ -2,6 +2,10 @@
|
||||
# The shipped profile owns application startup; this patch fixes only the
|
||||
# deterministic test composition and raw persistence needed for recording.
|
||||
|
||||
# Shared recordings keep their editor across headless and SDK profile defaults.
|
||||
- id: tool-str-replace-editor
|
||||
disabled: false
|
||||
|
||||
- id: llm-deepseek
|
||||
name: '@deepseek-ai/dsh-llm-deepseek'
|
||||
config:
|
||||
|
||||
Reference in New Issue
Block a user