mirror of
https://github.com/deepseek-ai/deepseek-harness.git
synced 2026-10-26 16:55:08 +00:00
Merge master into DSH 0.2.1-rc.3 synchronization branch
This commit is contained in:
commit
8a01b8360b
254 files changed
+16147
-252
No files matched your search
@@ -107,7 +107,9 @@
|
||||
"@deepseek-ai/dsh-experimental-session-search": "workspace:*",
|
||||
"@deepseek-ai/dsh-experimental-tool-worktree": "workspace:*",
|
||||
"@deepseek-ai/dsh-cua-bundle": "workspace:*",
|
||||
"@deepseek-ai/dsh-experimental-plugin-market-bundle": "workspace:*"
|
||||
"@deepseek-ai/dsh-experimental-plugin-market-bundle": "workspace:*",
|
||||
"@deepseek-ai/dsh-creation-recommendations": "workspace:*",
|
||||
"@deepseek-ai/dsh-plugin-recommendations": "workspace:*"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@deepseek-ai/dsh-skill-badge": "workspace:*",
|
||||
|
||||
@@ -0,0 +1,130 @@
|
||||
/** The completed answer offers creation through a propose_action card; choosing a location does not start it. */
|
||||
import { readFile } from 'node:fs/promises'
|
||||
import { join } from 'node:path'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
import { chromium, type Browser, type Page } from 'playwright'
|
||||
import { afterAll, beforeAll, describe, expect, it } from 'vitest'
|
||||
import {
|
||||
acknowledgeReloadConnectionLoss, assertFixtureInventory, captureStableAria, compareOrRefreshGolden,
|
||||
fixtureUserPrompts, launchWebScaffold, watchConsole, type WebScaffold,
|
||||
} from './scaffold.ts'
|
||||
import { connectFreshWorkspace, newEnglishPage } from './support.ts'
|
||||
|
||||
const directory = fileURLToPath(new URL('../../../snapshots/web/creation-recommendations', import.meta.url))
|
||||
const fixture = join(directory, 'session.v4.jsonl')
|
||||
|
||||
describe('creation recommendation after an explicit wish', () => {
|
||||
let scaffold: WebScaffold
|
||||
let browser: Browser
|
||||
let page: Page
|
||||
|
||||
beforeAll(async () => {
|
||||
scaffold = await launchWebScaffold({ replayFixture: fixture, compareReplaySession: true,
|
||||
profile: { packages: [{ dir: fileURLToPath(new URL('../../../packages/experimental/creation-recommendations', import.meta.url)), enabled: true }] },
|
||||
})
|
||||
browser = await chromium.launch()
|
||||
page = await newEnglishPage(browser)
|
||||
})
|
||||
afterAll(async () => { await browser?.close(); await scaffold?.close() })
|
||||
|
||||
it('shows one card below the answer, lets the user change location, and restores a dismissal', async () => {
|
||||
const tripwire = watchConsole(page)
|
||||
await page.setViewportSize({ width: 620, height: 900 })
|
||||
await page.goto(scaffold.authenticatedUrl, { waitUntil: 'load' })
|
||||
await connectFreshWorkspace(page, scaffold.workspaceCwd)
|
||||
const input = page.locator('[data-composer-input]').first()
|
||||
const settled = scaffold.whenTurnSettled()
|
||||
await input.fill(fixtureUserPrompts(await readFile(fixture, 'utf8'))[0]!)
|
||||
await input.press('Enter')
|
||||
await settled
|
||||
const card = page.locator('[data-action-card]')
|
||||
await card.waitFor({ state: 'visible' })
|
||||
expect(await card.count()).toBe(1)
|
||||
expect(await page.locator('[data-turn-tail] [data-action-card]').count()).toBe(1)
|
||||
const answer = page.getByText('I can create a persistent counter with increment and reset controls. Choose its location below.', { exact: true })
|
||||
const answerBox = await answer.boundingBox()
|
||||
const cardBox = await card.boundingBox()
|
||||
expect(answerBox).not.toBeNull()
|
||||
expect(cardBox!.y).toBeGreaterThanOrEqual(answerBox!.y + answerBox!.height)
|
||||
expect(await card.getByRole('button', { name: 'Create', exact: true }).isEnabled()).toBe(true)
|
||||
await compareOrRefreshGolden(join(directory, 'offered.expected.md'), await captureStableAria(page, '[data-action-card]', scaffold.workspaceCwd), scaffold.mode)
|
||||
const info = card.getByRole('button', { name: 'How creation works and token usage', exact: true })
|
||||
expect(await info.getAttribute('aria-expanded')).toBe('true')
|
||||
expect(await card.getByRole('note').innerText()).toContain('large number of tokens')
|
||||
await info.focus()
|
||||
await info.press('Space')
|
||||
expect(await card.getByRole('note').count()).toBe(0)
|
||||
const infoWarnings = tripwire.warnings.length
|
||||
await page.reload({ waitUntil: 'load' })
|
||||
await card.waitFor({ state: 'visible' })
|
||||
acknowledgeReloadConnectionLoss(tripwire, infoWarnings)
|
||||
expect(await info.getAttribute('aria-expanded')).toBe('false')
|
||||
await info.focus()
|
||||
await info.press('Enter')
|
||||
expect(await info.getAttribute('aria-expanded')).toBe('true')
|
||||
expect(await card.getByRole('note').innerText()).toContain('large number of tokens')
|
||||
expect(await card.getByRole('note').innerText()).toContain('keep chatting here')
|
||||
expect(await card.getByRole('button', { name: 'Create', exact: true }).isEnabled()).toBe(true)
|
||||
expect(await card.evaluate(element => element.scrollWidth <= element.clientWidth)).toBe(true)
|
||||
await compareOrRefreshGolden(join(directory, 'info.expected.md'), await captureStableAria(page, '[data-action-card]', scaffold.workspaceCwd), scaffold.mode)
|
||||
await info.press('Space')
|
||||
expect(await info.getAttribute('aria-expanded')).toBe('false')
|
||||
expect(await card.getByRole('note').count()).toBe(0)
|
||||
const expand = card.getByRole('button', { name: 'Show more', exact: true })
|
||||
const plan = page.locator(`[id="${await expand.getAttribute('aria-controls')}"]`)
|
||||
const compactHeight = await plan.evaluate(element => element.clientHeight)
|
||||
const previewText = await plan.innerText()
|
||||
expect(previewText.endsWith('…')).toBe(true)
|
||||
// The preview keeps about 260 Latin-letter widths before the ellipsis; a trailing space may be trimmed.
|
||||
const previewLength = Array.from(new Intl.Segmenter(undefined, { granularity: 'grapheme' }).segment(previewText)).length
|
||||
expect(previewLength).toBeGreaterThan(200)
|
||||
expect(previewLength).toBeLessThanOrEqual(261)
|
||||
await expand.click()
|
||||
expect(await plan.evaluate(element => element.clientHeight)).toBeGreaterThan(compactHeight)
|
||||
expect(await card.getByRole('button', { name: 'Create', exact: true }).isEnabled()).toBe(true)
|
||||
await compareOrRefreshGolden(join(directory, 'expanded.expected.md'), await captureStableAria(page, '[data-action-card]', scaffold.workspaceCwd), scaffold.mode)
|
||||
await card.getByRole('button', { name: 'Show less', exact: true }).click()
|
||||
const location = card.getByRole('button', { name: 'Add to: Right sidebar', exact: true })
|
||||
await location.click()
|
||||
expect(await page.getByRole('menuitem').count()).toBe(4)
|
||||
await compareOrRefreshGolden(join(directory, 'location-menu.expected.md'), await captureStableAria(page, '[role="menu"]', scaffold.workspaceCwd), scaffold.mode)
|
||||
await page.getByRole('menuitem').first().press('Escape')
|
||||
expect(await page.getByRole('menu').count()).toBe(0)
|
||||
expect(await location.evaluate(element => element === document.activeElement)).toBe(true)
|
||||
await location.click()
|
||||
await page.getByRole('menuitem', { name: /Write your own/ }).click()
|
||||
const custom = card.getByRole('textbox', { name: 'Where should it appear?', exact: true })
|
||||
expect(await card.getByRole('button', { name: 'Create', exact: true }).isEnabled()).toBe(false)
|
||||
await custom.fill('A left sidebar entry that opens a full-page calendar')
|
||||
expect(await card.getByRole('button', { name: 'Create', exact: true }).isEnabled()).toBe(true)
|
||||
await compareOrRefreshGolden(join(directory, 'custom-location.expected.md'), await captureStableAria(page, '[data-action-card]', scaffold.workspaceCwd), scaffold.mode)
|
||||
await card.getByRole('button', { name: 'Add to: Write your own', exact: true }).click()
|
||||
await page.getByRole('menuitem', { name: /Session tab/ }).click()
|
||||
expect(await card.getByRole('button', { name: 'Add to: Session tab', exact: true }).isVisible()).toBe(true)
|
||||
expect(await custom.count()).toBe(0)
|
||||
await compareOrRefreshGolden(join(directory, 'options.expected.md'), await captureStableAria(page, '[data-action-card]', scaffold.workspaceCwd), scaffold.mode)
|
||||
expect(await card.evaluate(element => element.scrollWidth <= element.clientWidth)).toBe(true)
|
||||
await card.getByRole('button', { name: 'Not now', exact: true }).click()
|
||||
await card.getByRole('status').getByText('Dismissed', { exact: true }).waitFor()
|
||||
const warnings = tripwire.warnings.length
|
||||
await page.reload({ waitUntil: 'load' })
|
||||
await card.getByRole('status').getByText('Dismissed', { exact: true }).waitFor()
|
||||
acknowledgeReloadConnectionLoss(tripwire, warnings)
|
||||
expect(await card.getByRole('button', { name: 'Create', exact: true }).count()).toBe(0)
|
||||
expect(await card.getByRole('button', { name: 'Show more', exact: true }).isVisible()).toBe(true)
|
||||
expect((await scaffold.ctx.pluginManager.listBundles()).some(bundle => bundle.name.startsWith('@dsh-local/view-'))).toBe(false)
|
||||
await compareOrRefreshGolden(join(directory, 'dismissed.expected.md'), await captureStableAria(page, '[data-action-card]', scaffold.workspaceCwd), scaffold.mode)
|
||||
const statusSettled = scaffold.whenTurnSettled()
|
||||
await input.fill(fixtureUserPrompts(await readFile(fixture, 'utf8'))[1]!)
|
||||
await input.press('Enter')
|
||||
await statusSettled
|
||||
await page.getByText('The counter proposal was dismissed. Creation never started.', { exact: true }).waitFor()
|
||||
expect(await card.count()).toBe(1)
|
||||
expect(await card.getByRole('button', { name: 'Create', exact: true }).count()).toBe(0)
|
||||
expect(tripwire.pageErrors).toEqual([])
|
||||
expect(tripwire.warnings).toEqual([])
|
||||
if (scaffold.mode === 'replay') await assertFixtureInventory(directory, [
|
||||
'session.v4.jsonl', 'offered.expected.md', 'info.expected.md', 'expanded.expected.md', 'options.expected.md', 'dismissed.expected.md', 'location-menu.expected.md', 'custom-location.expected.md', 'system-prompt.expected.md', 'tool-schemas.expected.json',
|
||||
])
|
||||
})
|
||||
})
|
||||
@@ -863,6 +863,8 @@ describe('web e2e: plugin manager', () => {
|
||||
['@deepseek-ai/dsh-experimental-voice-input-bundle', 1],
|
||||
['@deepseek-ai/dsh-experimental-plugin-market-bundle', 1],
|
||||
['@deepseek-ai/dsh-experimental-auto-review', 1],
|
||||
['@deepseek-ai/dsh-creation-recommendations', 1],
|
||||
['@deepseek-ai/dsh-plugin-recommendations', 1],
|
||||
['@deepseek-ai/dsh-experimental-inspector-profile', 1],
|
||||
['@deepseek-ai/dsh-cua-bundle', 1],
|
||||
['@deepseek-ai/dsh-experimental-tool-worktree', 1],
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
/** Replay model output through the shipped Web profile and decide its real propose_action card. */
|
||||
import { readFile } from 'node:fs/promises'
|
||||
import { join } from 'node:path'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
import { chromium, type Browser, type Page } from 'playwright'
|
||||
import { afterAll, beforeAll, describe, expect, it } from 'vitest'
|
||||
import type {} from '@deepseek-ai/dsh-plugin-manager'
|
||||
import {
|
||||
acknowledgeReloadConnectionLoss, assertFixtureInventory, captureStableAria, compareOrRefreshGolden,
|
||||
fixtureUserPrompts, launchWebScaffold, watchConsole, type WebScaffold,
|
||||
} from './scaffold.ts'
|
||||
import { connectFreshWorkspace, newEnglishPage } from './support.ts'
|
||||
|
||||
const directory = fileURLToPath(new URL('../../../snapshots/web/plugin-recommendations', import.meta.url))
|
||||
const fixture = join(directory, 'session.v4.jsonl')
|
||||
const voiceBundle = '@deepseek-ai/dsh-experimental-voice-input-bundle'
|
||||
|
||||
describe('official plugin recommendation in a conversation', () => {
|
||||
let scaffold: WebScaffold
|
||||
let browser: Browser
|
||||
let page: Page
|
||||
|
||||
beforeAll(async () => {
|
||||
scaffold = await launchWebScaffold({ replayFixture: fixture, compareReplaySession: true,
|
||||
profile: { packages: [{ dir: fileURLToPath(new URL('../../../packages/experimental/plugin-recommendations', import.meta.url)), enabled: true }] },
|
||||
})
|
||||
browser = await chromium.launch()
|
||||
page = await newEnglishPage(browser)
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
await browser?.close()
|
||||
await scaffold?.close()
|
||||
})
|
||||
|
||||
it('offers the propose_action call as one card below the answer, and reports a dismissal on the next request', async () => {
|
||||
const tripwire = watchConsole(page)
|
||||
await page.goto(scaffold.authenticatedUrl, { waitUntil: 'load' })
|
||||
await connectFreshWorkspace(page, scaffold.workspaceCwd)
|
||||
const input = page.locator('[data-composer-input]').first()
|
||||
const settled = scaffold.whenTurnSettled()
|
||||
const prompts = fixtureUserPrompts(await readFile(fixture, 'utf8'))
|
||||
await input.fill(prompts[0]!)
|
||||
await input.press('Enter')
|
||||
await settled
|
||||
const card = page.locator('[data-action-card]')
|
||||
await card.waitFor({ state: 'visible' })
|
||||
expect(await card.count()).toBe(1)
|
||||
expect(await page.locator('[data-turn-tail] [data-action-card][data-action="enable_official_plugin"]').count()).toBe(1)
|
||||
const answer = page.getByText('Voice input transcribes your recordings locally into the composer. You can enable it below.', { exact: true })
|
||||
const answerBox = await answer.boundingBox()
|
||||
const cardBox = await card.boundingBox()
|
||||
expect(answerBox).not.toBeNull()
|
||||
expect(cardBox!.y).toBeGreaterThanOrEqual(answerBox!.y + answerBox!.height)
|
||||
expect(await page.getByText('enable_official_plugin').count()).toBe(0)
|
||||
await card.getByText('Voice input', { exact: true }).waitFor()
|
||||
expect(await card.getByRole('button', { name: 'Enable', exact: true }).isEnabled()).toBe(true)
|
||||
expect((await scaffold.ctx.pluginManager.listBundles()).find(bundle => bundle.name === voiceBundle)?.enabled).toBe(false)
|
||||
await compareOrRefreshGolden(join(directory, 'offered.expected.md'), await captureStableAria(page, '[data-action-card]', scaffold.workspaceCwd), scaffold.mode)
|
||||
await page.setViewportSize({ width: 620, height: 900 })
|
||||
expect(await card.evaluate(element => element.scrollWidth <= element.clientWidth)).toBe(true)
|
||||
await card.getByRole('button', { name: 'Not now', exact: true }).click()
|
||||
await card.getByRole('status').getByText('Dismissed', { exact: true }).waitFor()
|
||||
const warnings = tripwire.warnings.length
|
||||
await page.reload({ waitUntil: 'load' })
|
||||
await card.getByRole('status').getByText('Dismissed', { exact: true }).waitFor()
|
||||
acknowledgeReloadConnectionLoss(tripwire, warnings)
|
||||
expect(await card.count()).toBe(1)
|
||||
expect(await card.getByRole('button').count()).toBe(1)
|
||||
expect((await scaffold.ctx.pluginManager.listBundles()).find(bundle => bundle.name === voiceBundle)?.enabled).toBe(false)
|
||||
await compareOrRefreshGolden(join(directory, 'dismissed.expected.md'), await captureStableAria(page, '[data-action-card]', scaffold.workspaceCwd), scaffold.mode)
|
||||
const statusSettled = scaffold.whenTurnSettled()
|
||||
await input.fill(prompts[1]!)
|
||||
await input.press('Enter')
|
||||
await statusSettled
|
||||
await page.getByText('Voice input is not enabled: you dismissed the card.', { exact: true }).waitFor()
|
||||
expect(await card.count()).toBe(1)
|
||||
await card.getByRole('button', { name: 'View details: Voice input', exact: true }).click()
|
||||
await page.locator(`[data-plugin-detail="${voiceBundle}"]`).waitFor({ state: 'visible' })
|
||||
expect((await scaffold.ctx.pluginManager.listBundles()).find(bundle => bundle.name === voiceBundle)?.enabled).toBe(false)
|
||||
expect(tripwire.pageErrors).toEqual([])
|
||||
expect(tripwire.warnings).toEqual([])
|
||||
if (scaffold.mode === 'replay') await assertFixtureInventory(directory, [
|
||||
'session.v4.jsonl', 'offered.expected.md', 'dismissed.expected.md', 'system-prompt.expected.md', 'tool-schemas.expected.json',
|
||||
])
|
||||
})
|
||||
})
|
||||
@@ -23,6 +23,8 @@
|
||||
// this client-registered project must not also hold them (one program
|
||||
// cannot see both sides of the cordis Context merges).
|
||||
"exclude": [
|
||||
"tests/creation-recommendations.e2e.ts",
|
||||
"tests/plugin-recommendations.e2e.ts",
|
||||
"tests/japanese-plugin-metadata.e2e.ts",
|
||||
"tests/additional-locales.e2e.ts",
|
||||
"tests/rich-text-quotes.e2e.ts",
|
||||
|
||||
@@ -6,5 +6,5 @@
|
||||
en: 41d772192075e133
|
||||
zh: 5ef3da69b4de1d8a
|
||||
/capability-seams-and-core-services:
|
||||
en: f2546ac3454d220d
|
||||
zh: 642a473c0405e81f
|
||||
en: 506d61dfa8c71186
|
||||
zh: 46f05c4ef2f5c322
|
||||
@@ -7,6 +7,13 @@ A service can be a core spine service, a swappable capability seam, a bundle/com
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
pkg_action_cards["action-cards"]
|
||||
svc_actionCards["ctx.actionCards<br/>Optional action cards"]
|
||||
pkg_creation_recommendations["creation-recommendations"]
|
||||
pkg_client_ui_action_cards["client-ui-action-cards"]
|
||||
pkg_plugin_recommendations["plugin-recommendations"]
|
||||
svc_pluginRecommendations["ctx.pluginRecommendations<br/>Explicit-need plugin recommendations"]
|
||||
pkg_client_ui_plugin_recommendations["client-ui-plugin-recommendations"]
|
||||
pkg_headless["headless"]
|
||||
svc_headlessStartup["ctx.headlessStartup<br/>Headless invocation options"]
|
||||
pkg_experimental_client_ui_cot_translation["experimental-client-ui-cot-translation"]
|
||||
@@ -298,6 +305,7 @@ flowchart LR
|
||||
pkg_cordis_host_runner["cordis-host-runner"]
|
||||
svc_dynamicCordisRunner["ctx.dynamicCordisRunner<br/>Dynamic Cordis package host runner"]
|
||||
svc_cordisInspect["ctx.cordisInspect<br/>Dynamic Cordis inspect registry"]
|
||||
pkg_action_cards --> svc_actionCards
|
||||
pkg_agent --> svc_agents
|
||||
pkg_agent_default_model --> svc_agentDefaultModel
|
||||
pkg_agent_loop --> svc_agentLoop
|
||||
@@ -388,6 +396,7 @@ flowchart LR
|
||||
pkg_plugin_manager --> svc_pluginManager
|
||||
pkg_plugin_market --> svc_pluginMarket
|
||||
pkg_plugin_package_inventory_deepseek --> svc_deepseekLlmApiExtensions
|
||||
pkg_plugin_recommendations --> svc_pluginRecommendations
|
||||
pkg_ptc_runtime --> svc_ptcRuntime
|
||||
pkg_ptc_runtime_node --> svc_ptcRuntime
|
||||
pkg_pwsh_local --> svc_shell
|
||||
@@ -457,6 +466,8 @@ flowchart LR
|
||||
pkg_working_directory --> svc_workingDirectory
|
||||
pkg_workspace --> svc_workspaceRegistry
|
||||
pkg_workspace_changes --> svc_workspaceChanges
|
||||
svc_actionCards --> pkg_client_ui_action_cards
|
||||
svc_actionCards --> pkg_creation_recommendations
|
||||
svc_agentDefaultModel --> pkg_api_session_controller
|
||||
svc_agentDefaultModel --> pkg_headless
|
||||
svc_agentLoop --> pkg_base
|
||||
@@ -515,6 +526,7 @@ flowchart LR
|
||||
svc_pluginManager --> pkg_ui_settings_plugin_inventory
|
||||
svc_pluginMarket --> pkg_client_ui_plugin_market
|
||||
svc_pluginMarket --> pkg_plugin_market
|
||||
svc_pluginRecommendations --> pkg_client_ui_plugin_recommendations
|
||||
svc_pluginRegistryProbe --> pkg_client_ui_plugin_manager
|
||||
svc_profileContext --> pkg_plugin_manager
|
||||
svc_ptcRuntime --> pkg_tool_executor_ptc
|
||||
@@ -619,6 +631,8 @@ flowchart LR
|
||||
|
||||
| ctx key | Role | Owner | Implementations | Direct consumers | Companion plugins | Note |
|
||||
| --- | --- | --- | --- | --- | --- | --- |
|
||||
| `ctx.actionCards` | `service` | [`action-cards`](../packages/experimental/action-cards) | - | [`creation-recommendations`](../packages/experimental/creation-recommendations), [`client-ui-action-cards`](../packages/experimental/client-ui-action-cards) | - | Owns the card tool, card state, user actions and status notices; card kinds register their actions and handlers. |
|
||||
| `ctx.pluginRecommendations` | `service` | [`plugin-recommendations`](../packages/experimental/plugin-recommendations) | - | [`client-ui-plugin-recommendations`](../packages/experimental/client-ui-plugin-recommendations) | - | Reads the current catalog text of an official plugin card and enables the plugin through the profile plugin manager after a click. |
|
||||
| `ctx.headlessStartup` | `core` | [`headless`](../packages/bundle/headless) | - | [`headless`](../packages/bundle/headless) | - | Supplies parsed task and run options to the headless runner and its sandbox-policy configuration. |
|
||||
| `ctx.cotTranslation` | `service` | [`experimental-client-ui-cot-translation`](../packages/experimental/client-ui-cot-translation) | - | - | - | Serves reasoning translations, reuses saved results, and joins ordinary Session activation for uncached inactive Sessions. |
|
||||
| `ctx.translator` | `service` | [`experimental-translator`](../packages/experimental/translator) | - | [`experimental-client-ui-cot-translation`](../packages/experimental/client-ui-cot-translation) | - | Resolves Google or Bing requests and retains shared experimental records through the active Session writer. |
|
||||
|
||||
@@ -9,6 +9,13 @@
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
pkg_action_cards["action-cards"]
|
||||
svc_actionCards["ctx.actionCards<br/>Optional action cards"]
|
||||
pkg_creation_recommendations["creation-recommendations"]
|
||||
pkg_client_ui_action_cards["client-ui-action-cards"]
|
||||
pkg_plugin_recommendations["plugin-recommendations"]
|
||||
svc_pluginRecommendations["ctx.pluginRecommendations<br/>Explicit-need plugin recommendations"]
|
||||
pkg_client_ui_plugin_recommendations["client-ui-plugin-recommendations"]
|
||||
pkg_headless["headless"]
|
||||
svc_headlessStartup["ctx.headlessStartup<br/>Headless invocation options"]
|
||||
pkg_experimental_client_ui_cot_translation["experimental-client-ui-cot-translation"]
|
||||
@@ -300,6 +307,7 @@ flowchart LR
|
||||
pkg_cordis_host_runner["cordis-host-runner"]
|
||||
svc_dynamicCordisRunner["ctx.dynamicCordisRunner<br/>Dynamic Cordis package host runner"]
|
||||
svc_cordisInspect["ctx.cordisInspect<br/>Dynamic Cordis inspect registry"]
|
||||
pkg_action_cards --> svc_actionCards
|
||||
pkg_agent --> svc_agents
|
||||
pkg_agent_default_model --> svc_agentDefaultModel
|
||||
pkg_agent_loop --> svc_agentLoop
|
||||
@@ -390,6 +398,7 @@ flowchart LR
|
||||
pkg_plugin_manager --> svc_pluginManager
|
||||
pkg_plugin_market --> svc_pluginMarket
|
||||
pkg_plugin_package_inventory_deepseek --> svc_deepseekLlmApiExtensions
|
||||
pkg_plugin_recommendations --> svc_pluginRecommendations
|
||||
pkg_ptc_runtime --> svc_ptcRuntime
|
||||
pkg_ptc_runtime_node --> svc_ptcRuntime
|
||||
pkg_pwsh_local --> svc_shell
|
||||
@@ -459,6 +468,8 @@ flowchart LR
|
||||
pkg_working_directory --> svc_workingDirectory
|
||||
pkg_workspace --> svc_workspaceRegistry
|
||||
pkg_workspace_changes --> svc_workspaceChanges
|
||||
svc_actionCards --> pkg_client_ui_action_cards
|
||||
svc_actionCards --> pkg_creation_recommendations
|
||||
svc_agentDefaultModel --> pkg_api_session_controller
|
||||
svc_agentDefaultModel --> pkg_headless
|
||||
svc_agentLoop --> pkg_base
|
||||
@@ -517,6 +528,7 @@ flowchart LR
|
||||
svc_pluginManager --> pkg_ui_settings_plugin_inventory
|
||||
svc_pluginMarket --> pkg_client_ui_plugin_market
|
||||
svc_pluginMarket --> pkg_plugin_market
|
||||
svc_pluginRecommendations --> pkg_client_ui_plugin_recommendations
|
||||
svc_pluginRegistryProbe --> pkg_client_ui_plugin_manager
|
||||
svc_profileContext --> pkg_plugin_manager
|
||||
svc_ptcRuntime --> pkg_tool_executor_ptc
|
||||
@@ -621,6 +633,8 @@ flowchart LR
|
||||
|
||||
| ctx 键 | 角色 | 所属包 | 实现 | 直接消费方 | 配套插件 | 说明 |
|
||||
| --- | --- | --- | --- | --- | --- | --- |
|
||||
| `ctx.actionCards` | `service` | [`action-cards`](../packages/experimental/action-cards) | - | [`creation-recommendations`](../packages/experimental/creation-recommendations), [`client-ui-action-cards`](../packages/experimental/client-ui-action-cards) | - | 负责卡片工具、卡片状态、用户操作和状态通知;各卡片种类注册自己的动作和处理器。 |
|
||||
| `ctx.pluginRecommendations` | `service` | [`plugin-recommendations`](../packages/experimental/plugin-recommendations) | - | [`client-ui-plugin-recommendations`](../packages/experimental/client-ui-plugin-recommendations) | - | 读取官方插件卡片的当前目录文本,并在用户点击后通过配置插件管理器启用该插件。 |
|
||||
| `ctx.headlessStartup` | `core` | [`headless`](../packages/bundle/headless) | - | [`headless`](../packages/bundle/headless) | - | 将解析后的任务和运行选项提供给无界面运行器及其 sandbox-policy 配置。 |
|
||||
| `ctx.cotTranslation` | `service` | [`experimental-client-ui-cot-translation`](../packages/experimental/client-ui-cot-translation) | - | - | - | 为展开的思考内容提供有界的 Session 翻译请求,不改变模型可见历史。 |
|
||||
| `ctx.translator` | `service` | [`experimental-translator`](../packages/experimental/translator) | - | [`experimental-client-ui-cot-translation`](../packages/experimental/client-ui-cot-translation) | - | 解析 Google 或 Bing 请求,并可选保留统一的实验性 Session 记录。 |
|
||||
|
||||
@@ -33,6 +33,21 @@ export interface AcpConfig {
|
||||
```
|
||||
<!-- END GENERATED config-catalog:@deepseek-ai/dsh-acp -->
|
||||
|
||||
<!-- BEGIN GENERATED config-catalog:@deepseek-ai/dsh-action-cards -->
|
||||
<a id="deepseek-aidsh-action-cards"></a>
|
||||
|
||||
## `@deepseek-ai/dsh-action-cards`
|
||||
|
||||
- `inject`: `tools` · `agents` · `sessionProjections` · `remoteAccess`
|
||||
- `refs`: `z` (`zod`)
|
||||
- `source`: [`packages/experimental/action-cards/src/index.ts:23`](../packages/experimental/action-cards/src/index.ts)
|
||||
|
||||
```ts config-catalog
|
||||
/** Validated card limits after schema defaults. */
|
||||
export type Config = z.infer<typeof Config>
|
||||
```
|
||||
<!-- END GENERATED config-catalog:@deepseek-ai/dsh-action-cards -->
|
||||
|
||||
<!-- BEGIN GENERATED config-catalog:@deepseek-ai/dsh-agent-default-model -->
|
||||
<a id="deepseek-aidsh-agent-default-model"></a>
|
||||
|
||||
@@ -4689,6 +4704,7 @@ These load from a `cordis.yml` entry with no `config:` block; they declare no co
|
||||
| `@deepseek-ai/dsh-client-locale` | — | [`packages/client/locale/src/index.ts`](../packages/client/locale/src/index.ts) |
|
||||
| `@deepseek-ai/dsh-client-modules` | `loader` | [`packages/client/modules/src/index.ts`](../packages/client/modules/src/index.ts) |
|
||||
| `@deepseek-ai/dsh-client-resources` | — | [`packages/client/resources/src/index.ts`](../packages/client/resources/src/index.ts) |
|
||||
| `@deepseek-ai/dsh-client-ui-action-cards` | — | [`packages/experimental/client-ui-action-cards/src/index.ts`](../packages/experimental/client-ui-action-cards/src/index.ts) |
|
||||
| `@deepseek-ai/dsh-client-ui-agent-preset` | — | [`packages/client/ui-agent-preset/src/index.ts`](../packages/client/ui-agent-preset/src/index.ts) |
|
||||
| `@deepseek-ai/dsh-client-ui-approval` | — | [`packages/client/ui-approval/src/index.ts`](../packages/client/ui-approval/src/index.ts) |
|
||||
| `@deepseek-ai/dsh-client-ui-attachment` | — | [`packages/client/ui-attachment/src/index.ts`](../packages/client/ui-attachment/src/index.ts) |
|
||||
@@ -4697,6 +4713,7 @@ These load from a `cordis.yml` entry with no `config:` block; they declare no co
|
||||
| `@deepseek-ai/dsh-client-ui-commands` | — | [`packages/client/ui-commands/src/index.ts`](../packages/client/ui-commands/src/index.ts) |
|
||||
| `@deepseek-ai/dsh-client-ui-conversation` | — | [`packages/client/ui-conversation/src/index.ts`](../packages/client/ui-conversation/src/index.ts) |
|
||||
| `@deepseek-ai/dsh-client-ui-cordis` | — | [`packages/extensions/ui-cordis/src/index.ts`](../packages/extensions/ui-cordis/src/index.ts) |
|
||||
| `@deepseek-ai/dsh-client-ui-creation-recommendations` | — | [`packages/experimental/client-ui-creation-recommendations/src/index.ts`](../packages/experimental/client-ui-creation-recommendations/src/index.ts) |
|
||||
| `@deepseek-ai/dsh-client-ui-deepseek-model-label-1017` | — | [`packages/client/ui-deepseek-model-label-1017/src/index.ts`](../packages/client/ui-deepseek-model-label-1017/src/index.ts) |
|
||||
| `@deepseek-ai/dsh-client-ui-deliverables` | `connection` · `sessionQuery` · `sessionController` · `workspaceFiles` · `fs` · `sandboxPolicy` · `workspaceChanges` | [`packages/client/ui-deliverables/src/index.ts`](../packages/client/ui-deliverables/src/index.ts) |
|
||||
| `@deepseek-ai/dsh-client-ui-directory-picker-browse` | — | [`packages/client/ui-directory-picker-browse/src/index.ts`](../packages/client/ui-directory-picker-browse/src/index.ts) |
|
||||
@@ -4713,6 +4730,7 @@ These load from a `cordis.yml` entry with no `config:` block; they declare no co
|
||||
| `@deepseek-ai/dsh-client-ui-permission-presets` | — | [`packages/client/ui-permission-presets/src/index.ts`](../packages/client/ui-permission-presets/src/index.ts) |
|
||||
| `@deepseek-ai/dsh-client-ui-plan` | — | [`packages/client/ui-plan/src/index.ts`](../packages/client/ui-plan/src/index.ts) |
|
||||
| `@deepseek-ai/dsh-client-ui-plugin-market` | — | [`packages/client/ui-plugin-market/src/index.ts`](../packages/client/ui-plugin-market/src/index.ts) |
|
||||
| `@deepseek-ai/dsh-client-ui-plugin-recommendations` | — | [`packages/experimental/client-ui-plugin-recommendations/src/index.ts`](../packages/experimental/client-ui-plugin-recommendations/src/index.ts) |
|
||||
| `@deepseek-ai/dsh-client-ui-reference` | — | [`packages/client/ui-reference/src/index.ts`](../packages/client/ui-reference/src/index.ts) |
|
||||
| `@deepseek-ai/dsh-client-ui-renderer` | — | [`packages/client/ui-renderer/src/index.ts`](../packages/client/ui-renderer/src/index.ts) |
|
||||
| `@deepseek-ai/dsh-client-ui-schedule` | — | [`packages/client/ui-schedule/src/index.ts`](../packages/client/ui-schedule/src/index.ts) |
|
||||
@@ -4748,6 +4766,7 @@ These load from a `cordis.yml` entry with no `config:` block; they declare no co
|
||||
| `@deepseek-ai/dsh-computer-use` | — | [`packages/computer-use/computer-use/src/index.ts`](../packages/computer-use/computer-use/src/index.ts) |
|
||||
| `@deepseek-ai/dsh-config-editor` | `loader` · `profileContext` | [`packages/boot/config-editor/src/index.ts`](../packages/boot/config-editor/src/index.ts) |
|
||||
| `@deepseek-ai/dsh-cordis-client-runner` | — | [`packages/extensions/cordis-client-runner/src/index.ts`](../packages/extensions/cordis-client-runner/src/index.ts) |
|
||||
| `@deepseek-ai/dsh-creation-recommendations` | `tools` · `pluginManager` · `agents` · `subagents` · `profileContext` · `skills` · `actionCards` | [`packages/experimental/creation-recommendations/src/index.ts`](../packages/experimental/creation-recommendations/src/index.ts) |
|
||||
| `@deepseek-ai/dsh-cua` | — | [`packages/experimental/cua/src/index.ts`](../packages/experimental/cua/src/index.ts) |
|
||||
| `@deepseek-ai/dsh-deepseek-llm-api-extensions` | — | [`packages/llm/deepseek-llm-api-extensions/src/index.ts`](../packages/llm/deepseek-llm-api-extensions/src/index.ts) |
|
||||
| `@deepseek-ai/dsh-deliverable-file-references` | `systemPrompt` | [`packages/deliverables/deliverable-file-references/src/index.ts`](../packages/deliverables/deliverable-file-references/src/index.ts) |
|
||||
@@ -4770,6 +4789,7 @@ These load from a `cordis.yml` entry with no `config:` block; they declare no co
|
||||
| `@deepseek-ai/dsh-mcp-resources` | `tools` | [`packages/mcp/mcp-resources/src/index.ts`](../packages/mcp/mcp-resources/src/index.ts) |
|
||||
| `@deepseek-ai/dsh-message-quotes` | — | [`packages/session/message-quotes/src/index.ts`](../packages/session/message-quotes/src/index.ts) |
|
||||
| `@deepseek-ai/dsh-otel` | — | [`packages/telemetry/otel/src/index.ts`](../packages/telemetry/otel/src/index.ts) |
|
||||
| `@deepseek-ai/dsh-plugin-recommendations` | `pluginManager` · `agents` · `skills` · `actionCards` | [`packages/experimental/plugin-recommendations/src/index.ts`](../packages/experimental/plugin-recommendations/src/index.ts) |
|
||||
| `@deepseek-ai/dsh-sandbox-ssh` | `ssh` | [`packages/ssh/sandbox-ssh/src/index.ts`](../packages/ssh/sandbox-ssh/src/index.ts) |
|
||||
| `@deepseek-ai/dsh-session` | — | [`packages/core/session/src/index.ts`](../packages/core/session/src/index.ts) |
|
||||
| `@deepseek-ai/dsh-session-checkpoint-policy` | `llm` · `sessionPersistence` · `sessions` · `tools` | [`packages/session/session-checkpoint-policy/src/index.ts`](../packages/session/session-checkpoint-policy/src/index.ts) |
|
||||
|
||||
@@ -35,6 +35,21 @@ export interface AcpConfig {
|
||||
```
|
||||
<!-- END GENERATED config-catalog:@deepseek-ai/dsh-acp -->
|
||||
|
||||
<!-- BEGIN GENERATED config-catalog:@deepseek-ai/dsh-action-cards -->
|
||||
<a id="deepseek-aidsh-action-cards"></a>
|
||||
|
||||
## `@deepseek-ai/dsh-action-cards`
|
||||
|
||||
- `inject`: `tools` · `agents` · `sessionProjections` · `remoteAccess`
|
||||
- `refs`: `z` (`zod`)
|
||||
- `source`: [`packages/experimental/action-cards/src/index.ts:23`](../packages/experimental/action-cards/src/index.ts)
|
||||
|
||||
```ts config-catalog
|
||||
/** Validated card limits after schema defaults. */
|
||||
export type Config = z.infer<typeof Config>
|
||||
```
|
||||
<!-- END GENERATED config-catalog:@deepseek-ai/dsh-action-cards -->
|
||||
|
||||
<!-- BEGIN GENERATED config-catalog:@deepseek-ai/dsh-agent-default-model -->
|
||||
<a id="deepseek-aidsh-agent-default-model"></a>
|
||||
|
||||
@@ -4691,6 +4706,7 @@ export interface Config {
|
||||
| `@deepseek-ai/dsh-client-locale` | — | [`packages/client/locale/src/index.ts`](../packages/client/locale/src/index.ts) |
|
||||
| `@deepseek-ai/dsh-client-modules` | `loader` | [`packages/client/modules/src/index.ts`](../packages/client/modules/src/index.ts) |
|
||||
| `@deepseek-ai/dsh-client-resources` | — | [`packages/client/resources/src/index.ts`](../packages/client/resources/src/index.ts) |
|
||||
| `@deepseek-ai/dsh-client-ui-action-cards` | — | [`packages/experimental/client-ui-action-cards/src/index.ts`](../packages/experimental/client-ui-action-cards/src/index.ts) |
|
||||
| `@deepseek-ai/dsh-client-ui-agent-preset` | — | [`packages/client/ui-agent-preset/src/index.ts`](../packages/client/ui-agent-preset/src/index.ts) |
|
||||
| `@deepseek-ai/dsh-client-ui-approval` | — | [`packages/client/ui-approval/src/index.ts`](../packages/client/ui-approval/src/index.ts) |
|
||||
| `@deepseek-ai/dsh-client-ui-attachment` | — | [`packages/client/ui-attachment/src/index.ts`](../packages/client/ui-attachment/src/index.ts) |
|
||||
@@ -4699,6 +4715,7 @@ export interface Config {
|
||||
| `@deepseek-ai/dsh-client-ui-commands` | — | [`packages/client/ui-commands/src/index.ts`](../packages/client/ui-commands/src/index.ts) |
|
||||
| `@deepseek-ai/dsh-client-ui-conversation` | — | [`packages/client/ui-conversation/src/index.ts`](../packages/client/ui-conversation/src/index.ts) |
|
||||
| `@deepseek-ai/dsh-client-ui-cordis` | — | [`packages/extensions/ui-cordis/src/index.ts`](../packages/extensions/ui-cordis/src/index.ts) |
|
||||
| `@deepseek-ai/dsh-client-ui-creation-recommendations` | — | [`packages/experimental/client-ui-creation-recommendations/src/index.ts`](../packages/experimental/client-ui-creation-recommendations/src/index.ts) |
|
||||
| `@deepseek-ai/dsh-client-ui-deepseek-model-label-1017` | — | [`packages/client/ui-deepseek-model-label-1017/src/index.ts`](../packages/client/ui-deepseek-model-label-1017/src/index.ts) |
|
||||
| `@deepseek-ai/dsh-client-ui-deliverables` | `connection` · `sessionQuery` · `sessionController` · `workspaceFiles` · `fs` · `sandboxPolicy` · `workspaceChanges` | [`packages/client/ui-deliverables/src/index.ts`](../packages/client/ui-deliverables/src/index.ts) |
|
||||
| `@deepseek-ai/dsh-client-ui-directory-picker-browse` | — | [`packages/client/ui-directory-picker-browse/src/index.ts`](../packages/client/ui-directory-picker-browse/src/index.ts) |
|
||||
@@ -4715,6 +4732,7 @@ export interface Config {
|
||||
| `@deepseek-ai/dsh-client-ui-permission-presets` | — | [`packages/client/ui-permission-presets/src/index.ts`](../packages/client/ui-permission-presets/src/index.ts) |
|
||||
| `@deepseek-ai/dsh-client-ui-plan` | — | [`packages/client/ui-plan/src/index.ts`](../packages/client/ui-plan/src/index.ts) |
|
||||
| `@deepseek-ai/dsh-client-ui-plugin-market` | — | [`packages/client/ui-plugin-market/src/index.ts`](../packages/client/ui-plugin-market/src/index.ts) |
|
||||
| `@deepseek-ai/dsh-client-ui-plugin-recommendations` | — | [`packages/experimental/client-ui-plugin-recommendations/src/index.ts`](../packages/experimental/client-ui-plugin-recommendations/src/index.ts) |
|
||||
| `@deepseek-ai/dsh-client-ui-reference` | — | [`packages/client/ui-reference/src/index.ts`](../packages/client/ui-reference/src/index.ts) |
|
||||
| `@deepseek-ai/dsh-client-ui-renderer` | — | [`packages/client/ui-renderer/src/index.ts`](../packages/client/ui-renderer/src/index.ts) |
|
||||
| `@deepseek-ai/dsh-client-ui-schedule` | — | [`packages/client/ui-schedule/src/index.ts`](../packages/client/ui-schedule/src/index.ts) |
|
||||
@@ -4750,6 +4768,7 @@ export interface Config {
|
||||
| `@deepseek-ai/dsh-computer-use` | — | [`packages/computer-use/computer-use/src/index.ts`](../packages/computer-use/computer-use/src/index.ts) |
|
||||
| `@deepseek-ai/dsh-config-editor` | `loader` · `profileContext` | [`packages/boot/config-editor/src/index.ts`](../packages/boot/config-editor/src/index.ts) |
|
||||
| `@deepseek-ai/dsh-cordis-client-runner` | — | [`packages/extensions/cordis-client-runner/src/index.ts`](../packages/extensions/cordis-client-runner/src/index.ts) |
|
||||
| `@deepseek-ai/dsh-creation-recommendations` | `tools` · `pluginManager` · `agents` · `subagents` · `profileContext` · `skills` · `actionCards` | [`packages/experimental/creation-recommendations/src/index.ts`](../packages/experimental/creation-recommendations/src/index.ts) |
|
||||
| `@deepseek-ai/dsh-cua` | — | [`packages/experimental/cua/src/index.ts`](../packages/experimental/cua/src/index.ts) |
|
||||
| `@deepseek-ai/dsh-deepseek-llm-api-extensions` | — | [`packages/llm/deepseek-llm-api-extensions/src/index.ts`](../packages/llm/deepseek-llm-api-extensions/src/index.ts) |
|
||||
| `@deepseek-ai/dsh-deliverable-file-references` | `systemPrompt` | [`packages/deliverables/deliverable-file-references/src/index.ts`](../packages/deliverables/deliverable-file-references/src/index.ts) |
|
||||
@@ -4772,6 +4791,7 @@ export interface Config {
|
||||
| `@deepseek-ai/dsh-mcp-resources` | `tools` | [`packages/mcp/mcp-resources/src/index.ts`](../packages/mcp/mcp-resources/src/index.ts) |
|
||||
| `@deepseek-ai/dsh-message-quotes` | — | [`packages/session/message-quotes/src/index.ts`](../packages/session/message-quotes/src/index.ts) |
|
||||
| `@deepseek-ai/dsh-otel` | — | [`packages/telemetry/otel/src/index.ts`](../packages/telemetry/otel/src/index.ts) |
|
||||
| `@deepseek-ai/dsh-plugin-recommendations` | `pluginManager` · `agents` · `skills` · `actionCards` | [`packages/experimental/plugin-recommendations/src/index.ts`](../packages/experimental/plugin-recommendations/src/index.ts) |
|
||||
| `@deepseek-ai/dsh-sandbox-ssh` | `ssh` | [`packages/ssh/sandbox-ssh/src/index.ts`](../packages/ssh/sandbox-ssh/src/index.ts) |
|
||||
| `@deepseek-ai/dsh-session` | — | [`packages/core/session/src/index.ts`](../packages/core/session/src/index.ts) |
|
||||
| `@deepseek-ai/dsh-session-checkpoint-policy` | `llm` · `sessionPersistence` · `sessions` · `tools` | [`packages/session/session-checkpoint-policy/src/index.ts`](../packages/session/session-checkpoint-policy/src/index.ts) |
|
||||
|
||||
@@ -11,13 +11,13 @@ This matrix shows which packages dispatch each harness-owned event and which pac
|
||||
| `agent-loop/config-start-failed` | `emit` | [`packages/core/agent-loop/src/index.ts:199`](../packages/core/agent-loop/src/index.ts) | [`agent-loop`](../packages/core/agent-loop) (`events.dispatch`) | - |
|
||||
| `agent-preset/selected` | `emit` | [`packages/preset/agent-preset-registry/src/types.ts:66`](../packages/preset/agent-preset-registry/src/types.ts) | [`agent-preset-registry`](../packages/preset/agent-preset-registry) (`emit`) | [`cua`](../packages/experimental/cua), `remotes` |
|
||||
| `agent/assistant-stream` | `emit` | [`packages/core/agent/src/runtime-types.ts:399`](../packages/core/agent/src/runtime-types.ts) | [`agent-loop`](../packages/core/agent-loop) (`emit`) | [`headless`](../packages/bundle/headless), `session-controller` |
|
||||
| `agent/created` | `serial` | [`packages/core/agent/src/runtime-types.ts:290`](../packages/core/agent/src/runtime-types.ts) | [`agent`](../packages/core/agent) (`serial`) | `agent-team`, `browser-use-runtime`, `claude-code-mods`, [`cua`](../packages/experimental/cua), [`file-reference-local`](../packages/context/file-reference-local), [`goal`](../packages/goal/goal), [`goal-round-driver`](../packages/goal/goal-round-driver), [`hooks-claude-code`](../packages/experimental/hooks-claude-code), [`hooks-codex`](../packages/experimental/hooks-codex), [`loader-smoke`](../packages/test-support/loader-smoke), [`permission-presets`](../packages/interaction/permission-presets), `session-controller`, `tool-agent-team`, [`tool-subagent`](../packages/subagent/tool-subagent) |
|
||||
| `agent/disposed` | `emit` | [`packages/core/agent/src/runtime-types.ts:299`](../packages/core/agent/src/runtime-types.ts) | [`agent`](../packages/core/agent) (`events.dispatch`) | [`agent-loop`](../packages/core/agent-loop), `claude-code-mods`, [`file-reference-local`](../packages/context/file-reference-local), [`goal-round-driver`](../packages/goal/goal-round-driver), `session-controller`, [`subagent`](../packages/subagent/subagent), `tool-agent-team`, [`tool-subagent`](../packages/subagent/tool-subagent) |
|
||||
| `agent/created` | `serial` | [`packages/core/agent/src/runtime-types.ts:290`](../packages/core/agent/src/runtime-types.ts) | [`agent`](../packages/core/agent) (`serial`) | `agent-team`, `browser-use-runtime`, `claude-code-mods`, [`creation-recommendations`](../packages/experimental/creation-recommendations), [`cua`](../packages/experimental/cua), [`file-reference-local`](../packages/context/file-reference-local), [`goal`](../packages/goal/goal), [`goal-round-driver`](../packages/goal/goal-round-driver), [`hooks-claude-code`](../packages/experimental/hooks-claude-code), [`hooks-codex`](../packages/experimental/hooks-codex), [`loader-smoke`](../packages/test-support/loader-smoke), [`permission-presets`](../packages/interaction/permission-presets), `session-controller`, `tool-agent-team`, [`tool-subagent`](../packages/subagent/tool-subagent) |
|
||||
| `agent/disposed` | `emit` | [`packages/core/agent/src/runtime-types.ts:299`](../packages/core/agent/src/runtime-types.ts) | [`agent`](../packages/core/agent) (`events.dispatch`) | [`action-cards`](../packages/experimental/action-cards), [`agent-loop`](../packages/core/agent-loop), `claude-code-mods`, [`creation-recommendations`](../packages/experimental/creation-recommendations), [`file-reference-local`](../packages/context/file-reference-local), [`goal-round-driver`](../packages/goal/goal-round-driver), `session-controller`, [`subagent`](../packages/subagent/subagent), `tool-agent-team`, [`tool-subagent`](../packages/subagent/tool-subagent) |
|
||||
| `agent/error` | `emit` | [`packages/core/agent/src/runtime-types.ts:429`](../packages/core/agent/src/runtime-types.ts) | [`agent-loop`](../packages/core/agent-loop) (`emit`) | [`acp`](../packages/acp/acp), [`deepseek-account`](../packages/credentials/deepseek-account), [`goal-round-driver`](../packages/goal/goal-round-driver), [`headless`](../packages/bundle/headless), `server`, `session-controller`, [`session-telemetry`](../packages/session/session-telemetry), [`subagent`](../packages/subagent/subagent) |
|
||||
| `agent/inbox/claimed` | `emit` | [`packages/core/agent/src/runtime-types.ts:328`](../packages/core/agent/src/runtime-types.ts) | [`agent-loop`](../packages/core/agent-loop) (`emit`) | [`acp`](../packages/acp/acp), [`goal-round-driver`](../packages/goal/goal-round-driver), [`subagent`](../packages/subagent/subagent), [`tool-jobs`](../packages/jobs/tool-jobs), [`user-questions`](../packages/interaction/user-questions) |
|
||||
| `agent/inbox/discarded` | `emit` | [`packages/core/agent/src/runtime-types.ts:336`](../packages/core/agent/src/runtime-types.ts) | [`agent-loop`](../packages/core/agent-loop) (`emit`) | [`goal-round-driver`](../packages/goal/goal-round-driver), [`subagent`](../packages/subagent/subagent), [`user-questions`](../packages/interaction/user-questions) |
|
||||
| `agent/inbox/inserted` | `emit` | [`packages/core/agent/src/runtime-types.ts:317`](../packages/core/agent/src/runtime-types.ts) | [`agent-loop`](../packages/core/agent-loop) (`emit`) | [`goal-round-driver`](../packages/goal/goal-round-driver), [`subagent`](../packages/subagent/subagent), [`tool-jobs`](../packages/jobs/tool-jobs) |
|
||||
| `agent/pre-step` | `waterfall` | [`packages/core/agent/src/runtime-types.ts:350`](../packages/core/agent/src/runtime-types.ts) | [`agent-loop`](../packages/core/agent-loop) (`waterfall`) | [`agent`](../packages/core/agent), [`agent-instructions`](../packages/context/agent-instructions), `claude-code-mods`, [`compaction-basic`](../packages/compaction/compaction-basic), [`goal-round-driver`](../packages/goal/goal-round-driver), [`hooks-claude-code`](../packages/experimental/hooks-claude-code), [`hooks-codex`](../packages/experimental/hooks-codex), [`plan-mode`](../packages/plan/plan-mode), [`repeat-tool-reminder`](../packages/guard/repeat-tool-reminder), [`session-checkpoint-policy`](../packages/session/session-checkpoint-policy), `session-controller`, [`session-reference`](../packages/context/session-reference), [`time-context`](../packages/context/time-context), [`tmux-context`](../packages/context/tmux-context), [`tool-skill`](../packages/skill/tool-skill) |
|
||||
| `agent/pre-step` | `waterfall` | [`packages/core/agent/src/runtime-types.ts:350`](../packages/core/agent/src/runtime-types.ts) | [`agent-loop`](../packages/core/agent-loop) (`waterfall`) | [`action-cards`](../packages/experimental/action-cards), [`agent`](../packages/core/agent), [`agent-instructions`](../packages/context/agent-instructions), `claude-code-mods`, [`compaction-basic`](../packages/compaction/compaction-basic), [`goal-round-driver`](../packages/goal/goal-round-driver), [`hooks-claude-code`](../packages/experimental/hooks-claude-code), [`hooks-codex`](../packages/experimental/hooks-codex), [`plan-mode`](../packages/plan/plan-mode), [`repeat-tool-reminder`](../packages/guard/repeat-tool-reminder), [`session-checkpoint-policy`](../packages/session/session-checkpoint-policy), `session-controller`, [`session-reference`](../packages/context/session-reference), [`time-context`](../packages/context/time-context), [`tmux-context`](../packages/context/tmux-context), [`tool-skill`](../packages/skill/tool-skill) |
|
||||
| `agent/request-error` | `waterfall` | [`packages/core/agent/src/runtime-types.ts:389`](../packages/core/agent/src/runtime-types.ts) | [`agent-loop`](../packages/core/agent-loop) (`waterfall`) | [`compaction-basic`](../packages/compaction/compaction-basic), [`compaction-image-offload`](../packages/compaction/compaction-image-offload), [`llm-retry`](../packages/llm/llm-retry) |
|
||||
| `agent/status` | `emit` | [`packages/core/agent/src/runtime-types.ts:309`](../packages/core/agent/src/runtime-types.ts) | [`agent-loop`](../packages/core/agent-loop) (`emit`) | [`acp`](../packages/acp/acp), `agent-team`, [`compaction-basic`](../packages/compaction/compaction-basic), [`goal-round-driver`](../packages/goal/goal-round-driver), `server`, `session-controller` |
|
||||
| `agent/turn-stopping` | `serial` | [`packages/core/agent/src/runtime-types.ts:417`](../packages/core/agent/src/runtime-types.ts) | [`agent-loop`](../packages/core/agent-loop) (`serial`) | [`hooks-claude-code`](../packages/experimental/hooks-claude-code), [`hooks-codex`](../packages/experimental/hooks-codex), [`workspace-changes`](../packages/deliverables/workspace-changes) |
|
||||
@@ -80,7 +80,7 @@ This matrix shows which packages dispatch each harness-owned event and which pac
|
||||
| `tools/post-execute` | `waterfall` | [`packages/core/tools/src/events.ts:41`](../packages/core/tools/src/events.ts) | [`tools`](../packages/core/tools) (`waterfall`) | `claude-code-mods`, [`hooks-claude-code`](../packages/experimental/hooks-claude-code), [`hooks-codex`](../packages/experimental/hooks-codex), [`repeat-tool-reminder`](../packages/guard/repeat-tool-reminder), [`spill-policy`](../packages/spill/spill-policy), [`tool-fs-search`](../packages/fs/tool-fs-search) |
|
||||
| `tools/pre-execute` | `waterfall` | [`packages/core/tools/src/events.ts:18`](../packages/core/tools/src/events.ts) | [`tools`](../packages/core/tools) (`waterfall`) | `auto-review`, [`hooks-claude-code`](../packages/experimental/hooks-claude-code), [`hooks-codex`](../packages/experimental/hooks-codex), [`tool-jobs`](../packages/jobs/tool-jobs), [`workspace-changes`](../packages/deliverables/workspace-changes) |
|
||||
| `tools/ptc-dispatch-log` | `waterfall` | [`packages/core/tool-executor-ptc/src/runtime-types.ts:46`](../packages/core/tool-executor-ptc/src/runtime-types.ts) | [`tool-executor-ptc`](../packages/core/tool-executor-ptc) (`waterfall`) | [`spill-policy`](../packages/spill/spill-policy) |
|
||||
| `tools/result` | `emit` | [`packages/core/tools/src/events.ts:49`](../packages/core/tools/src/events.ts) | [`tools`](../packages/core/tools) (`events.dispatch`) | [`agent-instructions`](../packages/context/agent-instructions), `claude-code-mods`, [`subagent`](../packages/subagent/subagent), [`tool-present`](../packages/deliverables/tool-present) |
|
||||
| `tools/result` | `emit` | [`packages/core/tools/src/events.ts:49`](../packages/core/tools/src/events.ts) | [`tools`](../packages/core/tools) (`events.dispatch`) | [`action-cards`](../packages/experimental/action-cards), [`agent-instructions`](../packages/context/agent-instructions), `claude-code-mods`, [`subagent`](../packages/subagent/subagent), [`tool-present`](../packages/deliverables/tool-present) |
|
||||
| `user-questions/request` | `waterfall` | [`packages/interaction/user-questions/src/types.ts:174`](../packages/interaction/user-questions/src/types.ts) | [`user-questions`](../packages/interaction/user-questions) (`waterfall`) | `remotes`, `server` |
|
||||
| `webserver/index-inject` | `emit` | [`packages/host/webserver/src/index.ts:44`](../packages/host/webserver/src/index.ts) | `webserver` (`emit`) | `connection`, `inspector`, `modules`, `remote-access`, `shortcuts`, `ui-sidebar-documentpreview`, `ui-theme` |
|
||||
| `workflow/agent-end` | `emit` | [`packages/workflow/workflow/src/index.ts:79`](../packages/workflow/workflow/src/index.ts) | [`workflow`](../packages/workflow/workflow) (`events.dispatch`) | [`tool-workflow`](../packages/workflow/tool-workflow) |
|
||||
|
||||
@@ -13,13 +13,13 @@
|
||||
| `agent-loop/config-start-failed` | `emit` | [`packages/core/agent-loop/src/index.ts:199`](../packages/core/agent-loop/src/index.ts) | [`agent-loop`](../packages/core/agent-loop) (`events.dispatch`) | - |
|
||||
| `agent-preset/selected` | `emit` | [`packages/preset/agent-preset-registry/src/types.ts:66`](../packages/preset/agent-preset-registry/src/types.ts) | [`agent-preset-registry`](../packages/preset/agent-preset-registry) (`emit`) | [`cua`](../packages/experimental/cua), `remotes` |
|
||||
| `agent/assistant-stream` | `emit` | [`packages/core/agent/src/runtime-types.ts:399`](../packages/core/agent/src/runtime-types.ts) | [`agent-loop`](../packages/core/agent-loop) (`emit`) | [`headless`](../packages/bundle/headless), `session-controller` |
|
||||
| `agent/created` | `serial` | [`packages/core/agent/src/runtime-types.ts:290`](../packages/core/agent/src/runtime-types.ts) | [`agent`](../packages/core/agent) (`serial`) | `agent-team`, `browser-use-runtime`, `claude-code-mods`, [`cua`](../packages/experimental/cua), [`file-reference-local`](../packages/context/file-reference-local), [`goal`](../packages/goal/goal), [`goal-round-driver`](../packages/goal/goal-round-driver), [`hooks-claude-code`](../packages/experimental/hooks-claude-code), [`hooks-codex`](../packages/experimental/hooks-codex), [`loader-smoke`](../packages/test-support/loader-smoke), [`permission-presets`](../packages/interaction/permission-presets), `session-controller`, `tool-agent-team`, [`tool-subagent`](../packages/subagent/tool-subagent) |
|
||||
| `agent/disposed` | `emit` | [`packages/core/agent/src/runtime-types.ts:299`](../packages/core/agent/src/runtime-types.ts) | [`agent`](../packages/core/agent) (`events.dispatch`) | [`agent-loop`](../packages/core/agent-loop), `claude-code-mods`, [`file-reference-local`](../packages/context/file-reference-local), [`goal-round-driver`](../packages/goal/goal-round-driver), `session-controller`, [`subagent`](../packages/subagent/subagent), `tool-agent-team`, [`tool-subagent`](../packages/subagent/tool-subagent) |
|
||||
| `agent/created` | `serial` | [`packages/core/agent/src/runtime-types.ts:290`](../packages/core/agent/src/runtime-types.ts) | [`agent`](../packages/core/agent) (`serial`) | `agent-team`, `browser-use-runtime`, `claude-code-mods`, [`creation-recommendations`](../packages/experimental/creation-recommendations), [`cua`](../packages/experimental/cua), [`file-reference-local`](../packages/context/file-reference-local), [`goal`](../packages/goal/goal), [`goal-round-driver`](../packages/goal/goal-round-driver), [`hooks-claude-code`](../packages/experimental/hooks-claude-code), [`hooks-codex`](../packages/experimental/hooks-codex), [`loader-smoke`](../packages/test-support/loader-smoke), [`permission-presets`](../packages/interaction/permission-presets), `session-controller`, `tool-agent-team`, [`tool-subagent`](../packages/subagent/tool-subagent) |
|
||||
| `agent/disposed` | `emit` | [`packages/core/agent/src/runtime-types.ts:299`](../packages/core/agent/src/runtime-types.ts) | [`agent`](../packages/core/agent) (`events.dispatch`) | [`action-cards`](../packages/experimental/action-cards), [`agent-loop`](../packages/core/agent-loop), `claude-code-mods`, [`creation-recommendations`](../packages/experimental/creation-recommendations), [`file-reference-local`](../packages/context/file-reference-local), [`goal-round-driver`](../packages/goal/goal-round-driver), `session-controller`, [`subagent`](../packages/subagent/subagent), `tool-agent-team`, [`tool-subagent`](../packages/subagent/tool-subagent) |
|
||||
| `agent/error` | `emit` | [`packages/core/agent/src/runtime-types.ts:429`](../packages/core/agent/src/runtime-types.ts) | [`agent-loop`](../packages/core/agent-loop) (`emit`) | [`acp`](../packages/acp/acp), [`deepseek-account`](../packages/credentials/deepseek-account), [`goal-round-driver`](../packages/goal/goal-round-driver), [`headless`](../packages/bundle/headless), `server`, `session-controller`, [`session-telemetry`](../packages/session/session-telemetry), [`subagent`](../packages/subagent/subagent) |
|
||||
| `agent/inbox/claimed` | `emit` | [`packages/core/agent/src/runtime-types.ts:328`](../packages/core/agent/src/runtime-types.ts) | [`agent-loop`](../packages/core/agent-loop) (`emit`) | [`acp`](../packages/acp/acp), [`goal-round-driver`](../packages/goal/goal-round-driver), [`subagent`](../packages/subagent/subagent), [`tool-jobs`](../packages/jobs/tool-jobs), [`user-questions`](../packages/interaction/user-questions) |
|
||||
| `agent/inbox/discarded` | `emit` | [`packages/core/agent/src/runtime-types.ts:336`](../packages/core/agent/src/runtime-types.ts) | [`agent-loop`](../packages/core/agent-loop) (`emit`) | [`goal-round-driver`](../packages/goal/goal-round-driver), [`subagent`](../packages/subagent/subagent), [`user-questions`](../packages/interaction/user-questions) |
|
||||
| `agent/inbox/inserted` | `emit` | [`packages/core/agent/src/runtime-types.ts:317`](../packages/core/agent/src/runtime-types.ts) | [`agent-loop`](../packages/core/agent-loop) (`emit`) | [`goal-round-driver`](../packages/goal/goal-round-driver), [`subagent`](../packages/subagent/subagent), [`tool-jobs`](../packages/jobs/tool-jobs) |
|
||||
| `agent/pre-step` | `waterfall` | [`packages/core/agent/src/runtime-types.ts:350`](../packages/core/agent/src/runtime-types.ts) | [`agent-loop`](../packages/core/agent-loop) (`waterfall`) | [`agent`](../packages/core/agent), [`agent-instructions`](../packages/context/agent-instructions), `claude-code-mods`, [`compaction-basic`](../packages/compaction/compaction-basic), [`goal-round-driver`](../packages/goal/goal-round-driver), [`hooks-claude-code`](../packages/experimental/hooks-claude-code), [`hooks-codex`](../packages/experimental/hooks-codex), [`plan-mode`](../packages/plan/plan-mode), [`repeat-tool-reminder`](../packages/guard/repeat-tool-reminder), [`session-checkpoint-policy`](../packages/session/session-checkpoint-policy), `session-controller`, [`session-reference`](../packages/context/session-reference), [`time-context`](../packages/context/time-context), [`tmux-context`](../packages/context/tmux-context), [`tool-skill`](../packages/skill/tool-skill) |
|
||||
| `agent/pre-step` | `waterfall` | [`packages/core/agent/src/runtime-types.ts:350`](../packages/core/agent/src/runtime-types.ts) | [`agent-loop`](../packages/core/agent-loop) (`waterfall`) | [`action-cards`](../packages/experimental/action-cards), [`agent`](../packages/core/agent), [`agent-instructions`](../packages/context/agent-instructions), `claude-code-mods`, [`compaction-basic`](../packages/compaction/compaction-basic), [`goal-round-driver`](../packages/goal/goal-round-driver), [`hooks-claude-code`](../packages/experimental/hooks-claude-code), [`hooks-codex`](../packages/experimental/hooks-codex), [`plan-mode`](../packages/plan/plan-mode), [`repeat-tool-reminder`](../packages/guard/repeat-tool-reminder), [`session-checkpoint-policy`](../packages/session/session-checkpoint-policy), `session-controller`, [`session-reference`](../packages/context/session-reference), [`time-context`](../packages/context/time-context), [`tmux-context`](../packages/context/tmux-context), [`tool-skill`](../packages/skill/tool-skill) |
|
||||
| `agent/request-error` | `waterfall` | [`packages/core/agent/src/runtime-types.ts:389`](../packages/core/agent/src/runtime-types.ts) | [`agent-loop`](../packages/core/agent-loop) (`waterfall`) | [`compaction-basic`](../packages/compaction/compaction-basic), [`compaction-image-offload`](../packages/compaction/compaction-image-offload), [`llm-retry`](../packages/llm/llm-retry) |
|
||||
| `agent/status` | `emit` | [`packages/core/agent/src/runtime-types.ts:309`](../packages/core/agent/src/runtime-types.ts) | [`agent-loop`](../packages/core/agent-loop) (`emit`) | [`acp`](../packages/acp/acp), `agent-team`, [`compaction-basic`](../packages/compaction/compaction-basic), [`goal-round-driver`](../packages/goal/goal-round-driver), `server`, `session-controller` |
|
||||
| `agent/turn-stopping` | `serial` | [`packages/core/agent/src/runtime-types.ts:417`](../packages/core/agent/src/runtime-types.ts) | [`agent-loop`](../packages/core/agent-loop) (`serial`) | [`hooks-claude-code`](../packages/experimental/hooks-claude-code), [`hooks-codex`](../packages/experimental/hooks-codex), [`workspace-changes`](../packages/deliverables/workspace-changes) |
|
||||
@@ -82,7 +82,7 @@
|
||||
| `tools/post-execute` | `waterfall` | [`packages/core/tools/src/events.ts:41`](../packages/core/tools/src/events.ts) | [`tools`](../packages/core/tools) (`waterfall`) | `claude-code-mods`, [`hooks-claude-code`](../packages/experimental/hooks-claude-code), [`hooks-codex`](../packages/experimental/hooks-codex), [`repeat-tool-reminder`](../packages/guard/repeat-tool-reminder), [`spill-policy`](../packages/spill/spill-policy), [`tool-fs-search`](../packages/fs/tool-fs-search) |
|
||||
| `tools/pre-execute` | `waterfall` | [`packages/core/tools/src/events.ts:18`](../packages/core/tools/src/events.ts) | [`tools`](../packages/core/tools) (`waterfall`) | `auto-review`, [`hooks-claude-code`](../packages/experimental/hooks-claude-code), [`hooks-codex`](../packages/experimental/hooks-codex), [`tool-jobs`](../packages/jobs/tool-jobs), [`workspace-changes`](../packages/deliverables/workspace-changes) |
|
||||
| `tools/ptc-dispatch-log` | `waterfall` | [`packages/core/tool-executor-ptc/src/runtime-types.ts:46`](../packages/core/tool-executor-ptc/src/runtime-types.ts) | [`tool-executor-ptc`](../packages/core/tool-executor-ptc) (`waterfall`) | [`spill-policy`](../packages/spill/spill-policy) |
|
||||
| `tools/result` | `emit` | [`packages/core/tools/src/events.ts:49`](../packages/core/tools/src/events.ts) | [`tools`](../packages/core/tools) (`events.dispatch`) | [`agent-instructions`](../packages/context/agent-instructions), `claude-code-mods`, [`subagent`](../packages/subagent/subagent), [`tool-present`](../packages/deliverables/tool-present) |
|
||||
| `tools/result` | `emit` | [`packages/core/tools/src/events.ts:49`](../packages/core/tools/src/events.ts) | [`tools`](../packages/core/tools) (`events.dispatch`) | [`action-cards`](../packages/experimental/action-cards), [`agent-instructions`](../packages/context/agent-instructions), `claude-code-mods`, [`subagent`](../packages/subagent/subagent), [`tool-present`](../packages/deliverables/tool-present) |
|
||||
| `user-questions/request` | `waterfall` | [`packages/interaction/user-questions/src/types.ts:174`](../packages/interaction/user-questions/src/types.ts) | [`user-questions`](../packages/interaction/user-questions) (`waterfall`) | `remotes`, `server` |
|
||||
| `webserver/index-inject` | `emit` | [`packages/host/webserver/src/index.ts:44`](../packages/host/webserver/src/index.ts) | `webserver` (`emit`) | `connection`, `inspector`, `modules`, `remote-access`, `shortcuts`, `ui-sidebar-documentpreview`, `ui-theme` |
|
||||
| `workflow/agent-end` | `emit` | [`packages/workflow/workflow/src/index.ts:79`](../packages/workflow/workflow/src/index.ts) | [`workflow`](../packages/workflow/workflow) (`events.dispatch`) | [`tool-workflow`](../packages/workflow/tool-workflow) |
|
||||
|
||||
@@ -6,5 +6,5 @@
|
||||
en: a11f106978c9dce7
|
||||
zh: a11f106978c9dce7
|
||||
/experimental-plugin-record-catalog:
|
||||
en: 84dbc9c06ab92877
|
||||
zh: b82ef2a46292ab0e
|
||||
en: cb931db3b4bcbe33
|
||||
zh: aca9cfecfdee34c0
|
||||
@@ -13,5 +13,6 @@ Shared Session event declarations and resolved schemas appear in the [Session pe
|
||||
|
||||
| Record | Owner | Purpose | Payload and source |
|
||||
|---|---|---|---|
|
||||
| `plugin:action-cards/decision` | `@deepseek-ai/dsh-action-cards` | Dismissals and kind-defined progress of action cards. | <code>ActionCardDecision</code> · [`packages/experimental/action-cards/src/types.ts`](../packages/experimental/action-cards/src/types.ts) |
|
||||
| `plugin:translator/request` | `@deepseek-ai/dsh-experimental-translator` | Provider-independent translation input, retained before dispatch. | <code>TranslationRequestRecord</code> · [`packages/experimental/translator/src/types.ts`](../packages/experimental/translator/src/types.ts) |
|
||||
| `plugin:translator/result` | `@deepseek-ai/dsh-experimental-translator` | Successful translation, retained before it is returned to the consumer. | <code>TranslationResultRecord</code> · [`packages/experimental/translator/src/types.ts`](../packages/experimental/translator/src/types.ts) |
|
||||
@@ -13,5 +13,6 @@
|
||||
|
||||
| 记录 | 所属包 | 用途 | 载荷与源码 |
|
||||
|---|---|---|---|
|
||||
| `plugin:action-cards/decision` | `@deepseek-ai/dsh-action-cards` | Dismissals and kind-defined progress of action cards. | <code>ActionCardDecision</code> · [`packages/experimental/action-cards/src/types.ts`](../packages/experimental/action-cards/src/types.ts) |
|
||||
| `plugin:translator/request` | `@deepseek-ai/dsh-experimental-translator` | Provider-independent translation input, retained before dispatch. | <code>TranslationRequestRecord</code> · [`packages/experimental/translator/src/types.ts`](../packages/experimental/translator/src/types.ts) |
|
||||
| `plugin:translator/result` | `@deepseek-ai/dsh-experimental-translator` | Successful translation, retained before it is returned to the consumer. | <code>TranslationResultRecord</code> · [`packages/experimental/translator/src/types.ts`](../packages/experimental/translator/src/types.ts) |
|
||||
@@ -254,6 +254,11 @@ flowchart TD
|
||||
pkg_office_to_pdf["office-to-pdf"]
|
||||
end
|
||||
subgraph group_experimental["packages/experimental"]
|
||||
pkg_action_cards["action-cards"]
|
||||
pkg_client_ui_action_cards["client-ui-action-cards"]
|
||||
pkg_client_ui_creation_recommendations["client-ui-creation-recommendations"]
|
||||
pkg_client_ui_plugin_recommendations["client-ui-plugin-recommendations"]
|
||||
pkg_creation_recommendations["creation-recommendations"]
|
||||
pkg_cua["cua"]
|
||||
pkg_cua_bundle["cua-bundle"]
|
||||
pkg_experimental_agent_team["experimental-agent-team"]
|
||||
@@ -297,6 +302,7 @@ flowchart TD
|
||||
pkg_hook_protocol["hook-protocol"]
|
||||
pkg_hooks_claude_code["hooks-claude-code"]
|
||||
pkg_hooks_codex["hooks-codex"]
|
||||
pkg_plugin_recommendations["plugin-recommendations"]
|
||||
pkg_session_title_all_prompts_llm["session-title-all-prompts-llm"]
|
||||
pkg_skill_badge["skill-badge"]
|
||||
pkg_tool_ralph["tool-ralph"]
|
||||
@@ -515,6 +521,9 @@ flowchart TD
|
||||
pkg_experimental_webworker_runtime --> pkg_client_connection
|
||||
pkg_experimental_webworker_runtime --> pkg_client_modules
|
||||
pkg_experimental_webworker_runtime --> pkg_host_webserver
|
||||
pkg_plugin_recommendations --> pkg_llm
|
||||
pkg_plugin_recommendations --> pkg_skill
|
||||
pkg_plugin_recommendations --> pkg_typert_protocol
|
||||
pkg_skill_badge --> pkg_skill
|
||||
pkg_host_directory_picker_auto --> pkg_client_connection
|
||||
pkg_host_directory_picker_auto --> pkg_client_ui_directory_picker_browse
|
||||
@@ -924,6 +933,14 @@ flowchart TD
|
||||
pkg_workspace_changes --> pkg_session
|
||||
pkg_workspace_changes --> pkg_subprocess
|
||||
pkg_workspace_changes --> pkg_tools
|
||||
pkg_action_cards --> pkg_llm
|
||||
pkg_action_cards --> pkg_session
|
||||
pkg_action_cards --> pkg_tools
|
||||
pkg_action_cards --> pkg_typert_protocol
|
||||
pkg_creation_recommendations --> pkg_llm
|
||||
pkg_creation_recommendations --> pkg_session
|
||||
pkg_creation_recommendations --> pkg_skill
|
||||
pkg_creation_recommendations --> pkg_tools
|
||||
pkg_experimental_browser_use_chrome_devtools_mcp --> pkg_agent
|
||||
pkg_experimental_browser_use_chrome_devtools_mcp --> pkg_browser_use
|
||||
pkg_experimental_browser_use_chrome_devtools_mcp --> pkg_system_prompt
|
||||
@@ -1560,6 +1577,9 @@ flowchart TD
|
||||
| [`client-web`](../packages/client/web) | `client` | — |
|
||||
| [`credentials`](../packages/credentials/credentials) | `credentials` | — |
|
||||
| [`office-to-pdf`](../packages/document/office-to-pdf) | `document` | — |
|
||||
| [`client-ui-action-cards`](../packages/experimental/client-ui-action-cards) | `experimental` | — |
|
||||
| [`client-ui-creation-recommendations`](../packages/experimental/client-ui-creation-recommendations) | `experimental` | — |
|
||||
| [`client-ui-plugin-recommendations`](../packages/experimental/client-ui-plugin-recommendations) | `experimental` | — |
|
||||
| [`cua-bundle`](../packages/experimental/cua-bundle) | `experimental` | — |
|
||||
| [`experimental-agent-team-profile`](../packages/experimental/agent-team-profile) | `experimental` | — |
|
||||
| [`experimental-badge-skill-bundle`](../packages/experimental/badge-skill-bundle) | `experimental` | — |
|
||||
@@ -1628,6 +1648,7 @@ flowchart TD
|
||||
| [`deliverable-file-references`](../packages/deliverables/deliverable-file-references) | `deliverables` | [`system-prompt`](../packages/core/system-prompt) |
|
||||
| [`experimental-computer-use-cua-driver-mcp`](../packages/experimental/computer-use-cua-driver-mcp) | `experimental` | [`computer-use`](../packages/computer-use/computer-use) |
|
||||
| [`experimental-webworker-runtime`](../packages/experimental/webworker-runtime) | `experimental` | [`client-connection`](../packages/client/connection), [`client-modules`](../packages/client/modules), [`host-webserver`](../packages/host/webserver) |
|
||||
| [`plugin-recommendations`](../packages/experimental/plugin-recommendations) | `experimental` | [`llm`](../packages/llm/llm), [`skill`](../packages/skill/skill), [`typert-protocol`](../packages/typert/protocol) |
|
||||
| [`skill-badge`](../packages/experimental/skill-badge) | `experimental` | [`skill`](../packages/skill/skill) |
|
||||
| [`host-directory-picker-auto`](../packages/host/directory-picker-auto) | `host` | [`client-connection`](../packages/client/connection), [`client-ui-directory-picker-browse`](../packages/client/ui-directory-picker-browse), [`client-ui-directory-picker-native`](../packages/client/ui-directory-picker-native), [`host-directory-picker-browse`](../packages/host/directory-picker-browse), [`host-directory-picker-native`](../packages/host/directory-picker-native), [`host-webserver`](../packages/host/webserver) |
|
||||
| [`host-frontend-static`](../packages/host/frontend-static) | `host` | [`client-connection`](../packages/client/connection), [`host-webserver`](../packages/host/webserver) |
|
||||
@@ -1730,6 +1751,8 @@ flowchart TD
|
||||
| [`file-reference-local`](../packages/context/file-reference-local) | `context` | [`agent`](../packages/core/agent), [`file-reference`](../packages/context/file-reference), [`system-prompt`](../packages/core/system-prompt), [`tools`](../packages/core/tools), [`working-directory`](../packages/session/working-directory) |
|
||||
| [`tool-present`](../packages/deliverables/tool-present) | `deliverables` | [`agent`](../packages/core/agent), [`fs`](../packages/fs/fs), [`llm`](../packages/llm/llm), [`session`](../packages/core/session), [`tools`](../packages/core/tools), [`working-directory`](../packages/session/working-directory) |
|
||||
| [`workspace-changes`](../packages/deliverables/workspace-changes) | `deliverables` | [`agent`](../packages/core/agent), [`fs`](../packages/fs/fs), [`session`](../packages/core/session), [`subprocess`](../packages/subprocess/subprocess), [`tools`](../packages/core/tools) |
|
||||
| [`action-cards`](../packages/experimental/action-cards) | `experimental` | [`llm`](../packages/llm/llm), [`session`](../packages/core/session), [`tools`](../packages/core/tools), [`typert-protocol`](../packages/typert/protocol) |
|
||||
| [`creation-recommendations`](../packages/experimental/creation-recommendations) | `experimental` | [`llm`](../packages/llm/llm), [`session`](../packages/core/session), [`skill`](../packages/skill/skill), [`tools`](../packages/core/tools) |
|
||||
| [`experimental-browser-use-chrome-devtools-mcp`](../packages/experimental/browser-use-chrome-devtools-mcp) | `experimental` | [`agent`](../packages/core/agent), [`browser-use`](../packages/browser-use/browser-use), [`system-prompt`](../packages/core/system-prompt), [`tools`](../packages/core/tools), [`working-directory`](../packages/session/working-directory) |
|
||||
| [`experimental-browser-use-playwright-mcp`](../packages/experimental/browser-use-playwright-mcp) | `experimental` | [`agent`](../packages/core/agent), [`browser-use`](../packages/browser-use/browser-use), [`system-prompt`](../packages/core/system-prompt), [`tools`](../packages/core/tools), [`working-directory`](../packages/session/working-directory) |
|
||||
| [`experimental-browser-use-stagehand-native`](../packages/experimental/browser-use-stagehand-native) | `experimental` | [`agent`](../packages/core/agent), [`browser-use`](../packages/browser-use/browser-use), [`system-prompt`](../packages/core/system-prompt), [`tools`](../packages/core/tools) |
|
||||
|
||||
@@ -256,6 +256,11 @@ flowchart TD
|
||||
pkg_office_to_pdf["office-to-pdf"]
|
||||
end
|
||||
subgraph group_experimental["packages/experimental"]
|
||||
pkg_action_cards["action-cards"]
|
||||
pkg_client_ui_action_cards["client-ui-action-cards"]
|
||||
pkg_client_ui_creation_recommendations["client-ui-creation-recommendations"]
|
||||
pkg_client_ui_plugin_recommendations["client-ui-plugin-recommendations"]
|
||||
pkg_creation_recommendations["creation-recommendations"]
|
||||
pkg_cua["cua"]
|
||||
pkg_cua_bundle["cua-bundle"]
|
||||
pkg_experimental_agent_team["experimental-agent-team"]
|
||||
@@ -299,6 +304,7 @@ flowchart TD
|
||||
pkg_hook_protocol["hook-protocol"]
|
||||
pkg_hooks_claude_code["hooks-claude-code"]
|
||||
pkg_hooks_codex["hooks-codex"]
|
||||
pkg_plugin_recommendations["plugin-recommendations"]
|
||||
pkg_session_title_all_prompts_llm["session-title-all-prompts-llm"]
|
||||
pkg_skill_badge["skill-badge"]
|
||||
pkg_tool_ralph["tool-ralph"]
|
||||
@@ -517,6 +523,9 @@ flowchart TD
|
||||
pkg_experimental_webworker_runtime --> pkg_client_connection
|
||||
pkg_experimental_webworker_runtime --> pkg_client_modules
|
||||
pkg_experimental_webworker_runtime --> pkg_host_webserver
|
||||
pkg_plugin_recommendations --> pkg_llm
|
||||
pkg_plugin_recommendations --> pkg_skill
|
||||
pkg_plugin_recommendations --> pkg_typert_protocol
|
||||
pkg_skill_badge --> pkg_skill
|
||||
pkg_host_directory_picker_auto --> pkg_client_connection
|
||||
pkg_host_directory_picker_auto --> pkg_client_ui_directory_picker_browse
|
||||
@@ -926,6 +935,14 @@ flowchart TD
|
||||
pkg_workspace_changes --> pkg_session
|
||||
pkg_workspace_changes --> pkg_subprocess
|
||||
pkg_workspace_changes --> pkg_tools
|
||||
pkg_action_cards --> pkg_llm
|
||||
pkg_action_cards --> pkg_session
|
||||
pkg_action_cards --> pkg_tools
|
||||
pkg_action_cards --> pkg_typert_protocol
|
||||
pkg_creation_recommendations --> pkg_llm
|
||||
pkg_creation_recommendations --> pkg_session
|
||||
pkg_creation_recommendations --> pkg_skill
|
||||
pkg_creation_recommendations --> pkg_tools
|
||||
pkg_experimental_browser_use_chrome_devtools_mcp --> pkg_agent
|
||||
pkg_experimental_browser_use_chrome_devtools_mcp --> pkg_browser_use
|
||||
pkg_experimental_browser_use_chrome_devtools_mcp --> pkg_system_prompt
|
||||
@@ -1562,6 +1579,9 @@ flowchart TD
|
||||
| [`client-web`](../packages/client/web) | `client` | — |
|
||||
| [`credentials`](../packages/credentials/credentials) | `credentials` | — |
|
||||
| [`office-to-pdf`](../packages/document/office-to-pdf) | `document` | — |
|
||||
| [`client-ui-action-cards`](../packages/experimental/client-ui-action-cards) | `experimental` | — |
|
||||
| [`client-ui-creation-recommendations`](../packages/experimental/client-ui-creation-recommendations) | `experimental` | — |
|
||||
| [`client-ui-plugin-recommendations`](../packages/experimental/client-ui-plugin-recommendations) | `experimental` | — |
|
||||
| [`cua-bundle`](../packages/experimental/cua-bundle) | `experimental` | — |
|
||||
| [`experimental-agent-team-profile`](../packages/experimental/agent-team-profile) | `experimental` | — |
|
||||
| [`experimental-badge-skill-bundle`](../packages/experimental/badge-skill-bundle) | `experimental` | — |
|
||||
@@ -1630,6 +1650,7 @@ flowchart TD
|
||||
| [`deliverable-file-references`](../packages/deliverables/deliverable-file-references) | `deliverables` | [`system-prompt`](../packages/core/system-prompt) |
|
||||
| [`experimental-computer-use-cua-driver-mcp`](../packages/experimental/computer-use-cua-driver-mcp) | `experimental` | [`computer-use`](../packages/computer-use/computer-use) |
|
||||
| [`experimental-webworker-runtime`](../packages/experimental/webworker-runtime) | `experimental` | [`client-connection`](../packages/client/connection), [`client-modules`](../packages/client/modules), [`host-webserver`](../packages/host/webserver) |
|
||||
| [`plugin-recommendations`](../packages/experimental/plugin-recommendations) | `experimental` | [`llm`](../packages/llm/llm), [`skill`](../packages/skill/skill), [`typert-protocol`](../packages/typert/protocol) |
|
||||
| [`skill-badge`](../packages/experimental/skill-badge) | `experimental` | [`skill`](../packages/skill/skill) |
|
||||
| [`host-directory-picker-auto`](../packages/host/directory-picker-auto) | `host` | [`client-connection`](../packages/client/connection), [`client-ui-directory-picker-browse`](../packages/client/ui-directory-picker-browse), [`client-ui-directory-picker-native`](../packages/client/ui-directory-picker-native), [`host-directory-picker-browse`](../packages/host/directory-picker-browse), [`host-directory-picker-native`](../packages/host/directory-picker-native), [`host-webserver`](../packages/host/webserver) |
|
||||
| [`host-frontend-static`](../packages/host/frontend-static) | `host` | [`client-connection`](../packages/client/connection), [`host-webserver`](../packages/host/webserver) |
|
||||
@@ -1732,6 +1753,8 @@ flowchart TD
|
||||
| [`file-reference-local`](../packages/context/file-reference-local) | `context` | [`agent`](../packages/core/agent), [`file-reference`](../packages/context/file-reference), [`system-prompt`](../packages/core/system-prompt), [`tools`](../packages/core/tools), [`working-directory`](../packages/session/working-directory) |
|
||||
| [`tool-present`](../packages/deliverables/tool-present) | `deliverables` | [`agent`](../packages/core/agent), [`fs`](../packages/fs/fs), [`llm`](../packages/llm/llm), [`session`](../packages/core/session), [`tools`](../packages/core/tools), [`working-directory`](../packages/session/working-directory) |
|
||||
| [`workspace-changes`](../packages/deliverables/workspace-changes) | `deliverables` | [`agent`](../packages/core/agent), [`fs`](../packages/fs/fs), [`session`](../packages/core/session), [`subprocess`](../packages/subprocess/subprocess), [`tools`](../packages/core/tools) |
|
||||
| [`action-cards`](../packages/experimental/action-cards) | `experimental` | [`llm`](../packages/llm/llm), [`session`](../packages/core/session), [`tools`](../packages/core/tools), [`typert-protocol`](../packages/typert/protocol) |
|
||||
| [`creation-recommendations`](../packages/experimental/creation-recommendations) | `experimental` | [`llm`](../packages/llm/llm), [`session`](../packages/core/session), [`skill`](../packages/skill/skill), [`tools`](../packages/core/tools) |
|
||||
| [`experimental-browser-use-chrome-devtools-mcp`](../packages/experimental/browser-use-chrome-devtools-mcp) | `experimental` | [`agent`](../packages/core/agent), [`browser-use`](../packages/browser-use/browser-use), [`system-prompt`](../packages/core/system-prompt), [`tools`](../packages/core/tools), [`working-directory`](../packages/session/working-directory) |
|
||||
| [`experimental-browser-use-playwright-mcp`](../packages/experimental/browser-use-playwright-mcp) | `experimental` | [`agent`](../packages/core/agent), [`browser-use`](../packages/browser-use/browser-use), [`system-prompt`](../packages/core/system-prompt), [`tools`](../packages/core/tools), [`working-directory`](../packages/session/working-directory) |
|
||||
| [`experimental-browser-use-stagehand-native`](../packages/experimental/browser-use-stagehand-native) | `experimental` | [`agent`](../packages/core/agent), [`browser-use`](../packages/browser-use/browser-use), [`system-prompt`](../packages/core/system-prompt), [`tools`](../packages/core/tools) |
|
||||
|
||||
@@ -9,8 +9,8 @@
|
||||
en: 1387c4505dde2faf
|
||||
zh: 48570fa1c13d6910
|
||||
/session-persistence-event-catalog/persistence-type-fingerprints:
|
||||
en: bcff48893d904af8
|
||||
zh: f82e75c91c39adb1
|
||||
en: 3e24343c4745793d
|
||||
zh: 90f808fd6b79c5a3
|
||||
/session-persistence-event-catalog/event-envelope:
|
||||
en: 981db6b1928eda50
|
||||
zh: d77bc66cf678099d
|
||||
@@ -309,8 +309,11 @@
|
||||
en: 3493ecf0993e5397
|
||||
zh: ec95688f593a4ed4
|
||||
/session-persistence-event-catalog/resolved-persistence-types/aborted:
|
||||
en: d716fb9ee9baa564
|
||||
zh: d716fb9ee9baa564
|
||||
en: 40049fd36471e4b2
|
||||
zh: 40049fd36471e4b2
|
||||
/session-persistence-event-catalog/resolved-persistence-types/action-cards:
|
||||
en: 629f821b50a38bc6
|
||||
zh: 629f821b50a38bc6
|
||||
/session-persistence-event-catalog/resolved-persistence-types/active:
|
||||
en: 6b343e390ae7d7a7
|
||||
zh: 6b343e390ae7d7a7
|
||||
@@ -1005,11 +1008,11 @@
|
||||
en: a6a2e38fdd6d127a
|
||||
zh: 1fe82356d89f5769
|
||||
/session-persistence-event-catalog/resolved-persistence-types/deepseeksearchllmrequest:
|
||||
en: 128c0ecc1897eb68
|
||||
zh: e4c67c92752bcc2a
|
||||
en: 0e286bae74e78505
|
||||
zh: b1c9da5aa56d5a81
|
||||
/session-persistence-event-catalog/resolved-persistence-types/developermessage:
|
||||
en: 997b5db27df00446
|
||||
zh: 07e5197ddd7bd59b
|
||||
en: 3d8a393be23efcde
|
||||
zh: f95f337d816dbbe7
|
||||
/session-persistence-event-catalog/resolved-persistence-types/epochheader:
|
||||
en: c804cb9e2e31c5ec
|
||||
zh: 3ed7ac59cd1441b7
|
||||
@@ -1119,11 +1122,11 @@
|
||||
en: 6dbe099c62f7c226
|
||||
zh: 6fd788f63c038c91
|
||||
/session-persistence-event-catalog/resolved-persistence-types/llmretrystartedeventdata:
|
||||
en: c2d9edd8d9f492b7
|
||||
zh: f59c687ac691f7ce
|
||||
en: 3d2f7c88259b6446
|
||||
zh: 58bee68c335d6d4f
|
||||
/session-persistence-event-catalog/resolved-persistence-types/message:
|
||||
en: 594707e4894819a8
|
||||
zh: 268c4bfd5c4c28f2
|
||||
en: 76d13d39fe22f7bd
|
||||
zh: b1e19cfe90a6d6b6
|
||||
/session-persistence-event-catalog/resolved-persistence-types/messagefeedbackdelete:
|
||||
en: c582953270d4ca44
|
||||
zh: 966ccfe2e7660a2a
|
||||
@@ -1134,14 +1137,14 @@
|
||||
en: f58575a1fc96df42
|
||||
zh: 9f0c6ed9033e5c9d
|
||||
/session-persistence-event-catalog/resolved-persistence-types/messagefeedbackrating:
|
||||
en: 674296d54c1914d0
|
||||
zh: 3d71ab319514be25
|
||||
en: 887549d6401dd116
|
||||
zh: 30198672b67dac6b
|
||||
/session-persistence-event-catalog/resolved-persistence-types/messagesource:
|
||||
en: 3fab179fe8d58c31
|
||||
zh: 5328c9161ff908a9
|
||||
en: 2f21414632f8d184
|
||||
zh: d85f66e001fd814c
|
||||
/session-persistence-event-catalog/resolved-persistence-types/message~2:
|
||||
en: 8bd12543fcdcda5f
|
||||
zh: d4c6b17083948856
|
||||
en: 87e95476b4985e5e
|
||||
zh: 0e0322e005b3e995
|
||||
/session-persistence-event-catalog/resolved-persistence-types/modelmessagesource:
|
||||
en: 5f9154ca34235ab9
|
||||
zh: a833105910ebfa82
|
||||
@@ -1203,11 +1206,11 @@
|
||||
en: 9a54c4478ad3b620
|
||||
zh: 02c4c1fd7e252770
|
||||
/session-persistence-event-catalog/resolved-persistence-types/sessiontitleeventdata:
|
||||
en: bf7325029c9338d6
|
||||
zh: e5f98271511e5318
|
||||
en: c0104327b481ae54
|
||||
zh: b4624d112bee37f1
|
||||
/session-persistence-event-catalog/resolved-persistence-types/sessiontitlellmrequesteventdata:
|
||||
en: 89dcb9a9b957c126
|
||||
zh: 132aeb7dfd435290
|
||||
en: 2e40681d575da503
|
||||
zh: 57cbccb16548e2da
|
||||
/session-persistence-event-catalog/resolved-persistence-types/sessiontitlemodelidentity:
|
||||
en: 9531468264499498
|
||||
zh: 9da23c0ad2776563
|
||||
@@ -1314,14 +1317,14 @@
|
||||
en: 4dc89c072fe5d0d1
|
||||
zh: 4ed2c9e9e8b4f7e2
|
||||
/session-persistence-event-catalog/resolved-persistence-types/turnendreason:
|
||||
en: 344a7207a4199a32
|
||||
zh: d500af39e83289cf
|
||||
en: e39f2f99ea109af9
|
||||
zh: f95ec41c72738f3e
|
||||
/session-persistence-event-catalog/resolved-persistence-types/usermessage:
|
||||
en: bd3aedd570ded4d2
|
||||
zh: f020d0816d3a6c1a
|
||||
en: 79b3ac6c731859aa
|
||||
zh: 81058fe7edf61bdb
|
||||
/session-persistence-event-catalog/resolved-persistence-types/usermessage~2:
|
||||
en: b99d66ffe277f0bc
|
||||
zh: eacc9c1f62ae66c1
|
||||
en: 8e699c0217638bbe
|
||||
zh: a2047db24c25217b
|
||||
/session-persistence-event-catalog/resolved-persistence-types/workflowagentoutcome:
|
||||
en: d0a3f9aab18c3de5
|
||||
zh: 76ac69a835ca4e29
|
||||
@@ -1500,11 +1503,11 @@
|
||||
en: 51af619ed8532a43
|
||||
zh: a5ad878c63d0e046
|
||||
/session-persistence-event-catalog/resolved-persistence-types/header-reason-startsseries:
|
||||
en: 0b1ca5c765d716d1
|
||||
zh: dd939095c250c4eb
|
||||
en: 8c523b44a081ffe0
|
||||
zh: d94ac2402fe80645
|
||||
/session-persistence-event-catalog/resolved-persistence-types/headerseq-message-step-turn:
|
||||
en: 3d16abb7b9581429
|
||||
zh: dc959157864261d8
|
||||
en: 174b2c8332e397b2
|
||||
zh: 31b94e9a33b9bdac
|
||||
/session-persistence-event-catalog/resolved-persistence-types/height-width:
|
||||
en: a5df50710083ac25
|
||||
zh: aad3ccf6f6de70e4
|
||||
@@ -1521,17 +1524,38 @@
|
||||
en: 41f73c58a77dfa28
|
||||
zh: af77f4aee3cb4a40
|
||||
/session-persistence-event-catalog/resolved-persistence-types/inherited:
|
||||
en: 6ce6ddac6d815805
|
||||
zh: f7196176e902c965
|
||||
en: bbffa2689f69314f
|
||||
zh: c691059ad7b99d67
|
||||
/session-persistence-event-catalog/resolved-persistence-types/inserted-outcome-removedcount-start:
|
||||
en: 346d884a7a74e48d
|
||||
zh: 646ac1021f9ca920
|
||||
en: 1750502af87d698c
|
||||
zh: 382a3356f0a61546
|
||||
/session-persistence-event-catalog/resolved-persistence-types/interrupted-message-step-stream:
|
||||
en: 89fb3f919d181c86
|
||||
zh: 4380624236500687
|
||||
/session-persistence-event-catalog/resolved-persistence-types/kind-aborted-reason:
|
||||
en: 48424cbed3fbc269
|
||||
zh: 2ce88c04ad002104
|
||||
en: 8bdd31bfea14a015
|
||||
zh: 203d7ebf5ea4d352
|
||||
/session-persistence-event-catalog/resolved-persistence-types/kind-action-cards:
|
||||
en: 8d057f0bd0b88fc6
|
||||
zh: 500d1e3d54e6d7c4
|
||||
/session-persistence-event-catalog/resolved-persistence-types/kind-action-cards-form-catalog:
|
||||
en: 14e9dd01c49f91e0
|
||||
zh: 4a7e4e4aeeb15982
|
||||
/session-persistence-event-catalog/resolved-persistence-types/kind-action-cards-form-instructions:
|
||||
en: f59ec0c37dc8f9b6
|
||||
zh: debc915ed98581fb
|
||||
/session-persistence-event-catalog/resolved-persistence-types/kind-action-cards-form-notice:
|
||||
en: ef0a456530698cca
|
||||
zh: 23f2ace5345eb847
|
||||
/session-persistence-event-catalog/resolved-persistence-types/kind-action-cards-form-recall:
|
||||
en: 0b607f9577e3a3c5
|
||||
zh: 237ed72b7a4154df
|
||||
/session-persistence-event-catalog/resolved-persistence-types/kind-action-cards-form-relay:
|
||||
en: 712bc9ad7c51a8fe
|
||||
zh: f230dc9c09bdbf3c
|
||||
/session-persistence-event-catalog/resolved-persistence-types/kind-action-cards-form-snapshot:
|
||||
en: 4e030b06ef900819
|
||||
zh: 27532bbabe118206
|
||||
/session-persistence-event-catalog/resolved-persistence-types/kind-blocked:
|
||||
en: 2fad818b19823c48
|
||||
zh: a6b33dee21c3fdc9
|
||||
@@ -1920,11 +1944,11 @@
|
||||
en: ea32b4165dbfb182
|
||||
zh: 57f48af06cfa201c
|
||||
/session-persistence-event-catalog/resolved-persistence-types/type-agent-preset-selected:
|
||||
en: c8c731ee23bed85a
|
||||
zh: f4ffc80f7828701d
|
||||
en: 6a59f1cd472759e9
|
||||
zh: 1db67f4f97207efc
|
||||
/session-persistence-event-catalog/resolved-persistence-types/type-agent-inbox-spliced:
|
||||
en: 62dfe9447efaceb1
|
||||
zh: 076454de19b5d7d7
|
||||
en: 6c276128e62a5432
|
||||
zh: 4ff5e93d255caece
|
||||
/session-persistence-event-catalog/resolved-persistence-types/type-approval-asked:
|
||||
en: 9c77f18b0dad22f0
|
||||
zh: 8894cf2878fe90db
|
||||
@@ -1968,11 +1992,11 @@
|
||||
en: ba73fb10b7e2ffc9
|
||||
zh: 8d5c97e63e5f16da
|
||||
/session-persistence-event-catalog/resolved-persistence-types/type-deliverables-presented:
|
||||
en: a4d9eab2928e9b30
|
||||
zh: b36702c866518273
|
||||
en: 10d95ce64c285e64
|
||||
zh: 0ddb26f1fa16629c
|
||||
/session-persistence-event-catalog/resolved-persistence-types/type-developer-message:
|
||||
en: a9e6e24b98390923
|
||||
zh: 65addae898d8aaec
|
||||
en: 78d421c83506ebe9
|
||||
zh: 2e9399ba2d360627
|
||||
/session-persistence-event-catalog/resolved-persistence-types/type-disabled:
|
||||
en: 585627a50ece4e5f
|
||||
zh: 157837aee3da0ac3
|
||||
@@ -2046,11 +2070,11 @@
|
||||
en: acf7e21e4d21ebff
|
||||
zh: fb83a853634d204a
|
||||
/session-persistence-event-catalog/resolved-persistence-types/type-session-title:
|
||||
en: b99fbacda0db1abd
|
||||
zh: 9e75ce6b1d174d48
|
||||
en: 26d99fabe31f7fa3
|
||||
zh: 0a44b5c8f7f6488c
|
||||
/session-persistence-event-catalog/resolved-persistence-types/type-session-title-llm-request:
|
||||
en: 7ba30b98d8e3f653
|
||||
zh: ca68b01ab4b6ba3d
|
||||
en: bbbb345651600abf
|
||||
zh: e3b29e05fecb136a
|
||||
/session-persistence-event-catalog/resolved-persistence-types/type-step-end:
|
||||
en: 7fc233c4a569dae2
|
||||
zh: bc2b3fed4a397c00
|
||||
@@ -2127,11 +2151,11 @@
|
||||
en: 1b045de96172be4b
|
||||
zh: 8a15c6f35b576b37
|
||||
/session-persistence-event-catalog/resolved-persistence-types/type-usage:
|
||||
en: 8eec3bb6eee5085b
|
||||
zh: 04bb3281fd7bd95c
|
||||
en: ebb801c4444061fb
|
||||
zh: f2d6531de88ee16e
|
||||
/session-persistence-event-catalog/resolved-persistence-types/type-user-message:
|
||||
en: d6d9401f19a66ee8
|
||||
zh: 569fdddf887660a2
|
||||
en: 536f875df13987d0
|
||||
zh: 857a381433a4217f
|
||||
/session-persistence-event-catalog/resolved-persistence-types/type-web-deepseek-search-llm-request:
|
||||
en: 99c8837344178a47
|
||||
zh: bf746f5678346596
|
||||
|
||||
+146
-46
@@ -23,7 +23,7 @@ The [format references](persistence-changes/historical-formats/README.md) cover
|
||||
| `JsonlHeaderLine` | header | `18ee62b8900a4c3d046700f05d7a4d49d6cab2a660a020c87481d1603dd8bd4f` | [`HeaderLine`](#persistence-type-sha256-18ee62b8900a4c3d046700f05d7a4d49d6cab2a660a020c87481d1603dd8bd4f) |
|
||||
| `SessionEventEnvelope` | envelope | `5776e5553ff2dfe3f5bc202dbb1e7c9f93e35a531aebb7764c23b2b6153b2ccc` | [`union (3 variants)`](#persistence-type-sha256-5776e5553ff2dfe3f5bc202dbb1e7c9f93e35a531aebb7764c23b2b6153b2ccc) |
|
||||
| `event:agent-preset/selected` | event | `a10c17474eaf2ddab7095a099e0fe3d046fc18e56c3e344fc8894c05ff9ef97b` | [`{ type: "agent-preset/selected" }`](#persistence-type-sha256-a10c17474eaf2ddab7095a099e0fe3d046fc18e56c3e344fc8894c05ff9ef97b) |
|
||||
| `event:agent/inbox/spliced` | event | `0755b7d1128319ba2e389619cbbf2c961ad648882b4e91da7f3e9582cc8a2034` | [`{ type: "agent/inbox/spliced" }`](#persistence-type-sha256-0755b7d1128319ba2e389619cbbf2c961ad648882b4e91da7f3e9582cc8a2034) |
|
||||
| `event:agent/inbox/spliced` | event | `b36fd842cd004b532ce96fd5d6f5be28e017eda043131aa3cf5e69edc436108e` | [`{ type: "agent/inbox/spliced" }`](#persistence-type-sha256-b36fd842cd004b532ce96fd5d6f5be28e017eda043131aa3cf5e69edc436108e) |
|
||||
| `event:approval/asked` | event | `3bfeb47b58606f4661904bc723da612782214c463d01e6d61cd6d6193d7374e1` | [`{ type: "approval/asked" }`](#persistence-type-sha256-3bfeb47b58606f4661904bc723da612782214c463d01e6d61cd6d6193d7374e1) |
|
||||
| `event:approval/decided` | event | `bb1ab3d08f49a9f3b265f844cd78d5c49813062a7b34b54904b426f85d0ff6e3` | [`{ type: "approval/decided" }`](#persistence-type-sha256-bb1ab3d08f49a9f3b265f844cd78d5c49813062a7b34b54904b426f85d0ff6e3) |
|
||||
| `event:approval/policy` | event | `26718e15e7e395bce9642dba5bbe09b3b1a4ce2213d20d566cd9207d7fc5fb78` | [`{ type: "approval/policy" }`](#persistence-type-sha256-26718e15e7e395bce9642dba5bbe09b3b1a4ce2213d20d566cd9207d7fc5fb78) |
|
||||
@@ -36,7 +36,7 @@ The [format references](persistence-changes/historical-formats/README.md) cover
|
||||
| `event:compaction/start` | event | `db874d463b0fdec77e9da1c4568f37cb70bd6596781eb93800db44fb8a116965` | [`{ type: "compaction/start" }`](#persistence-type-sha256-db874d463b0fdec77e9da1c4568f37cb70bd6596781eb93800db44fb8a116965) |
|
||||
| `event:compaction/summary` | event | `e2f9a41e0989f54ed8cee80f8db2bcf9d60a5c810dc9d45b83fa050b9dce7602` | [`{ type: "compaction/summary" }`](#persistence-type-sha256-e2f9a41e0989f54ed8cee80f8db2bcf9d60a5c810dc9d45b83fa050b9dce7602) |
|
||||
| `event:deliverables/presented` | event | `13d3d180f977bf78081d487ffa0ecb75857349bcab29a5a3fb48189fca2a6176` | [`{ type: "deliverables/presented" }`](#persistence-type-sha256-13d3d180f977bf78081d487ffa0ecb75857349bcab29a5a3fb48189fca2a6176) |
|
||||
| `event:developer/message` | event | `97e0162f983c27456ec71269fb4976b1851588b8c1aeac5d071d43e11f95e03c` | [`{ type: "developer/message" }`](#persistence-type-sha256-97e0162f983c27456ec71269fb4976b1851588b8c1aeac5d071d43e11f95e03c) |
|
||||
| `event:developer/message` | event | `5ef58f2a1bdc576c1f12fa1f4da1920ece020b13c0f991a578cddcbeb28bc5be` | [`{ type: "developer/message" }`](#persistence-type-sha256-5ef58f2a1bdc576c1f12fa1f4da1920ece020b13c0f991a578cddcbeb28bc5be) |
|
||||
| `event:feedback/message-delete` | event | `3ee93b06f3a125850337602bcdf155d2538c43a5c944ec55b1b3c365152d6796` | [`{ type: "feedback/message-delete" }`](#persistence-type-sha256-3ee93b06f3a125850337602bcdf155d2538c43a5c944ec55b1b3c365152d6796) |
|
||||
| `event:feedback/message-put` | event | `b5086d249e8502e9ead1d39156bb8d559bde7951cac0f14ce150345b4e42a2bf` | [`{ type: "feedback/message-put" }`](#persistence-type-sha256-b5086d249e8502e9ead1d39156bb8d559bde7951cac0f14ce150345b4e42a2bf) |
|
||||
| `event:feedback/record` | event | `b54940ff095c17e874c5be03815f4c2145a256cf3a1d34dae4ab2f7769dfffe8` | [`{ type: "feedback/record" }`](#persistence-type-sha256-b54940ff095c17e874c5be03815f4c2145a256cf3a1d34dae4ab2f7769dfffe8) |
|
||||
@@ -58,7 +58,7 @@ The [format references](persistence-changes/historical-formats/README.md) cover
|
||||
| `event:session-log-deepseek/delivery-accepted` | event | `d63b8b8ffad9c02fd80c43a17df4f240c1fe8118ecca9de34f9d5871838ab5b9` | [`{ type: "session-log-deepseek/delivery-accepted" }`](#persistence-type-sha256-d63b8b8ffad9c02fd80c43a17df4f240c1fe8118ecca9de34f9d5871838ab5b9) |
|
||||
| `event:session/end-seed` | event | `5e6db6e24948d4a853c71cb9fabd252ad051ce93d4672c1266cf837c1c17b84e` | [`{ type: "session/end-seed" }`](#persistence-type-sha256-5e6db6e24948d4a853c71cb9fabd252ad051ce93d4672c1266cf837c1c17b84e) |
|
||||
| `event:session/title` | event | `1b912703e2d64f91c99c675b8f805b01076c8325b905c1218ad81ef0b24909d5` | [`{ type: "session/title" }`](#persistence-type-sha256-1b912703e2d64f91c99c675b8f805b01076c8325b905c1218ad81ef0b24909d5) |
|
||||
| `event:session/title-llm-request` | event | `79a4c87f8bfb4d6d05cd9952b99210d6a7db3b478c4a01d94b4c50602308c056` | [`{ type: "session/title-llm-request" }`](#persistence-type-sha256-79a4c87f8bfb4d6d05cd9952b99210d6a7db3b478c4a01d94b4c50602308c056) |
|
||||
| `event:session/title-llm-request` | event | `efa1a091017ce533e38b0ef3e14d11a5c102ff1793229b18dad719a4268d9adc` | [`{ type: "session/title-llm-request" }`](#persistence-type-sha256-efa1a091017ce533e38b0ef3e14d11a5c102ff1793229b18dad719a4268d9adc) |
|
||||
| `event:step/end` | event | `e0a787e6ec76c7c94fecbc501b489164ab0293db05bc947914077ad01e674f05` | [`{ type: "step/end" }`](#persistence-type-sha256-e0a787e6ec76c7c94fecbc501b489164ab0293db05bc947914077ad01e674f05) |
|
||||
| `event:step/start` | event | `4513e088d43e6c68425be30451b9f961cc264fe7318ca62681c41d4d78615986` | [`{ type: "step/start" }`](#persistence-type-sha256-4513e088d43e6c68425be30451b9f961cc264fe7318ca62681c41d4d78615986) |
|
||||
| `event:subagent/catalog` | event | `53750b9abf61efb7992b0aadc3e247ec927449c63266df28230fd1139f5590ac` | [`{ type: "subagent/catalog" }`](#persistence-type-sha256-53750b9abf61efb7992b0aadc3e247ec927449c63266df28230fd1139f5590ac) |
|
||||
@@ -80,7 +80,7 @@ The [format references](persistence-changes/historical-formats/README.md) cover
|
||||
| `event:tool/result` | event | `7c9f44e90a0058f4cc532ae20dad0c10afa6eba22e70a6c79fc79490bad64397` | [`{ type: "tool/result" }`](#persistence-type-sha256-7c9f44e90a0058f4cc532ae20dad0c10afa6eba22e70a6c79fc79490bad64397) |
|
||||
| `event:turn/end` | event | `0f8512903d94f57a4748fa1a2092e64342856796684e6b8343db685b192745ce` | [`{ type: "turn/end" }`](#persistence-type-sha256-0f8512903d94f57a4748fa1a2092e64342856796684e6b8343db685b192745ce) |
|
||||
| `event:turn/start` | event | `aa0957eca50aeb28bcd2e6930b95809926edacb550c8c340ba526ba6b861b3d8` | [`{ type: "turn/start" }`](#persistence-type-sha256-aa0957eca50aeb28bcd2e6930b95809926edacb550c8c340ba526ba6b861b3d8) |
|
||||
| `event:user/message` | event | `2ae8594a998c9862a597129e782277bcc518266712a703b5c3161bdf552d13b8` | [`{ type: "user/message" }`](#persistence-type-sha256-2ae8594a998c9862a597129e782277bcc518266712a703b5c3161bdf552d13b8) |
|
||||
| `event:user/message` | event | `58b122df513aeaf7ddc5783dbb1fd844e2979bb273964e30ae351a8db6510019` | [`{ type: "user/message" }`](#persistence-type-sha256-58b122df513aeaf7ddc5783dbb1fd844e2979bb273964e30ae351a8db6510019) |
|
||||
| `event:web/deepseek-search-llm-request` | event | `0c556c9b9f2a96238a6b9bbb99e748206cbff2ed6203041c9571f04ae5802f52` | [`{ type: "web/deepseek-search-llm-request" }`](#persistence-type-sha256-0c556c9b9f2a96238a6b9bbb99e748206cbff2ed6203041c9571f04ae5802f52) |
|
||||
| `event:working-directory/change` | event | `124aa62078ca3311353b39cc3bf6c75da281338be6bbf672f8b361d828cddca3` | [`{ type: "working-directory/change" }`](#persistence-type-sha256-124aa62078ca3311353b39cc3bf6c75da281338be6bbf672f8b361d828cddca3) |
|
||||
| `event:workspace/changes` | event | `e308ccf867a5398e316e0af8cb6ce238a8d33a63b9b384c8250a686786285f72` | [`{ type: "workspace/changes" }`](#persistence-type-sha256-e308ccf867a5398e316e0af8cb6ce238a8d33a63b9b384c8250a686786285f72) |
|
||||
@@ -1347,6 +1347,14 @@ SHA-256: `1e0b0b66b6f0c53fc72e52289d06b4708d776f1ca9df4c86a22bff621d403cf0`
|
||||
|
||||
`"aborted"`
|
||||
|
||||
<a id="persistence-type-sha256-05205074b24d8340cfd7995f6cb64779c7f1241490954700115601e264178877"></a>
|
||||
|
||||
### `"action-cards"`
|
||||
|
||||
SHA-256: `05205074b24d8340cfd7995f6cb64779c7f1241490954700115601e264178877`
|
||||
|
||||
`"action-cards"`
|
||||
|
||||
<a id="persistence-type-sha256-c8e6f48878cc2a2f0dc59682280d81f407943fb503f32c64bf9ff3d9393c3eff"></a>
|
||||
|
||||
### `"active"`
|
||||
@@ -3365,7 +3373,7 @@ Sources: [`packages/web/web-search-deepseek/src/provider.ts:55`](../packages/web
|
||||
| `body` | required | [`{ max_tokens, messages, model, thinking?, … }`](#persistence-type-sha256-9c001ecb5e1d3c3894410db2a1e383842e5f8454fb52182338686158abc1b3ee) |
|
||||
| `endpoint` | required | `string` |
|
||||
|
||||
<a id="persistence-type-sha256-0f6265188dae7ba6faa26830a180bb4deb0760561f97ee0c9d399ccf6c9cf1f7"></a>
|
||||
<a id="persistence-type-sha256-7580e7d96dc8475fffe813a42af499665de3d4517fcdb3bc2337d0340e98d616"></a>
|
||||
|
||||
<a id="persistence-type-developermessage"></a>
|
||||
|
||||
@@ -3373,7 +3381,7 @@ Sources: [`packages/web/web-search-deepseek/src/provider.ts:55`](../packages/web
|
||||
|
||||
### `DeveloperMessage`
|
||||
|
||||
SHA-256: `0f6265188dae7ba6faa26830a180bb4deb0760561f97ee0c9d399ccf6c9cf1f7`
|
||||
SHA-256: `7580e7d96dc8475fffe813a42af499665de3d4517fcdb3bc2337d0340e98d616`
|
||||
|
||||
Sources: [`packages/llm/llm/src/message.ts:157`](../packages/llm/llm/src/message.ts)
|
||||
|
||||
@@ -3382,11 +3390,11 @@ Sources: [`packages/llm/llm/src/message.ts:157`](../packages/llm/llm/src/message
|
||||
| `content` | required | [`ContentBlock[]`](#persistence-type-sha256-b52f215a6cd691058a3413c12f161fa3b563a2f4895adb3df6f744ec4b0a6ef1) |
|
||||
| `id` | required | `string` |
|
||||
| `role` | required | `"developer"` |
|
||||
| `source` | required | [`MessageSource`](#persistence-type-sha256-5bc2d7f02503fc6b3e1bb7e0b7fa22c0b9e4b9841fa3175b2ad8e607ae3525a8) |
|
||||
| `source` | required | [`MessageSource`](#persistence-type-sha256-7a5b68bd1a5118c827df9e2466acc5e4d16b83e3f97a2304d992958647592690) |
|
||||
|
||||
Source compatibility: `source` — `session-source-attribution` v1; `session.developer-message.source`; `kind`; `preserve`.
|
||||
|
||||
Attribution-only additions: `tmux-context`, `user-question-reply`, `working-directory`.
|
||||
Attribution-only additions: `action-cards`, `tmux-context`, `user-question-reply`, `working-directory`.
|
||||
|
||||
<a id="persistence-type-sha256-9a930283b91d493d6347146f2475bb107294b379415ca02162354f46a64164f7"></a>
|
||||
|
||||
@@ -4081,7 +4089,7 @@ Sources: [`packages/llm/llm-retry/src/types.ts:43`](../packages/llm/llm-retry/sr
|
||||
| `step` | required | `number` |
|
||||
| `turn` | required | `number` |
|
||||
|
||||
<a id="persistence-type-sha256-040cd65423bd64264d225504f1c572d239eeb1793d0c2856ad8e42bb6e1e148b"></a>
|
||||
<a id="persistence-type-sha256-cda79b839d8cc0c7a7bd09dd067de04925f6e9037080d878b65aaa5a383f117c"></a>
|
||||
|
||||
<a id="persistence-type-message"></a>
|
||||
|
||||
@@ -4089,17 +4097,17 @@ Sources: [`packages/llm/llm-retry/src/types.ts:43`](../packages/llm/llm-retry/sr
|
||||
|
||||
### `Message`
|
||||
|
||||
SHA-256: `040cd65423bd64264d225504f1c572d239eeb1793d0c2856ad8e42bb6e1e148b`
|
||||
SHA-256: `cda79b839d8cc0c7a7bd09dd067de04925f6e9037080d878b65aaa5a383f117c`
|
||||
|
||||
Sources: [`packages/llm/llm/src/message.ts:196`](../packages/llm/llm/src/message.ts)
|
||||
|
||||
One of:
|
||||
|
||||
- [`ToolResultMessage`](#persistence-type-sha256-4b259f7f8f0a44ad5e90b70a73553ced1df27012d126921d397ff403b6c86731)
|
||||
- [`DeveloperMessage`](#persistence-type-sha256-0f6265188dae7ba6faa26830a180bb4deb0760561f97ee0c9d399ccf6c9cf1f7)
|
||||
- [`UserMessage`](#persistence-type-sha256-2cf075b013d363ad743b5a4982900678d108499c721bc11255137402003db711)
|
||||
- [`AssistantMessage`](#persistence-type-sha256-fa87537f4a9c1e25602990a8bf686b383e9e00352ec8946e16ae24ba7c1625be)
|
||||
- [`DeveloperMessage`](#persistence-type-sha256-7580e7d96dc8475fffe813a42af499665de3d4517fcdb3bc2337d0340e98d616)
|
||||
- [`UserMessage`](#persistence-type-sha256-b782058cef83caf3eb44a16adeef5657e4d5cdff2d50655aba418c4490670a69)
|
||||
- [`SystemMessage`](#persistence-type-sha256-09f3f8dc417f278257202714132f98ba7b52957d7b558c4a04456603890eb363)
|
||||
- [`AssistantMessage`](#persistence-type-sha256-fa87537f4a9c1e25602990a8bf686b383e9e00352ec8946e16ae24ba7c1625be)
|
||||
|
||||
<a id="persistence-type-sha256-7c6129b6961cf4b2a030f36c78d2b0a5be38617651a9b81322e054ee512bee06"></a>
|
||||
|
||||
@@ -4174,7 +4182,7 @@ One of:
|
||||
- `"negative"`
|
||||
- `"positive"`
|
||||
|
||||
<a id="persistence-type-sha256-5bc2d7f02503fc6b3e1bb7e0b7fa22c0b9e4b9841fa3175b2ad8e607ae3525a8"></a>
|
||||
<a id="persistence-type-sha256-7a5b68bd1a5118c827df9e2466acc5e4d16b83e3f97a2304d992958647592690"></a>
|
||||
|
||||
<a id="persistence-type-messagesource"></a>
|
||||
|
||||
@@ -4182,12 +4190,19 @@ One of:
|
||||
|
||||
### `MessageSource`
|
||||
|
||||
SHA-256: `5bc2d7f02503fc6b3e1bb7e0b7fa22c0b9e4b9841fa3175b2ad8e607ae3525a8`
|
||||
SHA-256: `7a5b68bd1a5118c827df9e2466acc5e4d16b83e3f97a2304d992958647592690`
|
||||
|
||||
Sources: [`packages/llm/llm/src/message.ts:136`](../packages/llm/llm/src/message.ts)
|
||||
|
||||
| kind | Form property | Other required fields | Full definition |
|
||||
|---|---|---|---|
|
||||
| `action-cards` | `"catalog"` | `through`: `number` | [`{ kind: "action-cards", form: "catalog" }`](#persistence-type-sha256-dd00cdccd0ba487b92362ef67db58cd264f48c1bfd368291424a1da9a899489a) |
|
||||
| `action-cards` | `"instructions"` | `through`: `number` | [`{ kind: "action-cards", form: "instructions" }`](#persistence-type-sha256-ba2a1a8f194b1bb21f270713398f6643e206e8ff5f7f26f6d36a88e3f0f0ab10) |
|
||||
| `action-cards` | `"notice"` | `summary`: `string`; `through`: `number` | [`{ kind: "action-cards", form: "notice" }`](#persistence-type-sha256-e7f4cbb3a57f4cbdb61ea41e95bcba626ad1fff6bb9b1e063b1d50a32da6e864) |
|
||||
| `action-cards` | `"recall"` | `through`: `number` | [`{ kind: "action-cards", form: "recall" }`](#persistence-type-sha256-b613f83572fe2fbf7259c72308cafd008f4fceea897749128a48bcd158f290aa) |
|
||||
| `action-cards` | `"relay"` | `through`: `number` | [`{ kind: "action-cards", form: "relay" }`](#persistence-type-sha256-45f005e6bbb7645248be792b715a74bc7fdf5a67f5381655d3a75dcc7aa2112e) |
|
||||
| `action-cards` | `"snapshot"` | `sections`: [`ContextSnapshotSection[]`](#persistence-type-sha256-c748fb42c80a120038a8c587af80ec39924803c401364db11c8974d5bf6d0262); `through`: `number` | [`{ kind: "action-cards", form: "snapshot" }`](#persistence-type-sha256-3247e566f4340029325b70e4366b56fa9719977f1e39033b769a2ec221ab22a9) |
|
||||
| `action-cards` | not declared | `through`: `number` | [`{ kind: "action-cards" }`](#persistence-type-sha256-dde0cdf9d426768b649b5a9783d2144e7f900c35ef65229cd89036dbf411d1b0) |
|
||||
| `agent-instructions` | `"instructions"` | `changes`: [`AgentInstructionChange[]`](#persistence-type-sha256-2ab12a0e345658f9342816d773fe610f049982bcad82631f43b9205abe43e5ee) | [`AgentInstructionSource`](#persistence-type-sha256-6f22a9d02b9a1f1157f3b0e7bdccd7e7b12b085c4efdb709dfc74a465cd4e590) |
|
||||
| `agent-message` | `"relay"` | `senderSessionId`: `string` | [`AgentMessageSource`](#persistence-type-sha256-4a9bef9f27a942520cc2279ca7dd3082556e4bff543f66b5c0333e1bbed1cd86) |
|
||||
| `compact-checkpoint` | not declared | `compactionId`: `string` | [`CompactionCheckpointSource`](#persistence-type-sha256-31907de9563751822af6d9be02bafaf26faa098bbd1cb412524134d577cc1648) |
|
||||
@@ -4300,13 +4315,13 @@ Sources: [`packages/llm/llm/src/message.ts:136`](../packages/llm/llm/src/message
|
||||
| `webhook` | `"notice"` | `deliveryId`: `string`; `provider`: `string`; `ruleId`: `string`; `source`: `string`; `summary`: `string` | [`{ kind: "webhook", form: "notice" }`](#persistence-type-sha256-9edc162949abf93bd5ff049191b345454ba104f583937ce5580fb50f067d2b94) |
|
||||
| `working-directory` | not declared | none | [`{ kind: "working-directory" }`](#persistence-type-sha256-2235d957bf4b7c6cf959231d480f0ba1f3a6d72d82981493fb6c7c963021d3d5) |
|
||||
|
||||
<a id="persistence-type-sha256-a927d444c928ac0efd9dd8b2e7d7d04d711c264cb71578d81e0e2fd143ff669f"></a>
|
||||
<a id="persistence-type-sha256-78b9204976ab9faaf133c3488b73d1dfb6f1a4bb6c0903e3473cd41a5e1e39e1"></a>
|
||||
|
||||
### `Message[]`
|
||||
|
||||
SHA-256: `a927d444c928ac0efd9dd8b2e7d7d04d711c264cb71578d81e0e2fd143ff669f`
|
||||
SHA-256: `78b9204976ab9faaf133c3488b73d1dfb6f1a4bb6c0903e3473cd41a5e1e39e1`
|
||||
|
||||
Array of [`Message`](#persistence-type-sha256-040cd65423bd64264d225504f1c572d239eeb1793d0c2856ad8e42bb6e1e148b).
|
||||
Array of [`Message`](#persistence-type-sha256-cda79b839d8cc0c7a7bd09dd067de04925f6e9037080d878b65aaa5a383f117c).
|
||||
|
||||
<a id="persistence-type-sha256-719c51f67074f97034a6c94297fe1f4b5d3c8d392c57586dab732aa5398c7a91"></a>
|
||||
|
||||
@@ -4690,7 +4705,7 @@ Sources: [`packages/session/session-title/src/types.ts:41`](../packages/session/
|
||||
| `source` | required | [`SessionTitleSource`](#persistence-type-sha256-30d5a537b296685770b1241c4b4bbde19d5a31ff81aa23df73fab5e90b8fc65f) |
|
||||
| `title` | required | `string` |
|
||||
|
||||
<a id="persistence-type-sha256-00c054d3018c198d92f459563331edd1385e58345c677bb499791df2da0ade9f"></a>
|
||||
<a id="persistence-type-sha256-a3e299483348f27a4787a36bb3f29cd86024c65336abc10bb3d687468302c4cf"></a>
|
||||
|
||||
<a id="persistence-type-packagessessionsession-title-llmsrcindextssessiontitlellmrequesteventdata"></a>
|
||||
|
||||
@@ -4698,7 +4713,7 @@ Sources: [`packages/session/session-title/src/types.ts:41`](../packages/session/
|
||||
|
||||
### `SessionTitleLlmRequestEventData`
|
||||
|
||||
SHA-256: `00c054d3018c198d92f459563331edd1385e58345c677bb499791df2da0ade9f`
|
||||
SHA-256: `a3e299483348f27a4787a36bb3f29cd86024c65336abc10bb3d687468302c4cf`
|
||||
|
||||
Sources: [`packages/session/session-title-llm/src/index.ts:37`](../packages/session/session-title-llm/src/index.ts)
|
||||
|
||||
@@ -4706,7 +4721,7 @@ Sources: [`packages/session/session-title-llm/src/index.ts:37`](../packages/sess
|
||||
|---|---|---|
|
||||
| `maxTokens` | required | `number` |
|
||||
| `messageSeqs` | required | [`number[]`](#persistence-type-sha256-5d03ba38734809bcbd2a55221bd938b3b3fc34b49bb686c6113e9e4931e3aa78) |
|
||||
| `messages` | required | [`Message[]`](#persistence-type-sha256-a927d444c928ac0efd9dd8b2e7d7d04d711c264cb71578d81e0e2fd143ff669f) |
|
||||
| `messages` | required | [`Message[]`](#persistence-type-sha256-78b9204976ab9faaf133c3488b73d1dfb6f1a4bb6c0903e3473cd41a5e1e39e1) |
|
||||
| `reasoningEffort` | optional | `string` |
|
||||
| `route` | required | [`SessionTitleModelIdentity`](#persistence-type-sha256-07e1a58c58b593f507b8e7f25723bb0aa42baae6e00f5ecfddf28cb1e64d3235) |
|
||||
| `system` | required | `string` |
|
||||
@@ -5362,7 +5377,7 @@ Sources: [`packages/core/session/src/types.ts:234`](../packages/core/session/src
|
||||
| `interrupted` | not declared | none | [`{ kind: "interrupted" }`](#persistence-type-sha256-56b7c047694875a843ba020dfea3c8380d54ae4ff88ab349e72004dc21e07c23) |
|
||||
| `max-tokens` | not declared | none | [`{ kind: "max-tokens" }`](#persistence-type-sha256-ab7ec5f9eb2c6dfacca5da4c37cf7ba85d04172053ee6b1ebf1709ffcd99c1a7) |
|
||||
|
||||
<a id="persistence-type-sha256-2cf075b013d363ad743b5a4982900678d108499c721bc11255137402003db711"></a>
|
||||
<a id="persistence-type-sha256-b782058cef83caf3eb44a16adeef5657e4d5cdff2d50655aba418c4490670a69"></a>
|
||||
|
||||
<a id="persistence-type-packagesllmllmsrcmessagetsusermessage"></a>
|
||||
|
||||
@@ -5370,7 +5385,7 @@ Sources: [`packages/core/session/src/types.ts:234`](../packages/core/session/src
|
||||
|
||||
### `UserMessage`
|
||||
|
||||
SHA-256: `2cf075b013d363ad743b5a4982900678d108499c721bc11255137402003db711`
|
||||
SHA-256: `b782058cef83caf3eb44a16adeef5657e4d5cdff2d50655aba418c4490670a69`
|
||||
|
||||
Sources: [`packages/llm/llm/src/message.ts:162`](../packages/llm/llm/src/message.ts)
|
||||
|
||||
@@ -5379,19 +5394,19 @@ Sources: [`packages/llm/llm/src/message.ts:162`](../packages/llm/llm/src/message
|
||||
| `content` | required | [`ContentBlock[]`](#persistence-type-sha256-b52f215a6cd691058a3413c12f161fa3b563a2f4895adb3df6f744ec4b0a6ef1) |
|
||||
| `id` | required | `string` |
|
||||
| `role` | required | `"user"` |
|
||||
| `source` | required | [`MessageSource`](#persistence-type-sha256-5bc2d7f02503fc6b3e1bb7e0b7fa22c0b9e4b9841fa3175b2ad8e607ae3525a8) |
|
||||
| `source` | required | [`MessageSource`](#persistence-type-sha256-7a5b68bd1a5118c827df9e2466acc5e4d16b83e3f97a2304d992958647592690) |
|
||||
|
||||
Source compatibility: `source` — `session-source-attribution` v1; `session.user-message.source`; `kind`; `preserve`.
|
||||
|
||||
Attribution-only additions: `tmux-context`, `user-question-reply`, `working-directory`.
|
||||
Attribution-only additions: `action-cards`, `tmux-context`, `user-question-reply`, `working-directory`.
|
||||
|
||||
<a id="persistence-type-sha256-454a0fa879e38076bdcdbd87ef561cd67d7e43e58a287cf7dbaa7b6cf7847020"></a>
|
||||
<a id="persistence-type-sha256-5d00abf938272f22eb47199e9d40801e8d8ec4c88e2b138b15aa2a5a5bf87520"></a>
|
||||
|
||||
### `UserMessage[]`
|
||||
|
||||
SHA-256: `454a0fa879e38076bdcdbd87ef561cd67d7e43e58a287cf7dbaa7b6cf7847020`
|
||||
SHA-256: `5d00abf938272f22eb47199e9d40801e8d8ec4c88e2b138b15aa2a5a5bf87520`
|
||||
|
||||
Array of [`UserMessage`](#persistence-type-sha256-2cf075b013d363ad743b5a4982900678d108499c721bc11255137402003db711).
|
||||
Array of [`UserMessage`](#persistence-type-sha256-b782058cef83caf3eb44a16adeef5657e4d5cdff2d50655aba418c4490670a69).
|
||||
|
||||
<a id="persistence-type-sha256-c2deb7c9183735d4e0fffddf5c623f4e34daa1c8e96b111982e957dfcbbcf896"></a>
|
||||
|
||||
@@ -6276,18 +6291,18 @@ Sources: [`packages/core/session/src/types.ts:392`](../packages/core/session/src
|
||||
| `reason` | required | [`RequestHeaderReason`](#persistence-type-sha256-530da6c0267813bb4511af72883cc518834e624e3b3220a7062955fd57a788a6) |
|
||||
| `startsSeries` | optional | `true` |
|
||||
|
||||
<a id="persistence-type-sha256-f4ed4717b4c259e933b550a8dcd90dc93628cda8a3c7affcaa53b9c13c1d53eb"></a>
|
||||
<a id="persistence-type-sha256-7404c6123fdaa591474a37979a5a8ae70d1387af7c9f09bfe568b218935a974d"></a>
|
||||
|
||||
### `{ headerSeq?, message, step, turn }`
|
||||
|
||||
SHA-256: `f4ed4717b4c259e933b550a8dcd90dc93628cda8a3c7affcaa53b9c13c1d53eb`
|
||||
SHA-256: `7404c6123fdaa591474a37979a5a8ae70d1387af7c9f09bfe568b218935a974d`
|
||||
|
||||
Sources: [`packages/core/session/src/types.ts:313`](../packages/core/session/src/types.ts)
|
||||
|
||||
| Property | Presence | Type |
|
||||
|---|---|---|
|
||||
| `headerSeq` | optional | `number` |
|
||||
| `message` | required | [`DeveloperMessage`](#persistence-type-sha256-0f6265188dae7ba6faa26830a180bb4deb0760561f97ee0c9d399ccf6c9cf1f7) |
|
||||
| `message` | required | [`DeveloperMessage`](#persistence-type-sha256-7580e7d96dc8475fffe813a42af499665de3d4517fcdb3bc2337d0340e98d616) |
|
||||
| `step` | required | `number` |
|
||||
| `turn` | required | `number` |
|
||||
|
||||
@@ -6371,17 +6386,17 @@ Sources: [`packages/core/session/src/types.ts:429`](../packages/core/session/src
|
||||
|---|---|---|
|
||||
| `inherited` | optional | `true` |
|
||||
|
||||
<a id="persistence-type-sha256-fa106c5b33b657e8ef16e8cbf39f3b7d44e5cbcdf4f9303d9db6410f28951e42"></a>
|
||||
<a id="persistence-type-sha256-b2a948a5340a9341fa3bab99507c7090c5b0456de72ec28b5b157b8df3f1d640"></a>
|
||||
|
||||
### `{ inserted, outcome?, removedCount?, start, … }`
|
||||
|
||||
SHA-256: `fa106c5b33b657e8ef16e8cbf39f3b7d44e5cbcdf4f9303d9db6410f28951e42`
|
||||
SHA-256: `b2a948a5340a9341fa3bab99507c7090c5b0456de72ec28b5b157b8df3f1d640`
|
||||
|
||||
Sources: [`packages/core/agent/src/types.ts:110`](../packages/core/agent/src/types.ts)
|
||||
|
||||
| Property | Presence | Type |
|
||||
|---|---|---|
|
||||
| `inserted` | required | [`UserMessage[]`](#persistence-type-sha256-454a0fa879e38076bdcdbd87ef561cd67d7e43e58a287cf7dbaa7b6cf7847020) |
|
||||
| `inserted` | required | [`UserMessage[]`](#persistence-type-sha256-5d00abf938272f22eb47199e9d40801e8d8ec4c88e2b138b15aa2a5a5bf87520) |
|
||||
| `outcome` | optional | `"canceled"` |
|
||||
| `removedCount` | optional | `number` |
|
||||
| `start` | required | `number` |
|
||||
@@ -6417,6 +6432,91 @@ Sources: [`packages/core/session/src/types.ts:205`](../packages/core/session/src
|
||||
| `kind` | required | `"aborted"` |
|
||||
| `reason` | required | [`TurnEndCancelCause`](#persistence-type-sha256-1f8c126cfab3df812cd115cfc23e3256f0fa2383400f4ce91ecad313577e59b0) |
|
||||
|
||||
<a id="persistence-type-sha256-dde0cdf9d426768b649b5a9783d2144e7f900c35ef65229cd89036dbf411d1b0"></a>
|
||||
|
||||
### `{ kind: "action-cards" }`
|
||||
|
||||
SHA-256: `dde0cdf9d426768b649b5a9783d2144e7f900c35ef65229cd89036dbf411d1b0`
|
||||
|
||||
| Property | Presence | Type |
|
||||
|---|---|---|
|
||||
| `kind` | required | `"action-cards"` |
|
||||
| `through` | required | `number` |
|
||||
|
||||
<a id="persistence-type-sha256-dd00cdccd0ba487b92362ef67db58cd264f48c1bfd368291424a1da9a899489a"></a>
|
||||
|
||||
### `{ kind: "action-cards", form: "catalog" }`
|
||||
|
||||
SHA-256: `dd00cdccd0ba487b92362ef67db58cd264f48c1bfd368291424a1da9a899489a`
|
||||
|
||||
| Property | Presence | Type |
|
||||
|---|---|---|
|
||||
| `form` | required | `"catalog"` |
|
||||
| `kind` | required | `"action-cards"` |
|
||||
| `through` | required | `number` |
|
||||
|
||||
<a id="persistence-type-sha256-ba2a1a8f194b1bb21f270713398f6643e206e8ff5f7f26f6d36a88e3f0f0ab10"></a>
|
||||
|
||||
### `{ kind: "action-cards", form: "instructions" }`
|
||||
|
||||
SHA-256: `ba2a1a8f194b1bb21f270713398f6643e206e8ff5f7f26f6d36a88e3f0f0ab10`
|
||||
|
||||
| Property | Presence | Type |
|
||||
|---|---|---|
|
||||
| `form` | required | `"instructions"` |
|
||||
| `kind` | required | `"action-cards"` |
|
||||
| `through` | required | `number` |
|
||||
|
||||
<a id="persistence-type-sha256-e7f4cbb3a57f4cbdb61ea41e95bcba626ad1fff6bb9b1e063b1d50a32da6e864"></a>
|
||||
|
||||
### `{ kind: "action-cards", form: "notice" }`
|
||||
|
||||
SHA-256: `e7f4cbb3a57f4cbdb61ea41e95bcba626ad1fff6bb9b1e063b1d50a32da6e864`
|
||||
|
||||
| Property | Presence | Type |
|
||||
|---|---|---|
|
||||
| `form` | required | `"notice"` |
|
||||
| `kind` | required | `"action-cards"` |
|
||||
| `summary` | required | `string` |
|
||||
| `through` | required | `number` |
|
||||
|
||||
<a id="persistence-type-sha256-b613f83572fe2fbf7259c72308cafd008f4fceea897749128a48bcd158f290aa"></a>
|
||||
|
||||
### `{ kind: "action-cards", form: "recall" }`
|
||||
|
||||
SHA-256: `b613f83572fe2fbf7259c72308cafd008f4fceea897749128a48bcd158f290aa`
|
||||
|
||||
| Property | Presence | Type |
|
||||
|---|---|---|
|
||||
| `form` | required | `"recall"` |
|
||||
| `kind` | required | `"action-cards"` |
|
||||
| `through` | required | `number` |
|
||||
|
||||
<a id="persistence-type-sha256-45f005e6bbb7645248be792b715a74bc7fdf5a67f5381655d3a75dcc7aa2112e"></a>
|
||||
|
||||
### `{ kind: "action-cards", form: "relay" }`
|
||||
|
||||
SHA-256: `45f005e6bbb7645248be792b715a74bc7fdf5a67f5381655d3a75dcc7aa2112e`
|
||||
|
||||
| Property | Presence | Type |
|
||||
|---|---|---|
|
||||
| `form` | required | `"relay"` |
|
||||
| `kind` | required | `"action-cards"` |
|
||||
| `through` | required | `number` |
|
||||
|
||||
<a id="persistence-type-sha256-3247e566f4340029325b70e4366b56fa9719977f1e39033b769a2ec221ab22a9"></a>
|
||||
|
||||
### `{ kind: "action-cards", form: "snapshot" }`
|
||||
|
||||
SHA-256: `3247e566f4340029325b70e4366b56fa9719977f1e39033b769a2ec221ab22a9`
|
||||
|
||||
| Property | Presence | Type |
|
||||
|---|---|---|
|
||||
| `form` | required | `"snapshot"` |
|
||||
| `kind` | required | `"action-cards"` |
|
||||
| `sections` | required | [`ContextSnapshotSection[]`](#persistence-type-sha256-c748fb42c80a120038a8c587af80ec39924803c401364db11c8974d5bf6d0262) |
|
||||
| `through` | required | `number` |
|
||||
|
||||
<a id="persistence-type-sha256-023a355b2be0d688fb6e4df8388dadb942761d46cfe96d0f499aae9631a159d4"></a>
|
||||
|
||||
### `{ kind: "blocked" }`
|
||||
@@ -7943,17 +8043,17 @@ SHA-256: `a10c17474eaf2ddab7095a099e0fe3d046fc18e56c3e344fc8894c05ff9ef97b`
|
||||
| `time` | required | `number` |
|
||||
| `type` | required | `"agent-preset/selected"` |
|
||||
|
||||
<a id="persistence-type-sha256-0755b7d1128319ba2e389619cbbf2c961ad648882b4e91da7f3e9582cc8a2034"></a>
|
||||
<a id="persistence-type-sha256-b36fd842cd004b532ce96fd5d6f5be28e017eda043131aa3cf5e69edc436108e"></a>
|
||||
|
||||
<a id="persistence-type-eventagentinboxspliced"></a>
|
||||
|
||||
### `{ type: "agent/inbox/spliced" }`
|
||||
|
||||
SHA-256: `0755b7d1128319ba2e389619cbbf2c961ad648882b4e91da7f3e9582cc8a2034`
|
||||
SHA-256: `b36fd842cd004b532ce96fd5d6f5be28e017eda043131aa3cf5e69edc436108e`
|
||||
|
||||
| Property | Presence | Type |
|
||||
|---|---|---|
|
||||
| `data` | required | [`{ inserted, outcome?, removedCount?, start, … }`](#persistence-type-sha256-fa106c5b33b657e8ef16e8cbf39f3b7d44e5cbcdf4f9303d9db6410f28951e42) |
|
||||
| `data` | required | [`{ inserted, outcome?, removedCount?, start, … }`](#persistence-type-sha256-b2a948a5340a9341fa3bab99507c7090c5b0456de72ec28b5b157b8df3f1d640) |
|
||||
| `ignorable` | optional | `true` |
|
||||
| `seq` | required | `number` |
|
||||
| `time` | required | `number` |
|
||||
@@ -8194,17 +8294,17 @@ SHA-256: `13d3d180f977bf78081d487ffa0ecb75857349bcab29a5a3fb48189fca2a6176`
|
||||
| `time` | required | `number` |
|
||||
| `type` | required | `"deliverables/presented"` |
|
||||
|
||||
<a id="persistence-type-sha256-97e0162f983c27456ec71269fb4976b1851588b8c1aeac5d071d43e11f95e03c"></a>
|
||||
<a id="persistence-type-sha256-5ef58f2a1bdc576c1f12fa1f4da1920ece020b13c0f991a578cddcbeb28bc5be"></a>
|
||||
|
||||
<a id="persistence-type-eventdevelopermessage"></a>
|
||||
|
||||
### `{ type: "developer/message" }`
|
||||
|
||||
SHA-256: `97e0162f983c27456ec71269fb4976b1851588b8c1aeac5d071d43e11f95e03c`
|
||||
SHA-256: `5ef58f2a1bdc576c1f12fa1f4da1920ece020b13c0f991a578cddcbeb28bc5be`
|
||||
|
||||
| Property | Presence | Type |
|
||||
|---|---|---|
|
||||
| `data` | required | [`{ headerSeq?, message, step, turn }`](#persistence-type-sha256-f4ed4717b4c259e933b550a8dcd90dc93628cda8a3c7affcaa53b9c13c1d53eb) |
|
||||
| `data` | required | [`{ headerSeq?, message, step, turn }`](#persistence-type-sha256-7404c6123fdaa591474a37979a5a8ae70d1387af7c9f09bfe568b218935a974d) |
|
||||
| `ignorable` | optional | `true` |
|
||||
| `seq` | required | `number` |
|
||||
| `sourceEventSeqs` | optional | [`number[]`](#persistence-type-sha256-5d03ba38734809bcbd2a55221bd938b3b3fc34b49bb686c6113e9e4931e3aa78) |
|
||||
@@ -8604,17 +8704,17 @@ SHA-256: `1b912703e2d64f91c99c675b8f805b01076c8325b905c1218ad81ef0b24909d5`
|
||||
| `time` | required | `number` |
|
||||
| `type` | required | `"session/title"` |
|
||||
|
||||
<a id="persistence-type-sha256-79a4c87f8bfb4d6d05cd9952b99210d6a7db3b478c4a01d94b4c50602308c056"></a>
|
||||
<a id="persistence-type-sha256-efa1a091017ce533e38b0ef3e14d11a5c102ff1793229b18dad719a4268d9adc"></a>
|
||||
|
||||
<a id="persistence-type-eventsessiontitle-llm-request"></a>
|
||||
|
||||
### `{ type: "session/title-llm-request" }`
|
||||
|
||||
SHA-256: `79a4c87f8bfb4d6d05cd9952b99210d6a7db3b478c4a01d94b4c50602308c056`
|
||||
SHA-256: `efa1a091017ce533e38b0ef3e14d11a5c102ff1793229b18dad719a4268d9adc`
|
||||
|
||||
| Property | Presence | Type |
|
||||
|---|---|---|
|
||||
| `data` | required | [`SessionTitleLlmRequestEventData`](#persistence-type-sha256-00c054d3018c198d92f459563331edd1385e58345c677bb499791df2da0ade9f) |
|
||||
| `data` | required | [`SessionTitleLlmRequestEventData`](#persistence-type-sha256-a3e299483348f27a4787a36bb3f29cd86024c65336abc10bb3d687468302c4cf) |
|
||||
| `ignorable` | optional | `true` |
|
||||
| `seq` | required | `number` |
|
||||
| `time` | required | `number` |
|
||||
@@ -9037,17 +9137,17 @@ Sources: [`packages/llm/llm/src/types.ts:476`](../packages/llm/llm/src/types.ts)
|
||||
| `type` | required | `"usage"` |
|
||||
| `usage` | required | [`TokenUsage`](#persistence-type-sha256-fec5442b9ee4122e10514d81d5a43648003fe8bfb7ee2ba50c0cdbdd383ed394) |
|
||||
|
||||
<a id="persistence-type-sha256-2ae8594a998c9862a597129e782277bcc518266712a703b5c3161bdf552d13b8"></a>
|
||||
<a id="persistence-type-sha256-58b122df513aeaf7ddc5783dbb1fd844e2979bb273964e30ae351a8db6510019"></a>
|
||||
|
||||
<a id="persistence-type-eventusermessage"></a>
|
||||
|
||||
### `{ type: "user/message" }`
|
||||
|
||||
SHA-256: `2ae8594a998c9862a597129e782277bcc518266712a703b5c3161bdf552d13b8`
|
||||
SHA-256: `58b122df513aeaf7ddc5783dbb1fd844e2979bb273964e30ae351a8db6510019`
|
||||
|
||||
| Property | Presence | Type |
|
||||
|---|---|---|
|
||||
| `data` | required | [`UserMessage`](#persistence-type-sha256-2cf075b013d363ad743b5a4982900678d108499c721bc11255137402003db711) |
|
||||
| `data` | required | [`UserMessage`](#persistence-type-sha256-b782058cef83caf3eb44a16adeef5657e4d5cdff2d50655aba418c4490670a69) |
|
||||
| `ignorable` | optional | `true` |
|
||||
| `seq` | required | `number` |
|
||||
| `sourceEventSeqs` | optional | [`number[]`](#persistence-type-sha256-5d03ba38734809bcbd2a55221bd938b3b3fc34b49bb686c6113e9e4931e3aa78) |
|
||||
|
||||
+146
-46
@@ -25,7 +25,7 @@
|
||||
| `JsonlHeaderLine` | header | `18ee62b8900a4c3d046700f05d7a4d49d6cab2a660a020c87481d1603dd8bd4f` | [`HeaderLine`](#persistence-type-sha256-18ee62b8900a4c3d046700f05d7a4d49d6cab2a660a020c87481d1603dd8bd4f) |
|
||||
| `SessionEventEnvelope` | envelope | `5776e5553ff2dfe3f5bc202dbb1e7c9f93e35a531aebb7764c23b2b6153b2ccc` | [`union (3 variants)`](#persistence-type-sha256-5776e5553ff2dfe3f5bc202dbb1e7c9f93e35a531aebb7764c23b2b6153b2ccc) |
|
||||
| `event:agent-preset/selected` | event | `a10c17474eaf2ddab7095a099e0fe3d046fc18e56c3e344fc8894c05ff9ef97b` | [`{ type: "agent-preset/selected" }`](#persistence-type-sha256-a10c17474eaf2ddab7095a099e0fe3d046fc18e56c3e344fc8894c05ff9ef97b) |
|
||||
| `event:agent/inbox/spliced` | event | `0755b7d1128319ba2e389619cbbf2c961ad648882b4e91da7f3e9582cc8a2034` | [`{ type: "agent/inbox/spliced" }`](#persistence-type-sha256-0755b7d1128319ba2e389619cbbf2c961ad648882b4e91da7f3e9582cc8a2034) |
|
||||
| `event:agent/inbox/spliced` | event | `b36fd842cd004b532ce96fd5d6f5be28e017eda043131aa3cf5e69edc436108e` | [`{ type: "agent/inbox/spliced" }`](#persistence-type-sha256-b36fd842cd004b532ce96fd5d6f5be28e017eda043131aa3cf5e69edc436108e) |
|
||||
| `event:approval/asked` | event | `3bfeb47b58606f4661904bc723da612782214c463d01e6d61cd6d6193d7374e1` | [`{ type: "approval/asked" }`](#persistence-type-sha256-3bfeb47b58606f4661904bc723da612782214c463d01e6d61cd6d6193d7374e1) |
|
||||
| `event:approval/decided` | event | `bb1ab3d08f49a9f3b265f844cd78d5c49813062a7b34b54904b426f85d0ff6e3` | [`{ type: "approval/decided" }`](#persistence-type-sha256-bb1ab3d08f49a9f3b265f844cd78d5c49813062a7b34b54904b426f85d0ff6e3) |
|
||||
| `event:approval/policy` | event | `26718e15e7e395bce9642dba5bbe09b3b1a4ce2213d20d566cd9207d7fc5fb78` | [`{ type: "approval/policy" }`](#persistence-type-sha256-26718e15e7e395bce9642dba5bbe09b3b1a4ce2213d20d566cd9207d7fc5fb78) |
|
||||
@@ -38,7 +38,7 @@
|
||||
| `event:compaction/start` | event | `db874d463b0fdec77e9da1c4568f37cb70bd6596781eb93800db44fb8a116965` | [`{ type: "compaction/start" }`](#persistence-type-sha256-db874d463b0fdec77e9da1c4568f37cb70bd6596781eb93800db44fb8a116965) |
|
||||
| `event:compaction/summary` | event | `e2f9a41e0989f54ed8cee80f8db2bcf9d60a5c810dc9d45b83fa050b9dce7602` | [`{ type: "compaction/summary" }`](#persistence-type-sha256-e2f9a41e0989f54ed8cee80f8db2bcf9d60a5c810dc9d45b83fa050b9dce7602) |
|
||||
| `event:deliverables/presented` | event | `13d3d180f977bf78081d487ffa0ecb75857349bcab29a5a3fb48189fca2a6176` | [`{ type: "deliverables/presented" }`](#persistence-type-sha256-13d3d180f977bf78081d487ffa0ecb75857349bcab29a5a3fb48189fca2a6176) |
|
||||
| `event:developer/message` | event | `97e0162f983c27456ec71269fb4976b1851588b8c1aeac5d071d43e11f95e03c` | [`{ type: "developer/message" }`](#persistence-type-sha256-97e0162f983c27456ec71269fb4976b1851588b8c1aeac5d071d43e11f95e03c) |
|
||||
| `event:developer/message` | event | `5ef58f2a1bdc576c1f12fa1f4da1920ece020b13c0f991a578cddcbeb28bc5be` | [`{ type: "developer/message" }`](#persistence-type-sha256-5ef58f2a1bdc576c1f12fa1f4da1920ece020b13c0f991a578cddcbeb28bc5be) |
|
||||
| `event:feedback/message-delete` | event | `3ee93b06f3a125850337602bcdf155d2538c43a5c944ec55b1b3c365152d6796` | [`{ type: "feedback/message-delete" }`](#persistence-type-sha256-3ee93b06f3a125850337602bcdf155d2538c43a5c944ec55b1b3c365152d6796) |
|
||||
| `event:feedback/message-put` | event | `b5086d249e8502e9ead1d39156bb8d559bde7951cac0f14ce150345b4e42a2bf` | [`{ type: "feedback/message-put" }`](#persistence-type-sha256-b5086d249e8502e9ead1d39156bb8d559bde7951cac0f14ce150345b4e42a2bf) |
|
||||
| `event:feedback/record` | event | `b54940ff095c17e874c5be03815f4c2145a256cf3a1d34dae4ab2f7769dfffe8` | [`{ type: "feedback/record" }`](#persistence-type-sha256-b54940ff095c17e874c5be03815f4c2145a256cf3a1d34dae4ab2f7769dfffe8) |
|
||||
@@ -60,7 +60,7 @@
|
||||
| `event:session-log-deepseek/delivery-accepted` | event | `d63b8b8ffad9c02fd80c43a17df4f240c1fe8118ecca9de34f9d5871838ab5b9` | [`{ type: "session-log-deepseek/delivery-accepted" }`](#persistence-type-sha256-d63b8b8ffad9c02fd80c43a17df4f240c1fe8118ecca9de34f9d5871838ab5b9) |
|
||||
| `event:session/end-seed` | event | `5e6db6e24948d4a853c71cb9fabd252ad051ce93d4672c1266cf837c1c17b84e` | [`{ type: "session/end-seed" }`](#persistence-type-sha256-5e6db6e24948d4a853c71cb9fabd252ad051ce93d4672c1266cf837c1c17b84e) |
|
||||
| `event:session/title` | event | `1b912703e2d64f91c99c675b8f805b01076c8325b905c1218ad81ef0b24909d5` | [`{ type: "session/title" }`](#persistence-type-sha256-1b912703e2d64f91c99c675b8f805b01076c8325b905c1218ad81ef0b24909d5) |
|
||||
| `event:session/title-llm-request` | event | `79a4c87f8bfb4d6d05cd9952b99210d6a7db3b478c4a01d94b4c50602308c056` | [`{ type: "session/title-llm-request" }`](#persistence-type-sha256-79a4c87f8bfb4d6d05cd9952b99210d6a7db3b478c4a01d94b4c50602308c056) |
|
||||
| `event:session/title-llm-request` | event | `efa1a091017ce533e38b0ef3e14d11a5c102ff1793229b18dad719a4268d9adc` | [`{ type: "session/title-llm-request" }`](#persistence-type-sha256-efa1a091017ce533e38b0ef3e14d11a5c102ff1793229b18dad719a4268d9adc) |
|
||||
| `event:step/end` | event | `e0a787e6ec76c7c94fecbc501b489164ab0293db05bc947914077ad01e674f05` | [`{ type: "step/end" }`](#persistence-type-sha256-e0a787e6ec76c7c94fecbc501b489164ab0293db05bc947914077ad01e674f05) |
|
||||
| `event:step/start` | event | `4513e088d43e6c68425be30451b9f961cc264fe7318ca62681c41d4d78615986` | [`{ type: "step/start" }`](#persistence-type-sha256-4513e088d43e6c68425be30451b9f961cc264fe7318ca62681c41d4d78615986) |
|
||||
| `event:subagent/catalog` | event | `53750b9abf61efb7992b0aadc3e247ec927449c63266df28230fd1139f5590ac` | [`{ type: "subagent/catalog" }`](#persistence-type-sha256-53750b9abf61efb7992b0aadc3e247ec927449c63266df28230fd1139f5590ac) |
|
||||
@@ -82,7 +82,7 @@
|
||||
| `event:tool/result` | event | `7c9f44e90a0058f4cc532ae20dad0c10afa6eba22e70a6c79fc79490bad64397` | [`{ type: "tool/result" }`](#persistence-type-sha256-7c9f44e90a0058f4cc532ae20dad0c10afa6eba22e70a6c79fc79490bad64397) |
|
||||
| `event:turn/end` | event | `0f8512903d94f57a4748fa1a2092e64342856796684e6b8343db685b192745ce` | [`{ type: "turn/end" }`](#persistence-type-sha256-0f8512903d94f57a4748fa1a2092e64342856796684e6b8343db685b192745ce) |
|
||||
| `event:turn/start` | event | `aa0957eca50aeb28bcd2e6930b95809926edacb550c8c340ba526ba6b861b3d8` | [`{ type: "turn/start" }`](#persistence-type-sha256-aa0957eca50aeb28bcd2e6930b95809926edacb550c8c340ba526ba6b861b3d8) |
|
||||
| `event:user/message` | event | `2ae8594a998c9862a597129e782277bcc518266712a703b5c3161bdf552d13b8` | [`{ type: "user/message" }`](#persistence-type-sha256-2ae8594a998c9862a597129e782277bcc518266712a703b5c3161bdf552d13b8) |
|
||||
| `event:user/message` | event | `58b122df513aeaf7ddc5783dbb1fd844e2979bb273964e30ae351a8db6510019` | [`{ type: "user/message" }`](#persistence-type-sha256-58b122df513aeaf7ddc5783dbb1fd844e2979bb273964e30ae351a8db6510019) |
|
||||
| `event:web/deepseek-search-llm-request` | event | `0c556c9b9f2a96238a6b9bbb99e748206cbff2ed6203041c9571f04ae5802f52` | [`{ type: "web/deepseek-search-llm-request" }`](#persistence-type-sha256-0c556c9b9f2a96238a6b9bbb99e748206cbff2ed6203041c9571f04ae5802f52) |
|
||||
| `event:working-directory/change` | event | `124aa62078ca3311353b39cc3bf6c75da281338be6bbf672f8b361d828cddca3` | [`{ type: "working-directory/change" }`](#persistence-type-sha256-124aa62078ca3311353b39cc3bf6c75da281338be6bbf672f8b361d828cddca3) |
|
||||
| `event:workspace/changes` | event | `e308ccf867a5398e316e0af8cb6ce238a8d33a63b9b384c8250a686786285f72` | [`{ type: "workspace/changes" }`](#persistence-type-sha256-e308ccf867a5398e316e0af8cb6ce238a8d33a63b9b384c8250a686786285f72) |
|
||||
@@ -1349,6 +1349,14 @@ SHA-256: `1e0b0b66b6f0c53fc72e52289d06b4708d776f1ca9df4c86a22bff621d403cf0`
|
||||
|
||||
`"aborted"`
|
||||
|
||||
<a id="persistence-type-sha256-05205074b24d8340cfd7995f6cb64779c7f1241490954700115601e264178877"></a>
|
||||
|
||||
### `"action-cards"`
|
||||
|
||||
SHA-256: `05205074b24d8340cfd7995f6cb64779c7f1241490954700115601e264178877`
|
||||
|
||||
`"action-cards"`
|
||||
|
||||
<a id="persistence-type-sha256-c8e6f48878cc2a2f0dc59682280d81f407943fb503f32c64bf9ff3d9393c3eff"></a>
|
||||
|
||||
### `"active"`
|
||||
@@ -3367,7 +3375,7 @@ SHA-256: `abd6ca62a5ab166553848324a23fef90eed7f59c8021bd63e7ea5bc6fd666b0c`
|
||||
| `body` | 必需 | [`{ max_tokens, messages, model, thinking?, … }`](#persistence-type-sha256-9c001ecb5e1d3c3894410db2a1e383842e5f8454fb52182338686158abc1b3ee) |
|
||||
| `endpoint` | 必需 | `string` |
|
||||
|
||||
<a id="persistence-type-sha256-0f6265188dae7ba6faa26830a180bb4deb0760561f97ee0c9d399ccf6c9cf1f7"></a>
|
||||
<a id="persistence-type-sha256-7580e7d96dc8475fffe813a42af499665de3d4517fcdb3bc2337d0340e98d616"></a>
|
||||
|
||||
<a id="persistence-type-developermessage"></a>
|
||||
|
||||
@@ -3375,7 +3383,7 @@ SHA-256: `abd6ca62a5ab166553848324a23fef90eed7f59c8021bd63e7ea5bc6fd666b0c`
|
||||
|
||||
### `DeveloperMessage`
|
||||
|
||||
SHA-256: `0f6265188dae7ba6faa26830a180bb4deb0760561f97ee0c9d399ccf6c9cf1f7`
|
||||
SHA-256: `7580e7d96dc8475fffe813a42af499665de3d4517fcdb3bc2337d0340e98d616`
|
||||
|
||||
来源:[`packages/llm/llm/src/message.ts:157`](../packages/llm/llm/src/message.ts)
|
||||
|
||||
@@ -3384,11 +3392,11 @@ SHA-256: `0f6265188dae7ba6faa26830a180bb4deb0760561f97ee0c9d399ccf6c9cf1f7`
|
||||
| `content` | 必需 | [`ContentBlock[]`](#persistence-type-sha256-b52f215a6cd691058a3413c12f161fa3b563a2f4895adb3df6f744ec4b0a6ef1) |
|
||||
| `id` | 必需 | `string` |
|
||||
| `role` | 必需 | `"developer"` |
|
||||
| `source` | 必需 | [`MessageSource`](#persistence-type-sha256-5bc2d7f02503fc6b3e1bb7e0b7fa22c0b9e4b9841fa3175b2ad8e607ae3525a8) |
|
||||
| `source` | 必需 | [`MessageSource`](#persistence-type-sha256-7a5b68bd1a5118c827df9e2466acc5e4d16b83e3f97a2304d992958647592690) |
|
||||
|
||||
消息源兼容策略:`source` — `session-source-attribution` v1; `session.developer-message.source`; `kind`; `preserve`.
|
||||
|
||||
仅表示归属的新增 kind:`tmux-context`, `user-question-reply`, `working-directory`.
|
||||
仅表示归属的新增 kind:`action-cards`, `tmux-context`, `user-question-reply`, `working-directory`.
|
||||
|
||||
<a id="persistence-type-sha256-9a930283b91d493d6347146f2475bb107294b379415ca02162354f46a64164f7"></a>
|
||||
|
||||
@@ -4083,7 +4091,7 @@ SHA-256: `6f72ece8f317cd080c4f20a93f1bf709965f5b81ac4669528f5a023191cfcf20`
|
||||
| `step` | 必需 | `number` |
|
||||
| `turn` | 必需 | `number` |
|
||||
|
||||
<a id="persistence-type-sha256-040cd65423bd64264d225504f1c572d239eeb1793d0c2856ad8e42bb6e1e148b"></a>
|
||||
<a id="persistence-type-sha256-cda79b839d8cc0c7a7bd09dd067de04925f6e9037080d878b65aaa5a383f117c"></a>
|
||||
|
||||
<a id="persistence-type-message"></a>
|
||||
|
||||
@@ -4091,17 +4099,17 @@ SHA-256: `6f72ece8f317cd080c4f20a93f1bf709965f5b81ac4669528f5a023191cfcf20`
|
||||
|
||||
### `Message`
|
||||
|
||||
SHA-256: `040cd65423bd64264d225504f1c572d239eeb1793d0c2856ad8e42bb6e1e148b`
|
||||
SHA-256: `cda79b839d8cc0c7a7bd09dd067de04925f6e9037080d878b65aaa5a383f117c`
|
||||
|
||||
来源:[`packages/llm/llm/src/message.ts:196`](../packages/llm/llm/src/message.ts)
|
||||
|
||||
以下类型之一:
|
||||
|
||||
- [`ToolResultMessage`](#persistence-type-sha256-4b259f7f8f0a44ad5e90b70a73553ced1df27012d126921d397ff403b6c86731)
|
||||
- [`DeveloperMessage`](#persistence-type-sha256-0f6265188dae7ba6faa26830a180bb4deb0760561f97ee0c9d399ccf6c9cf1f7)
|
||||
- [`UserMessage`](#persistence-type-sha256-2cf075b013d363ad743b5a4982900678d108499c721bc11255137402003db711)
|
||||
- [`AssistantMessage`](#persistence-type-sha256-fa87537f4a9c1e25602990a8bf686b383e9e00352ec8946e16ae24ba7c1625be)
|
||||
- [`DeveloperMessage`](#persistence-type-sha256-7580e7d96dc8475fffe813a42af499665de3d4517fcdb3bc2337d0340e98d616)
|
||||
- [`UserMessage`](#persistence-type-sha256-b782058cef83caf3eb44a16adeef5657e4d5cdff2d50655aba418c4490670a69)
|
||||
- [`SystemMessage`](#persistence-type-sha256-09f3f8dc417f278257202714132f98ba7b52957d7b558c4a04456603890eb363)
|
||||
- [`AssistantMessage`](#persistence-type-sha256-fa87537f4a9c1e25602990a8bf686b383e9e00352ec8946e16ae24ba7c1625be)
|
||||
|
||||
<a id="persistence-type-sha256-7c6129b6961cf4b2a030f36c78d2b0a5be38617651a9b81322e054ee512bee06"></a>
|
||||
|
||||
@@ -4176,7 +4184,7 @@ SHA-256: `390eed1028aba02774f14408647acec10ec5516e97d4f15ecde2b9989d5a69f2`
|
||||
- `"negative"`
|
||||
- `"positive"`
|
||||
|
||||
<a id="persistence-type-sha256-5bc2d7f02503fc6b3e1bb7e0b7fa22c0b9e4b9841fa3175b2ad8e607ae3525a8"></a>
|
||||
<a id="persistence-type-sha256-7a5b68bd1a5118c827df9e2466acc5e4d16b83e3f97a2304d992958647592690"></a>
|
||||
|
||||
<a id="persistence-type-messagesource"></a>
|
||||
|
||||
@@ -4184,12 +4192,19 @@ SHA-256: `390eed1028aba02774f14408647acec10ec5516e97d4f15ecde2b9989d5a69f2`
|
||||
|
||||
### `MessageSource`
|
||||
|
||||
SHA-256: `5bc2d7f02503fc6b3e1bb7e0b7fa22c0b9e4b9841fa3175b2ad8e607ae3525a8`
|
||||
SHA-256: `7a5b68bd1a5118c827df9e2466acc5e4d16b83e3f97a2304d992958647592690`
|
||||
|
||||
来源:[`packages/llm/llm/src/message.ts:136`](../packages/llm/llm/src/message.ts)
|
||||
|
||||
| kind | form 属性 | 其他必需字段 | 完整定义 |
|
||||
|---|---|---|---|
|
||||
| `action-cards` | `"catalog"` | `through`: `number` | [`{ kind: "action-cards", form: "catalog" }`](#persistence-type-sha256-dd00cdccd0ba487b92362ef67db58cd264f48c1bfd368291424a1da9a899489a) |
|
||||
| `action-cards` | `"instructions"` | `through`: `number` | [`{ kind: "action-cards", form: "instructions" }`](#persistence-type-sha256-ba2a1a8f194b1bb21f270713398f6643e206e8ff5f7f26f6d36a88e3f0f0ab10) |
|
||||
| `action-cards` | `"notice"` | `summary`: `string`; `through`: `number` | [`{ kind: "action-cards", form: "notice" }`](#persistence-type-sha256-e7f4cbb3a57f4cbdb61ea41e95bcba626ad1fff6bb9b1e063b1d50a32da6e864) |
|
||||
| `action-cards` | `"recall"` | `through`: `number` | [`{ kind: "action-cards", form: "recall" }`](#persistence-type-sha256-b613f83572fe2fbf7259c72308cafd008f4fceea897749128a48bcd158f290aa) |
|
||||
| `action-cards` | `"relay"` | `through`: `number` | [`{ kind: "action-cards", form: "relay" }`](#persistence-type-sha256-45f005e6bbb7645248be792b715a74bc7fdf5a67f5381655d3a75dcc7aa2112e) |
|
||||
| `action-cards` | `"snapshot"` | `sections`: [`ContextSnapshotSection[]`](#persistence-type-sha256-c748fb42c80a120038a8c587af80ec39924803c401364db11c8974d5bf6d0262); `through`: `number` | [`{ kind: "action-cards", form: "snapshot" }`](#persistence-type-sha256-3247e566f4340029325b70e4366b56fa9719977f1e39033b769a2ec221ab22a9) |
|
||||
| `action-cards` | 未声明 | `through`: `number` | [`{ kind: "action-cards" }`](#persistence-type-sha256-dde0cdf9d426768b649b5a9783d2144e7f900c35ef65229cd89036dbf411d1b0) |
|
||||
| `agent-instructions` | `"instructions"` | `changes`: [`AgentInstructionChange[]`](#persistence-type-sha256-2ab12a0e345658f9342816d773fe610f049982bcad82631f43b9205abe43e5ee) | [`AgentInstructionSource`](#persistence-type-sha256-6f22a9d02b9a1f1157f3b0e7bdccd7e7b12b085c4efdb709dfc74a465cd4e590) |
|
||||
| `agent-message` | `"relay"` | `senderSessionId`: `string` | [`AgentMessageSource`](#persistence-type-sha256-4a9bef9f27a942520cc2279ca7dd3082556e4bff543f66b5c0333e1bbed1cd86) |
|
||||
| `compact-checkpoint` | 未声明 | `compactionId`: `string` | [`CompactionCheckpointSource`](#persistence-type-sha256-31907de9563751822af6d9be02bafaf26faa098bbd1cb412524134d577cc1648) |
|
||||
@@ -4302,13 +4317,13 @@ SHA-256: `5bc2d7f02503fc6b3e1bb7e0b7fa22c0b9e4b9841fa3175b2ad8e607ae3525a8`
|
||||
| `webhook` | `"notice"` | `deliveryId`: `string`; `provider`: `string`; `ruleId`: `string`; `source`: `string`; `summary`: `string` | [`{ kind: "webhook", form: "notice" }`](#persistence-type-sha256-9edc162949abf93bd5ff049191b345454ba104f583937ce5580fb50f067d2b94) |
|
||||
| `working-directory` | 未声明 | 无 | [`{ kind: "working-directory" }`](#persistence-type-sha256-2235d957bf4b7c6cf959231d480f0ba1f3a6d72d82981493fb6c7c963021d3d5) |
|
||||
|
||||
<a id="persistence-type-sha256-a927d444c928ac0efd9dd8b2e7d7d04d711c264cb71578d81e0e2fd143ff669f"></a>
|
||||
<a id="persistence-type-sha256-78b9204976ab9faaf133c3488b73d1dfb6f1a4bb6c0903e3473cd41a5e1e39e1"></a>
|
||||
|
||||
### `Message[]`
|
||||
|
||||
SHA-256: `a927d444c928ac0efd9dd8b2e7d7d04d711c264cb71578d81e0e2fd143ff669f`
|
||||
SHA-256: `78b9204976ab9faaf133c3488b73d1dfb6f1a4bb6c0903e3473cd41a5e1e39e1`
|
||||
|
||||
[`Message`](#persistence-type-sha256-040cd65423bd64264d225504f1c572d239eeb1793d0c2856ad8e42bb6e1e148b) 的数组。
|
||||
[`Message`](#persistence-type-sha256-cda79b839d8cc0c7a7bd09dd067de04925f6e9037080d878b65aaa5a383f117c) 的数组。
|
||||
|
||||
<a id="persistence-type-sha256-719c51f67074f97034a6c94297fe1f4b5d3c8d392c57586dab732aa5398c7a91"></a>
|
||||
|
||||
@@ -4692,7 +4707,7 @@ SHA-256: `b56f6a885da3dc394c69a3e3cc5c0cfc4da15601b63fda4989eee8f40efc5be4`
|
||||
| `source` | 必需 | [`SessionTitleSource`](#persistence-type-sha256-30d5a537b296685770b1241c4b4bbde19d5a31ff81aa23df73fab5e90b8fc65f) |
|
||||
| `title` | 必需 | `string` |
|
||||
|
||||
<a id="persistence-type-sha256-00c054d3018c198d92f459563331edd1385e58345c677bb499791df2da0ade9f"></a>
|
||||
<a id="persistence-type-sha256-a3e299483348f27a4787a36bb3f29cd86024c65336abc10bb3d687468302c4cf"></a>
|
||||
|
||||
<a id="persistence-type-packagessessionsession-title-llmsrcindextssessiontitlellmrequesteventdata"></a>
|
||||
|
||||
@@ -4700,7 +4715,7 @@ SHA-256: `b56f6a885da3dc394c69a3e3cc5c0cfc4da15601b63fda4989eee8f40efc5be4`
|
||||
|
||||
### `SessionTitleLlmRequestEventData`
|
||||
|
||||
SHA-256: `00c054d3018c198d92f459563331edd1385e58345c677bb499791df2da0ade9f`
|
||||
SHA-256: `a3e299483348f27a4787a36bb3f29cd86024c65336abc10bb3d687468302c4cf`
|
||||
|
||||
来源:[`packages/session/session-title-llm/src/index.ts:37`](../packages/session/session-title-llm/src/index.ts)
|
||||
|
||||
@@ -4708,7 +4723,7 @@ SHA-256: `00c054d3018c198d92f459563331edd1385e58345c677bb499791df2da0ade9f`
|
||||
|---|---|---|
|
||||
| `maxTokens` | 必需 | `number` |
|
||||
| `messageSeqs` | 必需 | [`number[]`](#persistence-type-sha256-5d03ba38734809bcbd2a55221bd938b3b3fc34b49bb686c6113e9e4931e3aa78) |
|
||||
| `messages` | 必需 | [`Message[]`](#persistence-type-sha256-a927d444c928ac0efd9dd8b2e7d7d04d711c264cb71578d81e0e2fd143ff669f) |
|
||||
| `messages` | 必需 | [`Message[]`](#persistence-type-sha256-78b9204976ab9faaf133c3488b73d1dfb6f1a4bb6c0903e3473cd41a5e1e39e1) |
|
||||
| `reasoningEffort` | 可选 | `string` |
|
||||
| `route` | 必需 | [`SessionTitleModelIdentity`](#persistence-type-sha256-07e1a58c58b593f507b8e7f25723bb0aa42baae6e00f5ecfddf28cb1e64d3235) |
|
||||
| `system` | 必需 | `string` |
|
||||
@@ -5364,7 +5379,7 @@ SHA-256: `f1687f982fa3d41ef29e159feed154ecd13af4dd209acaee16038f223f2e9402`
|
||||
| `interrupted` | 未声明 | 无 | [`{ kind: "interrupted" }`](#persistence-type-sha256-56b7c047694875a843ba020dfea3c8380d54ae4ff88ab349e72004dc21e07c23) |
|
||||
| `max-tokens` | 未声明 | 无 | [`{ kind: "max-tokens" }`](#persistence-type-sha256-ab7ec5f9eb2c6dfacca5da4c37cf7ba85d04172053ee6b1ebf1709ffcd99c1a7) |
|
||||
|
||||
<a id="persistence-type-sha256-2cf075b013d363ad743b5a4982900678d108499c721bc11255137402003db711"></a>
|
||||
<a id="persistence-type-sha256-b782058cef83caf3eb44a16adeef5657e4d5cdff2d50655aba418c4490670a69"></a>
|
||||
|
||||
<a id="persistence-type-packagesllmllmsrcmessagetsusermessage"></a>
|
||||
|
||||
@@ -5372,7 +5387,7 @@ SHA-256: `f1687f982fa3d41ef29e159feed154ecd13af4dd209acaee16038f223f2e9402`
|
||||
|
||||
### `UserMessage`
|
||||
|
||||
SHA-256: `2cf075b013d363ad743b5a4982900678d108499c721bc11255137402003db711`
|
||||
SHA-256: `b782058cef83caf3eb44a16adeef5657e4d5cdff2d50655aba418c4490670a69`
|
||||
|
||||
来源:[`packages/llm/llm/src/message.ts:162`](../packages/llm/llm/src/message.ts)
|
||||
|
||||
@@ -5381,19 +5396,19 @@ SHA-256: `2cf075b013d363ad743b5a4982900678d108499c721bc11255137402003db711`
|
||||
| `content` | 必需 | [`ContentBlock[]`](#persistence-type-sha256-b52f215a6cd691058a3413c12f161fa3b563a2f4895adb3df6f744ec4b0a6ef1) |
|
||||
| `id` | 必需 | `string` |
|
||||
| `role` | 必需 | `"user"` |
|
||||
| `source` | 必需 | [`MessageSource`](#persistence-type-sha256-5bc2d7f02503fc6b3e1bb7e0b7fa22c0b9e4b9841fa3175b2ad8e607ae3525a8) |
|
||||
| `source` | 必需 | [`MessageSource`](#persistence-type-sha256-7a5b68bd1a5118c827df9e2466acc5e4d16b83e3f97a2304d992958647592690) |
|
||||
|
||||
消息源兼容策略:`source` — `session-source-attribution` v1; `session.user-message.source`; `kind`; `preserve`.
|
||||
|
||||
仅表示归属的新增 kind:`tmux-context`, `user-question-reply`, `working-directory`.
|
||||
仅表示归属的新增 kind:`action-cards`, `tmux-context`, `user-question-reply`, `working-directory`.
|
||||
|
||||
<a id="persistence-type-sha256-454a0fa879e38076bdcdbd87ef561cd67d7e43e58a287cf7dbaa7b6cf7847020"></a>
|
||||
<a id="persistence-type-sha256-5d00abf938272f22eb47199e9d40801e8d8ec4c88e2b138b15aa2a5a5bf87520"></a>
|
||||
|
||||
### `UserMessage[]`
|
||||
|
||||
SHA-256: `454a0fa879e38076bdcdbd87ef561cd67d7e43e58a287cf7dbaa7b6cf7847020`
|
||||
SHA-256: `5d00abf938272f22eb47199e9d40801e8d8ec4c88e2b138b15aa2a5a5bf87520`
|
||||
|
||||
[`UserMessage`](#persistence-type-sha256-2cf075b013d363ad743b5a4982900678d108499c721bc11255137402003db711) 的数组。
|
||||
[`UserMessage`](#persistence-type-sha256-b782058cef83caf3eb44a16adeef5657e4d5cdff2d50655aba418c4490670a69) 的数组。
|
||||
|
||||
<a id="persistence-type-sha256-c2deb7c9183735d4e0fffddf5c623f4e34daa1c8e96b111982e957dfcbbcf896"></a>
|
||||
|
||||
@@ -6278,18 +6293,18 @@ SHA-256: `ad0c38a0adb82a94c925456df41586d9b5f9202fca18593eae2213d4445b4585`
|
||||
| `reason` | 必需 | [`RequestHeaderReason`](#persistence-type-sha256-530da6c0267813bb4511af72883cc518834e624e3b3220a7062955fd57a788a6) |
|
||||
| `startsSeries` | 可选 | `true` |
|
||||
|
||||
<a id="persistence-type-sha256-f4ed4717b4c259e933b550a8dcd90dc93628cda8a3c7affcaa53b9c13c1d53eb"></a>
|
||||
<a id="persistence-type-sha256-7404c6123fdaa591474a37979a5a8ae70d1387af7c9f09bfe568b218935a974d"></a>
|
||||
|
||||
### `{ headerSeq?, message, step, turn }`
|
||||
|
||||
SHA-256: `f4ed4717b4c259e933b550a8dcd90dc93628cda8a3c7affcaa53b9c13c1d53eb`
|
||||
SHA-256: `7404c6123fdaa591474a37979a5a8ae70d1387af7c9f09bfe568b218935a974d`
|
||||
|
||||
来源:[`packages/core/session/src/types.ts:313`](../packages/core/session/src/types.ts)
|
||||
|
||||
| 属性 | 存在性 | 类型 |
|
||||
|---|---|---|
|
||||
| `headerSeq` | 可选 | `number` |
|
||||
| `message` | 必需 | [`DeveloperMessage`](#persistence-type-sha256-0f6265188dae7ba6faa26830a180bb4deb0760561f97ee0c9d399ccf6c9cf1f7) |
|
||||
| `message` | 必需 | [`DeveloperMessage`](#persistence-type-sha256-7580e7d96dc8475fffe813a42af499665de3d4517fcdb3bc2337d0340e98d616) |
|
||||
| `step` | 必需 | `number` |
|
||||
| `turn` | 必需 | `number` |
|
||||
|
||||
@@ -6373,17 +6388,17 @@ SHA-256: `17d1afb770d9941936130996da00dc86782cfef731d8d6526162c301256a4ac3`
|
||||
|---|---|---|
|
||||
| `inherited` | 可选 | `true` |
|
||||
|
||||
<a id="persistence-type-sha256-fa106c5b33b657e8ef16e8cbf39f3b7d44e5cbcdf4f9303d9db6410f28951e42"></a>
|
||||
<a id="persistence-type-sha256-b2a948a5340a9341fa3bab99507c7090c5b0456de72ec28b5b157b8df3f1d640"></a>
|
||||
|
||||
### `{ inserted, outcome?, removedCount?, start, … }`
|
||||
|
||||
SHA-256: `fa106c5b33b657e8ef16e8cbf39f3b7d44e5cbcdf4f9303d9db6410f28951e42`
|
||||
SHA-256: `b2a948a5340a9341fa3bab99507c7090c5b0456de72ec28b5b157b8df3f1d640`
|
||||
|
||||
来源:[`packages/core/agent/src/types.ts:110`](../packages/core/agent/src/types.ts)
|
||||
|
||||
| 属性 | 存在性 | 类型 |
|
||||
|---|---|---|
|
||||
| `inserted` | 必需 | [`UserMessage[]`](#persistence-type-sha256-454a0fa879e38076bdcdbd87ef561cd67d7e43e58a287cf7dbaa7b6cf7847020) |
|
||||
| `inserted` | 必需 | [`UserMessage[]`](#persistence-type-sha256-5d00abf938272f22eb47199e9d40801e8d8ec4c88e2b138b15aa2a5a5bf87520) |
|
||||
| `outcome` | 可选 | `"canceled"` |
|
||||
| `removedCount` | 可选 | `number` |
|
||||
| `start` | 必需 | `number` |
|
||||
@@ -6419,6 +6434,91 @@ SHA-256: `0a30c3be336cdd4f8f34e66543a3d46d611c43986edd9b3ce6cbb9b721d3b5d3`
|
||||
| `kind` | 必需 | `"aborted"` |
|
||||
| `reason` | 必需 | [`TurnEndCancelCause`](#persistence-type-sha256-1f8c126cfab3df812cd115cfc23e3256f0fa2383400f4ce91ecad313577e59b0) |
|
||||
|
||||
<a id="persistence-type-sha256-dde0cdf9d426768b649b5a9783d2144e7f900c35ef65229cd89036dbf411d1b0"></a>
|
||||
|
||||
### `{ kind: "action-cards" }`
|
||||
|
||||
SHA-256: `dde0cdf9d426768b649b5a9783d2144e7f900c35ef65229cd89036dbf411d1b0`
|
||||
|
||||
| 属性 | 存在性 | 类型 |
|
||||
|---|---|---|
|
||||
| `kind` | 必需 | `"action-cards"` |
|
||||
| `through` | 必需 | `number` |
|
||||
|
||||
<a id="persistence-type-sha256-dd00cdccd0ba487b92362ef67db58cd264f48c1bfd368291424a1da9a899489a"></a>
|
||||
|
||||
### `{ kind: "action-cards", form: "catalog" }`
|
||||
|
||||
SHA-256: `dd00cdccd0ba487b92362ef67db58cd264f48c1bfd368291424a1da9a899489a`
|
||||
|
||||
| 属性 | 存在性 | 类型 |
|
||||
|---|---|---|
|
||||
| `form` | 必需 | `"catalog"` |
|
||||
| `kind` | 必需 | `"action-cards"` |
|
||||
| `through` | 必需 | `number` |
|
||||
|
||||
<a id="persistence-type-sha256-ba2a1a8f194b1bb21f270713398f6643e206e8ff5f7f26f6d36a88e3f0f0ab10"></a>
|
||||
|
||||
### `{ kind: "action-cards", form: "instructions" }`
|
||||
|
||||
SHA-256: `ba2a1a8f194b1bb21f270713398f6643e206e8ff5f7f26f6d36a88e3f0f0ab10`
|
||||
|
||||
| 属性 | 存在性 | 类型 |
|
||||
|---|---|---|
|
||||
| `form` | 必需 | `"instructions"` |
|
||||
| `kind` | 必需 | `"action-cards"` |
|
||||
| `through` | 必需 | `number` |
|
||||
|
||||
<a id="persistence-type-sha256-e7f4cbb3a57f4cbdb61ea41e95bcba626ad1fff6bb9b1e063b1d50a32da6e864"></a>
|
||||
|
||||
### `{ kind: "action-cards", form: "notice" }`
|
||||
|
||||
SHA-256: `e7f4cbb3a57f4cbdb61ea41e95bcba626ad1fff6bb9b1e063b1d50a32da6e864`
|
||||
|
||||
| 属性 | 存在性 | 类型 |
|
||||
|---|---|---|
|
||||
| `form` | 必需 | `"notice"` |
|
||||
| `kind` | 必需 | `"action-cards"` |
|
||||
| `summary` | 必需 | `string` |
|
||||
| `through` | 必需 | `number` |
|
||||
|
||||
<a id="persistence-type-sha256-b613f83572fe2fbf7259c72308cafd008f4fceea897749128a48bcd158f290aa"></a>
|
||||
|
||||
### `{ kind: "action-cards", form: "recall" }`
|
||||
|
||||
SHA-256: `b613f83572fe2fbf7259c72308cafd008f4fceea897749128a48bcd158f290aa`
|
||||
|
||||
| 属性 | 存在性 | 类型 |
|
||||
|---|---|---|
|
||||
| `form` | 必需 | `"recall"` |
|
||||
| `kind` | 必需 | `"action-cards"` |
|
||||
| `through` | 必需 | `number` |
|
||||
|
||||
<a id="persistence-type-sha256-45f005e6bbb7645248be792b715a74bc7fdf5a67f5381655d3a75dcc7aa2112e"></a>
|
||||
|
||||
### `{ kind: "action-cards", form: "relay" }`
|
||||
|
||||
SHA-256: `45f005e6bbb7645248be792b715a74bc7fdf5a67f5381655d3a75dcc7aa2112e`
|
||||
|
||||
| 属性 | 存在性 | 类型 |
|
||||
|---|---|---|
|
||||
| `form` | 必需 | `"relay"` |
|
||||
| `kind` | 必需 | `"action-cards"` |
|
||||
| `through` | 必需 | `number` |
|
||||
|
||||
<a id="persistence-type-sha256-3247e566f4340029325b70e4366b56fa9719977f1e39033b769a2ec221ab22a9"></a>
|
||||
|
||||
### `{ kind: "action-cards", form: "snapshot" }`
|
||||
|
||||
SHA-256: `3247e566f4340029325b70e4366b56fa9719977f1e39033b769a2ec221ab22a9`
|
||||
|
||||
| 属性 | 存在性 | 类型 |
|
||||
|---|---|---|
|
||||
| `form` | 必需 | `"snapshot"` |
|
||||
| `kind` | 必需 | `"action-cards"` |
|
||||
| `sections` | 必需 | [`ContextSnapshotSection[]`](#persistence-type-sha256-c748fb42c80a120038a8c587af80ec39924803c401364db11c8974d5bf6d0262) |
|
||||
| `through` | 必需 | `number` |
|
||||
|
||||
<a id="persistence-type-sha256-023a355b2be0d688fb6e4df8388dadb942761d46cfe96d0f499aae9631a159d4"></a>
|
||||
|
||||
### `{ kind: "blocked" }`
|
||||
@@ -7945,17 +8045,17 @@ SHA-256: `a10c17474eaf2ddab7095a099e0fe3d046fc18e56c3e344fc8894c05ff9ef97b`
|
||||
| `time` | 必需 | `number` |
|
||||
| `type` | 必需 | `"agent-preset/selected"` |
|
||||
|
||||
<a id="persistence-type-sha256-0755b7d1128319ba2e389619cbbf2c961ad648882b4e91da7f3e9582cc8a2034"></a>
|
||||
<a id="persistence-type-sha256-b36fd842cd004b532ce96fd5d6f5be28e017eda043131aa3cf5e69edc436108e"></a>
|
||||
|
||||
<a id="persistence-type-eventagentinboxspliced"></a>
|
||||
|
||||
### `{ type: "agent/inbox/spliced" }`
|
||||
|
||||
SHA-256: `0755b7d1128319ba2e389619cbbf2c961ad648882b4e91da7f3e9582cc8a2034`
|
||||
SHA-256: `b36fd842cd004b532ce96fd5d6f5be28e017eda043131aa3cf5e69edc436108e`
|
||||
|
||||
| 属性 | 存在性 | 类型 |
|
||||
|---|---|---|
|
||||
| `data` | 必需 | [`{ inserted, outcome?, removedCount?, start, … }`](#persistence-type-sha256-fa106c5b33b657e8ef16e8cbf39f3b7d44e5cbcdf4f9303d9db6410f28951e42) |
|
||||
| `data` | 必需 | [`{ inserted, outcome?, removedCount?, start, … }`](#persistence-type-sha256-b2a948a5340a9341fa3bab99507c7090c5b0456de72ec28b5b157b8df3f1d640) |
|
||||
| `ignorable` | 可选 | `true` |
|
||||
| `seq` | 必需 | `number` |
|
||||
| `time` | 必需 | `number` |
|
||||
@@ -8196,17 +8296,17 @@ SHA-256: `13d3d180f977bf78081d487ffa0ecb75857349bcab29a5a3fb48189fca2a6176`
|
||||
| `time` | 必需 | `number` |
|
||||
| `type` | 必需 | `"deliverables/presented"` |
|
||||
|
||||
<a id="persistence-type-sha256-97e0162f983c27456ec71269fb4976b1851588b8c1aeac5d071d43e11f95e03c"></a>
|
||||
<a id="persistence-type-sha256-5ef58f2a1bdc576c1f12fa1f4da1920ece020b13c0f991a578cddcbeb28bc5be"></a>
|
||||
|
||||
<a id="persistence-type-eventdevelopermessage"></a>
|
||||
|
||||
### `{ type: "developer/message" }`
|
||||
|
||||
SHA-256: `97e0162f983c27456ec71269fb4976b1851588b8c1aeac5d071d43e11f95e03c`
|
||||
SHA-256: `5ef58f2a1bdc576c1f12fa1f4da1920ece020b13c0f991a578cddcbeb28bc5be`
|
||||
|
||||
| 属性 | 存在性 | 类型 |
|
||||
|---|---|---|
|
||||
| `data` | 必需 | [`{ headerSeq?, message, step, turn }`](#persistence-type-sha256-f4ed4717b4c259e933b550a8dcd90dc93628cda8a3c7affcaa53b9c13c1d53eb) |
|
||||
| `data` | 必需 | [`{ headerSeq?, message, step, turn }`](#persistence-type-sha256-7404c6123fdaa591474a37979a5a8ae70d1387af7c9f09bfe568b218935a974d) |
|
||||
| `ignorable` | 可选 | `true` |
|
||||
| `seq` | 必需 | `number` |
|
||||
| `sourceEventSeqs` | 可选 | [`number[]`](#persistence-type-sha256-5d03ba38734809bcbd2a55221bd938b3b3fc34b49bb686c6113e9e4931e3aa78) |
|
||||
@@ -8606,17 +8706,17 @@ SHA-256: `1b912703e2d64f91c99c675b8f805b01076c8325b905c1218ad81ef0b24909d5`
|
||||
| `time` | 必需 | `number` |
|
||||
| `type` | 必需 | `"session/title"` |
|
||||
|
||||
<a id="persistence-type-sha256-79a4c87f8bfb4d6d05cd9952b99210d6a7db3b478c4a01d94b4c50602308c056"></a>
|
||||
<a id="persistence-type-sha256-efa1a091017ce533e38b0ef3e14d11a5c102ff1793229b18dad719a4268d9adc"></a>
|
||||
|
||||
<a id="persistence-type-eventsessiontitle-llm-request"></a>
|
||||
|
||||
### `{ type: "session/title-llm-request" }`
|
||||
|
||||
SHA-256: `79a4c87f8bfb4d6d05cd9952b99210d6a7db3b478c4a01d94b4c50602308c056`
|
||||
SHA-256: `efa1a091017ce533e38b0ef3e14d11a5c102ff1793229b18dad719a4268d9adc`
|
||||
|
||||
| 属性 | 存在性 | 类型 |
|
||||
|---|---|---|
|
||||
| `data` | 必需 | [`SessionTitleLlmRequestEventData`](#persistence-type-sha256-00c054d3018c198d92f459563331edd1385e58345c677bb499791df2da0ade9f) |
|
||||
| `data` | 必需 | [`SessionTitleLlmRequestEventData`](#persistence-type-sha256-a3e299483348f27a4787a36bb3f29cd86024c65336abc10bb3d687468302c4cf) |
|
||||
| `ignorable` | 可选 | `true` |
|
||||
| `seq` | 必需 | `number` |
|
||||
| `time` | 必需 | `number` |
|
||||
@@ -9039,17 +9139,17 @@ SHA-256: `f1a96afe7503ac1817de769cd0ba13d9b80111c7034c50106b3344ecc14cc515`
|
||||
| `type` | 必需 | `"usage"` |
|
||||
| `usage` | 必需 | [`TokenUsage`](#persistence-type-sha256-fec5442b9ee4122e10514d81d5a43648003fe8bfb7ee2ba50c0cdbdd383ed394) |
|
||||
|
||||
<a id="persistence-type-sha256-2ae8594a998c9862a597129e782277bcc518266712a703b5c3161bdf552d13b8"></a>
|
||||
<a id="persistence-type-sha256-58b122df513aeaf7ddc5783dbb1fd844e2979bb273964e30ae351a8db6510019"></a>
|
||||
|
||||
<a id="persistence-type-eventusermessage"></a>
|
||||
|
||||
### `{ type: "user/message" }`
|
||||
|
||||
SHA-256: `2ae8594a998c9862a597129e782277bcc518266712a703b5c3161bdf552d13b8`
|
||||
SHA-256: `58b122df513aeaf7ddc5783dbb1fd844e2979bb273964e30ae351a8db6510019`
|
||||
|
||||
| 属性 | 存在性 | 类型 |
|
||||
|---|---|---|
|
||||
| `data` | 必需 | [`UserMessage`](#persistence-type-sha256-2cf075b013d363ad743b5a4982900678d108499c721bc11255137402003db711) |
|
||||
| `data` | 必需 | [`UserMessage`](#persistence-type-sha256-b782058cef83caf3eb44a16adeef5657e4d5cdff2d50655aba418c4490670a69) |
|
||||
| `ignorable` | 可选 | `true` |
|
||||
| `seq` | 必需 | `number` |
|
||||
| `sourceEventSeqs` | 可选 | [`number[]`](#persistence-type-sha256-5d03ba38734809bcbd2a55221bd938b3b3fc34b49bb686c6113e9e4931e3aa78) |
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
# Bilingual-pair consistency record for 2026-10-22-action-card-status.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/persistence-changes/2026-10-22-action-card-status.md
|
||||
/:
|
||||
en: 3d5a424ae7d7e46b
|
||||
zh: c22a8e4a62d8cc1a
|
||||
/2026-10-22-action-card-status:
|
||||
en: f580a2fb64e941db
|
||||
zh: 0e34217155210da6
|
||||
/2026-10-22-action-card-status/summary:
|
||||
en: 3da2594bf2891e0e
|
||||
zh: 5bc7d279d99400aa
|
||||
/2026-10-22-action-card-status/table-of-contents:
|
||||
en: 6cf314a069ceb451
|
||||
zh: 9adff678e9ecab3b
|
||||
/2026-10-22-action-card-status/declaration:
|
||||
en: 6907136f28e48c90
|
||||
zh: 02f8298485f3d8e7
|
||||
/2026-10-22-action-card-status/compatibility:
|
||||
en: fbf4d1ada55f35fe
|
||||
zh: bd5ce9a23c55fac6
|
||||
/2026-10-22-action-card-status/verification:
|
||||
en: 91043c4f0b19e7bc
|
||||
zh: ee1c541133475bb8
|
||||
/2026-10-22-action-card-status/dev-note:
|
||||
en: b75c8458928b72b9
|
||||
zh: 003ba4e17b4b5269
|
||||
@@ -0,0 +1,60 @@
|
||||
---
|
||||
description: "Records a persistence type transition and its compatibility acknowledgement."
|
||||
kind: persistence-change
|
||||
---
|
||||
|
||||
# 2026-10-22-action-card-status
|
||||
|
||||
English | [中文](2026-10-22-action-card-status.zh.md)
|
||||
|
||||
## Summary
|
||||
|
||||
Adds action-card status attribution to logged model context.
|
||||
|
||||
## Table of Contents
|
||||
|
||||
- [Declaration](#declaration)
|
||||
- [Compatibility](#compatibility)
|
||||
- [Verification](#verification)
|
||||
- [Dev Note](#dev-note)
|
||||
|
||||
<a id="declaration"></a>
|
||||
## Declaration
|
||||
|
||||
```yaml persistence-change
|
||||
schemaVersion: 1
|
||||
id: 2026-10-22-action-card-status
|
||||
baseline: false
|
||||
changes:
|
||||
- root: "event:agent/inbox/spliced"
|
||||
previous: "2026-10-13-user-rpc-principal"
|
||||
after: "b36fd842cd004b532ce96fd5d6f5be28e017eda043131aa3cf5e69edc436108e"
|
||||
decision: same-version
|
||||
- root: "event:developer/message"
|
||||
previous: "2026-10-13-user-rpc-principal"
|
||||
after: "5ef58f2a1bdc576c1f12fa1f4da1920ece020b13c0f991a578cddcbeb28bc5be"
|
||||
decision: same-version
|
||||
- root: "event:session/title-llm-request"
|
||||
previous: "2026-10-13-user-rpc-principal"
|
||||
after: "efa1a091017ce533e38b0ef3e14d11a5c102ff1793229b18dad719a4268d9adc"
|
||||
decision: same-version
|
||||
- root: "event:user/message"
|
||||
previous: "2026-10-13-user-rpc-principal"
|
||||
after: "58b122df513aeaf7ddc5783dbb1fd844e2979bb273964e30ae351a8db6510019"
|
||||
decision: same-version
|
||||
```
|
||||
|
||||
<a id="compatibility"></a>
|
||||
## Compatibility
|
||||
|
||||
Existing messages and records are unchanged. Readers without the action-card plugin preserve the new action-cards source kind and its JSON metadata and derive the recorded text as ordinary context. Only the producer uses the through sequence, to acknowledge delivered decisions; it grants no authority and does not change replay interpretation.
|
||||
|
||||
<a id="verification"></a>
|
||||
## Verification
|
||||
|
||||
pnpm exec vitest run on the action-cards, creation-recommendations, client-ui-action-cards and client-ui-creation-recommendations tests: 120 tests passed with 100% coverage of their sources. The Web creation-recommendations replay logs the status notice of a dismissed card before the next answer.
|
||||
|
||||
<a id="dev-note"></a>
|
||||
## Dev Note
|
||||
|
||||
None.
|
||||
@@ -0,0 +1,249 @@
|
||||
{
|
||||
"formatVersion": 2,
|
||||
"roots": [
|
||||
{"key":"event:agent/inbox/spliced","kind":"event","event":"agent/inbox/spliced","surface":false,"digest":"b36fd842cd004b532ce96fd5d6f5be28e017eda043131aa3cf5e69edc436108e"},
|
||||
{"key":"event:developer/message","kind":"event","event":"developer/message","surface":true,"digest":"5ef58f2a1bdc576c1f12fa1f4da1920ece020b13c0f991a578cddcbeb28bc5be"},
|
||||
{"key":"event:session/title-llm-request","kind":"event","event":"session/title-llm-request","surface":false,"digest":"efa1a091017ce533e38b0ef3e14d11a5c102ff1793229b18dad719a4268d9adc"},
|
||||
{"key":"event:user/message","kind":"event","event":"user/message","surface":true,"digest":"58b122df513aeaf7ddc5783dbb1fd844e2979bb273964e30ae351a8db6510019"}
|
||||
],
|
||||
"types": [],
|
||||
"nodes": {
|
||||
"0203243b72fc867a": {"kind":"object","properties":[{"name":"kind","type":"24b10f7cdae64928","optional":false}],"indices":[]},
|
||||
"022623b9ef98ec47": {"kind":"object","properties":[{"name":"form","type":"383cf73ae4748e5b","optional":false},{"name":"kind","type":"f68c335306535a00","optional":false}],"indices":[]},
|
||||
"02b2c23f2d94b028": {"kind":"object","properties":[{"name":"kind","type":"c5687b1313206a6f","optional":false}],"indices":[]},
|
||||
"05205074b24d8340": {"kind":"literal","value":"action-cards"},
|
||||
"0657d3ca5ac4e7bf": {"kind":"primitive","type":"number"},
|
||||
"07e1a58c58b593f5": {"kind":"object","properties":[{"name":"model","type":"4cd48f3e5108bd6e","optional":false},{"name":"provider","type":"4cd48f3e5108bd6e","optional":false}],"indices":[]},
|
||||
"09655b34d7f3cf1e": {"kind":"literal","value":"system-prompt"},
|
||||
"09f3f8dc417f2782": {"kind":"object","properties":[{"name":"content","type":"b52f215a6cd69105","optional":false},{"name":"id","type":"4cd48f3e5108bd6e","optional":false},{"name":"role","type":"8af841fc9b265ade","optional":false},{"name":"source","type":"65a8400e451e667e","optional":false}],"indices":[]},
|
||||
"0ed8d1108fe7a5e1": {"kind":"object","properties":[{"name":"kind","type":"a9059a81430b3207","optional":false}],"indices":[]},
|
||||
"0eeb17e1df89b1eb": {"kind":"object","properties":[{"name":"form","type":"fee1caf8ab6a65c1","optional":false},{"name":"kind","type":"24b10f7cdae64928","optional":false}],"indices":[]},
|
||||
"0f46153645c29784": {"kind":"object","properties":[{"name":"height","type":"0657d3ca5ac4e7bf","optional":false},{"name":"width","type":"0657d3ca5ac4e7bf","optional":false}],"indices":[]},
|
||||
"0fe52387f6505270": {"kind":"literal","value":"plan-mode"},
|
||||
"11638dc58a31496f": {"kind":"object","properties":[{"name":"form","type":"6f9e00383836275e","optional":false},{"name":"kind","type":"2f3f201c8846e19c","optional":false},{"name":"sections","type":"c748fb42c80a1200","optional":false}],"indices":[]},
|
||||
"12d5808fac1996b9": {"kind":"object","properties":[{"name":"attachment","type":"b0b0eb1b16490f6b","optional":false},{"name":"offloaded","type":"dacf3d5f3e4ff619","optional":true},{"name":"type","type":"fb8b6a2e53cb9cf4","optional":false}],"indices":[]},
|
||||
"1379f0b72275994d": {"kind":"literal","value":"developer/message"},
|
||||
"16d0507cb94b4cfc": {"kind":"literal","value":"relay"},
|
||||
"1922cd79a70806c1": {"kind":"literal","value":"skill-invocation"},
|
||||
"1938c8c20f1cba7c": {"kind":"object","properties":[{"name":"form","type":"fee1caf8ab6a65c1","optional":false},{"name":"kind","type":"d9edf1862e4471d6","optional":false}],"indices":[]},
|
||||
"1e709346005826eb": {"kind":"object","properties":[{"name":"form","type":"aec150797b655c5f","optional":false},{"name":"kind","type":"d9edf1862e4471d6","optional":false}],"indices":[]},
|
||||
"1f0133217eeeffd8": {"kind":"literal","value":"tool-call"},
|
||||
"1f1385dbc3e875c0": {"kind":"literal","value":"repeat-tool-reminder"},
|
||||
"1fdad624334d3548": {"kind":"object","properties":[{"name":"form","type":"16d0507cb94b4cfc","optional":false},{"name":"kind","type":"bb94f3217aa56c88","optional":false}],"indices":[]},
|
||||
"2152caf1a71e588e": {"kind":"object","properties":[{"name":"kind","type":"2e4debca12f2c449","optional":false},{"name":"messageId","type":"4cd48f3e5108bd6e","optional":false},{"name":"senderId","type":"4cd48f3e5108bd6e","optional":false},{"name":"senderName","type":"4cd48f3e5108bd6e","optional":false},{"name":"teamId","type":"4cd48f3e5108bd6e","optional":false}],"indices":[]},
|
||||
"2235d957bf4b7c6c": {"kind":"object","properties":[{"name":"kind","type":"7b1ce60193fa8b69","optional":false}],"indices":[]},
|
||||
"224aa11d4d5f88c4": {"kind":"object","properties":[{"name":"form","type":"fee1caf8ab6a65c1","optional":false},{"name":"kind","type":"23af3759678a30de","optional":false}],"indices":[]},
|
||||
"23af3759678a30de": {"kind":"literal","value":"dsh-session-title-llm"},
|
||||
"24b10f7cdae64928": {"kind":"literal","value":"runtime-context"},
|
||||
"24ce31aa528272e5": {"kind":"object","properties":[{"name":"kind","type":"99e7e7d7fed55ae6","optional":false}],"indices":[]},
|
||||
"260523b412c19ad8": {"kind":"object","properties":[{"name":"form","type":"aec150797b655c5f","optional":false},{"name":"kind","type":"2f3f201c8846e19c","optional":false}],"indices":[]},
|
||||
"2765e9119edf5816": {"kind":"literal","value":"model"},
|
||||
"277b61f9c6f81704": {"kind":"literal","value":"file"},
|
||||
"28936c614bd4e7e2": {"kind":"object","properties":[{"name":"form","type":"6f9e00383836275e","optional":false},{"name":"kind","type":"d9edf1862e4471d6","optional":false},{"name":"sections","type":"c748fb42c80a1200","optional":false}],"indices":[]},
|
||||
"290f32bfd81ff85a": {"kind":"object","properties":[{"name":"kind","type":"23af3759678a30de","optional":false}],"indices":[]},
|
||||
"297fbd8067d7815a": {"kind":"object","properties":[{"name":"form","type":"aec150797b655c5f","optional":false},{"name":"kind","type":"a9059a81430b3207","optional":false}],"indices":[]},
|
||||
"2aad1179f9576314": {"kind":"object","properties":[{"name":"form","type":"6f9e00383836275e","optional":false},{"name":"kind","type":"24b10f7cdae64928","optional":false},{"name":"sections","type":"c748fb42c80a1200","optional":false}],"indices":[]},
|
||||
"2ab12a0e345658f9": {"kind":"array","element":"83da72c6857601c7"},
|
||||
"2e4debca12f2c449": {"kind":"literal","value":"team-message"},
|
||||
"2f1e6a7ebace43d7": {"kind":"union","types":["3f74ba74acd10644","58f94390b982f8a5","de30b1fa12c75f81","ebb768d85ec87fb6"]},
|
||||
"2f3f201c8846e19c": {"kind":"literal","value":"tool-goal"},
|
||||
"312aee2f0c42aabb": {"kind":"object","properties":[{"name":"form","type":"e8de0f457fed5b9f","optional":false},{"name":"kind","type":"d9edf1862e4471d6","optional":false},{"name":"summary","type":"4cd48f3e5108bd6e","optional":false}],"indices":[]},
|
||||
"31907de956375182": {"kind":"object","properties":[{"name":"compactionId","type":"4cd48f3e5108bd6e","optional":false},{"name":"kind","type":"6b23ed9ce1b397e6","optional":false},{"name":"sourceCommandId","type":"4cd48f3e5108bd6e","optional":true}],"indices":[]},
|
||||
"3247e566f4340029": {"kind":"object","properties":[{"name":"form","type":"6f9e00383836275e","optional":false},{"name":"kind","type":"05205074b24d8340","optional":false},{"name":"sections","type":"c748fb42c80a1200","optional":false},{"name":"through","type":"0657d3ca5ac4e7bf","optional":false}],"indices":[]},
|
||||
"335e242de1fcc17b": {"kind":"union","types":["bcf0caf62d964b2f","e438a9d4fb883b3e"]},
|
||||
"383cf73ae4748e5b": {"kind":"literal","value":"recall"},
|
||||
"3b04790e08b35241": {"kind":"object","properties":[{"name":"form","type":"aec150797b655c5f","optional":false},{"name":"kind","type":"0fe52387f6505270","optional":false}],"indices":[]},
|
||||
"3b4f2c9ef2c1217e": {"kind":"object","properties":[{"name":"form","type":"383cf73ae4748e5b","optional":false},{"name":"kind","type":"bb94f3217aa56c88","optional":false}],"indices":[]},
|
||||
"3bd652ebfa8726b3": {"kind":"union","types":["0657d3ca5ac4e7bf","938f7c7357bc403e"]},
|
||||
"3bdb8dc6989655b0": {"kind":"object","properties":[{"name":"form","type":"6f9e00383836275e","optional":false},{"name":"kind","type":"a9059a81430b3207","optional":false},{"name":"sections","type":"c748fb42c80a1200","optional":false}],"indices":[]},
|
||||
"3c2535ca0a2062f1": {"kind":"literal","value":"reasoning"},
|
||||
"3e2ece4967cfebe9": {"kind":"literal","value":"next-step"},
|
||||
"3f74ba74acd10644": {"kind":"literal","value":"image/jpeg"},
|
||||
"408927267422a7b2": {"kind":"object","properties":[{"name":"form","type":"fee1caf8ab6a65c1","optional":false},{"name":"kind","type":"0fe52387f6505270","optional":false}],"indices":[]},
|
||||
"43e311235aa537df": {"kind":"object","properties":[{"name":"toolName","type":"4cd48f3e5108bd6e","optional":false},{"name":"type","type":"83d6916021eede8f","optional":false}],"indices":[]},
|
||||
"45f005e6bbb76452": {"kind":"object","properties":[{"name":"form","type":"16d0507cb94b4cfc","optional":false},{"name":"kind","type":"05205074b24d8340","optional":false},{"name":"through","type":"0657d3ca5ac4e7bf","optional":false}],"indices":[]},
|
||||
"4991dfc415c9efeb": {"kind":"object","properties":[{"name":"form","type":"16d0507cb94b4cfc","optional":false},{"name":"kind","type":"1f1385dbc3e875c0","optional":false}],"indices":[]},
|
||||
"49dab019d00e8c26": {"kind":"object","properties":[{"name":"form","type":"6f9e00383836275e","optional":false},{"name":"kind","type":"78a9be340090b735","optional":false},{"name":"sections","type":"c748fb42c80a1200","optional":false}],"indices":[]},
|
||||
"4a9bef9f27a94252": {"kind":"object","properties":[{"name":"form","type":"16d0507cb94b4cfc","optional":false},{"name":"kind","type":"82470020b5bfcb1a","optional":false},{"name":"senderSessionId","type":"4cd48f3e5108bd6e","optional":false}],"indices":[]},
|
||||
"4b259f7f8f0a44ad": {"kind":"object","properties":[{"name":"content","type":"b52f215a6cd69105","optional":false},{"name":"id","type":"4cd48f3e5108bd6e","optional":false},{"name":"isError","type":"aa93010d0e521ad7","optional":true},{"name":"role","type":"a13d8f379222ece8","optional":false},{"name":"source","type":"d9c462b9f62fdd3e","optional":false},{"name":"toolCallId","type":"4cd48f3e5108bd6e","optional":false}],"indices":[]},
|
||||
"4cd48f3e5108bd6e": {"kind":"primitive","type":"string"},
|
||||
"4e44c9118152f682": {"kind":"literal","value":"text"},
|
||||
"4e88776858652856": {"kind":"object","properties":[{"name":"text","type":"4cd48f3e5108bd6e","optional":false},{"name":"type","type":"4e44c9118152f682","optional":false}],"indices":[]},
|
||||
"4e97c3d85c0fc817": {"kind":"object","properties":[{"name":"form","type":"e8de0f457fed5b9f","optional":false},{"name":"kind","type":"bf16d2e98a7f1389","optional":false},{"name":"senderSessionId","type":"4cd48f3e5108bd6e","optional":false},{"name":"summary","type":"4cd48f3e5108bd6e","optional":false}],"indices":[]},
|
||||
"4edec1b770e8ec4c": {"kind":"literal","value":"ptc-mode"},
|
||||
"4f91f187baeabef5": {"kind":"object","properties":[{"name":"capturedFormatVersion","type":"0657d3ca5ac4e7bf","optional":true},{"name":"capturedThroughSeq","type":"3bd652ebfa8726b3","optional":false},{"name":"compacted","type":"aa93010d0e521ad7","optional":false},{"name":"inputIndex","type":"0657d3ca5ac4e7bf","optional":false},{"name":"label","type":"4cd48f3e5108bd6e","optional":false},{"name":"omittedBytes","type":"0657d3ca5ac4e7bf","optional":false},{"name":"omittedMessages","type":"0657d3ca5ac4e7bf","optional":false},{"name":"originalMessages","type":"0657d3ca5ac4e7bf","optional":false},{"name":"retainedMessages","type":"0657d3ca5ac4e7bf","optional":false},{"name":"sessionId","type":"4cd48f3e5108bd6e","optional":false},{"name":"truncated","type":"aa93010d0e521ad7","optional":false}],"indices":[]},
|
||||
"52c6113cb0e53f34": {"kind":"object","properties":[{"name":"form","type":"6f9e00383836275e","optional":false},{"name":"kind","type":"9ac52f0f84fec2eb","optional":false},{"name":"sections","type":"c748fb42c80a1200","optional":false}],"indices":[]},
|
||||
"53cf1704ae0709c7": {"kind":"object","properties":[{"name":"form","type":"fee1caf8ab6a65c1","optional":false},{"name":"kind","type":"99e7e7d7fed55ae6","optional":false}],"indices":[]},
|
||||
"5654685d7557ec74": {"kind":"object","properties":[{"name":"form","type":"6f9e00383836275e","optional":false},{"name":"kind","type":"f68c335306535a00","optional":false},{"name":"sections","type":"c748fb42c80a1200","optional":false}],"indices":[]},
|
||||
"58015da1c1950a66": {"kind":"object","properties":[{"name":"form","type":"aec150797b655c5f","optional":false},{"name":"kind","type":"24b10f7cdae64928","optional":false}],"indices":[]},
|
||||
"587bb11da730e06a": {"kind":"literal","value":"session/title-llm-request"},
|
||||
"589d0d91239681f8": {"kind":"literal","value":"developer"},
|
||||
"58b122df513aeaf7": {"kind":"object","properties":[{"name":"data","type":"b782058cef83caf3","optional":false},{"name":"ignorable","type":"dacf3d5f3e4ff619","optional":true},{"name":"seq","type":"0657d3ca5ac4e7bf","optional":false},{"name":"sourceEventSeqs","type":"5d03ba38734809bc","optional":true},{"name":"surfaceOp","type":"335e242de1fcc17b","optional":false},{"name":"time","type":"0657d3ca5ac4e7bf","optional":false},{"name":"type","type":"de25352d2dc41963","optional":false}],"indices":[]},
|
||||
"58f94390b982f8a5": {"kind":"literal","value":"image/png"},
|
||||
"5bb69b88517f6214": {"kind":"object","properties":[{"name":"form","type":"e8de0f457fed5b9f","optional":false},{"name":"kind","type":"99e7e7d7fed55ae6","optional":false},{"name":"summary","type":"4cd48f3e5108bd6e","optional":false}],"indices":[]},
|
||||
"5bc66269cfaf614c": {"kind":"object","properties":[{"name":"form","type":"16d0507cb94b4cfc","optional":false},{"name":"kind","type":"d9edf1862e4471d6","optional":false}],"indices":[]},
|
||||
"5cdbf342b7748d15": {"kind":"object","properties":[{"name":"form","type":"16d0507cb94b4cfc","optional":false},{"name":"kind","type":"f68c335306535a00","optional":false}],"indices":[]},
|
||||
"5d00abf938272f22": {"kind":"array","element":"b782058cef83caf3"},
|
||||
"5d03ba38734809bc": {"kind":"array","element":"0657d3ca5ac4e7bf"},
|
||||
"5d7a64ed6aac5551": {"kind":"object","properties":[{"name":"form","type":"16d0507cb94b4cfc","optional":false},{"name":"kind","type":"8067b0d232c350f1","optional":false}],"indices":[]},
|
||||
"5ef58f2a1bdc576c": {"kind":"object","properties":[{"name":"data","type":"7404c6123fdaa591","optional":false},{"name":"ignorable","type":"dacf3d5f3e4ff619","optional":true},{"name":"seq","type":"0657d3ca5ac4e7bf","optional":false},{"name":"sourceEventSeqs","type":"5d03ba38734809bc","optional":true},{"name":"surfaceOp","type":"335e242de1fcc17b","optional":false},{"name":"time","type":"0657d3ca5ac4e7bf","optional":false},{"name":"type","type":"1379f0b72275994d","optional":false}],"indices":[]},
|
||||
"6085488d223aeffd": {"kind":"object","properties":[{"name":"form","type":"fee1caf8ab6a65c1","optional":false},{"name":"kind","type":"2f3f201c8846e19c","optional":false}],"indices":[]},
|
||||
"6292bcbedaa97fea": {"kind":"object","properties":[{"name":"kind","type":"f68c335306535a00","optional":false}],"indices":[]},
|
||||
"62ecb62dc0fe1b5e": {"kind":"literal","value":"next-turn"},
|
||||
"65a8400e451e667e": {"kind":"object","properties":[{"name":"kind","type":"09655b34d7f3cf1e","optional":false}],"indices":[]},
|
||||
"672c4aa2a9b736e3": {"kind":"object","properties":[{"name":"form","type":"fee1caf8ab6a65c1","optional":false},{"name":"kind","type":"1922cd79a70806c1","optional":false},{"name":"name","type":"4cd48f3e5108bd6e","optional":false}],"indices":[]},
|
||||
"68f44f59e91c4139": {"kind":"literal","value":"user"},
|
||||
"6b23ed9ce1b397e6": {"kind":"literal","value":"compact-checkpoint"},
|
||||
"6ccb6bc423fb3952": {"kind":"object","properties":[{"name":"form","type":"e8de0f457fed5b9f","optional":false},{"name":"kind","type":"f68c335306535a00","optional":false},{"name":"summary","type":"4cd48f3e5108bd6e","optional":false}],"indices":[]},
|
||||
"6dacb1584f2bfbe2": {"kind":"object","properties":[{"name":"clientTimeZone","type":"4cd48f3e5108bd6e","optional":true},{"name":"kind","type":"68f44f59e91c4139","optional":false},{"name":"principal","type":"deebfc7c62177ea8","optional":true},{"name":"rpcId","type":"4cd48f3e5108bd6e","optional":false}],"indices":[]},
|
||||
"6ea608bdc8a7a63d": {"kind":"object","properties":[{"name":"form","type":"16d0507cb94b4cfc","optional":false},{"name":"kind","type":"a9059a81430b3207","optional":false}],"indices":[]},
|
||||
"6ebcc2dbec9f2dab": {"kind":"literal","value":"skill-catalog"},
|
||||
"6f22a9d02b9a1f11": {"kind":"object","properties":[{"name":"baseline","type":"dacf3d5f3e4ff619","optional":true},{"name":"baselineIdentity","type":"4cd48f3e5108bd6e","optional":true},{"name":"changes","type":"2ab12a0e345658f9","optional":false},{"name":"form","type":"fee1caf8ab6a65c1","optional":false},{"name":"kind","type":"fbd2c74b346a1595","optional":false}],"indices":[]},
|
||||
"6f44f32be9bcd9a8": {"kind":"object","properties":[{"name":"form","type":"fee1caf8ab6a65c1","optional":false},{"name":"kind","type":"1f1385dbc3e875c0","optional":false}],"indices":[]},
|
||||
"6f9e00383836275e": {"kind":"literal","value":"snapshot"},
|
||||
"719c51f67074f970": {"kind":"object","properties":[{"name":"kind","type":"2765e9119edf5816","optional":false},{"name":"model","type":"4cd48f3e5108bd6e","optional":false},{"name":"provider","type":"4cd48f3e5108bd6e","optional":false},{"name":"replayState","type":"bbc5696e3f13c758","optional":true}],"indices":[]},
|
||||
"7382c4fc95fe8c5d": {"kind":"literal","value":"remove"},
|
||||
"7404c6123fdaa591": {"kind":"object","properties":[{"name":"headerSeq","type":"0657d3ca5ac4e7bf","optional":true},{"name":"message","type":"7580e7d96dc8475f","optional":false},{"name":"step","type":"0657d3ca5ac4e7bf","optional":false},{"name":"turn","type":"0657d3ca5ac4e7bf","optional":false}],"indices":[]},
|
||||
"7554565be416b034": {"kind":"object","properties":[{"name":"form","type":"383cf73ae4748e5b","optional":false},{"name":"kind","type":"2f3f201c8846e19c","optional":false}],"indices":[]},
|
||||
"756b5e23a5cb2c7f": {"kind":"object","properties":[{"name":"form","type":"383cf73ae4748e5b","optional":false},{"name":"kind","type":"8067b0d232c350f1","optional":false}],"indices":[]},
|
||||
"7580e7d96dc8475f": {"kind":"object","properties":[{"name":"content","type":"b52f215a6cd69105","optional":false},{"name":"id","type":"4cd48f3e5108bd6e","optional":false},{"name":"role","type":"589d0d91239681f8","optional":false},{"name":"source","type":"7a5b68bd1a5118c8","optional":false,"compatibility":{"version":1,"policy":"session-source-attribution","binding":"session.developer-message.source","discriminator":"kind","unknownKinds":"preserve","attributionKinds":["action-cards","tmux-context","user-question-reply","working-directory"]}}],"indices":[]},
|
||||
"78a9be340090b735": {"kind":"literal","value":"tmux-context"},
|
||||
"78b9204976ab9faa": {"kind":"array","element":"cda79b839d8cc0c7"},
|
||||
"7a5b68bd1a5118c8": {"kind":"union","types":["0203243b72fc867a","022623b9ef98ec47","02b2c23f2d94b028","0ed8d1108fe7a5e1","0eeb17e1df89b1eb","11638dc58a31496f","1938c8c20f1cba7c","1e709346005826eb","1fdad624334d3548","2152caf1a71e588e","2235d957bf4b7c6c","224aa11d4d5f88c4","24ce31aa528272e5","260523b412c19ad8","28936c614bd4e7e2","290f32bfd81ff85a","297fbd8067d7815a","2aad1179f9576314","312aee2f0c42aabb","31907de956375182","3247e566f4340029","3b04790e08b35241","3b4f2c9ef2c1217e","3bdb8dc6989655b0","408927267422a7b2","45f005e6bbb76452","4991dfc415c9efeb","49dab019d00e8c26","4a9bef9f27a94252","4e97c3d85c0fc817","52c6113cb0e53f34","53cf1704ae0709c7","5654685d7557ec74","58015da1c1950a66","5bb69b88517f6214","5bc66269cfaf614c","5cdbf342b7748d15","5d7a64ed6aac5551","6085488d223aeffd","6292bcbedaa97fea","65a8400e451e667e","672c4aa2a9b736e3","6ccb6bc423fb3952","6dacb1584f2bfbe2","6ea608bdc8a7a63d","6f22a9d02b9a1f11","6f44f32be9bcd9a8","719c51f67074f970","7554565be416b034","756b5e23a5cb2c7f","7df62978a2b7de85","7eaef7a763ba5b94","7f959241c24128b4","80677c8c8b804189","825ca23416b1ea9d","8338ee303e2bd448","854db3efdfb0cd39","85fe96bf15d5c755","8620189c8e335827","87b1a33564b9a4d6","88841202942c7683","8a046b52331959aa","8c1c4f72755a78ea","8c627d7a45fa406c","8f324cea3916c051","8fcb0b44a575e998","96bfb916a727cd44","99135d8a39379779","99f0e98184709ad1","9edc162949abf93b","9f65c43e340bba31","a15a19ef63cf5d1b","a16e567c8cd2c55c","a2066bd52f61218b","a3c6f1ea38e9a61d","aa2bf9e82b9fdeb9","aae343bc3d663c83","ada310bf0bdb8fed","ade057f4fdc387ae","b062078e899958f9","b2a5c8c008a31e3d","b3681c026a0b98e9","b4ec0af39fd52ed9","b613f83572fe2fbf","b6f94c17dd9bbd7c","b70f3e81fe11b7a5","b79641a9d25e7566","ba2a1a8f194b1bb2","ba4c40b4381e0dcd","baccc97ec34be6c4","c5228b7a55498d84","c55827fba7018198","cb1c8959e1726f82","cda2345a9be9d139","d85590a5675c6e2f","d9c462b9f62fdd3e","db06ef35b27a3842","dba54c09c6e7aafc","dd00cdccd0ba487b","dd5ee8762bd8a14b","dd6cc2bb2a8f2824","dde0cdf9d426768b","deaae5cd30987d4f","e7f4cbb3a57f4cbd","edbbfff1128099fd","ee577a0cc18664c9","f230c0b583e23b25","f29d63336e8266d8","f4a66f654996c093","f56c5b59ca016131","f6329fb30c7ea801","f6605d6c57933aea","f6afe41e3926f422","f7283223aacdc39b","f97f47b0eb87905e","fc2ae6962f9f8801","fcf81d3c58c13593","fe1a7acdeed4d0f5"]},
|
||||
"7b1ce60193fa8b69": {"kind":"literal","value":"working-directory"},
|
||||
"7df62978a2b7de85": {"kind":"object","properties":[{"name":"form","type":"aec150797b655c5f","optional":false},{"name":"kind","type":"78a9be340090b735","optional":false}],"indices":[]},
|
||||
"7eaef7a763ba5b94": {"kind":"object","properties":[{"name":"form","type":"16d0507cb94b4cfc","optional":false},{"name":"kind","type":"23af3759678a30de","optional":false}],"indices":[]},
|
||||
"7f13860ee89a2d35": {"kind":"literal","value":"session-reference"},
|
||||
"7f959241c24128b4": {"kind":"object","properties":[{"name":"goalId","type":"4cd48f3e5108bd6e","optional":false},{"name":"kind","type":"b815d7b91cdd9fc6","optional":false},{"name":"revision","type":"0657d3ca5ac4e7bf","optional":false},{"name":"round","type":"0657d3ca5ac4e7bf","optional":false}],"indices":[]},
|
||||
"8064c03c87c357fd": {"kind":"union","types":["12d5808fac1996b9","43e311235aa537df","4e88776858652856","814d9434e1ddf907","8e611bf46821e500","c1f0f17b6493b85d","f2da0f27c1e6add5"]},
|
||||
"80677c8c8b804189": {"kind":"object","properties":[{"name":"form","type":"aec150797b655c5f","optional":false},{"name":"kind","type":"23af3759678a30de","optional":false}],"indices":[]},
|
||||
"8067b0d232c350f1": {"kind":"literal","value":"time-context"},
|
||||
"814d9434e1ddf907": {"kind":"object","properties":[{"name":"text","type":"4cd48f3e5108bd6e","optional":false},{"name":"type","type":"3c2535ca0a2062f1","optional":false}],"indices":[]},
|
||||
"82470020b5bfcb1a": {"kind":"literal","value":"agent-message"},
|
||||
"825ca23416b1ea9d": {"kind":"object","properties":[{"name":"form","type":"aec150797b655c5f","optional":false},{"name":"kind","type":"f68c335306535a00","optional":false}],"indices":[]},
|
||||
"829a2fb3be6efd4b": {"kind":"literal","value":"agent/inbox/spliced"},
|
||||
"83079c8a3f733ac3": {"kind":"object","properties":[{"name":"description","type":"4cd48f3e5108bd6e","optional":false},{"name":"name","type":"4cd48f3e5108bd6e","optional":false}],"indices":[]},
|
||||
"8338ee303e2bd448": {"kind":"object","properties":[{"name":"form","type":"e8de0f457fed5b9f","optional":false},{"name":"kind","type":"23af3759678a30de","optional":false},{"name":"summary","type":"4cd48f3e5108bd6e","optional":false}],"indices":[]},
|
||||
"83d6916021eede8f": {"kind":"literal","value":"tool-removal"},
|
||||
"83da72c6857601c7": {"kind":"object","properties":[{"name":"action","type":"904bf499d98be4a3","optional":false},{"name":"digest","type":"4cd48f3e5108bd6e","optional":true},{"name":"path","type":"4cd48f3e5108bd6e","optional":false},{"name":"scope","type":"4cd48f3e5108bd6e","optional":false}],"indices":[]},
|
||||
"854db3efdfb0cd39": {"kind":"object","properties":[{"name":"form","type":"e8de0f457fed5b9f","optional":false},{"name":"kind","type":"bb94f3217aa56c88","optional":false},{"name":"summary","type":"4cd48f3e5108bd6e","optional":false}],"indices":[]},
|
||||
"85d6d96ff8842974": {"kind":"literal","value":"answered"},
|
||||
"85f9b505b7bdff1f": {"kind":"literal","value":"tool-addition"},
|
||||
"85fe96bf15d5c755": {"kind":"object","properties":[{"name":"form","type":"aec150797b655c5f","optional":false},{"name":"kind","type":"8067b0d232c350f1","optional":false}],"indices":[]},
|
||||
"8620189c8e335827": {"kind":"object","properties":[{"name":"form","type":"383cf73ae4748e5b","optional":false},{"name":"kind","type":"1f1385dbc3e875c0","optional":false}],"indices":[]},
|
||||
"86e1e384495ee09a": {"kind":"object","properties":[{"name":"name","type":"4cd48f3e5108bd6e","optional":false},{"name":"text","type":"4cd48f3e5108bd6e","optional":false}],"indices":[]},
|
||||
"87b1a33564b9a4d6": {"kind":"object","properties":[{"name":"form","type":"383cf73ae4748e5b","optional":false},{"name":"kind","type":"a9059a81430b3207","optional":false}],"indices":[]},
|
||||
"88841202942c7683": {"kind":"object","properties":[{"name":"form","type":"6f9e00383836275e","optional":false},{"name":"kind","type":"bb94f3217aa56c88","optional":false},{"name":"sections","type":"c748fb42c80a1200","optional":false}],"indices":[]},
|
||||
"8a046b52331959aa": {"kind":"object","properties":[{"name":"kind","type":"78a9be340090b735","optional":false}],"indices":[]},
|
||||
"8af841fc9b265ade": {"kind":"literal","value":"system"},
|
||||
"8c1c4f72755a78ea": {"kind":"object","properties":[{"name":"form","type":"6f9e00383836275e","optional":false},{"name":"kind","type":"0fe52387f6505270","optional":false},{"name":"sections","type":"c748fb42c80a1200","optional":false}],"indices":[]},
|
||||
"8c627d7a45fa406c": {"kind":"object","properties":[{"name":"form","type":"e8de0f457fed5b9f","optional":false},{"name":"kind","type":"2f3f201c8846e19c","optional":false},{"name":"summary","type":"4cd48f3e5108bd6e","optional":false}],"indices":[]},
|
||||
"8e611bf46821e500": {"kind":"object","properties":[{"name":"tool","type":"fcf427290c6213c2","optional":true},{"name":"toolName","type":"4cd48f3e5108bd6e","optional":false},{"name":"type","type":"85f9b505b7bdff1f","optional":false}],"indices":[]},
|
||||
"8f324cea3916c051": {"kind":"object","properties":[{"name":"form","type":"16d0507cb94b4cfc","optional":false},{"name":"kind","type":"2f3f201c8846e19c","optional":false}],"indices":[]},
|
||||
"8fcb0b44a575e998": {"kind":"object","properties":[{"name":"kind","type":"a720757f704a2512","optional":false}],"indices":[]},
|
||||
"904bf499d98be4a3": {"kind":"union","types":["7382c4fc95fe8c5d","b765ee31033cea46","f6cb462f808309e3"]},
|
||||
"938f7c7357bc403e": {"kind":"primitive","type":"null"},
|
||||
"95a3ffccbf3c8afc": {"kind":"literal","value":"owner"},
|
||||
"95c0e88fcf0bafb2": {"kind":"literal","value":"assistant"},
|
||||
"9645cf93769a6dfb": {"kind":"literal","value":"user-question-reply"},
|
||||
"96bfb916a727cd44": {"kind":"object","properties":[{"name":"form","type":"383cf73ae4748e5b","optional":false},{"name":"kind","type":"24b10f7cdae64928","optional":false}],"indices":[]},
|
||||
"96f4a9c81fc0f940": {"kind":"union","types":["3e2ece4967cfebe9","62ecb62dc0fe1b5e"]},
|
||||
"99135d8a39379779": {"kind":"object","properties":[{"name":"form","type":"aec150797b655c5f","optional":false},{"name":"kind","type":"9ac52f0f84fec2eb","optional":false}],"indices":[]},
|
||||
"99e7e7d7fed55ae6": {"kind":"literal","value":"tool-jobs"},
|
||||
"99f0e98184709ad1": {"kind":"object","properties":[{"name":"form","type":"aec150797b655c5f","optional":false},{"name":"kind","type":"bb94f3217aa56c88","optional":false}],"indices":[]},
|
||||
"9ac52f0f84fec2eb": {"kind":"literal","value":"model-selection"},
|
||||
"9edc162949abf93b": {"kind":"object","properties":[{"name":"deliveryId","type":"4cd48f3e5108bd6e","optional":false},{"name":"form","type":"e8de0f457fed5b9f","optional":false},{"name":"kind","type":"db6c5246911d47a7","optional":false},{"name":"provider","type":"4cd48f3e5108bd6e","optional":false},{"name":"ruleId","type":"4cd48f3e5108bd6e","optional":false},{"name":"source","type":"4cd48f3e5108bd6e","optional":false},{"name":"summary","type":"4cd48f3e5108bd6e","optional":false}],"indices":[]},
|
||||
"9f65c43e340bba31": {"kind":"object","properties":[{"name":"form","type":"fee1caf8ab6a65c1","optional":false},{"name":"kind","type":"78a9be340090b735","optional":false}],"indices":[]},
|
||||
"a13d8f379222ece8": {"kind":"literal","value":"tool"},
|
||||
"a15a19ef63cf5d1b": {"kind":"object","properties":[{"name":"form","type":"16d0507cb94b4cfc","optional":false},{"name":"kind","type":"9ac52f0f84fec2eb","optional":false}],"indices":[]},
|
||||
"a16e567c8cd2c55c": {"kind":"object","properties":[{"name":"form","type":"383cf73ae4748e5b","optional":false},{"name":"kind","type":"d9edf1862e4471d6","optional":false}],"indices":[]},
|
||||
"a2066bd52f61218b": {"kind":"object","properties":[{"name":"kind","type":"2f3f201c8846e19c","optional":false}],"indices":[]},
|
||||
"a3c6f1ea38e9a61d": {"kind":"object","properties":[{"name":"form","type":"e8de0f457fed5b9f","optional":false},{"name":"kind","type":"9ac52f0f84fec2eb","optional":false},{"name":"summary","type":"4cd48f3e5108bd6e","optional":false}],"indices":[]},
|
||||
"a3e299483348f27a": {"kind":"object","properties":[{"name":"maxTokens","type":"0657d3ca5ac4e7bf","optional":false},{"name":"messageSeqs","type":"5d03ba38734809bc","optional":false},{"name":"messages","type":"78b9204976ab9faa","optional":false},{"name":"reasoningEffort","type":"4cd48f3e5108bd6e","optional":true},{"name":"route","type":"07e1a58c58b593f5","optional":false},{"name":"system","type":"4cd48f3e5108bd6e","optional":false},{"name":"titleProvider","type":"4cd48f3e5108bd6e","optional":false}],"indices":[]},
|
||||
"a720757f704a2512": {"kind":"literal","value":"tool-registry"},
|
||||
"a9059a81430b3207": {"kind":"literal","value":"hooks-claude-code"},
|
||||
"aa2bf9e82b9fdeb9": {"kind":"object","properties":[{"name":"form","type":"fee1caf8ab6a65c1","optional":false},{"name":"kind","type":"f68c335306535a00","optional":false}],"indices":[]},
|
||||
"aa93010d0e521ad7": {"kind":"primitive","type":"boolean"},
|
||||
"aae343bc3d663c83": {"kind":"object","properties":[{"name":"form","type":"383cf73ae4748e5b","optional":false},{"name":"kind","type":"9ac52f0f84fec2eb","optional":false}],"indices":[]},
|
||||
"aba175fb20ffc711": {"kind":"array","element":"83079c8a3f733ac3"},
|
||||
"ada310bf0bdb8fed": {"kind":"object","properties":[{"name":"kind","type":"68f44f59e91c4139","optional":false}],"indices":[]},
|
||||
"ade057f4fdc387ae": {"kind":"object","properties":[{"name":"form","type":"16d0507cb94b4cfc","optional":false},{"name":"kind","type":"99e7e7d7fed55ae6","optional":false}],"indices":[]},
|
||||
"aec150797b655c5f": {"kind":"literal","value":"catalog"},
|
||||
"b062078e899958f9": {"kind":"object","properties":[{"name":"kind","type":"1f1385dbc3e875c0","optional":false}],"indices":[]},
|
||||
"b0b0eb1b16490f6b": {"kind":"object","properties":[{"name":"attachmentId","type":"4cd48f3e5108bd6e","optional":false},{"name":"bytes","type":"0657d3ca5ac4e7bf","optional":false},{"name":"height","type":"0657d3ca5ac4e7bf","optional":false},{"name":"mediaType","type":"2f1e6a7ebace43d7","optional":false},{"name":"name","type":"4cd48f3e5108bd6e","optional":true},{"name":"originalDimensions","type":"0f46153645c29784","optional":true},{"name":"width","type":"0657d3ca5ac4e7bf","optional":false}],"indices":[]},
|
||||
"b2a5c8c008a31e3d": {"kind":"object","properties":[{"name":"form","type":"383cf73ae4748e5b","optional":false},{"name":"kind","type":"23af3759678a30de","optional":false}],"indices":[]},
|
||||
"b2a948a5340a9341": {"kind":"object","properties":[{"name":"inserted","type":"5d00abf938272f22","optional":false},{"name":"outcome","type":"d4e4d575abeb4b72","optional":true},{"name":"removedCount","type":"0657d3ca5ac4e7bf","optional":true},{"name":"start","type":"0657d3ca5ac4e7bf","optional":false},{"name":"target","type":"96f4a9c81fc0f940","optional":false}],"indices":[]},
|
||||
"b3681c026a0b98e9": {"kind":"object","properties":[{"name":"form","type":"e8de0f457fed5b9f","optional":false},{"name":"kind","type":"78a9be340090b735","optional":false},{"name":"summary","type":"4cd48f3e5108bd6e","optional":false}],"indices":[]},
|
||||
"b36fd842cd004b53": {"kind":"object","properties":[{"name":"data","type":"b2a948a5340a9341","optional":false},{"name":"ignorable","type":"dacf3d5f3e4ff619","optional":true},{"name":"seq","type":"0657d3ca5ac4e7bf","optional":false},{"name":"time","type":"0657d3ca5ac4e7bf","optional":false},{"name":"type","type":"829a2fb3be6efd4b","optional":false}],"indices":[]},
|
||||
"b4ec0af39fd52ed9": {"kind":"object","properties":[{"name":"kind","type":"bb94f3217aa56c88","optional":false}],"indices":[]},
|
||||
"b52f215a6cd69105": {"kind":"array","element":"8064c03c87c357fd"},
|
||||
"b613f83572fe2fbf": {"kind":"object","properties":[{"name":"form","type":"383cf73ae4748e5b","optional":false},{"name":"kind","type":"05205074b24d8340","optional":false},{"name":"through","type":"0657d3ca5ac4e7bf","optional":false}],"indices":[]},
|
||||
"b6f94c17dd9bbd7c": {"kind":"object","properties":[{"name":"form","type":"fee1caf8ab6a65c1","optional":false},{"name":"kind","type":"bb94f3217aa56c88","optional":false}],"indices":[]},
|
||||
"b70f3e81fe11b7a5": {"kind":"object","properties":[{"name":"form","type":"fee1caf8ab6a65c1","optional":false},{"name":"kind","type":"a9059a81430b3207","optional":false}],"indices":[]},
|
||||
"b765ee31033cea46": {"kind":"literal","value":"set"},
|
||||
"b782058cef83caf3": {"kind":"object","properties":[{"name":"content","type":"b52f215a6cd69105","optional":false},{"name":"id","type":"4cd48f3e5108bd6e","optional":false},{"name":"role","type":"68f44f59e91c4139","optional":false},{"name":"source","type":"7a5b68bd1a5118c8","optional":false,"compatibility":{"version":1,"policy":"session-source-attribution","binding":"session.user-message.source","discriminator":"kind","unknownKinds":"preserve","attributionKinds":["action-cards","tmux-context","user-question-reply","working-directory"]}}],"indices":[]},
|
||||
"b79641a9d25e7566": {"kind":"object","properties":[{"name":"kind","type":"8067b0d232c350f1","optional":false}],"indices":[]},
|
||||
"b815d7b91cdd9fc6": {"kind":"literal","value":"goal"},
|
||||
"ba2a1a8f194b1bb2": {"kind":"object","properties":[{"name":"form","type":"fee1caf8ab6a65c1","optional":false},{"name":"kind","type":"05205074b24d8340","optional":false},{"name":"through","type":"0657d3ca5ac4e7bf","optional":false}],"indices":[]},
|
||||
"ba4c40b4381e0dcd": {"kind":"object","properties":[{"name":"form","type":"6f9e00383836275e","optional":false},{"name":"kind","type":"23af3759678a30de","optional":false},{"name":"sections","type":"c748fb42c80a1200","optional":false}],"indices":[]},
|
||||
"baccc97ec34be6c4": {"kind":"object","properties":[{"name":"form","type":"e8de0f457fed5b9f","optional":false},{"name":"kind","type":"0fe52387f6505270","optional":false},{"name":"summary","type":"4cd48f3e5108bd6e","optional":false}],"indices":[]},
|
||||
"bb94f3217aa56c88": {"kind":"literal","value":"hooks-codex"},
|
||||
"bbc5696e3f13c758": {"kind":"opaque","reason":"unknown"},
|
||||
"bcf0caf62d964b2f": {"kind":"object","properties":[{"name":"endSeq","type":"0657d3ca5ac4e7bf","optional":false},{"name":"op","type":"f6cb462f808309e3","optional":false},{"name":"startSeq","type":"0657d3ca5ac4e7bf","optional":false}],"indices":[]},
|
||||
"bf16d2e98a7f1389": {"kind":"literal","value":"subagent-settled"},
|
||||
"c1f0f17b6493b85d": {"kind":"object","properties":[{"name":"arguments","type":"4cd48f3e5108bd6e","optional":false},{"name":"id","type":"4cd48f3e5108bd6e","optional":false},{"name":"name","type":"4cd48f3e5108bd6e","optional":false},{"name":"type","type":"1f0133217eeeffd8","optional":false}],"indices":[]},
|
||||
"c5228b7a55498d84": {"kind":"object","properties":[{"name":"form","type":"6f9e00383836275e","optional":false},{"name":"kind","type":"99e7e7d7fed55ae6","optional":false},{"name":"sections","type":"c748fb42c80a1200","optional":false}],"indices":[]},
|
||||
"c55827fba7018198": {"kind":"object","properties":[{"name":"callId","type":"4cd48f3e5108bd6e","optional":false},{"name":"kind","type":"9645cf93769a6dfb","optional":false},{"name":"outcome","type":"85d6d96ff8842974","optional":false}],"indices":[]},
|
||||
"c5687b1313206a6f": {"kind":"literal","value":"cordis-host-runner"},
|
||||
"c748fb42c80a1200": {"kind":"array","element":"86e1e384495ee09a"},
|
||||
"cb1c8959e1726f82": {"kind":"object","properties":[{"name":"form","type":"16d0507cb94b4cfc","optional":false},{"name":"kind","type":"24b10f7cdae64928","optional":false}],"indices":[]},
|
||||
"cda2345a9be9d139": {"kind":"object","properties":[{"name":"form","type":"e8de0f457fed5b9f","optional":false},{"name":"kind","type":"24b10f7cdae64928","optional":false},{"name":"summary","type":"4cd48f3e5108bd6e","optional":false}],"indices":[]},
|
||||
"cda79b839d8cc0c7": {"kind":"union","types":["09f3f8dc417f2782","4b259f7f8f0a44ad","7580e7d96dc8475f","b782058cef83caf3","fa87537f4a9c1e25"]},
|
||||
"d4e4d575abeb4b72": {"kind":"literal","value":"canceled"},
|
||||
"d85590a5675c6e2f": {"kind":"object","properties":[{"name":"form","type":"aec150797b655c5f","optional":false},{"name":"kind","type":"1f1385dbc3e875c0","optional":false}],"indices":[]},
|
||||
"d9c462b9f62fdd3e": {"kind":"object","properties":[{"name":"callId","type":"4cd48f3e5108bd6e","optional":false},{"name":"kind","type":"a13d8f379222ece8","optional":false}],"indices":[]},
|
||||
"d9edf1862e4471d6": {"kind":"literal","value":"schedule"},
|
||||
"dacf3d5f3e4ff619": {"kind":"literal","value":true},
|
||||
"db06ef35b27a3842": {"kind":"object","properties":[{"name":"form","type":"6f9e00383836275e","optional":false},{"name":"kind","type":"1f1385dbc3e875c0","optional":false},{"name":"sections","type":"c748fb42c80a1200","optional":false}],"indices":[]},
|
||||
"db6c5246911d47a7": {"kind":"literal","value":"webhook"},
|
||||
"dba54c09c6e7aafc": {"kind":"object","properties":[{"name":"kind","type":"4edec1b770e8ec4c","optional":false}],"indices":[]},
|
||||
"dd00cdccd0ba487b": {"kind":"object","properties":[{"name":"form","type":"aec150797b655c5f","optional":false},{"name":"kind","type":"05205074b24d8340","optional":false},{"name":"through","type":"0657d3ca5ac4e7bf","optional":false}],"indices":[]},
|
||||
"dd5ee8762bd8a14b": {"kind":"object","properties":[{"name":"form","type":"aec150797b655c5f","optional":false},{"name":"kind","type":"99e7e7d7fed55ae6","optional":false}],"indices":[]},
|
||||
"dd6cc2bb2a8f2824": {"kind":"object","properties":[{"name":"form","type":"383cf73ae4748e5b","optional":false},{"name":"kind","type":"99e7e7d7fed55ae6","optional":false}],"indices":[]},
|
||||
"dde0cdf9d426768b": {"kind":"object","properties":[{"name":"kind","type":"05205074b24d8340","optional":false},{"name":"through","type":"0657d3ca5ac4e7bf","optional":false}],"indices":[]},
|
||||
"de25352d2dc41963": {"kind":"literal","value":"user/message"},
|
||||
"de30b1fa12c75f81": {"kind":"literal","value":"image/gif"},
|
||||
"deaae5cd30987d4f": {"kind":"object","properties":[{"name":"form","type":"16d0507cb94b4cfc","optional":false},{"name":"kind","type":"0fe52387f6505270","optional":false}],"indices":[]},
|
||||
"deebfc7c62177ea8": {"kind":"object","properties":[{"name":"kind","type":"95a3ffccbf3c8afc","optional":false}],"indices":[]},
|
||||
"df843efd87c78cf8": {"kind":"array","element":"4f91f187baeabef5"},
|
||||
"e438a9d4fb883b3e": {"kind":"literal","value":"append"},
|
||||
"e7f4cbb3a57f4cbd": {"kind":"object","properties":[{"name":"form","type":"e8de0f457fed5b9f","optional":false},{"name":"kind","type":"05205074b24d8340","optional":false},{"name":"summary","type":"4cd48f3e5108bd6e","optional":false},{"name":"through","type":"0657d3ca5ac4e7bf","optional":false}],"indices":[]},
|
||||
"e8de0f457fed5b9f": {"kind":"literal","value":"notice"},
|
||||
"ebb768d85ec87fb6": {"kind":"literal","value":"image/webp"},
|
||||
"edbbfff1128099fd": {"kind":"object","properties":[{"name":"form","type":"e8de0f457fed5b9f","optional":false},{"name":"kind","type":"a9059a81430b3207","optional":false},{"name":"summary","type":"4cd48f3e5108bd6e","optional":false}],"indices":[]},
|
||||
"ee577a0cc18664c9": {"kind":"object","properties":[{"name":"form","type":"e8de0f457fed5b9f","optional":false},{"name":"kind","type":"8067b0d232c350f1","optional":false},{"name":"summary","type":"4cd48f3e5108bd6e","optional":false}],"indices":[]},
|
||||
"efa1a091017ce533": {"kind":"object","properties":[{"name":"data","type":"a3e299483348f27a","optional":false},{"name":"ignorable","type":"dacf3d5f3e4ff619","optional":true},{"name":"seq","type":"0657d3ca5ac4e7bf","optional":false},{"name":"time","type":"0657d3ca5ac4e7bf","optional":false},{"name":"type","type":"587bb11da730e06a","optional":false}],"indices":[]},
|
||||
"f19bee84bf3d2090": {"kind":"object","properties":[{"name":"attachmentId","type":"4cd48f3e5108bd6e","optional":false},{"name":"bytes","type":"0657d3ca5ac4e7bf","optional":false},{"name":"name","type":"4cd48f3e5108bd6e","optional":false}],"indices":[]},
|
||||
"f230c0b583e23b25": {"kind":"object","properties":[{"name":"form","type":"6f9e00383836275e","optional":false},{"name":"kind","type":"8067b0d232c350f1","optional":false},{"name":"sections","type":"c748fb42c80a1200","optional":false}],"indices":[]},
|
||||
"f29d63336e8266d8": {"kind":"object","properties":[{"name":"kind","type":"d9edf1862e4471d6","optional":false}],"indices":[]},
|
||||
"f2da0f27c1e6add5": {"kind":"object","properties":[{"name":"attachment","type":"f19bee84bf3d2090","optional":false},{"name":"type","type":"277b61f9c6f81704","optional":false}],"indices":[]},
|
||||
"f4a66f654996c093": {"kind":"object","properties":[{"name":"kind","type":"0fe52387f6505270","optional":false}],"indices":[]},
|
||||
"f56c5b59ca016131": {"kind":"object","properties":[{"name":"form","type":"383cf73ae4748e5b","optional":false},{"name":"kind","type":"7f13860ee89a2d35","optional":false},{"name":"references","type":"df843efd87c78cf8","optional":false},{"name":"version","type":"f88f1b7b6bb733f6","optional":false}],"indices":[]},
|
||||
"f6329fb30c7ea801": {"kind":"object","properties":[{"name":"form","type":"383cf73ae4748e5b","optional":false},{"name":"kind","type":"0fe52387f6505270","optional":false}],"indices":[]},
|
||||
"f6605d6c57933aea": {"kind":"object","properties":[{"name":"form","type":"fee1caf8ab6a65c1","optional":false},{"name":"kind","type":"9ac52f0f84fec2eb","optional":false}],"indices":[]},
|
||||
"f68c335306535a00": {"kind":"literal","value":"user-approval"},
|
||||
"f6afe41e3926f422": {"kind":"object","properties":[{"name":"form","type":"fee1caf8ab6a65c1","optional":false},{"name":"kind","type":"8067b0d232c350f1","optional":false}],"indices":[]},
|
||||
"f6cb462f808309e3": {"kind":"literal","value":"replace"},
|
||||
"f7283223aacdc39b": {"kind":"object","properties":[{"name":"kind","type":"9ac52f0f84fec2eb","optional":false}],"indices":[]},
|
||||
"f88f1b7b6bb733f6": {"kind":"literal","value":1},
|
||||
"f97f47b0eb87905e": {"kind":"object","properties":[{"name":"form","type":"16d0507cb94b4cfc","optional":false},{"name":"kind","type":"78a9be340090b735","optional":false}],"indices":[]},
|
||||
"fa87537f4a9c1e25": {"kind":"object","properties":[{"name":"content","type":"b52f215a6cd69105","optional":false},{"name":"id","type":"4cd48f3e5108bd6e","optional":false},{"name":"role","type":"95c0e88fcf0bafb2","optional":false},{"name":"source","type":"719c51f67074f970","optional":false}],"indices":[]},
|
||||
"fb8b6a2e53cb9cf4": {"kind":"literal","value":"image"},
|
||||
"fbd2c74b346a1595": {"kind":"literal","value":"agent-instructions"},
|
||||
"fc2ae6962f9f8801": {"kind":"object","properties":[{"name":"entries","type":"aba175fb20ffc711","optional":false},{"name":"form","type":"aec150797b655c5f","optional":false},{"name":"kind","type":"6ebcc2dbec9f2dab","optional":false},{"name":"update","type":"dacf3d5f3e4ff619","optional":true}],"indices":[]},
|
||||
"fcf427290c6213c2": {"kind":"primitive","type":"never"},
|
||||
"fcf81d3c58c13593": {"kind":"object","properties":[{"name":"form","type":"383cf73ae4748e5b","optional":false},{"name":"kind","type":"78a9be340090b735","optional":false}],"indices":[]},
|
||||
"fe1a7acdeed4d0f5": {"kind":"object","properties":[{"name":"form","type":"e8de0f457fed5b9f","optional":false},{"name":"kind","type":"1f1385dbc3e875c0","optional":false},{"name":"summary","type":"4cd48f3e5108bd6e","optional":false}],"indices":[]},
|
||||
"fee1caf8ab6a65c1": {"kind":"literal","value":"instructions"}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
---
|
||||
description: "记录持久化类型更改及其兼容性确认。"
|
||||
kind: persistence-change
|
||||
---
|
||||
|
||||
# 2026-10-22-action-card-status
|
||||
|
||||
[English](2026-10-22-action-card-status.md) | 中文
|
||||
|
||||
## 概述
|
||||
|
||||
为写入日志的模型上下文新增操作卡片状态的来源标识。
|
||||
|
||||
## 目录
|
||||
|
||||
- [声明](#declaration)
|
||||
- [兼容性](#compatibility)
|
||||
- [验证](#verification)
|
||||
- [开发备注](#dev-note)
|
||||
|
||||
<a id="declaration"></a>
|
||||
## 声明
|
||||
|
||||
```yaml persistence-change
|
||||
schemaVersion: 1
|
||||
id: 2026-10-22-action-card-status
|
||||
baseline: false
|
||||
changes:
|
||||
- root: "event:agent/inbox/spliced"
|
||||
previous: "2026-10-13-user-rpc-principal"
|
||||
after: "b36fd842cd004b532ce96fd5d6f5be28e017eda043131aa3cf5e69edc436108e"
|
||||
decision: same-version
|
||||
- root: "event:developer/message"
|
||||
previous: "2026-10-13-user-rpc-principal"
|
||||
after: "5ef58f2a1bdc576c1f12fa1f4da1920ece020b13c0f991a578cddcbeb28bc5be"
|
||||
decision: same-version
|
||||
- root: "event:session/title-llm-request"
|
||||
previous: "2026-10-13-user-rpc-principal"
|
||||
after: "efa1a091017ce533e38b0ef3e14d11a5c102ff1793229b18dad719a4268d9adc"
|
||||
decision: same-version
|
||||
- root: "event:user/message"
|
||||
previous: "2026-10-13-user-rpc-principal"
|
||||
after: "58b122df513aeaf7ddc5783dbb1fd844e2979bb273964e30ae351a8db6510019"
|
||||
decision: same-version
|
||||
```
|
||||
|
||||
<a id="compatibility"></a>
|
||||
## 兼容性
|
||||
|
||||
已有消息和记录不变。没有操作卡片插件的读取方保留新的 action-cards 来源类型及其 JSON 元数据,并把记录的文本当作普通上下文。只有写入方使用 through 序号确认已送达的决定;它不授予任何权限,也不改变回放的解释。
|
||||
|
||||
<a id="verification"></a>
|
||||
## 验证
|
||||
|
||||
对 action-cards、creation-recommendations、client-ui-action-cards 和 client-ui-creation-recommendations 的测试运行 pnpm exec vitest run:120 个测试通过,源码覆盖率 100%。Web creation-recommendations 回放在下一次回答之前记录了已忽略卡片的状态通知。
|
||||
|
||||
<a id="dev-note"></a>
|
||||
## 开发备注
|
||||
|
||||
无。
|
||||
@@ -15,8 +15,8 @@
|
||||
en: 14c57f30e676f6e3
|
||||
zh: b1a0ccf26fab3727
|
||||
/session-persistence-formats/format-references:
|
||||
en: 17ef09dfc5a89073
|
||||
zh: 59b8d60acb66c2dc
|
||||
en: e3511a4ac3bc4457
|
||||
zh: 828f3c39f80d5370
|
||||
/session-persistence-formats/scope-and-evidence:
|
||||
en: b220062139ddac1e
|
||||
zh: 7c4c0efe05dafa9c
|
||||
|
||||
@@ -32,7 +32,7 @@ The index is generated from validated snapshots and the current writer constant.
|
||||
| 1 | PR #3349 | [V1](v1.md) | [JSON](v1.schema.json) | 54 / 415 |
|
||||
| 2 | `dsh-v0.1.3-alpha.2` | [V2](v2.md) | [JSON](v2.schema.json) | 56 / 435 |
|
||||
| 3 | PR #4320 | [V3](v3.md) | [JSON](v3.schema.json) | 60 / 467 |
|
||||
| 4 | Current checkout | [Current catalog](../../persistence-catalog.md) | [JSON](../../persistence-schema.json) | 65 / 614 |
|
||||
| 4 | Current checkout | [Current catalog](../../persistence-catalog.md) | [JSON](../../persistence-schema.json) | 65 / 622 |
|
||||
|
||||
<!-- persistence-format-index:end -->
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ description: "查找从 V0 到工作区写入器版本的每个 Session 格式
|
||||
| 1 | PR #3349 | [V1](v1.zh.md) | [JSON](v1.schema.json) | 54 / 415 |
|
||||
| 2 | `dsh-v0.1.3-alpha.2` | [V2](v2.zh.md) | [JSON](v2.schema.json) | 56 / 435 |
|
||||
| 3 | PR #4320 | [V3](v3.zh.md) | [JSON](v3.schema.json) | 60 / 467 |
|
||||
| 4 | 当前工作树 | [当前目录](../../persistence-catalog.zh.md) | [JSON](../../persistence-schema.json) | 65 / 614 |
|
||||
| 4 | 当前工作树 | [当前目录](../../persistence-catalog.zh.md) | [JSON](../../persistence-schema.json) | 65 / 622 |
|
||||
|
||||
<!-- persistence-format-index:end -->
|
||||
|
||||
|
||||
Generated
+46
-30
@@ -5,7 +5,7 @@
|
||||
{"key":"JsonlHeaderLine","kind":"header","digest":"18ee62b8900a4c3d046700f05d7a4d49d6cab2a660a020c87481d1603dd8bd4f"},
|
||||
{"key":"SessionEventEnvelope","kind":"envelope","digest":"5776e5553ff2dfe3f5bc202dbb1e7c9f93e35a531aebb7764c23b2b6153b2ccc"},
|
||||
{"key":"event:agent-preset/selected","kind":"event","event":"agent-preset/selected","surface":false,"digest":"a10c17474eaf2ddab7095a099e0fe3d046fc18e56c3e344fc8894c05ff9ef97b"},
|
||||
{"key":"event:agent/inbox/spliced","kind":"event","event":"agent/inbox/spliced","surface":false,"digest":"0755b7d1128319ba2e389619cbbf2c961ad648882b4e91da7f3e9582cc8a2034"},
|
||||
{"key":"event:agent/inbox/spliced","kind":"event","event":"agent/inbox/spliced","surface":false,"digest":"b36fd842cd004b532ce96fd5d6f5be28e017eda043131aa3cf5e69edc436108e"},
|
||||
{"key":"event:approval/asked","kind":"event","event":"approval/asked","surface":false,"digest":"3bfeb47b58606f4661904bc723da612782214c463d01e6d61cd6d6193d7374e1"},
|
||||
{"key":"event:approval/decided","kind":"event","event":"approval/decided","surface":false,"digest":"bb1ab3d08f49a9f3b265f844cd78d5c49813062a7b34b54904b426f85d0ff6e3"},
|
||||
{"key":"event:approval/policy","kind":"event","event":"approval/policy","surface":false,"digest":"26718e15e7e395bce9642dba5bbe09b3b1a4ce2213d20d566cd9207d7fc5fb78"},
|
||||
@@ -18,7 +18,7 @@
|
||||
{"key":"event:compaction/start","kind":"event","event":"compaction/start","surface":false,"digest":"db874d463b0fdec77e9da1c4568f37cb70bd6596781eb93800db44fb8a116965"},
|
||||
{"key":"event:compaction/summary","kind":"event","event":"compaction/summary","surface":false,"digest":"e2f9a41e0989f54ed8cee80f8db2bcf9d60a5c810dc9d45b83fa050b9dce7602"},
|
||||
{"key":"event:deliverables/presented","kind":"event","event":"deliverables/presented","surface":false,"digest":"13d3d180f977bf78081d487ffa0ecb75857349bcab29a5a3fb48189fca2a6176"},
|
||||
{"key":"event:developer/message","kind":"event","event":"developer/message","surface":true,"digest":"97e0162f983c27456ec71269fb4976b1851588b8c1aeac5d071d43e11f95e03c"},
|
||||
{"key":"event:developer/message","kind":"event","event":"developer/message","surface":true,"digest":"5ef58f2a1bdc576c1f12fa1f4da1920ece020b13c0f991a578cddcbeb28bc5be"},
|
||||
{"key":"event:feedback/message-delete","kind":"event","event":"feedback/message-delete","surface":false,"digest":"3ee93b06f3a125850337602bcdf155d2538c43a5c944ec55b1b3c365152d6796"},
|
||||
{"key":"event:feedback/message-put","kind":"event","event":"feedback/message-put","surface":false,"digest":"b5086d249e8502e9ead1d39156bb8d559bde7951cac0f14ce150345b4e42a2bf"},
|
||||
{"key":"event:feedback/record","kind":"event","event":"feedback/record","surface":false,"digest":"b54940ff095c17e874c5be03815f4c2145a256cf3a1d34dae4ab2f7769dfffe8"},
|
||||
@@ -40,7 +40,7 @@
|
||||
{"key":"event:session-log-deepseek/delivery-accepted","kind":"event","event":"session-log-deepseek/delivery-accepted","surface":false,"digest":"d63b8b8ffad9c02fd80c43a17df4f240c1fe8118ecca9de34f9d5871838ab5b9"},
|
||||
{"key":"event:session/end-seed","kind":"event","event":"session/end-seed","surface":false,"digest":"5e6db6e24948d4a853c71cb9fabd252ad051ce93d4672c1266cf837c1c17b84e"},
|
||||
{"key":"event:session/title","kind":"event","event":"session/title","surface":false,"digest":"1b912703e2d64f91c99c675b8f805b01076c8325b905c1218ad81ef0b24909d5"},
|
||||
{"key":"event:session/title-llm-request","kind":"event","event":"session/title-llm-request","surface":false,"digest":"79a4c87f8bfb4d6d05cd9952b99210d6a7db3b478c4a01d94b4c50602308c056"},
|
||||
{"key":"event:session/title-llm-request","kind":"event","event":"session/title-llm-request","surface":false,"digest":"efa1a091017ce533e38b0ef3e14d11a5c102ff1793229b18dad719a4268d9adc"},
|
||||
{"key":"event:step/end","kind":"event","event":"step/end","surface":false,"digest":"e0a787e6ec76c7c94fecbc501b489164ab0293db05bc947914077ad01e674f05"},
|
||||
{"key":"event:step/start","kind":"event","event":"step/start","surface":false,"digest":"4513e088d43e6c68425be30451b9f961cc264fe7318ca62681c41d4d78615986"},
|
||||
{"key":"event:subagent/catalog","kind":"event","event":"subagent/catalog","surface":false,"digest":"53750b9abf61efb7992b0aadc3e247ec927449c63266df28230fd1139f5590ac"},
|
||||
@@ -62,24 +62,22 @@
|
||||
{"key":"event:tool/result","kind":"event","event":"tool/result","surface":true,"digest":"7c9f44e90a0058f4cc532ae20dad0c10afa6eba22e70a6c79fc79490bad64397"},
|
||||
{"key":"event:turn/end","kind":"event","event":"turn/end","surface":false,"digest":"0f8512903d94f57a4748fa1a2092e64342856796684e6b8343db685b192745ce"},
|
||||
{"key":"event:turn/start","kind":"event","event":"turn/start","surface":false,"digest":"aa0957eca50aeb28bcd2e6930b95809926edacb550c8c340ba526ba6b861b3d8"},
|
||||
{"key":"event:user/message","kind":"event","event":"user/message","surface":true,"digest":"2ae8594a998c9862a597129e782277bcc518266712a703b5c3161bdf552d13b8"},
|
||||
{"key":"event:user/message","kind":"event","event":"user/message","surface":true,"digest":"58b122df513aeaf7ddc5783dbb1fd844e2979bb273964e30ae351a8db6510019"},
|
||||
{"key":"event:web/deepseek-search-llm-request","kind":"event","event":"web/deepseek-search-llm-request","surface":false,"digest":"0c556c9b9f2a96238a6b9bbb99e748206cbff2ed6203041c9571f04ae5802f52"},
|
||||
{"key":"event:working-directory/change","kind":"event","event":"working-directory/change","surface":false,"digest":"124aa62078ca3311353b39cc3bf6c75da281338be6bbf672f8b361d828cddca3"},
|
||||
{"key":"event:workspace/changes","kind":"event","event":"workspace/changes","surface":false,"digest":"e308ccf867a5398e316e0af8cb6ce238a8d33a63b9b384c8250a686786285f72"}
|
||||
],
|
||||
"types": [
|
||||
{"digest":"00c054d3018c198d92f459563331edd1385e58345c677bb499791df2da0ade9f","names":["packages/session/session-title-llm/src/index.ts#SessionTitleLlmRequestEventData"],"sources":["packages/session/session-title-llm/src/index.ts:37"]},
|
||||
{"digest":"0116b1f89c05221d56b0ba35c83d302bf4857bc7277d247e9bbaf74b27d2c66e","names":[],"sources":[]},
|
||||
{"digest":"0203243b72fc867afc81aff5f4cf2167e564ed342534eb612fc92f295cf07789","names":[],"sources":[]},
|
||||
{"digest":"022623b9ef98ec47ec3c3bae0c51027c70d2601141c5e92e26a0d83d1b4cef06","names":[],"sources":[]},
|
||||
{"digest":"023a355b2be0d688fb6e4df8388dadb942761d46cfe96d0f499aae9631a159d4","names":[],"sources":["packages/core/session/src/types.ts:207"]},
|
||||
{"digest":"02b2c23f2d94b028c9588a8faace3fce1217405db346da3389368b495457bf79","names":[],"sources":["packages/extensions/cordis-host-runner/src/index.ts:14"]},
|
||||
{"digest":"0341d4c3dfcd53253cdc1e789d9130d3cd848b6f8b0706bf92f313a68b39ff23","names":[],"sources":[]},
|
||||
{"digest":"040cd65423bd64264d225504f1c572d239eeb1793d0c2856ad8e42bb6e1e148b","names":["packages/llm/llm/src/message.ts#Message"],"sources":["packages/llm/llm/src/message.ts:196"]},
|
||||
{"digest":"05205074b24d8340cfd7995f6cb64779c7f1241490954700115601e264178877","names":[],"sources":[]},
|
||||
{"digest":"05a2796621b1ee6c03ef7abe560b25116bb4da4d592312117242a78415a32b04","names":[],"sources":[]},
|
||||
{"digest":"05d2ae1e0c7f8770f83f9a09047afb39a335d8ac986df3193659aa1e581472cf","names":["packages/interaction/user-approval/src/index.ts#ApprovalPolicy"],"sources":["packages/interaction/user-approval/src/index.ts:68"]},
|
||||
{"digest":"0657d3ca5ac4e7bf79b00bcf860b1c7159d01a9da137497221ec2f1776e365f7","names":["packages/core/session/src/types.ts#SessionSeq"],"sources":["packages/core/session/src/types.ts:33"]},
|
||||
{"digest":"0755b7d1128319ba2e389619cbbf2c961ad648882b4e91da7f3e9582cc8a2034","names":[],"sources":[]},
|
||||
{"digest":"07e1a58c58b593f507b8e7f25723bb0aa42baae6e00f5ecfddf28cb1e64d3235","names":["packages/session/session-title/src/types.ts#SessionTitleModelIdentity","packages/subagent/tool-subagent/src/model-selection.ts#AllowedModelRoute"],"sources":["packages/session/session-title/src/types.ts:20","packages/subagent/tool-subagent/src/model-selection.ts:9"]},
|
||||
{"digest":"07eccc9ea2f9b5439d76cc77d5e062936677d43f07a23da749819b0a22ee36b7","names":[],"sources":[]},
|
||||
{"digest":"09655b34d7f3cf1e9005974de2357de2d4a60deea165d16dac1eadaa6ec539a8","names":[],"sources":[]},
|
||||
@@ -101,7 +99,6 @@
|
||||
{"digest":"0ed8d1108fe7a5e1c3078ef1faea12199a56b6b1216ccaceb0f6103b0c9a7691","names":[],"sources":[]},
|
||||
{"digest":"0eeb17e1df89b1ebc2902116fe7145e0d321ef0db26e6bdebc802cb8513a01c1","names":[],"sources":[]},
|
||||
{"digest":"0f46153645c297846a3fad3911636659ca4717a5e7d71c9f50bffacd312115ef","names":[],"sources":["packages/attachment/attachment/src/types.ts:28"]},
|
||||
{"digest":"0f6265188dae7ba6faa26830a180bb4deb0760561f97ee0c9d399ccf6c9cf1f7","names":["packages/llm/llm/src/message.ts#DeveloperMessage"],"sources":["packages/llm/llm/src/message.ts:157"]},
|
||||
{"digest":"0f8512903d94f57a4748fa1a2092e64342856796684e6b8343db685b192745ce","names":[],"sources":[]},
|
||||
{"digest":"0fe52387f65052702ed9d7cd59db826468936595d1b3eec207e7a823adc719db","names":[],"sources":[]},
|
||||
{"digest":"1033093edd0db80ff410e00830b523405e00bb0c7684948e531ff65095799625","names":[],"sources":[]},
|
||||
@@ -178,11 +175,9 @@
|
||||
{"digest":"2aad1179f957631477b582e57cd8f538cb82618fc3fb816bde1171154235b065","names":[],"sources":[]},
|
||||
{"digest":"2ab12a0e345658f9342816d773fe610f049982bcad82631f43b9205abe43e5ee","names":[],"sources":[]},
|
||||
{"digest":"2abb711460e6238d851c30f3e4bdd87a2aa1887ee70575b3d3b7b25610673095","names":[],"sources":["packages/llm/llm/src/types.ts:473"]},
|
||||
{"digest":"2ae8594a998c9862a597129e782277bcc518266712a703b5c3161bdf552d13b8","names":[],"sources":[]},
|
||||
{"digest":"2aed07493b1c65b6d00de5586da1e743cf501684b9ad43a1765fb4007d4ea456","names":[],"sources":[]},
|
||||
{"digest":"2c4c21f19f426a58f2dac914e34313aa43f8408972de857a486d1f086d5adb6c","names":[],"sources":[]},
|
||||
{"digest":"2c64d4bc7264fd3f8bed47e96ab8a593bce05a1e4e1c436dcd244a3b7e0c2a9d","names":[],"sources":[]},
|
||||
{"digest":"2cf075b013d363ad743b5a4982900678d108499c721bc11255137402003db711","names":["packages/llm/llm/src/message.ts#UserMessage"],"sources":["packages/llm/llm/src/message.ts:162"]},
|
||||
{"digest":"2d11ca7b0d4493e244b74eba093227866b33249841e59a1e9bf56afed38604c3","names":[],"sources":["packages/web/web-search-deepseek/src/provider.ts:71"]},
|
||||
{"digest":"2da725e554cd89301d829ed9dc45a572c3cd1b93b5e91d0d71f007976d8a0863","names":[],"sources":[]},
|
||||
{"digest":"2e3523541e942ef6cc9fbc5b91f242e0ca4c6ada479b79b96025b797f6e41f3f","names":["packages/schedule/schedule/src/types.ts#ScheduleChange"],"sources":["packages/schedule/schedule/src/types.ts:256"]},
|
||||
@@ -194,6 +189,7 @@
|
||||
{"digest":"30d5a537b296685770b1241c4b4bbde19d5a31ff81aa23df73fab5e90b8fc65f","names":["packages/session/session-title/src/types.ts#SessionTitleSource"],"sources":["packages/session/session-title/src/types.ts:28"]},
|
||||
{"digest":"312aee2f0c42aabbae6cc60d92d596d8453c0aeb061c5868d1755a69ef49e69a","names":[],"sources":[]},
|
||||
{"digest":"31907de9563751822af6d9be02bafaf26faa098bbd1cb412524134d577cc1648","names":["packages/compaction/compaction/src/checkpoint.ts#CompactionCheckpointSource"],"sources":["packages/compaction/compaction/src/checkpoint.ts:22"]},
|
||||
{"digest":"3247e566f4340029325b70e4366b56fa9719977f1e39033b769a2ec221ab22a9","names":[],"sources":[]},
|
||||
{"digest":"326a9bfda27dda5882fb3cbe6e715df41dae2298fdae3d66437457268a665693","names":["packages/llm/llm/src/call-config.ts#LlmCallConfigAdapterDefaults"],"sources":["packages/llm/llm/src/call-config.ts:54"]},
|
||||
{"digest":"3305a4bb6b6c29b482ba91d59c60b47e8f98282d3dacc8c29e4a4c2712209bdd","names":[],"sources":[]},
|
||||
{"digest":"33341aac09312300de5a178e6cc6f6544a4876f7f710cfea55eda473c8d329ef","names":["packages/llm/llm/src/assistant-stream.ts#AssistantStreamRecord"],"sources":["packages/llm/llm/src/assistant-stream.ts:20"]},
|
||||
@@ -236,7 +232,7 @@
|
||||
{"digest":"44818000e56acb97afdb5045ce235eb55e3fb1ccabc9fc7d0750bb38f36a7f8e","names":[],"sources":[]},
|
||||
{"digest":"44c8c77aa9aa100b0d74d2deee85474b29faa6eee0ac0f662f7abe9931ddd7f2","names":[],"sources":[]},
|
||||
{"digest":"4513e088d43e6c68425be30451b9f961cc264fe7318ca62681c41d4d78615986","names":[],"sources":[]},
|
||||
{"digest":"454a0fa879e38076bdcdbd87ef561cd67d7e43e58a287cf7dbaa7b6cf7847020","names":[],"sources":[]},
|
||||
{"digest":"45f005e6bbb7645248be792b715a74bc7fdf5a67f5381655d3a75dcc7aa2112e","names":[],"sources":[]},
|
||||
{"digest":"45f2a07ea94573123b6ae14db787a40062dec3834f36d8be92c523d40ba28448","names":[],"sources":["packages/interaction/user-approval/src/types.ts:44"]},
|
||||
{"digest":"477614bca595a9e7adb5a1870be446b9a8684f3ba8950259d6289f2d3b74f028","names":[],"sources":["packages/compaction/compaction-image-offload/src/projection.ts:25"]},
|
||||
{"digest":"47e5d84f1a93450a78c7f3954b43990d0f629af7c034a56313e5deb63e772c1b","names":[],"sources":[]},
|
||||
@@ -285,17 +281,18 @@
|
||||
{"digest":"5808e36c95355f0e745201b5db1b6bcec4ebf5adb75d3e82d7d59cc89635ab80","names":["packages/llm/llm/src/types.ts#FinishReason"],"sources":["packages/llm/llm/src/types.ts:165"]},
|
||||
{"digest":"587bb11da730e06aa52b62c087d217d6f8f22459b25f31cb9e1e1baf17944e5e","names":[],"sources":[]},
|
||||
{"digest":"589d0d91239681f89ee485459dc8c2f73ea47183b5534289d966637024a2c35d","names":[],"sources":[]},
|
||||
{"digest":"58b122df513aeaf7ddc5783dbb1fd844e2979bb273964e30ae351a8db6510019","names":[],"sources":[]},
|
||||
{"digest":"58f94390b982f8a5ac1f4f235ba612557f4a1dc4a995d8b1cec63ce7639decb0","names":[],"sources":[]},
|
||||
{"digest":"5abab3a27fd2736660ecddd94b28d6bbf114986dd894880153bd1be3ccacb563","names":[],"sources":[]},
|
||||
{"digest":"5b232a9b9bfcc0fc6794dab7865bcf203a65785c5de5aa647a51228bff628413","names":[],"sources":[]},
|
||||
{"digest":"5b6fb1f226ff56402db08a6aae82af76100b14056271875f69ec526a1ae05d51","names":[],"sources":["packages/interaction/commands/src/types.ts:112"]},
|
||||
{"digest":"5bb69b88517f6214f2af4d1a6d2b771e271ad3ad695cc9c2c272069ae698c9bc","names":[],"sources":[]},
|
||||
{"digest":"5bc2d7f02503fc6b3e1bb7e0b7fa22c0b9e4b9841fa3175b2ad8e607ae3525a8","names":["packages/llm/llm/src/message.ts#MessageSource"],"sources":["packages/llm/llm/src/message.ts:136"]},
|
||||
{"digest":"5bc66269cfaf614c0ecda8ecb469f23101a7609793fc2b693ac23c4aecdb575e","names":[],"sources":[]},
|
||||
{"digest":"5bd310104cfe448e530beb11422d2f791e2e32e8e95fdc528a15f9ca693dae75","names":[],"sources":[]},
|
||||
{"digest":"5c45bf4c544a7211dcd8ba6ba7e5f1bc39b49e7a9df9d5cbdc8e87c22771b37b","names":[],"sources":[]},
|
||||
{"digest":"5cb63db9fe57dc09c3a1c2b84c3edf73ff5b62960155d8436a2377a5c43ce32c","names":[],"sources":[]},
|
||||
{"digest":"5cdbf342b7748d152bc987b68f58e565e5bba4b227e076e2d2120d87662e45cd","names":[],"sources":[]},
|
||||
{"digest":"5d00abf938272f22eb47199e9d40801e8d8ec4c88e2b138b15aa2a5a5bf87520","names":[],"sources":[]},
|
||||
{"digest":"5d03ba38734809bcbd2a55221bd938b3b3fc34b49bb686c6113e9e4931e3aa78","names":[],"sources":[]},
|
||||
{"digest":"5d17f27a1ef9f7026c0232714adf7573961536d75f3303ca97973975f5af170e","names":[],"sources":[]},
|
||||
{"digest":"5d542ac7bdf13310c46e1a884dec9fb18ad8c6e153cff207e639cd7bf9d7e694","names":[],"sources":[]},
|
||||
@@ -303,6 +300,7 @@
|
||||
{"digest":"5dd766ccd1702a1142ad8b4bd44f2242f8e8a6752669ad3de0a5d224329b1438","names":[],"sources":["packages/compaction/compaction/src/types.ts:82"]},
|
||||
{"digest":"5e6db6e24948d4a853c71cb9fabd252ad051ce93d4672c1266cf837c1c17b84e","names":[],"sources":[]},
|
||||
{"digest":"5ebce1317eacd2c148456627a09668e927ee15c204f0643f5ea76b46b54a2647","names":[],"sources":[]},
|
||||
{"digest":"5ef58f2a1bdc576c1f12fa1f4da1920ece020b13c0f991a578cddcbeb28bc5be","names":[],"sources":[]},
|
||||
{"digest":"5f2117d1856a5ab43c28371faa978ebfaa48f8c7d734ea3fc94842210df83dca","names":["packages/llm/llm/src/types.ts#LlmFailure"],"sources":["packages/llm/llm/src/types.ts:41"]},
|
||||
{"digest":"5f26a6c20b37632f8f57729d171c671def4683d994ac6257a8dffcd855101627","names":[],"sources":[]},
|
||||
{"digest":"5f758f3de5f00c18968a7c6d347083aac5c9ae13f6a79c78f6611b23c4973564","names":["packages/subagent/subagent/src/descriptor.ts#OneShotSubagentDescriptorData"],"sources":["packages/subagent/subagent/src/descriptor.ts:61"]},
|
||||
@@ -351,16 +349,19 @@
|
||||
{"digest":"71bb3254ec8f1e491ce63b762a7b5f18709de23aa4e8abcc8b886f4b6ce051dd","names":[],"sources":["packages/llm/llm/src/assistant-stream.ts:28"]},
|
||||
{"digest":"72ec79127a9c0d0241b1106a74cc2b24c81ce467170f1c3c93f7b71a9496d227","names":[],"sources":[]},
|
||||
{"digest":"7382c4fc95fe8c5db65ca4d9da572b115d0dbb818b7f32c22ab040318ffbb4bc","names":[],"sources":[]},
|
||||
{"digest":"7404c6123fdaa591474a37979a5a8ae70d1387af7c9f09bfe568b218935a974d","names":[],"sources":["packages/core/session/src/types.ts:313"]},
|
||||
{"digest":"750a2b129d67704df675c06823c20c80b65cbae89d5aaa914fd5a72e3df395b5","names":["packages/jobs/jobs/src/types.ts#JobSettleCause"],"sources":["packages/jobs/jobs/src/types.ts:247"]},
|
||||
{"digest":"7554565be416b0342053ee6a46256c9dab07c487349b4a5f10bab1edc151c619","names":[],"sources":[]},
|
||||
{"digest":"756b5e23a5cb2c7f486f366a828f7461c88902af21125bd6810881f4ccbff6cc","names":[],"sources":[]},
|
||||
{"digest":"7580e7d96dc8475fffe813a42af499665de3d4517fcdb3bc2337d0340e98d616","names":["packages/llm/llm/src/message.ts#DeveloperMessage"],"sources":["packages/llm/llm/src/message.ts:157"]},
|
||||
{"digest":"7624ca28c61ca0eaa4f015140f3cea6e0c16cce2f2960fab5f531203d253903e","names":[],"sources":[]},
|
||||
{"digest":"763c8a20af487263a0080548274f7437ef4a86e0ba8769127d1ced10a72c664d","names":[],"sources":[]},
|
||||
{"digest":"76632533f67879dcb346fcae640540dbc89b2472b0bce88c59f7e48fc5c0e668","names":[],"sources":[]},
|
||||
{"digest":"78a9be340090b735a39980e7222ce730c972fbcf1de7c9e0aef2125884b7caee","names":[],"sources":[]},
|
||||
{"digest":"78b9204976ab9faaf133c3488b73d1dfb6f1a4bb6c0903e3473cd41a5e1e39e1","names":[],"sources":[]},
|
||||
{"digest":"79650cfa10aa3c52440328d85e8a25f0ffadc8d7efd784e3c0819d8bb74a1985","names":[],"sources":["packages/core/session/src/types.ts:214"]},
|
||||
{"digest":"79a4c87f8bfb4d6d05cd9952b99210d6a7db3b478c4a01d94b4c50602308c056","names":[],"sources":[]},
|
||||
{"digest":"79ddc907312f97cf9553d4841e8b3fc937097bd8d97900a790efad3c05255e99","names":[],"sources":["packages/todo/tool-todo/src/types.ts:33"]},
|
||||
{"digest":"7a5b68bd1a5118c827df9e2466acc5e4d16b83e3f97a2304d992958647592690","names":["packages/llm/llm/src/message.ts#MessageSource"],"sources":["packages/llm/llm/src/message.ts:136"]},
|
||||
{"digest":"7a651f3b672c52fb615f22c0ce9cb3cc5b22aad92e6bbeefb0808fd7b9233a50","names":[],"sources":[]},
|
||||
{"digest":"7af85bf70d4eafce63e739adae38ea85501e68df3a0e22f97f3a0be90fd9e4cb","names":[],"sources":[]},
|
||||
{"digest":"7b1ce60193fa8b69292e5843858d9cee7dc565dcb40d33c136e5d7e8b8d4296a","names":[],"sources":[]},
|
||||
@@ -431,7 +432,6 @@
|
||||
{"digest":"9645cf93769a6dfb227bd400bd6cb9fa7bab9140f4a851e4ae92514ade6e3114","names":[],"sources":[]},
|
||||
{"digest":"96bfb916a727cd4445a594df264c523fc039749a31bfed924b8cc7bb308a5bb0","names":[],"sources":[]},
|
||||
{"digest":"96f4a9c81fc0f940ef71528a8cc66731ae4cf1f40d79680c5fe3c39f96d7723c","names":["packages/core/agent/src/types.ts#InboxTarget"],"sources":["packages/core/agent/src/types.ts:40"]},
|
||||
{"digest":"97e0162f983c27456ec71269fb4976b1851588b8c1aeac5d071d43e11f95e03c","names":[],"sources":[]},
|
||||
{"digest":"9890113e97dd3541787bfe6704f2b223d3a890b5325ca0acae2b0398909b413e","names":[],"sources":["packages/sandbox/sandbox-policy/src/session-mode.ts:33"]},
|
||||
{"digest":"99135d8a3937977955eaac5f8f04f930dcd1562f8450a54a51cde9b921dd59a6","names":[],"sources":[]},
|
||||
{"digest":"9947aa5938fe19a895298da412917acbf9ffb5093a73ab8baa257e6ae9e63a07","names":[],"sources":[]},
|
||||
@@ -464,6 +464,7 @@
|
||||
{"digest":"a2be0f0cb59f0d4a06557d45847d1938aced238baa77a6da416e590b8b958553","names":[],"sources":[]},
|
||||
{"digest":"a3a259a1aa5401af786ce08c4a8419681d3000d73467991b5fc563389bc4ebd2","names":[],"sources":[]},
|
||||
{"digest":"a3c6f1ea38e9a61d7a9706057ba65aabe02dfe6d9dd90d4736aa62325d874531","names":[],"sources":[]},
|
||||
{"digest":"a3e299483348f27a4787a36bb3f29cd86024c65336abc10bb3d687468302c4cf","names":["packages/session/session-title-llm/src/index.ts#SessionTitleLlmRequestEventData"],"sources":["packages/session/session-title-llm/src/index.ts:37"]},
|
||||
{"digest":"a3edd1efd1fef21b72c55e213c8a8b24196b091abde2b89db52be0b2aaae3cfa","names":[],"sources":[]},
|
||||
{"digest":"a40d12070f6f4a124f32fb3cc86e7857554702e32f0eda3080a25c4b9ac9b18c","names":[],"sources":["packages/experimental/agent-team/src/types.ts:232"]},
|
||||
{"digest":"a6567ccb2e530606b775371eb4fa31468d72084339968e8b0440a516a23b39dc","names":[],"sources":[]},
|
||||
@@ -476,7 +477,6 @@
|
||||
{"digest":"a8a2b9011fc067862df7ce40748868467e5778283d7ac193c13f77684a914c57","names":[],"sources":[]},
|
||||
{"digest":"a9059a81430b320792bbb7c2ee1f8f6c77ff71e40ee44c18aec72e157c522694","names":[],"sources":[]},
|
||||
{"digest":"a926dc71814edd01a4f041eb5fc766d153db3407ef4704e98f4c1b6527309ebb","names":["packages/schedule/schedule/src/types.ts#LegacyEveryScheduleRecord"],"sources":["packages/schedule/schedule/src/types.ts:173"]},
|
||||
{"digest":"a927d444c928ac0efd9dd8b2e7d7d04d711c264cb71578d81e0e2fd143ff669f","names":[],"sources":[]},
|
||||
{"digest":"a99ec0993c62c058e50af9f68922202a3b54f5e259bc2abf1915a73381d2316d","names":[],"sources":[]},
|
||||
{"digest":"a99f76fd149051c363f960bfeeb5b9509587ecaf7591a42797e4bfe810d8987a","names":["packages/todo/tool-todo/src/types.ts#TodoItem"],"sources":["packages/todo/tool-todo/src/types.ts:23"]},
|
||||
{"digest":"aa0957eca50aeb28bcd2e6930b95809926edacb550c8c340ba526ba6b861b3d8","names":[],"sources":[]},
|
||||
@@ -509,8 +509,10 @@
|
||||
{"digest":"b222069eea2d768065161c1147b1f2c78c1b54328c84b3586ae5c8f91b8ed35e","names":[],"sources":[]},
|
||||
{"digest":"b2245a906e13aa94f2d3cc6cf7b04cfa0267f7b7f4d468de1b00b1a314e54626","names":[],"sources":[]},
|
||||
{"digest":"b2a5c8c008a31e3dc6c3013502f2356aca13894b31c8e70601fa92f2d40d1dba","names":[],"sources":[]},
|
||||
{"digest":"b2a948a5340a9341fa3bab99507c7090c5b0456de72ec28b5b157b8df3f1d640","names":[],"sources":["packages/core/agent/src/types.ts:110"]},
|
||||
{"digest":"b2d2a01e51341a3bfec809198952c8c830a7899f4cb6ecd3c1dc0b5d9a2af943","names":["packages/experimental/agent-team/src/types.ts#TeamTaskStatus"],"sources":["packages/experimental/agent-team/src/types.ts:72"]},
|
||||
{"digest":"b3681c026a0b98e98b103f057dfd217fbe904129c090efd668253ec9aea7fece","names":[],"sources":[]},
|
||||
{"digest":"b36fd842cd004b532ce96fd5d6f5be28e017eda043131aa3cf5e69edc436108e","names":[],"sources":[]},
|
||||
{"digest":"b38f206d59bad891fa58c89f97a0036987b3defe7685acbd318fa55eb85f9751","names":[],"sources":[]},
|
||||
{"digest":"b4ec0af39fd52ed971990e42f04e5be3204882e555c409eb330f8238eec21569","names":[],"sources":[]},
|
||||
{"digest":"b5086d249e8502e9ead1d39156bb8d559bde7951cac0f14ce150345b4e42a2bf","names":[],"sources":[]},
|
||||
@@ -519,12 +521,14 @@
|
||||
{"digest":"b56f6a885da3dc394c69a3e3cc5c0cfc4da15601b63fda4989eee8f40efc5be4","names":["packages/session/session-title/src/types.ts#SessionTitleEventData"],"sources":["packages/session/session-title/src/types.ts:41"]},
|
||||
{"digest":"b57a2889408de36e4516807194c73bdecd51a92f633ccd05db81bf049200f420","names":[],"sources":[]},
|
||||
{"digest":"b57ae1b37e52bee0a21cbdace168dc6a15582bcda8c306dad962c5dcc8a8e28b","names":[],"sources":[]},
|
||||
{"digest":"b613f83572fe2fbf7259c72308cafd008f4fceea897749128a48bcd158f290aa","names":[],"sources":[]},
|
||||
{"digest":"b63b089a00b3b9357675b3e0c3d3e9aa4fdbda1fba9c91a6b0c59ffdbb89f505","names":["packages/schedule/schedule/src/types.ts#LegacyAtScheduleRecord"],"sources":["packages/schedule/schedule/src/types.ts:167"]},
|
||||
{"digest":"b6896938660a1dfe4ddd100fb3164d9f8fa57feeabfe37441a80106c9942697a","names":[],"sources":[]},
|
||||
{"digest":"b6ef9c6210be8350cd465f485cf520031fffa6bf3809c61a1e713e834c5982d0","names":[],"sources":["packages/core/session/src/types.ts:203"]},
|
||||
{"digest":"b6f94c17dd9bbd7cd57015198b7c7c88407f0e3b89faab176ca3c11c3d864d3e","names":[],"sources":[]},
|
||||
{"digest":"b70f3e81fe11b7a5f2504fb47a4502fb8d9c8f0731fdfe8ddcaf9b41f5a6e196","names":[],"sources":[]},
|
||||
{"digest":"b765ee31033cea463863faf3fc6a0a1b85c47c6a2f13fe1ce833abe56105114b","names":[],"sources":[]},
|
||||
{"digest":"b782058cef83caf3eb44a16adeef5657e4d5cdff2d50655aba418c4490670a69","names":["packages/llm/llm/src/message.ts#UserMessage"],"sources":["packages/llm/llm/src/message.ts:162"]},
|
||||
{"digest":"b79641a9d25e756636dc0c706fdf3c4583ccb7d4920e009e6e86c0759cf4de4c","names":[],"sources":[]},
|
||||
{"digest":"b79ada42962cad0190a9d465805260567621fa3a4abd757eb31e6016b52d5ab5","names":[],"sources":[]},
|
||||
{"digest":"b815d7b91cdd9fc6ccc7dcba05cfc5ce1d55fab5fc0c0801803cd3630cedb602","names":[],"sources":[]},
|
||||
@@ -534,6 +538,7 @@
|
||||
{"digest":"b9305f0ea75ccd6a6061c27fde19f2ab85534f9f3c1a717b573b077ebae0f611","names":[],"sources":[]},
|
||||
{"digest":"b978cff734e62143eb56c9125423ec275405eda969802d42aaf73ecb987d3b26","names":[],"sources":[]},
|
||||
{"digest":"b993441f8ce7d27b80e619e113e232ae8e62d3d5a8340f6bfe12d8c4c018e62f","names":[],"sources":[]},
|
||||
{"digest":"ba2a1a8f194b1bb21f270713398f6643e206e8ff5f7f26f6d36a88e3f0f0ab10","names":[],"sources":[]},
|
||||
{"digest":"ba4c40b4381e0dcdfab8fc9fc75b5c9b3e8f09ef56deeb1bec8e703b0ef8cd6d","names":[],"sources":[]},
|
||||
{"digest":"ba77b58995e36f14bb13886b0493d0a1a63d5db10b1a6cd9f6ac65a72cf832ec","names":[],"sources":[]},
|
||||
{"digest":"bab68657940075483f086fffb711682a45bcc99c43d659fbe1c36af21ac05dd7","names":[],"sources":[]},
|
||||
@@ -568,6 +573,7 @@
|
||||
{"digest":"cbca49bde16b656d5b8fbe4a8a507769f7b594c6287782b809c03814941bc5e3","names":[],"sources":[]},
|
||||
{"digest":"cd186c309e2bef305705e1d324139240f5e681f4f6a957d6a25b0225f65560df","names":[],"sources":[]},
|
||||
{"digest":"cda2345a9be9d139df49ccbd16dcba716f3440178bf20ff8b801fda1f5eb77dc","names":[],"sources":[]},
|
||||
{"digest":"cda79b839d8cc0c7a7bd09dd067de04925f6e9037080d878b65aaa5a383f117c","names":["packages/llm/llm/src/message.ts#Message"],"sources":["packages/llm/llm/src/message.ts:196"]},
|
||||
{"digest":"cdca80b8dad24d4e7b1d5a288a8475ba8d8d46be385bd2da85f122ee836f1670","names":[],"sources":[]},
|
||||
{"digest":"cdee10e87dbed8440d8b6935888624884878efc7af95402e94171b29f173dced","names":[],"sources":["packages/llm/llm-retry/src/types.ts:17"]},
|
||||
{"digest":"cef171adf021a1867d244618a3dbbaafc22beb17c7f3df3ee203393271c8c6f6","names":["packages/core/tool-executor-ptc/src/types.ts#PtcDispatchEventData"],"sources":["packages/core/tool-executor-ptc/src/types.ts:21"]},
|
||||
@@ -592,9 +598,11 @@
|
||||
{"digest":"db874d463b0fdec77e9da1c4568f37cb70bd6596781eb93800db44fb8a116965","names":[],"sources":[]},
|
||||
{"digest":"dba54c09c6e7aafc9acbed7792ecc920d99f92d0784aeeed10af55f7fe0bc8cd","names":[],"sources":["packages/core/tool-executor-ptc/src/types.ts:68"]},
|
||||
{"digest":"dbdafceb9a900183cccc80596498d386f3bf7bddead2b8cfde68453aa4739edc","names":[],"sources":[]},
|
||||
{"digest":"dd00cdccd0ba487b92362ef67db58cd264f48c1bfd368291424a1da9a899489a","names":[],"sources":[]},
|
||||
{"digest":"dd2780e7e07684332f7a9ab047237798d260e7eaffb1321cb38eca695d184c3d","names":[],"sources":[]},
|
||||
{"digest":"dd5ee8762bd8a14b6c6bffedd1753e4e78505bb0f9ea1621018d03a54eef59d5","names":[],"sources":[]},
|
||||
{"digest":"dd6cc2bb2a8f28248347021ad93565360b196a042360b4cd16b569d3a2a91f2d","names":[],"sources":[]},
|
||||
{"digest":"dde0cdf9d426768b649b5a9783d2144e7f900c35ef65229cd89036dbf411d1b0","names":[],"sources":[]},
|
||||
{"digest":"de25352d2dc4196309bd84b5bac6319f6d5c898ea0e82bb5ae66c5738d0d426f","names":[],"sources":[]},
|
||||
{"digest":"de30b1fa12c75f81df6aa4096e1595296d2d04e2be14a7c29849cf8028b79048","names":[],"sources":[]},
|
||||
{"digest":"deaae5cd30987d4f49398e8f9d994c125907e7f928300745fb1dbf15f145d0e7","names":[],"sources":[]},
|
||||
@@ -624,6 +632,7 @@
|
||||
{"digest":"e7ce49f12953583fad217bf80fb9f1463acff2c3e9471a823782661675fb124c","names":[],"sources":[]},
|
||||
{"digest":"e7e154d47d5fbc5366330fb4dade1f108c6dfe4335044d21ded14b7bf1dce084","names":[],"sources":[]},
|
||||
{"digest":"e7e8f1318170b8284f16ab45a557afd4675c96071c0f2a456636481dab20b427","names":[],"sources":[]},
|
||||
{"digest":"e7f4cbb3a57f4cbdb61ea41e95bcba626ad1fff6bb9b1e063b1d50a32da6e864","names":[],"sources":[]},
|
||||
{"digest":"e8de0f457fed5b9ff94dc4950b59ef75fd8ba8af665cc7899485924a62653367","names":[],"sources":[]},
|
||||
{"digest":"e95f957154b2b1b58692af53d4131180b6dd19e2264869f876dbaa959991494e","names":[],"sources":[]},
|
||||
{"digest":"ea08ec1df0c33108fd03345b9af199cf04dea450aa045d3c683f216311403403","names":[],"sources":["packages/experimental/agent-team/src/types.ts:234"]},
|
||||
@@ -639,6 +648,7 @@
|
||||
{"digest":"ef11a3b7fa2033ae4279545ff8a8a2ee4e301b9b73e5b91654c48e6d08283545","names":[],"sources":["packages/core/session/src/types.ts:301","packages/core/session/src/types.ts:303"]},
|
||||
{"digest":"ef226a90ddac6cd8e631a3a337a3a3e27f9494be92befb7c718b404681d75e21","names":[],"sources":[]},
|
||||
{"digest":"ef4f00923b9edbae15c7ef05320280bf61147ca17146cf59690359bfd5e5da45","names":[],"sources":[]},
|
||||
{"digest":"efa1a091017ce533e38b0ef3e14d11a5c102ff1793229b18dad719a4268d9adc","names":[],"sources":[]},
|
||||
{"digest":"f05fb85e715af4ab4de0b6ba111166dd0435bd8bb74a0fa0f32b9d174113fc7c","names":[],"sources":[]},
|
||||
{"digest":"f09e5e7acf5ff5ccd193ff2eeec015fa2ff7c29d98bc465f8c3302058d47e29b","names":["packages/core/agent/src/types.ts#ModelSelection"],"sources":["packages/core/agent/src/types.ts:79"]},
|
||||
{"digest":"f1687f982fa3d41ef29e159feed154ecd13af4dd209acaee16038f223f2e9402","names":["packages/core/session/src/types.ts#TurnEndReason"],"sources":["packages/core/session/src/types.ts:234"]},
|
||||
@@ -650,7 +660,6 @@
|
||||
{"digest":"f2da0f27c1e6add59982c37b15e4a4912c5b33466859cce3b13d503600e24aef","names":["packages/llm/llm/src/types.ts#FileBlock"],"sources":["packages/llm/llm/src/types.ts:98"]},
|
||||
{"digest":"f311671e07bc7fa645a0b6597de9966b97147956565296ba76a36543801b66c5","names":["packages/llm/llm/src/types.ts#SystemPromptUpdate"],"sources":["packages/llm/llm/src/types.ts:414"]},
|
||||
{"digest":"f4a66f654996c093aae700ea4c434ff2ee3569fea9c0e5813ccf6afdccabd163","names":[],"sources":[]},
|
||||
{"digest":"f4ed4717b4c259e933b550a8dcd90dc93628cda8a3c7affcaa53b9c13c1d53eb","names":[],"sources":["packages/core/session/src/types.ts:313"]},
|
||||
{"digest":"f5520c1d261ca86ea03735799c311a0a9ede8babb588cf0a65422576d2ee0ad1","names":[],"sources":[]},
|
||||
{"digest":"f56c5b59ca0161310c338d31dd16cf14287ccd602ff4181058df178c1c286d7f","names":["packages/context/session-reference/src/types.ts#SessionReferenceSource"],"sources":["packages/context/session-reference/src/types.ts:13"]},
|
||||
{"digest":"f6329fb30c7ea8013e8975ca5e78284fb7685cc6bd620e8aa4e9a99bc81d45eb","names":[],"sources":[]},
|
||||
@@ -666,7 +675,6 @@
|
||||
{"digest":"f90eb4ab2d3897bc20c521a038e3119d581f791ec974b1a0004f63a8ab9e232d","names":[],"sources":["packages/core/session/src/types.ts:290","packages/deliverables/workspace-changes/src/types.ts:106"]},
|
||||
{"digest":"f97f47b0eb87905ed77cc27c5e4ed75ef805cb372c98905253709de1aab9b63c","names":[],"sources":[]},
|
||||
{"digest":"f9cfc89e8fe085b4fcc9cd32b74b6f103608c54d7d8cd97b47c01de34f252ba3","names":[],"sources":[]},
|
||||
{"digest":"fa106c5b33b657e8ef16e8cbf39f3b7d44e5cbcdf4f9303d9db6410f28951e42","names":[],"sources":["packages/core/agent/src/types.ts:110"]},
|
||||
{"digest":"fa87537f4a9c1e25602990a8bf686b383e9e00352ec8946e16ae24ba7c1625be","names":["packages/llm/llm/src/message.ts#AssistantMessage"],"sources":["packages/llm/llm/src/message.ts:167"]},
|
||||
{"digest":"fab2bb09bc5e3b9db0685e8f5500b029af1a2b33e70bc703c1d5d0f596fbc1fd","names":["packages/sandbox/sandbox/src/index.ts#SandboxMode"],"sources":["packages/sandbox/sandbox/src/index.ts:30"]},
|
||||
{"digest":"fab35c4520883c0d69e42d079c9f543fc5ac7a2d15b537b5572fcd99059c7018","names":[],"sources":[]},
|
||||
@@ -684,18 +692,16 @@
|
||||
{"digest":"fee1caf8ab6a65c1bc981f5a1730164490f22a2a89ffa3d0b76f1f432c44c8b5","names":[],"sources":[]}
|
||||
],
|
||||
"nodes": {
|
||||
"00c054d3018c198d": {"kind":"object","properties":[{"name":"maxTokens","type":"0657d3ca5ac4e7bf","optional":false},{"name":"messageSeqs","type":"5d03ba38734809bc","optional":false},{"name":"messages","type":"a927d444c928ac0e","optional":false},{"name":"reasoningEffort","type":"4cd48f3e5108bd6e","optional":true},{"name":"route","type":"07e1a58c58b593f5","optional":false},{"name":"system","type":"4cd48f3e5108bd6e","optional":false},{"name":"titleProvider","type":"4cd48f3e5108bd6e","optional":false}],"indices":[]},
|
||||
"0116b1f89c05221d": {"kind":"literal","value":"web_search_20250305"},
|
||||
"0203243b72fc867a": {"kind":"object","properties":[{"name":"kind","type":"24b10f7cdae64928","optional":false}],"indices":[]},
|
||||
"022623b9ef98ec47": {"kind":"object","properties":[{"name":"form","type":"383cf73ae4748e5b","optional":false},{"name":"kind","type":"f68c335306535a00","optional":false}],"indices":[]},
|
||||
"023a355b2be0d688": {"kind":"object","properties":[{"name":"kind","type":"254dce209e735f9c","optional":false}],"indices":[]},
|
||||
"02b2c23f2d94b028": {"kind":"object","properties":[{"name":"kind","type":"c5687b1313206a6f","optional":false}],"indices":[]},
|
||||
"0341d4c3dfcd5325": {"kind":"literal","value":"product-interaction"},
|
||||
"040cd65423bd6426": {"kind":"union","types":["09f3f8dc417f2782","0f6265188dae7ba6","2cf075b013d363ad","4b259f7f8f0a44ad","fa87537f4a9c1e25"]},
|
||||
"05205074b24d8340": {"kind":"literal","value":"action-cards"},
|
||||
"05a2796621b1ee6c": {"kind":"literal","value":"unknown"},
|
||||
"05d2ae1e0c7f8770": {"kind":"union","types":["1571525adc95a24e","9e07693fd7cd9bab"]},
|
||||
"0657d3ca5ac4e7bf": {"kind":"primitive","type":"number"},
|
||||
"0755b7d1128319ba": {"kind":"object","properties":[{"name":"data","type":"fa106c5b33b657e8","optional":false},{"name":"ignorable","type":"dacf3d5f3e4ff619","optional":true},{"name":"seq","type":"0657d3ca5ac4e7bf","optional":false},{"name":"time","type":"0657d3ca5ac4e7bf","optional":false},{"name":"type","type":"829a2fb3be6efd4b","optional":false}],"indices":[]},
|
||||
"07e1a58c58b593f5": {"kind":"object","properties":[{"name":"model","type":"4cd48f3e5108bd6e","optional":false},{"name":"provider","type":"4cd48f3e5108bd6e","optional":false}],"indices":[]},
|
||||
"07eccc9ea2f9b543": {"kind":"literal","value":"security-privacy-permission"},
|
||||
"09655b34d7f3cf1e": {"kind":"literal","value":"system-prompt"},
|
||||
@@ -717,7 +723,6 @@
|
||||
"0ed8d1108fe7a5e1": {"kind":"object","properties":[{"name":"kind","type":"a9059a81430b3207","optional":false}],"indices":[]},
|
||||
"0eeb17e1df89b1eb": {"kind":"object","properties":[{"name":"form","type":"fee1caf8ab6a65c1","optional":false},{"name":"kind","type":"24b10f7cdae64928","optional":false}],"indices":[]},
|
||||
"0f46153645c29784": {"kind":"object","properties":[{"name":"height","type":"0657d3ca5ac4e7bf","optional":false},{"name":"width","type":"0657d3ca5ac4e7bf","optional":false}],"indices":[]},
|
||||
"0f6265188dae7ba6": {"kind":"object","properties":[{"name":"content","type":"b52f215a6cd69105","optional":false},{"name":"id","type":"4cd48f3e5108bd6e","optional":false},{"name":"role","type":"589d0d91239681f8","optional":false},{"name":"source","type":"5bc2d7f02503fc6b","optional":false,"compatibility":{"version":1,"policy":"session-source-attribution","binding":"session.developer-message.source","discriminator":"kind","unknownKinds":"preserve","attributionKinds":["tmux-context","user-question-reply","working-directory"]}}],"indices":[]},
|
||||
"0f8512903d94f57a": {"kind":"object","properties":[{"name":"data","type":"e481c46af3813e00","optional":false},{"name":"ignorable","type":"dacf3d5f3e4ff619","optional":true},{"name":"seq","type":"0657d3ca5ac4e7bf","optional":false},{"name":"time","type":"0657d3ca5ac4e7bf","optional":false},{"name":"type","type":"4312134fc6f9cad5","optional":false}],"indices":[]},
|
||||
"0fe52387f6505270": {"kind":"literal","value":"plan-mode"},
|
||||
"1033093edd0db80f": {"kind":"object","properties":[{"name":"data","type":"1ccb56061942f5cc","optional":false},{"name":"ignorable","type":"dacf3d5f3e4ff619","optional":true},{"name":"seq","type":"0657d3ca5ac4e7bf","optional":false},{"name":"surfaceOp","type":"335e242de1fcc17b","optional":false},{"name":"time","type":"0657d3ca5ac4e7bf","optional":false},{"name":"type","type":"6ab45ac76839722d","optional":false}],"indices":[]},
|
||||
@@ -794,11 +799,9 @@
|
||||
"2aad1179f9576314": {"kind":"object","properties":[{"name":"form","type":"6f9e00383836275e","optional":false},{"name":"kind","type":"24b10f7cdae64928","optional":false},{"name":"sections","type":"c748fb42c80a1200","optional":false}],"indices":[]},
|
||||
"2ab12a0e345658f9": {"kind":"array","element":"83da72c6857601c7"},
|
||||
"2abb711460e6238d": {"kind":"object","properties":[{"name":"index","type":"0657d3ca5ac4e7bf","optional":false},{"name":"text","type":"4cd48f3e5108bd6e","optional":false},{"name":"type","type":"6f091fe32ab24407","optional":false}],"indices":[]},
|
||||
"2ae8594a998c9862": {"kind":"object","properties":[{"name":"data","type":"2cf075b013d363ad","optional":false},{"name":"ignorable","type":"dacf3d5f3e4ff619","optional":true},{"name":"seq","type":"0657d3ca5ac4e7bf","optional":false},{"name":"sourceEventSeqs","type":"5d03ba38734809bc","optional":true},{"name":"surfaceOp","type":"335e242de1fcc17b","optional":false},{"name":"time","type":"0657d3ca5ac4e7bf","optional":false},{"name":"type","type":"de25352d2dc41963","optional":false}],"indices":[]},
|
||||
"2aed07493b1c65b6": {"kind":"literal","value":"tool/ptc-dispatch-start"},
|
||||
"2c4c21f19f426a58": {"kind":"literal","value":"unavailable"},
|
||||
"2c64d4bc7264fd3f": {"kind":"literal","value":"step/start"},
|
||||
"2cf075b013d363ad": {"kind":"object","properties":[{"name":"content","type":"b52f215a6cd69105","optional":false},{"name":"id","type":"4cd48f3e5108bd6e","optional":false},{"name":"role","type":"68f44f59e91c4139","optional":false},{"name":"source","type":"5bc2d7f02503fc6b","optional":false,"compatibility":{"version":1,"policy":"session-source-attribution","binding":"session.user-message.source","discriminator":"kind","unknownKinds":"preserve","attributionKinds":["tmux-context","user-question-reply","working-directory"]}}],"indices":[]},
|
||||
"2d11ca7b0d4493e2": {"kind":"object","properties":[{"name":"max_uses","type":"0657d3ca5ac4e7bf","optional":false},{"name":"name","type":"935c8d486292b13c","optional":false},{"name":"type","type":"0116b1f89c05221d","optional":false}],"indices":[]},
|
||||
"2da725e554cd8930": {"kind":"literal","value":"fork"},
|
||||
"2e3523541e942ef6": {"kind":"union","types":["18dc21f12bbac8ad","8e8e91646a5cae3f","e6063d0451dc0202","eea687d437880bd5"]},
|
||||
@@ -810,6 +813,7 @@
|
||||
"30d5a537b2966857": {"kind":"union","types":["1b5649238876e288","ada310bf0bdb8fed","b81e9de81a481b24"]},
|
||||
"312aee2f0c42aabb": {"kind":"object","properties":[{"name":"form","type":"e8de0f457fed5b9f","optional":false},{"name":"kind","type":"d9edf1862e4471d6","optional":false},{"name":"summary","type":"4cd48f3e5108bd6e","optional":false}],"indices":[]},
|
||||
"31907de956375182": {"kind":"object","properties":[{"name":"compactionId","type":"4cd48f3e5108bd6e","optional":false},{"name":"kind","type":"6b23ed9ce1b397e6","optional":false},{"name":"sourceCommandId","type":"4cd48f3e5108bd6e","optional":true}],"indices":[]},
|
||||
"3247e566f4340029": {"kind":"object","properties":[{"name":"form","type":"6f9e00383836275e","optional":false},{"name":"kind","type":"05205074b24d8340","optional":false},{"name":"sections","type":"c748fb42c80a1200","optional":false},{"name":"through","type":"0657d3ca5ac4e7bf","optional":false}],"indices":[]},
|
||||
"326a9bfda27dda58": {"kind":"object","properties":[{"name":"maxTokens","type":"dacf3d5f3e4ff619","optional":true},{"name":"reasoningEffort","type":"dacf3d5f3e4ff619","optional":true}],"indices":[]},
|
||||
"3305a4bb6b6c29b4": {"kind":"union","types":["0341d4c3dfcd5325","07eccc9ea2f9b543","5bd310104cfe448e","7180844e1066230c","9d80129e13edfb6f","e4cac694f8b6e1d5","f05fb85e715af4ab"]},
|
||||
"33341aac09312300": {"kind":"union","types":["3860b4757d512a28","487b65c37bfedb8b","71bb3254ec8f1e49","e72269f931559e90"]},
|
||||
@@ -852,7 +856,7 @@
|
||||
"44818000e56acb97": {"kind":"literal","value":"feedback/message-delete"},
|
||||
"44c8c77aa9aa100b": {"kind":"literal","value":"subagent/catalog"},
|
||||
"4513e088d43e6c68": {"kind":"object","properties":[{"name":"data","type":"ef11a3b7fa2033ae","optional":false},{"name":"ignorable","type":"dacf3d5f3e4ff619","optional":true},{"name":"seq","type":"0657d3ca5ac4e7bf","optional":false},{"name":"time","type":"0657d3ca5ac4e7bf","optional":false},{"name":"type","type":"2c64d4bc7264fd3f","optional":false}],"indices":[]},
|
||||
"454a0fa879e38076": {"kind":"array","element":"2cf075b013d363ad"},
|
||||
"45f005e6bbb76452": {"kind":"object","properties":[{"name":"form","type":"16d0507cb94b4cfc","optional":false},{"name":"kind","type":"05205074b24d8340","optional":false},{"name":"through","type":"0657d3ca5ac4e7bf","optional":false}],"indices":[]},
|
||||
"45f2a07ea9457312": {"kind":"object","properties":[{"name":"callId","type":"4cd48f3e5108bd6e","optional":true},{"name":"id","type":"4cd48f3e5108bd6e","optional":false},{"name":"reason","type":"4cd48f3e5108bd6e","optional":true},{"name":"toolName","type":"4cd48f3e5108bd6e","optional":false}],"indices":[]},
|
||||
"477614bca595a9e7": {"kind":"object","properties":[{"name":"targets","type":"9e2c06d8653585b3","optional":false}],"indices":[]},
|
||||
"47e5d84f1a93450a": {"kind":"literal","value":"session-log-deepseek/delivery-accepted"},
|
||||
@@ -901,17 +905,18 @@
|
||||
"5808e36c95355f0e": {"kind":"union","types":["1d76406cbb2ddadb","287211846beea1ec","693f4952fb5565da","8e31bb958e9b015e","ab7ec5f9eb2c6dfa"]},
|
||||
"587bb11da730e06a": {"kind":"literal","value":"session/title-llm-request"},
|
||||
"589d0d91239681f8": {"kind":"literal","value":"developer"},
|
||||
"58b122df513aeaf7": {"kind":"object","properties":[{"name":"data","type":"b782058cef83caf3","optional":false},{"name":"ignorable","type":"dacf3d5f3e4ff619","optional":true},{"name":"seq","type":"0657d3ca5ac4e7bf","optional":false},{"name":"sourceEventSeqs","type":"5d03ba38734809bc","optional":true},{"name":"surfaceOp","type":"335e242de1fcc17b","optional":false},{"name":"time","type":"0657d3ca5ac4e7bf","optional":false},{"name":"type","type":"de25352d2dc41963","optional":false}],"indices":[]},
|
||||
"58f94390b982f8a5": {"kind":"literal","value":"image/png"},
|
||||
"5abab3a27fd27366": {"kind":"literal","value":"text-delta"},
|
||||
"5b232a9b9bfcc0fc": {"kind":"literal","value":"after"},
|
||||
"5b6fb1f226ff5640": {"kind":"object","properties":[{"name":"commandId","type":"4cd48f3e5108bd6e","optional":false},{"name":"kind","type":"1ab2ef1296f157ba","optional":false},{"name":"sourceEventSeq","type":"0657d3ca5ac4e7bf","optional":true},{"name":"text","type":"4cd48f3e5108bd6e","optional":true}],"indices":[]},
|
||||
"5bb69b88517f6214": {"kind":"object","properties":[{"name":"form","type":"e8de0f457fed5b9f","optional":false},{"name":"kind","type":"99e7e7d7fed55ae6","optional":false},{"name":"summary","type":"4cd48f3e5108bd6e","optional":false}],"indices":[]},
|
||||
"5bc2d7f02503fc6b": {"kind":"union","types":["0203243b72fc867a","022623b9ef98ec47","02b2c23f2d94b028","0ed8d1108fe7a5e1","0eeb17e1df89b1eb","11638dc58a31496f","1938c8c20f1cba7c","1e709346005826eb","1fdad624334d3548","2152caf1a71e588e","2235d957bf4b7c6c","224aa11d4d5f88c4","24ce31aa528272e5","260523b412c19ad8","28936c614bd4e7e2","290f32bfd81ff85a","297fbd8067d7815a","2aad1179f9576314","312aee2f0c42aabb","31907de956375182","3b04790e08b35241","3b4f2c9ef2c1217e","3bdb8dc6989655b0","408927267422a7b2","4991dfc415c9efeb","49dab019d00e8c26","4a9bef9f27a94252","4e97c3d85c0fc817","52c6113cb0e53f34","53cf1704ae0709c7","5654685d7557ec74","58015da1c1950a66","5bb69b88517f6214","5bc66269cfaf614c","5cdbf342b7748d15","5d7a64ed6aac5551","6085488d223aeffd","6292bcbedaa97fea","65a8400e451e667e","672c4aa2a9b736e3","6ccb6bc423fb3952","6dacb1584f2bfbe2","6ea608bdc8a7a63d","6f22a9d02b9a1f11","6f44f32be9bcd9a8","719c51f67074f970","7554565be416b034","756b5e23a5cb2c7f","7df62978a2b7de85","7eaef7a763ba5b94","7f959241c24128b4","80677c8c8b804189","825ca23416b1ea9d","8338ee303e2bd448","854db3efdfb0cd39","85fe96bf15d5c755","8620189c8e335827","87b1a33564b9a4d6","88841202942c7683","8a046b52331959aa","8c1c4f72755a78ea","8c627d7a45fa406c","8f324cea3916c051","8fcb0b44a575e998","96bfb916a727cd44","99135d8a39379779","99f0e98184709ad1","9edc162949abf93b","9f65c43e340bba31","a15a19ef63cf5d1b","a16e567c8cd2c55c","a2066bd52f61218b","a3c6f1ea38e9a61d","aa2bf9e82b9fdeb9","aae343bc3d663c83","ada310bf0bdb8fed","ade057f4fdc387ae","b062078e899958f9","b2a5c8c008a31e3d","b3681c026a0b98e9","b4ec0af39fd52ed9","b6f94c17dd9bbd7c","b70f3e81fe11b7a5","b79641a9d25e7566","ba4c40b4381e0dcd","baccc97ec34be6c4","c5228b7a55498d84","c55827fba7018198","cb1c8959e1726f82","cda2345a9be9d139","d85590a5675c6e2f","d9c462b9f62fdd3e","db06ef35b27a3842","dba54c09c6e7aafc","dd5ee8762bd8a14b","dd6cc2bb2a8f2824","deaae5cd30987d4f","edbbfff1128099fd","ee577a0cc18664c9","f230c0b583e23b25","f29d63336e8266d8","f4a66f654996c093","f56c5b59ca016131","f6329fb30c7ea801","f6605d6c57933aea","f6afe41e3926f422","f7283223aacdc39b","f97f47b0eb87905e","fc2ae6962f9f8801","fcf81d3c58c13593","fe1a7acdeed4d0f5"]},
|
||||
"5bc66269cfaf614c": {"kind":"object","properties":[{"name":"form","type":"16d0507cb94b4cfc","optional":false},{"name":"kind","type":"d9edf1862e4471d6","optional":false}],"indices":[]},
|
||||
"5bd310104cfe448e": {"kind":"literal","value":"resource-cost"},
|
||||
"5c45bf4c544a7211": {"kind":"object","properties":[{"name":"data","type":"8a9c990773f798ea","optional":false},{"name":"ignorable","type":"dacf3d5f3e4ff619","optional":true},{"name":"seq","type":"0657d3ca5ac4e7bf","optional":false},{"name":"time","type":"0657d3ca5ac4e7bf","optional":false},{"name":"type","type":"ae63d9d1080ed894","optional":false}],"indices":[]},
|
||||
"5cb63db9fe57dc09": {"kind":"literal","value":"teardown"},
|
||||
"5cdbf342b7748d15": {"kind":"object","properties":[{"name":"form","type":"16d0507cb94b4cfc","optional":false},{"name":"kind","type":"f68c335306535a00","optional":false}],"indices":[]},
|
||||
"5d00abf938272f22": {"kind":"array","element":"b782058cef83caf3"},
|
||||
"5d03ba38734809bc": {"kind":"array","element":"0657d3ca5ac4e7bf"},
|
||||
"5d17f27a1ef9f702": {"kind":"literal","value":"tool-workflow/agent-end"},
|
||||
"5d542ac7bdf13310": {"kind":"object","properties":[{"name":"childCreatedAt","type":"0657d3ca5ac4e7bf","optional":false},{"name":"childId","type":"4cd48f3e5108bd6e","optional":false},{"name":"label","type":"4cd48f3e5108bd6e","optional":true},{"name":"mode","type":"d28765f87d6b6ab4","optional":false},{"name":"version","type":"93d38436347f67c9","optional":false}],"indices":[]},
|
||||
@@ -919,6 +924,7 @@
|
||||
"5dd766ccd1702a11": {"kind":"object","properties":[{"name":"shadowedRange","type":"9e41386b3a0c9572","optional":false},{"name":"shadowedSeqs","type":"5d03ba38734809bc","optional":false},{"name":"shadowedTokenCount","type":"0657d3ca5ac4e7bf","optional":false}],"indices":[]},
|
||||
"5e6db6e24948d4a8": {"kind":"object","properties":[{"name":"data","type":"17d1afb770d99419","optional":false},{"name":"ignorable","type":"dacf3d5f3e4ff619","optional":true},{"name":"seq","type":"0657d3ca5ac4e7bf","optional":false},{"name":"time","type":"0657d3ca5ac4e7bf","optional":false},{"name":"type","type":"1c2686c0682e7bc5","optional":false}],"indices":[]},
|
||||
"5ebce1317eacd2c1": {"kind":"literal","value":"subagent/descriptor"},
|
||||
"5ef58f2a1bdc576c": {"kind":"object","properties":[{"name":"data","type":"7404c6123fdaa591","optional":false},{"name":"ignorable","type":"dacf3d5f3e4ff619","optional":true},{"name":"seq","type":"0657d3ca5ac4e7bf","optional":false},{"name":"sourceEventSeqs","type":"5d03ba38734809bc","optional":true},{"name":"surfaceOp","type":"335e242de1fcc17b","optional":false},{"name":"time","type":"0657d3ca5ac4e7bf","optional":false},{"name":"type","type":"1379f0b72275994d","optional":false}],"indices":[]},
|
||||
"5f2117d1856a5ab4": {"kind":"object","properties":[{"name":"code","type":"4cd48f3e5108bd6e","optional":false},{"name":"message","type":"4cd48f3e5108bd6e","optional":false},{"name":"offloadImages","type":"0657d3ca5ac4e7bf","optional":true},{"name":"providerRetryAfterMs","type":"0657d3ca5ac4e7bf","optional":true},{"name":"requestId","type":"4cd48f3e5108bd6e","optional":true},{"name":"status","type":"0657d3ca5ac4e7bf","optional":true}],"indices":[]},
|
||||
"5f26a6c20b37632f": {"kind":"object","properties":[{"name":"data","type":"9a410ddf56792b2b","optional":false},{"name":"ignorable","type":"dacf3d5f3e4ff619","optional":true},{"name":"seq","type":"0657d3ca5ac4e7bf","optional":false},{"name":"time","type":"0657d3ca5ac4e7bf","optional":false},{"name":"type","type":"ad92f473a03ae725","optional":false}],"indices":[]},
|
||||
"5f758f3de5f00c18": {"kind":"object","properties":[{"name":"label","type":"4cd48f3e5108bd6e","optional":true},{"name":"mode","type":"d28765f87d6b6ab4","optional":false},{"name":"provider","type":"4cd48f3e5108bd6e","optional":false},{"name":"version","type":"0657d3ca5ac4e7bf","optional":false}],"indices":[]},
|
||||
@@ -967,16 +973,19 @@
|
||||
"71bb3254ec8f1e49": {"kind":"object","properties":[{"name":"dt","type":"5d03ba38734809bc","optional":false},{"name":"index","type":"0657d3ca5ac4e7bf","optional":false},{"name":"texts","type":"93c33d9687613293","optional":false},{"name":"time0","type":"0657d3ca5ac4e7bf","optional":false},{"name":"type","type":"688e853dc149f0d3","optional":false}],"indices":[]},
|
||||
"72ec79127a9c0d02": {"kind":"array","element":"c592ce75aab73fca"},
|
||||
"7382c4fc95fe8c5d": {"kind":"literal","value":"remove"},
|
||||
"7404c6123fdaa591": {"kind":"object","properties":[{"name":"headerSeq","type":"0657d3ca5ac4e7bf","optional":true},{"name":"message","type":"7580e7d96dc8475f","optional":false},{"name":"step","type":"0657d3ca5ac4e7bf","optional":false},{"name":"turn","type":"0657d3ca5ac4e7bf","optional":false}],"indices":[]},
|
||||
"750a2b129d67704d": {"kind":"union","types":["5cb63db9fe57dc09","6cf082d0fb6034de","bab6865794007548"]},
|
||||
"7554565be416b034": {"kind":"object","properties":[{"name":"form","type":"383cf73ae4748e5b","optional":false},{"name":"kind","type":"2f3f201c8846e19c","optional":false}],"indices":[]},
|
||||
"756b5e23a5cb2c7f": {"kind":"object","properties":[{"name":"form","type":"383cf73ae4748e5b","optional":false},{"name":"kind","type":"8067b0d232c350f1","optional":false}],"indices":[]},
|
||||
"7580e7d96dc8475f": {"kind":"object","properties":[{"name":"content","type":"b52f215a6cd69105","optional":false},{"name":"id","type":"4cd48f3e5108bd6e","optional":false},{"name":"role","type":"589d0d91239681f8","optional":false},{"name":"source","type":"7a5b68bd1a5118c8","optional":false,"compatibility":{"version":1,"policy":"session-source-attribution","binding":"session.developer-message.source","discriminator":"kind","unknownKinds":"preserve","attributionKinds":["action-cards","tmux-context","user-question-reply","working-directory"]}}],"indices":[]},
|
||||
"7624ca28c61ca0ea": {"kind":"literal","value":"create"},
|
||||
"763c8a20af487263": {"kind":"object","properties":[{"name":"data","type":"7d226b9fd95b4ba2","optional":false},{"name":"ignorable","type":"dacf3d5f3e4ff619","optional":true},{"name":"seq","type":"0657d3ca5ac4e7bf","optional":false},{"name":"time","type":"0657d3ca5ac4e7bf","optional":false},{"name":"type","type":"237c004c73b6b288","optional":false}],"indices":[]},
|
||||
"76632533f67879dc": {"kind":"literal","value":"delegation"},
|
||||
"78a9be340090b735": {"kind":"literal","value":"tmux-context"},
|
||||
"78b9204976ab9faa": {"kind":"array","element":"cda79b839d8cc0c7"},
|
||||
"79650cfa10aa3c52": {"kind":"object","properties":[{"name":"error","type":"5f2117d1856a5ab4","optional":false},{"name":"kind","type":"a2be0f0cb59f0d4a","optional":false}],"indices":[]},
|
||||
"79a4c87f8bfb4d6d": {"kind":"object","properties":[{"name":"data","type":"00c054d3018c198d","optional":false},{"name":"ignorable","type":"dacf3d5f3e4ff619","optional":true},{"name":"seq","type":"0657d3ca5ac4e7bf","optional":false},{"name":"time","type":"0657d3ca5ac4e7bf","optional":false},{"name":"type","type":"587bb11da730e06a","optional":false}],"indices":[]},
|
||||
"79ddc907312f97cf": {"kind":"object","properties":[{"name":"todos","type":"4b7ddaf3710b88ff","optional":false}],"indices":[]},
|
||||
"7a5b68bd1a5118c8": {"kind":"union","types":["0203243b72fc867a","022623b9ef98ec47","02b2c23f2d94b028","0ed8d1108fe7a5e1","0eeb17e1df89b1eb","11638dc58a31496f","1938c8c20f1cba7c","1e709346005826eb","1fdad624334d3548","2152caf1a71e588e","2235d957bf4b7c6c","224aa11d4d5f88c4","24ce31aa528272e5","260523b412c19ad8","28936c614bd4e7e2","290f32bfd81ff85a","297fbd8067d7815a","2aad1179f9576314","312aee2f0c42aabb","31907de956375182","3247e566f4340029","3b04790e08b35241","3b4f2c9ef2c1217e","3bdb8dc6989655b0","408927267422a7b2","45f005e6bbb76452","4991dfc415c9efeb","49dab019d00e8c26","4a9bef9f27a94252","4e97c3d85c0fc817","52c6113cb0e53f34","53cf1704ae0709c7","5654685d7557ec74","58015da1c1950a66","5bb69b88517f6214","5bc66269cfaf614c","5cdbf342b7748d15","5d7a64ed6aac5551","6085488d223aeffd","6292bcbedaa97fea","65a8400e451e667e","672c4aa2a9b736e3","6ccb6bc423fb3952","6dacb1584f2bfbe2","6ea608bdc8a7a63d","6f22a9d02b9a1f11","6f44f32be9bcd9a8","719c51f67074f970","7554565be416b034","756b5e23a5cb2c7f","7df62978a2b7de85","7eaef7a763ba5b94","7f959241c24128b4","80677c8c8b804189","825ca23416b1ea9d","8338ee303e2bd448","854db3efdfb0cd39","85fe96bf15d5c755","8620189c8e335827","87b1a33564b9a4d6","88841202942c7683","8a046b52331959aa","8c1c4f72755a78ea","8c627d7a45fa406c","8f324cea3916c051","8fcb0b44a575e998","96bfb916a727cd44","99135d8a39379779","99f0e98184709ad1","9edc162949abf93b","9f65c43e340bba31","a15a19ef63cf5d1b","a16e567c8cd2c55c","a2066bd52f61218b","a3c6f1ea38e9a61d","aa2bf9e82b9fdeb9","aae343bc3d663c83","ada310bf0bdb8fed","ade057f4fdc387ae","b062078e899958f9","b2a5c8c008a31e3d","b3681c026a0b98e9","b4ec0af39fd52ed9","b613f83572fe2fbf","b6f94c17dd9bbd7c","b70f3e81fe11b7a5","b79641a9d25e7566","ba2a1a8f194b1bb2","ba4c40b4381e0dcd","baccc97ec34be6c4","c5228b7a55498d84","c55827fba7018198","cb1c8959e1726f82","cda2345a9be9d139","d85590a5675c6e2f","d9c462b9f62fdd3e","db06ef35b27a3842","dba54c09c6e7aafc","dd00cdccd0ba487b","dd5ee8762bd8a14b","dd6cc2bb2a8f2824","dde0cdf9d426768b","deaae5cd30987d4f","e7f4cbb3a57f4cbd","edbbfff1128099fd","ee577a0cc18664c9","f230c0b583e23b25","f29d63336e8266d8","f4a66f654996c093","f56c5b59ca016131","f6329fb30c7ea801","f6605d6c57933aea","f6afe41e3926f422","f7283223aacdc39b","f97f47b0eb87905e","fc2ae6962f9f8801","fcf81d3c58c13593","fe1a7acdeed4d0f5"]},
|
||||
"7a651f3b672c52fb": {"kind":"literal","value":"session/title"},
|
||||
"7af85bf70d4eafce": {"kind":"object","properties":[{"name":"ignorable","type":"dacf3d5f3e4ff619","optional":true},{"name":"seq","type":"0657d3ca5ac4e7bf","optional":false},{"name":"surfaceOp","type":"335e242de1fcc17b","optional":false},{"name":"time","type":"0657d3ca5ac4e7bf","optional":false},{"name":"type","type":"4cd48f3e5108bd6e","optional":false}],"indices":[]},
|
||||
"7b1ce60193fa8b69": {"kind":"literal","value":"working-directory"},
|
||||
@@ -1047,7 +1056,6 @@
|
||||
"9645cf93769a6dfb": {"kind":"literal","value":"user-question-reply"},
|
||||
"96bfb916a727cd44": {"kind":"object","properties":[{"name":"form","type":"383cf73ae4748e5b","optional":false},{"name":"kind","type":"24b10f7cdae64928","optional":false}],"indices":[]},
|
||||
"96f4a9c81fc0f940": {"kind":"union","types":["3e2ece4967cfebe9","62ecb62dc0fe1b5e"]},
|
||||
"97e0162f983c2745": {"kind":"object","properties":[{"name":"data","type":"f4ed4717b4c259e9","optional":false},{"name":"ignorable","type":"dacf3d5f3e4ff619","optional":true},{"name":"seq","type":"0657d3ca5ac4e7bf","optional":false},{"name":"sourceEventSeqs","type":"5d03ba38734809bc","optional":true},{"name":"surfaceOp","type":"335e242de1fcc17b","optional":false},{"name":"time","type":"0657d3ca5ac4e7bf","optional":false},{"name":"type","type":"1379f0b72275994d","optional":false}],"indices":[]},
|
||||
"9890113e97dd3541": {"kind":"object","properties":[{"name":"mode","type":"fab2bb09bc5e3b9d","optional":false},{"name":"source","type":"76632533f67879dc","optional":true}],"indices":[]},
|
||||
"99135d8a39379779": {"kind":"object","properties":[{"name":"form","type":"aec150797b655c5f","optional":false},{"name":"kind","type":"9ac52f0f84fec2eb","optional":false}],"indices":[]},
|
||||
"9947aa5938fe19a8": {"kind":"union","types":["576a2de8355eb098","a99ec0993c62c058"]},
|
||||
@@ -1080,6 +1088,7 @@
|
||||
"a2be0f0cb59f0d4a": {"kind":"literal","value":"error"},
|
||||
"a3a259a1aa5401af": {"kind":"literal","value":"hook/result"},
|
||||
"a3c6f1ea38e9a61d": {"kind":"object","properties":[{"name":"form","type":"e8de0f457fed5b9f","optional":false},{"name":"kind","type":"9ac52f0f84fec2eb","optional":false},{"name":"summary","type":"4cd48f3e5108bd6e","optional":false}],"indices":[]},
|
||||
"a3e299483348f27a": {"kind":"object","properties":[{"name":"maxTokens","type":"0657d3ca5ac4e7bf","optional":false},{"name":"messageSeqs","type":"5d03ba38734809bc","optional":false},{"name":"messages","type":"78b9204976ab9faa","optional":false},{"name":"reasoningEffort","type":"4cd48f3e5108bd6e","optional":true},{"name":"route","type":"07e1a58c58b593f5","optional":false},{"name":"system","type":"4cd48f3e5108bd6e","optional":false},{"name":"titleProvider","type":"4cd48f3e5108bd6e","optional":false}],"indices":[]},
|
||||
"a3edd1efd1fef21b": {"kind":"literal","value":"workspace-write"},
|
||||
"a40d12070f6f4a12": {"kind":"object","properties":[{"name":"task","type":"51edec100659da3a","optional":false},{"name":"teamId","type":"4cd48f3e5108bd6e","optional":false},{"name":"version","type":"a0f906856fc06f1c","optional":false}],"indices":[]},
|
||||
"a6567ccb2e530606": {"kind":"object","properties":[{"name":"data","type":"0d47a8f3d847243c","optional":false},{"name":"ignorable","type":"dacf3d5f3e4ff619","optional":true},{"name":"seq","type":"0657d3ca5ac4e7bf","optional":false},{"name":"time","type":"0657d3ca5ac4e7bf","optional":false},{"name":"type","type":"0a8a062bc9c3c0d9","optional":false}],"indices":[]},
|
||||
@@ -1092,7 +1101,6 @@
|
||||
"a8a2b9011fc06786": {"kind":"literal","value":"team/message/delivered"},
|
||||
"a9059a81430b3207": {"kind":"literal","value":"hooks-claude-code"},
|
||||
"a926dc71814edd01": {"kind":"object","properties":[{"name":"everySeconds","type":"0657d3ca5ac4e7bf","optional":false},{"name":"id","type":"4cd48f3e5108bd6e","optional":false},{"name":"kind","type":"e42b0f40b5d0b628","optional":false},{"name":"prompt","type":"4cd48f3e5108bd6e","optional":false},{"name":"scheduledAt","type":"4cd48f3e5108bd6e","optional":false},{"name":"title","type":"4cd48f3e5108bd6e","optional":true}],"indices":[]},
|
||||
"a927d444c928ac0e": {"kind":"array","element":"040cd65423bd6426"},
|
||||
"a99ec0993c62c058": {"kind":"object","properties":[{"name":"compactionId","type":"4cd48f3e5108bd6e","optional":false},{"name":"llmStreamCall","type":"dacf3d5f3e4ff619","optional":false},{"name":"maxTokens","type":"0657d3ca5ac4e7bf","optional":true},{"name":"model","type":"4cd48f3e5108bd6e","optional":false},{"name":"provider","type":"4cd48f3e5108bd6e","optional":false},{"name":"rawOutput","type":"b52f215a6cd69105","optional":false},{"name":"shadowedRange","type":"9e41386b3a0c9572","optional":false},{"name":"shadowedSeqs","type":"5d03ba38734809bc","optional":false},{"name":"shadowedTokenCount","type":"0657d3ca5ac4e7bf","optional":false},{"name":"sourceCommandId","type":"4cd48f3e5108bd6e","optional":true},{"name":"summary","type":"b52f215a6cd69105","optional":false},{"name":"usage","type":"fec5442b9ee4122e","optional":true}],"indices":[]},
|
||||
"a99f76fd149051c3": {"kind":"object","properties":[{"name":"content","type":"4cd48f3e5108bd6e","optional":false},{"name":"status","type":"fd0d91a1f9dd2efb","optional":false}],"indices":[]},
|
||||
"aa0957eca50aeb28": {"kind":"object","properties":[{"name":"data","type":"f90eb4ab2d3897bc","optional":false},{"name":"ignorable","type":"dacf3d5f3e4ff619","optional":true},{"name":"seq","type":"0657d3ca5ac4e7bf","optional":false},{"name":"time","type":"0657d3ca5ac4e7bf","optional":false},{"name":"type","type":"0af3ecfb8c60d416","optional":false}],"indices":[]},
|
||||
@@ -1125,8 +1133,10 @@
|
||||
"b222069eea2d7680": {"kind":"object","properties":[{"name":"data","type":"477614bca595a9e7","optional":false},{"name":"ignorable","type":"dacf3d5f3e4ff619","optional":true},{"name":"seq","type":"0657d3ca5ac4e7bf","optional":false},{"name":"time","type":"0657d3ca5ac4e7bf","optional":false},{"name":"type","type":"9acbe713f3f64192","optional":false}],"indices":[]},
|
||||
"b2245a906e13aa94": {"kind":"literal","value":"forked"},
|
||||
"b2a5c8c008a31e3d": {"kind":"object","properties":[{"name":"form","type":"383cf73ae4748e5b","optional":false},{"name":"kind","type":"23af3759678a30de","optional":false}],"indices":[]},
|
||||
"b2a948a5340a9341": {"kind":"object","properties":[{"name":"inserted","type":"5d00abf938272f22","optional":false},{"name":"outcome","type":"d4e4d575abeb4b72","optional":true},{"name":"removedCount","type":"0657d3ca5ac4e7bf","optional":true},{"name":"start","type":"0657d3ca5ac4e7bf","optional":false},{"name":"target","type":"96f4a9c81fc0f940","optional":false}],"indices":[]},
|
||||
"b2d2a01e51341a3b": {"kind":"union","types":["1ebc6f9ff3aa9e3a","234142ee4f996f38","94c56aeb1564ad73","e7e8f1318170b828"]},
|
||||
"b3681c026a0b98e9": {"kind":"object","properties":[{"name":"form","type":"e8de0f457fed5b9f","optional":false},{"name":"kind","type":"78a9be340090b735","optional":false},{"name":"summary","type":"4cd48f3e5108bd6e","optional":false}],"indices":[]},
|
||||
"b36fd842cd004b53": {"kind":"object","properties":[{"name":"data","type":"b2a948a5340a9341","optional":false},{"name":"ignorable","type":"dacf3d5f3e4ff619","optional":true},{"name":"seq","type":"0657d3ca5ac4e7bf","optional":false},{"name":"time","type":"0657d3ca5ac4e7bf","optional":false},{"name":"type","type":"829a2fb3be6efd4b","optional":false}],"indices":[]},
|
||||
"b38f206d59bad891": {"kind":"literal","value":"disposed"},
|
||||
"b4ec0af39fd52ed9": {"kind":"object","properties":[{"name":"kind","type":"bb94f3217aa56c88","optional":false}],"indices":[]},
|
||||
"b5086d249e8502e9": {"kind":"object","properties":[{"name":"data","type":"aa7bc2817014ca6c","optional":false},{"name":"ignorable","type":"dacf3d5f3e4ff619","optional":true},{"name":"seq","type":"0657d3ca5ac4e7bf","optional":false},{"name":"time","type":"0657d3ca5ac4e7bf","optional":false},{"name":"type","type":"6cda0d6d3b4336d8","optional":false}],"indices":[]},
|
||||
@@ -1135,12 +1145,14 @@
|
||||
"b56f6a885da3dc39": {"kind":"object","properties":[{"name":"messageSeqs","type":"5d03ba38734809bc","optional":false},{"name":"source","type":"30d5a537b2966857","optional":false},{"name":"title","type":"4cd48f3e5108bd6e","optional":false}],"indices":[]},
|
||||
"b57a2889408de36e": {"kind":"literal","value":"failed"},
|
||||
"b57ae1b37e52bee0": {"kind":"literal","value":"team/task"},
|
||||
"b613f83572fe2fbf": {"kind":"object","properties":[{"name":"form","type":"383cf73ae4748e5b","optional":false},{"name":"kind","type":"05205074b24d8340","optional":false},{"name":"through","type":"0657d3ca5ac4e7bf","optional":false}],"indices":[]},
|
||||
"b63b089a00b3b935": {"kind":"object","properties":[{"name":"id","type":"4cd48f3e5108bd6e","optional":false},{"name":"kind","type":"17aae616ef020b8b","optional":false},{"name":"prompt","type":"4cd48f3e5108bd6e","optional":false},{"name":"scheduledAt","type":"4cd48f3e5108bd6e","optional":false},{"name":"title","type":"4cd48f3e5108bd6e","optional":true}],"indices":[]},
|
||||
"b6896938660a1dfe": {"kind":"object","properties":[{"name":"childCreatedAt","type":"0657d3ca5ac4e7bf","optional":false},{"name":"childId","type":"4cd48f3e5108bd6e","optional":false},{"name":"label","type":"4cd48f3e5108bd6e","optional":true},{"name":"mode","type":"d28765f87d6b6ab4","optional":false},{"name":"version","type":"f88f1b7b6bb733f6","optional":false}],"indices":[]},
|
||||
"b6ef9c6210be8350": {"kind":"object","properties":[{"name":"kind","type":"1ebc6f9ff3aa9e3a","optional":false}],"indices":[]},
|
||||
"b6f94c17dd9bbd7c": {"kind":"object","properties":[{"name":"form","type":"fee1caf8ab6a65c1","optional":false},{"name":"kind","type":"bb94f3217aa56c88","optional":false}],"indices":[]},
|
||||
"b70f3e81fe11b7a5": {"kind":"object","properties":[{"name":"form","type":"fee1caf8ab6a65c1","optional":false},{"name":"kind","type":"a9059a81430b3207","optional":false}],"indices":[]},
|
||||
"b765ee31033cea46": {"kind":"literal","value":"set"},
|
||||
"b782058cef83caf3": {"kind":"object","properties":[{"name":"content","type":"b52f215a6cd69105","optional":false},{"name":"id","type":"4cd48f3e5108bd6e","optional":false},{"name":"role","type":"68f44f59e91c4139","optional":false},{"name":"source","type":"7a5b68bd1a5118c8","optional":false,"compatibility":{"version":1,"policy":"session-source-attribution","binding":"session.user-message.source","discriminator":"kind","unknownKinds":"preserve","attributionKinds":["action-cards","tmux-context","user-question-reply","working-directory"]}}],"indices":[]},
|
||||
"b79641a9d25e7566": {"kind":"object","properties":[{"name":"kind","type":"8067b0d232c350f1","optional":false}],"indices":[]},
|
||||
"b79ada42962cad01": {"kind":"object","properties":[{"name":"data","type":"86d1d0e9cfebb240","optional":false},{"name":"ignorable","type":"dacf3d5f3e4ff619","optional":true},{"name":"seq","type":"0657d3ca5ac4e7bf","optional":false},{"name":"time","type":"0657d3ca5ac4e7bf","optional":false},{"name":"type","type":"5ebce1317eacd2c1","optional":false}],"indices":[]},
|
||||
"b815d7b91cdd9fc6": {"kind":"literal","value":"goal"},
|
||||
@@ -1150,6 +1162,7 @@
|
||||
"b9305f0ea75ccd6a": {"kind":"literal","value":"hook/invoked"},
|
||||
"b978cff734e62143": {"kind":"object","properties":[{"name":"data","type":"79ddc907312f97cf","optional":false},{"name":"ignorable","type":"dacf3d5f3e4ff619","optional":true},{"name":"seq","type":"0657d3ca5ac4e7bf","optional":false},{"name":"time","type":"0657d3ca5ac4e7bf","optional":false},{"name":"type","type":"af0750d32d97d47b","optional":false}],"indices":[]},
|
||||
"b993441f8ce7d27b": {"kind":"tuple","elements":[{"type":"9a2a9029f8d7ede0","optional":false,"rest":false}]},
|
||||
"ba2a1a8f194b1bb2": {"kind":"object","properties":[{"name":"form","type":"fee1caf8ab6a65c1","optional":false},{"name":"kind","type":"05205074b24d8340","optional":false},{"name":"through","type":"0657d3ca5ac4e7bf","optional":false}],"indices":[]},
|
||||
"ba4c40b4381e0dcd": {"kind":"object","properties":[{"name":"form","type":"6f9e00383836275e","optional":false},{"name":"kind","type":"23af3759678a30de","optional":false},{"name":"sections","type":"c748fb42c80a1200","optional":false}],"indices":[]},
|
||||
"ba77b58995e36f14": {"kind":"array","element":"07e1a58c58b593f5"},
|
||||
"bab6865794007548": {"kind":"literal","value":"kill"},
|
||||
@@ -1184,6 +1197,7 @@
|
||||
"cbca49bde16b656d": {"kind":"literal","value":"block-start"},
|
||||
"cd186c309e2bef30": {"kind":"literal","value":"approval/asked"},
|
||||
"cda2345a9be9d139": {"kind":"object","properties":[{"name":"form","type":"e8de0f457fed5b9f","optional":false},{"name":"kind","type":"24b10f7cdae64928","optional":false},{"name":"summary","type":"4cd48f3e5108bd6e","optional":false}],"indices":[]},
|
||||
"cda79b839d8cc0c7": {"kind":"union","types":["09f3f8dc417f2782","4b259f7f8f0a44ad","7580e7d96dc8475f","b782058cef83caf3","fa87537f4a9c1e25"]},
|
||||
"cdca80b8dad24d4e": {"kind":"literal","value":"tool-workflow/run-start"},
|
||||
"cdee10e87dbed844": {"kind":"object","properties":[{"name":"delayMs","type":"0657d3ca5ac4e7bf","optional":false},{"name":"failure","type":"5f2117d1856a5ab4","optional":false},{"name":"maxRetries","type":"0657d3ca5ac4e7bf","optional":false},{"name":"mode","type":"3bc287e765d58dc3","optional":false},{"name":"policyKey","type":"4cd48f3e5108bd6e","optional":false},{"name":"provider","type":"4cd48f3e5108bd6e","optional":false},{"name":"retry","type":"0657d3ca5ac4e7bf","optional":false},{"name":"retryId","type":"4cd48f3e5108bd6e","optional":false},{"name":"step","type":"0657d3ca5ac4e7bf","optional":false},{"name":"turn","type":"0657d3ca5ac4e7bf","optional":false}],"indices":[]},
|
||||
"cef171adf021a186": {"kind":"object","properties":[{"name":"arguments","type":"bbc5696e3f13c758","optional":false},{"name":"content","type":"b52f215a6cd69105","optional":false},{"name":"error","type":"a81059ca06999da1","optional":true},{"name":"isError","type":"aa93010d0e521ad7","optional":false},{"name":"meta","type":"c592ce75aab73fca","optional":true},{"name":"name","type":"4cd48f3e5108bd6e","optional":false},{"name":"parentCallId","type":"4cd48f3e5108bd6e","optional":false},{"name":"rootCallId","type":"4cd48f3e5108bd6e","optional":false},{"name":"subCallId","type":"4cd48f3e5108bd6e","optional":false}],"indices":[]},
|
||||
@@ -1208,9 +1222,11 @@
|
||||
"db874d463b0fdec7": {"kind":"object","properties":[{"name":"data","type":"3e4e7683b0192c9f","optional":false},{"name":"ignorable","type":"dacf3d5f3e4ff619","optional":true},{"name":"seq","type":"0657d3ca5ac4e7bf","optional":false},{"name":"time","type":"0657d3ca5ac4e7bf","optional":false},{"name":"type","type":"e2d0367e5716bc18","optional":false}],"indices":[]},
|
||||
"dba54c09c6e7aafc": {"kind":"object","properties":[{"name":"kind","type":"4edec1b770e8ec4c","optional":false}],"indices":[]},
|
||||
"dbdafceb9a900183": {"kind":"literal","value":"hook"},
|
||||
"dd00cdccd0ba487b": {"kind":"object","properties":[{"name":"form","type":"aec150797b655c5f","optional":false},{"name":"kind","type":"05205074b24d8340","optional":false},{"name":"through","type":"0657d3ca5ac4e7bf","optional":false}],"indices":[]},
|
||||
"dd2780e7e0768433": {"kind":"literal","value":"fresh"},
|
||||
"dd5ee8762bd8a14b": {"kind":"object","properties":[{"name":"form","type":"aec150797b655c5f","optional":false},{"name":"kind","type":"99e7e7d7fed55ae6","optional":false}],"indices":[]},
|
||||
"dd6cc2bb2a8f2824": {"kind":"object","properties":[{"name":"form","type":"383cf73ae4748e5b","optional":false},{"name":"kind","type":"99e7e7d7fed55ae6","optional":false}],"indices":[]},
|
||||
"dde0cdf9d426768b": {"kind":"object","properties":[{"name":"kind","type":"05205074b24d8340","optional":false},{"name":"through","type":"0657d3ca5ac4e7bf","optional":false}],"indices":[]},
|
||||
"de25352d2dc41963": {"kind":"literal","value":"user/message"},
|
||||
"de30b1fa12c75f81": {"kind":"literal","value":"image/gif"},
|
||||
"deaae5cd30987d4f": {"kind":"object","properties":[{"name":"form","type":"16d0507cb94b4cfc","optional":false},{"name":"kind","type":"0fe52387f6505270","optional":false}],"indices":[]},
|
||||
@@ -1240,6 +1256,7 @@
|
||||
"e7ce49f12953583f": {"kind":"literal","value":"initial"},
|
||||
"e7e154d47d5fbc53": {"kind":"literal","value":"clear"},
|
||||
"e7e8f1318170b828": {"kind":"literal","value":"deleted"},
|
||||
"e7f4cbb3a57f4cbd": {"kind":"object","properties":[{"name":"form","type":"e8de0f457fed5b9f","optional":false},{"name":"kind","type":"05205074b24d8340","optional":false},{"name":"summary","type":"4cd48f3e5108bd6e","optional":false},{"name":"through","type":"0657d3ca5ac4e7bf","optional":false}],"indices":[]},
|
||||
"e8de0f457fed5b9f": {"kind":"literal","value":"notice"},
|
||||
"e95f957154b2b1b5": {"kind":"literal","value":"assistant/attempt"},
|
||||
"ea08ec1df0c33108": {"kind":"object","properties":[{"name":"message","type":"2eafefdc6f79a492","optional":false},{"name":"teamId","type":"4cd48f3e5108bd6e","optional":false},{"name":"version","type":"a0f906856fc06f1c","optional":false}],"indices":[]},
|
||||
@@ -1255,6 +1272,7 @@
|
||||
"ef11a3b7fa2033ae": {"kind":"object","properties":[{"name":"step","type":"0657d3ca5ac4e7bf","optional":false},{"name":"turn","type":"0657d3ca5ac4e7bf","optional":false}],"indices":[]},
|
||||
"ef226a90ddac6cd8": {"kind":"literal","value":"killed"},
|
||||
"ef4f00923b9edbae": {"kind":"literal","value":"compaction/summary"},
|
||||
"efa1a091017ce533": {"kind":"object","properties":[{"name":"data","type":"a3e299483348f27a","optional":false},{"name":"ignorable","type":"dacf3d5f3e4ff619","optional":true},{"name":"seq","type":"0657d3ca5ac4e7bf","optional":false},{"name":"time","type":"0657d3ca5ac4e7bf","optional":false},{"name":"type","type":"587bb11da730e06a","optional":false}],"indices":[]},
|
||||
"f05fb85e715af4ab": {"kind":"literal","value":"task-result"},
|
||||
"f09e5e7acf5ff5cc": {"kind":"object","properties":[{"name":"model","type":"4cd48f3e5108bd6e","optional":false},{"name":"provider","type":"4cd48f3e5108bd6e","optional":false},{"name":"reasoningEffort","type":"4cd48f3e5108bd6e","optional":true}],"indices":[]},
|
||||
"f1687f982fa3d41e": {"kind":"union","types":["023a355b2be0d688","0a30c3be336cdd4f","56b7c047694875a8","79650cfa10aa3c52","ab7ec5f9eb2c6dfa","b6ef9c6210be8350","ec8b5ff7c77ca689"]},
|
||||
@@ -1266,7 +1284,6 @@
|
||||
"f2da0f27c1e6add5": {"kind":"object","properties":[{"name":"attachment","type":"f19bee84bf3d2090","optional":false},{"name":"type","type":"277b61f9c6f81704","optional":false}],"indices":[]},
|
||||
"f311671e07bc7fa6": {"kind":"literal","value":"in-history"},
|
||||
"f4a66f654996c093": {"kind":"object","properties":[{"name":"kind","type":"0fe52387f6505270","optional":false}],"indices":[]},
|
||||
"f4ed4717b4c259e9": {"kind":"object","properties":[{"name":"headerSeq","type":"0657d3ca5ac4e7bf","optional":true},{"name":"message","type":"0f6265188dae7ba6","optional":false},{"name":"step","type":"0657d3ca5ac4e7bf","optional":false},{"name":"turn","type":"0657d3ca5ac4e7bf","optional":false}],"indices":[]},
|
||||
"f5520c1d261ca86e": {"kind":"object","properties":[{"name":"data","type":"e3056e0dda3a379e","optional":false},{"name":"ignorable","type":"dacf3d5f3e4ff619","optional":true},{"name":"seq","type":"0657d3ca5ac4e7bf","optional":false},{"name":"time","type":"0657d3ca5ac4e7bf","optional":false},{"name":"type","type":"24a8188c4d61b70a","optional":false}],"indices":[]},
|
||||
"f56c5b59ca016131": {"kind":"object","properties":[{"name":"form","type":"383cf73ae4748e5b","optional":false},{"name":"kind","type":"7f13860ee89a2d35","optional":false},{"name":"references","type":"df843efd87c78cf8","optional":false},{"name":"version","type":"f88f1b7b6bb733f6","optional":false}],"indices":[]},
|
||||
"f6329fb30c7ea801": {"kind":"object","properties":[{"name":"form","type":"383cf73ae4748e5b","optional":false},{"name":"kind","type":"0fe52387f6505270","optional":false}],"indices":[]},
|
||||
@@ -1282,7 +1299,6 @@
|
||||
"f90eb4ab2d3897bc": {"kind":"object","properties":[{"name":"turn","type":"0657d3ca5ac4e7bf","optional":false}],"indices":[]},
|
||||
"f97f47b0eb87905e": {"kind":"object","properties":[{"name":"form","type":"16d0507cb94b4cfc","optional":false},{"name":"kind","type":"78a9be340090b735","optional":false}],"indices":[]},
|
||||
"f9cfc89e8fe085b4": {"kind":"literal","value":"text-chunks"},
|
||||
"fa106c5b33b657e8": {"kind":"object","properties":[{"name":"inserted","type":"454a0fa879e38076","optional":false},{"name":"outcome","type":"d4e4d575abeb4b72","optional":true},{"name":"removedCount","type":"0657d3ca5ac4e7bf","optional":true},{"name":"start","type":"0657d3ca5ac4e7bf","optional":false},{"name":"target","type":"96f4a9c81fc0f940","optional":false}],"indices":[]},
|
||||
"fa87537f4a9c1e25": {"kind":"object","properties":[{"name":"content","type":"b52f215a6cd69105","optional":false},{"name":"id","type":"4cd48f3e5108bd6e","optional":false},{"name":"role","type":"95c0e88fcf0bafb2","optional":false},{"name":"source","type":"719c51f67074f970","optional":false}],"indices":[]},
|
||||
"fab2bb09bc5e3b9d": {"kind":"union","types":["12a0cfa619ac4a5f","18fce9540bb20897","a3edd1efd1fef21b"]},
|
||||
"fab35c4520883c0d": {"kind":"literal","value":"rejected"},
|
||||
|
||||
@@ -69,6 +69,53 @@ interface PendingModule {
|
||||
|
||||
Generated from source by `scripts/gen-cordis-catalog.ts` (verified fresh by `pnpm run verify-cordis-catalog` in doc-sync; regenerate with `pnpm run gen-cordis-catalog`) — the language sides differ only in locale-specific paired document paths. Signature blocks use a `ts cordis-catalog` fence and keep the original source JSDoc; dispatch modes are defined in the [primer](../cordis-primer.md#dispatch-modes), and the framework-inherited `ctx` API lives in [cordis-api/inherited.md](../cordis-api/inherited.md).
|
||||
|
||||
<a id="ctxactioncards--actioncards"></a>
|
||||
|
||||
### `ctx.actionCards` — `ActionCards`
|
||||
|
||||
Card tool, kind registry, Session projection, user actions and status notices.
|
||||
|
||||
```ts cordis-catalog
|
||||
/**
|
||||
* Register one action kind for the caller's lifetime.
|
||||
* @param kind - the kind's skill, details schema, verbs and handler.
|
||||
* @returns disposer removing the kind; actions on its cards are then unavailable.
|
||||
* @throws when another kind already registered the same action.
|
||||
*/
|
||||
register<Details>(kind: ActionCardKind<Details>): () => void
|
||||
|
||||
/**
|
||||
* Record a card decision in the Session log; the next model request reports it.
|
||||
* @param agent - agent whose Session owns the card.
|
||||
* @param decision - the card's new state.
|
||||
* @throws when no kind ever registered the decision's action with this service, or its phase is one the projection derives.
|
||||
*/
|
||||
record(agent: Agent, decision: ActionCardDecision): void
|
||||
|
||||
/**
|
||||
* Read the cards of one Session.
|
||||
* @param session - a Session whose projections are prepared.
|
||||
* @returns proposals and decisions by call id.
|
||||
*/
|
||||
view(session: Session): ActionCardView
|
||||
|
||||
/**
|
||||
* Apply a user action to a logged card. Shared checks run first, then the kind reconciles the card; `dismiss` is
|
||||
* recorded here and every other verb goes to the card's kind. `dismiss` also works on an unstarted card whose kind
|
||||
* is no longer registered. Concurrent actions on one card share one operation.
|
||||
* @param agent - live root resolved from the displayed Session.
|
||||
* @param callId - the card's `propose_action` call id.
|
||||
* @param verb - `dismiss` or one of the kind's verbs.
|
||||
* @param payload - kind-defined fields such as a chosen location.
|
||||
* @returns acceptance of background work, the decision in effect, or a refusal.
|
||||
*/
|
||||
@Remote act(agent: Agent, callId: ToolCallId, verb: string, payload?: Record<string, JsonValue>): Promise<ActionCardResult>
|
||||
```
|
||||
|
||||
Types: [Agent](core.md) · [Session](session.md) · [ToolCallId](core.md)
|
||||
|
||||
Source: [`packages/experimental/action-cards/src/index.ts`](../../packages/experimental/action-cards/src/index.ts)
|
||||
|
||||
<a id="ctxconfigeditor--configeditor"></a>
|
||||
|
||||
### `ctx.configEditor` — `ConfigEditor`
|
||||
@@ -355,6 +402,26 @@ async entry(url: string, name: string): Promise<MarketListingEntry | undefined>
|
||||
|
||||
Source: [`packages/boot/plugin-market/src/index.ts`](../../packages/boot/plugin-market/src/index.ts)
|
||||
|
||||
<a id="ctxpluginrecommendations--pluginrecommendations"></a>
|
||||
|
||||
### `ctx.pluginRecommendations` — `PluginRecommendations`
|
||||
|
||||
Catalog lookups for card text and the enabling behind the `enable_official_plugin` card.
|
||||
|
||||
```ts cordis-catalog
|
||||
/**
|
||||
* Read the current catalog text for a logged card.
|
||||
* @param agent - Exact live root resolved by the Gateway from the Session id.
|
||||
* @param callId - The card's `propose_action` call id, never a package supplied by the browser.
|
||||
* @returns the plugin's title, description and selection, or a refusal when the card names no available official plugin.
|
||||
*/
|
||||
@Remote async describe(agent: Agent, callId: ToolCallId): Promise<RecommendationDetails>
|
||||
```
|
||||
|
||||
Types: [Agent](core.md) · [ToolCallId](core.md)
|
||||
|
||||
Source: [`packages/experimental/plugin-recommendations/src/index.ts`](../../packages/experimental/plugin-recommendations/src/index.ts)
|
||||
|
||||
<a id="ctxpluginregistryprobe--pluginregistryprobe"></a>
|
||||
|
||||
### `ctx.pluginRegistryProbe` — `PluginRegistryProbe`
|
||||
|
||||
@@ -69,6 +69,53 @@ interface PendingModule {
|
||||
|
||||
Generated from source by `scripts/gen-cordis-catalog.ts` (verified fresh by `pnpm run verify-cordis-catalog` in doc-sync; regenerate with `pnpm run gen-cordis-catalog`) — the language sides differ only in locale-specific paired document paths. Signature blocks use a `ts cordis-catalog` fence and keep the original source JSDoc; dispatch modes are defined in the [primer](../cordis-primer.zh.md#dispatch-modes), and the framework-inherited `ctx` API lives in [cordis-api/inherited.md](../cordis-api/inherited.md).
|
||||
|
||||
<a id="ctxactioncards--actioncards"></a>
|
||||
|
||||
### `ctx.actionCards` — `ActionCards`
|
||||
|
||||
Card tool, kind registry, Session projection, user actions and status notices.
|
||||
|
||||
```ts cordis-catalog
|
||||
/**
|
||||
* Register one action kind for the caller's lifetime.
|
||||
* @param kind - the kind's skill, details schema, verbs and handler.
|
||||
* @returns disposer removing the kind; actions on its cards are then unavailable.
|
||||
* @throws when another kind already registered the same action.
|
||||
*/
|
||||
register<Details>(kind: ActionCardKind<Details>): () => void
|
||||
|
||||
/**
|
||||
* Record a card decision in the Session log; the next model request reports it.
|
||||
* @param agent - agent whose Session owns the card.
|
||||
* @param decision - the card's new state.
|
||||
* @throws when no kind ever registered the decision's action with this service, or its phase is one the projection derives.
|
||||
*/
|
||||
record(agent: Agent, decision: ActionCardDecision): void
|
||||
|
||||
/**
|
||||
* Read the cards of one Session.
|
||||
* @param session - a Session whose projections are prepared.
|
||||
* @returns proposals and decisions by call id.
|
||||
*/
|
||||
view(session: Session): ActionCardView
|
||||
|
||||
/**
|
||||
* Apply a user action to a logged card. Shared checks run first, then the kind reconciles the card; `dismiss` is
|
||||
* recorded here and every other verb goes to the card's kind. `dismiss` also works on an unstarted card whose kind
|
||||
* is no longer registered. Concurrent actions on one card share one operation.
|
||||
* @param agent - live root resolved from the displayed Session.
|
||||
* @param callId - the card's `propose_action` call id.
|
||||
* @param verb - `dismiss` or one of the kind's verbs.
|
||||
* @param payload - kind-defined fields such as a chosen location.
|
||||
* @returns acceptance of background work, the decision in effect, or a refusal.
|
||||
*/
|
||||
@Remote act(agent: Agent, callId: ToolCallId, verb: string, payload?: Record<string, JsonValue>): Promise<ActionCardResult>
|
||||
```
|
||||
|
||||
Types: [Agent](core.zh.md) · [Session](session.zh.md) · [ToolCallId](core.zh.md)
|
||||
|
||||
Source: [`packages/experimental/action-cards/src/index.ts`](../../packages/experimental/action-cards/src/index.ts)
|
||||
|
||||
<a id="ctxconfigeditor--configeditor"></a>
|
||||
|
||||
### `ctx.configEditor` — `ConfigEditor`
|
||||
@@ -355,6 +402,26 @@ async entry(url: string, name: string): Promise<MarketListingEntry | undefined>
|
||||
|
||||
Source: [`packages/boot/plugin-market/src/index.ts`](../../packages/boot/plugin-market/src/index.ts)
|
||||
|
||||
<a id="ctxpluginrecommendations--pluginrecommendations"></a>
|
||||
|
||||
### `ctx.pluginRecommendations` — `PluginRecommendations`
|
||||
|
||||
Catalog lookups for card text and the enabling behind the `enable_official_plugin` card.
|
||||
|
||||
```ts cordis-catalog
|
||||
/**
|
||||
* Read the current catalog text for a logged card.
|
||||
* @param agent - Exact live root resolved by the Gateway from the Session id.
|
||||
* @param callId - The card's `propose_action` call id, never a package supplied by the browser.
|
||||
* @returns the plugin's title, description and selection, or a refusal when the card names no available official plugin.
|
||||
*/
|
||||
@Remote async describe(agent: Agent, callId: ToolCallId): Promise<RecommendationDetails>
|
||||
```
|
||||
|
||||
Types: [Agent](core.zh.md) · [ToolCallId](core.zh.md)
|
||||
|
||||
Source: [`packages/experimental/plugin-recommendations/src/index.ts`](../../packages/experimental/plugin-recommendations/src/index.ts)
|
||||
|
||||
<a id="ctxpluginregistryprobe--pluginregistryprobe"></a>
|
||||
|
||||
### `ctx.pluginRegistryProbe` — `PluginRegistryProbe`
|
||||
|
||||
@@ -9,8 +9,8 @@
|
||||
en: 6cc2cd9ced70bb09
|
||||
zh: 1c0e6cb4ba2ed637
|
||||
/tool-schema-catalog/tool-package-map:
|
||||
en: 10fe940a3d17cde7
|
||||
zh: ef1e8863c28e3c05
|
||||
en: c089eeb9ebe832b1
|
||||
zh: 97f6ac552abb55e3
|
||||
/tool-schema-catalog/deepseek-ai-dsh-plugin-manager:
|
||||
en: e0143916bb634762
|
||||
zh: e0143916bb634762
|
||||
@@ -54,8 +54,14 @@
|
||||
en: 4910ab327694ee97
|
||||
zh: 17e79e4366cb636d
|
||||
/tool-schema-catalog/deepseek-ai-dsh-experimental-browser-use-stagehand-native/stagehand-tabs:
|
||||
en: 095b18f9376e073d
|
||||
zh: abd8785f8acaa555
|
||||
en: a0d5b9b891358120
|
||||
zh: 25793a62709770b5
|
||||
/tool-schema-catalog/deepseek-ai-dsh-action-cards:
|
||||
en: 60c9df6ffda98a1d
|
||||
zh: 60c9df6ffda98a1d
|
||||
/tool-schema-catalog/deepseek-ai-dsh-action-cards/propose-action:
|
||||
en: c289411d447b015a
|
||||
zh: 3a770388e90df4df
|
||||
/tool-schema-catalog/deepseek-ai-dsh-tool-ask-user:
|
||||
en: e713a4a11a15d13c
|
||||
zh: e713a4a11a15d13c
|
||||
|
||||
@@ -19,6 +19,7 @@ This table connects model-visible tool names to the plugin package and service s
|
||||
| `@deepseek-ai/dsh-plugin-market` | `plugin_market` | `ctx.tools`, `ctx.pluginMarket` | `tool/call`, `tool/result` | - | - |
|
||||
| `@deepseek-ai/dsh-mcp-resources` | `list_mcp_resource_templates`, `list_mcp_resources`, `read_mcp_resource` | `ctx.tools`, `ctx.mcpResources` | `tool/call`, `tool/result` | - | - |
|
||||
| `@deepseek-ai/dsh-experimental-browser-use-stagehand-native` | `stagehand_act`, `stagehand_extract`, `stagehand_navigate`, `stagehand_observe`, `stagehand_screenshot`, `stagehand_tabs` | `ctx.browserUse`, `ctx.agents`, `ctx.tools`, `ctx.systemPrompt` | `tool/call`, `tool/result` | - | - |
|
||||
| `@deepseek-ai/dsh-action-cards` | `propose_action` | `ctx.tools`, `ctx.agents`, `ctx.sessionProjections`, `ctx.remoteAccess` | `tool/call`, `tool/result`, `plugin:action-cards/decision`, `user/message` | - | Declared only to an Agent that loaded the skill of a registered card kind; the kind packages register their actions, and the Personalized pages and Plugin recommendations bundles supply the shipped kinds. |
|
||||
| `@deepseek-ai/dsh-tool-ask-user` | `ask_user_question` | `ctx.tools`, `ctx.userQuestions` | `tool/call`, `tool/result after an answer or timeout`, `late user/message` | - | ask_user_question keeps the original blocking behavior by default; set `mode: timed` to opt into a foreground timeout and pending result while the question remains answerable. In timed mode, `timeout: -1` keeps that call blocking indefinitely. |
|
||||
| `@deepseek-ai/dsh-tool-executor-ptc` | `run_code` | `ctx.workingDirectory (Agent executions)`, `ctx.tools`, `ctx.ptcRuntime`, `ctx.systemPrompt` | `tool/call`, `one tool/ptc-dispatch-start + tool/ptc-dispatch pair per bridged sub-call`, `tool/result` | - | The PTC executor exposes only run_code to the model and declares other visible capabilities in a generated SDK in the runtime’s language. Program bindings enter the shared guarded tool pipeline in submission order; concurrency-safe bodies overlap up to maxParallelSubCalls, and nested results remain linked to the outer program. |
|
||||
| `@deepseek-ai/dsh-plan-mode` | `exit_plan_mode` | `ctx.tools`, `ctx.systemPrompt`, `ctx.agents`, `ctx.userQuestions (execution time, opportunistic)` | `tool/call`, `plan/mode inactive on an approved review`, `tool/result` | - | exit_plan_mode stays in the model-facing schema while planning is inactive so transitions add no tool-catalog churn on top of the plan-policy change. Its execute path rejects calls outside plan mode; in plan mode it presents the plan over the user-questions seam (approve / keep planning with feedback), and approval logs plan mode inactive at the step boundary. |
|
||||
@@ -497,6 +498,49 @@ List, create, select, or close a Stagehand browser tab.
|
||||
|
||||
Source: [`packages/experimental/browser-use-stagehand-native/src/index.ts`](../packages/experimental/browser-use-stagehand-native/src/index.ts)
|
||||
|
||||
<a id="deepseek-aidsh-action-cards"></a>
|
||||
|
||||
## `@deepseek-ai/dsh-action-cards`
|
||||
|
||||
### `propose_action`
|
||||
|
||||
Show the user one optional action card under this answer. Call only as the skill that names the action instructs.
|
||||
|
||||
```json
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"action": {
|
||||
"type": "string",
|
||||
"description": "Action name from the skill."
|
||||
},
|
||||
"title": {
|
||||
"type": "string",
|
||||
"description": "Card title."
|
||||
},
|
||||
"brief": {
|
||||
"type": "string",
|
||||
"description": "What the action does, in the user's language."
|
||||
},
|
||||
"details": {
|
||||
"type": "object",
|
||||
"description": "Fields the skill lists for this action.",
|
||||
"additionalProperties": true
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"action",
|
||||
"title",
|
||||
"brief",
|
||||
"details"
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
Source: [`packages/experimental/action-cards/src/index.ts`](../packages/experimental/action-cards/src/index.ts)
|
||||
|
||||
Declared only to an Agent that loaded the skill of a registered card kind; the kind packages register their actions, and the Personalized pages and Plugin recommendations bundles supply the shipped kinds.
|
||||
|
||||
<a id="deepseek-aidsh-tool-ask-user"></a>
|
||||
|
||||
## `@deepseek-ai/dsh-tool-ask-user`
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
| `@deepseek-ai/dsh-plugin-market` | `plugin_market` | `ctx.tools`, `ctx.pluginMarket` | `tool/call`, `tool/result` | - | - |
|
||||
| `@deepseek-ai/dsh-mcp-resources` | `list_mcp_resource_templates`, `list_mcp_resources`, `read_mcp_resource` | `ctx.tools`, `ctx.mcpResources` | `tool/call`, `tool/result` | - | - |
|
||||
| `@deepseek-ai/dsh-experimental-browser-use-stagehand-native` | `stagehand_act`、`stagehand_extract`、`stagehand_navigate`、`stagehand_observe`、`stagehand_screenshot`、`stagehand_tabs` | `ctx.browserUse`、`ctx.agents`、`ctx.tools`、`ctx.systemPrompt` | `tool/call`、`tool/result` | - | - |
|
||||
| `@deepseek-ai/dsh-action-cards` | `propose_action` | `ctx.tools`、`ctx.agents`、`ctx.sessionProjections`、`ctx.remoteAccess` | `tool/call`、`tool/result`、`plugin:action-cards/decision`、`user/message` | - | 只向加载过已注册卡片种类 Skill 的 Agent 声明;各种类的包注册自己的动作,个性化页面和插件推荐两个 Bundle 提供随产品发布的种类。 |
|
||||
| `@deepseek-ai/dsh-tool-ask-user` | `ask_user_question` | `ctx.tools`、`ctx.userQuestions` | `tool/call`、`tool/result after an answer or timeout`、`late user/message` | - | ask_user_question 默认保持原有阻塞行为;设置 `mode: timed` 后才启用前台超时与 pending 结果,同时问题仍可回答;timed 模式内 `timeout: -1` 让本次调用无限期阻塞。 |
|
||||
| `@deepseek-ai/dsh-tool-executor-ptc` | `run_code` | `ctx.workingDirectory (Agent executions)`、`ctx.tools`、`ctx.ptcRuntime`、`ctx.systemPrompt` | `tool/call`、`one tool/ptc-dispatch-start + tool/ptc-dispatch pair per bridged sub-call`、`tool/result` | - | PTC 执行器只向模型公开 run_code,并在运行时语言生成的 SDK 中声明其他可见能力。程序绑定按提交顺序进入共享的受守卫工具流水线;并行安全的函数体最多重叠 maxParallelSubCalls 个,嵌套结果保持与外层程序关联。 |
|
||||
| `@deepseek-ai/dsh-plan-mode` | `exit_plan_mode` | `ctx.tools`、`ctx.systemPrompt`、`ctx.agents`、`ctx.userQuestions (execution time, opportunistic)` | `tool/call`、`plan/mode inactive on an approved review`、`tool/result` | - | 规划未激活时,exit_plan_mode 仍保留在面向模型的 schema 中,这样状态转换不会在规划策略变更之外额外造成工具目录变动。其执行路径会拒绝规划模式之外的调用;在规划模式下,它通过用户交互 seam 提交计划(批准/根据反馈继续规划),批准后会在步骤边界记录规划模式已停用。 |
|
||||
@@ -501,6 +502,49 @@
|
||||
|
||||
来源:[`packages/experimental/browser-use-stagehand-native/src/index.ts`](../packages/experimental/browser-use-stagehand-native/src/index.ts)
|
||||
|
||||
<a id="deepseek-aidsh-action-cards"></a>
|
||||
|
||||
## `@deepseek-ai/dsh-action-cards`
|
||||
|
||||
### `propose_action`
|
||||
|
||||
在本次回答下方向用户展示一张可选操作卡片。只按指定该操作的 Skill 的要求调用。
|
||||
|
||||
```json
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"action": {
|
||||
"type": "string",
|
||||
"description": "Action name from the skill."
|
||||
},
|
||||
"title": {
|
||||
"type": "string",
|
||||
"description": "Card title."
|
||||
},
|
||||
"brief": {
|
||||
"type": "string",
|
||||
"description": "What the action does, in the user's language."
|
||||
},
|
||||
"details": {
|
||||
"type": "object",
|
||||
"description": "Fields the skill lists for this action.",
|
||||
"additionalProperties": true
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"action",
|
||||
"title",
|
||||
"brief",
|
||||
"details"
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
来源:[`packages/experimental/action-cards/src/index.ts`](../packages/experimental/action-cards/src/index.ts)
|
||||
|
||||
只向加载过已注册卡片种类 Skill 的 Agent 声明;各种类的包注册自己的动作,个性化页面和插件推荐两个 Bundle 提供随产品发布的种类。
|
||||
|
||||
<a id="deepseek-aidsh-tool-ask-user"></a>
|
||||
|
||||
## `@deepseek-ai/dsh-tool-ask-user`
|
||||
|
||||
+2
-1
@@ -300,6 +300,7 @@
|
||||
"@deepseek-ai/dsh-cua-bundle": "workspace:*",
|
||||
"@deepseek-ai/dsh-experimental-subagent-oar": "workspace:*",
|
||||
"@deepseek-ai/dsh-experimental-tool-subagent-oar": "workspace:*",
|
||||
"@deepseek-ai/dsh-experimental-cua-macos": "workspace:*"
|
||||
"@deepseek-ai/dsh-experimental-cua-macos": "workspace:*",
|
||||
"@deepseek-ai/dsh-action-cards": "workspace:*"
|
||||
}
|
||||
}
|
||||
@@ -15,8 +15,8 @@
|
||||
en: ffc55792d6e922e1
|
||||
zh: 83bd759638857e2d
|
||||
/packages/package-groups:
|
||||
en: d67996086e3b4f28
|
||||
zh: cb758b1fcee5ab3e
|
||||
en: c397fc0c1885058a
|
||||
zh: c720d0e91dd1d15e
|
||||
/packages/release-expectations:
|
||||
en: 236081c1659b25ab
|
||||
zh: 809110adf003802e
|
||||
|
||||
+2
-2
@@ -75,11 +75,11 @@ Every package lives in exactly one group; new packages join existing groups, and
|
||||
| [`sdk/`](sdk/README.md) | Out-of-process SDK: JSON-RPC protocol and TypeScript client/server |
|
||||
| [`acp/`](acp/README.md) | Automation-only Agent Client Protocol server |
|
||||
| [`interaction/`](interaction/README.md) | Human-collaboration plane: approval/interaction seams, permission preset, commands, ask-user tool |
|
||||
| [`boot/`](boot/README.md) | Shared app-bin boot glue and installation bundle lists |
|
||||
| [`boot/`](boot/README.md) | Shared app-bin boot glue |
|
||||
| [`host/`](host/README.md) | Web GUI host services, directory picking, application launch, plugin inventory, and product telemetry |
|
||||
| [`client/`](client/README.md) | Web-GUI browser half: shell, wire, object services, slots, `ui-*` plugins |
|
||||
| [`test-support/`](test-support/README.md) | Test infrastructure (testkits, replay, Loader smokes) |
|
||||
| [`util/`](util/README.md) | Low-level zero-dependency utilities shared across groups (`Branded<B>`, home/path helpers, timeout, retention) |
|
||||
| [`util/`](util/README.md) | Low-level utilities and data-only package lists shared across groups (`Branded<B>`, home/path helpers, timeout, retention, official bundle lists) |
|
||||
|
||||
-----
|
||||
|
||||
|
||||
@@ -75,11 +75,11 @@ harness 由 `packages/` 下的 npm 包组装而成,按能力系列分组:会
|
||||
| [`sdk/`](sdk/README.zh.md) | 进程外 SDK:JSON-RPC 协议与 TypeScript 客户端/服务器 |
|
||||
| [`acp/`](acp/README.zh.md) | 仅面向自动化的 ACP(Agent Client Protocol)服务器 |
|
||||
| [`interaction/`](interaction/README.zh.md) | 人机协作平面:批准/交互 seam、权限预设、命令、询问用户的工具 |
|
||||
| [`boot/`](boot/README.zh.md) | 共享的 app bin 启动粘合层与安装方组合包列表 |
|
||||
| [`boot/`](boot/README.zh.md) | 共享的 app bin 启动粘合层 |
|
||||
| [`host/`](host/README.zh.md) | Web GUI 宿主服务、目录选择、应用启动、插件清单和产品遥测 |
|
||||
| [`client/`](client/README.zh.md) | web GUI 浏览器半侧:shell、协议层、对象服务、slot、`ui-*` 插件 |
|
||||
| [`test-support/`](test-support/README.zh.md) | 测试基础设施(testkit、回放、Loader 冒烟测试) |
|
||||
| [`util/`](util/README.zh.md) | 组间共享的低层零依赖工具(`Branded<B>`、home/路径辅助函数、超时、留存) |
|
||||
| [`util/`](util/README.zh.md) | 组间共享的低层工具与纯数据包列表(`Branded<B>`、home/路径辅助函数、超时、留存、官方组合包列表) |
|
||||
|
||||
-----
|
||||
|
||||
|
||||
@@ -100,7 +100,7 @@ function AddPluginMenu({ t, disabled, openInstall, renderSlot }: {
|
||||
const HIGHLIGHT_MS = 2_400
|
||||
|
||||
/**
|
||||
* Whether the main list shows an official optional bundle: the always-held ones, and any held-back one the profile enabled.
|
||||
* Whether the main list shows an official optional bundle: any bundle outside `MORE_BUNDLES`, and any held-back one the profile enabled.
|
||||
* @param pkg - the official bundle as the Host reports it.
|
||||
* @returns whether the main list shows it.
|
||||
*/
|
||||
@@ -109,14 +109,14 @@ function pinnedToMainList(pkg: PackageView): boolean {
|
||||
}
|
||||
|
||||
/**
|
||||
* Where an optional bundle sits on both lists: the always-held ones in their order, then the bundles neither list
|
||||
* Where an optional bundle sits on both lists: the `EXTENSION_BUNDLES` in their order, then the bundles neither list
|
||||
* ranks, then the held-back ones in theirs, so Codex and Claude Code stay last on the More list.
|
||||
* @param name - the bundle's package name.
|
||||
* @returns the rank; bundles of equal rank keep the order the Host reported.
|
||||
*/
|
||||
function optionalBundleRank(name: string): number {
|
||||
const alwaysHeld = EXTENSION_BUNDLES.indexOf(name)
|
||||
if (alwaysHeld >= 0) return alwaysHeld
|
||||
const ranked = EXTENSION_BUNDLES.indexOf(name)
|
||||
if (ranked >= 0) return ranked
|
||||
const heldBack = MORE_BUNDLES.indexOf(name)
|
||||
return heldBack < 0 ? EXTENSION_BUNDLES.length : EXTENSION_BUNDLES.length + 1 + heldBack
|
||||
}
|
||||
|
||||
@@ -1237,8 +1237,11 @@ describe('PluginManagerPage', () => {
|
||||
expect(document.querySelector(`[data-plugin-package="${name}"]`)).toBeTruthy()
|
||||
})
|
||||
|
||||
it('returns from package details to the secondary page and retains it across React remounts', () => {
|
||||
const name = '@deepseek-ai/dsh-experimental-session-titles-bundle'
|
||||
it.each([
|
||||
'@deepseek-ai/dsh-experimental-session-titles-bundle',
|
||||
'@deepseek-ai/dsh-creation-recommendations',
|
||||
'@deepseek-ai/dsh-plugin-recommendations',
|
||||
])('returns %s details to the secondary page and retains it across React remounts', (name) => {
|
||||
const b = renderTab({ packages: [pkg({ name, official: true, enabled: false })] })
|
||||
fireEvent.click(screen.getByRole('button', { name: en.moreAction }))
|
||||
expect(screen.getByRole('heading', { name: en.moreTitle, level: 1 })).toBeTruthy()
|
||||
@@ -1253,9 +1256,12 @@ describe('PluginManagerPage', () => {
|
||||
expect(document.querySelector(`[data-plugin-package="${name}"]`)).toBeNull()
|
||||
})
|
||||
|
||||
it('pins a bundle the profile picks onto the main list, in its full-list place', () => {
|
||||
it.each([
|
||||
'@deepseek-ai/dsh-experimental-tool-worktree',
|
||||
'@deepseek-ai/dsh-creation-recommendations',
|
||||
'@deepseek-ai/dsh-plugin-recommendations',
|
||||
])('pins enabled %s onto the main list and removes it when disabled', (first) => {
|
||||
const team = '@deepseek-ai/dsh-experimental-agent-team-profile'
|
||||
const first = '@deepseek-ai/dsh-experimental-tool-worktree'
|
||||
const second = '@deepseek-ai/dsh-experimental-cot-translation-bundle'
|
||||
const entry = (name: string, enabled: boolean): PackageView => pkg({ name, official: true, enabled })
|
||||
const b = renderTab({ packages: [entry(second, true), entry(team, true), entry(first, false)] })
|
||||
|
||||
@@ -54,8 +54,8 @@
|
||||
en: ca75c51c89c2c9b0
|
||||
zh: de54f3467ef3b9be
|
||||
/deepseek-ai-dsh-client-ui-primitives/known-limitations-and-deferred-work:
|
||||
en: 5a1e9d041b556b0e
|
||||
zh: c66b4e7d5f77162d
|
||||
en: 9c5bc17e35af9d0b
|
||||
zh: 4f1a142c7d56cf72
|
||||
/deepseek-ai-dsh-client-ui-primitives/known-limitations-and-deferred-work/dev-note:
|
||||
en: e67f633dc6fe7773
|
||||
zh: 3bb0c20c93f16f98
|
||||
@@ -220,6 +220,7 @@ These limits define how the atoms behave at the edges; they are current package
|
||||
- **Streaming defers cross-boundary reference resolution** — a reference-style link or footnote whose definition sits on the other side of the incremental freeze boundary renders as literal text while the reply streams; the settled full parse at finalize resolves it.
|
||||
- **A long highlighted fence retains its complete token DOM** — streaming avoids re-parsing, re-tokenizing, and reconciling the completed prefix, but it does not discard old colors or virtualize token spans. Final DOM cardinality therefore still follows the fence's token count; nested/container fences and a pathological single long line remain on the general tail path.
|
||||
- **Overlong lines stay uncolored** — a source line of 1,000 or more UTF-16 units renders as one plain run in every highlighted surface, because TextMate scanning cost grows superlinearly with line length and a single generated line can otherwise block the page for seconds. The grammar state skips that line, so a comment or template literal that opens or closes on it mis-colors the following lines. Highlighting still runs synchronously during render, so a file with thousands of ordinary lines costs proportionally more.
|
||||
- **The Go struct-field rule is patched locally** — when the Go grammar loads, its repeated one-line struct-field rule is replaced with the rule [worlpaker/go-syntax#25](https://github.com/worlpaker/go-syntax/pull/25) merged, because the vendored rule backtracks exponentially on lines such as a brace-bearing comment after `struct {`. If a dependency upgrade removes that rule, loading the grammar throws and Go code renders as plain text; delete the patch once `@shikijs/langs` ships the upstream rule.
|
||||
- **The fish logo is a redrawn approximation** — its font glyph has no exportable vector geometry in the local design data, so a hand-authored recreation stands in until an exact export path exists.
|
||||
- **`Pill` and `Input` have no design source** — both atoms are self-defined; the sidebar search field and view-tab strip that resemble them are consumer-owned compositions, not these atoms.
|
||||
- **Product icons need the ui-theme sprite** — each icon only references its symbol, so without ui-theme, or inside another document such as an iframe, the icon renders nothing.
|
||||
|
||||
@@ -220,6 +220,7 @@ kind: "package-library"
|
||||
- **流式期间跨边界引用解析被推迟**:定义落在增量冻结边界另一侧的引用式链接或脚注,在回复流式输出期间渲染为字面文本;定稿时的全量解析会将其解析。
|
||||
- **长高亮 fence 会保留完整 token DOM**:流式路径避免重新解析、重新 tokenize 和 reconcile 已完成前缀,但不会丢弃旧颜色或虚拟化 token span。因此最终 DOM 数量仍随 fence 的 token 数增长;嵌套/容器内 fence 与病态的单个超长行仍走通用尾部路径。
|
||||
- **超长行不着色**:所有高亮界面中,长度达到 1,000 个 UTF-16 单元的源码行渲染为一段纯文本,因为 TextMate 扫描成本随行长超线性增长,单个生成行否则会阻塞页面数秒。语法状态会跳过该行,因此在该行开始或结束的注释、模板字符串会使后续行着色错误。高亮仍在渲染期间同步执行,因此数千个普通行的文件仍按比例增加开销。
|
||||
- **Go 结构体字段规则在本地打了补丁**:Go 语法加载时,重复匹配单行结构体字段的规则会替换为 [worlpaker/go-syntax#25](https://github.com/worlpaker/go-syntax/pull/25) 合入的规则,因为内置规则在 `struct {` 之后含花括号注释等行上会指数级回溯。若依赖升级后该规则消失,加载语法会抛错,Go 代码以纯文本显示;`@shikijs/langs` 发布上游规则后删除此补丁。
|
||||
- **鱼形标志是重新绘制的近似版本**:它来自字体字形,而本地设计数据无法导出其矢量几何;在获得精确导出路径前,使用手工重建版本代替。
|
||||
- **`Pill` 与 `Input` 没有设计来源**:两个原子组件均自行定义;与其相似的侧边栏搜索字段和视图标签条由消费方组合,不是这些原子组件。
|
||||
- **产品图标依赖 ui-theme 的 sprite**:每个图标只引用自己的 symbol,因此没有 ui-theme 时,或在 iframe 等另一个文档中,图标不渲染任何内容。
|
||||
|
||||
@@ -41,6 +41,39 @@ type LangModule = { default: typeof langTs }
|
||||
*/
|
||||
const LANGS = [langTs, langBash, langJson]
|
||||
|
||||
/**
|
||||
* Replace the Go grammar's repeated one-line struct-field rule with the rule
|
||||
* worlpaker/go-syntax merged in 4a9b120a52c (https://github.com/worlpaker/go-syntax/pull/25):
|
||||
* the repeated rule backtracks exponentially on lines such as a brace-bearing
|
||||
* comment after `struct {`. Delete this patch once `@shikijs/langs` ships that
|
||||
* commit; 4.5.0 does not. The rule is located as the only rule in
|
||||
* `struct_variables_types_fields` containing the field-token literal below,
|
||||
* taken from `@shikijs/langs` 4.4.3.
|
||||
* @param grammars - the `@shikijs/langs/go` default export, left unmodified.
|
||||
* @returns copies of `grammars` with that rule's match replaced in the `go` grammar.
|
||||
* @throws When the module has no `go` grammar, the grammar lacks
|
||||
* `struct_variables_types_fields`, or that entry has no or several such rules.
|
||||
* The lazy load then rejects unhandled and Go code renders as plain text.
|
||||
*/
|
||||
export function patchGoGrammar(grammars: LangModule['default']): LangModule['default'] {
|
||||
const go = grammars.find(grammar => grammar.name === 'go')
|
||||
const fields = go?.repository.struct_variables_types_fields
|
||||
const patterns = fields?.patterns ?? []
|
||||
const rules = patterns.filter(rule => typeof rule.match === 'string' && rule.match.includes('[^"/`\\s]+;?'))
|
||||
if (go === undefined || fields === undefined || rules.length !== 1) {
|
||||
throw new Error(`ui-primitives: expected exactly one Go struct-field rule to patch for worlpaker/go-syntax#25, found ${
|
||||
rules.length}; update or delete the patch`)
|
||||
}
|
||||
const repository = { ...go.repository }
|
||||
repository.struct_variables_types_fields = {
|
||||
...fields,
|
||||
patterns: patterns.map(rule => rule === rules[0]
|
||||
? { ...rule, match: '(?:(?<=\\{)([^/\\`"]*[^\\s/\\`"])\\s*(?=\\}))' }
|
||||
: rule),
|
||||
}
|
||||
return grammars.map(grammar => grammar === go ? { ...go, repository } : grammar)
|
||||
}
|
||||
|
||||
/**
|
||||
* The non-boot extension grammars, each behind a dynamic import so its module
|
||||
* stays out of the boot chunk until a code surface renders that language.
|
||||
@@ -53,7 +86,7 @@ const LANGS = [langTs, langBash, langJson]
|
||||
const LAZY_GRAMMARS = new Map<string, () => Promise<LangModule>>([
|
||||
['python', () => import('@shikijs/langs/python')],
|
||||
['ruby', () => import('@shikijs/langs/ruby')],
|
||||
['go', () => import('@shikijs/langs/go')],
|
||||
['go', async () => ({ default: patchGoGrammar((await import('@shikijs/langs/go')).default) })],
|
||||
['rust', () => import('@shikijs/langs/rust')],
|
||||
['java', () => import('@shikijs/langs/java')],
|
||||
['c', () => import('@shikijs/langs/c')],
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
/** Go regex matching runs in a terminable source-mode worker, not on the test runner's event loop. */
|
||||
import { Worker } from 'node:worker_threads'
|
||||
import { expect, it } from 'vitest'
|
||||
import { patchGoGrammar } from '../src/markdown/highlight.ts'
|
||||
import { GO_SOURCE } from './go-source.ts'
|
||||
|
||||
it('highlights struct comments with braces without blocking settled or streaming code', async () => {
|
||||
// The worker and highlight.ts use erasable syntax and only package-name imports, so Node loads them directly.
|
||||
const worker = new Worker(new URL('./go-highlighting.worker.ts', import.meta.url))
|
||||
let timer: ReturnType<typeof setTimeout> | undefined
|
||||
try {
|
||||
const result = await new Promise<unknown>((resolve, reject) => {
|
||||
const fail = (message: string): void => { reject(new Error(message)) }
|
||||
timer = setTimeout(() => { fail('Go grammar did not load within 120 seconds') }, 120_000)
|
||||
worker.on('message', (reply: unknown) => {
|
||||
if (reply !== 'loaded') {
|
||||
resolve(reply)
|
||||
return
|
||||
}
|
||||
clearTimeout(timer)
|
||||
// Bound runaway synchronous matching once imports and grammar loading are done.
|
||||
timer = setTimeout(() => { fail('Go highlighting did not complete within 10 seconds') }, 10_000)
|
||||
})
|
||||
worker.once('error', reject)
|
||||
worker.once('exit', (code) => { fail(`Go highlighting worker exited before its reply: ${code}`) })
|
||||
})
|
||||
expect(result).toMatchObject({ text: GO_SOURCE, streamingMatchesSettled: true })
|
||||
expect(result).toHaveProperty('html', expect.stringContaining('var(--shiki-'))
|
||||
const keyword = (...texts: string[]): string[] => texts.map(text => `${text}:keyword`)
|
||||
expect(result).toHaveProperty('colored', [
|
||||
['package:keyword', 'example:function'],
|
||||
[],
|
||||
['type:keyword', 'Record:function', 'struct:keyword'],
|
||||
['// docs: {id} explains the ordinary field names for an example record ending here:comment'],
|
||||
['int:keyword'],
|
||||
[],
|
||||
[],
|
||||
['type:keyword', 'Inline:function', ...keyword('struct', 'string', 'int')],
|
||||
['type:keyword', 'Nested:function', ...keyword('struct', 'map', 'string', 'struct', 'struct', 'int')],
|
||||
['type:keyword', 'OneLineFields:function', ...keyword('struct', 'int', 'chan<-', 'struct', 'string'),
|
||||
'sync:function', 'Mutex:function'],
|
||||
['type:keyword', 'SplitOneLine:function', ...keyword('struct', 'int'), 'B:function', 'string:keyword'],
|
||||
[],
|
||||
[...keyword('var', '=', 'struct', 'string'), 'Port:function', 'int:keyword', 'Tags:function', 'string:keyword'],
|
||||
[],
|
||||
['type:keyword', 'Many:function', ...keyword('struct', ...Array<string>(24).fill('int'), 'struct', 'int')],
|
||||
['type:keyword', 'Open:function', 'struct:keyword', ...Array<string>(47).fill('field:function')],
|
||||
])
|
||||
} finally {
|
||||
clearTimeout(timer)
|
||||
await worker.terminate()
|
||||
}
|
||||
}, 150_000)
|
||||
|
||||
it('patches exactly the vendored struct-field rule and rejects a grammar without it', async () => {
|
||||
const { default: grammars } = await import('@shikijs/langs/go')
|
||||
const other = { name: 'go-embedded', scopeName: 'source.go.embedded', patterns: [], repository: {} }
|
||||
const before = grammars[0]?.repository.struct_variables_types_fields?.patterns
|
||||
const patched = patchGoGrammar([...grammars, other])
|
||||
const after = patched[0]?.repository.struct_variables_types_fields?.patterns
|
||||
const changed = after?.flatMap((rule, index) => rule === before?.[index] ? [] : [[before?.[index]?.match, rule.match]])
|
||||
expect(changed).toEqual([[
|
||||
expect.stringContaining('[^"/`\\s]+;?'),
|
||||
'(?:(?<=\\{)([^/\\`"]*[^\\s/\\`"])\\s*(?=\\}))',
|
||||
]])
|
||||
expect(patched[1]).toBe(other)
|
||||
for (const repository of [{}, { struct_variables_types_fields: {} }]) {
|
||||
expect(() => patchGoGrammar([{ name: 'go', scopeName: 'source.go', patterns: [], repository }]))
|
||||
.toThrow('expected exactly one Go struct-field rule to patch for worlpaker/go-syntax#25, found 0')
|
||||
}
|
||||
expect(() => patchGoGrammar([other])).toThrow('found 0')
|
||||
})
|
||||
@@ -0,0 +1,31 @@
|
||||
/** Source-mode highlighter fixture; the parent owns termination during synchronous regex matching. */
|
||||
import { parentPort } from 'node:worker_threads'
|
||||
import {
|
||||
highlightLines, highlightToHtml, StreamingHighlightSession, subscribeGrammarLoaded,
|
||||
} from '../src/markdown/highlight.ts'
|
||||
import { GO_SOURCE } from './go-source.ts'
|
||||
|
||||
const ready = Promise.withResolvers<undefined>()
|
||||
const dispose = subscribeGrammarLoaded(() => {
|
||||
if (highlightLines('package example', 'go') !== undefined) ready.resolve(undefined)
|
||||
})
|
||||
try {
|
||||
if (highlightLines('package example', 'go') === undefined) await ready.promise
|
||||
} finally {
|
||||
dispose()
|
||||
}
|
||||
// The parent times matching separately from imports and grammar loading.
|
||||
parentPort?.postMessage('loaded')
|
||||
const lines = highlightLines(GO_SOURCE, 'go')
|
||||
const stream = new StreamingHighlightSession()
|
||||
const split = GO_SOURCE.indexOf('\t//')
|
||||
if (split <= 0) throw new Error('GO_SOURCE no longer contains the brace-bearing struct comment')
|
||||
stream.update(GO_SOURCE.slice(0, split), 'go')
|
||||
const streamed = stream.update(GO_SOURCE, 'go')
|
||||
parentPort?.postMessage({
|
||||
text: lines?.map(line => line.map(span => span.text).join('')).join('\n'),
|
||||
colored: lines?.map(line => line.flatMap(span =>
|
||||
span.style.color === 'var(--shiki-foreground)' ? [] : [`${span.text}:${String(span.style.color).replace('var(--shiki-token-', '').replace(')', '')}`])),
|
||||
streamingMatchesSettled: JSON.stringify(streamed) === JSON.stringify(new StreamingHighlightSession().update(GO_SOURCE, 'go')),
|
||||
html: highlightToHtml(GO_SOURCE, 'go'),
|
||||
})
|
||||
@@ -0,0 +1,21 @@
|
||||
/** Synthetic Go struct comments and declarations for syntax-highlighting regressions. */
|
||||
export const GO_SOURCE = [
|
||||
'package example',
|
||||
'',
|
||||
'type Record struct {',
|
||||
'\t// docs: {id} explains the ordinary field names for an example record ending here',
|
||||
'\tValue int',
|
||||
'}',
|
||||
'',
|
||||
'type Inline struct { Name string; Count int }',
|
||||
'type Nested struct { Flags map[string]struct{}; Child struct { Value int } }',
|
||||
// Shapes from worlpaker/go-syntax#25's test/semantic_tokens.go and test/stress.go.
|
||||
'type OneLineFields struct{ A, B int; C chan<- struct{}; D []string; sync.Mutex }',
|
||||
'type SplitOneLine struct { A int; B string',
|
||||
'}',
|
||||
'var stressFoo14 = struct{ Host string; Port int; Tags []string',
|
||||
'}{}',
|
||||
`type Many struct { ${Array.from({ length: 24 }, (_, index) => `F${index} int;`).join(' ')} Child struct { X int } }`,
|
||||
// Last: its unclosed brace keeps the struct body open to the end of the source.
|
||||
`type Open struct { ${'field '.repeat(48)}`,
|
||||
].join('\n')
|
||||
@@ -31,7 +31,7 @@ describe('gen-tool-catalog collectToolCatalog', () => {
|
||||
'create_goal', 'create_worktree', 'edit', 'exit_plan_mode', 'get_goal', 'glob', 'grep',
|
||||
'interrupt_agent', 'interrupt_agent', 'job_kill', 'job_list', 'job_output',
|
||||
'list_agents', 'list_agents', 'list_mcp_resource_templates', 'list_mcp_resources',
|
||||
'list_subagent_models', 'load_workspace_dependencies', 'lsp', 'plugin_manager', 'plugin_market', 'present', 'pwsh', 'pwsh', 'ralph',
|
||||
'list_subagent_models', 'load_workspace_dependencies', 'lsp', 'plugin_manager', 'plugin_market', 'present', 'propose_action', 'pwsh', 'pwsh', 'ralph',
|
||||
'read', 'read_image', 'read_mcp_resource', 'run_code', 'schedule_create', 'schedule_delete',
|
||||
'schedule_list', 'schedule_update', 'send_message', 'send_message', 'session_event_read', 'session_event_search',
|
||||
'session_event_trace', 'session_search', 'session_trace', 'skill', 'spawn_teammate',
|
||||
|
||||
@@ -18,8 +18,8 @@
|
||||
en: b55aeb927737b90d
|
||||
zh: 0b215fcb5c2c7908
|
||||
/packages-experimental/packages:
|
||||
en: 9fd1c2ac5ede5d47
|
||||
zh: 9e8fc6c374b6f5e9
|
||||
en: 4d32c0a6c009a2ca
|
||||
zh: 47bf9acd64100263
|
||||
/packages-experimental/related-documentation:
|
||||
en: 1cb9d3448d44e48d
|
||||
zh: cd326d70a746b896
|
||||
|
||||
@@ -36,6 +36,12 @@ Promotion requires a named product role, documented public behavior and limitati
|
||||
|
||||
| Package | Role | ctx key |
|
||||
|---|---|---|
|
||||
| [`action-cards`](action-cards/README.md) | Optional action cards below answers: the proposal tool, card state, user actions and status notices | `ctx.actionCards` |
|
||||
| [`client-ui-action-cards`](client-ui-action-cards/README.md) | Card frame below completed answers, kind bodies and the proposal process row | — |
|
||||
| [`creation-recommendations`](creation-recommendations/README.md) | Explicit-need creation of persistent removable interface plugins | — |
|
||||
| [`client-ui-creation-recommendations`](client-ui-creation-recommendations/README.md) | Personalized page card body with location selection and undo | — |
|
||||
| [`plugin-recommendations`](plugin-recommendations/README.md) | Explicit-need official plugin recommendations in conversations | `ctx.pluginRecommendations` |
|
||||
| [`client-ui-plugin-recommendations`](client-ui-plugin-recommendations/README.md) | Official plugin card body with catalog text and enabling | — |
|
||||
| [`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 global session search tools | — |
|
||||
| [`ralph-bundle`](ralph-bundle/README.md) | Optional repeated delegation with an isolated workflow engine | — |
|
||||
|
||||
@@ -36,6 +36,12 @@ kind: "package-group"
|
||||
|
||||
| 包 | 职责 | ctx 键 |
|
||||
|---|---|---|
|
||||
| [`action-cards`](action-cards/README.zh.md) | 回答下方的可选操作卡片:提议工具、卡片状态、用户操作与状态通知 | `ctx.actionCards` |
|
||||
| [`client-ui-action-cards`](client-ui-action-cards/README.zh.md) | 已完成回答下方的卡片框架、种类正文与提议过程行 | — |
|
||||
| [`creation-recommendations`](creation-recommendations/README.zh.md) | 针对明确需求创建持续可用、可移除的界面插件 | — |
|
||||
| [`client-ui-creation-recommendations`](client-ui-creation-recommendations/README.zh.md) | 个性化页面卡片正文、位置选择和撤销 | — |
|
||||
| [`plugin-recommendations`](plugin-recommendations/README.zh.md) | 在对话中针对明确需求推荐官方插件 | `ctx.pluginRecommendations` |
|
||||
| [`client-ui-plugin-recommendations`](client-ui-plugin-recommendations/README.zh.md) | 官方插件卡片正文:目录文本与启用 | — |
|
||||
| [`tool-session-query`](tool-session-query/README.zh.md) | 按工作区授权的模型会话搜索、追踪与事件读取 | — |
|
||||
| [`session-search`](session-search/README.zh.md) | 可选实验性全局会话搜索工具 | — |
|
||||
| [`ralph-bundle`](ralph-bundle/README.zh.md) | 带隔离 workflow 引擎的可选重复委派 | — |
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
# 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/action-cards/README.md
|
||||
/:
|
||||
en: 1a68a7a733a2676d
|
||||
zh: 01f72eb61a0626b7
|
||||
/deepseek-ai-dsh-action-cards:
|
||||
en: 63bf9077e164f6fe
|
||||
zh: 8b696bb8c3d6fcd4
|
||||
/deepseek-ai-dsh-action-cards/summary:
|
||||
en: 7621088773d073f4
|
||||
zh: 57674e6dcee15997
|
||||
/deepseek-ai-dsh-action-cards/table-of-contents:
|
||||
en: d152484eb41ac6b4
|
||||
zh: b00dddf4c88f0a45
|
||||
/deepseek-ai-dsh-action-cards/use-this-package:
|
||||
en: 4e3a256d5aa6d29b
|
||||
zh: b89ffa23ebb49e7e
|
||||
/deepseek-ai-dsh-action-cards/use-this-package/register-a-card-kind:
|
||||
en: 8432c02ef18eda11
|
||||
zh: 6d43a0a32edd7e30
|
||||
/deepseek-ai-dsh-action-cards/use-this-package/card-rules:
|
||||
en: 2f5b3ccb91f3b30e
|
||||
zh: 9bd877d9d92615da
|
||||
/deepseek-ai-dsh-action-cards/understand-the-implementation:
|
||||
en: d92243d71d2106c1
|
||||
zh: 47f0840fa723bb31
|
||||
/deepseek-ai-dsh-action-cards/further-exploration:
|
||||
en: 1966ab8d7063c450
|
||||
zh: 033c2c0d258a257f
|
||||
/deepseek-ai-dsh-action-cards/model-experience:
|
||||
en: 215e7ba838619b7b
|
||||
zh: a311da3843709f90
|
||||
/deepseek-ai-dsh-action-cards/model-experience/card-tool:
|
||||
en: 4925bc5f7153825a
|
||||
zh: 3a7bfb2210d9c6aa
|
||||
/deepseek-ai-dsh-action-cards/model-experience/card-tool/what-the-model-sees:
|
||||
en: 58521d3992ce42ec
|
||||
zh: 45681f7b43e67613
|
||||
/deepseek-ai-dsh-action-cards/model-experience/card-tool/token-effect:
|
||||
en: 7efaaad09be98a07
|
||||
zh: 86c7fa13d60c3588
|
||||
/deepseek-ai-dsh-action-cards/model-experience/card-tool/kv-cache-effect:
|
||||
en: d4192e35d47b5fa3
|
||||
zh: c786828e123de657
|
||||
/deepseek-ai-dsh-action-cards/model-experience/card-status-notice:
|
||||
en: 407ebca5eb94992e
|
||||
zh: 779819ea83974103
|
||||
/deepseek-ai-dsh-action-cards/model-experience/card-status-notice/what-the-model-sees:
|
||||
en: a14013ca3ddb5ee3
|
||||
zh: 18cd7ffc62fd6590
|
||||
/deepseek-ai-dsh-action-cards/model-experience/card-status-notice/what-the-model-sees/notice-preamble:
|
||||
en: 04dd9469bfaff052
|
||||
zh: 35110b231b8e3928
|
||||
/deepseek-ai-dsh-action-cards/model-experience/card-status-notice/token-effect:
|
||||
en: 4e73a2cff60b5e88
|
||||
zh: 4887212815e7425d
|
||||
/deepseek-ai-dsh-action-cards/model-experience/card-status-notice/kv-cache-effect:
|
||||
en: 58785543e2428dba
|
||||
zh: 4b082f77b3b2f482
|
||||
/deepseek-ai-dsh-action-cards/known-limitations-and-deferred-work:
|
||||
en: 163aa0c2a6b7e3f8
|
||||
zh: 26cdcae33579114a
|
||||
/deepseek-ai-dsh-action-cards/known-limitations-and-deferred-work/dev-note:
|
||||
en: e67f633dc6fe7773
|
||||
zh: bd8a8936229e035e
|
||||
@@ -0,0 +1,138 @@
|
||||
---
|
||||
description: "Shared Host service of optional action cards: the propose_action tool, card state, user actions and status notices that experiment packages register card kinds into."
|
||||
kind: "package-reference"
|
||||
---
|
||||
|
||||
# @deepseek-ai/dsh-action-cards
|
||||
|
||||
English | [中文](README.zh.md)
|
||||
|
||||
## Summary
|
||||
|
||||
An experiment can offer one optional action below an answer, such as creating a page, without adding a tool of its own. The model loads the experiment's skill, then calls `propose_action`; the card appears after the turn ends, and nothing runs until the user acts on it. Each choice is recorded and reported to the model on its next request. The tool costs nothing until a card skill loads in the conversation.
|
||||
|
||||
## 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
|
||||
|
||||
The [Personalized pages](../creation-recommendations/README.md) and [Plugin recommendations](../plugin-recommendations/README.md) bundles each insert this service and its [browser half](../client-ui-action-cards/README.md); enabling either bundle enables both. The service has one configuration field:
|
||||
|
||||
| Field | Default | Meaning |
|
||||
|---|---|---|
|
||||
| `queuedMessageLimit` | `2` | Queued next-turn user messages at or above which `propose_action` refuses the call, so no card is offered. |
|
||||
|
||||
The generated [configuration catalog](../../../docs/config-catalog.md#deepseek-aidsh-action-cards) is the exhaustive source for accepted fields.
|
||||
|
||||
### Register a card kind
|
||||
|
||||
A kind package injects `actionCards` and calls `ctx.actionCards.register(kind)` from its own plugin; unloading that plugin removes the kind, and actions on its cards are then refused as unavailable, except that Not now still dismisses an unstarted card. The kind names its action, the skill that proposes it, the closing invitation guidance that an accepted call's result gives the model, a zod schema for the card's `details`, the user actions it accepts and the shared checks each needs (`global` Remote access, `writes` refused in a read-only Session), the recorded phases that still offer dismissal, optional status guidance, the decision data fields the status notice reports, an optional `reconcile` that updates the card's recorded decision from state outside the Session before every action, and the handler for every action except `dismiss`. The handler records each new decision with `ctx.actionCards.record()`, which refuses an action no kind registered and the derived `replaced` phase, and returns `accepted`, `settled` with the decision in effect, `refused` or `unconfirmed`.
|
||||
|
||||
### Card rules
|
||||
|
||||
- The first accepted `propose_action` call of a turn becomes the card. The tool refuses a second call in the same turn, an unregistered action, a call whose kind skill was not loaded in the current turn, a blank title or brief, details that fail the kind schema, calls dispatched from code, calls from a subagent, and any call while `queuedMessageLimit` or more user messages wait for later turns.
|
||||
- A newer card of any kind replaces every unstarted earlier card. Replacement is derived from the log and never recorded.
|
||||
- Events a forked Session inherits create no cards.
|
||||
- Before every action, including Not now, the kind's `reconcile` updates the card from state outside the Session. Not now is then recorded for an unstarted card and for the phases the kind lists; dismissed and replaced cards accept no further action. Without its registered kind, Not now still dismisses an unstarted card, and every other action is refused as unavailable.
|
||||
- Concurrent actions on one card share one operation. Actions require the card's live root Agent.
|
||||
|
||||
-----
|
||||
|
||||
<a id="understand-the-implementation"></a>
|
||||
## Understand the implementation
|
||||
|
||||
<details>
|
||||
<summary>Implementation internals — click to expand</summary>
|
||||
|
||||
The package default-exports the `actionCards` Remote service. It registers `propose_action` once, globally, with a `when` condition: a live root Agent becomes eligible when its own direct `skill` call loads the skill of a registered kind, while loads by subagents or from code are ignored. The flag lives in memory until the Agent is disposed. The call's `execute` checks the live root, the queued messages the projection counts against `queuedMessageLimit` and the current turn's skill loads through the turn boundary, and keeps an in-memory mark of the turn's accepted call; the logged `tool/call` and its successful `tool/result` are the durable proposal.
|
||||
|
||||
The `actionCards` Session projection (state version 2) pairs each `propose_action` call with its successful result, records decisions from `plugin:action-cards/decision`, counts queued next-turn messages from inbox splices for the tool's limit, and keeps unreported decisions until a status notice whose `through` covers them enters the log. Its Client view `{ proposals, decisions }` is excluded from Session summaries.
|
||||
|
||||
The Remote `act(sessionId, callId, verb, payload?)` checks the owner, the live root and the card; Not now continues without a registered kind, while other verbs need the kind, the verb and Remote access. It then shares one operation per card. The kind's `reconcile` runs first and the live root is checked again; a dismissed or replaced card then settles unchanged, Not now is recorded, a writing verb is refused in a read-only Session, and every other verb goes to the kind handler under the Agent's initiator. `record()` also accepts an action whose kind has unregistered, because Cordis disposes a plugin's effects concurrently and an unloading kind still records the outcome of work it started. An `agent/pre-step` listener adds the status notice after later listeners prepared the step.
|
||||
|
||||
| Source | Contents |
|
||||
|---|---|
|
||||
| [`src/index.ts`](src/index.ts) | Service, tool, kind registry, Remote action and status notice |
|
||||
| [`src/projection.ts`](src/projection.ts) | Session projection |
|
||||
| [`src/types.ts`](src/types.ts) | Proposal, decision, view and result types |
|
||||
| [`tests/`](tests/) | Activation, validation, projection, action and notice tests |
|
||||
|
||||
</details>
|
||||
|
||||
-----
|
||||
|
||||
<a id="further-exploration"></a>
|
||||
## Further Exploration
|
||||
|
||||
- [Action card display](../client-ui-action-cards/README.md) — the browser frame, kind bodies and the process row.
|
||||
- [Personalized pages](../creation-recommendations/README.md) and [Plugin recommendations](../plugin-recommendations/README.md) — the shipped card kinds.
|
||||
- [Tools](../../core/tools/README.md) — conditional registration and step admission.
|
||||
- [Session projection](../../session/session-projection/README.md) — the card state the browser reads.
|
||||
|
||||
<a id="model-experience"></a>
|
||||
## Model Experience
|
||||
|
||||
### Card tool
|
||||
|
||||
#### What the model sees
|
||||
|
||||
The [`propose_action` declaration](../../../docs/tool-catalog.md#deepseek-aidsh-action-cards) appears only to a live root Agent whose own direct call loaded the skill of a registered kind in this Session, from the next step on, for that Agent's lifetime. Subagents never see it, and neither do PTC presets, whose skill loads are dispatched from code, so they show no cards. A kind's skill names the action and the fields of `details`. An accepted call returns `Card shown below your answer. Do not restate it. <invitation>`, where `<invitation>` is the kind's one- or two-sentence guidance on inviting the user to the card in the user's language, so the model writes an invitation only after a card exists. A refused call carries no invitation and returns its reason, for example `Load skill <skill> first, then call propose_action.`, `One card per turn; the earlier card stands.`, `The user has queued more messages; show no card and answer briefly.`, `Cards are offered in the main conversation only.`, `Unknown action "<action>". Registered actions: <actions>.`, where the list reads `none` once the last kind unregistered, or the failing `details` fields.
|
||||
|
||||
#### Token effect
|
||||
|
||||
Before a card skill loads, the tool adds no tokens. Afterwards each request of that Agent declares it: 574 characters of JSON, about 144 tokens at the token meter's four characters per token. A card costs one extra model round trip, the call before the final answer, and its tool result: a 49-character prefix plus the kind's invitation. The Personalized pages result is 305 characters, about 77 tokens at the same rate.
|
||||
|
||||
#### KV Cache effect
|
||||
|
||||
Activation is append-only on routes that declare tool updates, such as DeepSeek-V4.1-Flash: when the condition turns true the loop logs a header change and a `tool-addition` developer message, and those routes receive the definition as a deferred declaration referenced at that position, so the cached prefix is kept. A route without tool updates receives the tool in its declaration list from that step on, which changes the request prefix once. Disposing the Agent drops the activation; a reopened Session declares the tool again only after a card skill loads again, logging a removal and a later addition.
|
||||
|
||||
### Card status notice
|
||||
|
||||
#### What the model sees
|
||||
|
||||
After a decision is recorded, the next request carries one `action-cards` notice: the preamble below, the guidance sentences of each involved kind, `Continue with the user’s current request.`, and a JSON array of the changed cards with `action`, `callId`, `title`, `phase` and the data fields their kind reports.
|
||||
|
||||
##### Notice preamble
|
||||
|
||||
```markdown
|
||||
Latest status of action cards from user actions and background work. These are status facts, not a request to start or retry work. Use these receipts instead of the earlier proposal when describing progress.
|
||||
```
|
||||
|
||||
#### Token effect
|
||||
|
||||
One notice per request that follows new decisions, sized by the changed cards; unchanged cards add nothing, and several decisions of one card collapse to its latest.
|
||||
|
||||
#### KV Cache effect
|
||||
|
||||
The notice is appended after the request's other new context and never rewrites earlier messages. The notice neither starts a turn nor wakes an idle conversation.
|
||||
|
||||
## Known Limitations and Deferred Work
|
||||
|
||||
<a id="known-limitations-and-deferred-work"></a>
|
||||
|
||||
- Activation is per live Agent and kept in memory, so after a Session reopens the tool appears again only after a card skill loads again.
|
||||
- PTC presets show no cards: skill loads and calls dispatched from code never activate or reach the tool, because the log records them as program dispatches rather than tool calls.
|
||||
- Cards are offered in the main conversation only. A subagent's skill load, including a Creator child's, activates nothing and its calls are refused, because only a live root can act on a card.
|
||||
- Only one card is offered per turn across all kinds. A later card of any kind replaces every unstarted earlier card, so a second kind's card replaces an unstarted card of the first.
|
||||
- Refusal reasons of user actions are plain strings by design: the service defines `closing`, `not-live-root`, `unknown`, `unavailable`, `access-denied` and `read-only`, each kind adds its own, and a browser body names the reasons it knows and treats others as unavailable.
|
||||
- Each kind validates `details` on both sides, with its Host schema when the model proposes and before each action, and with its browser body's own schema, so the two schemas change together.
|
||||
- The Personalized pages and Plugin recommendations bundles both insert the rows of this service and its browser half, and with both enabled the Loader keeps one entry per row id. Two optional bundles cannot yet share a dependency row addressably: while both are enabled, the Plugins page cannot address the two shared rows (`action-cards`, `client-ui-action-cards`), so they cannot be switched or configured individually. Use the bundle switches; `queuedMessageLimit` can then be changed only in the profile's `cordis.patch.yml`.
|
||||
|
||||
<a id="dev-note"></a>
|
||||
### Dev Note
|
||||
|
||||
<details>
|
||||
<summary>Working context for maintainers — click to expand</summary>
|
||||
|
||||
None.
|
||||
|
||||
</details>
|
||||
@@ -0,0 +1,138 @@
|
||||
---
|
||||
description: "可选操作卡片的共享 Host 服务:propose_action 工具、卡片状态、用户操作和状态通知,各实验包把自己的卡片种类注册进来。"
|
||||
kind: "package-reference"
|
||||
---
|
||||
|
||||
# @deepseek-ai/dsh-action-cards
|
||||
|
||||
[English](README.md) | 中文
|
||||
|
||||
## 概述
|
||||
|
||||
实验可以在回答下方提供一个可选操作,例如创建页面,而不必新增自己的工具。模型先加载该实验的 Skill,再调用 `propose_action`;本轮结束后卡片出现在回答下方,用户操作之前不会执行任何事。用户的每次选择都会被记录,并在模型的下一次请求中告知模型。对话中加载卡片 Skill 之前,这个工具不占用任何 token。
|
||||
|
||||
## 目录
|
||||
|
||||
- [使用本包](#use-this-package)
|
||||
- [实现原理](#understand-the-implementation)
|
||||
- [延伸阅读](#further-exploration)
|
||||
- [模型体验](#model-experience)
|
||||
- [已知限制与后续工作](#known-limitations-and-deferred-work)
|
||||
- [开发备注](#dev-note)
|
||||
|
||||
-----
|
||||
|
||||
<a id="use-this-package"></a>
|
||||
## 使用本包
|
||||
|
||||
[个性化页面](../creation-recommendations/README.zh.md)和[插件推荐](../plugin-recommendations/README.zh.md)两个 Bundle 都会插入本服务及其[浏览器端](../client-ui-action-cards/README.zh.md);启用其中任一个即同时启用两者。本服务只有一个配置字段:
|
||||
|
||||
| 字段 | 默认值 | 含义 |
|
||||
|---|---|---|
|
||||
| `queuedMessageLimit` | `2` | 排队到后续轮次的用户消息达到该数量时,`propose_action` 拒绝调用,因此不会展示卡片。 |
|
||||
|
||||
生成的[配置目录](../../../docs/config-catalog.zh.md#deepseek-aidsh-action-cards)是可接受字段的完整来源。
|
||||
|
||||
### 注册卡片种类
|
||||
|
||||
种类所在的包注入 `actionCards`,并在自己的插件中调用 `ctx.actionCards.register(kind)`;该插件卸载时种类随之移除,此后对其卡片的操作会以 unavailable 拒绝,只有“暂不需要”仍可忽略尚未开始的卡片。种类需要给出:动作名、提议该动作的 Skill、被接受的调用结果交给模型的结尾邀请指引、卡片 `details` 的 zod 校验、接受的用户操作及各自需要的共享检查(`global` 表示需要全局 Remote 权限,`writes` 表示只读会话中拒绝)、仍可忽略卡片的已记录阶段、可选的状态说明、状态通知要报告的决定数据字段、可选的 `reconcile`(每次操作前根据会话之外的状态更新卡片的已记录决定),以及处理 `dismiss` 以外所有操作的处理器。处理器用 `ctx.actionCards.record()` 记录每个新决定(该方法拒绝没有种类注册过的动作和推导得出的 `replaced` 阶段),并返回 `accepted`、带当前决定的 `settled`、`refused` 或 `unconfirmed`。
|
||||
|
||||
### 卡片规则
|
||||
|
||||
- 一轮中第一个被接受的 `propose_action` 调用成为卡片。工具会拒绝同一轮的第二次调用、未注册的动作、本轮没有加载对应种类 Skill 的调用、空白的标题或说明、未通过种类校验的 details、从代码中发起的调用、来自 subagent 的调用,以及排队到后续轮次的用户消息达到 `queuedMessageLimit` 条时的任何调用。
|
||||
- 任何种类的新卡片都会替换此前所有尚未开始的卡片。替换从日志推导,从不单独记录。
|
||||
- fork 出的会话从父会话继承的事件不会产生卡片。
|
||||
- 每次操作(包括“暂不需要”)之前,种类的 `reconcile` 先根据会话之外的状态更新卡片。之后,对尚未开始的卡片,以及处于种类列出阶段的卡片,“暂不需要”会被记录;已忽略、已替换的卡片不再接受任何操作。卡片的种类未注册时,“暂不需要”仍可忽略尚未开始的卡片,其他操作一律以 unavailable 拒绝。
|
||||
- 同一张卡片上的并发操作共用一次处理。操作要求卡片所在会话的根 Agent 仍然在线。
|
||||
|
||||
-----
|
||||
|
||||
<a id="understand-the-implementation"></a>
|
||||
## 实现原理
|
||||
|
||||
<details>
|
||||
<summary>实现细节——点击展开</summary>
|
||||
|
||||
本包默认导出 `actionCards` Remote 服务。它在全局注册一次 `propose_action`,并附带 `when` 条件:在线的根 Agent 自己直接调用 `skill` 加载了已注册种类的 Skill 后,该 Agent 才满足条件,subagent 或代码中发起的加载一律忽略;这个标记保存在内存中,直到 Agent 被释放。调用的 `execute` 检查在线根 Agent、投影累计的排队消息是否达到 `queuedMessageLimit`,并通过轮次边界检查本轮加载过的 Skill,同时在内存中标记本轮已接受的调用;日志中的 `tool/call` 及其成功的 `tool/result` 就是持久的提议。
|
||||
|
||||
`actionCards` 会话投影(状态版本 2)把每个 `propose_action` 调用与其成功结果配对,从 `plugin:action-cards/decision` 读取决定,从收件箱拼接事件累计排队到下一轮的消息供工具上限使用,并保留尚未报告的决定,直到 `through` 覆盖它们的状态通知写入日志。投影的客户端视图 `{ proposals, decisions }` 不进入会话摘要。
|
||||
|
||||
Remote `act(sessionId, callId, verb, payload?)` 先检查服务所有者、在线根 Agent 和卡片;“暂不需要”在种类未注册时也继续处理,其他操作还需要种类、操作和 Remote 权限。然后同一张卡片共用一次处理。种类的 `reconcile` 先运行,之后再次检查在线根 Agent;已忽略或已替换的卡片原样返回,“暂不需要”被记录,写入类操作在只读会话中被拒绝,其余操作在该 Agent 的发起方作用域内交给种类处理器。`record()` 也接受种类已注销的动作,因为 Cordis 并发释放插件的各个 effect,卸载中的种类仍要记录已开始工作的结果。一个 `agent/pre-step` 监听器在后续监听器准备好本步之后追加状态通知。
|
||||
|
||||
| 源码 | 内容 |
|
||||
|---|---|
|
||||
| [`src/index.ts`](src/index.ts) | 服务、工具、种类注册表、Remote 操作与状态通知 |
|
||||
| [`src/projection.ts`](src/projection.ts) | 会话投影 |
|
||||
| [`src/types.ts`](src/types.ts) | 提议、决定、视图与结果类型 |
|
||||
| [`tests/`](tests/) | 激活、校验、投影、操作与通知测试 |
|
||||
|
||||
</details>
|
||||
|
||||
-----
|
||||
|
||||
<a id="further-exploration"></a>
|
||||
## 延伸阅读
|
||||
|
||||
- [操作卡片显示](../client-ui-action-cards/README.zh.md) — 浏览器端卡片框架、种类正文与过程行。
|
||||
- [个性化页面](../creation-recommendations/README.zh.md)和[插件推荐](../plugin-recommendations/README.zh.md) — 随产品提供的卡片种类。
|
||||
- [工具](../../core/tools/README.zh.md) — 条件注册与每步准入。
|
||||
- [会话投影](../../session/session-projection/README.zh.md) — 浏览器读取的卡片状态。
|
||||
|
||||
<a id="model-experience"></a>
|
||||
## 模型体验
|
||||
|
||||
### 卡片工具
|
||||
|
||||
#### 模型看到什么
|
||||
|
||||
[`propose_action` 声明](../../../docs/tool-catalog.zh.md#deepseek-aidsh-action-cards)只对在本会话中自己直接调用加载过已注册种类 Skill 的在线根 Agent 出现,从下一步开始,持续到该 Agent 被释放。subagent 看不到它;PTC 预设的 Skill 加载由代码发起,也看不到它,因此不会展示卡片。种类的 Skill 给出动作名和 `details` 的字段。被接受的调用返回 `Card shown below your answer. Do not restate it. <invitation>`,其中 `<invitation>` 是种类给出的一两句指引,说明如何用用户的语言邀请用户使用卡片,因此模型只会在卡片已经存在之后写邀请。被拒绝的调用不带邀请,只返回原因,例如 `Load skill <skill> first, then call propose_action.`、`One card per turn; the earlier card stands.`、`The user has queued more messages; show no card and answer briefly.`、`Cards are offered in the main conversation only.`、`Unknown action "<action>". Registered actions: <actions>.`(最后一个种类注销后列表为 `none`),或未通过校验的 `details` 字段。
|
||||
|
||||
#### Token 影响
|
||||
|
||||
加载卡片 Skill 之前,工具不增加任何 token。加载之后,该 Agent 的每次请求都会声明它:574 个字符的 JSON,按 token 计量器每 4 个字符计 1 个 token 约 144 个 token。出一张卡片多一次模型往返(最终回答前的这次调用)以及一条工具结果:49 个字符的前缀加上种类的邀请。个性化页面的结果为 305 个字符,按同样的比例约 77 个 token。
|
||||
|
||||
#### KV Cache 影响
|
||||
|
||||
在声明支持工具更新的路由上(例如 DeepSeek-V4.1-Flash),激活只追加内容:条件变为真时,循环记录一次请求头变化和一条 `tool-addition` 开发者消息,这些路由以延迟加载声明的形式在该位置引用新定义,因此已缓存的前缀保持不变。不支持工具更新的路由从这一步起在声明列表中收到该工具,请求前缀因此改变一次。Agent 被释放后激活随之失效;重新打开的会话要再次加载卡片 Skill 才会再次声明该工具,并依次记录一次移除和一次添加。
|
||||
|
||||
### 卡片状态通知
|
||||
|
||||
#### 模型看到什么
|
||||
|
||||
记录决定之后,下一次请求会带一条 `action-cards` 通知:下方的开头段落、所涉及各种类的说明句、`Continue with the user’s current request.`,以及一个 JSON 数组,列出发生变化的卡片的 `action`、`callId`、`title`、`phase` 和种类要报告的数据字段。
|
||||
|
||||
##### 通知开头
|
||||
|
||||
```markdown
|
||||
Latest status of action cards from user actions and background work. These are status facts, not a request to start or retry work. Use these receipts instead of the earlier proposal when describing progress.
|
||||
```
|
||||
|
||||
#### Token 影响
|
||||
|
||||
有新决定之后的每次请求带一条通知,大小取决于发生变化的卡片;没有变化的卡片不增加内容,同一张卡片的多次决定只报告最新一次。
|
||||
|
||||
#### KV Cache 影响
|
||||
|
||||
通知追加在本次请求其他新上下文之后,从不改写之前的消息。通知既不会开始新轮次,也不会唤醒空闲的对话。
|
||||
|
||||
## 已知限制与后续工作
|
||||
|
||||
<a id="known-limitations-and-deferred-work"></a>
|
||||
|
||||
- 激活按在线 Agent 记在内存中,因此会话重新打开后,要再次加载卡片 Skill 工具才会再次出现。
|
||||
- PTC 预设不会展示卡片:从代码中发起的 Skill 加载和调用既不会激活工具,也到达不了工具,因为日志把它们记为程序派发而不是工具调用。
|
||||
- 卡片只在主对话中提供。subagent(包括 Creator 子 Agent)加载 Skill 不会激活任何东西,其调用也会被拒绝,因为只有在线的根 Agent 才能对卡片进行操作。
|
||||
- 所有种类合计每轮只展示一张卡片。任何种类的新卡片都会替换此前所有尚未开始的卡片,因此第二个种类的卡片会替换第一个种类尚未开始的卡片。
|
||||
- 用户操作的拒绝原因有意设计为普通字符串:服务定义 `closing`、`not-live-root`、`unknown`、`unavailable`、`access-denied` 和 `read-only`,各种类可以添加自己的原因,浏览器端正文为已知原因显示文案,其余按 unavailable 处理。
|
||||
- 每个种类在两端各自校验 `details`:Host 端的 schema 在模型提议时和每次操作前校验,浏览器端正文用自己的 schema 校验,因此两个 schema 要一起修改。
|
||||
- 个性化页面和插件推荐两个 Bundle 都会插入本服务及其浏览器端的行,两个都启用时 Loader 对每个行 id 只保留一个条目。平台目前不支持两个可选 Bundle 以可定位的方式共享同一依赖行:两个都启用时,插件页无法定位这两条共享行(`action-cards`、`client-ui-action-cards`),不能单独开关或配置它们。请使用 Bundle 开关;此时 `queuedMessageLimit` 只能在 profile 的 `cordis.patch.yml` 中修改。
|
||||
|
||||
<a id="dev-note"></a>
|
||||
### 开发备注
|
||||
|
||||
<details>
|
||||
<summary>维护者工作背景——点击展开</summary>
|
||||
|
||||
无。
|
||||
|
||||
</details>
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"meta": {
|
||||
"title": "Aktionskarten",
|
||||
"description": "Zeigt für aktivierte Experimente optionale Aktionskarten unter Antworten an und meldet die Entscheidungen des Benutzers an das Gespräch zurück."
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"meta": {
|
||||
"title": "Action cards",
|
||||
"description": "Show optional action cards below answers for enabled experiments, and report the user's choices back to the conversation."
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"meta": {
|
||||
"title": "Tarjetas de acción",
|
||||
"description": "Muestra tarjetas de acción opcionales debajo de las respuestas para los experimentos habilitados e informa a la conversación de las elecciones del usuario."
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"meta": {
|
||||
"title": "Cartes d'action",
|
||||
"description": "Affiche des cartes d'action facultatives sous les réponses pour les expériences activées et transmet les choix de l'utilisateur à la conversation."
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"meta": {
|
||||
"title": "アクションカード",
|
||||
"description": "有効な実験のために回答の下に任意のアクションカードを表示し、ユーザーの選択を会話に伝えます。"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"meta": {
|
||||
"title": "Cartões de ação",
|
||||
"description": "Mostra cartões de ação opcionais abaixo das respostas para experimentos ativados e informa as escolhas do usuário à conversa."
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"meta": {
|
||||
"title": "Карточки действий",
|
||||
"description": "Показывает необязательные карточки действий под ответами для включенных экспериментов и передает выбор пользователя в разговор."
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"meta": {
|
||||
"title": "操作卡片",
|
||||
"description": "为已启用的实验在回答下方显示可选操作卡片,并把用户的选择告知对话。"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
{
|
||||
"name": "@deepseek-ai/dsh-action-cards",
|
||||
"description": "Optional action cards below answers: one shared proposal tool, card state, user actions and status notices",
|
||||
"version": "0.2.1-rc.2",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/deepseek-ai/deepseek-harness.git",
|
||||
"directory": "packages/experimental/action-cards"
|
||||
},
|
||||
"type": "module",
|
||||
"main": "lib/index.js",
|
||||
"types": "lib/types/index.d.ts",
|
||||
"exports": {
|
||||
".": {
|
||||
"types": "./lib/types/index.d.ts",
|
||||
"default": "./lib/index.js"
|
||||
},
|
||||
"./src/*": "./src/*",
|
||||
"./package.json": "./package.json",
|
||||
"./locale/*.json": "./locale/*.json",
|
||||
"./types": {
|
||||
"types": "./lib/types/types.d.ts",
|
||||
"default": "./lib/types/types.js"
|
||||
},
|
||||
"./typert": {
|
||||
"types": "./lib/typert.host.d.ts",
|
||||
"default": "./lib/typert.host.js"
|
||||
},
|
||||
"./remote": {
|
||||
"types": "./lib/typert.remote-client.d.ts",
|
||||
"default": "./lib/typert.remote-client.js"
|
||||
}
|
||||
},
|
||||
"license": "MIT",
|
||||
"peerDependencies": {
|
||||
"@deepseek-ai/cordis": "workspace:~",
|
||||
"@deepseek-ai/dsh-typert-protocol": "workspace:*",
|
||||
"@deepseek-ai/dsh-llm": "workspace:*",
|
||||
"@deepseek-ai/dsh-tools": "workspace:*",
|
||||
"@deepseek-ai/dsh-session": "workspace:*"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@deepseek-ai/cordis": "workspace:~",
|
||||
"@deepseek-ai/dsh-typert-protocol": "workspace:*",
|
||||
"@deepseek-ai/dsh-llm": "workspace:*",
|
||||
"@deepseek-ai/dsh-tools": "workspace:*",
|
||||
"@deepseek-ai/dsh-agent": "workspace:*",
|
||||
"@deepseek-ai/dsh-agent-loop": "workspace:*",
|
||||
"@deepseek-ai/dsh-agent-loop-testkit": "workspace:*",
|
||||
"@deepseek-ai/dsh-session": "workspace:*",
|
||||
"@deepseek-ai/dsh-session-projection": "workspace:*",
|
||||
"@deepseek-ai/dsh-api-remote-access": "workspace:*",
|
||||
"@deepseek-ai/dsh-sandbox-policy": "workspace:*",
|
||||
"@deepseek-ai/dsh-skill": "workspace:*",
|
||||
"@deepseek-ai/dsh-tool-skill": "workspace:*",
|
||||
"@deepseek-ai/dsh-tool-testkit": "workspace:*",
|
||||
"@deepseek-ai/dsh-util-values": "workspace:*"
|
||||
},
|
||||
"dependencies": {
|
||||
"zod": "4.4.3"
|
||||
},
|
||||
"files": [
|
||||
"locale/*.json",
|
||||
"lib/index.js",
|
||||
"lib/types/**/*.js",
|
||||
"lib/types/**/*.d.ts",
|
||||
"lib/typert.host.js",
|
||||
"lib/typert.host.d.ts",
|
||||
"lib/typert.remote-client.js",
|
||||
"lib/typert.remote-client.d.ts"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,451 @@
|
||||
/** Optional action cards below an answer: the `propose_action` tool, card state, user actions and status notices for registered kinds. */
|
||||
import { FiberState, Service, type Context } from '@deepseek-ai/cordis'
|
||||
import { z, type ZodError, type ZodType } from 'zod'
|
||||
import { Remote, TypertRemoteService } from '@deepseek-ai/dsh-typert-protocol'
|
||||
import { createUserMessage, HarnessError, type ToolCallId } from '@deepseek-ai/dsh-llm'
|
||||
import { defineTool, type ToolRunContext } from '@deepseek-ai/dsh-tools'
|
||||
import { appendPluginRecord, SessionSeq, type Session } from '@deepseek-ai/dsh-session'
|
||||
import type { Agent } from '@deepseek-ai/dsh-agent'
|
||||
import type { ProjectionHandle } from '@deepseek-ai/dsh-session-projection'
|
||||
import type { JsonValue } from '@deepseek-ai/dsh-util-values'
|
||||
import type {} from '@deepseek-ai/dsh-api-remote-access'
|
||||
import type {} from '@deepseek-ai/dsh-sandbox-policy'
|
||||
import { actionCardProjection, PROPOSE_ACTION, type ActionCardState } from './projection.ts'
|
||||
import type { ActionCardDecision, ActionCardFields, ActionCardProposal, ActionCardResult, ActionCardView } from './types.ts'
|
||||
export type * from './types.ts'
|
||||
|
||||
/** Deployment-tunable limits for offering cards. */
|
||||
export const Config = z.object({
|
||||
/** Queued next-turn user messages at or above which `propose_action` refuses, so no card is offered. */
|
||||
queuedMessageLimit: z.number().int().min(1).default(2),
|
||||
}).prefault({})
|
||||
/** Validated card limits after schema defaults. */
|
||||
export type Config = z.infer<typeof Config>
|
||||
|
||||
declare module '@deepseek-ai/cordis' {
|
||||
interface Context { actionCards: ActionCards }
|
||||
}
|
||||
|
||||
/** The user action every card offers; the shared service records it. */
|
||||
const DISMISS = 'dismiss'
|
||||
/** Phases the projection derives from the log; no decision may record them. */
|
||||
const DERIVED_PHASES: readonly string[] = ['replaced']
|
||||
/** Phases after which no user action changes the card. */
|
||||
const FINAL_PHASES: readonly string[] = ['dismissed', ...DERIVED_PHASES]
|
||||
/** Tool whose successful loads activate `propose_action`; its `name` argument names the skill. */
|
||||
const SKILL_TOOL = 'skill'
|
||||
const skillArguments = z.object({ name: z.string() })
|
||||
|
||||
const STATUS_PREAMBLE = 'Latest status of action cards from user actions and background work. '
|
||||
+ 'These are status facts, not a request to start or retry work. Use these receipts instead of the earlier proposal when describing progress.'
|
||||
const STATUS_CLOSING = 'Continue with the user’s current request.'
|
||||
|
||||
/** The fiber fields the stopping check reads. */
|
||||
export interface PluginFiber {
|
||||
readonly uid: number | null
|
||||
readonly state: FiberState
|
||||
readonly parent: { readonly fiber: PluginFiber }
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether a plugin must refuse new work: its fiber or an ancestor is disposed or unloading, since a parent's disposal
|
||||
* begins before the plugin's own effects run, or the plugin's own drain has begun.
|
||||
* @param owner - the plugin's fiber.
|
||||
* @param draining - whether the plugin's drain effect has started.
|
||||
* @returns whether the plugin is stopping.
|
||||
*/
|
||||
export function isPluginStopping(owner: PluginFiber, draining: boolean): boolean {
|
||||
for (let fiber = owner; ; fiber = fiber.parent.fiber) {
|
||||
if (fiber.uid === null || fiber.state === FiberState.UNLOADING) return true
|
||||
if (fiber.parent.fiber === fiber) return draining
|
||||
}
|
||||
}
|
||||
|
||||
/** A refused `propose_action` call; the message tells the model what to do instead. */
|
||||
export class ActionCardError extends HarnessError {}
|
||||
|
||||
/** Shared checks one user action of a kind requires before the kind handles it. */
|
||||
export interface ActionCardVerb {
|
||||
/** The connection must hold global Remote access, as for profile changes. */
|
||||
readonly global?: true
|
||||
/** Refused while the Session sandbox mode is read-only. */
|
||||
readonly writes?: true
|
||||
}
|
||||
|
||||
/** A proposal whose details passed its kind's schema. */
|
||||
export type ActionCardProposalOf<Details> = Omit<ActionCardProposal, 'details'> & { readonly details: Details }
|
||||
|
||||
/** Host half of one action kind: the skill that proposes it, its fields and its user actions. */
|
||||
export interface ActionCardKind<Details> {
|
||||
/** Value of the `action` argument. */
|
||||
readonly action: string
|
||||
/** Skill whose instructions propose this action; a load in the current turn admits the call. */
|
||||
readonly skill: string
|
||||
/**
|
||||
* Model-facing closing guidance that the result of an accepted call gives: one or two sentences on how to invite
|
||||
* the user to the card, in the user's language. Refused calls never carry it, so the model invites the user only to a
|
||||
* card that exists.
|
||||
*/
|
||||
readonly invitation: string
|
||||
/** Validates `details` when the model proposes and before each user action. */
|
||||
readonly details: ZodType<Details>
|
||||
/** User actions besides `dismiss`, with the shared checks each requires; other verbs are refused as unavailable. */
|
||||
readonly verbs: Readonly<Record<string, ActionCardVerb>>
|
||||
/** Recorded phases that still offer the action; dismissal is recorded for these and for an unstarted card. */
|
||||
readonly openPhases?: readonly string[]
|
||||
/** Sentences the status notice adds when it reports this kind's decisions. */
|
||||
readonly statusGuidance?: string
|
||||
/** Decision data fields the status notice reports; omitted reports every field. */
|
||||
readonly statusFields?: readonly string[]
|
||||
/**
|
||||
* Fields recorded with a dismissal.
|
||||
* @param proposal - the dismissed card.
|
||||
* @param payload - fields the user's client sent.
|
||||
* @returns decision data, or undefined to record none.
|
||||
*/
|
||||
dismissal?(proposal: ActionCardProposalOf<Details>, payload: ActionCardFields | undefined): ActionCardFields | undefined
|
||||
/**
|
||||
* Bring the card's recorded decision up to date with state outside the Session, such as an installation that
|
||||
* finished while the Session was closed, recording each change with {@link ActionCards.record}. The service awaits it
|
||||
* before every user action, including `dismiss`, then reads the card's decision again, so a card that is no longer
|
||||
* open settles instead of being dismissed.
|
||||
* @param agent - live root of the card's Session.
|
||||
* @param proposal - the card with validated details.
|
||||
* @throws when that state cannot be read; the action is then refused as unavailable.
|
||||
*/
|
||||
reconcile?(agent: Agent, proposal: ActionCardProposalOf<Details>): Promise<void>
|
||||
/**
|
||||
* Handle one user action other than `dismiss` after the shared checks passed. The handler records each new
|
||||
* decision with {@link ActionCards.record}.
|
||||
* @param agent - live root of the card's Session.
|
||||
* @param proposal - the card with validated details.
|
||||
* @param verb - one of {@link verbs}.
|
||||
* @param payload - fields the user's client sent; the kind validates them.
|
||||
* @returns the action's result.
|
||||
*/
|
||||
act(agent: Agent, proposal: ActionCardProposalOf<Details>, verb: string, payload: ActionCardFields | undefined): Promise<ActionCardResult>
|
||||
}
|
||||
|
||||
/** A registered kind with its details type erased behind validating closures. */
|
||||
interface RegisteredKind {
|
||||
readonly skill: string
|
||||
readonly invitation: string
|
||||
readonly verbs: Readonly<Record<string, ActionCardVerb>>
|
||||
readonly openPhases: readonly string[]
|
||||
readonly statusGuidance: string | undefined
|
||||
readonly statusFields: readonly string[] | undefined
|
||||
/** Describe why details fail the kind's schema; undefined when they pass. */
|
||||
readonly detailsIssues: (details: ActionCardFields) => string | undefined
|
||||
readonly dismissal: (proposal: ActionCardProposal, payload: ActionCardFields | undefined) => ActionCardFields | undefined
|
||||
/** Absent when the kind keeps no state outside the Session. */
|
||||
readonly reconcile: ((agent: Agent, proposal: ActionCardProposal) => Promise<void>) | undefined
|
||||
readonly act: (
|
||||
agent: Agent, proposal: ActionCardProposal, verb: string, payload: ActionCardFields | undefined,
|
||||
) => Promise<ActionCardResult>
|
||||
}
|
||||
|
||||
/** Own entries only: browser-supplied ids such as `toString` never reach inherited object members. */
|
||||
function ownEntry<T>(record: Readonly<Record<string, T>>, key: string): T | undefined {
|
||||
return Object.hasOwn(record, key) ? record[key] : undefined
|
||||
}
|
||||
|
||||
function refused(reason: string): ActionCardResult {
|
||||
return { status: 'refused', reason }
|
||||
}
|
||||
|
||||
function issuesOf(error: ZodError): string {
|
||||
return 'Invalid details: ' + error.issues.map(issue => `${['details', ...issue.path.map(String)].join('.')}: ${issue.message}`).join('; ')
|
||||
}
|
||||
|
||||
/** Card tool, kind registry, Session projection, user actions and status notices. */
|
||||
export class ActionCards extends TypertRemoteService {
|
||||
static inject = ['tools', 'agents', 'sessionProjections', 'remoteAccess']
|
||||
static Config = Config
|
||||
private projection!: ProjectionHandle<ActionCardState>
|
||||
private readonly kinds = new Map<string, RegisteredKind>()
|
||||
/**
|
||||
* Actions whose kind unregistered. Cordis disposes a plugin's effects concurrently, so a kind's unload drain can
|
||||
* still record the outcome of its in-flight work after its registration is gone.
|
||||
*/
|
||||
private readonly retired = new Set<string>()
|
||||
/** Skills of registered kinds each live agent has loaded; `propose_action` is declared while one is still registered. */
|
||||
private readonly loaded = new Map<Agent, Set<string>>()
|
||||
/** Kind skills each agent loaded in its latest turn. */
|
||||
private readonly turnLoads = new Map<Agent, { readonly turn: number; readonly skills: Set<string> }>()
|
||||
/** The call accepted in each agent's latest turn, until its result fails. */
|
||||
private readonly accepted = new Map<Agent, { readonly turn: number; readonly callId: ToolCallId }>()
|
||||
private readonly actions = new Map<string, Promise<ActionCardResult>>()
|
||||
private closing = false
|
||||
private readonly owner: Context['fiber']
|
||||
|
||||
/**
|
||||
* @param ctx - Owning plugin context.
|
||||
* @param config - Validated card limits; direct composition without a config gets the schema defaults.
|
||||
*/
|
||||
constructor(ctx: Context, private readonly config: Config = Config.parse({})) {
|
||||
super(ctx, 'actionCards')
|
||||
this.owner = ctx.fiber
|
||||
}
|
||||
|
||||
protected async [Service.init](): Promise<void> {
|
||||
this.projection = await this.ctx.sessionProjections.register(actionCardProjection)
|
||||
this.ctx.tools.register(defineTool({
|
||||
name: PROPOSE_ACTION,
|
||||
description: 'Show the user one optional action card under this answer. Call only as the skill that names the action instructs.',
|
||||
parameters: {
|
||||
action: { type: 'string', required: true, description: 'Action name from the skill.' },
|
||||
title: { type: 'string', required: true, description: 'Card title.' },
|
||||
brief: { type: 'string', required: true, description: 'What the action does, in the user\'s language.' },
|
||||
details: { type: 'object', additionalProperties: true, required: true, description: 'Fields the skill lists for this action.' },
|
||||
},
|
||||
output: {
|
||||
schema: {
|
||||
type: 'object', additionalProperties: false,
|
||||
properties: {
|
||||
action: { type: 'string', required: true }, title: { type: 'string', required: true }, invitation: { type: 'string', required: true },
|
||||
},
|
||||
},
|
||||
render: (_args, value) => [{ type: 'text', text: `Card shown below your answer. Do not restate it. ${value.invitation}` }],
|
||||
},
|
||||
execute: (args, exec) => Promise.resolve(this.propose(args, exec)),
|
||||
}), { when: ({ agent }) => this.declares(agent) })
|
||||
this.ctx.on('tools/result', (exec, result) => {
|
||||
const agent = exec.agent
|
||||
if (agent === undefined) return
|
||||
if (exec.name === PROPOSE_ACTION) {
|
||||
if (result.isError && this.accepted.get(agent)?.callId === exec.callId) this.accepted.delete(agent)
|
||||
return
|
||||
}
|
||||
// Loads by subagents or from code activate nothing: `propose_action` refuses both callers.
|
||||
if (exec.parent !== undefined || !this.ctx.agents.roots().includes(agent)) return
|
||||
const skill = exec.name === SKILL_TOOL && !result.isError ? skillArguments.safeParse(exec.arguments) : undefined
|
||||
if (skill?.success !== true || ![...this.kinds.values()].some(kind => kind.skill === skill.data.name)) return
|
||||
const turn = this.ctx.agents.turnBoundaryOf(agent.session).lastTurn
|
||||
const loads = this.turnLoads.get(agent)
|
||||
if (loads?.turn === turn) loads.skills.add(skill.data.name)
|
||||
else this.turnLoads.set(agent, { turn, skills: new Set([skill.data.name]) })
|
||||
this.loaded.set(agent, new Set([...this.loaded.get(agent) ?? [], skill.data.name]))
|
||||
})
|
||||
this.ctx.on('agent/disposed', ({ agent }) => {
|
||||
this.loaded.delete(agent)
|
||||
this.turnLoads.delete(agent)
|
||||
this.accepted.delete(agent)
|
||||
})
|
||||
this.ctx.on('agent/pre-step', async ({ agent, signal }, next) => {
|
||||
const decision = await next()
|
||||
if (decision.kind === 'reject' || signal.aborted || this.isStopping()) return decision
|
||||
const state = this.projection.stateOf(agent.session)
|
||||
const pending = Object.values(state.pendingStatus)
|
||||
if (pending.length === 0) return decision
|
||||
const receipts = Object.values(state.view.decisions).filter(receipt => Object.hasOwn(state.pendingStatus, receipt.callId))
|
||||
const guidance = new Set(receipts.flatMap(receipt => this.kinds.get(receipt.action)?.statusGuidance ?? []))
|
||||
const updates = receipts.map((receipt) => {
|
||||
const fields = this.kinds.get(receipt.action)?.statusFields
|
||||
const data = receipt.data === undefined || fields === undefined ? receipt.data
|
||||
: Object.fromEntries(Object.entries(receipt.data).filter(([key]) => fields.includes(key)))
|
||||
return { action: receipt.action, callId: receipt.callId, title: ownEntry(state.view.proposals, receipt.callId)?.title,
|
||||
phase: receipt.phase, ...data === undefined ? {} : { data } }
|
||||
})
|
||||
return { ...decision, messages: [...decision.messages, createUserMessage({
|
||||
source: { kind: 'action-cards', through: SessionSeq(Math.max(...pending)), form: 'notice', summary: 'Action card status updated' },
|
||||
content: [{ type: 'text', text: [STATUS_PREAMBLE, ...guidance, STATUS_CLOSING].join(' ') + '\n' + JSON.stringify(updates) }],
|
||||
})] }
|
||||
}, { prepend: true })
|
||||
this.ctx.effect(() => async () => {
|
||||
this.closing = true
|
||||
await Promise.allSettled([...this.actions.values()])
|
||||
}, 'action-cards: drain user actions')
|
||||
}
|
||||
|
||||
/**
|
||||
* Register one action kind for the caller's lifetime.
|
||||
* @param kind - the kind's skill, details schema, verbs and handler.
|
||||
* @returns disposer removing the kind; actions on its cards are then unavailable.
|
||||
* @throws when another kind already registered the same action.
|
||||
*/
|
||||
register<Details>(kind: ActionCardKind<Details>): () => void {
|
||||
const typed = (proposal: ActionCardProposal): ActionCardProposalOf<Details> | undefined => {
|
||||
const details = kind.details.safeParse(proposal.details)
|
||||
return details.success ? { ...proposal, details: details.data } : undefined
|
||||
}
|
||||
const reconcile = kind.reconcile?.bind(kind)
|
||||
const entry: RegisteredKind = {
|
||||
skill: kind.skill, invitation: kind.invitation, verbs: kind.verbs, openPhases: kind.openPhases ?? [],
|
||||
statusGuidance: kind.statusGuidance, statusFields: kind.statusFields,
|
||||
detailsIssues: (details) => {
|
||||
const parsed = kind.details.safeParse(details)
|
||||
return parsed.success ? undefined : issuesOf(parsed.error)
|
||||
},
|
||||
dismissal: (proposal, payload) => {
|
||||
const card = typed(proposal)
|
||||
return card === undefined ? undefined : kind.dismissal?.(card, payload)
|
||||
},
|
||||
// A card whose details no longer validate never reached the kind, so the kind has nothing to reconcile.
|
||||
reconcile: reconcile === undefined ? undefined : async (agent, proposal) => {
|
||||
const card = typed(proposal)
|
||||
if (card !== undefined) await reconcile(agent, card)
|
||||
},
|
||||
act: (agent, proposal, verb, payload) => {
|
||||
const card = typed(proposal)
|
||||
return card === undefined ? Promise.resolve(refused('unavailable')) : kind.act(agent, card, verb, payload)
|
||||
},
|
||||
}
|
||||
const dispose = this.ctx.effect(() => {
|
||||
if (this.kinds.has(kind.action)) throw new Error(`action-cards: action "${kind.action}" is already registered`)
|
||||
this.kinds.set(kind.action, entry)
|
||||
return () => {
|
||||
this.kinds.delete(kind.action)
|
||||
this.retired.add(kind.action)
|
||||
}
|
||||
}, `action-cards: kind ${kind.action}`)
|
||||
return () => { void dispose() }
|
||||
}
|
||||
|
||||
/**
|
||||
* Record a card decision in the Session log; the next model request reports it.
|
||||
* @param agent - agent whose Session owns the card.
|
||||
* @param decision - the card's new state.
|
||||
* @throws when no kind ever registered the decision's action with this service, or its phase is one the projection derives.
|
||||
*/
|
||||
record(agent: Agent, decision: ActionCardDecision): void {
|
||||
if (!this.kinds.has(decision.action) && !this.retired.has(decision.action)) {
|
||||
throw new Error(`action-cards: cannot record a decision for unregistered action "${decision.action}"`)
|
||||
}
|
||||
if (DERIVED_PHASES.includes(decision.phase)) throw new Error(`action-cards: phase "${decision.phase}" is derived from the log and cannot be recorded`)
|
||||
this.append(agent, decision)
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the cards of one Session.
|
||||
* @param session - a Session whose projections are prepared.
|
||||
* @returns proposals and decisions by call id.
|
||||
*/
|
||||
view(session: Session): ActionCardView {
|
||||
return this.projection.stateOf(session).view
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply a user action to a logged card. Shared checks run first, then the kind reconciles the card; `dismiss` is
|
||||
* recorded here and every other verb goes to the card's kind. `dismiss` also works on an unstarted card whose kind
|
||||
* is no longer registered. Concurrent actions on one card share one operation.
|
||||
* @param agent - live root resolved from the displayed Session.
|
||||
* @param callId - the card's `propose_action` call id.
|
||||
* @param verb - `dismiss` or one of the kind's verbs.
|
||||
* @param payload - kind-defined fields such as a chosen location.
|
||||
* @returns acceptance of background work, the decision in effect, or a refusal.
|
||||
*/
|
||||
@Remote
|
||||
act(agent: Agent, callId: ToolCallId, verb: string, payload?: Record<string, JsonValue>): Promise<ActionCardResult> {
|
||||
if (this.isStopping()) return Promise.resolve(refused('closing'))
|
||||
if (!this.ctx.agents.roots().includes(agent)) return Promise.resolve(refused('not-live-root'))
|
||||
const proposal = ownEntry(this.projection.stateOf(agent.session).view.proposals, callId)
|
||||
if (proposal === undefined) return Promise.resolve(refused('unknown'))
|
||||
const kind = this.kinds.get(proposal.action)
|
||||
if (verb === DISMISS) return this.coalesce(agent, callId, () => this.dismiss(agent, kind, proposal, payload))
|
||||
const policy = kind === undefined ? undefined : ownEntry(kind.verbs, verb)
|
||||
if (kind === undefined || policy === undefined) return Promise.resolve(refused('unavailable'))
|
||||
if (policy.global === true && !this.ctx.remoteAccess.allows({ kind: 'global' })) return Promise.resolve(refused('access-denied'))
|
||||
return this.coalesce(agent, callId, () => this.perform(agent, kind, proposal, verb, policy, payload))
|
||||
}
|
||||
|
||||
/** Share one operation per card, run under the Agent's initiator, until it settles. */
|
||||
private coalesce(agent: Agent, callId: ToolCallId, run: () => Promise<ActionCardResult>): Promise<ActionCardResult> {
|
||||
const key = JSON.stringify([agent.id, callId])
|
||||
const existing = this.actions.get(key)
|
||||
if (existing !== undefined) return existing
|
||||
const operation = this.ctx.agents.withInitiator(agent, run).finally(() => { this.actions.delete(key) })
|
||||
this.actions.set(key, operation)
|
||||
return operation
|
||||
}
|
||||
|
||||
/**
|
||||
* Await the kind's reconciliation. A kind that unloads meanwhile still handles the action and refuses it itself.
|
||||
* @returns a refusal when reconciliation failed or the root closed meanwhile; undefined to continue.
|
||||
*/
|
||||
private async reconciled(
|
||||
agent: Agent, kind: RegisteredKind, proposal: ActionCardProposal, verb: string,
|
||||
): Promise<ActionCardResult | undefined> {
|
||||
if (kind.reconcile === undefined) return undefined
|
||||
try { await kind.reconcile(agent, proposal) }
|
||||
catch (error) {
|
||||
this.ctx.logger.warn('Cannot reconcile action card %s before %s: %s', proposal.callId, verb, String(error))
|
||||
return refused('unavailable')
|
||||
}
|
||||
return this.ctx.agents.roots().includes(agent) ? undefined : refused('not-live-root')
|
||||
}
|
||||
|
||||
private async dismiss(
|
||||
agent: Agent, kind: RegisteredKind | undefined, proposal: ActionCardProposal, payload: ActionCardFields | undefined,
|
||||
): Promise<ActionCardResult> {
|
||||
const refusal = kind === undefined ? undefined : await this.reconciled(agent, kind, proposal, DISMISS)
|
||||
if (refusal !== undefined) return refusal
|
||||
const decision = ownEntry(this.projection.stateOf(agent.session).view.decisions, proposal.callId)
|
||||
// Without its kind no recorded phase is known to be open, and the kind may return to act on it.
|
||||
if (decision !== undefined && (FINAL_PHASES.includes(decision.phase) || kind?.openPhases.includes(decision.phase) !== true)) {
|
||||
return { status: 'settled', decision }
|
||||
}
|
||||
const data = kind?.dismissal(proposal, payload)
|
||||
const dismissed: ActionCardDecision = { callId: proposal.callId, action: proposal.action, phase: 'dismissed', ...data === undefined ? {} : { data } }
|
||||
this.append(agent, dismissed)
|
||||
return { status: 'settled', decision: dismissed }
|
||||
}
|
||||
|
||||
private async perform(
|
||||
agent: Agent, kind: RegisteredKind, proposal: ActionCardProposal, verb: string, policy: ActionCardVerb,
|
||||
payload: ActionCardFields | undefined,
|
||||
): Promise<ActionCardResult> {
|
||||
const refusal = await this.reconciled(agent, kind, proposal, verb)
|
||||
if (refusal !== undefined) return refusal
|
||||
const decision = ownEntry(this.projection.stateOf(agent.session).view.decisions, proposal.callId)
|
||||
if (decision !== undefined && FINAL_PHASES.includes(decision.phase)) return { status: 'settled', decision }
|
||||
if (policy.writes === true && this.ctx.get('sandboxPolicy')?.resolve({ session: agent.session }).mode === 'read-only') return refused('read-only')
|
||||
return await kind.act(agent, proposal, verb, payload)
|
||||
}
|
||||
|
||||
private append(agent: Agent, decision: ActionCardDecision): void {
|
||||
appendPluginRecord(agent.session, 'plugin:action-cards/decision', decision)
|
||||
}
|
||||
|
||||
/** Whether `propose_action` is declared for this agent's next step. */
|
||||
private declares(agent: Agent): boolean {
|
||||
const skills = this.loaded.get(agent)
|
||||
return skills !== undefined && [...this.kinds.values()].some(kind => skills.has(kind.skill))
|
||||
}
|
||||
|
||||
private propose(
|
||||
args: { readonly action: string; readonly title: string; readonly brief: string; readonly details: ActionCardFields },
|
||||
exec: ToolRunContext,
|
||||
): { action: string; title: string; invitation: string } {
|
||||
const agent = exec.agent
|
||||
// Step admission declares the tool only to an agent; calls dispatched from code are not logged as tool calls,
|
||||
// so no card could follow them.
|
||||
if (agent === undefined || exec.parent !== undefined) throw new ActionCardError('Call propose_action directly, not from code.', 'ACTION_CARD_NESTED')
|
||||
// Only a live root can act on a card, so a subagent's card could never be used.
|
||||
if (!this.ctx.agents.roots().includes(agent)) throw new ActionCardError('Cards are offered in the main conversation only.', 'ACTION_CARD_ROOT')
|
||||
if (this.projection.stateOf(agent.session).queued >= this.config.queuedMessageLimit) {
|
||||
throw new ActionCardError('The user has queued more messages; show no card and answer briefly.', 'ACTION_CARD_QUEUED')
|
||||
}
|
||||
const kind = this.kinds.get(args.action)
|
||||
// Admission is decided when the step starts, so the last kind can unregister before this call runs.
|
||||
if (kind === undefined) throw new ActionCardError(`Unknown action "${args.action}". Registered actions: ${[...this.kinds.keys()].join(', ') || 'none'}.`, 'ACTION_CARD_UNKNOWN')
|
||||
const turn = this.ctx.agents.turnBoundaryOf(agent.session).lastTurn
|
||||
const loads = this.turnLoads.get(agent)
|
||||
if (loads?.turn !== turn || !loads.skills.has(kind.skill)) {
|
||||
throw new ActionCardError(`Load skill ${kind.skill} first, then call propose_action.`, 'ACTION_CARD_SKILL')
|
||||
}
|
||||
if (args.title.trim() === '' || args.brief.trim() === '') throw new ActionCardError('Write a title and a brief.', 'ACTION_CARD_BLANK')
|
||||
const issues = kind.detailsIssues(args.details)
|
||||
if (issues !== undefined) throw new ActionCardError(issues, 'ACTION_CARD_DETAILS')
|
||||
if (this.accepted.get(agent)?.turn === turn || Object.values(this.view(agent.session).proposals).some(card => card.turn === turn)) {
|
||||
throw new ActionCardError('One card per turn; the earlier card stands.', 'ACTION_CARD_LIMIT')
|
||||
}
|
||||
this.accepted.set(agent, { turn, callId: exec.callId })
|
||||
return { action: args.action, title: args.title.trim(), invitation: kind.invitation }
|
||||
}
|
||||
|
||||
private isStopping(): boolean {
|
||||
return isPluginStopping(this.owner, this.closing)
|
||||
}
|
||||
}
|
||||
|
||||
export default ActionCards
|
||||
@@ -0,0 +1,124 @@
|
||||
/** Recover card proposals from logged `propose_action` calls and decisions from plugin records. */
|
||||
import { z } from 'zod'
|
||||
import { ToolCallId } from '@deepseek-ai/dsh-llm'
|
||||
import { pluginRecordOf, SessionLogOffset } from '@deepseek-ai/dsh-session'
|
||||
import type { ProjectionDefinition } from '@deepseek-ai/dsh-session-projection'
|
||||
|
||||
/** Model-facing name of the card tool. */
|
||||
export const PROPOSE_ACTION = 'propose_action'
|
||||
|
||||
/** Kind-defined JSON object of a proposal or decision. */
|
||||
export const fieldsSchema = z.record(z.string(), z.json())
|
||||
|
||||
/** Arguments of a `propose_action` call; blank titles and briefs create no card. */
|
||||
export const argumentsSchema = z.object({
|
||||
action: z.string().min(1),
|
||||
title: z.string().trim().min(1),
|
||||
brief: z.string().trim().min(1),
|
||||
details: fieldsSchema,
|
||||
})
|
||||
|
||||
const proposalSchema = z.object({
|
||||
callId: z.string().min(1).transform(ToolCallId),
|
||||
turn: z.number().int().nonnegative(),
|
||||
action: z.string().min(1),
|
||||
title: z.string().min(1),
|
||||
brief: z.string().min(1),
|
||||
details: fieldsSchema,
|
||||
}).strict()
|
||||
|
||||
/** Recorded decision of one card. */
|
||||
export const decisionSchema = z.object({
|
||||
callId: z.string().min(1).transform(ToolCallId),
|
||||
action: z.string().min(1),
|
||||
phase: z.string().min(1),
|
||||
data: fieldsSchema.optional(),
|
||||
}).strict()
|
||||
|
||||
const viewSchema = z.object({
|
||||
proposals: z.record(z.string(), proposalSchema),
|
||||
decisions: z.record(z.string(), decisionSchema),
|
||||
})
|
||||
|
||||
const stateSchema = z.object({
|
||||
/** Fork-inherited prefix length; inherited events create no proposals or decisions. */
|
||||
inheritedEventCount: z.number().int().nonnegative().max(Number.MAX_SAFE_INTEGER).transform(SessionLogOffset),
|
||||
view: viewSchema,
|
||||
/** `propose_action` calls of the open turn still waiting for their result. */
|
||||
calls: z.record(z.string(), proposalSchema.omit({ callId: true })),
|
||||
/** Turn of the latest admitted proposal; later calls of that turn create no card. */
|
||||
admittedTurn: z.number().int().nullable(),
|
||||
/** Decisions not yet reported to the model, by call id, with the seq of their record. */
|
||||
pendingStatus: z.record(z.string(), z.number()),
|
||||
/** User messages still queued for later turns, folded from inbox splices; the card tool compares it with its limit. */
|
||||
queued: z.number().int().nonnegative(),
|
||||
})
|
||||
|
||||
/** Fold state; `view` is also the Client wire value. */
|
||||
export type ActionCardState = z.infer<typeof stateSchema>
|
||||
|
||||
/** Type of {@link actionCardProjection}: the fold plus its Client view wire. */
|
||||
export type ActionCardProjectionDefinition = Omit<ProjectionDefinition<'actionCards', ActionCardState>, 'wire'> & {
|
||||
readonly wire: NonNullable<ProjectionDefinition<'actionCards', ActionCardState>['wire']>
|
||||
}
|
||||
|
||||
/**
|
||||
* Full-Session fold. A successful `propose_action` result admits the call as a card, at most one per turn;
|
||||
* the first admitted call of a turn wins. A newer card of any kind replaces every unstarted earlier card.
|
||||
* Events inherited by a forked Session create no proposals or decisions.
|
||||
*/
|
||||
export const actionCardProjection: ActionCardProjectionDefinition = {
|
||||
key: 'actionCards', stateVersion: 2, stateSchema,
|
||||
init: (_header, inheritedEventCount) => ({
|
||||
inheritedEventCount, view: { proposals: {}, decisions: {} }, calls: {}, admittedTurn: null, pendingStatus: {}, queued: 0,
|
||||
}),
|
||||
apply: (state, event) => {
|
||||
if (event.seq < state.inheritedEventCount) return state
|
||||
switch (event.type) {
|
||||
case 'turn/start':
|
||||
// A turn's calls settle inside it; a call left without a result never becomes a card.
|
||||
return Object.keys(state.calls).length === 0 ? state : { ...state, calls: {} }
|
||||
case 'agent/inbox/spliced':
|
||||
if (event.data.target !== 'next-turn') return state
|
||||
return { ...state, queued: Math.max(0, state.queued - (event.data.removedCount ?? 0) + event.data.inserted.length) }
|
||||
case 'user/message': {
|
||||
if (event.data.source.kind !== 'action-cards') return state
|
||||
const through = event.data.source.through
|
||||
return { ...state, pendingStatus: Object.fromEntries(Object.entries(state.pendingStatus).filter(([, seq]) => seq > through)) }
|
||||
}
|
||||
case 'tool/call': {
|
||||
if (event.data.name !== PROPOSE_ACTION) return state
|
||||
let raw: unknown
|
||||
try { raw = JSON.parse(event.data.arguments) }
|
||||
catch { return state } // Malformed model JSON failed in the tool too and creates no card.
|
||||
const parsed = argumentsSchema.safeParse(raw)
|
||||
if (!parsed.success) return state
|
||||
return { ...state, calls: { ...state.calls, [event.data.callId]: { turn: event.data.turn, ...parsed.data } } }
|
||||
}
|
||||
case 'tool/result': {
|
||||
const callId = event.data.message.toolCallId
|
||||
const call = Object.hasOwn(state.calls, callId) ? state.calls[callId] : undefined
|
||||
if (call === undefined) return state
|
||||
const calls = Object.fromEntries(Object.entries(state.calls).filter(([id]) => id !== callId))
|
||||
if (event.data.message.isError === true || state.admittedTurn === call.turn) return { ...state, calls }
|
||||
const decisions = { ...state.view.decisions }
|
||||
// A newer card supersedes every unstarted card; the model made that choice, so no status is reported.
|
||||
for (const earlier of Object.values(state.view.proposals)) {
|
||||
if (decisions[earlier.callId] === undefined) decisions[earlier.callId] = { callId: earlier.callId, action: earlier.action, phase: 'replaced' }
|
||||
}
|
||||
return { ...state, calls, admittedTurn: call.turn,
|
||||
view: { proposals: { ...state.view.proposals, [callId]: { callId, ...call } }, decisions } }
|
||||
}
|
||||
default: {
|
||||
const record = pluginRecordOf(event)
|
||||
if (record?.type !== 'plugin:action-cards/decision') return state
|
||||
// A malformed or newer record is skipped; throwing here would fail every later read of this Session.
|
||||
const decision = decisionSchema.safeParse(record.data)
|
||||
if (!decision.success) return state
|
||||
return { ...state, view: { ...state.view, decisions: { ...state.view.decisions, [decision.data.callId]: decision.data } },
|
||||
pendingStatus: { ...state.pendingStatus, [decision.data.callId]: event.seq } }
|
||||
}
|
||||
}
|
||||
},
|
||||
wire: { summary: false, viewSchema, view: (state: ActionCardState) => state.view },
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
/** Card proposals, recorded decisions and user-action results shared by every action kind. */
|
||||
import type { ContextFormed } from '@deepseek-ai/dsh-llm'
|
||||
import type { ToolCallId } from '@deepseek-ai/dsh-llm/brand'
|
||||
import type { SessionSeq } from '@deepseek-ai/dsh-session/types'
|
||||
import type { SessionProjectionSummaryExcluded } from '@deepseek-ai/dsh-session-projection/types'
|
||||
import type { JsonValue } from '@deepseek-ai/dsh-util-values'
|
||||
|
||||
/** Kind-defined JSON fields of a proposal or decision; each kind validates its own fields. */
|
||||
export type ActionCardFields = Readonly<Record<string, JsonValue>>
|
||||
|
||||
/** One card admitted from a successful `propose_action` call. */
|
||||
export interface ActionCardProposal {
|
||||
/** Id of the logged tool call. */
|
||||
readonly callId: ToolCallId
|
||||
/** Turn whose answer the card follows. */
|
||||
readonly turn: number
|
||||
/** Registered action kind named by the call. */
|
||||
readonly action: string
|
||||
readonly title: string
|
||||
/** What the action does, in the user's language. */
|
||||
readonly brief: string
|
||||
/** Fields the kind's skill asks for. */
|
||||
readonly details: ActionCardFields
|
||||
}
|
||||
|
||||
/**
|
||||
* Latest state of one card. Kinds define their own phases; `dismissed` is shared.
|
||||
* `replaced` (a later proposal superseded an unstarted card) is derived from the
|
||||
* log and never recorded.
|
||||
*/
|
||||
export interface ActionCardDecision {
|
||||
readonly callId: ToolCallId
|
||||
readonly action: string
|
||||
readonly phase: string
|
||||
/** Kind-defined fields such as a chosen location or a created package. */
|
||||
readonly data?: ActionCardFields | undefined
|
||||
}
|
||||
|
||||
/** Open-Session proposals and decisions by call id, excluded from Session summaries. */
|
||||
export interface ActionCardView {
|
||||
readonly proposals: Readonly<Record<string, ActionCardProposal>>
|
||||
readonly decisions: Readonly<Record<string, ActionCardDecision>>
|
||||
}
|
||||
|
||||
/**
|
||||
* Result of a user action. `accepted` starts background work that records its
|
||||
* own progress; `settled` returns the decision now in effect; `refused` changed
|
||||
* nothing; `unconfirmed` lost its outcome to an unloading owner, which the
|
||||
* kind reconciles when the Session reopens.
|
||||
*/
|
||||
export type ActionCardResult =
|
||||
| { readonly status: 'accepted' }
|
||||
| { readonly status: 'settled'; readonly decision: ActionCardDecision }
|
||||
| { readonly status: 'refused'; readonly reason: string }
|
||||
| { readonly status: 'unconfirmed'; readonly reason: string }
|
||||
|
||||
declare module '@deepseek-ai/dsh-llm' {
|
||||
interface MessageSourceMap {
|
||||
/** Card status notice; other readers preserve the recorded text without this plugin.
|
||||
* The producer uses through only to acknowledge delivered decisions.
|
||||
* @persistenceAttribution
|
||||
*/
|
||||
'action-cards': { kind: 'action-cards'; through: SessionSeq } & ContextFormed
|
||||
}
|
||||
}
|
||||
|
||||
declare module '@deepseek-ai/dsh-session/types' {
|
||||
interface PluginRecordMap {
|
||||
/** Dismissals and kind-defined progress of action cards. */
|
||||
'plugin:action-cards/decision': ActionCardDecision
|
||||
}
|
||||
}
|
||||
|
||||
declare module '@deepseek-ai/dsh-session-projection/types' {
|
||||
interface SessionProjectionMap {
|
||||
/** Action card proposals and decisions for the currently open Session. */
|
||||
actionCards: SessionProjectionSummaryExcluded<ActionCardView>
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
||||
|
||||
exports[`reports recorded decisions once on the next request, with each kind guidance once, without waking the conversation > status notice 1`] = `
|
||||
[
|
||||
{
|
||||
"text": "Latest status of action cards from user actions and background work. These are status facts, not a request to start or retry work. Use these receipts instead of the earlier proposal when describing progress. Failed runs can be retried from their card. Continue with the user’s current request.
|
||||
[{"action":"test_action","callId":"call-card-1","title":"Counter","phase":"failed","data":{"reason":"timeout"}},{"action":"test_action","callId":"call-card-2","title":"Second","phase":"dismissed"},{"action":"retired_action","callId":"call-orphan","phase":"done"}]",
|
||||
"type": "text",
|
||||
},
|
||||
]
|
||||
`;
|
||||
@@ -0,0 +1,36 @@
|
||||
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
||||
|
||||
exports[`declares propose_action from the step after a card skill loads, and logs the addition > tool declaration 1`] = `
|
||||
{
|
||||
"description": "Show the user one optional action card under this answer. Call only as the skill that names the action instructs.",
|
||||
"name": "propose_action",
|
||||
"parameters": {
|
||||
"properties": {
|
||||
"action": {
|
||||
"description": "Action name from the skill.",
|
||||
"type": "string",
|
||||
},
|
||||
"brief": {
|
||||
"description": "What the action does, in the user's language.",
|
||||
"type": "string",
|
||||
},
|
||||
"details": {
|
||||
"additionalProperties": true,
|
||||
"description": "Fields the skill lists for this action.",
|
||||
"type": "object",
|
||||
},
|
||||
"title": {
|
||||
"description": "Card title.",
|
||||
"type": "string",
|
||||
},
|
||||
},
|
||||
"required": [
|
||||
"action",
|
||||
"title",
|
||||
"brief",
|
||||
"details",
|
||||
],
|
||||
"type": "object",
|
||||
},
|
||||
}
|
||||
`;
|
||||
@@ -0,0 +1,167 @@
|
||||
import { expect, it, onTestFinished, vi } from 'vitest'
|
||||
import { z } from 'zod'
|
||||
import { ToolCallId } from '@deepseek-ai/dsh-llm'
|
||||
import type { Agent } from '@deepseek-ai/dsh-agent'
|
||||
import type { ActionCardProposalOf, ActionCardResult } from '../src/index.ts'
|
||||
import { ACTION, callId, fixture, proposal, type TestDetails } from './fixture.ts'
|
||||
|
||||
const dismissed = (data?: object) => ({ status: 'settled', decision: { callId, action: ACTION, phase: 'dismissed', ...data === undefined ? {} : { data } } })
|
||||
|
||||
it('refuses unknown cards, closed owners, verbs of removed kinds and undeclared verbs before any handler runs', async () => {
|
||||
const f = await fixture()
|
||||
expect(await f.ctx.actionCards.act(f.agent, callId, 'start')).toEqual({ status: 'refused', reason: 'unknown' })
|
||||
f.propose()
|
||||
for (const id of ['toString', 'constructor']) {
|
||||
expect(await f.ctx.actionCards.act(f.agent, ToolCallId(id), 'dismiss')).toEqual({ status: 'refused', reason: 'unknown' })
|
||||
}
|
||||
for (const verb of ['toString', 'missing']) {
|
||||
expect(await f.ctx.actionCards.act(f.agent, callId, verb)).toEqual({ status: 'refused', reason: 'unavailable' })
|
||||
}
|
||||
const roots = vi.spyOn(f.ctx.agents, 'roots').mockReturnValue([])
|
||||
expect(await f.ctx.actionCards.act(f.agent, callId, 'start')).toEqual({ status: 'refused', reason: 'not-live-root' })
|
||||
roots.mockRestore()
|
||||
await f.kindFiber.dispose()
|
||||
expect(await f.ctx.actionCards.act(f.agent, callId, 'start')).toEqual({ status: 'refused', reason: 'unavailable' })
|
||||
const service = f.ctx.actionCards
|
||||
await f.cards.dispose()
|
||||
expect(await service.act(f.agent, callId, 'dismiss')).toEqual({ status: 'refused', reason: 'closing' })
|
||||
expect(f.act).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('applies the shared access and read-only checks the kind declares, then hands typed details to the kind', async () => {
|
||||
const f = await fixture()
|
||||
f.propose()
|
||||
const access = vi.spyOn(f.ctx.remoteAccess, 'allows').mockReturnValue(false)
|
||||
expect(await f.ctx.actionCards.act(f.agent, callId, 'publish')).toEqual({ status: 'refused', reason: 'access-denied' })
|
||||
expect(await f.ctx.actionCards.act(f.agent, callId, 'start', { note: 'x' })).toEqual({ status: 'settled', decision: { callId, action: ACTION, phase: 'start' } })
|
||||
access.mockRestore()
|
||||
expect(f.act).toHaveBeenCalledWith(f.agent, { callId, turn: 1, ...proposal }, 'start', { note: 'x' })
|
||||
const resolve = vi.fn(() => ({ mode: 'read-only', workspaceRoot: '/' }))
|
||||
f.ctx.provide('sandboxPolicy', { resolve })
|
||||
expect(await f.ctx.actionCards.act(f.agent, callId, 'write')).toEqual({ status: 'refused', reason: 'read-only' })
|
||||
expect(resolve).toHaveBeenCalledWith({ session: f.agent.session })
|
||||
expect((await f.ctx.actionCards.act(f.agent, callId, 'publish')).status).toBe('settled')
|
||||
resolve.mockReturnValue({ mode: 'workspace-write', workspaceRoot: '/' })
|
||||
expect((await f.ctx.actionCards.act(f.agent, callId, 'write')).status).toBe('settled')
|
||||
f.propose(ToolCallId('call-invalid'), { ...proposal, details: { value: 3 } }, f.agent, 2)
|
||||
expect(await f.ctx.actionCards.act(f.agent, ToolCallId('call-invalid'), 'start')).toEqual({ status: 'refused', reason: 'unavailable' })
|
||||
expect(f.act).toHaveBeenCalledTimes(3)
|
||||
})
|
||||
|
||||
it('records dismissal of an unstarted or open card with the kind data, and settles started or final cards', async () => {
|
||||
const f = await fixture({
|
||||
openPhases: ['failed'],
|
||||
dismissal: (card, payload) => ({ value: card.details.value, ...z.object({ choice: z.string() }).safeParse(payload).data }),
|
||||
})
|
||||
f.propose()
|
||||
expect(await f.ctx.actionCards.act(f.agent, callId, 'dismiss', { choice: 'later' })).toEqual(dismissed({ value: 'a', choice: 'later' }))
|
||||
expect(f.view().decisions[callId]?.phase).toBe('dismissed')
|
||||
for (const verb of ['dismiss', 'start']) expect(await f.ctx.actionCards.act(f.agent, callId, verb)).toEqual(dismissed({ value: 'a', choice: 'later' }))
|
||||
f.ctx.actionCards.record(f.agent, { callId, action: ACTION, phase: 'failed' })
|
||||
expect(await f.ctx.actionCards.act(f.agent, callId, 'dismiss')).toEqual(dismissed({ value: 'a' }))
|
||||
f.ctx.actionCards.record(f.agent, { callId, action: ACTION, phase: 'running', data: { step: 1 } })
|
||||
expect(await f.ctx.actionCards.act(f.agent, callId, 'dismiss')).toEqual({ status: 'settled',
|
||||
decision: { callId, action: ACTION, phase: 'running', data: { step: 1 } } })
|
||||
f.propose(ToolCallId('call-invalid'), { ...proposal, details: { value: 3 } }, f.agent, 2)
|
||||
expect(await f.ctx.actionCards.act(f.agent, ToolCallId('call-invalid'), 'dismiss')).toEqual({ status: 'settled',
|
||||
decision: { callId: 'call-invalid', action: ACTION, phase: 'dismissed' } })
|
||||
expect(f.act).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('dismisses without data when the kind records none', async () => {
|
||||
const f = await fixture()
|
||||
f.propose()
|
||||
expect(await f.ctx.actionCards.act(f.agent, callId, 'dismiss', { choice: 'later' })).toEqual(dismissed())
|
||||
})
|
||||
|
||||
it('shares one operation between concurrent actions on a card and drains it on unload', async () => {
|
||||
const pending = Promise.withResolvers<ActionCardResult>()
|
||||
onTestFinished(() => { pending.resolve({ status: 'accepted' }) })
|
||||
const f = await fixture({ act: vi.fn(() => pending.promise) })
|
||||
f.propose()
|
||||
const first = f.ctx.actionCards.act(f.agent, callId, 'start')
|
||||
expect(f.ctx.actionCards.act(f.agent, callId, 'dismiss')).toBe(first)
|
||||
const disposing = f.cards.dispose()
|
||||
pending.resolve({ status: 'accepted' })
|
||||
expect(await first).toEqual({ status: 'accepted' })
|
||||
await disposing
|
||||
})
|
||||
|
||||
it('rejects a second kind for the same action and releases a kind through its disposer', async () => {
|
||||
const f = await fixture()
|
||||
const kind = (action: string) => ({ action, skill: 'other-skill', invitation: 'Invite the user.', details: z.object({}), verbs: { start: {} },
|
||||
act: () => Promise.resolve<ActionCardResult>({ status: 'accepted' }) })
|
||||
expect(() => f.ctx.actionCards.register(kind(ACTION))).toThrow('action-cards: action "test_action" is already registered')
|
||||
const unregister = f.ctx.actionCards.register(kind('other_action'))
|
||||
f.propose(ToolCallId('call-other'), { action: 'other_action', title: 'Other', brief: 'Other card.', details: {} })
|
||||
expect(await f.ctx.actionCards.act(f.agent, ToolCallId('call-other'), 'start')).toEqual({ status: 'accepted' })
|
||||
unregister()
|
||||
expect(await f.ctx.actionCards.act(f.agent, ToolCallId('call-other'), 'start')).toEqual({ status: 'refused', reason: 'unavailable' })
|
||||
})
|
||||
|
||||
it('lets the kind reconcile before every action, so a card that is no longer open settles instead of being dismissed', async () => {
|
||||
let finished = false
|
||||
const reconcile = vi.fn(async (agent: Agent, card: ActionCardProposalOf<TestDetails>) => {
|
||||
if (finished) f.ctx.actionCards.record(agent, { callId: card.callId, action: ACTION, phase: 'installed' })
|
||||
})
|
||||
const f = await fixture({ openPhases: ['unconfirmed'], reconcile })
|
||||
f.propose()
|
||||
f.ctx.actionCards.record(f.agent, { callId, action: ACTION, phase: 'unconfirmed' })
|
||||
finished = true
|
||||
const installed = { status: 'settled', decision: { callId, action: ACTION, phase: 'installed' } }
|
||||
expect(await f.ctx.actionCards.act(f.agent, callId, 'dismiss')).toEqual(installed)
|
||||
expect(reconcile).toHaveBeenCalledWith(f.agent, { callId, turn: 1, ...proposal })
|
||||
expect(f.view().decisions[callId]?.phase).toBe('installed')
|
||||
expect(await f.ctx.actionCards.act(f.agent, callId, 'start')).toEqual({ status: 'settled', decision: { callId, action: ACTION, phase: 'start' } })
|
||||
expect(reconcile).toHaveBeenCalledTimes(2)
|
||||
f.propose(ToolCallId('call-invalid'), { ...proposal, details: { value: 3 } }, f.agent, 2)
|
||||
expect((await f.ctx.actionCards.act(f.agent, ToolCallId('call-invalid'), 'dismiss')).status).toBe('settled')
|
||||
expect(reconcile).toHaveBeenCalledTimes(2)
|
||||
})
|
||||
|
||||
it('refuses the action when reconciliation fails or the root closes meanwhile', async () => {
|
||||
const reconcile = vi.fn<(agent: Agent) => Promise<void>>(async () => { throw new Error('profile read failed') })
|
||||
const f = await fixture({ reconcile })
|
||||
f.propose()
|
||||
const warn = vi.spyOn(f.ctx.logger, 'warn').mockImplementation(() => {})
|
||||
expect(await f.ctx.actionCards.act(f.agent, callId, 'dismiss')).toEqual({ status: 'refused', reason: 'unavailable' })
|
||||
expect(warn).toHaveBeenCalledWith('Cannot reconcile action card %s before %s: %s', callId, 'dismiss', 'Error: profile read failed')
|
||||
expect(await f.ctx.actionCards.act(f.agent, callId, 'start')).toEqual({ status: 'refused', reason: 'unavailable' })
|
||||
expect(warn).toHaveBeenLastCalledWith('Cannot reconcile action card %s before %s: %s', callId, 'start', 'Error: profile read failed')
|
||||
expect(f.view().decisions).toEqual({})
|
||||
reconcile.mockImplementationOnce(async () => { await f.agentHandle.dispose() })
|
||||
expect(await f.ctx.actionCards.act(f.agent, callId, 'dismiss')).toEqual({ status: 'refused', reason: 'not-live-root' })
|
||||
expect(f.act).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('refuses to record decisions of actions no kind registered or of phases the projection derives', async () => {
|
||||
const f = await fixture()
|
||||
f.propose()
|
||||
expect(() => { f.ctx.actionCards.record(f.agent, { callId, action: 'other_action', phase: 'done' }) })
|
||||
.toThrow('action-cards: cannot record a decision for unregistered action "other_action"')
|
||||
expect(() => { f.ctx.actionCards.record(f.agent, { callId, action: ACTION, phase: 'replaced' }) })
|
||||
.toThrow('action-cards: phase "replaced" is derived from the log and cannot be recorded')
|
||||
expect(f.view().decisions).toEqual({})
|
||||
// An unloading kind still records the outcome of work it had started.
|
||||
await f.kindFiber.dispose()
|
||||
f.ctx.actionCards.record(f.agent, { callId, action: ACTION, phase: 'interrupted' })
|
||||
expect(f.view().decisions[callId]?.phase).toBe('interrupted')
|
||||
})
|
||||
|
||||
it('dismisses an unstarted card whose kind is no longer registered, without data, and settles recorded ones', async () => {
|
||||
const f = await fixture({ openPhases: ['failed'], dismissal: () => ({ value: 'kind data' }) })
|
||||
f.propose(ToolCallId('call-failed'), proposal, f.agent, 1)
|
||||
f.ctx.actionCards.record(f.agent, { callId: ToolCallId('call-failed'), action: ACTION, phase: 'failed' })
|
||||
f.propose(ToolCallId('call-done'), proposal, f.agent, 2)
|
||||
f.ctx.actionCards.record(f.agent, { callId: ToolCallId('call-done'), action: ACTION, phase: 'dismissed' })
|
||||
f.propose(callId, proposal, f.agent, 3)
|
||||
await f.kindFiber.dispose()
|
||||
expect(await f.ctx.actionCards.act(f.agent, callId, 'dismiss', { choice: 'later' })).toEqual(dismissed())
|
||||
expect(f.view().decisions[callId]).toEqual({ callId, action: ACTION, phase: 'dismissed' })
|
||||
// The kind may return and act on its recorded phases, so they stay as they are.
|
||||
expect(await f.ctx.actionCards.act(f.agent, ToolCallId('call-failed'), 'dismiss')).toEqual({ status: 'settled',
|
||||
decision: { callId: 'call-failed', action: ACTION, phase: 'failed' } })
|
||||
expect(await f.ctx.actionCards.act(f.agent, ToolCallId('call-done'), 'dismiss')).toEqual({ status: 'settled',
|
||||
decision: { callId: 'call-done', action: ACTION, phase: 'dismissed' } })
|
||||
expect(f.act).not.toHaveBeenCalled()
|
||||
})
|
||||
@@ -0,0 +1,73 @@
|
||||
/** Real Agent, Tools, skills and projections with the card service and one scripted test kind. */
|
||||
import { Context } from '@deepseek-ai/cordis'
|
||||
import { onTestFinished, vi } from 'vitest'
|
||||
import { z } from 'zod'
|
||||
import { createToolResultMessage, ToolCallId } from '@deepseek-ai/dsh-llm'
|
||||
import { SessionId, type SessionEvent } from '@deepseek-ai/dsh-session'
|
||||
import { mountAgentLoopTestDependencies, mountAgentLoopTestHarness } from '@deepseek-ai/dsh-agent-loop-testkit'
|
||||
import Skills, { BUNDLED_SKILL_RANK } from '@deepseek-ai/dsh-skill'
|
||||
import * as SkillTool from '@deepseek-ai/dsh-tool-skill'
|
||||
import RemoteAccess from '@deepseek-ai/dsh-api-remote-access'
|
||||
import type { Agent } from '@deepseek-ai/dsh-agent'
|
||||
import ActionCards from '../src/index.ts'
|
||||
import type { ActionCardFields, ActionCardKind, ActionCardProposalOf, ActionCardResult } from '../src/index.ts'
|
||||
|
||||
export const ACTION = 'test_action'
|
||||
export const SKILL = 'test-skill'
|
||||
export const INVITATION = 'Invite the user to try the card in one sentence.'
|
||||
export const callId = ToolCallId('call-card-1')
|
||||
export const proposal = { action: ACTION, title: 'Counter', brief: 'Keep a counter visible.', details: { value: 'a' } }
|
||||
|
||||
/** Details of the test kind. */
|
||||
export interface TestDetails { readonly value: string }
|
||||
|
||||
/** Provide one model-invocable skill per name. */
|
||||
export function provideSkills(ctx: Context, ...names: string[]): void {
|
||||
ctx.skills.registerProvider(() => ({
|
||||
name: 'card-skills',
|
||||
list: () => Promise.resolve(names.map(name => ({
|
||||
name, description: `Use ${name}.`, provider: 'card-skills', source: 'bundled' as const, rank: BUNDLED_SKILL_RANK, locator: null,
|
||||
invocation: { modelInvocable: true, userInvocable: false },
|
||||
}))),
|
||||
get: candidate => Promise.resolve({ name: candidate.name, description: candidate.description, provider: 'card-skills', source: 'bundled' as const,
|
||||
invocation: candidate.invocation, content: `Call propose_action for ${candidate.name}.` }),
|
||||
}))
|
||||
}
|
||||
|
||||
/** Mount the card service with one registered kind whose handler is a spy. */
|
||||
export async function fixture(kind: Partial<ActionCardKind<TestDetails>> = {}) {
|
||||
const ctx = new Context()
|
||||
onTestFinished(async () => { await ctx.fiber.dispose() })
|
||||
await mountAgentLoopTestDependencies(ctx, { workingDirectory: true })
|
||||
const harness = await mountAgentLoopTestHarness(ctx)
|
||||
await ctx.plugin(RemoteAccess)
|
||||
await ctx.plugin(Skills)
|
||||
await ctx.plugin(SkillTool)
|
||||
provideSkills(ctx, SKILL, 'other-skill')
|
||||
const cards = await ctx.plugin(ActionCards)
|
||||
type Handler = (
|
||||
agent: Agent, card: ActionCardProposalOf<TestDetails>, verb: string, payload: ActionCardFields | undefined,
|
||||
) => Promise<ActionCardResult>
|
||||
const act = vi.fn<Handler>(async (_agent, card, verb) =>
|
||||
({ status: 'settled', decision: { callId: card.callId, action: ACTION, phase: verb } }))
|
||||
const kindFiber = await ctx.plugin({ name: 'test-kind', inject: ['actionCards'], apply: (inner: Context) => {
|
||||
inner.actionCards.register({
|
||||
action: ACTION, skill: SKILL, invitation: INVITATION, details: z.object({ value: z.string() }),
|
||||
verbs: { start: {}, publish: { global: true }, write: { writes: true } },
|
||||
act, ...kind,
|
||||
})
|
||||
} })
|
||||
const agentHandle = await ctx.agents.create({ sessionId: SessionId('cards-root') })
|
||||
const agent = agentHandle.agent
|
||||
const events: SessionEvent[] = []
|
||||
ctx.on('session/event', (session, event) => { if (session === agent.session) events.push(event) })
|
||||
let step = 0
|
||||
/** Log a successful `propose_action` call, as the loop does after the tool accepts it. */
|
||||
const propose = (id: ToolCallId = callId, args: object = proposal, caller = agent, turn = 1) => {
|
||||
caller.session.append('tool/call', { turn, step: ++step, callId: id, name: 'propose_action', arguments: JSON.stringify(args) })
|
||||
caller.session.append('tool/result', { turn, step, message: createToolResultMessage({ callId: id, content: [], isError: false }) }, { surfaceOp: 'append' })
|
||||
return id
|
||||
}
|
||||
const view = (caller = agent) => ctx.actionCards.view(caller.session)
|
||||
return { ctx, harness, cards, kindFiber, agent, agentHandle, events, act, propose, view }
|
||||
}
|
||||
@@ -0,0 +1,130 @@
|
||||
import { expect, it } from 'vitest'
|
||||
import { createToolResultMessage, createUserMessage, ToolCallId } from '@deepseek-ai/dsh-llm'
|
||||
import {
|
||||
appendPluginRecord, Session, SESSION_FORMAT_VERSION, SessionId, SessionLogOffset, SessionSeq, type SessionEvent, type SessionHeader,
|
||||
} from '@deepseek-ai/dsh-session'
|
||||
import { actionCardProjection, type ActionCardState } from '../src/projection.ts'
|
||||
import type { ActionCardDecision } from '../src/types.ts'
|
||||
|
||||
const projection = actionCardProjection
|
||||
const args = { action: 'test_action', title: 'Counter', brief: 'Keep count visible', details: { value: 'a' } }
|
||||
let seq = 0
|
||||
|
||||
function init(inherited = 0): ActionCardState {
|
||||
const header: SessionHeader = { version: SESSION_FORMAT_VERSION, id: SessionId('cards'), createdAt: 0, isSeeded: inherited > 0 }
|
||||
return projection.init(header, SessionLogOffset(inherited))
|
||||
}
|
||||
|
||||
function turn(value: number): SessionEvent<'turn/start'> {
|
||||
return { type: 'turn/start', seq: SessionSeq(seq++), time: 0, data: { turn: value } }
|
||||
}
|
||||
|
||||
function call(callId: string, value: object | string = args, turnNumber = 1, name = 'propose_action'): SessionEvent<'tool/call'> {
|
||||
return { type: 'tool/call', seq: SessionSeq(seq++), time: 0,
|
||||
data: { turn: turnNumber, step: 1, callId: ToolCallId(callId), name, arguments: typeof value === 'string' ? value : JSON.stringify(value) } }
|
||||
}
|
||||
|
||||
function result(callId: string, isError = false, turnNumber = 1): SessionEvent<'tool/result'> {
|
||||
return { type: 'tool/result', seq: SessionSeq(seq++), time: 0, surfaceOp: 'append',
|
||||
data: { turn: turnNumber, step: 1, message: createToolResultMessage({ callId: ToolCallId(callId), content: [], isError }) } }
|
||||
}
|
||||
|
||||
function spliced(inserted: number, removedCount?: number, target: 'next-turn' | 'next-step' = 'next-turn'): SessionEvent<'agent/inbox/spliced'> {
|
||||
return { type: 'agent/inbox/spliced', seq: SessionSeq(seq++), time: 0, data: { target, start: 0, ...removedCount === undefined ? {} : { removedCount },
|
||||
inserted: Array.from({ length: inserted }, () => createUserMessage({ content: [{ type: 'text', text: 'next' }], source: { kind: 'user' } })) } }
|
||||
}
|
||||
|
||||
function records(...data: ActionCardDecision[]): readonly SessionEvent[] {
|
||||
const session = Session.create(SessionId('records'))
|
||||
for (const value of data) appendPluginRecord(session, 'plugin:action-cards/decision', value)
|
||||
return session.snapshotEvents()
|
||||
}
|
||||
|
||||
const fold = (events: readonly SessionEvent[], state = init()) => events.reduce(projection.apply, state)
|
||||
|
||||
it('admits a successful propose_action call as a card in its turn and ignores failed, malformed and other calls', () => {
|
||||
const state = fold([turn(1), call('c1'), result('c1')])
|
||||
expect(state.view.proposals).toEqual({ c1: { callId: 'c1', turn: 1, ...args } })
|
||||
expect(state.calls).toEqual({})
|
||||
for (const events of [
|
||||
[call('c2'), result('c2', true)],
|
||||
[call('c3', '{broken')],
|
||||
[call('c4', { ...args, title: ' ' })],
|
||||
[call('c5', { ...args, details: 'text' })],
|
||||
[call('c6', args, 1, 'other_tool'), result('c6')],
|
||||
[result('unrelated')],
|
||||
]) {
|
||||
expect(fold(events).view.proposals).toEqual({})
|
||||
}
|
||||
const trimmed = fold([call('c7', { ...args, title: ' Counter ' }), result('c7')])
|
||||
expect(trimmed.view.proposals.c7?.title).toBe('Counter')
|
||||
const pending = fold([call('c8')])
|
||||
expect(Object.keys(pending.calls)).toEqual(['c8'])
|
||||
expect(projection.apply(pending, turn(2)).calls).toEqual({})
|
||||
const idle = fold([turn(3)])
|
||||
expect(projection.apply(idle, turn(4))).toBe(idle)
|
||||
})
|
||||
|
||||
it('keeps the first admitted card of a turn and replaces only unstarted earlier cards', () => {
|
||||
const first = fold([turn(1), call('a'), result('a')])
|
||||
const late = fold([call('b'), result('b')], first)
|
||||
expect(Object.keys(late.view.proposals)).toEqual(['a'])
|
||||
const next = fold([turn(2), call('c', args, 2), result('c', false, 2)], first)
|
||||
expect(next.view.decisions).toEqual({ a: { callId: 'a', action: 'test_action', phase: 'replaced' } })
|
||||
const started = fold(records({ callId: ToolCallId('a'), action: 'test_action', phase: 'creating' }), first)
|
||||
const afterStart = fold([turn(2), call('c', args, 2), result('c', false, 2)], started)
|
||||
expect(afterStart.view.decisions.a?.phase).toBe('creating')
|
||||
expect(afterStart.view.decisions.c).toBeUndefined()
|
||||
// Replacement crosses kinds: a card of another action replaces the unstarted one too.
|
||||
const other = fold([turn(2), call('d', { ...args, action: 'other_action' }, 2), result('d', false, 2)], first)
|
||||
expect(other.view.decisions).toEqual({ a: { callId: 'a', action: 'test_action', phase: 'replaced' } })
|
||||
})
|
||||
|
||||
it('counts user messages queued for later turns for the card tool and leaves cards to it', () => {
|
||||
const queued = fold([turn(1), spliced(1, undefined, 'next-step'), spliced(2), call('a'), result('a')])
|
||||
expect(queued.queued).toBe(2)
|
||||
expect(Object.keys(queued.view.proposals)).toEqual(['a'])
|
||||
expect(queued.view.decisions).toEqual({})
|
||||
expect(fold([spliced(0, 2)], queued).queued).toBe(0)
|
||||
expect(fold([spliced(0, 5)]).queued).toBe(0)
|
||||
})
|
||||
|
||||
it('ignores the events a forked Session inherits from its parent', () => {
|
||||
const parent = [turn(1), call('a'), result('a')]
|
||||
// Every event created so far precedes the fork point.
|
||||
const inherited = init(seq)
|
||||
expect(fold(parent, inherited)).toBe(inherited)
|
||||
const own = fold([turn(2), call('b', args, 2), result('b', false, 2)], inherited)
|
||||
expect(Object.keys(own.view.proposals)).toEqual(['b'])
|
||||
expect(own.view.decisions).toEqual({})
|
||||
})
|
||||
|
||||
it('records valid decisions as pending status until a status notice acknowledges them', () => {
|
||||
const [created, malformed, dismissed] = records(
|
||||
{ callId: ToolCallId('a'), action: 'test_action', phase: 'creating', data: { value: 1 } },
|
||||
{ callId: ToolCallId('a'), action: 'test_action', phase: '' },
|
||||
{ callId: ToolCallId('b'), action: 'test_action', phase: 'dismissed' },
|
||||
)
|
||||
const state = fold([created!, malformed!, dismissed!])
|
||||
expect(state.view.decisions).toEqual({
|
||||
a: { callId: 'a', action: 'test_action', phase: 'creating', data: { value: 1 } },
|
||||
b: { callId: 'b', action: 'test_action', phase: 'dismissed' },
|
||||
})
|
||||
expect(state.pendingStatus).toEqual({ a: created!.seq, b: dismissed!.seq })
|
||||
const notice = (through: number): SessionEvent<'user/message'> => ({ type: 'user/message', seq: SessionSeq(99), time: 0, surfaceOp: 'append',
|
||||
data: createUserMessage({ content: [{ type: 'text', text: 'status' }],
|
||||
source: { kind: 'action-cards', through: SessionSeq(through), form: 'notice', summary: 'status' } }) })
|
||||
expect(projection.apply(state, notice(created!.seq)).pendingStatus).toEqual({ b: dismissed!.seq })
|
||||
const user: SessionEvent<'user/message'> = { type: 'user/message', seq: SessionSeq(100), time: 0, surfaceOp: 'append',
|
||||
data: createUserMessage({ content: [{ type: 'text', text: 'hi' }], source: { kind: 'user' } }) }
|
||||
expect(projection.apply(state, user)).toBe(state)
|
||||
})
|
||||
|
||||
it('publishes proposals and decisions as one view reused across internal state changes', () => {
|
||||
const state = fold([turn(1), call('a'), result('a')])
|
||||
const view = projection.wire.view(state)
|
||||
expect(view).toBe(state.view)
|
||||
expect(projection.wire.viewSchema.parse(view)).toEqual(view)
|
||||
expect(projection.wire.view(fold([spliced(1), call('pending')], state))).toBe(view)
|
||||
expect(projection.stateSchema.parse(state)).toEqual(state)
|
||||
})
|
||||
@@ -0,0 +1,71 @@
|
||||
import { expect, it, vi } from 'vitest'
|
||||
import { agentEvents, type Agent, type PreStepDecision } from '@deepseek-ai/dsh-agent'
|
||||
import { ToolCallId } from '@deepseek-ai/dsh-llm'
|
||||
import { appendPluginRecord } from '@deepseek-ai/dsh-session'
|
||||
import ActionCards from '../src/index.ts'
|
||||
import { ACTION, callId, fixture } from './fixture.ts'
|
||||
|
||||
type Fixture = Awaited<ReturnType<typeof fixture>>
|
||||
|
||||
async function prepare(f: Fixture, agent: Agent = f.agent, signal = new AbortController().signal, admitted?: () => void | Promise<void>) {
|
||||
const decision = await agentEvents(f.ctx, agent).waterfall('agent/pre-step', { messages: [], turn: 2, step: 1, signal, modelSelection: { provider: 'mock', model: 'mock' } },
|
||||
async (): Promise<PreStepDecision> => { await admitted?.(); return { kind: 'enter', messages: [] } })
|
||||
return decision.kind === 'reject' ? decision : { ...decision, messages: decision.messages.filter(message => message.source.kind === 'action-cards') }
|
||||
}
|
||||
|
||||
function enter(agent: Agent, decision: PreStepDecision): void {
|
||||
if (decision.kind === 'enter') for (const message of decision.messages) agent.session.append('user/message', message, { surfaceOp: 'append' })
|
||||
}
|
||||
|
||||
it('reports recorded decisions once on the next request, with each kind guidance once, without waking the conversation', async () => {
|
||||
const f = await fixture({ statusGuidance: 'Failed runs can be retried from their card.', statusFields: ['reason'] })
|
||||
const followup = vi.spyOn(f.agent, 'followup')
|
||||
expect(await prepare(f)).toEqual({ kind: 'enter', messages: [] })
|
||||
f.propose()
|
||||
f.propose(ToolCallId('call-card-2'), { action: ACTION, title: 'Second', brief: 'Another card.', details: { value: 'b' } }, f.agent, 2)
|
||||
expect(await prepare(f)).toEqual({ kind: 'enter', messages: [] })
|
||||
f.ctx.actionCards.record(f.agent, { callId, action: ACTION, phase: 'failed', data: { reason: 'timeout', internal: 'x' } })
|
||||
f.ctx.actionCards.record(f.agent, { callId: ToolCallId('call-card-2'), action: ACTION, phase: 'dismissed' })
|
||||
// A decision logged by a kind that is no longer registered is still reported.
|
||||
appendPluginRecord(f.agent.session, 'plugin:action-cards/decision', { callId: ToolCallId('call-orphan'), action: 'retired_action', phase: 'done' })
|
||||
const decision = await prepare(f)
|
||||
if (decision.kind !== 'enter') throw new Error('request was rejected')
|
||||
expect(decision.messages).toHaveLength(1)
|
||||
expect(decision.messages[0]!.source).toMatchObject({ kind: 'action-cards', form: 'notice', summary: 'Action card status updated' })
|
||||
expect(decision.messages[0]!.content).toMatchSnapshot('status notice')
|
||||
enter(f.agent, decision)
|
||||
expect(await prepare(f)).toEqual({ kind: 'enter', messages: [] })
|
||||
expect(followup).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('keeps undelivered status through rejection, cancellation and plugin reload', async () => {
|
||||
const f = await fixture()
|
||||
f.propose()
|
||||
await f.ctx.actionCards.act(f.agent, callId, 'dismiss')
|
||||
const cancelled = new AbortController()
|
||||
await expect(prepare(f, f.agent, cancelled.signal, () => { cancelled.abort() })).rejects.toThrow()
|
||||
const rejected = f.ctx.on('agent/pre-step', async (): Promise<PreStepDecision> => ({ kind: 'reject' }))
|
||||
expect((await prepare(f)).kind).toBe('reject')
|
||||
rejected()
|
||||
expect(await prepare(f, f.agent, undefined, async () => { await f.cards.dispose() })).toEqual({ kind: 'enter', messages: [] })
|
||||
await f.ctx.plugin(ActionCards, { queuedMessageLimit: 3 })
|
||||
const decision = await prepare(f)
|
||||
if (decision.kind !== 'enter') throw new Error('request was rejected')
|
||||
expect(JSON.stringify(decision.messages[0]!.content)).toContain('dismissed')
|
||||
})
|
||||
|
||||
it('adds nothing when cancellation arrives after downstream preparation', async () => {
|
||||
const f = await fixture()
|
||||
f.propose()
|
||||
await f.ctx.actionCards.act(f.agent, callId, 'dismiss')
|
||||
await f.cards.dispose()
|
||||
const controller = new AbortController()
|
||||
// Prepended before the card service returns, so it runs right after the service's own listener.
|
||||
f.ctx.on('agent/pre-step', async (_event, next) => {
|
||||
const decision = await next()
|
||||
controller.abort()
|
||||
return decision
|
||||
}, { prepend: true })
|
||||
await f.ctx.plugin(ActionCards)
|
||||
expect(await prepare(f, f.agent, controller.signal)).toEqual({ kind: 'enter', messages: [] })
|
||||
})
|
||||
@@ -0,0 +1,198 @@
|
||||
import { expect, it, vi } from 'vitest'
|
||||
import { createUserMessage, ToolCallId } from '@deepseek-ai/dsh-llm'
|
||||
import { SessionId } from '@deepseek-ai/dsh-session'
|
||||
import type { ToolExecutionToken } from '@deepseek-ai/dsh-tools'
|
||||
import { executeModelToolFixture, executeToolFixture } from '@deepseek-ai/dsh-tool-testkit'
|
||||
import type { Agent } from '@deepseek-ai/dsh-agent'
|
||||
import { MockAdapter, textResponse, toolCallResponse } from '../../../core/agent-loop/tests/mock-adapter.ts'
|
||||
import { z } from 'zod'
|
||||
import type { ActionCardKind, ActionCardResult } from '../src/index.ts'
|
||||
import { ACTION, fixture, INVITATION, proposal, SKILL, type TestDetails } from './fixture.ts'
|
||||
|
||||
type Fixture = Awaited<ReturnType<typeof fixture>>
|
||||
const signal = new AbortController().signal
|
||||
const modelSelection = { provider: 'mock', model: 'mock' }
|
||||
|
||||
/** Run one call through the executor with the step admission the loop would resolve. */
|
||||
async function call(f: Fixture, name: string, args: object, id: string, agent: Agent = f.agent, parent?: ToolExecutionToken) {
|
||||
const toolSet = await f.ctx.tools.resolve({ agent, modelSelection, signal })
|
||||
try {
|
||||
return parent === undefined
|
||||
? await executeModelToolFixture(f.ctx, { callId: ToolCallId(id), name, arguments: args, agent, signal, toolSet })
|
||||
: await executeToolFixture(f.ctx, { callId: ToolCallId(id), name, arguments: args, agent, signal, toolSet, parent })
|
||||
} finally { toolSet.dispose() }
|
||||
}
|
||||
|
||||
async function declared(f: Fixture, agent: Agent = f.agent): Promise<boolean> {
|
||||
const toolSet = await f.ctx.tools.resolve({ agent, modelSelection, signal })
|
||||
const visible = toolSet.view(agent).has('propose_action')
|
||||
toolSet.dispose()
|
||||
return visible
|
||||
}
|
||||
|
||||
function text(result: { content: readonly { type: string; text?: string }[] }): string {
|
||||
return result.content.map(block => block.text ?? '').join('')
|
||||
}
|
||||
|
||||
it('declares propose_action from the step after a card skill loads, and logs the addition', async () => {
|
||||
const f = await fixture()
|
||||
const adapter = new MockAdapter([
|
||||
toolCallResponse('call-skill', 'skill', { name: SKILL }),
|
||||
toolCallResponse('call-card-1', 'propose_action', proposal),
|
||||
textResponse('The card is below.'),
|
||||
])
|
||||
f.ctx.llm.registerAdapter(['mock'], adapter)
|
||||
const agent = await f.harness.create(SessionId('loop'), modelSelection)
|
||||
expect(await declared(f, agent)).toBe(false)
|
||||
agent.followup(createUserMessage({ content: [{ type: 'text', text: 'I want a counter.' }], source: { kind: 'user' } }))
|
||||
await agent.whenIdle()
|
||||
expect(adapter.requests.map(request => (request.tools ?? []).some(tool => tool.name === 'propose_action'))).toEqual([false, true, true])
|
||||
const tool = adapter.requests[1]!.tools!.find(candidate => candidate.name === 'propose_action')
|
||||
expect(tool).toMatchSnapshot('tool declaration')
|
||||
expect(agent.session.snapshotEvents().flatMap(event => event.type === 'developer/message' ? event.data.message.content : []))
|
||||
.toEqual([{ type: 'tool-addition', toolName: 'propose_action' }])
|
||||
expect(await declared(f, agent)).toBe(true)
|
||||
const result = agent.session.snapshotEvents().find(event => event.type === 'tool/result' && event.data.message.toolCallId === 'call-card-1')
|
||||
expect(result?.type === 'tool/result' && result.data.message.content).toEqual([
|
||||
{ type: 'text', text: `Card shown below your answer. Do not restate it. ${INVITATION}` },
|
||||
])
|
||||
expect(f.view(agent).proposals['call-card-1']).toEqual({ callId: 'call-card-1', turn: 1, ...proposal })
|
||||
})
|
||||
|
||||
it('declares nothing for other skills and stops declaring when the kind unregisters', async () => {
|
||||
const f = await fixture()
|
||||
f.agent.session.append('turn/start', { turn: 1 })
|
||||
expect((await call(f, 'skill', { name: 'other-skill' }, 'other')).isError).toBe(false)
|
||||
expect((await call(f, 'skill', { name: 'missing-skill' }, 'missing')).isError).toBe(true)
|
||||
expect(await declared(f)).toBe(false)
|
||||
expect((await call(f, 'propose_action', proposal, 'early')).isError).toBe(true)
|
||||
expect((await call(f, 'skill', { name: SKILL }, 'load')).isError).toBe(false)
|
||||
expect((await call(f, 'skill', { name: SKILL }, 'reload')).isError).toBe(false)
|
||||
expect((await executeToolFixture(f.ctx, { callId: ToolCallId('detached'), name: 'skill', arguments: { name: SKILL }, signal })).isError).toBe(false)
|
||||
expect(await declared(f)).toBe(true)
|
||||
await f.kindFiber.dispose()
|
||||
expect(await declared(f)).toBe(false)
|
||||
await f.cards.dispose()
|
||||
expect(f.ctx.tools.get('propose_action')).toBeUndefined()
|
||||
})
|
||||
|
||||
it('refuses unknown actions, a skill not loaded in this turn, blank fields, invalid details and nested calls', async () => {
|
||||
const f = await fixture()
|
||||
f.agent.session.append('turn/start', { turn: 1 })
|
||||
await call(f, 'skill', { name: SKILL }, 'load')
|
||||
expect(text(await call(f, 'propose_action', { ...proposal, action: 'nope' }, 'unknown'))).toBe('Error: Unknown action "nope". Registered actions: test_action.')
|
||||
expect(text(await call(f, 'propose_action', { ...proposal, title: ' ' }, 'blank'))).toBe('Error: Write a title and a brief.')
|
||||
expect(text(await call(f, 'propose_action', { ...proposal, brief: '' }, 'blank-brief'))).toBe('Error: Write a title and a brief.')
|
||||
expect(text(await call(f, 'propose_action', { ...proposal, details: { value: 1 } }, 'invalid')))
|
||||
.toBe('Error: Invalid details: details.value: Invalid input: expected string, received number')
|
||||
expect(text(await call(f, 'propose_action', proposal, 'nested', f.agent, Symbol('outer') as ToolExecutionToken)))
|
||||
.toBe('Error: Call propose_action directly, not from code.')
|
||||
f.agent.session.append('turn/start', { turn: 2 })
|
||||
expect(text(await call(f, 'propose_action', proposal, 'stale'))).toBe('Error: Load skill test-skill first, then call propose_action.')
|
||||
await f.kindFiber.dispose()
|
||||
await call(f, 'skill', { name: SKILL }, 'load-again')
|
||||
expect(await declared(f)).toBe(false)
|
||||
expect(Object.keys(f.view().proposals)).toEqual([])
|
||||
})
|
||||
|
||||
it('accepts one card per turn, admits a retry after a failed result and names the registered actions', async () => {
|
||||
const f = await fixture()
|
||||
f.agent.session.append('turn/start', { turn: 1 })
|
||||
await call(f, 'skill', { name: SKILL }, 'load')
|
||||
const blocked = f.ctx.on('tools/post-execute', async (exec, _result, next) => exec.callId === 'blocked'
|
||||
? { kind: 'block', feedback: [{ type: 'text', text: 'blocked' }] } : await next())
|
||||
expect((await call(f, 'propose_action', proposal, 'blocked')).isError).toBe(true)
|
||||
blocked()
|
||||
const accepted = await call(f, 'propose_action', { ...proposal, title: ' Counter ' }, 'accepted')
|
||||
expect(accepted).toMatchObject({ isError: false, value: { action: ACTION, title: 'Counter', invitation: INVITATION } })
|
||||
expect(text(accepted)).toBe(`Card shown below your answer. Do not restate it. ${INVITATION}`)
|
||||
const second = text(await call(f, 'propose_action', proposal, 'second'))
|
||||
// Only an accepted call tells the model how to invite the user to its card.
|
||||
expect(second).toBe('Error: One card per turn; the earlier card stands.')
|
||||
expect(second).not.toContain(INVITATION)
|
||||
f.agent.session.append('turn/start', { turn: 2 })
|
||||
await call(f, 'skill', { name: SKILL }, 'load-2')
|
||||
f.propose(ToolCallId('logged'), proposal, f.agent, 2)
|
||||
expect(text(await call(f, 'propose_action', proposal, 'after-log'))).toBe('Error: One card per turn; the earlier card stands.')
|
||||
// Disposing the agent releases its activation.
|
||||
expect(await declared(f)).toBe(true)
|
||||
await f.agentHandle.dispose()
|
||||
expect(await declared(f)).toBe(false)
|
||||
})
|
||||
|
||||
it('activates nothing for a skill load dispatched from code, so a PTC preset never declares the tool', async () => {
|
||||
const f = await fixture()
|
||||
f.agent.session.append('turn/start', { turn: 1 })
|
||||
const outer = Symbol('outer') as ToolExecutionToken
|
||||
expect((await call(f, 'skill', { name: SKILL }, 'nested-load', f.agent, outer)).isError).toBe(false)
|
||||
expect(await declared(f)).toBe(false)
|
||||
expect((await call(f, 'propose_action', proposal, 'unadmitted')).isError).toBe(true)
|
||||
expect((await call(f, 'skill', { name: SKILL }, 'direct-load')).isError).toBe(false)
|
||||
expect(await declared(f)).toBe(true)
|
||||
})
|
||||
|
||||
it('offers cards in the main conversation only: subagent skill loads activate nothing and non-root calls are refused', async () => {
|
||||
const f = await fixture()
|
||||
const child = (await f.ctx.agents.create({ sessionId: SessionId('cards-child'), parentAgent: f.agent,
|
||||
meta: { parentSession: f.agent.id, origin: 'subagent' } })).agent
|
||||
child.session.append('turn/start', { turn: 1 })
|
||||
expect((await call(f, 'skill', { name: SKILL }, 'child-load', child)).isError).toBe(false)
|
||||
expect(await declared(f, child)).toBe(false)
|
||||
expect((await call(f, 'propose_action', proposal, 'child-card', child)).isError).toBe(true)
|
||||
f.agent.session.append('turn/start', { turn: 1 })
|
||||
await call(f, 'skill', { name: SKILL }, 'load')
|
||||
// Admission is fixed when the step starts; the call still checks that its agent is a live root.
|
||||
const toolSet = await f.ctx.tools.resolve({ agent: f.agent, modelSelection, signal })
|
||||
vi.spyOn(f.ctx.agents, 'roots').mockReturnValue([])
|
||||
const refused = await executeModelToolFixture(f.ctx, { callId: ToolCallId('detached-root'), name: 'propose_action', arguments: proposal,
|
||||
agent: f.agent, signal, toolSet })
|
||||
toolSet.dispose()
|
||||
expect(text(refused)).toBe('Error: Cards are offered in the main conversation only.')
|
||||
})
|
||||
|
||||
it('names no actions when the last kind unregisters after the step admitted the tool', async () => {
|
||||
const f = await fixture()
|
||||
f.agent.session.append('turn/start', { turn: 1 })
|
||||
await call(f, 'skill', { name: SKILL }, 'load')
|
||||
const toolSet = await f.ctx.tools.resolve({ agent: f.agent, modelSelection, signal })
|
||||
await f.kindFiber.dispose()
|
||||
const result = await executeModelToolFixture(f.ctx, { callId: ToolCallId('late'), name: 'propose_action', arguments: proposal,
|
||||
agent: f.agent, signal, toolSet })
|
||||
toolSet.dispose()
|
||||
expect(text(result)).toBe('Error: Unknown action "test_action". Registered actions: none.')
|
||||
})
|
||||
|
||||
it('refuses a card while the user has queued messages for later turns, so the log holds no card', async () => {
|
||||
const f = await fixture()
|
||||
const queued = () => createUserMessage({ content: [{ type: 'text', text: 'Next question.' }], source: { kind: 'user' } })
|
||||
const live: { agent?: Agent } = {}
|
||||
const adapter = new MockAdapter([
|
||||
toolCallResponse('call-skill', 'skill', { name: SKILL }),
|
||||
() => {
|
||||
// The user queues two more messages while the model writes its answer.
|
||||
live.agent!.inbox.append('next-turn', queued())
|
||||
live.agent!.inbox.append('next-turn', queued())
|
||||
return toolCallResponse('call-card-1', 'propose_action', proposal)
|
||||
},
|
||||
textResponse('Short answer.'),
|
||||
textResponse('Next answer.'),
|
||||
textResponse('Last answer.'),
|
||||
])
|
||||
f.ctx.llm.registerAdapter(['mock'], adapter)
|
||||
const agent = await f.harness.create(SessionId('queued'), modelSelection)
|
||||
live.agent = agent
|
||||
agent.followup(createUserMessage({ content: [{ type: 'text', text: 'I want a counter.' }], source: { kind: 'user' } }))
|
||||
await agent.whenIdle()
|
||||
const result = agent.session.snapshotEvents().find(event => event.type === 'tool/result' && event.data.message.toolCallId === 'call-card-1')
|
||||
expect(result?.type === 'tool/result' && result.data.message).toMatchObject({ isError: true,
|
||||
content: [{ type: 'text', text: 'Error: The user has queued more messages; show no card and answer briefly.' }] })
|
||||
expect(f.view(agent)).toEqual({ proposals: {}, decisions: {} })
|
||||
})
|
||||
|
||||
it('requires every kind to give the invitation its accepted calls return', () => {
|
||||
const kind = { action: 'other_action', skill: 'other-skill', details: z.object({ value: z.string() }), verbs: {},
|
||||
act: () => Promise.resolve<ActionCardResult>({ status: 'accepted' }) }
|
||||
// @ts-expect-error: a kind without its invitation does not compile.
|
||||
const incomplete: ActionCardKind<TestDetails> = kind
|
||||
expect(incomplete).toBe(kind)
|
||||
})
|
||||
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"extends": "../../../tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"rootDir": "src",
|
||||
"outDir": "lib/types"
|
||||
},
|
||||
"references": [
|
||||
{ "path": "../../../vendor/cordis" },
|
||||
{ "path": "../../typert/protocol" },
|
||||
{ "path": "../../llm/llm" },
|
||||
{ "path": "../../core/tools" },
|
||||
{ "path": "../../core/agent" },
|
||||
{ "path": "../../core/session" },
|
||||
{ "path": "../../session/session-projection" },
|
||||
{ "path": "../../api/remote-access/tsconfig.host.json" },
|
||||
{ "path": "../../sandbox/sandbox-policy" },
|
||||
{ "path": "../../util/values" }
|
||||
],
|
||||
"files": [
|
||||
"src/index.ts",
|
||||
"src/types.ts",
|
||||
"src/projection.ts"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
import { defineConfig } from 'tsdown'
|
||||
|
||||
/** Build the action card plugin. */
|
||||
export default defineConfig([
|
||||
{
|
||||
entry: ['lib/types/index.js'],
|
||||
outDir: 'lib',
|
||||
format: ['esm'],
|
||||
platform: 'node',
|
||||
target: 'es2024',
|
||||
fixedExtension: false,
|
||||
dts: false,
|
||||
clean: false,
|
||||
},
|
||||
])
|
||||
@@ -0,0 +1,40 @@
|
||||
# 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/client-ui-action-cards/README.md
|
||||
/:
|
||||
en: eec43de9002f4ab1
|
||||
zh: 0d2fddca5a1f993a
|
||||
/deepseek-ai-dsh-client-ui-action-cards:
|
||||
en: c36a554629f96f79
|
||||
zh: 0ea837da87938e52
|
||||
/deepseek-ai-dsh-client-ui-action-cards/summary:
|
||||
en: 89ea57734c42a481
|
||||
zh: c7a4f5f0b59b78ad
|
||||
/deepseek-ai-dsh-client-ui-action-cards/table-of-contents:
|
||||
en: d152484eb41ac6b4
|
||||
zh: b00dddf4c88f0a45
|
||||
/deepseek-ai-dsh-client-ui-action-cards/use-this-package:
|
||||
en: 163d385e91a5df38
|
||||
zh: 95bdde9e844cca51
|
||||
/deepseek-ai-dsh-client-ui-action-cards/use-this-package/register-a-card-body:
|
||||
en: 9ec9f9f8f3165d3e
|
||||
zh: 2d8154ec2fe0c9ab
|
||||
/deepseek-ai-dsh-client-ui-action-cards/understand-the-implementation:
|
||||
en: 168ae39a83d6f4eb
|
||||
zh: 312cc12876bca834
|
||||
/deepseek-ai-dsh-client-ui-action-cards/further-exploration:
|
||||
en: 55e4d74a33cdeeb3
|
||||
zh: f601d5a4dcf63ec5
|
||||
/deepseek-ai-dsh-client-ui-action-cards/model-experience:
|
||||
en: f80a4b656c108f22
|
||||
zh: a3e30f46fa7136ac
|
||||
/deepseek-ai-dsh-client-ui-action-cards/model-experience/kv-cache-effect:
|
||||
en: 9cb7131bde146341
|
||||
zh: 1c7d1af00f58004d
|
||||
/deepseek-ai-dsh-client-ui-action-cards/known-limitations-and-deferred-work:
|
||||
en: df94821940e4e2b8
|
||||
zh: 490441ab06b153c9
|
||||
/deepseek-ai-dsh-client-ui-action-cards/known-limitations-and-deferred-work/dev-note:
|
||||
en: e67f633dc6fe7773
|
||||
zh: bd8a8936229e035e
|
||||
@@ -0,0 +1,89 @@
|
||||
---
|
||||
description: "Browser half of optional action cards: the card frame below completed answers, the body registry that experiment packages fill, and the one-line process row of propose_action calls."
|
||||
kind: "package-reference"
|
||||
---
|
||||
|
||||
# @deepseek-ai/dsh-client-ui-action-cards
|
||||
|
||||
English | [中文](README.zh.md)
|
||||
|
||||
## Summary
|
||||
|
||||
Users see an optional action card below a completed answer: its title, a brief that folds when long, and the controls of the experiment that proposed it. In the process area, the proposal shows as one row with the card title and whether the call was accepted; a refused call expands to its reason. A card whose experiment provides no controls in this browser offers only Not now. Showing, expanding and folding cards make no model request.
|
||||
|
||||
## 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
|
||||
|
||||
Enable the [Personalized pages](../creation-recommendations/README.md) or [Plugin recommendations](../plugin-recommendations/README.md) bundle; each inserts this package beside its [Host service](../action-cards/README.md). This browser contribution has no configuration fields.
|
||||
|
||||
### Register a card body
|
||||
|
||||
A kind's browser plugin injects `actionCards` and registers its body inside its own `ctx.effect`: `ctx.actionCards.register({ action, locale, Body })` returns the disposer. The frame renders `Body` for cards of that action with the card, its recorded or derived decision, the Session id, the frame's title and folded brief as `summary`, the frame's fold component as `Folded`, an `act(verb, payload?)` bound to the card, and a translator `t` for the body's own locale namespace. The body places `summary` in its own layout and owns its header, controls, status and footer. A second body for the same action is a registration error.
|
||||
|
||||
-----
|
||||
|
||||
<a id="understand-the-implementation"></a>
|
||||
## Understand the implementation
|
||||
|
||||
<details>
|
||||
<summary>Implementation internals — click to expand</summary>
|
||||
|
||||
One `conversation.chat.turnTail` entry reads the `actionCards` Session projection and shows the card admitted in its Turn after that Turn has ended with a final answer; a Turn that ends without answer text shows no card, and should several cards share a Turn, the lowest call id is shown. The frame sets `data-action-card` to the call id and names its region by the card title. Folding counts a wide grapheme, such as a Chinese character, as two Latin-letter widths and folds after about 260; it never measures layout or alters the full text.
|
||||
|
||||
A `tool.call.toolview` entry keyed `propose_action` renders the process row from the recorded call arguments and result. The plugin provides the body registry at its top level, then mounts the generated `actionCards` Remote and registers its dictionaries and slot entries for the same lifetime.
|
||||
|
||||
| Source | Contents |
|
||||
|---|---|
|
||||
| [`src/client/mount.ts`](src/client/mount.ts) | Registry, Remote, dictionaries and slot entries |
|
||||
| [`src/client/Card.tsx`](src/client/Card.tsx) | Turn tail, frame, fold and fallback body |
|
||||
| [`src/client/ProposeRow.tsx`](src/client/ProposeRow.tsx) | Process row |
|
||||
| [`src/client/registry.ts`](src/client/registry.ts) | Body registry and body props |
|
||||
| [`tests/`](tests/) | Placement, frame, fallback, row and registration tests |
|
||||
|
||||
</details>
|
||||
|
||||
-----
|
||||
|
||||
<a id="further-exploration"></a>
|
||||
## Further Exploration
|
||||
|
||||
- [Action cards](../action-cards/README.md) — the tool, card state and user actions behind the frame.
|
||||
- [Personalized page cards](../client-ui-creation-recommendations/README.md) and [recommendation cards](../client-ui-plugin-recommendations/README.md) — the shipped card bodies.
|
||||
- [Slots](../../client/ui-slots/README.md) — Turn tail and tool row registration.
|
||||
|
||||
<a id="model-experience"></a>
|
||||
## Model Experience
|
||||
|
||||
Indirectly, through the Host card service: card actions reach it as Remote calls, and it owns the logged tool, decisions and status notice.
|
||||
|
||||
#### KV Cache effect
|
||||
|
||||
Rendering cards and process rows does not change any model request.
|
||||
|
||||
## Known Limitations and Deferred Work
|
||||
|
||||
<a id="known-limitations-and-deferred-work"></a>
|
||||
|
||||
- A card whose action has no registered body offers only Not now, so its experiment's other actions need that experiment's browser plugin. Not now still works after the experiment's Host plugin is turned off.
|
||||
- The Turn tail shows one card per Turn, matching the Host rule of one card per turn.
|
||||
|
||||
<a id="dev-note"></a>
|
||||
### Dev Note
|
||||
|
||||
<details>
|
||||
<summary>Working context for maintainers — click to expand</summary>
|
||||
|
||||
None.
|
||||
|
||||
</details>
|
||||
@@ -0,0 +1,89 @@
|
||||
---
|
||||
description: "可选操作卡片的浏览器端:已完成回答下方的卡片框架、供各实验包填入的正文注册表,以及 propose_action 调用的单行过程行。"
|
||||
kind: "package-reference"
|
||||
---
|
||||
|
||||
# @deepseek-ai/dsh-client-ui-action-cards
|
||||
|
||||
[English](README.md) | 中文
|
||||
|
||||
## 概述
|
||||
|
||||
用户在已完成的回答下方看到一张可选操作卡片:标题、过长时会折叠的说明,以及提议该卡片的实验所提供的控件。在过程区中,提议显示为一行,带卡片标题和调用是否被接受;被拒绝的调用可以展开查看原因。如果实验在当前浏览器中没有提供控件,卡片只提供“暂不需要”。展示、展开和折叠卡片都不会发起模型请求。
|
||||
|
||||
## 目录
|
||||
|
||||
- [使用本包](#use-this-package)
|
||||
- [实现原理](#understand-the-implementation)
|
||||
- [延伸阅读](#further-exploration)
|
||||
- [模型体验](#model-experience)
|
||||
- [已知限制与后续工作](#known-limitations-and-deferred-work)
|
||||
- [开发备注](#dev-note)
|
||||
|
||||
-----
|
||||
|
||||
<a id="use-this-package"></a>
|
||||
## 使用本包
|
||||
|
||||
启用[个性化页面](../creation-recommendations/README.zh.md)或[插件推荐](../plugin-recommendations/README.zh.md) Bundle,它们都会在本包旁插入对应的 [Host 服务](../action-cards/README.zh.md)。本浏览器组件没有配置字段。
|
||||
|
||||
### 注册卡片正文
|
||||
|
||||
种类的浏览器插件注入 `actionCards`,并在自己的 `ctx.effect` 中注册正文:`ctx.actionCards.register({ action, locale, Body })` 返回注销函数。框架为该动作的卡片渲染 `Body`,并传入:卡片、已记录或推导出的决定、会话 id、框架渲染的标题与折叠说明 `summary`、框架的折叠组件 `Folded`、绑定到该卡片的 `act(verb, payload?)`,以及正文自己语言命名空间的翻译函数 `t`。正文把 `summary` 放进自己的布局,并负责自己的标题栏、控件、状态和底部操作。为同一动作注册第二个正文属于注册错误。
|
||||
|
||||
-----
|
||||
|
||||
<a id="understand-the-implementation"></a>
|
||||
## 实现原理
|
||||
|
||||
<details>
|
||||
<summary>实现细节——点击展开</summary>
|
||||
|
||||
一个 `conversation.chat.turnTail` 条目读取 `actionCards` 会话投影,在某一轮以最终回答结束后展示该轮接受的卡片;没有回答文本就结束的轮次不显示卡片,若同一轮有多张卡片,显示调用 id 最小的一张。框架把 `data-action-card` 设为调用 id,并以卡片标题命名所在区域。折叠时,宽字素(如汉字)按两个拉丁字母宽度计算,约 260 个单位后折叠;折叠不测量布局,也不改动完整文本。
|
||||
|
||||
一个以 `propose_action` 为键的 `tool.call.toolview` 条目,根据记录的调用参数和结果渲染过程行。插件在顶层提供正文注册表,然后挂载生成的 `actionCards` Remote,并在同一生命周期内注册词典和插槽条目。
|
||||
|
||||
| 源码 | 内容 |
|
||||
|---|---|
|
||||
| [`src/client/mount.ts`](src/client/mount.ts) | 注册表、Remote、词典与插槽条目 |
|
||||
| [`src/client/Card.tsx`](src/client/Card.tsx) | 轮次尾部、框架、折叠与兜底正文 |
|
||||
| [`src/client/ProposeRow.tsx`](src/client/ProposeRow.tsx) | 过程行 |
|
||||
| [`src/client/registry.ts`](src/client/registry.ts) | 正文注册表与正文属性 |
|
||||
| [`tests/`](tests/) | 位置、框架、兜底、过程行与注册测试 |
|
||||
|
||||
</details>
|
||||
|
||||
-----
|
||||
|
||||
<a id="further-exploration"></a>
|
||||
## 延伸阅读
|
||||
|
||||
- [操作卡片](../action-cards/README.zh.md) — 框架背后的工具、卡片状态与用户操作。
|
||||
- [个性化页面卡片](../client-ui-creation-recommendations/README.zh.md)和[推荐卡片](../client-ui-plugin-recommendations/README.zh.md) — 随产品提供的卡片正文。
|
||||
- [插槽](../../client/ui-slots/README.zh.md) — 轮次尾部与工具行的注册。
|
||||
|
||||
<a id="model-experience"></a>
|
||||
## 模型体验
|
||||
|
||||
间接影响来自 Host 卡片服务:卡片操作以 Remote 调用到达该服务,由它负责记录在日志中的工具、决定和状态通知。
|
||||
|
||||
#### KV Cache 影响
|
||||
|
||||
渲染卡片和过程行不会改变任何模型请求。
|
||||
|
||||
## 已知限制与后续工作
|
||||
|
||||
<a id="known-limitations-and-deferred-work"></a>
|
||||
|
||||
- 动作没有注册正文的卡片只提供“暂不需要”,该实验的其他操作需要它的浏览器插件。即使该实验的 Host 插件已关闭,“暂不需要”仍然可用。
|
||||
- 轮次尾部每轮只显示一张卡片,与 Host 每轮一张卡片的规则一致。
|
||||
|
||||
<a id="dev-note"></a>
|
||||
### 开发备注
|
||||
|
||||
<details>
|
||||
<summary>维护者工作背景——点击展开</summary>
|
||||
|
||||
无。
|
||||
|
||||
</details>
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"meta": {
|
||||
"title": "Anzeige von Aktionskarten",
|
||||
"description": "Zeigt optionale Aktionskarten unter Antworten mit den eigenen Bedienelementen jedes Experiments an."
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"meta": {
|
||||
"title": "Action card display",
|
||||
"description": "Show optional action cards below answers, with each experiment's own controls."
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"meta": {
|
||||
"title": "Visualización de tarjetas de acción",
|
||||
"description": "Muestra tarjetas de acción opcionales debajo de las respuestas, con los controles propios de cada experimento."
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"meta": {
|
||||
"title": "Affichage des cartes d'action",
|
||||
"description": "Affiche des cartes d'action facultatives sous les réponses, avec les commandes propres à chaque expérience."
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"meta": {
|
||||
"title": "アクションカード表示",
|
||||
"description": "回答の下に任意のアクションカードを表示します。カードの内容は各実験が提供します。"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"meta": {
|
||||
"title": "Exibição de cartões de ação",
|
||||
"description": "Mostra cartões de ação opcionais abaixo das respostas, com os controles próprios de cada experimento."
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"meta": {
|
||||
"title": "Отображение карточек действий",
|
||||
"description": "Показывает необязательные карточки действий под ответами с элементами управления каждого эксперимента."
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"meta": {
|
||||
"title": "操作卡片显示",
|
||||
"description": "在回答下方显示可选操作卡片,卡片内容由各实验提供。"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
{
|
||||
"version": "0.2.1-rc.2",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"type": "module",
|
||||
"main": "lib/index.js",
|
||||
"types": "lib/types/index.d.ts",
|
||||
"license": "MIT",
|
||||
"name": "@deepseek-ai/dsh-client-ui-action-cards",
|
||||
"description": "Action cards below completed answers: the shared card frame, kind bodies and the compact tool row",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/deepseek-ai/deepseek-harness.git",
|
||||
"directory": "packages/experimental/client-ui-action-cards"
|
||||
},
|
||||
"exports": {
|
||||
".": {
|
||||
"types": "./lib/types/index.d.ts",
|
||||
"default": "./lib/index.js"
|
||||
},
|
||||
"./src/*": "./src/*",
|
||||
"./package.json": "./package.json",
|
||||
"./client": {
|
||||
"types": "./lib/types/client/index.d.ts",
|
||||
"default": "./lib/client.js"
|
||||
},
|
||||
"./locale/*.json": "./locale/*.json"
|
||||
},
|
||||
"dsh": {
|
||||
"client": {
|
||||
"platform": "web",
|
||||
"inject": [
|
||||
"@deepseek-ai/dsh-api-remotes",
|
||||
"@deepseek-ai/dsh-client-locale",
|
||||
"@deepseek-ai/dsh-client-ui-conversation",
|
||||
"@deepseek-ai/dsh-client-ui-chat",
|
||||
"@deepseek-ai/dsh-client-ui-session",
|
||||
"@deepseek-ai/dsh-client-ui-tool"
|
||||
]
|
||||
}
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@deepseek-ai/cordis": "workspace:~"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@deepseek-ai/cordis": "workspace:~",
|
||||
"@deepseek-ai/dsh-llm": "workspace:*",
|
||||
"@deepseek-ai/dsh-session": "workspace:*",
|
||||
"@deepseek-ai/dsh-client-ui-renderer": "workspace:*",
|
||||
"@deepseek-ai/dsh-api-remotes": "workspace:*",
|
||||
"@deepseek-ai/dsh-client-locale": "workspace:*",
|
||||
"@deepseek-ai/dsh-client-ui-conversation": "workspace:*",
|
||||
"@deepseek-ai/dsh-client-ui-chat": "workspace:*",
|
||||
"@deepseek-ai/dsh-client-ui-session": "workspace:*",
|
||||
"@deepseek-ai/dsh-client-ui-slots": "workspace:*",
|
||||
"@deepseek-ai/dsh-client-ui-primitives": "workspace:*",
|
||||
"@deepseek-ai/dsh-client-ui-tool": "workspace:*",
|
||||
"react": "^18.2.0",
|
||||
"@deepseek-ai/dsh-action-cards": "workspace:*",
|
||||
"@deepseek-ai/dsh-typert-protocol": "workspace:*",
|
||||
"@deepseek-ai/dsh-util-values": "workspace:*",
|
||||
"@deepseek-ai/dsh-client-test-runtime": "workspace:*"
|
||||
},
|
||||
"files": [
|
||||
"locale/*.json",
|
||||
"lib/index.js",
|
||||
"lib/client.js",
|
||||
"lib/types/**/*.d.ts"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
.card { margin: 16px 0; border: 0.5px solid var(--dsw-alias-border-l2); border-radius: var(--dsw-radius-lg); overflow: hidden; background: var(--dsw-alias-bg-layer-1); font-family: var(--dsw-font-family); color: var(--dsw-alias-label-primary); }
|
||||
.body { padding: 12px 20px 20px; }
|
||||
.title { display: block; font-size: 16px; font-weight: 500; line-height: 1.5; overflow-wrap: anywhere; }
|
||||
.text { margin: 8px 0 0; font-size: 13px; line-height: 1.7; white-space: pre-wrap; overflow-wrap: anywhere; color: var(--dsw-alias-label-secondary); }
|
||||
.toggle { margin: 8px 0 0; padding-inline: 0; height: auto; min-height: 24px; font-size: 12px; }
|
||||
.status { margin: 12px 0 0; font-size: 12px; line-height: 1.6; color: var(--dsw-alias-label-secondary); }
|
||||
.footer { display: flex; align-items: center; justify-content: flex-end; gap: 12px; margin-top: 12px; }
|
||||
@@ -0,0 +1,150 @@
|
||||
/** The shared card frame below a completed answer: title, folded brief, and the kind's body or a dismiss-only fallback. */
|
||||
import { useCallback, useId, useMemo, useState, type ReactNode } from 'react'
|
||||
import { Button } from '@deepseek-ai/dsh-client-ui-primitives'
|
||||
import type { HostObservable, InjectFace, PropsLocale, PropsRuntime, Translate } from '@deepseek-ai/dsh-client-ui-slots'
|
||||
import type { SessionId } from '@deepseek-ai/dsh-session/types'
|
||||
import type { ToolCallId } from '@deepseek-ai/dsh-llm/brand'
|
||||
import type {
|
||||
ActionCardDecision, ActionCardFields, ActionCardProposal, ActionCardResult, ActionCardView,
|
||||
} from '@deepseek-ai/dsh-action-cards/types'
|
||||
import type {} from '@deepseek-ai/dsh-client-ui-chat/client'
|
||||
import type { ActionCardKey } from './locales.ts'
|
||||
import type { FoldedTextProps, RegisteredBody } from './registry.ts'
|
||||
import css from './Card.module.css'
|
||||
|
||||
/** Session-bound actions and registered bodies, without a service in the component. */
|
||||
export interface TailInjected {
|
||||
/**
|
||||
* Send one user action for a card of the displayed Session.
|
||||
* @param callId - the card's call id.
|
||||
* @param verb - `dismiss` or one of the kind's verbs.
|
||||
* @param payload - kind-defined fields.
|
||||
* @returns the Host result, or undefined when the reply was lost.
|
||||
*/
|
||||
act: (callId: ToolCallId, verb: string, payload?: ActionCardFields) => Promise<ActionCardResult | undefined>
|
||||
/**
|
||||
* Bind a body's own locale namespace.
|
||||
* @param locale - namespace the body declared.
|
||||
* @returns its translator.
|
||||
*/
|
||||
bind: (locale: string) => Translate
|
||||
hooks: { bodies: HostObservable<ReadonlyMap<string, RegisteredBody>> }
|
||||
sessionId: SessionId
|
||||
}
|
||||
|
||||
type TailProps = Pick<PropsRuntime<'conversation.chat.turnTail'>, 'turn' | 'useProjection'>
|
||||
& PropsLocale<'actionCards'> & InjectFace<TailInjected>
|
||||
|
||||
/** Graphemes drawn about twice as wide as a Latin letter: CJK scripts, CJK punctuation and fullwidth forms. */
|
||||
const WIDE_GRAPHEME = /^[\p{Script=Han}\p{Script=Hiragana}\p{Script=Katakana}\p{Script=Hangul} -〿-⦆¢-₩]/u
|
||||
/** Preview budget in Latin-letter widths, about two card lines at desktop width. */
|
||||
const FOLD_WIDTH = 260
|
||||
|
||||
/**
|
||||
* Fold omitted text without measuring layout; a wide grapheme counts twice so Chinese and English fold near the
|
||||
* same line. The full text is never altered.
|
||||
* @param props - text and its localized toggle labels.
|
||||
* @returns the paragraph and, when text was omitted, its toggle.
|
||||
*/
|
||||
export function FoldedText({ text, expandLabel, collapseLabel }: FoldedTextProps) {
|
||||
const id = useId()
|
||||
const [expanded, setExpanded] = useState(false)
|
||||
const preview = useMemo(() => {
|
||||
const compact = text.replace(/\s+/g, ' ').trim()
|
||||
const characters = Array.from(new Intl.Segmenter(undefined, { granularity: 'grapheme' }).segment(compact), part => part.segment)
|
||||
let width = 0
|
||||
for (const [index, character] of characters.entries()) {
|
||||
width += WIDE_GRAPHEME.test(character) ? 2 : 1
|
||||
if (width > FOLD_WIDTH) return characters.slice(0, index).join('').trimEnd() + '…'
|
||||
}
|
||||
return undefined
|
||||
}, [text])
|
||||
return <>
|
||||
<p id={id} className={css.text}>{expanded || preview === undefined ? text : preview}</p>
|
||||
{preview !== undefined && <Button variant="ghost" size="sm" className={css.toggle} aria-expanded={expanded} aria-controls={id}
|
||||
onClick={() => { setExpanded(value => !value) }}>{expanded ? collapseLabel : expandLabel}</Button>}
|
||||
</>
|
||||
}
|
||||
|
||||
/** The projection admits at most one card per turn; should several exist, the lowest call id is shown. */
|
||||
function proposalOf(view: ActionCardView | undefined, turn: number): ActionCardProposal | undefined {
|
||||
let found: ActionCardProposal | undefined
|
||||
for (const proposal of Object.values(view?.proposals ?? {})) {
|
||||
if (proposal.turn === turn && (found === undefined || proposal.callId < found.callId)) found = proposal
|
||||
}
|
||||
return found
|
||||
}
|
||||
|
||||
function decisionOf(view: ActionCardView | undefined, callId: string): ActionCardDecision | undefined {
|
||||
return view !== undefined && Object.hasOwn(view.decisions, callId) ? view.decisions[callId] : undefined
|
||||
}
|
||||
|
||||
/**
|
||||
* Place the card admitted in a turn after that turn's final answer, once the turn has ended with one.
|
||||
* @param props - Turn location, projection reader, registered bodies and Session-bound actions.
|
||||
* @returns the card, or null while the turn is open or when it ended without answer text.
|
||||
*/
|
||||
export function ActionCardTail({ turn, useProjection, ...props }: TailProps) {
|
||||
const view = useProjection('actionCards')
|
||||
const proposal = proposalOf(view, turn.turn)
|
||||
return proposal === undefined || turn.end === undefined || turn.data.get('turn-tail')?.closing == null
|
||||
? null : <ActionCard {...props} proposal={proposal} decision={decisionOf(view, proposal.callId)} />
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the frame around one card.
|
||||
* @param props - the card, its state, registered bodies and actions.
|
||||
* @returns the card section.
|
||||
*/
|
||||
export function ActionCard({ proposal, decision, sessionId, act, bind, useBodies, t }: {
|
||||
proposal: ActionCardProposal
|
||||
decision: ActionCardDecision | undefined
|
||||
} & InjectFace<TailInjected> & PropsLocale<'actionCards'>) {
|
||||
const body = useBodies(bodies => bodies.get(proposal.action))
|
||||
const send = useCallback((verb: string, payload?: ActionCardFields) => act(proposal.callId, verb, payload), [act, proposal.callId])
|
||||
const summary = <>
|
||||
<strong className={css.title}>{proposal.title}</strong>
|
||||
<FoldedText text={proposal.brief} expandLabel={t('expandBrief')} collapseLabel={t('collapseBrief')} />
|
||||
</>
|
||||
// The frame re-renders on a locale change and hands the body a new summary, so the body re-renders with it.
|
||||
const content = body === undefined
|
||||
? <FallbackBody summary={summary} decision={decision} act={send} t={t} />
|
||||
: body.render({ proposal, decision, sessionId, summary, Folded: FoldedText, act: send }, bind(body.locale))
|
||||
return <section className={css.card} aria-label={proposal.title} data-action-card={proposal.callId} data-action={proposal.action}>
|
||||
{content}
|
||||
</section>
|
||||
}
|
||||
|
||||
/** Phases the fallback can name; other kind phases leave only the summary. */
|
||||
const NAMED_PHASES: Readonly<Record<string, ActionCardKey>> = { dismissed: 'dismissed', replaced: 'replaced' }
|
||||
|
||||
/** Title, brief and Not now for a card whose kind registered no body in this browser. */
|
||||
function FallbackBody({ summary, decision, act, t }: {
|
||||
summary: ReactNode
|
||||
decision: ActionCardDecision | undefined
|
||||
act: (verb: string) => Promise<ActionCardResult | undefined>
|
||||
} & PropsLocale<'actionCards'>) {
|
||||
const [pending, setPending] = useState(false)
|
||||
const [error, setError] = useState<ActionCardKey>()
|
||||
const phase = decision === undefined || !Object.hasOwn(NAMED_PHASES, decision.phase) ? undefined : NAMED_PHASES[decision.phase]
|
||||
const dismiss = async () => {
|
||||
setPending(true)
|
||||
setError(undefined)
|
||||
try {
|
||||
const result = await act('dismiss')
|
||||
if (result === undefined) setError('transport')
|
||||
else if (result.status === 'refused' || result.status === 'unconfirmed') setError('unavailable')
|
||||
} catch {
|
||||
// A lost reply does not prove failure; replay supplies the durable decision.
|
||||
setError('transport')
|
||||
} finally { setPending(false) }
|
||||
}
|
||||
return <div className={css.body}>
|
||||
{summary}
|
||||
{phase !== undefined && <p role="status" className={css.status}>{t(phase)}</p>}
|
||||
{error !== undefined && <p role="alert" className={css.status}>{t(error)}</p>}
|
||||
{decision === undefined && <footer className={css.footer}>
|
||||
<Button variant="ghost" size="sm" disabled={pending} onClick={() => { void dismiss() }}>{t('dismiss')}</Button>
|
||||
</footer>}
|
||||
</div>
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
/** The card title stays readable beside the call state. */
|
||||
.summary { margin-left: 8px; display: flex; align-items: center; gap: 8px; min-width: 0; color: inherit; font-size: 12px; }
|
||||
.summary > :first-child { flex-shrink: 0; }
|
||||
.title { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
||||
.reason { margin: 8px 0; padding: 12px; border-radius: var(--dsw-radius-lg); background: var(--dsw-alias-bg-layer-1); color: var(--dsw-alias-label-secondary); white-space: pre-wrap; overflow-wrap: anywhere; font-size: 12px; }
|
||||
.inspect { align-self: flex-start; border: none; padding: 4px 0; background: transparent; color: var(--dsw-alias-link); font: inherit; font-size: 12px; cursor: pointer; }
|
||||
@@ -0,0 +1,43 @@
|
||||
/** One-line process row for a `propose_action` call: the card title and whether the card was shown. */
|
||||
import { useState } from 'react'
|
||||
import { DisclosureRow, IconAppsAddOutlineRegular } from '@deepseek-ai/dsh-client-ui-primitives'
|
||||
import type { ToolCallViewProps } from '@deepseek-ai/dsh-client-ui-tool/client'
|
||||
import type { PropsLocale } from '@deepseek-ai/dsh-client-ui-slots'
|
||||
import css from './ProposeRow.module.css'
|
||||
|
||||
type ProposeRowProps = ToolCallViewProps & PropsLocale<'actionCards'>
|
||||
|
||||
/** Call states with row copy; a preparing call has no complete arguments yet. */
|
||||
type RowState = 'preparing' | 'running' | 'ok' | 'error' | 'stopped'
|
||||
|
||||
function stateOf(props: ProposeRowProps): RowState {
|
||||
if (props.phase === 'preparing') return 'preparing'
|
||||
if (props.phase === 'start') return 'running'
|
||||
if (props.block.error?.code === 'interrupted') return 'stopped'
|
||||
return props.block.isError ? 'error' : 'ok'
|
||||
}
|
||||
|
||||
/**
|
||||
* Render a `propose_action` call from its recorded arguments and result. Only a refused call expands, to show
|
||||
* why no card followed the answer.
|
||||
* @param props - tool call and localized status copy.
|
||||
* @returns the status row.
|
||||
*/
|
||||
export function ProposeRow(props: ProposeRowProps) {
|
||||
const { block, inspect, t } = props
|
||||
const [expanded, setExpanded] = useState(false)
|
||||
const state = stateOf(props)
|
||||
const title = block.args.text('title') ?? ''
|
||||
const reason = props.phase === 'result' && props.block.isError
|
||||
? props.block.content.flatMap(item => item.type === 'text' ? [item.text] : []).join('\n')
|
||||
: ''
|
||||
return <div data-tool="propose_action" data-state={state}>
|
||||
<DisclosureRow title={t('row.title')} icon={<IconAppsAddOutlineRegular size={14} />} running={state === 'preparing' || state === 'running'}
|
||||
open={expanded && reason !== ''} expandable={reason !== ''} expandOnRowClick keepContentWhenOpen
|
||||
onToggle={() => { setExpanded(value => !value) }}
|
||||
collapsedContent={<span className={css.summary}><span>{t(`row.${state}`)}</span><span className={css.title}>{title}</span></span>}>
|
||||
<pre className={css.reason}>{reason}</pre>
|
||||
{inspect && <button type="button" className={css.inspect} onClick={inspect}>{t('row.inspect')}</button>}
|
||||
</DisclosureRow>
|
||||
</div>
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
/** Bind generated Remote descriptors to the source-tested browser lifecycle. */
|
||||
import type { Context } from '@deepseek-ai/cordis'
|
||||
import remote from '@deepseek-ai/dsh-action-cards/remote'
|
||||
import { mountActionCards } from './mount.ts'
|
||||
export { inject } from './mount.ts'
|
||||
export type { ActionCardBodyProps, ActionCardDescriptor, ActionCardRegistry, FoldedTextProps } from './registry.ts'
|
||||
|
||||
/**
|
||||
* Mount action cards and their Remote.
|
||||
* @param ctx - Client plugin context.
|
||||
* @returns disposer for every contribution.
|
||||
*/
|
||||
export async function apply(ctx: Context): Promise<() => Promise<void>> {
|
||||
return await mountActionCards(ctx, remote)
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
/** English card frame, fallback and tool-row copy. */
|
||||
export const en = {
|
||||
expandBrief: 'Show more', collapseBrief: 'Show less',
|
||||
dismiss: 'Not now', dismissed: 'Dismissed', replaced: 'Replaced',
|
||||
unavailable: 'This action is unavailable. Check the plugin in Plugins.',
|
||||
transport: 'Could not confirm the result. Reconnect and check the card before retrying.',
|
||||
'row.title': 'Action card', 'row.preparing': 'Preparing a card', 'row.running': 'Proposing',
|
||||
'row.ok': 'Proposed', 'row.error': 'Not shown', 'row.stopped': 'Interrupted', 'row.inspect': 'Inspect call',
|
||||
}
|
||||
|
||||
/** Keys shared by every dictionary. */
|
||||
export type ActionCardKey = keyof typeof en
|
||||
|
||||
/** Chinese card frame, fallback and tool-row copy. */
|
||||
export const zh: Record<ActionCardKey, string> = {
|
||||
expandBrief: '展开', collapseBrief: '收起',
|
||||
dismiss: '暂不需要', dismissed: '已忽略', replaced: '已替换',
|
||||
unavailable: '暂时无法执行,请到插件页面查看',
|
||||
transport: '暂时无法确认结果,请重新连接并查看卡片状态后再重试',
|
||||
'row.title': '操作卡片', 'row.preparing': '正在准备卡片', 'row.running': '正在提议',
|
||||
'row.ok': '已提议', 'row.error': '未显示', 'row.stopped': '已中断', 'row.inspect': '查看调用',
|
||||
}
|
||||
|
||||
/** Japanese card frame, fallback and tool-row copy. */
|
||||
export const ja: Record<ActionCardKey, string> = {
|
||||
expandBrief: 'すべて表示', collapseBrief: '折りたたむ',
|
||||
dismiss: '今はしない', dismissed: '却下済み', replaced: '置き換え済み',
|
||||
unavailable: 'この操作は利用できません。プラグイン画面でプラグインを確認してください。',
|
||||
transport: '結果を確認できませんでした。再接続してカードを確認してから再試行してください。',
|
||||
'row.title': 'アクションカード', 'row.preparing': 'カードを準備中', 'row.running': '提案中',
|
||||
'row.ok': '提案済み', 'row.error': '表示されませんでした', 'row.stopped': '中断されました', 'row.inspect': '呼び出しを確認',
|
||||
}
|
||||
|
||||
/** Spanish card frame, fallback and tool-row copy. */
|
||||
export const es: Record<ActionCardKey, string> = {
|
||||
expandBrief: 'Mostrar más', collapseBrief: 'Mostrar menos',
|
||||
dismiss: 'Ahora no', dismissed: 'Descartado', replaced: 'Reemplazado',
|
||||
unavailable: 'Esta acción no está disponible. Revisa el complemento en Complementos.',
|
||||
transport: 'No se pudo confirmar el resultado. Vuelve a conectarte y revisa la tarjeta antes de reintentar.',
|
||||
'row.title': 'Tarjeta de acción', 'row.preparing': 'Preparando una tarjeta', 'row.running': 'Proponiendo',
|
||||
'row.ok': 'Propuesto', 'row.error': 'No se mostró', 'row.stopped': 'Interrumpido', 'row.inspect': 'Inspeccionar llamada',
|
||||
}
|
||||
|
||||
/** French card frame, fallback and tool-row copy. */
|
||||
export const fr: Record<ActionCardKey, string> = {
|
||||
expandBrief: 'Afficher plus', collapseBrief: 'Afficher moins',
|
||||
dismiss: 'Pas maintenant', dismissed: 'Ignoré', replaced: 'Remplacé',
|
||||
unavailable: "Cette action n'est pas disponible. Vérifiez le plugin dans Plugins.",
|
||||
transport: 'Impossible de confirmer le résultat. Reconnectez-vous et vérifiez la carte avant de réessayer.',
|
||||
'row.title': "Carte d'action", 'row.preparing': "Préparation d'une carte", 'row.running': 'Proposition en cours',
|
||||
'row.ok': 'Proposé', 'row.error': 'Non affiché', 'row.stopped': 'Interrompu', 'row.inspect': "Inspecter l'appel",
|
||||
}
|
||||
|
||||
/** German card frame, fallback and tool-row copy. */
|
||||
export const de: Record<ActionCardKey, string> = {
|
||||
expandBrief: 'Mehr anzeigen', collapseBrief: 'Weniger anzeigen',
|
||||
dismiss: 'Nicht jetzt', dismissed: 'Verworfen', replaced: 'Ersetzt',
|
||||
unavailable: 'Diese Aktion ist nicht verfügbar. Prüfen Sie das Plugin unter Plugins.',
|
||||
transport: 'Das Ergebnis konnte nicht bestätigt werden. Verbinden Sie sich erneut und prüfen Sie die Karte, bevor Sie es erneut versuchen.',
|
||||
'row.title': 'Aktionskarte', 'row.preparing': 'Karte wird vorbereitet', 'row.running': 'Wird vorgeschlagen',
|
||||
'row.ok': 'Vorgeschlagen', 'row.error': 'Nicht angezeigt', 'row.stopped': 'Unterbrochen', 'row.inspect': 'Aufruf prüfen',
|
||||
}
|
||||
|
||||
/** Russian card frame, fallback and tool-row copy. */
|
||||
export const ru: Record<ActionCardKey, string> = {
|
||||
expandBrief: 'Показать больше', collapseBrief: 'Показать меньше',
|
||||
dismiss: 'Не сейчас', dismissed: 'Отклонено', replaced: 'Заменено',
|
||||
unavailable: 'Это действие недоступно. Проверьте плагин в разделе «Плагины».',
|
||||
transport: 'Не удалось подтвердить результат. Переподключитесь и проверьте карточку перед повторной попыткой.',
|
||||
'row.title': 'Карточка действия', 'row.preparing': 'Подготовка карточки', 'row.running': 'Предлагается',
|
||||
'row.ok': 'Предложено', 'row.error': 'Не показано', 'row.stopped': 'Прервано', 'row.inspect': 'Проверить вызов',
|
||||
}
|
||||
|
||||
/** Portuguese card frame, fallback and tool-row copy. */
|
||||
export const pt: Record<ActionCardKey, string> = {
|
||||
expandBrief: 'Mostrar mais', collapseBrief: 'Mostrar menos',
|
||||
dismiss: 'Agora não', dismissed: 'Dispensado', replaced: 'Substituído',
|
||||
unavailable: 'Esta ação não está disponível. Verifique o plug-in em Plug-ins.',
|
||||
transport: 'Não foi possível confirmar o resultado. Reconecte-se e verifique o cartão antes de tentar novamente.',
|
||||
'row.title': 'Cartão de ação', 'row.preparing': 'Preparando um cartão', 'row.running': 'Propondo',
|
||||
'row.ok': 'Proposto', 'row.error': 'Não exibido', 'row.stopped': 'Interrompido', 'row.inspect': 'Inspecionar chamada',
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
/** Register the card frame, the tool row, their copy and the body registry. */
|
||||
import type { Context } from '@deepseek-ai/cordis'
|
||||
import type { SessionId } from '@deepseek-ai/dsh-session/types'
|
||||
import type {} from '@deepseek-ai/dsh-api-remotes/client'
|
||||
import type {} from '@deepseek-ai/dsh-client-locale/client'
|
||||
import type {} from '@deepseek-ai/dsh-client-ui-session/client'
|
||||
import type {} from '@deepseek-ai/dsh-client-ui-renderer/client'
|
||||
import type {} from '@deepseek-ai/dsh-client-ui-tool/client'
|
||||
import type {} from '@deepseek-ai/dsh-action-cards/remote'
|
||||
import type { TypertRemoteContribution } from '@deepseek-ai/dsh-typert-protocol'
|
||||
import { ActionCardTail, type TailInjected } from './Card.tsx'
|
||||
import { ProposeRow } from './ProposeRow.tsx'
|
||||
import { ActionCardRegistry } from './registry.ts'
|
||||
import { de, en, es, fr, ja, pt, ru, zh, type ActionCardKey } from './locales.ts'
|
||||
|
||||
declare module '@deepseek-ai/dsh-client-ui-slots' {
|
||||
interface LocaleNamespaceMap { actionCards: ActionCardKey }
|
||||
}
|
||||
|
||||
declare module '@deepseek-ai/cordis' {
|
||||
interface Context {
|
||||
/** Card bodies by action kind; kinds register theirs inside their own `ctx.effect`. */
|
||||
actionCards: ActionCardRegistry
|
||||
}
|
||||
}
|
||||
|
||||
/** Registries available before this plugin mounts its Remote. */
|
||||
export const inject = ['slots', 'locale', 'remote']
|
||||
|
||||
/**
|
||||
* Provide the body registry, then mount the Remote and the UI for the same plugin lifetime.
|
||||
* @param ctx - Client plugin context.
|
||||
* @param contribution - Generated Remote descriptors supplied by the built entry.
|
||||
* @returns disposer removing the UI before the Remote contribution.
|
||||
*/
|
||||
export async function mountActionCards(ctx: Context, contribution: TypertRemoteContribution): Promise<() => Promise<void>> {
|
||||
// Built at the plugin's top level: kinds register into it from their own apply.
|
||||
const registry = new ActionCardRegistry(ctx)
|
||||
ctx.reflect.provide('actionCards', registry)
|
||||
const unmount = await ctx.remote.$mount(contribution)
|
||||
const ui = ctx.inject(['remote.actionCards'], (inner) => { registerUi(inner, registry) })
|
||||
try { await ui } catch (error) { await ui.dispose(); await unmount(); throw error }
|
||||
return async () => { await ui.dispose(); await unmount() }
|
||||
}
|
||||
|
||||
function registerUi(ctx: Context, registry: ActionCardRegistry): void {
|
||||
ctx.effect(() => ctx.locale.register('actionCards', { en, zh, ja, es, fr, de, ru, pt }), 'action-cards: locale')
|
||||
ctx.slots.inject('conversation.chat.turnTail', () => ctx.slots.register({
|
||||
name: 'conversation.chat.turnTail', id: '@deepseek-ai/dsh-client-ui-action-cards', locale: 'actionCards',
|
||||
inject: (sessionId: SessionId): TailInjected => ({
|
||||
sessionId,
|
||||
hooks: { bodies: registry.source },
|
||||
bind: locale => ctx.locale.bind(locale),
|
||||
act: async (callId, verb, payload) => {
|
||||
const result = await ctx.remote.actionCards.act(sessionId, callId, verb, payload)
|
||||
return result.ok ? result.value : undefined
|
||||
},
|
||||
}),
|
||||
}, ActionCardTail))
|
||||
ctx.slots.inject('tool.call.toolview', () => ctx.slots.register(
|
||||
{ name: 'tool.call.toolview', key: 'propose_action', locale: 'actionCards' }, ProposeRow,
|
||||
))
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
/** Card bodies registered by action kind for the shared card frame. */
|
||||
import { createElement, type ComponentType, type ReactNode } from 'react'
|
||||
import type { Context } from '@deepseek-ai/cordis'
|
||||
import type { HostObservable, LocaleNamespaceMap, Translate, TranslateNS } from '@deepseek-ai/dsh-client-ui-slots'
|
||||
import type { SessionId } from '@deepseek-ai/dsh-session/types'
|
||||
import type {
|
||||
ActionCardDecision, ActionCardFields, ActionCardProposal, ActionCardResult,
|
||||
} from '@deepseek-ai/dsh-action-cards/types'
|
||||
|
||||
/** Props of the frame's folded text, which bodies reuse for their own long fields. */
|
||||
export interface FoldedTextProps {
|
||||
readonly text: string
|
||||
readonly expandLabel: string
|
||||
readonly collapseLabel: string
|
||||
}
|
||||
|
||||
/** Everything a kind's body receives from the shared frame. */
|
||||
export interface ActionCardBodyProps<N extends Extract<keyof LocaleNamespaceMap, string>> {
|
||||
/** The card as admitted; the body validates `details` with its own schema. */
|
||||
readonly proposal: ActionCardProposal
|
||||
/** Recorded or derived card state; undefined while the card is unstarted. */
|
||||
readonly decision: ActionCardDecision | undefined
|
||||
readonly sessionId: SessionId
|
||||
/** Title and folded brief rendered by the frame; the body places them in its layout. */
|
||||
readonly summary: ReactNode
|
||||
/** The frame's width-weighted text fold. */
|
||||
readonly Folded: ComponentType<FoldedTextProps>
|
||||
/**
|
||||
* Send one user action for this card.
|
||||
* @param verb - `dismiss` or one of the kind's Host verbs.
|
||||
* @param payload - fields the kind's Host handler validates.
|
||||
* @returns the Host result, or undefined when the reply was lost.
|
||||
*/
|
||||
readonly act: (verb: string, payload?: ActionCardFields) => Promise<ActionCardResult | undefined>
|
||||
/** Translate the body's own locale namespace. */
|
||||
readonly t: TranslateNS<N>
|
||||
}
|
||||
|
||||
/** Browser half of one action kind. */
|
||||
export interface ActionCardDescriptor<N extends Extract<keyof LocaleNamespaceMap, string>> {
|
||||
/** Value of the card's `action`. */
|
||||
readonly action: string
|
||||
/** Locale namespace the body's copy belongs to. */
|
||||
readonly locale: N
|
||||
/** Kind-owned header, controls, status and footer. */
|
||||
readonly Body: ComponentType<ActionCardBodyProps<N>>
|
||||
}
|
||||
|
||||
/** Frame-supplied body props before the kind's translator is bound. */
|
||||
export type ActionCardFrameProps = Omit<ActionCardBodyProps<never>, 't'>
|
||||
|
||||
/** A registered body with its namespace type erased. */
|
||||
export interface RegisteredBody {
|
||||
readonly locale: string
|
||||
/**
|
||||
* Render the body.
|
||||
* @param props - frame-supplied props.
|
||||
* @param t - translator bound to {@link locale}.
|
||||
* @returns the body element.
|
||||
*/
|
||||
readonly render: (props: ActionCardFrameProps, t: Translate) => ReactNode
|
||||
}
|
||||
|
||||
/** Card bodies by action; the frame renders a dismiss-only fallback for an action without one. */
|
||||
export class ActionCardRegistry {
|
||||
private bodies: ReadonlyMap<string, RegisteredBody> = new Map()
|
||||
private readonly listeners = new Set<() => void>()
|
||||
/** Current bodies by action; the snapshot changes on every registration change. */
|
||||
readonly source: HostObservable<ReadonlyMap<string, RegisteredBody>> = {
|
||||
getSnapshot: () => this.bodies,
|
||||
subscribe: (listener) => {
|
||||
this.listeners.add(listener)
|
||||
return () => { this.listeners.delete(listener) }
|
||||
},
|
||||
}
|
||||
|
||||
/** @param ctx - Context whose effects own registered bodies. */
|
||||
constructor(private readonly ctx: Context) {}
|
||||
|
||||
/**
|
||||
* Register one kind's body. The caller holds the returned disposer inside its own `ctx.effect`, so the body
|
||||
* lives exactly as long as the plugin that contributed it.
|
||||
* @param descriptor - the kind's action, locale namespace and body.
|
||||
* @returns idempotent disposer.
|
||||
* @throws when another body already serves the action.
|
||||
*/
|
||||
register<N extends Extract<keyof LocaleNamespaceMap, string>>(descriptor: ActionCardDescriptor<N>): () => void {
|
||||
const { action, locale, Body } = descriptor
|
||||
const body: RegisteredBody = { locale, render: (props, t) => createElement(Body, { ...props, t }) }
|
||||
const dispose = this.ctx.effect(() => {
|
||||
if (this.bodies.has(action)) throw new Error(`action-cards: a body for "${action}" is already registered`)
|
||||
this.publish(new Map([...this.bodies, [action, body]]))
|
||||
return () => {
|
||||
const next = new Map(this.bodies)
|
||||
next.delete(action)
|
||||
this.publish(next)
|
||||
}
|
||||
}, `action-cards: body ${action}`)
|
||||
return () => { void dispose() }
|
||||
}
|
||||
|
||||
private publish(bodies: ReadonlyMap<string, RegisteredBody>): void {
|
||||
this.bodies = bodies
|
||||
for (const listener of [...this.listeners]) listener()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
declare module '*.module.css' {
|
||||
const classes: Readonly<Record<string, string>>
|
||||
export default classes
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
/** Browser registration is discovered through the package client declaration. */
|
||||
|
||||
/** Register the browser-only contribution without Host state. */
|
||||
export function apply(): void {}
|
||||
@@ -0,0 +1,74 @@
|
||||
/** Real registries bind actions to the displayed session and remove every contribution on unload. */
|
||||
import { isValidElement } from 'react'
|
||||
import { Context } from '@deepseek-ai/cordis'
|
||||
import { SlotRegistry } from '@deepseek-ai/dsh-client-ui-renderer/client'
|
||||
import { LocaleRuntime } from '@deepseek-ai/dsh-client-locale/client'
|
||||
import { SessionId } from '@deepseek-ai/dsh-session/types'
|
||||
import { ToolCallId } from '@deepseek-ai/dsh-llm/brand'
|
||||
import { expect, it, onTestFinished, vi } from 'vitest'
|
||||
import { mountActionCards, inject } from '../src/client/mount.ts'
|
||||
import { apply as hostApply } from '../src/index.ts'
|
||||
import type { TailInjected } from '../src/client/Card.tsx'
|
||||
|
||||
const apply = (ctx: Context) => mountActionCards(ctx, { package: '@deepseek-ai/dsh-action-cards', descriptors: [] })
|
||||
const Body = () => null
|
||||
|
||||
it('binds actions to the displayed session, serves registered bodies and removes registrations on unload', async () => {
|
||||
hostApply()
|
||||
const ctx = new Context()
|
||||
onTestFinished(() => ctx.fiber.dispose())
|
||||
await ctx.plugin(SlotRegistry)
|
||||
const slots = ctx.slots
|
||||
slots.register({ name: 'root', children: {
|
||||
'conversation.chat.turnTail': { kind: 'list', scope: 'session' },
|
||||
'tool.call.toolview': { kind: 'keyed', scope: 'session' },
|
||||
} }, (_props: { renderSlot?: unknown }) => null)
|
||||
const act = vi.fn().mockResolvedValue({ ok: true, value: { status: 'accepted' } })
|
||||
const unmount = vi.fn(async () => {})
|
||||
ctx.provide('remote', { actionCards: { act }, $mount: vi.fn(async () => unmount) })
|
||||
ctx.provide('remote.actionCards', { act })
|
||||
const locale = new LocaleRuntime(ctx)
|
||||
ctx.provide('locale', locale)
|
||||
const fiber = await ctx.plugin({ inject, apply })
|
||||
const entry = slots.entries('conversation.chat.turnTail')[0]!
|
||||
expect(slots.entries('tool.call.toolview').map(item => item.options.key)).toEqual(['propose_action'])
|
||||
const resolve = entry.inject as NonNullable<typeof entry.inject> & ((sessionId: SessionId) => TailInjected)
|
||||
const bound = resolve(SessionId('session-one'))
|
||||
expect(bound.sessionId).toBe('session-one')
|
||||
expect(await bound.act(ToolCallId('card'), 'create', { slot: 'page' })).toEqual({ status: 'accepted' })
|
||||
expect(act).toHaveBeenCalledWith('session-one', 'card', 'create', { slot: 'page' })
|
||||
act.mockResolvedValueOnce({ ok: false })
|
||||
expect(await bound.act(ToolCallId('card'), 'dismiss')).toBeUndefined()
|
||||
expect(bound.bind('actionCards')('dismiss')).toBe('Not now')
|
||||
const changes = vi.fn()
|
||||
const unsubscribe = bound.hooks.bodies.subscribe(changes)
|
||||
const kind = await ctx.plugin({ inject: ['actionCards'], apply: (inner: Context) => {
|
||||
inner.effect(() => inner.actionCards.register({ action: 'test_action', locale: 'actionCards', Body }))
|
||||
} })
|
||||
expect([...bound.hooks.bodies.getSnapshot().keys()]).toEqual(['test_action'])
|
||||
const translate = (key: string) => key
|
||||
const element = bound.hooks.bodies.getSnapshot().get('test_action')!.render({ proposal: { callId: ToolCallId('card'), turn: 1,
|
||||
action: 'test_action', title: 'Counter', brief: 'Keep count.', details: {} }, decision: undefined,
|
||||
sessionId: SessionId('session-one'), summary: null, Folded: Body, act: vi.fn() }, translate)
|
||||
expect(isValidElement(element) && element.type === Body && (element.props as { t: unknown }).t === translate).toBe(true)
|
||||
expect(() => ctx.actionCards.register({ action: 'test_action', locale: 'actionCards', Body })).toThrow('a body for "test_action" is already registered')
|
||||
await kind.dispose()
|
||||
expect(bound.hooks.bodies.getSnapshot().size).toBe(0)
|
||||
expect(changes).toHaveBeenCalledTimes(2)
|
||||
unsubscribe()
|
||||
const release = ctx.actionCards.register({ action: 'other_action', locale: 'actionCards', Body })
|
||||
expect(bound.hooks.bodies.getSnapshot().has('other_action')).toBe(true)
|
||||
release()
|
||||
expect(bound.hooks.bodies.getSnapshot().has('other_action')).toBe(false)
|
||||
expect(changes).toHaveBeenCalledTimes(2)
|
||||
await fiber.dispose()
|
||||
expect(unmount).toHaveBeenCalledOnce()
|
||||
expect(slots.entries('conversation.chat.turnTail')).toHaveLength(0)
|
||||
expect(slots.entries('tool.call.toolview')).toHaveLength(0)
|
||||
expect(ctx.get('actionCards')).toBeUndefined()
|
||||
vi.spyOn(locale, 'register').mockImplementation(() => { throw new Error('registration failed') })
|
||||
const failed = ctx.plugin({ inject, apply })
|
||||
await expect(failed.await()).rejects.toThrow('registration failed')
|
||||
await failed.dispose()
|
||||
expect(unmount).toHaveBeenCalledTimes(2)
|
||||
})
|
||||
@@ -0,0 +1,141 @@
|
||||
// @vitest-environment jsdom
|
||||
import { memo, type ComponentProps } from 'react'
|
||||
import { act, cleanup, fireEvent, render, screen } from '@testing-library/react'
|
||||
import { afterEach, expect, it, vi } from 'vitest'
|
||||
import { ToolCallId } from '@deepseek-ai/dsh-llm/brand'
|
||||
import { SessionId, SessionSeq } from '@deepseek-ai/dsh-session/types'
|
||||
import type { ActionCardDecision, ActionCardResult, ActionCardView } from '@deepseek-ai/dsh-action-cards/types'
|
||||
import { ActionCard, ActionCardTail, FoldedText } from '../src/client/Card.tsx'
|
||||
import { makeTranslate } from '@deepseek-ai/dsh-client-test-runtime'
|
||||
import { en, zh } from '../src/client/locales.ts'
|
||||
import type { ActionCardBodyProps, RegisteredBody } from '../src/client/registry.ts'
|
||||
|
||||
afterEach(() => { cleanup(); vi.restoreAllMocks(); vi.unstubAllGlobals() })
|
||||
|
||||
type CardProps = ComponentProps<typeof ActionCard>
|
||||
const callId = ToolCallId('card-1')
|
||||
const proposal = { callId, turn: 3, action: 'test_action', title: 'Counter', brief: 'Keep my task count visible.', details: { value: 'a' } }
|
||||
|
||||
function props(bodies: ReadonlyMap<string, RegisteredBody> = new Map(), decision?: ActionCardDecision, chinese = false): CardProps {
|
||||
return { proposal, decision, sessionId: SessionId('session-1'),
|
||||
act: vi.fn(async (): Promise<ActionCardResult | undefined> => ({ status: 'settled', decision: { callId, action: 'test_action', phase: 'dismissed' } })),
|
||||
bind: vi.fn(() => (key: string) => `body:${key}`),
|
||||
useBodies: selector => selector(bodies),
|
||||
t: makeTranslate(chinese ? zh : en) }
|
||||
}
|
||||
|
||||
it('places the card admitted in its turn once the turn has ended with an answer, and leaves other turns empty', () => {
|
||||
type Tail = ComponentProps<typeof ActionCardTail>
|
||||
const value = props()
|
||||
let view: ActionCardView | undefined
|
||||
const turnData = vi.fn().mockReturnValue({ closing: {} })
|
||||
const ended = { type: 'turn/end', seq: SessionSeq(1), time: 0, data: { turn: 3, reason: { kind: 'max-tokens' } } } as const
|
||||
const tail = (end: typeof ended | undefined): Tail => ({ ...value, useProjection: () => view,
|
||||
turn: { turn: 3, start: undefined, end, status: end === undefined ? 'open' : 'closed', steps: [],
|
||||
data: { get: turnData, source: () => ({ getSnapshot: () => undefined, subscribe: () => () => {} }) } } })
|
||||
const card = (id: string, turn: number) => ({ ...proposal, callId: ToolCallId(id), turn })
|
||||
const { rerender } = render(<ActionCardTail {...tail(ended)} />)
|
||||
expect(screen.queryByRole('region')).toBeNull()
|
||||
view = { decisions: {}, proposals: { earlier: card('earlier', 2) } }
|
||||
rerender(<ActionCardTail {...tail(ended)} />)
|
||||
expect(screen.queryByRole('region')).toBeNull()
|
||||
view = { decisions: {}, proposals: { ...view.proposals, b: card('b', 3), a: card('a', 3), c: card('c', 3) } }
|
||||
rerender(<ActionCardTail {...tail(ended)} />)
|
||||
expect(screen.getAllByRole('region').map(region => region.getAttribute('data-action-card'))).toEqual(['a'])
|
||||
expect(screen.getByRole('region', { name: 'Counter' }).getAttribute('data-action')).toBe('test_action')
|
||||
expect(turnData).toHaveBeenCalledWith('turn-tail')
|
||||
rerender(<ActionCardTail {...tail(undefined)} />)
|
||||
expect(screen.queryByRole('region')).toBeNull()
|
||||
turnData.mockReturnValueOnce({ closing: null })
|
||||
rerender(<ActionCardTail {...tail(ended)} />)
|
||||
expect(screen.queryByRole('region')).toBeNull()
|
||||
view = { ...view, decisions: { a: { callId: ToolCallId('a'), action: 'test_action', phase: 'dismissed' } } }
|
||||
rerender(<ActionCardTail {...tail(ended)} />)
|
||||
expect(screen.getByRole('status').textContent).toBe(en.dismissed)
|
||||
// A call id naming an inherited object member reads no decision.
|
||||
view = { decisions: {}, proposals: { toString: card('toString', 3) } }
|
||||
rerender(<ActionCardTail {...tail(ended)} />)
|
||||
expect(screen.getByRole('region').getAttribute('data-action-card')).toBe('toString')
|
||||
expect(screen.getByRole('button', { name: en.dismiss })).toBeTruthy()
|
||||
})
|
||||
|
||||
it('renders a registered body with the frame summary, the fold, its own translator and an action bound to the card', async () => {
|
||||
const seen: ActionCardBodyProps<never>[] = []
|
||||
const Body = memo((body: ActionCardBodyProps<never>) => {
|
||||
seen.push(body)
|
||||
return <div>{body.summary}<button type="button" onClick={() => { void body.act('start', { value: 'x' }) }}>{body.t('start' as never)}</button>
|
||||
<body.Folded text="Long details" expandLabel="more" collapseLabel="less" /></div>
|
||||
})
|
||||
const bodies = new Map<string, RegisteredBody>([['test_action', { locale: 'testCard', render: (frame, t) => <Body {...frame} t={t} /> }]])
|
||||
const value = props(bodies, { callId, action: 'test_action', phase: 'running' })
|
||||
render(<ActionCard {...value} />)
|
||||
expect(value.bind).toHaveBeenCalledWith('testCard')
|
||||
expect(screen.getByRole('region', { name: 'Counter' }).textContent).toContain('Keep my task count visible.')
|
||||
expect(screen.getByText('Long details')).toBeTruthy()
|
||||
expect(seen.at(-1)).toMatchObject({ proposal, decision: { phase: 'running' }, sessionId: 'session-1', Folded: FoldedText })
|
||||
fireEvent.click(screen.getByRole('button', { name: 'body:start' }))
|
||||
expect(value.act).toHaveBeenCalledWith(callId, 'start', { value: 'x' })
|
||||
})
|
||||
|
||||
it('offers only Not now for a card whose kind registered no body, and reports refusals and lost replies', async () => {
|
||||
const value = props(new Map(), undefined, true)
|
||||
const pending = Promise.withResolvers<ActionCardResult | undefined>()
|
||||
value.act = vi.fn().mockReturnValueOnce(pending.promise).mockResolvedValueOnce(undefined)
|
||||
.mockRejectedValueOnce(new Error('disconnected')).mockResolvedValueOnce({ status: 'unconfirmed', reason: 'closing' })
|
||||
.mockResolvedValueOnce({ status: 'accepted' })
|
||||
render(<ActionCard {...value} />)
|
||||
expect(screen.getByRole('region', { name: 'Counter' }).textContent).toContain('Keep my task count visible.')
|
||||
const dismiss = screen.getByRole('button', { name: zh.dismiss })
|
||||
fireEvent.click(dismiss)
|
||||
expect(dismiss.hasAttribute('disabled')).toBe(true)
|
||||
expect(value.act).toHaveBeenCalledWith(callId, 'dismiss', undefined)
|
||||
await act(async () => { pending.resolve({ status: 'refused', reason: 'unknown' }) })
|
||||
expect(screen.getByRole('alert').textContent).toBe(zh.unavailable)
|
||||
for (const text of [zh.transport, zh.transport, zh.unavailable]) {
|
||||
fireEvent.click(screen.getByRole('button', { name: zh.dismiss }))
|
||||
await vi.waitFor(() => { expect(screen.getByRole('alert').textContent).toBe(text) })
|
||||
}
|
||||
fireEvent.click(screen.getByRole('button', { name: zh.dismiss }))
|
||||
await vi.waitFor(() => { expect(screen.queryByRole('alert')).toBeNull() })
|
||||
})
|
||||
|
||||
it('dismisses a card through the fallback Not now when the Host records the dismissal without the card kind', async () => {
|
||||
const value = props()
|
||||
render(<ActionCard {...value} />)
|
||||
const dismiss = screen.getByRole('button', { name: en.dismiss })
|
||||
fireEvent.click(dismiss)
|
||||
expect(value.act).toHaveBeenCalledWith(callId, 'dismiss', undefined)
|
||||
await vi.waitFor(() => { expect(dismiss.hasAttribute('disabled')).toBe(false) })
|
||||
expect(screen.queryByRole('alert')).toBeNull()
|
||||
})
|
||||
|
||||
it.each([['dismissed', en.dismissed], ['replaced', en.replaced], ['finished', undefined], ['toString', undefined]] as const)(
|
||||
'shows the fallback status of a %s card without actions', (phase, text) => {
|
||||
render(<ActionCard {...props(new Map(), { callId, action: 'test_action', phase })} />)
|
||||
expect(screen.queryByRole('status')?.textContent).toBe(text)
|
||||
expect(screen.queryByRole('button', { name: en.dismiss })).toBeNull()
|
||||
})
|
||||
|
||||
it('only offers expansion for omitted text and preserves the full brief without layout measurement', () => {
|
||||
vi.stubGlobal('ResizeObserver', undefined)
|
||||
const short = 'Keep my task count visible.\n\nPersist across conversations.\nVerify removal.'
|
||||
const view = render(<FoldedText text={short} expandLabel={zh.expandBrief} collapseLabel={zh.collapseBrief} />)
|
||||
expect(screen.queryByRole('button', { name: zh.expandBrief })).toBeNull()
|
||||
expect(screen.getByText(/Keep my task count visible/).textContent).toBe(short)
|
||||
// 129 wide graphemes (258 units) plus one narrow emoji fill the 260-unit budget; the next grapheme folds.
|
||||
const prefix = '计'.repeat(129) + '👩🏽💻'
|
||||
const long = prefix + '\n\n保留完整方案,点击创建后交给 Creator。'
|
||||
view.rerender(<FoldedText text={long} expandLabel={zh.expandBrief} collapseLabel={zh.collapseBrief} />)
|
||||
const expand = screen.getByRole('button', { name: zh.expandBrief })
|
||||
const paragraph = document.getElementById(expand.getAttribute('aria-controls')!)!
|
||||
expect(paragraph.textContent).toBe(prefix + '…')
|
||||
expect(expand.getAttribute('aria-expanded')).toBe('false')
|
||||
fireEvent.click(expand)
|
||||
expect(screen.getByRole('button', { name: zh.collapseBrief }).getAttribute('aria-expanded')).toBe('true')
|
||||
expect(paragraph.textContent).toBe(long)
|
||||
fireEvent.click(screen.getByRole('button', { name: zh.collapseBrief }))
|
||||
expect(paragraph.textContent).toBe(prefix + '…')
|
||||
view.rerender(<FoldedText text={prefix} expandLabel={zh.expandBrief} collapseLabel={zh.collapseBrief} />)
|
||||
expect(screen.queryByRole('button', { name: zh.expandBrief })).toBeNull()
|
||||
expect(paragraph.textContent).toBe(prefix)
|
||||
})
|
||||
@@ -0,0 +1,55 @@
|
||||
// @vitest-environment jsdom
|
||||
/** The process row reads the card title from the recorded arguments and expands only a refused call. */
|
||||
import { cleanup, fireEvent, render } from '@testing-library/react'
|
||||
import { afterEach, expect, it, vi } from 'vitest'
|
||||
import type { StartedToolCall, ToolResultNode } from '@deepseek-ai/dsh-client-ui-chat/client'
|
||||
import { makeTranslate } from '@deepseek-ai/dsh-client-test-runtime'
|
||||
import { PartialArguments } from '@deepseek-ai/dsh-util-values'
|
||||
import { ProposeRow } from '../src/client/ProposeRow.tsx'
|
||||
import { en } from '../src/client/locales.ts'
|
||||
|
||||
afterEach(cleanup)
|
||||
type Props = Parameters<typeof ProposeRow>[0]
|
||||
const argsRaw = JSON.stringify({ action: 'test_action', title: 'Counter', brief: 'Keep count.', details: {} })
|
||||
const running: StartedToolCall = { phase: 'start', args: PartialArguments.fromText(argsRaw), callId: 'c', name: 'propose_action', argsRaw, turn: 1, step: 1, time: 1, subCalls: [] }
|
||||
const settled: ToolResultNode = { kind: 'tool-result', seq: 2, time: 2, callId: 'c', name: 'propose_action', args: PartialArguments.fromText(argsRaw),
|
||||
call: { name: 'propose_action', argsRaw }, callTime: 1, content: [{ type: 'text', text: 'Card shown below your answer. Do not restate it. Invite the user.' }], isError: false, subCalls: [] }
|
||||
function props(block: Props['block'], inspect?: () => void): Props {
|
||||
return { ...('kind' in block ? { phase: 'result' as const, block } : { phase: block.phase, block }),
|
||||
callId: 'c', toolName: 'propose_action', openFile: vi.fn(), inspect, t: makeTranslate(en) } as Props
|
||||
}
|
||||
|
||||
it('shows a proposed card on one line without exposing the model-facing result', () => {
|
||||
const view = render(<ProposeRow {...props(settled)} />)
|
||||
expect(view.container.querySelector('[data-tool="propose_action"]')?.getAttribute('data-state')).toBe('ok')
|
||||
expect(view.getByText('Proposed')).toBeTruthy()
|
||||
expect(view.getByText('Counter')).toBeTruthy()
|
||||
expect(view.queryByRole('button')).toBeNull()
|
||||
expect(view.container.textContent).not.toContain('Card shown below your answer. Do not restate it. Invite the user.')
|
||||
})
|
||||
|
||||
it('explains a refused call and offers call inspection', () => {
|
||||
const inspect = vi.fn()
|
||||
const view = render(<ProposeRow {...props({ ...settled, isError: true,
|
||||
content: [{ type: 'text', text: 'Error: Load skill test-skill first, then call propose_action.' }, { type: 'reasoning', text: 'hidden' }] }, inspect)} />)
|
||||
expect(view.getByText('Not shown')).toBeTruthy()
|
||||
const row = view.getByRole('button')
|
||||
fireEvent.click(row)
|
||||
expect(view.container.querySelector('pre')?.textContent).toBe('Error: Load skill test-skill first, then call propose_action.')
|
||||
fireEvent.click(view.getByRole('button', { name: 'Inspect call' }))
|
||||
expect(inspect).toHaveBeenCalledOnce()
|
||||
fireEvent.click(row)
|
||||
expect(row.getAttribute('aria-expanded')).toBe('false')
|
||||
})
|
||||
|
||||
it.each([
|
||||
['preparing', { phase: 'preparing', args: PartialArguments.EMPTY, callId: 'c', name: 'propose_action', turn: 1, step: 1, time: 1, subCalls: [] }, 'Preparing a card'],
|
||||
['running', running, 'Proposing'],
|
||||
['stopped', { ...settled, isError: true, content: [], error: { name: 'Interrupted', code: 'interrupted' } }, 'Interrupted'],
|
||||
] as const)('renders the %s call stage without claiming a card', (state, block, label) => {
|
||||
const view = render(<ProposeRow {...props(block)} />)
|
||||
expect(view.container.querySelector('[data-tool="propose_action"]')?.getAttribute('data-state')).toBe(state)
|
||||
expect(view.getAllByText(label).length).toBeGreaterThan(0)
|
||||
expect(view.queryByText('Proposed')).toBeNull()
|
||||
expect(view.queryByRole('button')).toBeNull()
|
||||
})
|
||||
@@ -0,0 +1,27 @@
|
||||
{
|
||||
"extends": "../../../tsconfig.base.client.json",
|
||||
"compilerOptions": {
|
||||
"rootDir": "src",
|
||||
"outDir": "lib/types"
|
||||
},
|
||||
"include": [
|
||||
"src"
|
||||
],
|
||||
"references": [
|
||||
{ "path": "../../client/ui-renderer" },
|
||||
{ "path": "../../../vendor/cordis" },
|
||||
{ "path": "../../api/remotes/tsconfig.client.json" },
|
||||
{ "path": "../../client/locale/tsconfig.client.json" },
|
||||
{ "path": "../../client/ui-conversation/tsconfig.client.json" },
|
||||
{ "path": "../../client/ui-chat/tsconfig.client.json" },
|
||||
{ "path": "../../client/ui-session" },
|
||||
{ "path": "../../client/ui-slots" },
|
||||
{ "path": "../../client/ui-primitives" },
|
||||
{ "path": "../../client/ui-tool" },
|
||||
{ "path": "../../llm/llm" },
|
||||
{ "path": "../../core/session" },
|
||||
{ "path": "../action-cards" },
|
||||
{ "path": "../../typert/protocol" },
|
||||
{ "path": "../../util/values" }
|
||||
]
|
||||
}
|
||||
Loaded 100 of 254 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user