dsh-ntr 0.3.1 → 0.3.3
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 +3 -1
- package/README.md +3 -1
- package/cordis.patch.yml +17 -1
- package/lib/bridge.js +2436 -82
- package/lib/client/acp-ui.js +103 -3
- package/lib/client/acp-view.js +24 -4
- package/lib/client/activity-pill.js +156 -0
- package/lib/client/branch-action.js +149 -0
- package/lib/client/composer-mode.js +48 -13
- package/lib/client/context-meter.js +86 -0
- package/lib/client/index.js +279 -16
- package/lib/client/model-seat.js +8 -2
- 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 +380 -13
- package/lib/client.js +1364 -70
- package/lib/client.js.map +1 -1
- package/lib/impl.js +1229 -8
- package/lib/index.js +34 -0
- package/lib/protocol.js +19 -0
- package/lib/tps.js +32 -0
- package/lib/types/bridge.d.ts +850 -18
- package/lib/types/client/acp-ui.d.ts +34 -2
- package/lib/types/client/acp-view.d.ts +13 -2
- package/lib/types/client/activity-pill.d.ts +81 -0
- package/lib/types/client/branch-action.d.ts +47 -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/model-seat.d.ts +21 -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 +108 -1
- package/lib/types/impl.d.ts +94 -7
- package/lib/types/protocol.d.ts +145 -0
- package/lib/types/tps.d.ts +17 -0
- package/package.json +2 -1
- package/src/bridge.ts +2754 -86
- package/src/client/acp-ui.tsx +123 -2
- package/src/client/acp-view.tsx +30 -5
- package/src/client/activity-pill.tsx +201 -0
- package/src/client/branch-action.tsx +178 -0
- package/src/client/composer-mode.tsx +59 -13
- package/src/client/context-meter.tsx +128 -0
- package/src/client/index.tsx +298 -15
- package/src/client/model-seat.tsx +28 -3
- 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 +412 -14
- package/src/impl.ts +1251 -13
- package/src/index.ts +33 -0
- package/src/protocol.ts +145 -0
- package/src/tps.ts +40 -0
package/lib/types/impl.d.ts
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* fakes.
|
|
6
6
|
*/
|
|
7
7
|
import { randomUUID } from './ids.ts';
|
|
8
|
-
import type { AcpAgentCatalog, AcpAgentDef, AcpApprovalDeadlines, AcpConversationChoice, AcpEvent, AcpMcpServerDef, AcpPluginConfig, AcpPresetStatus, AcpTagHalo, AgentCatalogResult, AgentProbeModelsResult, AgentTestResult, AgentView, ApprovalDeadlineKey, ApprovalDeadlinePatch, ChatSessionView, ChatTranscriptView, DetectedAgentInfo, PermissionOptionView, PermissionOutcome, PermissionTimeoutMode, PluginUpdateState, RpcResult } from './protocol.ts';
|
|
8
|
+
import type { AcpAgentCatalog, AcpAgentDef, AcpApprovalDeadlines, AcpConversationChoice, AcpEvent, AcpIdleRelease, AcpMcpServerDef, AcpPluginConfig, AcpPresetStatus, AcpTagHalo, AgentCatalogResult, AgentProbeModelsResult, AgentTestResult, AgentView, ApprovalDeadlineKey, ApprovalDeadlinePatch, ChatSessionView, ChatTranscriptView, DetectedAgentInfo, PermissionOptionView, PermissionOutcome, PermissionTimeoutMode, PluginUpdateState, RpcResult } from './protocol.ts';
|
|
9
9
|
export { randomUUID };
|
|
10
10
|
/** Structured failure the RPC layer converts to `{ok:false, error}` and `apply()` surfaces at boot. */
|
|
11
11
|
export declare class AcpError extends Error {
|
|
@@ -82,6 +82,15 @@ export declare function validateApprovalDeadlineMs(raw: unknown, label: string,
|
|
|
82
82
|
* reset the number. `reset` is not a deadline and is dropped here.
|
|
83
83
|
*/
|
|
84
84
|
export declare function validateApprovalDeadlines(value: unknown): Partial<Record<ApprovalDeadlineKey, number>>;
|
|
85
|
+
/**
|
|
86
|
+
* Validate the idle-release window the settings page writes.
|
|
87
|
+
*
|
|
88
|
+
* The window is expressed in MILLISECONDS on the shared ladder
|
|
89
|
+
* ({@link IDLE_RELEASE_MS}), so a value the slider can produce is always a
|
|
90
|
+
* value the host runs — the same one-ladder rule the approval deadline card
|
|
91
|
+
* follows.
|
|
92
|
+
*/
|
|
93
|
+
export declare function validateIdleReleaseMs(raw: unknown, code: 'bad_config' | 'bad_payload'): number;
|
|
85
94
|
/**
|
|
86
95
|
* Validate the mode a write asks for. Three values, and the list is the whole
|
|
87
96
|
* vocabulary: an unanswered ask is either answered for you, kept waiting, or
|
|
@@ -437,10 +446,42 @@ export declare function describeUnhandledUpdate(kind: string, update: Record<str
|
|
|
437
446
|
* injected context too (goal/subagent/skill material), and that turn carries no
|
|
438
447
|
* user intent to send anywhere.
|
|
439
448
|
*/
|
|
449
|
+
export interface PromptImageContent {
|
|
450
|
+
type: 'image';
|
|
451
|
+
data: string;
|
|
452
|
+
mimeType: string;
|
|
453
|
+
uri?: string;
|
|
454
|
+
}
|
|
455
|
+
export interface PromptTextContent {
|
|
456
|
+
type: 'text';
|
|
457
|
+
text: string;
|
|
458
|
+
}
|
|
459
|
+
export type PromptContentBlock = PromptTextContent | PromptImageContent;
|
|
460
|
+
/** Helper: guess MIME type from file extension or URL */
|
|
461
|
+
export declare function guessImageMimeType(pathOrUrl?: string): string | undefined;
|
|
462
|
+
/** Helper: parse Data URI */
|
|
463
|
+
export declare function parseImageDataUrl(url: string): {
|
|
464
|
+
data: string;
|
|
465
|
+
mimeType: string;
|
|
466
|
+
} | undefined;
|
|
467
|
+
export declare function isLocalFilePath(str: string): boolean;
|
|
468
|
+
export declare function normalizeFileUrlToPath(uri: string): string;
|
|
469
|
+
/**
|
|
470
|
+
* Detect image MIME type by examining binary magic numbers.
|
|
471
|
+
* Supports Buffer, Uint8Array, and base64 strings.
|
|
472
|
+
*/
|
|
473
|
+
export declare function detectImageMimeFromMagic(raw: Buffer | Uint8Array | string | undefined): string | undefined;
|
|
474
|
+
export declare function resolveImageAttachmentFromContext(id: string, context?: unknown, attachmentMeta?: unknown, rootContext?: unknown): unknown;
|
|
475
|
+
/**
|
|
476
|
+
* Extract an image payload (Base64 data + MIME type) from an image block and optional context.
|
|
477
|
+
*/
|
|
478
|
+
export declare function resolveImageContent(block: unknown, context?: unknown): PromptImageContent | undefined;
|
|
440
479
|
export type ForwardPromptSelection = {
|
|
441
480
|
kind: 'prompt';
|
|
442
481
|
text: string;
|
|
443
482
|
id?: string;
|
|
483
|
+
images?: PromptImageContent[];
|
|
484
|
+
content?: PromptContentBlock[];
|
|
444
485
|
} | {
|
|
445
486
|
kind: 'no-user-input';
|
|
446
487
|
} | {
|
|
@@ -459,19 +500,25 @@ export type ForwardPromptSelection = {
|
|
|
459
500
|
* (tests, headless callers) and counts as user input.
|
|
460
501
|
*
|
|
461
502
|
* @param messages - the request's ordered messages, exactly as the host built them.
|
|
462
|
-
* @
|
|
503
|
+
* @param context - optional host context or attachment resolver for reading attachments.
|
|
504
|
+
* @returns the last real user message's text and any image content blocks, or why there is none to forward.
|
|
463
505
|
*/
|
|
464
506
|
export declare function selectForwardPrompt(messages: readonly {
|
|
465
507
|
role: string;
|
|
466
|
-
content?: Array<{
|
|
508
|
+
content?: string | Array<{
|
|
467
509
|
type?: string;
|
|
468
510
|
text?: string;
|
|
469
|
-
|
|
511
|
+
[k: string]: unknown;
|
|
512
|
+
}> | {
|
|
513
|
+
type?: string;
|
|
514
|
+
text?: string;
|
|
515
|
+
[k: string]: unknown;
|
|
516
|
+
};
|
|
470
517
|
source?: {
|
|
471
518
|
kind?: string;
|
|
472
519
|
};
|
|
473
520
|
id?: string;
|
|
474
|
-
}[]): ForwardPromptSelection;
|
|
521
|
+
}[], context?: unknown): ForwardPromptSelection;
|
|
475
522
|
/** Structural read of ACP `ToolCall.kind`; anything unexpected stays `undefined` (= effect unknown). */
|
|
476
523
|
export declare function permissionToolKind(toolCall: unknown): string | undefined;
|
|
477
524
|
/** Structural read of ACP `ToolCall.locations[].path` — where an edit claims it will write. */
|
|
@@ -543,7 +590,16 @@ export interface RosterPresetRow {
|
|
|
543
590
|
* @returns the status, or `undefined` when the roster is unreadable.
|
|
544
591
|
*/
|
|
545
592
|
export declare function acpPresetStatusFromRoster(rows: readonly RosterPresetRow[] | undefined, id: string): AcpPresetStatus | undefined;
|
|
546
|
-
/**
|
|
593
|
+
/**
|
|
594
|
+
* Bounded log of raw ACP session updates with monotone seq.
|
|
595
|
+
*
|
|
596
|
+
* Consecutive ticks of the same state-only kind share one entry (the entry is
|
|
597
|
+
* replaced in place, not appended): chatty agents emit a usage / phase tick
|
|
598
|
+
* every few hundred milliseconds, and letting each occupy the ring evicts the
|
|
599
|
+
* conversation itself. This costs nothing on the live path — `append` still
|
|
600
|
+
* allocates a fresh seq and the bridge broadcasts that frame — but replay via
|
|
601
|
+
* `since` only sees the newest tick of each run.
|
|
602
|
+
*/
|
|
547
603
|
export declare class Transcript {
|
|
548
604
|
private readonly max;
|
|
549
605
|
private readonly entries;
|
|
@@ -655,7 +711,7 @@ export interface AcpManager {
|
|
|
655
711
|
startSession(agentId: string, cwd: string | undefined): Promise<{
|
|
656
712
|
sessionId: string;
|
|
657
713
|
}>;
|
|
658
|
-
prompt(sessionId: string,
|
|
714
|
+
prompt(sessionId: string, prompt: string | PromptContentBlock[]): Promise<{
|
|
659
715
|
turnId: string;
|
|
660
716
|
}>;
|
|
661
717
|
cancel(sessionId: string): Promise<void>;
|
|
@@ -698,6 +754,19 @@ export interface AcpManager {
|
|
|
698
754
|
* applies again. Applies to the running bridges without a restart.
|
|
699
755
|
*/
|
|
700
756
|
setApprovalDeadlines?(patch: ApprovalDeadlinePatch, reset?: boolean): Promise<void>;
|
|
757
|
+
/**
|
|
758
|
+
* The idle-release window in force for chat processes, plus the built-in
|
|
759
|
+
* default a reset returns to. `undefined` on a host half from before the
|
|
760
|
+
* card existed, which hides the settings tab instead of showing a number
|
|
761
|
+
* this browser invented.
|
|
762
|
+
*/
|
|
763
|
+
idleRelease?(): AcpIdleRelease | undefined;
|
|
764
|
+
/**
|
|
765
|
+
* Write the idle-release window (in ms), or drop the persisted
|
|
766
|
+
* override with `reset` so the built-in default applies again. Applies to
|
|
767
|
+
* the running bridges without a restart.
|
|
768
|
+
*/
|
|
769
|
+
setIdleRelease?(idleTimeoutMs: number | undefined, reset?: boolean): Promise<void>;
|
|
701
770
|
detectAgents?(): Promise<DetectedAgentInfo[]>;
|
|
702
771
|
saveAgent?(def: AcpAgentDef): Promise<void>;
|
|
703
772
|
deleteAgent?(agentId: string): Promise<void>;
|
|
@@ -770,6 +839,24 @@ export interface AcpManager {
|
|
|
770
839
|
* without it the live (non-released) session is picked.
|
|
771
840
|
*/
|
|
772
841
|
setChatSessionMode?(dshSessionId: string, modeId: string, agentId?: string): Promise<void>;
|
|
842
|
+
/**
|
|
843
|
+
* Bring one chat conversation's released session back on a fresh process on
|
|
844
|
+
* the user's explicit gesture (`session/chat-resume`, the released-session
|
|
845
|
+
* banner's button). Same recovery the next prompt performs lazily, minus
|
|
846
|
+
* the create path; no-op when the session is already live.
|
|
847
|
+
*/
|
|
848
|
+
resumeChatSession?(dshSessionId: string): Promise<void>;
|
|
849
|
+
/**
|
|
850
|
+
* Adopt the ACP side of a branched conversation (`session/chat-fork-adopt`):
|
|
851
|
+
* the browser has already asked the HOST to fork the DSH session tree, and
|
|
852
|
+
* this runs the agent's own `session/fork` of the parent's live ACP session,
|
|
853
|
+
* then binds the child to it. All-or-nothing — nothing is bound on failure,
|
|
854
|
+
* so the child stays an ordinary copied-history conversation.
|
|
855
|
+
*/
|
|
856
|
+
adoptForkedSession?(childDshSessionId: string, parentDshSessionId: string): Promise<{
|
|
857
|
+
sessionId: string;
|
|
858
|
+
acpSessionId: string;
|
|
859
|
+
}>;
|
|
773
860
|
/**
|
|
774
861
|
* Point one DSH chat conversation at an ACP agent — the plugin's own
|
|
775
862
|
* conversation↔agent mapping, never a DSH model route (see
|
package/lib/types/protocol.d.ts
CHANGED
|
@@ -178,6 +178,18 @@ export interface AcpPluginConfig {
|
|
|
178
178
|
* deployment baseline that override falls back to. See {@link AcpApprovalDeadlines}.
|
|
179
179
|
*/
|
|
180
180
|
permissionTimeoutMs?: number;
|
|
181
|
+
/**
|
|
182
|
+
* How long a chat process may sit idle before it is released (parked, then
|
|
183
|
+
* resumed by the next message). In MILLISECONDS; default 1800000 (30 min).
|
|
184
|
+
*
|
|
185
|
+
* This is the HOST DEFAULT: an agent that names its own
|
|
186
|
+
* {@link AcpAgentDef.idleTimeoutMs} keeps its own. Editable from the
|
|
187
|
+
* settings page (「进程管理」 → `ui/idle-release-set`), which persists an
|
|
188
|
+
* override in the plugin's own state file and applies it to the running
|
|
189
|
+
* bridges without restarting anything; the value here is the deployment
|
|
190
|
+
* baseline that override falls back to. See {@link AcpIdleRelease}.
|
|
191
|
+
*/
|
|
192
|
+
idleTimeoutMs?: number;
|
|
181
193
|
/**
|
|
182
194
|
* LEGACY: the old conversation-route window, kept so an existing
|
|
183
195
|
* `cordis.patch.yml` still says what it meant. Folded into
|
|
@@ -473,6 +485,17 @@ export type AcpEvent = {
|
|
|
473
485
|
sessionId: string;
|
|
474
486
|
turnId: string;
|
|
475
487
|
text: string;
|
|
488
|
+
} | {
|
|
489
|
+
type: 'turn/metrics';
|
|
490
|
+
/** ACP session id (the store keys live burst state by it). */
|
|
491
|
+
sessionId: string;
|
|
492
|
+
/** DSH chat session id (routing/context only). */
|
|
493
|
+
dshSessionId: string;
|
|
494
|
+
turnId: string;
|
|
495
|
+
/** Session aggregate INCLUDING the current turn when measurable. */
|
|
496
|
+
outputTokens: number;
|
|
497
|
+
burstMs: number;
|
|
498
|
+
final: boolean;
|
|
476
499
|
} | {
|
|
477
500
|
type: 'turn/end';
|
|
478
501
|
sessionId: string;
|
|
@@ -511,6 +534,13 @@ export type PermissionOutcome = {
|
|
|
511
534
|
} | {
|
|
512
535
|
outcome: 'cancelled';
|
|
513
536
|
};
|
|
537
|
+
/** Plugin-side measurable burst aggregate for one ACP session (not host turn timings). */
|
|
538
|
+
export interface SessionBurst {
|
|
539
|
+
/** Sum of estimated output tokens over measurable turns. */
|
|
540
|
+
outputTokens: number;
|
|
541
|
+
/** Sum of within-burst chunk gaps over those turns; tool/approval/long pauses excluded. */
|
|
542
|
+
burstMs: number;
|
|
543
|
+
}
|
|
514
544
|
/** Derived session snapshot for replay/reconnect (source of truth stays in the transcript). */
|
|
515
545
|
export interface SessionView {
|
|
516
546
|
sessionId: string;
|
|
@@ -542,6 +572,8 @@ export interface SessionView {
|
|
|
542
572
|
currency: string;
|
|
543
573
|
};
|
|
544
574
|
};
|
|
575
|
+
/** Measurable burst aggregate over this session's turns; absent until measured. */
|
|
576
|
+
burst?: SessionBurst;
|
|
545
577
|
running: boolean;
|
|
546
578
|
closed: boolean;
|
|
547
579
|
/**
|
|
@@ -550,6 +582,14 @@ export interface SessionView {
|
|
|
550
582
|
* recover") when the agent declares the `loadSession` capability.
|
|
551
583
|
*/
|
|
552
584
|
released?: boolean;
|
|
585
|
+
/**
|
|
586
|
+
* The agent-side session has history while the local buffer is empty: the
|
|
587
|
+
* record was restored from disk after a host restart (the `session/load`
|
|
588
|
+
* replay has not landed), or a resume cleared the buffer ahead of the
|
|
589
|
+
* replay. The ACP view then says history replays on restore instead of
|
|
590
|
+
* claiming "nothing yet".
|
|
591
|
+
*/
|
|
592
|
+
hasHistory?: boolean;
|
|
553
593
|
/** Highest transcript seq included in this snapshot (for gap detection). */
|
|
554
594
|
seq: number;
|
|
555
595
|
}
|
|
@@ -613,8 +653,38 @@ export interface ChatSessionView {
|
|
|
613
653
|
* agent can never see.
|
|
614
654
|
*/
|
|
615
655
|
availableCommands?: SessionView['availableCommands'];
|
|
656
|
+
/**
|
|
657
|
+
* Context occupancy the agent last reported (`usage_update`): prompt-side
|
|
658
|
+
* used/size, not request tokens. Absent until the agent reports one; the
|
|
659
|
+
* browser live-patches this row from the update frames (see AGENTS/ui.md).
|
|
660
|
+
*/
|
|
661
|
+
usage?: SessionView['usage'];
|
|
662
|
+
/** Measurable burst aggregate over this session's turns; absent until measured. */
|
|
663
|
+
burst?: SessionView['burst'];
|
|
616
664
|
/** The agent process died; the session awaits a `session/load` resume. */
|
|
617
665
|
released?: boolean;
|
|
666
|
+
/** The agent is running a turn on this session right now. */
|
|
667
|
+
running?: boolean;
|
|
668
|
+
/**
|
|
669
|
+
* Whether this session's ACP agent can be forked (`session/fork`) into a
|
|
670
|
+
* child conversation, as the host computed it. The browser does not derive
|
|
671
|
+
* this itself — the capability is host knowledge (the agent's
|
|
672
|
+
* `initialize`), and the row is the one place it is delivered.
|
|
673
|
+
* `supported: false` carries the reason; no reason on `false` means the
|
|
674
|
+
* host half predates the field (treat as unsupported).
|
|
675
|
+
*/
|
|
676
|
+
fork?: ChatSessionForkInfo;
|
|
677
|
+
}
|
|
678
|
+
/**
|
|
679
|
+
* The host's per-row verdict on forking one chat session's ACP session
|
|
680
|
+
* (`ChatSessionView.fork`). Computed from the agent's LAST KNOWN
|
|
681
|
+
* `sessionCapabilities.fork` (persisted with the model catalog) plus the
|
|
682
|
+
* session's own state — the browser never reads capability bits itself.
|
|
683
|
+
*/
|
|
684
|
+
export interface ChatSessionForkInfo {
|
|
685
|
+
supported: boolean;
|
|
686
|
+
/** Why {@link supported} is false: the agent cannot fork, or the session cannot be forked right now. */
|
|
687
|
+
reason?: 'unsupported' | 'released' | 'busy';
|
|
618
688
|
}
|
|
619
689
|
export type ChatSessionsListResult = {
|
|
620
690
|
sessions: ChatSessionView[];
|
|
@@ -770,6 +840,60 @@ export interface TagHaloSetPayload {
|
|
|
770
840
|
}
|
|
771
841
|
/** The approval deadline the settings page can edit, by field name. ONE window. */
|
|
772
842
|
export type ApprovalDeadlineKey = 'permissionTimeoutMs';
|
|
843
|
+
/**
|
|
844
|
+
* The idle-release windows the settings page offers, in MILLISECONDS.
|
|
845
|
+
*
|
|
846
|
+
* ONE ladder, shared by both halves: the browser snaps its slider to these
|
|
847
|
+
* values and the host accepts only these values, so a window the slider can
|
|
848
|
+
* produce is always a window the host runs. The first rung is 1 minute (an
|
|
849
|
+
* aggressive release), the rest are 5-minute steps up to an hour.
|
|
850
|
+
*/
|
|
851
|
+
export declare const IDLE_RELEASE_MS: readonly number[];
|
|
852
|
+
/**
|
|
853
|
+
* The built-in idle-release window for chat processes: 30 minutes.
|
|
854
|
+
*
|
|
855
|
+
* Lives beside the ladder it is a rung of, so the two cannot drift: a
|
|
856
|
+
* deployment that names no window of its own runs this, and the settings
|
|
857
|
+
* page's reset returns to it.
|
|
858
|
+
*/
|
|
859
|
+
export declare const DEFAULT_IDLE_TIMEOUT_MS = 1800000;
|
|
860
|
+
/**
|
|
861
|
+
* The idle-release window for chat processes, as the settings page edits it.
|
|
862
|
+
*
|
|
863
|
+
* The window is the HOST default: an agent that names its own
|
|
864
|
+
* {@link AcpAgentDef.idleTimeoutMs} keeps it, and a probe-only process (one
|
|
865
|
+
* that never hosted a session) still honors the short probe window — see
|
|
866
|
+
* `AGENTS/protocol.md` §5.
|
|
867
|
+
*/
|
|
868
|
+
export interface AcpIdleRelease {
|
|
869
|
+
/** The window in force, in ms. */
|
|
870
|
+
idleTimeoutMs: number;
|
|
871
|
+
/**
|
|
872
|
+
* The window a RESET returns to: the deployment baseline when the config
|
|
873
|
+
* file names one, else the built-in default (30 minutes).
|
|
874
|
+
*/
|
|
875
|
+
defaultIdleTimeoutMs: number;
|
|
876
|
+
/**
|
|
877
|
+
* The window `cordis.patch.yml` names, when it names one. Reported only
|
|
878
|
+
* when the file actually names one: the settings card must not say "the
|
|
879
|
+
* file asks for 30 minutes" about a file that says nothing.
|
|
880
|
+
*/
|
|
881
|
+
configuredIdleTimeoutMs?: number;
|
|
882
|
+
}
|
|
883
|
+
/** `ui/idle-release`: read the idle-release window in force. */
|
|
884
|
+
export type IdleReleaseResult = {
|
|
885
|
+
idleRelease?: AcpIdleRelease;
|
|
886
|
+
};
|
|
887
|
+
/**
|
|
888
|
+
* `ui/idle-release-set`: write the idle-release window, or drop the persisted
|
|
889
|
+
* override with `reset` so the built-in default applies again.
|
|
890
|
+
*/
|
|
891
|
+
export interface IdleReleaseSetPayload {
|
|
892
|
+
/** The window to run, in ms; omitted when `reset` is true. */
|
|
893
|
+
idleTimeoutMs?: number;
|
|
894
|
+
/** Drop the persisted override so the built-in default applies again. */
|
|
895
|
+
reset?: boolean;
|
|
896
|
+
}
|
|
773
897
|
/**
|
|
774
898
|
* What an EXPIRED approval deadline does. Three modes, and only three — an
|
|
775
899
|
* unanswered ask either gets answered for you, keeps waiting, or is refused.
|
|
@@ -868,6 +992,27 @@ export interface ChatConfigSetPayload {
|
|
|
868
992
|
value: string | boolean;
|
|
869
993
|
agentId?: string;
|
|
870
994
|
}
|
|
995
|
+
/**
|
|
996
|
+
* `session/chat-fork-adopt`: bind the DSH chat session a host `sessions.fork`
|
|
997
|
+
* just created to the SAME agent process, through the agent's own
|
|
998
|
+
* `session/fork` of the parent conversation's ACP session — the second half of
|
|
999
|
+
* the two-stage branch (host builds the DSH tree first, the plugin then adopts
|
|
1000
|
+
* the ACP side; see the NTR message-actions plan, §D5/D7).
|
|
1001
|
+
*
|
|
1002
|
+
* On success the child conversation's next message reaches an agent that
|
|
1003
|
+
* actually remembers the parent context. On failure NOTHING is bound: the
|
|
1004
|
+
* child stays an ordinary copied-history conversation and its first message
|
|
1005
|
+
* starts a fresh `session/new` (today's behavior).
|
|
1006
|
+
*/
|
|
1007
|
+
export interface ChatForkAdoptPayload {
|
|
1008
|
+
dshSessionId: string;
|
|
1009
|
+
parentDshSessionId: string;
|
|
1010
|
+
}
|
|
1011
|
+
/** `session/chat-fork-adopt` success: the adopted ACP session's ids. */
|
|
1012
|
+
export type ChatForkAdoptResult = {
|
|
1013
|
+
sessionId: string;
|
|
1014
|
+
acpSessionId: string;
|
|
1015
|
+
};
|
|
871
1016
|
/** Host-detected agent presence and tested defaults. */
|
|
872
1017
|
export interface DetectedAgentInfo {
|
|
873
1018
|
id: string;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/** ACP `usage_update` is context occupancy, not request tokens; this is the plugin's 4-chars/token OUTPUT estimate (tool args excluded). */
|
|
2
|
+
export declare const OUTPUT_CHARS_PER_TOKEN = 4;
|
|
3
|
+
export declare const BURST_GAP_MS = 1000;
|
|
4
|
+
export interface TurnTpsSnapshot {
|
|
5
|
+
outputTokens: number;
|
|
6
|
+
burstMs: number;
|
|
7
|
+
}
|
|
8
|
+
export declare class TurnTpsTracker {
|
|
9
|
+
private readonly gapMs;
|
|
10
|
+
private lastProseAt;
|
|
11
|
+
private outputChars;
|
|
12
|
+
private burstMs;
|
|
13
|
+
constructor(gapMs?: number);
|
|
14
|
+
onProse(text: string, at: number): void;
|
|
15
|
+
onBreak(): void;
|
|
16
|
+
snapshot(): TurnTpsSnapshot;
|
|
17
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-ntr",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.3",
|
|
4
4
|
"description": "Interactive Agent Client Protocol (ACP) client for the DSH web UI: attach any ACP-capable agent and stream its session.",
|
|
5
5
|
"repository": "https://github.com/GDWhisper/dsh-ntr.git",
|
|
6
6
|
"type": "module",
|
|
@@ -72,6 +72,7 @@
|
|
|
72
72
|
"@deepseek-ai/dsh-client-connection",
|
|
73
73
|
"@deepseek-ai/dsh-client-ui-conversation",
|
|
74
74
|
"@deepseek-ai/dsh-client-ui-layout",
|
|
75
|
+
"@deepseek-ai/dsh-client-ui-primitives",
|
|
75
76
|
"@deepseek-ai/dsh-client-ui-settings",
|
|
76
77
|
"@deepseek-ai/dsh-client-ui-sidebar",
|
|
77
78
|
"@deepseek-ai/dsh-client-ui-slots"
|