dsh-ntr 0.3.1 → 0.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.en.md +1 -1
- package/README.md +1 -1
- package/cordis.patch.yml +17 -1
- package/lib/bridge.js +607 -18
- package/lib/client/acp-ui.js +103 -3
- package/lib/client/acp-view.js +24 -4
- package/lib/client/branch-action.js +133 -0
- package/lib/client/composer-mode.js +48 -13
- package/lib/client/context-meter.js +86 -0
- package/lib/client/index.js +238 -15
- package/lib/client/panel.js +96 -29
- package/lib/client/released-banner.js +66 -0
- package/lib/client/session-controls.js +38 -13
- package/lib/client/slash-isolation.js +2 -2
- package/lib/client/store.js +348 -13
- package/lib/client.js +1138 -67
- package/lib/client.js.map +1 -1
- package/lib/impl.js +54 -1
- package/lib/index.js +7 -0
- package/lib/protocol.js +19 -0
- package/lib/types/bridge.d.ts +229 -6
- package/lib/types/client/acp-ui.d.ts +34 -2
- package/lib/types/client/acp-view.d.ts +13 -2
- package/lib/types/client/branch-action.d.ts +40 -0
- package/lib/types/client/composer-mode.d.ts +28 -0
- package/lib/types/client/context-meter.d.ts +51 -0
- package/lib/types/client/released-banner.d.ts +34 -0
- package/lib/types/client/slash-isolation.d.ts +1 -1
- package/lib/types/client/store.d.ts +98 -1
- package/lib/types/impl.d.ts +41 -1
- package/lib/types/protocol.d.ts +123 -0
- package/package.json +2 -1
- package/src/bridge.ts +638 -20
- package/src/client/acp-ui.tsx +123 -2
- package/src/client/acp-view.tsx +30 -5
- package/src/client/branch-action.tsx +160 -0
- package/src/client/composer-mode.tsx +59 -13
- package/src/client/context-meter.tsx +128 -0
- package/src/client/index.tsx +265 -14
- package/src/client/panel.tsx +157 -40
- package/src/client/primitives.d.ts +27 -0
- package/src/client/released-banner.tsx +97 -0
- package/src/client/session-controls.tsx +34 -11
- package/src/client/slash-isolation.ts +2 -1
- package/src/client/store.ts +375 -14
- package/src/impl.ts +84 -2
- package/src/index.ts +8 -0
- package/src/protocol.ts +121 -0
package/src/impl.ts
CHANGED
|
@@ -7,10 +7,10 @@
|
|
|
7
7
|
|
|
8
8
|
import { randomUUID } from './ids.ts'
|
|
9
9
|
import type {
|
|
10
|
-
AcpAgentCatalog, AcpAgentDef, AcpCatalogOption, AcpApprovalDeadlines, AcpConversationChoice, AcpEvent, AcpMcpServerDef, AcpPluginConfig, AcpPresetStatus, AcpTagHalo, AgentCatalogResult, AgentProbeModelsResult, AgentTestResult,
|
|
10
|
+
AcpAgentCatalog, AcpAgentDef, AcpCatalogOption, AcpApprovalDeadlines, AcpConversationChoice, AcpEvent, AcpIdleRelease, AcpMcpServerDef, AcpPluginConfig, AcpPresetStatus, AcpTagHalo, AgentCatalogResult, AgentProbeModelsResult, AgentTestResult,
|
|
11
11
|
AgentView, ApprovalDeadlineKey, ApprovalDeadlinePatch, ChatSessionView, ChatTranscriptView, DetectedAgentInfo, PermissionOptionView, PermissionOutcome, PermissionTimeoutMode, PluginUpdateState, RpcResult,
|
|
12
12
|
} from './protocol.ts'
|
|
13
|
-
import { DEFAULT_TAG_HALO } from './protocol.ts'
|
|
13
|
+
import { DEFAULT_IDLE_TIMEOUT_MS, DEFAULT_TAG_HALO, IDLE_RELEASE_MS } from './protocol.ts'
|
|
14
14
|
|
|
15
15
|
export { randomUUID }
|
|
16
16
|
|
|
@@ -175,6 +175,21 @@ export function validateApprovalDeadlines(value: unknown): Partial<Record<Approv
|
|
|
175
175
|
return out
|
|
176
176
|
}
|
|
177
177
|
|
|
178
|
+
/**
|
|
179
|
+
* Validate the idle-release window the settings page writes.
|
|
180
|
+
*
|
|
181
|
+
* The window is expressed in MILLISECONDS on the shared ladder
|
|
182
|
+
* ({@link IDLE_RELEASE_MS}), so a value the slider can produce is always a
|
|
183
|
+
* value the host runs — the same one-ladder rule the approval deadline card
|
|
184
|
+
* follows.
|
|
185
|
+
*/
|
|
186
|
+
export function validateIdleReleaseMs(raw: unknown, code: 'bad_config' | 'bad_payload'): number {
|
|
187
|
+
if (typeof raw !== 'number' || !Number.isInteger(raw) || !IDLE_RELEASE_MS.includes(raw)) {
|
|
188
|
+
throw new AcpError(code, `acp: idleTimeoutMs must be one of ${IDLE_RELEASE_MS.join(', ')}`)
|
|
189
|
+
}
|
|
190
|
+
return raw
|
|
191
|
+
}
|
|
192
|
+
|
|
178
193
|
/**
|
|
179
194
|
* Validate the mode a write asks for. Three values, and the list is the whole
|
|
180
195
|
* vocabulary: an unanswered ask is either answered for you, kept waiting, or
|
|
@@ -523,6 +538,14 @@ export function validateConfig(raw: unknown): AcpPluginConfig {
|
|
|
523
538
|
// `abort` a zero window would refuse every ask on arrival — the agent stops
|
|
524
539
|
// at every gate — so it becomes the shortest real wait.
|
|
525
540
|
const effectivePermissionTimeoutMs = normalizeApprovalWindow(permissionTimeoutMode, permissionTimeoutMs)
|
|
541
|
+
// The chat-process idle-release window (the settings page edits it).
|
|
542
|
+
// Same shape as the per-agent field: 0 = never release, otherwise an
|
|
543
|
+
// integer number of milliseconds.
|
|
544
|
+
const idleTimeoutMs = value.idleTimeoutMs ?? DEFAULT_IDLE_TIMEOUT_MS
|
|
545
|
+
if (typeof idleTimeoutMs !== 'number' || !Number.isInteger(idleTimeoutMs)
|
|
546
|
+
|| idleTimeoutMs > 86_400_000 || (idleTimeoutMs !== 0 && idleTimeoutMs < 1_000)) {
|
|
547
|
+
throw new AcpError('bad_config', 'acp: idleTimeoutMs must be 0 (never release) or an integer in [1000, 86400000]')
|
|
548
|
+
}
|
|
526
549
|
const cancelFallbackMs = value.cancelFallbackMs ?? 15_000
|
|
527
550
|
if (typeof cancelFallbackMs !== 'number' || !Number.isInteger(cancelFallbackMs) || cancelFallbackMs < 0 || cancelFallbackMs > 600_000) {
|
|
528
551
|
throw new AcpError('bad_config', 'acp: cancelFallbackMs must be an integer in [0, 600000] (0 = disable the fallback)')
|
|
@@ -564,6 +587,7 @@ export function validateConfig(raw: unknown): AcpPluginConfig {
|
|
|
564
587
|
turnStallMs,
|
|
565
588
|
turnStallToolMs,
|
|
566
589
|
turnStallTickMs,
|
|
590
|
+
idleTimeoutMs,
|
|
567
591
|
}
|
|
568
592
|
}
|
|
569
593
|
|
|
@@ -1789,6 +1813,19 @@ export interface AcpManager {
|
|
|
1789
1813
|
* applies again. Applies to the running bridges without a restart.
|
|
1790
1814
|
*/
|
|
1791
1815
|
setApprovalDeadlines?(patch: ApprovalDeadlinePatch, reset?: boolean): Promise<void>
|
|
1816
|
+
/**
|
|
1817
|
+
* The idle-release window in force for chat processes, plus the built-in
|
|
1818
|
+
* default a reset returns to. `undefined` on a host half from before the
|
|
1819
|
+
* card existed, which hides the settings tab instead of showing a number
|
|
1820
|
+
* this browser invented.
|
|
1821
|
+
*/
|
|
1822
|
+
idleRelease?(): AcpIdleRelease | undefined
|
|
1823
|
+
/**
|
|
1824
|
+
* Write the idle-release window (in ms), or drop the persisted
|
|
1825
|
+
* override with `reset` so the built-in default applies again. Applies to
|
|
1826
|
+
* the running bridges without a restart.
|
|
1827
|
+
*/
|
|
1828
|
+
setIdleRelease?(idleTimeoutMs: number | undefined, reset?: boolean): Promise<void>
|
|
1792
1829
|
detectAgents?(): Promise<DetectedAgentInfo[]>
|
|
1793
1830
|
saveAgent?(def: AcpAgentDef): Promise<void>
|
|
1794
1831
|
deleteAgent?(agentId: string): Promise<void>
|
|
@@ -1861,6 +1898,21 @@ export interface AcpManager {
|
|
|
1861
1898
|
* without it the live (non-released) session is picked.
|
|
1862
1899
|
*/
|
|
1863
1900
|
setChatSessionMode?(dshSessionId: string, modeId: string, agentId?: string): Promise<void>
|
|
1901
|
+
/**
|
|
1902
|
+
* Bring one chat conversation's released session back on a fresh process on
|
|
1903
|
+
* the user's explicit gesture (`session/chat-resume`, the released-session
|
|
1904
|
+
* banner's button). Same recovery the next prompt performs lazily, minus
|
|
1905
|
+
* the create path; no-op when the session is already live.
|
|
1906
|
+
*/
|
|
1907
|
+
resumeChatSession?(dshSessionId: string): Promise<void>
|
|
1908
|
+
/**
|
|
1909
|
+
* Adopt the ACP side of a branched conversation (`session/chat-fork-adopt`):
|
|
1910
|
+
* the browser has already asked the HOST to fork the DSH session tree, and
|
|
1911
|
+
* this runs the agent's own `session/fork` of the parent's live ACP session,
|
|
1912
|
+
* then binds the child to it. All-or-nothing — nothing is bound on failure,
|
|
1913
|
+
* so the child stays an ordinary copied-history conversation.
|
|
1914
|
+
*/
|
|
1915
|
+
adoptForkedSession?(childDshSessionId: string, parentDshSessionId: string): Promise<{ sessionId: string; acpSessionId: string }>
|
|
1864
1916
|
/**
|
|
1865
1917
|
* Point one DSH chat conversation at an ACP agent — the plugin's own
|
|
1866
1918
|
* conversation↔agent mapping, never a DSH model route (see
|
|
@@ -2055,6 +2107,26 @@ export async function dispatchRpc(manager: AcpManager, endpoint: string, payload
|
|
|
2055
2107
|
await manager.setChatSessionMode?.(dshSessionId, modeId, optionalStr(body, 'agentId', 64))
|
|
2056
2108
|
return ok({ done: true })
|
|
2057
2109
|
}
|
|
2110
|
+
case 'session/chat-resume': {
|
|
2111
|
+
// The released-session banner's explicit resume: the recovery the next
|
|
2112
|
+
// prompt performs lazily, on the user's gesture instead. Addressed by
|
|
2113
|
+
// DSH chat session id, like the rest of the conversation surfaces.
|
|
2114
|
+
const dshSessionId = str(body, 'dshSessionId', 128)
|
|
2115
|
+
await manager.resumeChatSession?.(dshSessionId)
|
|
2116
|
+
return ok({ done: true })
|
|
2117
|
+
}
|
|
2118
|
+
case 'session/chat-fork-adopt': {
|
|
2119
|
+
// The second half of a branched conversation: bind the DSH session the
|
|
2120
|
+
// host's `sessions.fork` just created to the agent's own `session/fork`
|
|
2121
|
+
// of the parent's live ACP session. Both ids are validated before the
|
|
2122
|
+
// optional call — the same shape rule as `session/chat-list` above.
|
|
2123
|
+
// The adopted ids ride the answer (the protocol's ChatForkAdoptResult);
|
|
2124
|
+
// a manager without the method keeps the plain `done` shape.
|
|
2125
|
+
const dshSessionId = str(body, 'dshSessionId', 128)
|
|
2126
|
+
const parentDshSessionId = str(body, 'parentDshSessionId', 128)
|
|
2127
|
+
const adopted = await manager.adoptForkedSession?.(dshSessionId, parentDshSessionId)
|
|
2128
|
+
return ok(adopted ?? { done: true })
|
|
2129
|
+
}
|
|
2058
2130
|
case 'session/chat-bind': {
|
|
2059
2131
|
// Point one chat conversation at an ACP agent. The plugin's own
|
|
2060
2132
|
// conversation↔agent mapping — NOT a DSH model route (see
|
|
@@ -2141,6 +2213,16 @@ export async function dispatchRpc(manager: AcpManager, endpoint: string, payload
|
|
|
2141
2213
|
await manager.setApprovalDeadlines?.(patch, body.reset === true)
|
|
2142
2214
|
return ok({ deadlines: manager.approvalDeadlines?.() })
|
|
2143
2215
|
}
|
|
2216
|
+
case 'ui/idle-release':
|
|
2217
|
+
// Absent on a host half from before the tab existed: the browser then
|
|
2218
|
+
// renders nothing rather than a number it cannot trust.
|
|
2219
|
+
return ok({ idleRelease: manager.idleRelease?.() })
|
|
2220
|
+
case 'ui/idle-release-set': {
|
|
2221
|
+
const reset = body.reset === true
|
|
2222
|
+
const idleTimeoutMs = reset ? undefined : validateIdleReleaseMs(body.idleTimeoutMs, 'bad_payload')
|
|
2223
|
+
await manager.setIdleRelease?.(idleTimeoutMs, reset)
|
|
2224
|
+
return ok({ idleRelease: manager.idleRelease?.() })
|
|
2225
|
+
}
|
|
2144
2226
|
case 'agent/set-exposed-models': {
|
|
2145
2227
|
const agentId = str(body, 'agentId', 64)
|
|
2146
2228
|
const raw = body.exposedModels
|
package/src/index.ts
CHANGED
|
@@ -91,6 +91,7 @@ export function apply(ctx: Context, config?: unknown): void {
|
|
|
91
91
|
turnStallMs: resolved.turnStallMs,
|
|
92
92
|
turnStallToolMs: resolved.turnStallToolMs,
|
|
93
93
|
turnStallTickMs: resolved.turnStallTickMs,
|
|
94
|
+
idleTimeoutMs: resolved.idleTimeoutMs,
|
|
94
95
|
},
|
|
95
96
|
)
|
|
96
97
|
const adapter = new AcpLlmAdapter(manager)
|
|
@@ -126,6 +127,13 @@ export function apply(ctx: Context, config?: unknown): void {
|
|
|
126
127
|
? rawConfig.permissionTimeoutMode
|
|
127
128
|
: undefined
|
|
128
129
|
manager.setConfiguredApprovalDeadlines(configuredDeadlines, configuredMode)
|
|
130
|
+
|
|
131
|
+
// The idle-release baseline the settings page's pick outranks. Only the
|
|
132
|
+
// raw value counts: `validateConfig` fills a default in, so the
|
|
133
|
+
// validated number cannot tell "the file says 10 minutes" from
|
|
134
|
+
// "the file says nothing, so 30 minutes applies".
|
|
135
|
+
const configuredIdleTimeoutMs = typeof rawConfig.idleTimeoutMs === 'number' ? rawConfig.idleTimeoutMs : undefined
|
|
136
|
+
manager.setConfiguredIdleRelease(configuredIdleTimeoutMs)
|
|
129
137
|
// Boot hook kept only so this entry point's shape does not change:
|
|
130
138
|
// `bootstrapCatalogs` is intentionally empty — boot never spawns an agent,
|
|
131
139
|
// in any environment and for any `probeModelsOnBoot` value. Catalogs fill
|
package/src/protocol.ts
CHANGED
|
@@ -187,6 +187,18 @@ export interface AcpPluginConfig {
|
|
|
187
187
|
* deployment baseline that override falls back to. See {@link AcpApprovalDeadlines}.
|
|
188
188
|
*/
|
|
189
189
|
permissionTimeoutMs?: number
|
|
190
|
+
/**
|
|
191
|
+
* How long a chat process may sit idle before it is released (parked, then
|
|
192
|
+
* resumed by the next message). In MILLISECONDS; default 1800000 (30 min).
|
|
193
|
+
*
|
|
194
|
+
* This is the HOST DEFAULT: an agent that names its own
|
|
195
|
+
* {@link AcpAgentDef.idleTimeoutMs} keeps its own. Editable from the
|
|
196
|
+
* settings page (「进程管理」 → `ui/idle-release-set`), which persists an
|
|
197
|
+
* override in the plugin's own state file and applies it to the running
|
|
198
|
+
* bridges without restarting anything; the value here is the deployment
|
|
199
|
+
* baseline that override falls back to. See {@link AcpIdleRelease}.
|
|
200
|
+
*/
|
|
201
|
+
idleTimeoutMs?: number
|
|
190
202
|
/**
|
|
191
203
|
* LEGACY: the old conversation-route window, kept so an existing
|
|
192
204
|
* `cordis.patch.yml` still says what it meant. Folded into
|
|
@@ -490,6 +502,14 @@ export interface SessionView {
|
|
|
490
502
|
* recover") when the agent declares the `loadSession` capability.
|
|
491
503
|
*/
|
|
492
504
|
released?: boolean
|
|
505
|
+
/**
|
|
506
|
+
* The agent-side session has history while the local buffer is empty: the
|
|
507
|
+
* record was restored from disk after a host restart (the `session/load`
|
|
508
|
+
* replay has not landed), or a resume cleared the buffer ahead of the
|
|
509
|
+
* replay. The ACP view then says history replays on restore instead of
|
|
510
|
+
* claiming "nothing yet".
|
|
511
|
+
*/
|
|
512
|
+
hasHistory?: boolean
|
|
493
513
|
/** Highest transcript seq included in this snapshot (for gap detection). */
|
|
494
514
|
seq: number
|
|
495
515
|
}
|
|
@@ -543,8 +563,36 @@ export interface ChatSessionView {
|
|
|
543
563
|
* agent can never see.
|
|
544
564
|
*/
|
|
545
565
|
availableCommands?: SessionView['availableCommands']
|
|
566
|
+
/**
|
|
567
|
+
* Context occupancy the agent last reported (`usage_update`): prompt-side
|
|
568
|
+
* used/size, not request tokens. Absent until the agent reports one; the
|
|
569
|
+
* browser live-patches this row from the update frames (see AGENTS/ui.md).
|
|
570
|
+
*/
|
|
571
|
+
usage?: SessionView['usage']
|
|
546
572
|
/** The agent process died; the session awaits a `session/load` resume. */
|
|
547
573
|
released?: boolean
|
|
574
|
+
/** The agent is running a turn on this session right now. */
|
|
575
|
+
running?: boolean
|
|
576
|
+
/**
|
|
577
|
+
* Whether this session's ACP agent can be forked (`session/fork`) into a
|
|
578
|
+
* child conversation, as the host computed it. The browser does not derive
|
|
579
|
+
* this itself — the capability is host knowledge (the agent's
|
|
580
|
+
* `initialize`), and the row is the one place it is delivered.
|
|
581
|
+
* `supported: false` carries the reason; no reason on `false` means the
|
|
582
|
+
* host half predates the field (treat as unsupported).
|
|
583
|
+
*/
|
|
584
|
+
fork?: ChatSessionForkInfo
|
|
585
|
+
}
|
|
586
|
+
/**
|
|
587
|
+
* The host's per-row verdict on forking one chat session's ACP session
|
|
588
|
+
* (`ChatSessionView.fork`). Computed from the agent's LAST KNOWN
|
|
589
|
+
* `sessionCapabilities.fork` (persisted with the model catalog) plus the
|
|
590
|
+
* session's own state — the browser never reads capability bits itself.
|
|
591
|
+
*/
|
|
592
|
+
export interface ChatSessionForkInfo {
|
|
593
|
+
supported: boolean
|
|
594
|
+
/** Why {@link supported} is false: the agent cannot fork, or the session cannot be forked right now. */
|
|
595
|
+
reason?: 'unsupported' | 'released' | 'busy'
|
|
548
596
|
}
|
|
549
597
|
export type ChatSessionsListResult = { sessions: ChatSessionView[] }
|
|
550
598
|
|
|
@@ -668,6 +716,63 @@ export interface TagHaloSetPayload { halo: AcpTagHalo }
|
|
|
668
716
|
/** The approval deadline the settings page can edit, by field name. ONE window. */
|
|
669
717
|
export type ApprovalDeadlineKey = 'permissionTimeoutMs'
|
|
670
718
|
|
|
719
|
+
/**
|
|
720
|
+
* The idle-release windows the settings page offers, in MILLISECONDS.
|
|
721
|
+
*
|
|
722
|
+
* ONE ladder, shared by both halves: the browser snaps its slider to these
|
|
723
|
+
* values and the host accepts only these values, so a window the slider can
|
|
724
|
+
* produce is always a window the host runs. The first rung is 1 minute (an
|
|
725
|
+
* aggressive release), the rest are 5-minute steps up to an hour.
|
|
726
|
+
*/
|
|
727
|
+
export const IDLE_RELEASE_MS: readonly number[] = [
|
|
728
|
+
60_000, 300_000, 600_000, 900_000, 1_200_000, 1_500_000, 1_800_000, 2_100_000, 2_400_000, 2_700_000, 3_000_000, 3_300_000, 3_600_000,
|
|
729
|
+
]
|
|
730
|
+
|
|
731
|
+
/**
|
|
732
|
+
* The built-in idle-release window for chat processes: 30 minutes.
|
|
733
|
+
*
|
|
734
|
+
* Lives beside the ladder it is a rung of, so the two cannot drift: a
|
|
735
|
+
* deployment that names no window of its own runs this, and the settings
|
|
736
|
+
* page's reset returns to it.
|
|
737
|
+
*/
|
|
738
|
+
export const DEFAULT_IDLE_TIMEOUT_MS = 1_800_000
|
|
739
|
+
|
|
740
|
+
/**
|
|
741
|
+
* The idle-release window for chat processes, as the settings page edits it.
|
|
742
|
+
*
|
|
743
|
+
* The window is the HOST default: an agent that names its own
|
|
744
|
+
* {@link AcpAgentDef.idleTimeoutMs} keeps it, and a probe-only process (one
|
|
745
|
+
* that never hosted a session) still honors the short probe window — see
|
|
746
|
+
* `AGENTS/protocol.md` §5.
|
|
747
|
+
*/
|
|
748
|
+
export interface AcpIdleRelease {
|
|
749
|
+
/** The window in force, in ms. */
|
|
750
|
+
idleTimeoutMs: number
|
|
751
|
+
/**
|
|
752
|
+
* The window a RESET returns to: the deployment baseline when the config
|
|
753
|
+
* file names one, else the built-in default (30 minutes).
|
|
754
|
+
*/
|
|
755
|
+
defaultIdleTimeoutMs: number
|
|
756
|
+
/**
|
|
757
|
+
* The window `cordis.patch.yml` names, when it names one. Reported only
|
|
758
|
+
* when the file actually names one: the settings card must not say "the
|
|
759
|
+
* file asks for 30 minutes" about a file that says nothing.
|
|
760
|
+
*/
|
|
761
|
+
configuredIdleTimeoutMs?: number
|
|
762
|
+
}
|
|
763
|
+
/** `ui/idle-release`: read the idle-release window in force. */
|
|
764
|
+
export type IdleReleaseResult = { idleRelease?: AcpIdleRelease }
|
|
765
|
+
/**
|
|
766
|
+
* `ui/idle-release-set`: write the idle-release window, or drop the persisted
|
|
767
|
+
* override with `reset` so the built-in default applies again.
|
|
768
|
+
*/
|
|
769
|
+
export interface IdleReleaseSetPayload {
|
|
770
|
+
/** The window to run, in ms; omitted when `reset` is true. */
|
|
771
|
+
idleTimeoutMs?: number
|
|
772
|
+
/** Drop the persisted override so the built-in default applies again. */
|
|
773
|
+
reset?: boolean
|
|
774
|
+
}
|
|
775
|
+
|
|
671
776
|
/**
|
|
672
777
|
* What an EXPIRED approval deadline does. Three modes, and only three — an
|
|
673
778
|
* unanswered ask either gets answered for you, keeps waiting, or is refused.
|
|
@@ -752,6 +857,22 @@ export interface ChatEffortSetPayload { dshSessionId: string; effort?: string; a
|
|
|
752
857
|
/** `session/chat-config-set`: set one of the agent's extra config options. */
|
|
753
858
|
export interface ChatConfigSetPayload { dshSessionId: string; configId: string; value: string | boolean; agentId?: string }
|
|
754
859
|
|
|
860
|
+
/**
|
|
861
|
+
* `session/chat-fork-adopt`: bind the DSH chat session a host `sessions.fork`
|
|
862
|
+
* just created to the SAME agent process, through the agent's own
|
|
863
|
+
* `session/fork` of the parent conversation's ACP session — the second half of
|
|
864
|
+
* the two-stage branch (host builds the DSH tree first, the plugin then adopts
|
|
865
|
+
* the ACP side; see the NTR message-actions plan, §D5/D7).
|
|
866
|
+
*
|
|
867
|
+
* On success the child conversation's next message reaches an agent that
|
|
868
|
+
* actually remembers the parent context. On failure NOTHING is bound: the
|
|
869
|
+
* child stays an ordinary copied-history conversation and its first message
|
|
870
|
+
* starts a fresh `session/new` (today's behavior).
|
|
871
|
+
*/
|
|
872
|
+
export interface ChatForkAdoptPayload { dshSessionId: string; parentDshSessionId: string }
|
|
873
|
+
/** `session/chat-fork-adopt` success: the adopted ACP session's ids. */
|
|
874
|
+
export type ChatForkAdoptResult = { sessionId: string; acpSessionId: string }
|
|
875
|
+
|
|
755
876
|
/** Host-detected agent presence and tested defaults. */
|
|
756
877
|
export interface DetectedAgentInfo {
|
|
757
878
|
id: string
|