fix(plugins): narrow optional bundles and create fresh session agents
This commit is contained in:
1 parent
fbb95c0f16
commit
55dfd3bab1
59 files changed
+208
-748
No files matched your search
@@ -103,9 +103,7 @@
|
|||||||
"@deepseek-ai/dsh-experimental-ralph-bundle": "workspace:*",
|
"@deepseek-ai/dsh-experimental-ralph-bundle": "workspace:*",
|
||||||
"@deepseek-ai/dsh-experimental-session-titles-bundle": "workspace:*",
|
"@deepseek-ai/dsh-experimental-session-titles-bundle": "workspace:*",
|
||||||
"@deepseek-ai/dsh-experimental-terminal-bundle": "workspace:*",
|
"@deepseek-ai/dsh-experimental-terminal-bundle": "workspace:*",
|
||||||
"@deepseek-ai/dsh-session-search": "workspace:*",
|
"@deepseek-ai/dsh-experimental-session-search": "workspace:*",
|
||||||
"@deepseek-ai/dsh-string-editor": "workspace:*",
|
|
||||||
"@deepseek-ai/dsh-tmux-location": "workspace:*",
|
|
||||||
"@deepseek-ai/dsh-experimental-tool-worktree": "workspace:*"
|
"@deepseek-ai/dsh-experimental-tool-worktree": "workspace:*"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|||||||
@@ -25,9 +25,7 @@ import { textResponse, toolCallResponse } from '../../../packages/core/agent-loo
|
|||||||
const root = fileURLToPath(new URL('../../..', import.meta.url))
|
const root = fileURLToPath(new URL('../../..', import.meta.url))
|
||||||
const installAnchor = join(root, 'apps/cli/package.json')
|
const installAnchor = join(root, 'apps/cli/package.json')
|
||||||
const bundles = {
|
const bundles = {
|
||||||
search: '@deepseek-ai/dsh-session-search',
|
search: '@deepseek-ai/dsh-experimental-session-search',
|
||||||
editor: '@deepseek-ai/dsh-string-editor',
|
|
||||||
tmux: '@deepseek-ai/dsh-tmux-location',
|
|
||||||
ralph: '@deepseek-ai/dsh-experimental-ralph-bundle',
|
ralph: '@deepseek-ai/dsh-experimental-ralph-bundle',
|
||||||
terminal: '@deepseek-ai/dsh-experimental-terminal-bundle',
|
terminal: '@deepseek-ai/dsh-experimental-terminal-bundle',
|
||||||
badge: '@deepseek-ai/dsh-experimental-badge-skill-bundle',
|
badge: '@deepseek-ai/dsh-experimental-badge-skill-bundle',
|
||||||
@@ -165,7 +163,6 @@ describe.skipIf(!existsSync(join(root, 'apps/cli/lib/bin.js')))('Official option
|
|||||||
}
|
}
|
||||||
|
|
||||||
const names = (owner?: Agent) => ctx.tools.schemas(owner).map(tool => tool.name).sort()
|
const names = (owner?: Agent) => ctx.tools.schemas(owner).map(tool => tool.name).sort()
|
||||||
const transcript = (owner: Agent) => JSON.stringify(owner.session.deriveMessages())
|
|
||||||
const toolResult = (owner: Agent, callId: string) => owner.session.deriveMessages()
|
const toolResult = (owner: Agent, callId: string) => owner.session.deriveMessages()
|
||||||
.flatMap(message => message.role === 'tool' && message.toolCallId === callId ? message.content : [])
|
.flatMap(message => message.role === 'tool' && message.toolCallId === callId ? message.content : [])
|
||||||
.flatMap(block => block.type === 'text' ? [block.text] : []).join('\n')
|
.flatMap(block => block.type === 'text' ? [block.text] : []).join('\n')
|
||||||
@@ -179,53 +176,25 @@ describe.skipIf(!existsSync(join(root, 'apps/cli/lib/bin.js')))('Official option
|
|||||||
expect((await ctx.skills.list({ cwd: workspace, scope: standard.agent })).some(skill => skill.name === 'dsh-badge')).toBe(false)
|
expect((await ctx.skills.list({ cwd: workspace, scope: standard.agent })).some(skill => skill.name === 'dsh-badge')).toBe(false)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('preserves existing Agent generations across editor off/on/off and resumes with the current preset', async () => {
|
it('generates and executes the PTC SDK for the selected search bundle', async () => {
|
||||||
const old = await agent()
|
await select(bundles.search, true)
|
||||||
await select(bundles.editor, true)
|
|
||||||
const enabled = await agent()
|
|
||||||
expect(names(old.agent)).not.toContain('str_replace_editor')
|
|
||||||
const first = join(workspace, 'editor-enabled.txt')
|
|
||||||
await turn(enabled.agent, 'Create the requested file with the string editor.', [
|
|
||||||
toolCallResponse('editor-on', 'str_replace_editor', { command: 'create', path: first, file_text: 'EDITOR_ENABLED' }), textResponse('EDITOR_DONE'),
|
|
||||||
])
|
|
||||||
expect(await readFile(first, 'utf8')).toBe('EDITOR_ENABLED')
|
|
||||||
expect(transcript(enabled.agent)).toContain('EDITOR_DONE')
|
|
||||||
await select(bundles.editor, false)
|
|
||||||
const after = await agent()
|
|
||||||
expect(names(after.agent)).not.toContain('str_replace_editor')
|
|
||||||
const retained = join(workspace, 'editor-retained.txt')
|
|
||||||
await turn(enabled.agent, 'Use the retained editor to create the second file.', [
|
|
||||||
toolCallResponse('editor-retained', 'str_replace_editor', { command: 'create', path: retained, file_text: 'RETAINED_EDITOR' }), textResponse('RETAINED_DONE'),
|
|
||||||
])
|
|
||||||
expect(await readFile(retained, 'utf8')).toBe('RETAINED_EDITOR')
|
|
||||||
const sessionId = enabled.agent.session.id
|
|
||||||
await enabled.dispose()
|
|
||||||
handles.delete(enabled)
|
|
||||||
const resumed = await ctx.agents.resume({ resumeSessionId: sessionId, setup: scoped => ctx.agentPresets.mount(scoped, 'standard').then(() => undefined) })
|
|
||||||
handles.add(resumed)
|
|
||||||
expect(names(resumed.agent)).not.toContain('str_replace_editor')
|
|
||||||
})
|
|
||||||
|
|
||||||
it('generates and executes the PTC SDK for a selected editor bundle', async () => {
|
|
||||||
await select(bundles.editor, true)
|
|
||||||
const coded = await agent('ptc')
|
const coded = await agent('ptc')
|
||||||
const native = await agent('cordis')
|
const native = await agent('cordis')
|
||||||
const minimal = await agent('minimal')
|
const minimal = await agent('minimal')
|
||||||
const target = join(workspace, 'ptc-editor.txt')
|
|
||||||
const assembly = await ctx.systemPrompt.assemble({ scope: coded.agent })
|
const assembly = await ctx.systemPrompt.assemble({ scope: coded.agent })
|
||||||
expect(assembly.tools.map(tool => tool.name)).toEqual(['run_code'])
|
expect(assembly.tools.map(tool => tool.name)).toEqual(['run_code'])
|
||||||
expect(assembly.sections.find(section => section.name === 'tools:sdk')?.text).toContain('str_replace_editor')
|
expect(assembly.sections.find(section => section.name === 'tools:sdk')?.text).toContain('session_trace')
|
||||||
expect(names(native.agent)).toContain('str_replace_editor')
|
expect(names(native.agent)).toContain('session_search')
|
||||||
expect(names(minimal.agent)).toEqual([process.platform === 'win32' ? 'pwsh' : 'bash', 'working_directory'])
|
expect(names(minimal.agent)).toEqual([process.platform === 'win32' ? 'pwsh' : 'bash', 'working_directory'])
|
||||||
await turn(coded.agent, 'Create the file with the editor through run_code.', [
|
await turn(coded.agent, 'Read this session lineage through run_code.', [
|
||||||
toolCallResponse('ptc-editor', 'run_code', {
|
toolCallResponse('ptc-search', 'run_code', {
|
||||||
code: `console.log(await tools.str_replace_editor(${JSON.stringify({ command: 'create', path: target, file_text: 'PTC_EDITOR_OK' })}));`,
|
code: 'console.log(await tools.session_trace({}));',
|
||||||
description: 'Create the optional editor file',
|
description: 'Read the current session lineage',
|
||||||
}), textResponse('PTC_EDITOR_DONE'),
|
}), textResponse('PTC_SEARCH_DONE'),
|
||||||
])
|
])
|
||||||
expect(await readFile(target, 'utf8')).toBe('PTC_EDITOR_OK')
|
expect(toolResult(coded.agent, 'ptc-search')).toContain(coded.agent.session.id)
|
||||||
expect(coded.agent.session.snapshotEvents().some(event => event.type === 'tool/ptc-dispatch' && event.data.name === 'str_replace_editor')).toBe(true)
|
expect(coded.agent.session.snapshotEvents().some(event => event.type === 'tool/ptc-dispatch' && event.data.name === 'session_trace')).toBe(true)
|
||||||
await select(bundles.editor, false)
|
await select(bundles.search, false)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('searches persisted conversation content only through the selected search bundle', async () => {
|
it('searches persisted conversation content only through the selected search bundle', async () => {
|
||||||
@@ -241,6 +210,7 @@ describe.skipIf(!existsSync(join(root, 'apps/cli/lib/bin.js')))('Official option
|
|||||||
const foreign = await agent('standard', otherWorkspace)
|
const foreign = await agent('standard', otherWorkspace)
|
||||||
await turn(foreign.agent, 'Keep OPTIONAL_SEARCH_MARKER in the other workspace.', [textResponse('Other marker recorded.')])
|
await turn(foreign.agent, 'Keep OPTIONAL_SEARCH_MARKER in the other workspace.', [textResponse('Other marker recorded.')])
|
||||||
await select(bundles.search, true)
|
await select(bundles.search, true)
|
||||||
|
expect(names(live.agent)).not.toContain('session_search')
|
||||||
const searcher = await agent()
|
const searcher = await agent()
|
||||||
await turn(searcher.agent, 'Find the previous marker in session history.', [
|
await turn(searcher.agent, 'Find the previous marker in session history.', [
|
||||||
toolCallResponse('search-history', 'session_search', { query: 'OPTIONAL_SEARCH_MARKER' }), textResponse('SEARCH_DONE'),
|
toolCallResponse('search-history', 'session_search', { query: 'OPTIONAL_SEARCH_MARKER' }), textResponse('SEARCH_DONE'),
|
||||||
@@ -255,6 +225,12 @@ describe.skipIf(!existsSync(join(root, 'apps/cli/lib/bin.js')))('Official option
|
|||||||
toolCallResponse('search-retained', 'session_search', { query: 'OPTIONAL_SEARCH_MARKER' }), textResponse('RETAINED_SEARCH_DONE'),
|
toolCallResponse('search-retained', 'session_search', { query: 'OPTIONAL_SEARCH_MARKER' }), textResponse('RETAINED_SEARCH_DONE'),
|
||||||
])
|
])
|
||||||
expect(toolResult(searcher.agent, 'search-retained')).toContain(seedId)
|
expect(toolResult(searcher.agent, 'search-retained')).toContain(seedId)
|
||||||
|
const sessionId = searcher.agent.session.id
|
||||||
|
await searcher.dispose()
|
||||||
|
handles.delete(searcher)
|
||||||
|
const reopened = await ctx.agents.resume({ resumeSessionId: sessionId, setup: scoped => ctx.agentPresets.mount(scoped, 'standard').then(() => undefined) })
|
||||||
|
handles.add(reopened)
|
||||||
|
expect(names(reopened.agent)).not.toContain('session_search')
|
||||||
})
|
})
|
||||||
|
|
||||||
it('loads the actual badge asset only while its bundle is selected', async () => {
|
it('loads the actual badge asset only while its bundle is selected', async () => {
|
||||||
@@ -322,18 +298,6 @@ describe.skipIf(!existsSync(join(root, 'apps/cli/lib/bin.js')))('Official option
|
|||||||
expect(names((await agent()).agent)).not.toContain('ralph')
|
expect(names((await agent()).agent)).not.toContain('ralph')
|
||||||
})
|
})
|
||||||
|
|
||||||
it('runs the selected tmux context plugin without inventing a location outside tmux', async () => {
|
|
||||||
await select(bundles.tmux, true)
|
|
||||||
expect((await ctx.agentPresets.readDocument('standard')).content).toContain('@deepseek-ai/dsh-tmux-context')
|
|
||||||
expect((await ctx.agentPresets.readDocument('minimal')).content).not.toContain('@deepseek-ai/dsh-tmux-context')
|
|
||||||
const owner = await agent()
|
|
||||||
await turn(owner.agent, 'Reply from this ordinary GUI process.', [textResponse('TMUX_UNAVAILABLE')])
|
|
||||||
expect(owner.agent.session.snapshotEvents().some(event => event.type === 'user/message' && event.data.source.kind === 'tmux-context')).toBe(false)
|
|
||||||
expect(transcript(owner.agent)).toContain('TMUX_UNAVAILABLE')
|
|
||||||
await select(bundles.tmux, false)
|
|
||||||
expect((await ctx.agentPresets.readDocument('standard')).content).not.toContain('@deepseek-ai/dsh-tmux-context')
|
|
||||||
})
|
|
||||||
|
|
||||||
it('switches title cadence off/on/off through the live manager', async () => {
|
it('switches title cadence off/on/off through the live manager', async () => {
|
||||||
const titleRequests = (owner: Agent) => owner.session.snapshotEvents().filter(event => event.type === 'session/title-llm-request')
|
const titleRequests = (owner: Agent) => owner.session.snapshotEvents().filter(event => event.type === 'session/title-llm-request')
|
||||||
const first = await agent()
|
const first = await agent()
|
||||||
@@ -359,28 +323,27 @@ describe.skipIf(!existsSync(join(root, 'apps/cli/lib/bin.js')))('Official option
|
|||||||
expect(titleRequests(restored.agent)[0]?.data.titleProvider).toBe('session-title-first-prompt-llm')
|
expect(titleRequests(restored.agent)[0]?.data.titleProvider).toBe('session-title-first-prompt-llm')
|
||||||
})
|
})
|
||||||
|
|
||||||
it('composes all seven bundles while leaving minimal and host tools unchanged', async () => {
|
it('composes all five bundles while leaving minimal and host tools unchanged', async () => {
|
||||||
for (const name of Object.values(bundles)) await select(name, true)
|
for (const name of Object.values(bundles)) await select(name, true)
|
||||||
let coded: Agent | undefined
|
let coded: Agent | undefined
|
||||||
for (const preset of ['standard', 'cordis', 'ptc']) {
|
for (const preset of ['standard', 'cordis', 'ptc']) {
|
||||||
const owner = await agent(preset)
|
const owner = await agent(preset)
|
||||||
expect(names(owner.agent)).toEqual(expect.arrayContaining(['str_replace_editor', 'session_search', 'terminal_open', 'ralph']))
|
expect(names(owner.agent)).toEqual(expect.arrayContaining(['session_search', 'terminal_open', 'ralph']))
|
||||||
if (preset === 'ptc') coded = owner.agent
|
if (preset === 'ptc') coded = owner.agent
|
||||||
}
|
}
|
||||||
if (coded === undefined) throw new Error('the PTC Agent was not created')
|
if (coded === undefined) throw new Error('the PTC Agent was not created')
|
||||||
const target = join(workspace, 'combined-bundles.txt')
|
await turn(coded, 'Read this session lineage and load the badge through one program.', [
|
||||||
await turn(coded, 'Create the file and load the badge through one program.', [
|
|
||||||
toolCallResponse('combined-program', 'run_code', {
|
toolCallResponse('combined-program', 'run_code', {
|
||||||
code: `await tools.str_replace_editor(${JSON.stringify({ command: 'create', path: target, file_text: 'COMBINED_BUNDLES_OK' })}); console.log(await tools.skill({ name: 'dsh-badge' }));`,
|
code: 'console.log(await tools.session_trace({})); console.log(await tools.skill({ name: "dsh-badge" }));',
|
||||||
description: 'Use the optional editor and badge together',
|
description: 'Use optional session search and badge together',
|
||||||
}), textResponse('COMBINED_DONE'),
|
}), textResponse('COMBINED_DONE'),
|
||||||
])
|
])
|
||||||
expect(await readFile(target, 'utf8')).toBe('COMBINED_BUNDLES_OK')
|
expect(toolResult(coded, 'combined-program')).toContain(coded.session.id)
|
||||||
expect(toolResult(coded, 'combined-program')).toContain('dsh-badge')
|
expect(toolResult(coded, 'combined-program')).toContain('dsh-badge')
|
||||||
const minimal = await agent('minimal')
|
const minimal = await agent('minimal')
|
||||||
expect(names(minimal.agent)).toEqual([process.platform === 'win32' ? 'pwsh' : 'bash', 'working_directory'])
|
expect(names(minimal.agent)).toEqual([process.platform === 'win32' ? 'pwsh' : 'bash', 'working_directory'])
|
||||||
expect(names()).toEqual(['working_directory'])
|
expect(names()).toEqual(['working_directory'])
|
||||||
for (const name of [...Object.values(bundles)].reverse()) await select(name, false)
|
for (const name of [...Object.values(bundles)].reverse()) await select(name, false)
|
||||||
expect(names((await agent()).agent)).not.toContain('str_replace_editor')
|
expect(names((await agent()).agent)).not.toContain('session_search')
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
+10
-16
@@ -1,11 +1,10 @@
|
|||||||
/** An optional bundle reaches the generated PTC SDK through real profile selection and a persisted Session. */
|
/** A standalone tool in a custom scoped patch reaches the PTC SDK and a persisted Session. */
|
||||||
import { readFile } from 'node:fs/promises'
|
import { readFile } from 'node:fs/promises'
|
||||||
import { join } from 'node:path'
|
import { join } from 'node:path'
|
||||||
import { fileURLToPath } from 'node:url'
|
import { fileURLToPath } from 'node:url'
|
||||||
import { chromium, type Browser, type Page } from 'playwright'
|
import { chromium, type Browser, type Page } from 'playwright'
|
||||||
import { afterAll, beforeAll, describe, expect, it, onTestFailed } from 'vitest'
|
import { afterAll, beforeAll, describe, expect, it, onTestFailed } from 'vitest'
|
||||||
import type {} from '@deepseek-ai/dsh-tools'
|
import type {} from '@deepseek-ai/dsh-tools'
|
||||||
import type {} from '@deepseek-ai/dsh-plugin-manager'
|
|
||||||
import {
|
import {
|
||||||
assertFinalWorkspaceSnapshot, assertFixtureInventory, captureExpandedTurnProcessAria, compareOrRefreshGolden,
|
assertFinalWorkspaceSnapshot, assertFixtureInventory, captureExpandedTurnProcessAria, compareOrRefreshGolden,
|
||||||
fixtureUserPrompts, launchWebScaffold, recordFixture, selectedSessionFixture, watchConsole, webSnapshotMode, type WebScaffold,
|
fixtureUserPrompts, launchWebScaffold, recordFixture, selectedSessionFixture, watchConsole, webSnapshotMode, type WebScaffold,
|
||||||
@@ -14,10 +13,9 @@ import { connectFreshWorkspace, newEnglishPage, saveFailureShot } from './suppor
|
|||||||
|
|
||||||
const DIR = fileURLToPath(new URL('../../../snapshots/web/optional-string-editor', import.meta.url))
|
const DIR = fileURLToPath(new URL('../../../snapshots/web/optional-string-editor', import.meta.url))
|
||||||
const FIXTURE = join(DIR, 'session.v4.jsonl')
|
const FIXTURE = join(DIR, 'session.v4.jsonl')
|
||||||
const BUNDLE = '@deepseek-ai/dsh-string-editor'
|
|
||||||
const MODE = webSnapshotMode()
|
const MODE = webSnapshotMode()
|
||||||
|
|
||||||
describe('web snapshot: optional string editor through PTC', () => {
|
describe('web snapshot: standalone string editor through PTC', () => {
|
||||||
let scaffold: WebScaffold
|
let scaffold: WebScaffold
|
||||||
let browser: Browser
|
let browser: Browser
|
||||||
let page: Page
|
let page: Page
|
||||||
@@ -26,20 +24,16 @@ describe('web snapshot: optional string editor through PTC', () => {
|
|||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
scaffold = await launchWebScaffold({
|
scaffold = await launchWebScaffold({
|
||||||
developerTools: true,
|
developerTools: true,
|
||||||
extraOverlayPath: fileURLToPath(new URL('./pin-browse-picker.overlay.yml', import.meta.url)),
|
extraOverlayPath: [
|
||||||
|
fileURLToPath(new URL('./pin-browse-picker.overlay.yml', import.meta.url)),
|
||||||
|
fileURLToPath(new URL('./standalone-string-editor.overlay.yml', import.meta.url)),
|
||||||
|
],
|
||||||
profile: { packages: [] },
|
profile: { packages: [] },
|
||||||
compareReplaySession: true,
|
compareReplaySession: true,
|
||||||
...(MODE === 'record' ? {} : { replayFixture: FIXTURE }),
|
...(MODE === 'record' ? {} : { replayFixture: FIXTURE }),
|
||||||
})
|
})
|
||||||
expect((await scaffold.ctx.pluginManager.listBundles()).find(bundle => bundle.name === BUNDLE))
|
|
||||||
.toMatchObject({ enabled: false, optional: true })
|
|
||||||
expect((await scaffold.ctx.agentPresets.compositionInventory()).find(preset => preset.id === 'ptc')?.rows
|
expect((await scaffold.ctx.agentPresets.compositionInventory()).find(preset => preset.id === 'ptc')?.rows
|
||||||
.some(row => row.moduleName === '@deepseek-ai/dsh-tool-str-replace-editor')).toBe(false)
|
.some(row => row.moduleName === '@deepseek-ai/dsh-tool-str-replace-editor')).toBe(true)
|
||||||
expect(await scaffold.ctx.pluginManager.setBundleEnabled(BUNDLE, true))
|
|
||||||
.toMatchObject({ application: 'applied', changed: true })
|
|
||||||
const active = (await scaffold.ctx.pluginManager.listBundles()).find(bundle => bundle.name === BUNDLE)
|
|
||||||
expect(active?.rows.find(row => row.preset === 'preset-ptc'))
|
|
||||||
.toMatchObject({ composition: { enabled: true, fiberPhase: 'active' } })
|
|
||||||
browser = await chromium.launch()
|
browser = await chromium.launch()
|
||||||
page = await newEnglishPage(browser)
|
page = await newEnglishPage(browser)
|
||||||
tripwire = watchConsole(page)
|
tripwire = watchConsole(page)
|
||||||
@@ -55,7 +49,7 @@ describe('web snapshot: optional string editor through PTC', () => {
|
|||||||
try { await browser?.close() } finally { await scaffold?.close() }
|
try { await browser?.close() } finally { await scaffold?.close() }
|
||||||
})
|
})
|
||||||
|
|
||||||
it('executes the newly selected SDK tool, persists its subcall, and verifies the created file', async () => {
|
it('executes the explicitly composed SDK tool, persists its subcall, and verifies the created file', async () => {
|
||||||
onTestFailed(() => saveFailureShot(page, 'optional-string-editor'))
|
onTestFailed(() => saveFailureShot(page, 'optional-string-editor'))
|
||||||
const prompts = fixtureUserPrompts(await readFile(await selectedSessionFixture(FIXTURE), 'utf8'))
|
const prompts = fixtureUserPrompts(await readFile(await selectedSessionFixture(FIXTURE), 'utf8'))
|
||||||
expect(prompts).toHaveLength(1)
|
expect(prompts).toHaveLength(1)
|
||||||
@@ -65,7 +59,7 @@ describe('web snapshot: optional string editor through PTC', () => {
|
|||||||
await input.press('Enter')
|
await input.press('Enter')
|
||||||
const sessionId = await settled
|
const sessionId = await settled
|
||||||
const agent = scaffold.ctx.agents.get(sessionId)
|
const agent = scaffold.ctx.agents.get(sessionId)
|
||||||
if (agent === undefined) throw new Error('Optional editor Session has no live Agent')
|
if (agent === undefined) throw new Error('Standalone editor Session has no live Agent')
|
||||||
expect(scaffold.ctx.agentPresets.composedPreset(agent.ctx)).toBe('ptc')
|
expect(scaffold.ctx.agentPresets.composedPreset(agent.ctx)).toBe('ptc')
|
||||||
expect(agent.session.requestHeader()?.tools?.map(tool => tool.name)).toEqual(['run_code'])
|
expect(agent.session.requestHeader()?.tools?.map(tool => tool.name)).toEqual(['run_code'])
|
||||||
const system = agent.session.deriveMessages().filter(message => message.role === 'system')
|
const system = agent.session.deriveMessages().filter(message => message.role === 'system')
|
||||||
@@ -76,7 +70,7 @@ describe('web snapshot: optional string editor through PTC', () => {
|
|||||||
expect(events.filter(event => event.type === 'tool/ptc-dispatch').map(event => event.data))
|
expect(events.filter(event => event.type === 'tool/ptc-dispatch').map(event => event.data))
|
||||||
.toMatchObject([{ name: 'str_replace_editor', arguments: { command: 'create' }, isError: false }])
|
.toMatchObject([{ name: 'str_replace_editor', arguments: { command: 'create' }, isError: false }])
|
||||||
const cwd = agent.session.header.cwd
|
const cwd = agent.session.header.cwd
|
||||||
if (cwd === undefined) throw new Error('Optional editor Session has no working directory')
|
if (cwd === undefined) throw new Error('Standalone editor Session has no working directory')
|
||||||
expect(await readFile(join(cwd, 'edited.txt'), 'utf8')).toBe('PTC_EDITOR_OK\n')
|
expect(await readFile(join(cwd, 'edited.txt'), 'utf8')).toBe('PTC_EDITOR_OK\n')
|
||||||
await assertFinalWorkspaceSnapshot(DIR, cwd)
|
await assertFinalWorkspaceSnapshot(DIR, cwd)
|
||||||
await expect.poll(() => page.getByText('DONE', { exact: true }).count()).toBeGreaterThanOrEqual(1)
|
await expect.poll(() => page.getByText('DONE', { exact: true }).count()).toBeGreaterThanOrEqual(1)
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
- preset: preset-ptc
|
||||||
|
insert:
|
||||||
|
- id: optional-tool-str-replace-editor
|
||||||
|
name: '@deepseek-ai/dsh-tool-str-replace-editor'
|
||||||
@@ -53,7 +53,7 @@
|
|||||||
"tests/question-composer.e2e.ts",
|
"tests/question-composer.e2e.ts",
|
||||||
"tests/approval-composer.e2e.ts",
|
"tests/approval-composer.e2e.ts",
|
||||||
"tests/ptc-escalation.e2e.ts",
|
"tests/ptc-escalation.e2e.ts",
|
||||||
"tests/optional-string-editor.e2e.ts",
|
"tests/standalone-string-editor.e2e.ts",
|
||||||
"tests/plan-control-row.e2e.ts",
|
"tests/plan-control-row.e2e.ts",
|
||||||
"tests/plan-review.e2e.ts",
|
"tests/plan-review.e2e.ts",
|
||||||
"tests/steering.e2e.ts",
|
"tests/steering.e2e.ts",
|
||||||
|
|||||||
@@ -0,0 +1,16 @@
|
|||||||
|
# Bilingual-pair consistency record for guide.md (docs/i18n/README.md): per heading
|
||||||
|
# section, a hash of its English and Chinese blocks outside code blocks and generated regions.
|
||||||
|
# After editing either side, bring the other along and re-record with:
|
||||||
|
# pnpm run verify-translation-pairing --write docs/upgrade-guide/v0.2.1-alpha.1/new-session-generations/guide.md
|
||||||
|
/:
|
||||||
|
en: ad37e45180bc096f
|
||||||
|
zh: e44c85b10b1d9d4b
|
||||||
|
/start-a-fresh-agent-with-new-session:
|
||||||
|
en: 5e4b26181326018f
|
||||||
|
zh: 99bc75dcd12bf647
|
||||||
|
/start-a-fresh-agent-with-new-session/change:
|
||||||
|
en: ab12aadb31d0d3e8
|
||||||
|
zh: 637b446aef86456e
|
||||||
|
/start-a-fresh-agent-with-new-session/migration:
|
||||||
|
en: 9565e66b6bcdf269
|
||||||
|
zh: 226e470de85aa8b6
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
---
|
||||||
|
kind: upgrade-guide
|
||||||
|
description: "New Session creates a fresh Agent instead of reusing an existing empty Session."
|
||||||
|
---
|
||||||
|
|
||||||
|
# Start a fresh Agent with New Session
|
||||||
|
|
||||||
|
English | [中文](guide.zh.md)
|
||||||
|
|
||||||
|
## Change
|
||||||
|
|
||||||
|
In Web and Desktop, New Session creates a fresh Session and Agent using the current preset definition. It previously reused an existing empty Session in the workspace, which could retain tools from before an optional bundle changed.
|
||||||
|
|
||||||
|
Client calls to `uiWorkspace.startSession(workspaceId)` follow the same behavior. Workspace reconnection through `openWorkspace` or `connectWorkspace` still reuses an eligible blank. Calls with draft-preparation options preserve their existing reuse and content rules. Existing Agents retain their composition.
|
||||||
|
|
||||||
|
## Migration
|
||||||
|
|
||||||
|
1. After changing optional bundles, use New Session to obtain the current tool composition. Continue in an existing Session when its retained composition is intentional.
|
||||||
|
2. Client integrations that reconnect a workspace should use `openWorkspace` or `connectWorkspace`. Keep explicit draft-preparation options when preparing an existing draft.
|
||||||
|
3. Confirm that the new Agent has the selected tools; no persisted Session files or profile patches need rewriting.
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
---
|
||||||
|
kind: upgrade-guide
|
||||||
|
description: "新会话会创建新的 Agent,不再复用已有空 Session。"
|
||||||
|
---
|
||||||
|
|
||||||
|
# 通过新会话创建新的 Agent
|
||||||
|
|
||||||
|
[English](guide.md) | 中文
|
||||||
|
|
||||||
|
## 变更
|
||||||
|
|
||||||
|
在 Web 和 Desktop 中,新会话按当前预设定义创建新的 Session 和 Agent。此前该操作会复用工作区内已有的空 Session,因而可能保留可选组合包变更前的工具。
|
||||||
|
|
||||||
|
客户端调用 `uiWorkspace.startSession(workspaceId)` 采用相同行为。通过 `openWorkspace` 或 `connectWorkspace` 重连工作区时仍复用符合条件的空 Session。带草稿准备选项的调用保留已有复用与内容规则。已有 Agent 保留其组合。
|
||||||
|
|
||||||
|
## 迁移
|
||||||
|
|
||||||
|
1. 更改可选组合包后,通过新会话取得当前工具组合。需要保留原组合时,继续使用已有 Session。
|
||||||
|
2. 重连工作区的客户端集成应使用 `openWorkspace` 或 `connectWorkspace`。准备已有草稿时保留显式草稿准备选项。
|
||||||
|
3. 确认新 Agent 拥有已选择的工具;无需重写持久化 Session 文件或 profile patch。
|
||||||
@@ -40,7 +40,7 @@ export interface SessionSummary {
|
|||||||
/**
|
/**
|
||||||
* New Session presentation and reuse eligibility, derived from the Host
|
* New Session presentation and reuse eligibility, derived from the Host
|
||||||
* summary, `sessionListMetadata`, and client acceptance/running observations.
|
* summary, `sessionListMetadata`, and client acceptance/running observations.
|
||||||
* New Session reuses a blank one targeting the same workspace. Filtering
|
* Workspace reconnection may reuse a blank in the same workspace. Filtering
|
||||||
* stays with the consumer: the store carries every row, while the Workspace
|
* stays with the consumer: the store carries every row, while the Workspace
|
||||||
* browser shows only the selected blank entry.
|
* browser shows only the selected blank entry.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -221,9 +221,7 @@ export const DEFAULT_PROFILE_BUNDLES: readonly string[] = ['@deepseek-ai/dsh-bas
|
|||||||
* [admission](../../../../.agents/notes/implemented/architecture/2026-09-21-experimental-capabilities-as-optional-bundles.md)).
|
* [admission](../../../../.agents/notes/implemented/architecture/2026-09-21-experimental-capabilities-as-optional-bundles.md)).
|
||||||
*/
|
*/
|
||||||
export const OPTIONAL_BUNDLES: readonly string[] = [
|
export const OPTIONAL_BUNDLES: readonly string[] = [
|
||||||
'@deepseek-ai/dsh-session-search',
|
'@deepseek-ai/dsh-experimental-session-search',
|
||||||
'@deepseek-ai/dsh-string-editor',
|
|
||||||
'@deepseek-ai/dsh-tmux-location',
|
|
||||||
'@deepseek-ai/dsh-experimental-ralph-bundle',
|
'@deepseek-ai/dsh-experimental-ralph-bundle',
|
||||||
'@deepseek-ai/dsh-experimental-terminal-bundle',
|
'@deepseek-ai/dsh-experimental-terminal-bundle',
|
||||||
'@deepseek-ai/dsh-experimental-badge-skill-bundle',
|
'@deepseek-ai/dsh-experimental-badge-skill-bundle',
|
||||||
|
|||||||
@@ -15,8 +15,8 @@
|
|||||||
en: 09848f4d056e4fc1
|
en: 09848f4d056e4fc1
|
||||||
zh: 8df6139cff0288f6
|
zh: 8df6139cff0288f6
|
||||||
/bundle-profile-plugin-bundles/packages:
|
/bundle-profile-plugin-bundles/packages:
|
||||||
en: 8313a008ecf37fe7
|
en: 3c0457febc9525d6
|
||||||
zh: 79c631b3ed7963ec
|
zh: a236402f8e9fb212
|
||||||
/bundle-profile-plugin-bundles/related-documentation:
|
/bundle-profile-plugin-bundles/related-documentation:
|
||||||
en: 29a969a46018d862
|
en: 29a969a46018d862
|
||||||
zh: bb0be22dd0273886
|
zh: bb0be22dd0273886
|
||||||
|
|||||||
@@ -22,9 +22,6 @@ This group maps the installable patch layers used by `dsh --profile`. Each packa
|
|||||||
|
|
||||||
| Package | Role | ctx key |
|
| Package | Role | ctx key |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
| [`session-search`](session-search/README.md) | Optional session search in full Web presets | — |
|
|
||||||
| [`string-editor`](string-editor/README.md) | Optional string-replacement editing in full Web presets | — |
|
|
||||||
| [`tmux-location`](tmux-location/README.md) | Optional tmux location context in full Web presets | — |
|
|
||||||
| [`base`](base/README.md) | Shared core for base-backed profiles | — (patch only) |
|
| [`base`](base/README.md) | Shared core for base-backed profiles | — (patch only) |
|
||||||
| [`acp-app`](acp-app/README.md) | Automation-only ACP stdio application over base | mounts the ACP bridge |
|
| [`acp-app`](acp-app/README.md) | Automation-only ACP stdio application over base | mounts the ACP bridge |
|
||||||
| [`web-app`](web-app/README.md) | Browser application layer over base | mounts Web rows |
|
| [`web-app`](web-app/README.md) | Browser application layer over base | mounts Web rows |
|
||||||
|
|||||||
@@ -22,9 +22,6 @@ kind: "package-group"
|
|||||||
|
|
||||||
| 包 | 职责 | ctx key |
|
| 包 | 职责 | ctx key |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
| [`session-search`](session-search/README.zh.md) | 完整 Web 预设的可选会话搜索 | — |
|
|
||||||
| [`string-editor`](string-editor/README.zh.md) | 完整 Web 预设的可选字符串替换编辑 | — |
|
|
||||||
| [`tmux-location`](tmux-location/README.zh.md) | 完整 Web 预设的可选 tmux 位置上下文 | — |
|
|
||||||
| [`base`](base/README.zh.md) | 基于 base 的 profile 共享核心 | —(仅 patch) |
|
| [`base`](base/README.zh.md) | 基于 base 的 profile 共享核心 | —(仅 patch) |
|
||||||
| [`acp-app`](acp-app/README.zh.md) | 基于 base、仅用于自动化的 ACP stdio 应用 | 挂载 ACP bridge |
|
| [`acp-app`](acp-app/README.zh.md) | 基于 base、仅用于自动化的 ACP stdio 应用 | 挂载 ACP bridge |
|
||||||
| [`web-app`](web-app/README.zh.md) | 基于 base 的浏览器应用层 | 挂载多条 Web 配置行 |
|
| [`web-app`](web-app/README.zh.md) | 基于 base 的浏览器应用层 | 挂载多条 Web 配置行 |
|
||||||
|
|||||||
@@ -1,37 +0,0 @@
|
|||||||
# Bilingual-pair consistency record for README.md (docs/i18n/README.md): per heading
|
|
||||||
# section, a hash of its English and Chinese blocks outside code blocks and generated regions.
|
|
||||||
# After editing either side, bring the other along and re-record with:
|
|
||||||
# pnpm run verify-translation-pairing --write packages/bundle/session-search/README.md
|
|
||||||
/:
|
|
||||||
en: ac0fb71830f58337
|
|
||||||
zh: 0ece950cf48261a1
|
|
||||||
/deepseek-ai-dsh-session-search:
|
|
||||||
en: 04bcc04b53b7a3b4
|
|
||||||
zh: aceb77b602fcb0e8
|
|
||||||
/deepseek-ai-dsh-session-search/summary:
|
|
||||||
en: 7626a2d873e7c0fa
|
|
||||||
zh: 4537d44c81126542
|
|
||||||
/deepseek-ai-dsh-session-search/table-of-contents:
|
|
||||||
en: d152484eb41ac6b4
|
|
||||||
zh: 988e839059414d27
|
|
||||||
/deepseek-ai-dsh-session-search/use-this-package:
|
|
||||||
en: 958c815e002afb63
|
|
||||||
zh: 2f429ace45fb2738
|
|
||||||
/deepseek-ai-dsh-session-search/understand-the-implementation:
|
|
||||||
en: e7eb9f3b6081a532
|
|
||||||
zh: 49a942e930a1b7f7
|
|
||||||
/deepseek-ai-dsh-session-search/further-exploration:
|
|
||||||
en: fcd73e6db7e973cd
|
|
||||||
zh: b158af8273d11df0
|
|
||||||
/deepseek-ai-dsh-session-search/model-experience:
|
|
||||||
en: e01cb02606d75f9c
|
|
||||||
zh: 38709ef0209996ac
|
|
||||||
/deepseek-ai-dsh-session-search/model-experience/kv-cache-effect:
|
|
||||||
en: 1b2209bbbf869b1a
|
|
||||||
zh: 5b9de62271343e4e
|
|
||||||
/deepseek-ai-dsh-session-search/known-limitations-and-deferred-work:
|
|
||||||
en: d5211fd04a6cdddd
|
|
||||||
zh: d8ee29b1a060b77d
|
|
||||||
/deepseek-ai-dsh-session-search/known-limitations-and-deferred-work/dev-note:
|
|
||||||
en: 279d01435256cd2a
|
|
||||||
zh: 83780964e5de2f54
|
|
||||||
@@ -1,37 +0,0 @@
|
|||||||
# Bilingual-pair consistency record for README.md (docs/i18n/README.md): per heading
|
|
||||||
# section, a hash of its English and Chinese blocks outside code blocks and generated regions.
|
|
||||||
# After editing either side, bring the other along and re-record with:
|
|
||||||
# pnpm run verify-translation-pairing --write packages/bundle/string-editor/README.md
|
|
||||||
/:
|
|
||||||
en: 0b3c78e2974ee23e
|
|
||||||
zh: a88be7b7a3597905
|
|
||||||
/deepseek-ai-dsh-string-editor:
|
|
||||||
en: 39dda6b9f981619c
|
|
||||||
zh: 84ff97fcc5366a6c
|
|
||||||
/deepseek-ai-dsh-string-editor/summary:
|
|
||||||
en: 7faabd373dc07650
|
|
||||||
zh: a103e851accd0f8a
|
|
||||||
/deepseek-ai-dsh-string-editor/table-of-contents:
|
|
||||||
en: d152484eb41ac6b4
|
|
||||||
zh: 988e839059414d27
|
|
||||||
/deepseek-ai-dsh-string-editor/use-this-package:
|
|
||||||
en: 983e3a8a6357ae12
|
|
||||||
zh: 1bad4087471b4c60
|
|
||||||
/deepseek-ai-dsh-string-editor/understand-the-implementation:
|
|
||||||
en: 878820ec8f3bab5c
|
|
||||||
zh: 51eddc38d2a7685d
|
|
||||||
/deepseek-ai-dsh-string-editor/further-exploration:
|
|
||||||
en: eb617353b0c4d3bb
|
|
||||||
zh: 7c8aa163a51d5646
|
|
||||||
/deepseek-ai-dsh-string-editor/model-experience:
|
|
||||||
en: 11bb237fccd3cad8
|
|
||||||
zh: c74b0c591a5dd72b
|
|
||||||
/deepseek-ai-dsh-string-editor/model-experience/kv-cache-effect:
|
|
||||||
en: 1b2209bbbf869b1a
|
|
||||||
zh: 5b9de62271343e4e
|
|
||||||
/deepseek-ai-dsh-string-editor/known-limitations-and-deferred-work:
|
|
||||||
en: 73646ce5ca58c7ad
|
|
||||||
zh: da9660b48eff816d
|
|
||||||
/deepseek-ai-dsh-string-editor/known-limitations-and-deferred-work/dev-note:
|
|
||||||
en: 279d01435256cd2a
|
|
||||||
zh: 83780964e5de2f54
|
|
||||||
@@ -1,78 +0,0 @@
|
|||||||
---
|
|
||||||
description: "Edit files with the str_replace_editor tool."
|
|
||||||
kind: "package-bundle"
|
|
||||||
---
|
|
||||||
|
|
||||||
# @deepseek-ai/dsh-string-editor
|
|
||||||
|
|
||||||
English | [中文](README.zh.md)
|
|
||||||
|
|
||||||
## Summary
|
|
||||||
|
|
||||||
Add str_replace_editor to standard, cordis, and ptc alongside their existing filesystem tools. It ships switched off in Web and Desktop. Select it in Plugins to enable it.
|
|
||||||
|
|
||||||
## Table of Contents
|
|
||||||
|
|
||||||
- [Use this package](#use-this-package)
|
|
||||||
- [Understand the implementation](#understand-the-implementation)
|
|
||||||
- [Further Exploration](#further-exploration)
|
|
||||||
- [Model Experience](#model-experience)
|
|
||||||
- [Known Limitations and Deferred Work](#known-limitations-and-deferred-work)
|
|
||||||
- [Dev Note](#dev-note)
|
|
||||||
|
|
||||||
-----
|
|
||||||
|
|
||||||
<a id="use-this-package"></a>
|
|
||||||
## Use this package
|
|
||||||
|
|
||||||
In Web or Desktop, open Plugins and enable **String editor** in Official. Switch it off to remove its profile layer.
|
|
||||||
|
|
||||||
New Agents and subsequently reopened Sessions use the selected composition; live Agents retain their existing plugins. The minimal preset and host-level tool catalog remain unchanged.
|
|
||||||
|
|
||||||
-----
|
|
||||||
|
|
||||||
<a id="understand-the-implementation"></a>
|
|
||||||
## Understand the implementation
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary>Implementation details — click to expand</summary>
|
|
||||||
|
|
||||||
[`cordis.patch.yml`](cordis.patch.yml) contributes rows through `preset: preset-standard`, `preset: preset-cordis`, and `preset: preset-ptc`. Later profile patches can override their settings. The [profile composer](../../boot/app-boot/README.md) owns patch ordering and errors.
|
|
||||||
|
|
||||||
</details>
|
|
||||||
|
|
||||||
-----
|
|
||||||
|
|
||||||
<a id="further-exploration"></a>
|
|
||||||
## Further Exploration
|
|
||||||
|
|
||||||
[Capability implementation](../../fs/tool-str-replace-editor/README.md)
|
|
||||||
|
|
||||||
-----
|
|
||||||
|
|
||||||
<a id="model-experience"></a>
|
|
||||||
## Model Experience
|
|
||||||
|
|
||||||
Indirectly, through the [capability implementation](../../fs/tool-str-replace-editor/README.md), which owns model context and results.
|
|
||||||
|
|
||||||
#### KV Cache effect
|
|
||||||
|
|
||||||
The layer adds no request content directly; the capability implementation owns cache effects from tools, prompts, and results.
|
|
||||||
|
|
||||||
## Known Limitations and Deferred Work
|
|
||||||
|
|
||||||
<a id="known-limitations-and-deferred-work"></a>
|
|
||||||
|
|
||||||
- This editor overlaps with existing filesystem tools and follows their workspace authorization and observation requirements.
|
|
||||||
|
|
||||||
-----
|
|
||||||
|
|
||||||
<a id="dev-note"></a>
|
|
||||||
### Dev Note
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary>Maintainer context — click to expand</summary>
|
|
||||||
|
|
||||||
None.
|
|
||||||
|
|
||||||
</details>
|
|
||||||
@@ -1,78 +0,0 @@
|
|||||||
---
|
|
||||||
description: "使用 str_replace_editor 工具编辑文件。"
|
|
||||||
kind: "package-bundle"
|
|
||||||
---
|
|
||||||
|
|
||||||
# @deepseek-ai/dsh-string-editor
|
|
||||||
|
|
||||||
[English](README.md) | 中文
|
|
||||||
|
|
||||||
## 概述
|
|
||||||
|
|
||||||
为 standard、cordis 和 ptc 添加 str_replace_editor,保留原有文件系统工具。 Web 和 Desktop 随附此功能,默认关闭。在插件页选择它即可启用。
|
|
||||||
|
|
||||||
## 目录
|
|
||||||
|
|
||||||
- [使用此包](#use-this-package)
|
|
||||||
- [理解实现](#understand-the-implementation)
|
|
||||||
- [进一步探索](#further-exploration)
|
|
||||||
- [模型体验](#model-experience)
|
|
||||||
- [已知限制与暂缓工作](#known-limitations-and-deferred-work)
|
|
||||||
- [开发备注](#dev-note)
|
|
||||||
|
|
||||||
-----
|
|
||||||
|
|
||||||
<a id="use-this-package"></a>
|
|
||||||
## 使用此包
|
|
||||||
|
|
||||||
在 Web 或 Desktop 中打开插件页,在官方分组启用 **字符串编辑器**。关闭后移除其配置层。
|
|
||||||
|
|
||||||
新智能体和随后重新打开的会话使用所选组合;正在运行的智能体保留已有插件。minimal 预设和 Host 层工具目录保持不变。
|
|
||||||
|
|
||||||
-----
|
|
||||||
|
|
||||||
<a id="understand-the-implementation"></a>
|
|
||||||
## 理解实现
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary>实现细节 — 点击展开</summary>
|
|
||||||
|
|
||||||
[`cordis.patch.yml`](cordis.patch.yml) 通过 `preset: preset-standard`、`preset: preset-cordis` 和 `preset: preset-ptc` 贡献插件行。后续配置补丁可以覆盖这些设置。[配置组合器](../../boot/app-boot/README.zh.md) 负责补丁顺序和错误处理。
|
|
||||||
|
|
||||||
</details>
|
|
||||||
|
|
||||||
-----
|
|
||||||
|
|
||||||
<a id="further-exploration"></a>
|
|
||||||
## 进一步探索
|
|
||||||
|
|
||||||
[能力实现](../../fs/tool-str-replace-editor/README.zh.md)
|
|
||||||
|
|
||||||
-----
|
|
||||||
|
|
||||||
<a id="model-experience"></a>
|
|
||||||
## 模型体验
|
|
||||||
|
|
||||||
间接影响,通过[能力实现](../../fs/tool-str-replace-editor/README.zh.md) 贡献模型上下文和结果。
|
|
||||||
|
|
||||||
#### KV Cache 影响
|
|
||||||
|
|
||||||
此配置层不直接添加请求内容;能力实现负责工具目录、提示和结果的缓存影响。
|
|
||||||
|
|
||||||
## 已知限制与暂缓工作
|
|
||||||
|
|
||||||
<a id="known-limitations-and-deferred-work"></a>
|
|
||||||
|
|
||||||
- 此编辑器与现有文件系统工具的功能重叠,并遵守工作区授权和文件观察要求。
|
|
||||||
|
|
||||||
-----
|
|
||||||
|
|
||||||
<a id="dev-note"></a>
|
|
||||||
### 开发备注
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary>维护者上下文 — 点击展开</summary>
|
|
||||||
|
|
||||||
无。
|
|
||||||
|
|
||||||
</details>
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
- preset: preset-standard
|
|
||||||
insert:
|
|
||||||
- id: optional-tool-str-replace-editor
|
|
||||||
name: '@deepseek-ai/dsh-tool-str-replace-editor'
|
|
||||||
|
|
||||||
- preset: preset-cordis
|
|
||||||
insert:
|
|
||||||
- id: optional-tool-str-replace-editor
|
|
||||||
name: '@deepseek-ai/dsh-tool-str-replace-editor'
|
|
||||||
|
|
||||||
- preset: preset-ptc
|
|
||||||
insert:
|
|
||||||
- id: optional-tool-str-replace-editor
|
|
||||||
name: '@deepseek-ai/dsh-tool-str-replace-editor'
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
<svg width="36" height="36" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" stroke-width="1"><path d="M8.85596 2.69971H4.19971C3.37141 2.69971 2.69992 3.37146 2.69971 4.19971V11.8003C2.69992 12.6285 3.37141 13.3003 4.19971 13.3003H11.8003C12.6283 13.2999 13.3001 12.6283 13.3003 11.8003V7.89893H14.3003V11.8003C14.3001 13.1806 13.1806 14.2999 11.8003 14.3003H4.19971C2.81913 14.3003 1.69992 13.1808 1.69971 11.8003V4.19971C1.69992 2.81918 2.81913 1.69971 4.19971 1.69971H8.85596V2.69971Z" fill="#658EFF"></path><path d="M7.7849 8.23878L13.888 2.13574" stroke="#658EFF"></path></svg>
|
|
||||||
|
Before Width: | Height: | Size: 621 B |
@@ -1,6 +0,0 @@
|
|||||||
{
|
|
||||||
"meta": {
|
|
||||||
"title": "String editor",
|
|
||||||
"description": "Edit files with the str_replace_editor tool."
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
{
|
|
||||||
"meta": {
|
|
||||||
"title": "字符串编辑器",
|
|
||||||
"description": "使用 str_replace_editor 工具编辑文件。"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,49 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "@deepseek-ai/dsh-string-editor",
|
|
||||||
"description": "Edit files with the str_replace_editor tool.",
|
|
||||||
"version": "0.2.1-alpha.1",
|
|
||||||
"icon": "./icon.svg",
|
|
||||||
"publishConfig": {
|
|
||||||
"access": "public"
|
|
||||||
},
|
|
||||||
"repository": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "git+https://github.com/deepseek-ai/deepseek-harness.git",
|
|
||||||
"directory": "packages/bundle/string-editor"
|
|
||||||
},
|
|
||||||
"type": "module",
|
|
||||||
"main": "lib/index.js",
|
|
||||||
"types": "lib/types/index.d.ts",
|
|
||||||
"exports": {
|
|
||||||
".": {
|
|
||||||
"types": "./lib/types/index.d.ts",
|
|
||||||
"default": "./lib/index.js"
|
|
||||||
},
|
|
||||||
"./cordis.patch.yml": "./cordis.patch.yml",
|
|
||||||
"./locale/*.json": "./locale/*.json",
|
|
||||||
"./src/*": "./src/*",
|
|
||||||
"./package.json": "./package.json"
|
|
||||||
},
|
|
||||||
"files": [
|
|
||||||
"icon.svg",
|
|
||||||
"locale/*.json",
|
|
||||||
"lib/index.js",
|
|
||||||
"cordis.patch.yml",
|
|
||||||
"lib/types/**/*.d.ts"
|
|
||||||
],
|
|
||||||
"license": "MIT",
|
|
||||||
"dsh": {
|
|
||||||
"bundle": {
|
|
||||||
"patch": "./cordis.patch.yml"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"@deepseek-ai/dsh-tool-str-replace-editor": "workspace:*"
|
|
||||||
},
|
|
||||||
"peerDependencies": {
|
|
||||||
"@deepseek-ai/cordis": "workspace:~"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"@deepseek-ai/cordis": "workspace:~"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
/** String editor profile layer; runtime entries are declared in cordis.patch.yml. */
|
|
||||||
export {}
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
{
|
|
||||||
"extends": "../../../tsconfig.base.json",
|
|
||||||
"compilerOptions": {
|
|
||||||
"rootDir": "src",
|
|
||||||
"outDir": "lib/types"
|
|
||||||
},
|
|
||||||
"include": [
|
|
||||||
"src"
|
|
||||||
],
|
|
||||||
"references": [
|
|
||||||
{
|
|
||||||
"path": "../../../vendor/cordis"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@@ -1,37 +0,0 @@
|
|||||||
# Bilingual-pair consistency record for README.md (docs/i18n/README.md): per heading
|
|
||||||
# section, a hash of its English and Chinese blocks outside code blocks and generated regions.
|
|
||||||
# After editing either side, bring the other along and re-record with:
|
|
||||||
# pnpm run verify-translation-pairing --write packages/bundle/tmux-location/README.md
|
|
||||||
/:
|
|
||||||
en: abb9ad88845a269c
|
|
||||||
zh: c9a96576c1c63e5f
|
|
||||||
/deepseek-ai-dsh-tmux-location:
|
|
||||||
en: 7a09a973be4f5928
|
|
||||||
zh: 4421d7042de293cd
|
|
||||||
/deepseek-ai-dsh-tmux-location/summary:
|
|
||||||
en: 0c24b9949fb2abca
|
|
||||||
zh: 454e3c18b985a62a
|
|
||||||
/deepseek-ai-dsh-tmux-location/table-of-contents:
|
|
||||||
en: d152484eb41ac6b4
|
|
||||||
zh: 988e839059414d27
|
|
||||||
/deepseek-ai-dsh-tmux-location/use-this-package:
|
|
||||||
en: 3060df5b52b95d4a
|
|
||||||
zh: c04fbce2fe75a633
|
|
||||||
/deepseek-ai-dsh-tmux-location/understand-the-implementation:
|
|
||||||
en: 878820ec8f3bab5c
|
|
||||||
zh: 51eddc38d2a7685d
|
|
||||||
/deepseek-ai-dsh-tmux-location/further-exploration:
|
|
||||||
en: 10b3d66543bb26a4
|
|
||||||
zh: a8474dcf3fc93d85
|
|
||||||
/deepseek-ai-dsh-tmux-location/model-experience:
|
|
||||||
en: e9a9a7b0723e98b9
|
|
||||||
zh: 3cf108307e3093ce
|
|
||||||
/deepseek-ai-dsh-tmux-location/model-experience/kv-cache-effect:
|
|
||||||
en: 1b2209bbbf869b1a
|
|
||||||
zh: 5b9de62271343e4e
|
|
||||||
/deepseek-ai-dsh-tmux-location/known-limitations-and-deferred-work:
|
|
||||||
en: 487ebdb62ba78ea2
|
|
||||||
zh: acd142a5cdaa5301
|
|
||||||
/deepseek-ai-dsh-tmux-location/known-limitations-and-deferred-work/dev-note:
|
|
||||||
en: 279d01435256cd2a
|
|
||||||
zh: 83780964e5de2f54
|
|
||||||
@@ -1,78 +0,0 @@
|
|||||||
---
|
|
||||||
description: "Let agents read the current tmux pane and layout when available."
|
|
||||||
kind: "package-bundle"
|
|
||||||
---
|
|
||||||
|
|
||||||
# @deepseek-ai/dsh-tmux-location
|
|
||||||
|
|
||||||
English | [中文](README.zh.md)
|
|
||||||
|
|
||||||
## Summary
|
|
||||||
|
|
||||||
Give standard, cordis, and ptc the current tmux session, window, pane, and layout when the process runs inside tmux. It ships switched off in Web and Desktop. Select it in Plugins to enable it.
|
|
||||||
|
|
||||||
## Table of Contents
|
|
||||||
|
|
||||||
- [Use this package](#use-this-package)
|
|
||||||
- [Understand the implementation](#understand-the-implementation)
|
|
||||||
- [Further Exploration](#further-exploration)
|
|
||||||
- [Model Experience](#model-experience)
|
|
||||||
- [Known Limitations and Deferred Work](#known-limitations-and-deferred-work)
|
|
||||||
- [Dev Note](#dev-note)
|
|
||||||
|
|
||||||
-----
|
|
||||||
|
|
||||||
<a id="use-this-package"></a>
|
|
||||||
## Use this package
|
|
||||||
|
|
||||||
In Web or Desktop, open Plugins and enable **tmux location** in Official. Switch it off to remove its profile layer.
|
|
||||||
|
|
||||||
New Agents and subsequently reopened Sessions use the selected composition; live Agents retain their existing plugins. The minimal preset and host-level tool catalog remain unchanged.
|
|
||||||
|
|
||||||
-----
|
|
||||||
|
|
||||||
<a id="understand-the-implementation"></a>
|
|
||||||
## Understand the implementation
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary>Implementation details — click to expand</summary>
|
|
||||||
|
|
||||||
[`cordis.patch.yml`](cordis.patch.yml) contributes rows through `preset: preset-standard`, `preset: preset-cordis`, and `preset: preset-ptc`. Later profile patches can override their settings. The [profile composer](../../boot/app-boot/README.md) owns patch ordering and errors.
|
|
||||||
|
|
||||||
</details>
|
|
||||||
|
|
||||||
-----
|
|
||||||
|
|
||||||
<a id="further-exploration"></a>
|
|
||||||
## Further Exploration
|
|
||||||
|
|
||||||
[Capability implementation](../../context/tmux-context/README.md)
|
|
||||||
|
|
||||||
-----
|
|
||||||
|
|
||||||
<a id="model-experience"></a>
|
|
||||||
## Model Experience
|
|
||||||
|
|
||||||
Indirectly, through the [capability implementation](../../context/tmux-context/README.md), which owns model context and results.
|
|
||||||
|
|
||||||
#### KV Cache effect
|
|
||||||
|
|
||||||
The layer adds no request content directly; the capability implementation owns cache effects from tools, prompts, and results.
|
|
||||||
|
|
||||||
## Known Limitations and Deferred Work
|
|
||||||
|
|
||||||
<a id="known-limitations-and-deferred-work"></a>
|
|
||||||
|
|
||||||
- No context is added outside a verified tmux pane. Inherited tmux variables alone do not establish that the process belongs to the pane.
|
|
||||||
|
|
||||||
-----
|
|
||||||
|
|
||||||
<a id="dev-note"></a>
|
|
||||||
### Dev Note
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary>Maintainer context — click to expand</summary>
|
|
||||||
|
|
||||||
None.
|
|
||||||
|
|
||||||
</details>
|
|
||||||
@@ -1,78 +0,0 @@
|
|||||||
---
|
|
||||||
description: "在可用时让智能体读取当前 tmux 窗格和布局。"
|
|
||||||
kind: "package-bundle"
|
|
||||||
---
|
|
||||||
|
|
||||||
# @deepseek-ai/dsh-tmux-location
|
|
||||||
|
|
||||||
[English](README.md) | 中文
|
|
||||||
|
|
||||||
## 概述
|
|
||||||
|
|
||||||
当进程在 tmux 中运行时,为 standard、cordis 和 ptc 提供当前 tmux 会话、窗口、窗格和布局。 Web 和 Desktop 随附此功能,默认关闭。在插件页选择它即可启用。
|
|
||||||
|
|
||||||
## 目录
|
|
||||||
|
|
||||||
- [使用此包](#use-this-package)
|
|
||||||
- [理解实现](#understand-the-implementation)
|
|
||||||
- [进一步探索](#further-exploration)
|
|
||||||
- [模型体验](#model-experience)
|
|
||||||
- [已知限制与暂缓工作](#known-limitations-and-deferred-work)
|
|
||||||
- [开发备注](#dev-note)
|
|
||||||
|
|
||||||
-----
|
|
||||||
|
|
||||||
<a id="use-this-package"></a>
|
|
||||||
## 使用此包
|
|
||||||
|
|
||||||
在 Web 或 Desktop 中打开插件页,在官方分组启用 **tmux 位置**。关闭后移除其配置层。
|
|
||||||
|
|
||||||
新智能体和随后重新打开的会话使用所选组合;正在运行的智能体保留已有插件。minimal 预设和 Host 层工具目录保持不变。
|
|
||||||
|
|
||||||
-----
|
|
||||||
|
|
||||||
<a id="understand-the-implementation"></a>
|
|
||||||
## 理解实现
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary>实现细节 — 点击展开</summary>
|
|
||||||
|
|
||||||
[`cordis.patch.yml`](cordis.patch.yml) 通过 `preset: preset-standard`、`preset: preset-cordis` 和 `preset: preset-ptc` 贡献插件行。后续配置补丁可以覆盖这些设置。[配置组合器](../../boot/app-boot/README.zh.md) 负责补丁顺序和错误处理。
|
|
||||||
|
|
||||||
</details>
|
|
||||||
|
|
||||||
-----
|
|
||||||
|
|
||||||
<a id="further-exploration"></a>
|
|
||||||
## 进一步探索
|
|
||||||
|
|
||||||
[能力实现](../../context/tmux-context/README.zh.md)
|
|
||||||
|
|
||||||
-----
|
|
||||||
|
|
||||||
<a id="model-experience"></a>
|
|
||||||
## 模型体验
|
|
||||||
|
|
||||||
间接影响,通过[能力实现](../../context/tmux-context/README.zh.md) 贡献模型上下文和结果。
|
|
||||||
|
|
||||||
#### KV Cache 影响
|
|
||||||
|
|
||||||
此配置层不直接添加请求内容;能力实现负责工具目录、提示和结果的缓存影响。
|
|
||||||
|
|
||||||
## 已知限制与暂缓工作
|
|
||||||
|
|
||||||
<a id="known-limitations-and-deferred-work"></a>
|
|
||||||
|
|
||||||
- 在未验证的 tmux 窗格之外不添加上下文。仅继承 tmux 变量不能证明进程属于该窗格。
|
|
||||||
|
|
||||||
-----
|
|
||||||
|
|
||||||
<a id="dev-note"></a>
|
|
||||||
### 开发备注
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary>维护者上下文 — 点击展开</summary>
|
|
||||||
|
|
||||||
无。
|
|
||||||
|
|
||||||
</details>
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
- preset: preset-standard
|
|
||||||
insert:
|
|
||||||
- id: optional-tmux-context
|
|
||||||
name: '@deepseek-ai/dsh-tmux-context'
|
|
||||||
|
|
||||||
- preset: preset-cordis
|
|
||||||
insert:
|
|
||||||
- id: optional-tmux-context
|
|
||||||
name: '@deepseek-ai/dsh-tmux-context'
|
|
||||||
|
|
||||||
- preset: preset-ptc
|
|
||||||
insert:
|
|
||||||
- id: optional-tmux-context
|
|
||||||
name: '@deepseek-ai/dsh-tmux-context'
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
<svg width="36" height="36" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" stroke-width="1"><path d="M9.96976 1.70572L13.1554 3.93629L10.9019 8.12317L11.5158 11.605L10.7192 12.7427L2.52767 7.00693L3.3243 5.86922L6.80612 5.25528L9.96976 1.70572Z" stroke="#658EFF" stroke-linejoin="round"></path><path d="M6.05285 9.47511C6.27284 9.16094 6.70586 9.08458 7.02003 9.30457C7.3342 9.52455 7.41055 9.95757 7.19057 10.2717L3.98587 14.4708L3.21223 13.9291L6.05285 9.47511Z" fill="#658EFF"></path></svg>
|
|
||||||
|
Before Width: | Height: | Size: 533 B |
@@ -1,6 +0,0 @@
|
|||||||
{
|
|
||||||
"meta": {
|
|
||||||
"title": "tmux location",
|
|
||||||
"description": "Let agents read the current tmux pane and layout when available."
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
{
|
|
||||||
"meta": {
|
|
||||||
"title": "tmux 位置",
|
|
||||||
"description": "在可用时让智能体读取当前 tmux 窗格和布局。"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,49 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "@deepseek-ai/dsh-tmux-location",
|
|
||||||
"description": "Let agents read the current tmux pane and layout when available.",
|
|
||||||
"version": "0.2.1-alpha.1",
|
|
||||||
"icon": "./icon.svg",
|
|
||||||
"publishConfig": {
|
|
||||||
"access": "public"
|
|
||||||
},
|
|
||||||
"repository": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "git+https://github.com/deepseek-ai/deepseek-harness.git",
|
|
||||||
"directory": "packages/bundle/tmux-location"
|
|
||||||
},
|
|
||||||
"type": "module",
|
|
||||||
"main": "lib/index.js",
|
|
||||||
"types": "lib/types/index.d.ts",
|
|
||||||
"exports": {
|
|
||||||
".": {
|
|
||||||
"types": "./lib/types/index.d.ts",
|
|
||||||
"default": "./lib/index.js"
|
|
||||||
},
|
|
||||||
"./cordis.patch.yml": "./cordis.patch.yml",
|
|
||||||
"./locale/*.json": "./locale/*.json",
|
|
||||||
"./src/*": "./src/*",
|
|
||||||
"./package.json": "./package.json"
|
|
||||||
},
|
|
||||||
"files": [
|
|
||||||
"icon.svg",
|
|
||||||
"locale/*.json",
|
|
||||||
"lib/index.js",
|
|
||||||
"cordis.patch.yml",
|
|
||||||
"lib/types/**/*.d.ts"
|
|
||||||
],
|
|
||||||
"license": "MIT",
|
|
||||||
"dsh": {
|
|
||||||
"bundle": {
|
|
||||||
"patch": "./cordis.patch.yml"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"@deepseek-ai/dsh-tmux-context": "workspace:*"
|
|
||||||
},
|
|
||||||
"peerDependencies": {
|
|
||||||
"@deepseek-ai/cordis": "workspace:~"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"@deepseek-ai/cordis": "workspace:~"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
/** tmux location profile layer; runtime entries are declared in cordis.patch.yml. */
|
|
||||||
export {}
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
{
|
|
||||||
"extends": "../../../tsconfig.base.json",
|
|
||||||
"compilerOptions": {
|
|
||||||
"rootDir": "src",
|
|
||||||
"outDir": "lib/types"
|
|
||||||
},
|
|
||||||
"include": [
|
|
||||||
"src"
|
|
||||||
],
|
|
||||||
"references": [
|
|
||||||
{
|
|
||||||
"path": "../../../vendor/cordis"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@@ -36,8 +36,8 @@
|
|||||||
en: dd0a7799c76c0f94
|
en: dd0a7799c76c0f94
|
||||||
zh: 48d1cdacc9168aa2
|
zh: 48d1cdacc9168aa2
|
||||||
/deepseek-ai-dsh-client-ui-workspace/understand-the-implementation:
|
/deepseek-ai-dsh-client-ui-workspace/understand-the-implementation:
|
||||||
en: 0cc718002a249cc9
|
en: 721d5a49fe231191
|
||||||
zh: 969b2a034331ab56
|
zh: 3ef1dd720219e00e
|
||||||
/deepseek-ai-dsh-client-ui-workspace/understand-the-implementation/the-directory-flow-hole:
|
/deepseek-ai-dsh-client-ui-workspace/understand-the-implementation/the-directory-flow-hole:
|
||||||
en: 978415ec6b2e0cc0
|
en: 978415ec6b2e0cc0
|
||||||
zh: 0d5c705ff34fb1da
|
zh: 0d5c705ff34fb1da
|
||||||
|
|||||||
@@ -89,7 +89,7 @@ The package is one composition: both target slots are declared by other plugins,
|
|||||||
|
|
||||||
The browser entry also declares two root-scoped `list` child seats on each Session row: `sidebar.session.row.leading`, rendered only while that row's primary status is idle and left blank on an archived row, and `sidebar.session.row.hover`, mounted only while that row's hover card is open. Both take the row's Session identity and nothing else, so an occupant reads its own data by that id; a Session-scoped seat would force a Session binding, which would activate and retain every listed Session.
|
The browser entry also declares two root-scoped `list` child seats on each Session row: `sidebar.session.row.leading`, rendered only while that row's primary status is idle and left blank on an archived row, and `sidebar.session.row.hover`, mounted only while that row's hover card is open. Both take the row's Session identity and nothing else, so an occupant reads its own data by that id; a Session-scoped seat would force a Session binding, which would activate and retain every listed Session.
|
||||||
|
|
||||||
Client callers can pass `prompt` and `clearPreviousDraft` in the second argument to `uiWorkspace.startSession`. A prompt is plain text; structured drafts are handled internally during restoration and Workspace transfer. Without clearing, existing text or attachments are preserved; explicit clearing replaces only the target Session's text and inline references, leaving attachments intact. Option values are captured before asynchronous creation and applied to the exact retained binding before navigation commits. Superseded navigation does not write content; a submission-blocked input refuses preparation and keeps the previous selection. Calls without options retain the normal New Session flow. The [draft initialization decision](../../../.agents/notes/implemented/architecture/2026-09-30-structured-draft-initialization.md) describes the input owner's data flow.
|
Client callers can pass `prompt` and `clearPreviousDraft` in the second argument to `uiWorkspace.startSession`. A prompt is plain text; structured drafts are handled internally during restoration and Workspace transfer. Without clearing, existing text or attachments are preserved; explicit clearing replaces only the target Session's text and inline references, leaving attachments intact. Option values are captured before asynchronous creation and applied to the exact retained binding before navigation commits. Superseded navigation does not write content; a submission-blocked input refuses preparation and keeps the previous selection. Calls without options create a fresh Session using the current Agent preset definition. Workspace reconnection and explicit draft preparation may reuse an existing blank Session. The [draft initialization decision](../../../.agents/notes/implemented/architecture/2026-09-30-structured-draft-initialization.md) describes the input owner's data flow.
|
||||||
|
|
||||||
### The directory-flow hole
|
### The directory-flow hole
|
||||||
|
|
||||||
|
|||||||
@@ -89,7 +89,7 @@ Workspace 和 Session 的启动基线均就绪后,空安装环境调用 `works
|
|||||||
|
|
||||||
浏览器入口还为每个 Session 行声明两个 root 作用域的 `list` 子 slot:`sidebar.session.row.leading` 仅在该行主状态为 idle 时渲染、归档行留空,`sidebar.session.row.hover` 仅在该行的悬浮卡片打开时挂载。两者只接收行的 Session 身份,占用方据此读取自己的数据;Session 作用域的 slot 会强制建立 Session 绑定,从而激活并保留列表中每个 Session。
|
浏览器入口还为每个 Session 行声明两个 root 作用域的 `list` 子 slot:`sidebar.session.row.leading` 仅在该行主状态为 idle 时渲染、归档行留空,`sidebar.session.row.hover` 仅在该行的悬浮卡片打开时挂载。两者只接收行的 Session 身份,占用方据此读取自己的数据;Session 作用域的 slot 会强制建立 Session 绑定,从而激活并保留列表中每个 Session。
|
||||||
|
|
||||||
客户端调用方可以在 `uiWorkspace.startSession` 的第二参数中传入 `prompt` 与 `clearPreviousDraft`。提示词仅接受普通文字;结构化草稿由内部恢复和工作区携带流程处理。不清空时保留已有文字或附件;显式清空只替换目标 Session 的文字和内联引用,不删除附件。在异步创建前捕获选项值,在导航提交前应用到准确保留的 binding。已被后续操作取代的导航不写内容;输入处于提交阻塞状态时拒绝准备并保留原选择。不传选项时保持正常新会话流程。[草稿初始化决策](../../../.agents/notes/implemented/architecture/2026-09-30-structured-draft-initialization.zh.md)说明输入 owner 的数据流。
|
客户端调用方可以在 `uiWorkspace.startSession` 的第二参数中传入 `prompt` 与 `clearPreviousDraft`。提示词仅接受普通文字;结构化草稿由内部恢复和工作区携带流程处理。不清空时保留已有文字或附件;显式清空只替换目标 Session 的文字和内联引用,不删除附件。在异步创建前捕获选项值,在导航提交前应用到准确保留的 binding。已被后续操作取代的导航不写内容;输入处于提交阻塞状态时拒绝准备并保留原选择。不传选项时按当前 Agent 预设定义创建新的 Session。工作区重连和显式草稿准备仍可复用已有空 Session。[草稿初始化决策](../../../.agents/notes/implemented/architecture/2026-09-30-structured-draft-initialization.zh.md)说明输入 owner 的数据流。
|
||||||
|
|
||||||
### 目录流子 slot
|
### 目录流子 slot
|
||||||
|
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ export interface UiWorkspace {
|
|||||||
*/
|
*/
|
||||||
connectWorkspace(workspaceId: WorkspaceId): Promise<SessionId>
|
connectWorkspace(workspaceId: WorkspaceId): Promise<SessionId>
|
||||||
/**
|
/**
|
||||||
* Start a New Session flow and navigate to its Session; a creation the Host
|
* Create a fresh Session, or reuse a blank when preparing an explicit draft. A creation the Host
|
||||||
* refuses is shown through the Workspace notice and leaves the selection as it was.
|
* refuses is shown through the Workspace notice and leaves the selection as it was.
|
||||||
* @param workspaceId - explicit target; absent inherits the current or most recent Workspace.
|
* @param workspaceId - explicit target; absent inherits the current or most recent Workspace.
|
||||||
* @param options - initial content; existing text or attachments are preserved unless clearPreviousDraft is true.
|
* @param options - initial content; existing text or attachments are preserved unless clearPreviousDraft is true.
|
||||||
@@ -167,12 +167,17 @@ class UiWorkspaceService extends Service implements UiWorkspace {
|
|||||||
}, 'ui-workspace: Workspace navigation policy')
|
}, 'ui-workspace: Workspace navigation policy')
|
||||||
}
|
}
|
||||||
|
|
||||||
async connectWorkspace(workspaceId: WorkspaceId): Promise<SessionId> {
|
connectWorkspace(workspaceId: WorkspaceId): Promise<SessionId> {
|
||||||
|
return this.connectBlank(workspaceId, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
private async connectBlank(workspaceId: WorkspaceId, reuse: boolean): Promise<SessionId> {
|
||||||
const workspace = this.workspaces.list.getSnapshot().items
|
const workspace = this.workspaces.list.getSnapshot().items
|
||||||
.find(item => item.workspaceId === workspaceId)
|
.find(item => item.workspaceId === workspaceId)
|
||||||
if (workspace === undefined) {
|
if (workspace === undefined) {
|
||||||
throw new Error(`uiWorkspace.connectWorkspace: unknown workspace ${workspaceId}`)
|
throw new Error(`uiWorkspace.connectWorkspace: unknown workspace ${workspaceId}`)
|
||||||
}
|
}
|
||||||
|
if (!reuse) return this.sessions.create({ workspaceId })
|
||||||
const inflight = this.connecting.get(workspaceId)
|
const inflight = this.connecting.get(workspaceId)
|
||||||
if (inflight !== undefined) return inflight
|
if (inflight !== undefined) return inflight
|
||||||
|
|
||||||
@@ -207,11 +212,17 @@ class UiWorkspaceService extends Service implements UiWorkspace {
|
|||||||
this.replaceMain(target, this.lifetime.signal, 'reveal')
|
this.replaceMain(target, this.lifetime.signal, 'reveal')
|
||||||
}
|
}
|
||||||
|
|
||||||
async openWorkspace(workspaceId: WorkspaceId, beforeOpen?: (sessionId: SessionId) => void): Promise<void> {
|
openWorkspace(workspaceId: WorkspaceId, beforeOpen?: (sessionId: SessionId) => void): Promise<void> {
|
||||||
|
return this.openWorkspaceSession(workspaceId, beforeOpen, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
private async openWorkspaceSession(
|
||||||
|
workspaceId: WorkspaceId, beforeOpen: ((sessionId: SessionId) => void) | undefined, reuse: boolean,
|
||||||
|
): Promise<void> {
|
||||||
const navigation = AbortSignal.any([this.ctx.layout.beginNavigation(), this.lifetime.signal])
|
const navigation = AbortSignal.any([this.ctx.layout.beginNavigation(), this.lifetime.signal])
|
||||||
let sessionId: SessionId
|
let sessionId: SessionId
|
||||||
try {
|
try {
|
||||||
sessionId = await this.connectWorkspace(workspaceId)
|
sessionId = await this.connectBlank(workspaceId, reuse)
|
||||||
} catch (error: unknown) {
|
} catch (error: unknown) {
|
||||||
// Reported here, not in connectWorkspace: startup restoration calls that
|
// Reported here, not in connectWorkspace: startup restoration calls that
|
||||||
// directly and stays console-only.
|
// directly and stays console-only.
|
||||||
@@ -248,11 +259,14 @@ class UiWorkspaceService extends Service implements UiWorkspace {
|
|||||||
this.clearMain()
|
this.clearMain()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
void this.openWorkspace(target, initializeDraft ? (id) => {
|
const opening = draftOptions === undefined
|
||||||
const binding = this.sessions.binding(id)
|
? this.openWorkspaceSession(target, undefined, false)
|
||||||
if (binding === undefined) this.draftPreparationFailed()
|
: this.openWorkspace(target, initializeDraft ? (id) => {
|
||||||
this.prepareDraft(binding, draftOptions)
|
const binding = this.sessions.binding(id)
|
||||||
} : undefined).catch(
|
if (binding === undefined) this.draftPreparationFailed()
|
||||||
|
this.prepareDraft(binding, draftOptions)
|
||||||
|
} : undefined)
|
||||||
|
void opening.catch(
|
||||||
(reason: unknown) => { console.warn('new session failed:', reason) },
|
(reason: unknown) => { console.warn('new session failed:', reason) },
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -662,6 +662,18 @@ describe('UiWorkspaceService', () => {
|
|||||||
expect(b.sessions.retain).not.toHaveBeenCalled()
|
expect(b.sessions.retain).not.toHaveBeenCalled()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('creates a fresh Agent on explicit New Session instead of reusing a mounted blank', async () => {
|
||||||
|
const b = bench({
|
||||||
|
sessions: sessionState([summary('blank', { blank: true, cwd: '/w/a' })], 'pending'),
|
||||||
|
workspaces: workspaceState([workspace('a', [sid('blank')])]),
|
||||||
|
})
|
||||||
|
b.uiWorkspace.startSession(wid('a'))
|
||||||
|
await vi.waitFor(() => {
|
||||||
|
expect(b.sessions.create).toHaveBeenCalledExactlyOnceWith({ workspaceId: wid('a') })
|
||||||
|
})
|
||||||
|
await vi.waitFor(() => { expect(b.sessions.retain).toHaveBeenCalledWith(sid('created-a'), expect.anything()) })
|
||||||
|
})
|
||||||
|
|
||||||
it('reports a refused explicit Session creation through the Workspace notice', async () => {
|
it('reports a refused explicit Session creation through the Workspace notice', async () => {
|
||||||
const b = bench({ workspaces: workspaceState([workspace('a')]), sessions: sessionState() })
|
const b = bench({ workspaces: workspaceState([workspace('a')]), sessions: sessionState() })
|
||||||
// Startup restoration creates its own Session first and stays quiet on failure (pinned above).
|
// Startup restoration creates its own Session first and stays quiet on failure (pinned above).
|
||||||
@@ -797,7 +809,8 @@ describe('UiWorkspaceService', () => {
|
|||||||
const opening = vi.spyOn(b.uiWorkspace, 'openWorkspace')
|
const opening = vi.spyOn(b.uiWorkspace, 'openWorkspace')
|
||||||
|
|
||||||
b.uiWorkspace.startSession(wid('a'), options)
|
b.uiWorkspace.startSession(wid('a'), options)
|
||||||
await lastOpening(opening)
|
if (options === undefined) await vi.waitFor(() => { expect(b.sessions.retain).toHaveBeenCalledOnce() })
|
||||||
|
else await lastOpening(opening)
|
||||||
|
|
||||||
expect(b.sessions.retain).toHaveBeenCalledExactlyOnceWith(sid('created-a'), { source: 'mainView' })
|
expect(b.sessions.retain).toHaveBeenCalledExactlyOnceWith(sid('created-a'), { source: 'mainView' })
|
||||||
expect(b.sessions.binding).not.toHaveBeenCalled()
|
expect(b.sessions.binding).not.toHaveBeenCalled()
|
||||||
|
|||||||
@@ -18,8 +18,8 @@
|
|||||||
en: b55aeb927737b90d
|
en: b55aeb927737b90d
|
||||||
zh: 0b215fcb5c2c7908
|
zh: 0b215fcb5c2c7908
|
||||||
/packages-experimental/packages:
|
/packages-experimental/packages:
|
||||||
en: a7fb1f6cc249d885
|
en: 8d4c5d32901b2ce6
|
||||||
zh: 523ecd7600ecd436
|
zh: 0240d4c81489edaa
|
||||||
/packages-experimental/related-documentation:
|
/packages-experimental/related-documentation:
|
||||||
en: 1cb9d3448d44e48d
|
en: 1cb9d3448d44e48d
|
||||||
zh: cd326d70a746b896
|
zh: cd326d70a746b896
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ Promotion requires a named product role, documented public behavior and limitati
|
|||||||
| Package | Role | ctx key |
|
| Package | Role | ctx key |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
| [`tool-session-query`](tool-session-query/README.md) | Workspace-authorized model session search, trace, and event reads | — |
|
| [`tool-session-query`](tool-session-query/README.md) | Workspace-authorized model session search, trace, and event reads | — |
|
||||||
|
| [`session-search`](session-search/README.md) | Optional experimental session search in full Web presets | — |
|
||||||
| [`ralph-bundle`](ralph-bundle/README.md) | Optional repeated delegation with an isolated workflow engine | — |
|
| [`ralph-bundle`](ralph-bundle/README.md) | Optional repeated delegation with an isolated workflow engine | — |
|
||||||
| [`terminal-bundle`](terminal-bundle/README.md) | Optional persistent terminal tools for full Web presets | — |
|
| [`terminal-bundle`](terminal-bundle/README.md) | Optional persistent terminal tools for full Web presets | — |
|
||||||
| [`badge-skill-bundle`](badge-skill-bundle/README.md) | Optional powered-by-dsh badge skill | — |
|
| [`badge-skill-bundle`](badge-skill-bundle/README.md) | Optional powered-by-dsh badge skill | — |
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ kind: "package-group"
|
|||||||
| 包 | 职责 | ctx 键 |
|
| 包 | 职责 | ctx 键 |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
| [`tool-session-query`](tool-session-query/README.zh.md) | 按工作区授权的模型会话搜索、追踪与事件读取 | — |
|
| [`tool-session-query`](tool-session-query/README.zh.md) | 按工作区授权的模型会话搜索、追踪与事件读取 | — |
|
||||||
|
| [`session-search`](session-search/README.zh.md) | 完整 Web 预设的可选实验性会话搜索 | — |
|
||||||
| [`ralph-bundle`](ralph-bundle/README.zh.md) | 带隔离 workflow 引擎的可选重复委派 | — |
|
| [`ralph-bundle`](ralph-bundle/README.zh.md) | 带隔离 workflow 引擎的可选重复委派 | — |
|
||||||
| [`terminal-bundle`](terminal-bundle/README.zh.md) | 完整 Web 预设的可选持久终端工具 | — |
|
| [`terminal-bundle`](terminal-bundle/README.zh.md) | 完整 Web 预设的可选持久终端工具 | — |
|
||||||
| [`badge-skill-bundle`](badge-skill-bundle/README.zh.md) | 可选 powered-by-dsh 徽章技能 | — |
|
| [`badge-skill-bundle`](badge-skill-bundle/README.zh.md) | 可选 powered-by-dsh 徽章技能 | — |
|
||||||
|
|||||||
@@ -0,0 +1,37 @@
|
|||||||
|
# Bilingual-pair consistency record for README.md (docs/i18n/README.md): per heading
|
||||||
|
# section, a hash of its English and Chinese blocks outside code blocks and generated regions.
|
||||||
|
# After editing either side, bring the other along and re-record with:
|
||||||
|
# pnpm run verify-translation-pairing --write packages/experimental/session-search/README.md
|
||||||
|
/:
|
||||||
|
en: ac0fb71830f58337
|
||||||
|
zh: 0ece950cf48261a1
|
||||||
|
/deepseek-ai-dsh-experimental-session-search:
|
||||||
|
en: f4f9c83d1dd36580
|
||||||
|
zh: f34e5a1c0df5e469
|
||||||
|
/deepseek-ai-dsh-experimental-session-search/summary:
|
||||||
|
en: 565d4c9c763ed823
|
||||||
|
zh: 36b12b0511b46f5e
|
||||||
|
/deepseek-ai-dsh-experimental-session-search/table-of-contents:
|
||||||
|
en: d152484eb41ac6b4
|
||||||
|
zh: 988e839059414d27
|
||||||
|
/deepseek-ai-dsh-experimental-session-search/use-this-package:
|
||||||
|
en: 958c815e002afb63
|
||||||
|
zh: 2f429ace45fb2738
|
||||||
|
/deepseek-ai-dsh-experimental-session-search/understand-the-implementation:
|
||||||
|
en: e7eb9f3b6081a532
|
||||||
|
zh: 49a942e930a1b7f7
|
||||||
|
/deepseek-ai-dsh-experimental-session-search/further-exploration:
|
||||||
|
en: 3016959b8c0546d0
|
||||||
|
zh: a356ef50b3ce9f77
|
||||||
|
/deepseek-ai-dsh-experimental-session-search/model-experience:
|
||||||
|
en: 00d8bdccc42b1f10
|
||||||
|
zh: 3264a962cff8127e
|
||||||
|
/deepseek-ai-dsh-experimental-session-search/model-experience/kv-cache-effect:
|
||||||
|
en: 1b2209bbbf869b1a
|
||||||
|
zh: 5b9de62271343e4e
|
||||||
|
/deepseek-ai-dsh-experimental-session-search/known-limitations-and-deferred-work:
|
||||||
|
en: d5211fd04a6cdddd
|
||||||
|
zh: d8ee29b1a060b77d
|
||||||
|
/deepseek-ai-dsh-experimental-session-search/known-limitations-and-deferred-work/dev-note:
|
||||||
|
en: 279d01435256cd2a
|
||||||
|
zh: 83780964e5de2f54
|
||||||
+4
-4
@@ -3,13 +3,13 @@ description: "Give Agents tools to search and read earlier sessions from the cur
|
|||||||
kind: "package-bundle"
|
kind: "package-bundle"
|
||||||
---
|
---
|
||||||
|
|
||||||
# @deepseek-ai/dsh-session-search
|
# @deepseek-ai/dsh-experimental-session-search
|
||||||
|
|
||||||
English | [中文](README.zh.md)
|
English | [中文](README.zh.md)
|
||||||
|
|
||||||
## Summary
|
## Summary
|
||||||
|
|
||||||
Give Agents five read-only tools to search earlier sessions in standard, cordis, and ptc. The content index opens on the first search and is shared by Agents using the same preset revision. The bundle ships switched off in Web and Desktop. Select it in Plugins to enable it.
|
Give Agents five experimental read-only tools to search earlier sessions in standard, cordis, and ptc. The content index opens on the first search and is shared by Agents using the same preset revision. The bundle ships switched off in Web and Desktop. Select it in Plugins to enable it.
|
||||||
|
|
||||||
## Table of Contents
|
## Table of Contents
|
||||||
|
|
||||||
@@ -50,14 +50,14 @@ Each preset revision owns an isolated `sessionQuery` provider with a lazy `:memo
|
|||||||
<a id="further-exploration"></a>
|
<a id="further-exploration"></a>
|
||||||
## Further Exploration
|
## Further Exploration
|
||||||
|
|
||||||
[Capability implementation](../../session-query/tool-session-query/README.md)
|
[Capability implementation](../tool-session-query/README.md)
|
||||||
|
|
||||||
-----
|
-----
|
||||||
|
|
||||||
<a id="model-experience"></a>
|
<a id="model-experience"></a>
|
||||||
## Model Experience
|
## Model Experience
|
||||||
|
|
||||||
Indirectly, through the [capability implementation](../../session-query/tool-session-query/README.md), which owns model context and results.
|
Indirectly, through the [capability implementation](../tool-session-query/README.md), which owns model context and results.
|
||||||
|
|
||||||
#### KV Cache effect
|
#### KV Cache effect
|
||||||
|
|
||||||
+4
-4
@@ -3,13 +3,13 @@ description: "为智能体提供搜索和读取当前工作区历史会话的工
|
|||||||
kind: "package-bundle"
|
kind: "package-bundle"
|
||||||
---
|
---
|
||||||
|
|
||||||
# @deepseek-ai/dsh-session-search
|
# @deepseek-ai/dsh-experimental-session-search
|
||||||
|
|
||||||
[English](README.md) | 中文
|
[English](README.md) | 中文
|
||||||
|
|
||||||
## 概述
|
## 概述
|
||||||
|
|
||||||
为 standard、cordis 和 ptc 中的智能体提供五个只读工具,用于搜索历史会话。内容索引在首次搜索时打开,由使用同一预设版本的智能体共享。Web 和 Desktop 随附此配置包,默认关闭。在插件页选择它即可启用。
|
为 standard、cordis 和 ptc 中的智能体提供五个实验性只读工具,用于搜索历史会话。内容索引在首次搜索时打开,由使用同一预设版本的智能体共享。Web 和 Desktop 随附此配置包,默认关闭。在插件页选择它即可启用。
|
||||||
|
|
||||||
## 目录
|
## 目录
|
||||||
|
|
||||||
@@ -50,14 +50,14 @@ kind: "package-bundle"
|
|||||||
<a id="further-exploration"></a>
|
<a id="further-exploration"></a>
|
||||||
## 进一步探索
|
## 进一步探索
|
||||||
|
|
||||||
[能力实现](../../session-query/tool-session-query/README.zh.md)
|
[能力实现](../tool-session-query/README.zh.md)
|
||||||
|
|
||||||
-----
|
-----
|
||||||
|
|
||||||
<a id="model-experience"></a>
|
<a id="model-experience"></a>
|
||||||
## 模型体验
|
## 模型体验
|
||||||
|
|
||||||
间接影响,通过[能力实现](../../session-query/tool-session-query/README.zh.md) 贡献模型上下文和结果。
|
间接影响,通过[能力实现](../tool-session-query/README.zh.md) 贡献模型上下文和结果。
|
||||||
|
|
||||||
#### KV Cache 影响
|
#### KV Cache 影响
|
||||||
|
|
||||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
+2
-2
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"name": "@deepseek-ai/dsh-session-search",
|
"name": "@deepseek-ai/dsh-experimental-session-search",
|
||||||
"description": "Give Agents tools to search and read earlier sessions from the current workspace.",
|
"description": "Give Agents tools to search and read earlier sessions from the current workspace.",
|
||||||
"version": "0.2.1-alpha.1",
|
"version": "0.2.1-alpha.1",
|
||||||
"icon": "./icon.svg",
|
"icon": "./icon.svg",
|
||||||
@@ -9,7 +9,7 @@
|
|||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "git+https://github.com/deepseek-ai/deepseek-harness.git",
|
"url": "git+https://github.com/deepseek-ai/deepseek-harness.git",
|
||||||
"directory": "packages/bundle/session-search"
|
"directory": "packages/experimental/session-search"
|
||||||
},
|
},
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "lib/index.js",
|
"main": "lib/index.js",
|
||||||
File renamed without changes.
File renamed without changes.
@@ -15,8 +15,8 @@
|
|||||||
en: d152484eb41ac6b4
|
en: d152484eb41ac6b4
|
||||||
zh: 09388d293f9be9cb
|
zh: 09388d293f9be9cb
|
||||||
/deepseek-ai-dsh-tool-str-replace-editor/use-this-package:
|
/deepseek-ai-dsh-tool-str-replace-editor/use-this-package:
|
||||||
en: 00b16ec00064922b
|
en: 549d3ed126a46a99
|
||||||
zh: 5e0f3e78f1bb4a29
|
zh: 476e0f61fa5e9ecb
|
||||||
/deepseek-ai-dsh-tool-str-replace-editor/use-this-package/minimal-composition:
|
/deepseek-ai-dsh-tool-str-replace-editor/use-this-package/minimal-composition:
|
||||||
en: db6e7d91ff7e0439
|
en: db6e7d91ff7e0439
|
||||||
zh: 2ed4096f6c856e17
|
zh: 2ed4096f6c856e17
|
||||||
|
|||||||
@@ -25,6 +25,8 @@ English | [中文](README.zh.md)
|
|||||||
<a id="use-this-package"></a>
|
<a id="use-this-package"></a>
|
||||||
## Use this package
|
## Use this package
|
||||||
|
|
||||||
|
This nonexperimental standalone plugin is intended for custom compositions. It is not offered as an optional bundle in the Plugins page.
|
||||||
|
|
||||||
Mount the tool alongside a `ctx.fs` backend (and, for guarded mutations, the policy plugin) when the model should edit files through the familiar `view`/`create`/`str_replace`/`insert` command vocabulary on absolute paths.
|
Mount the tool alongside a `ctx.fs` backend (and, for guarded mutations, the policy plugin) when the model should edit files through the familiar `view`/`create`/`str_replace`/`insert` command vocabulary on absolute paths.
|
||||||
|
|
||||||
### Minimal composition
|
### Minimal composition
|
||||||
|
|||||||
@@ -25,6 +25,8 @@ kind: "package-reference"
|
|||||||
<a id="use-this-package"></a>
|
<a id="use-this-package"></a>
|
||||||
## 使用本包
|
## 使用本包
|
||||||
|
|
||||||
|
此非实验性的独立插件面向自定义组合。Plugins 页面不将它作为可选 bundle 提供。
|
||||||
|
|
||||||
当模型应通过熟悉的 `view`/`create`/`str_replace`/`insert` 命令词汇在绝对路径上编辑文件时,把工具与 `ctx.fs` 后端(以及需要防护变更时的策略插件)一起挂载。
|
当模型应通过熟悉的 `view`/`create`/`str_replace`/`insert` 命令词汇在绝对路径上编辑文件时,把工具与 `ctx.fs` 后端(以及需要防护变更时的策略插件)一起挂载。
|
||||||
|
|
||||||
### 最小组合
|
### 最小组合
|
||||||
|
|||||||
@@ -31,9 +31,7 @@ function bundle(name: string): { dir: string; patches: ReturnType<typeof loadOve
|
|||||||
}
|
}
|
||||||
|
|
||||||
const lightweight = [
|
const lightweight = [
|
||||||
'@deepseek-ai/dsh-session-search',
|
'@deepseek-ai/dsh-experimental-session-search',
|
||||||
'@deepseek-ai/dsh-string-editor',
|
|
||||||
'@deepseek-ai/dsh-tmux-location',
|
|
||||||
'@deepseek-ai/dsh-experimental-ralph-bundle',
|
'@deepseek-ai/dsh-experimental-ralph-bundle',
|
||||||
'@deepseek-ai/dsh-experimental-terminal-bundle',
|
'@deepseek-ai/dsh-experimental-terminal-bundle',
|
||||||
'@deepseek-ai/dsh-experimental-badge-skill-bundle',
|
'@deepseek-ai/dsh-experimental-badge-skill-bundle',
|
||||||
@@ -166,7 +164,7 @@ describe('optional bundles', () => {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
it('ships all seven lightweight bundles without selecting them in a default template', () => {
|
it('ships all five lightweight bundles without selecting them in a default template', () => {
|
||||||
const defaults = Object.values(PROFILE_TEMPLATES).flatMap(template => template.bundles)
|
const defaults = Object.values(PROFILE_TEMPLATES).flatMap(template => template.bundles)
|
||||||
for (const name of lightweight) {
|
for (const name of lightweight) {
|
||||||
expect(OPTIONAL_BUNDLES).toContain(name)
|
expect(OPTIONAL_BUNDLES).toContain(name)
|
||||||
@@ -199,7 +197,7 @@ describe('optional bundles', () => {
|
|||||||
const roots = presetRows(composed, id)
|
const roots = presetRows(composed, id)
|
||||||
const names = flattenRows(roots).map(row => row.name)
|
const names = flattenRows(roots).map(row => row.name)
|
||||||
for (const name of [
|
for (const name of [
|
||||||
'@deepseek-ai/dsh-tool-session-query', '@deepseek-ai/dsh-tool-str-replace-editor', '@deepseek-ai/dsh-tmux-context',
|
'@deepseek-ai/dsh-tool-session-query',
|
||||||
'@deepseek-ai/dsh-tool-ralph', '@deepseek-ai/dsh-tool-terminal',
|
'@deepseek-ai/dsh-tool-ralph', '@deepseek-ai/dsh-tool-terminal',
|
||||||
]) expect(names).toContain(name)
|
]) expect(names).toContain(name)
|
||||||
expect(roots.find(row => row.id === 'optional-ralph')?.isolate).toEqual({ workflowEngine: true })
|
expect(roots.find(row => row.id === 'optional-ralph')?.isolate).toEqual({ workflowEngine: true })
|
||||||
|
|||||||
@@ -175,9 +175,7 @@ const SENTENCE_MODEL_EXPERIENCE: Readonly<Record<string, SentenceContract>> = {
|
|||||||
'packages/host/plugin-inventory': { kind: 'none', reason: 'Host-side read-only Loader projection; registers nothing model-facing.' },
|
'packages/host/plugin-inventory': { kind: 'none', reason: 'Host-side read-only Loader projection; registers nothing model-facing.' },
|
||||||
'packages/host/open-in-app': { kind: 'none', reason: 'Host routes opening desktop applications for a human; registers nothing model-facing.' },
|
'packages/host/open-in-app': { kind: 'none', reason: 'Host routes opening desktop applications for a human; registers nothing model-facing.' },
|
||||||
'packages/client/ui-open-in-app': { kind: 'none', reason: 'Browser-side split button opening the workspace directory for a human; registers nothing model-facing.' },
|
'packages/client/ui-open-in-app': { kind: 'none', reason: 'Browser-side split button opening the workspace directory for a human; registers nothing model-facing.' },
|
||||||
'packages/bundle/session-search': { kind: 'indirect', reason: 'The profile layer delegates model-visible behavior to its selected capability.' },
|
'packages/experimental/session-search': { kind: 'indirect', reason: 'The profile layer delegates model-visible behavior to its selected capability.' },
|
||||||
'packages/bundle/string-editor': { kind: 'indirect', reason: 'The profile layer delegates model-visible behavior to its selected capability.' },
|
|
||||||
'packages/bundle/tmux-location': { kind: 'indirect', reason: 'The profile layer delegates model-visible behavior to its selected capability.' },
|
|
||||||
'packages/experimental/ralph-bundle': { kind: 'indirect', reason: 'The profile layer delegates model-visible behavior to its selected capability.' },
|
'packages/experimental/ralph-bundle': { kind: 'indirect', reason: 'The profile layer delegates model-visible behavior to its selected capability.' },
|
||||||
'packages/experimental/terminal-bundle': { kind: 'indirect', reason: 'The profile layer delegates model-visible behavior to its selected capability.' },
|
'packages/experimental/terminal-bundle': { kind: 'indirect', reason: 'The profile layer delegates model-visible behavior to its selected capability.' },
|
||||||
'packages/experimental/badge-skill-bundle': { kind: 'indirect', reason: 'The profile layer delegates model-visible behavior to its selected capability.' },
|
'packages/experimental/badge-skill-bundle': { kind: 'indirect', reason: 'The profile layer delegates model-visible behavior to its selected capability.' },
|
||||||
|
|||||||
+1
-3
@@ -28,9 +28,7 @@
|
|||||||
// not declaration path aliases, keep each package/vendor source compiled
|
// not declaration path aliases, keep each package/vendor source compiled
|
||||||
// under its own tsconfig boundary.
|
// under its own tsconfig boundary.
|
||||||
"paths": {
|
"paths": {
|
||||||
"@deepseek-ai/dsh-session-search": ["./packages/bundle/session-search/src/index.ts"],
|
"@deepseek-ai/dsh-experimental-session-search": ["./packages/experimental/session-search/src/index.ts"],
|
||||||
"@deepseek-ai/dsh-string-editor": ["./packages/bundle/string-editor/src/index.ts"],
|
|
||||||
"@deepseek-ai/dsh-tmux-location": ["./packages/bundle/tmux-location/src/index.ts"],
|
|
||||||
"@deepseek-ai/dsh-experimental-ralph-bundle": ["./packages/experimental/ralph-bundle/src/index.ts"],
|
"@deepseek-ai/dsh-experimental-ralph-bundle": ["./packages/experimental/ralph-bundle/src/index.ts"],
|
||||||
"@deepseek-ai/dsh-experimental-terminal-bundle": ["./packages/experimental/terminal-bundle/src/index.ts"],
|
"@deepseek-ai/dsh-experimental-terminal-bundle": ["./packages/experimental/terminal-bundle/src/index.ts"],
|
||||||
"@deepseek-ai/dsh-experimental-badge-skill-bundle": ["./packages/experimental/badge-skill-bundle/src/index.ts"],
|
"@deepseek-ai/dsh-experimental-badge-skill-bundle": ["./packages/experimental/badge-skill-bundle/src/index.ts"],
|
||||||
|
|||||||
+2
-4
@@ -118,7 +118,7 @@
|
|||||||
"apps/web/tests/conversation-column-overflow.e2e.ts",
|
"apps/web/tests/conversation-column-overflow.e2e.ts",
|
||||||
"apps/web/tests/ptc-round.e2e.ts",
|
"apps/web/tests/ptc-round.e2e.ts",
|
||||||
"apps/web/tests/ptc-escalation.e2e.ts",
|
"apps/web/tests/ptc-escalation.e2e.ts",
|
||||||
"apps/web/tests/optional-string-editor.e2e.ts",
|
"apps/web/tests/standalone-string-editor.e2e.ts",
|
||||||
"apps/web/tests/present.e2e.ts",
|
"apps/web/tests/present.e2e.ts",
|
||||||
"apps/web/tests/present-svg.e2e.ts",
|
"apps/web/tests/present-svg.e2e.ts",
|
||||||
"apps/web/tests/composer-draft-scroll.e2e.ts",
|
"apps/web/tests/composer-draft-scroll.e2e.ts",
|
||||||
@@ -217,9 +217,7 @@
|
|||||||
"references": [
|
"references": [
|
||||||
{ "path": "./packages/experimental/client-ui-cot-translation/tsconfig.host.json" },
|
{ "path": "./packages/experimental/client-ui-cot-translation/tsconfig.host.json" },
|
||||||
{ "path": "./packages/experimental/cot-translation-bundle" },
|
{ "path": "./packages/experimental/cot-translation-bundle" },
|
||||||
{ "path": "./packages/bundle/session-search" },
|
{ "path": "./packages/experimental/session-search" },
|
||||||
{ "path": "./packages/bundle/string-editor" },
|
|
||||||
{ "path": "./packages/bundle/tmux-location" },
|
|
||||||
{ "path": "./packages/experimental/ralph-bundle" },
|
{ "path": "./packages/experimental/ralph-bundle" },
|
||||||
{ "path": "./packages/experimental/terminal-bundle" },
|
{ "path": "./packages/experimental/terminal-bundle" },
|
||||||
{ "path": "./packages/experimental/badge-skill-bundle" },
|
{ "path": "./packages/experimental/badge-skill-bundle" },
|
||||||
|
|||||||
Reference in new issue
Block a user