@vidge/dsh-agent-hub 0.1.0-rc1

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.
Files changed (56) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +133 -0
  3. package/README.zh.md +115 -0
  4. package/cordis.patch.yml +22 -0
  5. package/lib/client.js +1494 -0
  6. package/lib/index.js +5045 -0
  7. package/lib/invariant.js +96 -0
  8. package/lib/types/client/LoopEngineComposerSelect.d.ts +73 -0
  9. package/lib/types/client/LoopEngineSection.d.ts +43 -0
  10. package/lib/types/client/engine-rpc.d.ts +74 -0
  11. package/lib/types/client/index.d.ts +28 -0
  12. package/lib/types/client/locales.d.ts +44 -0
  13. package/lib/types/client/session-location.d.ts +63 -0
  14. package/lib/types/client/store.d.ts +58 -0
  15. package/lib/types/commands.d.ts +69 -0
  16. package/lib/types/driver-core/context-files.d.ts +62 -0
  17. package/lib/types/driver-core/ownership.d.ts +40 -0
  18. package/lib/types/driver-core/permission-knobs.d.ts +26 -0
  19. package/lib/types/driver-core/prompt.d.ts +23 -0
  20. package/lib/types/driver-core/skill-inject.d.ts +59 -0
  21. package/lib/types/engine-claude/agent.d.ts +116 -0
  22. package/lib/types/engine-claude/loop.d.ts +99 -0
  23. package/lib/types/engine-claude/mapping.d.ts +84 -0
  24. package/lib/types/engine-claude/permission.d.ts +41 -0
  25. package/lib/types/engine-claude/process.d.ts +59 -0
  26. package/lib/types/engine-claude/provider-env.d.ts +50 -0
  27. package/lib/types/engine-claude/sdk.d.ts +101 -0
  28. package/lib/types/engine-claude/types.d.ts +28 -0
  29. package/lib/types/engine-codex/agent.d.ts +109 -0
  30. package/lib/types/engine-codex/appserver/client.d.ts +49 -0
  31. package/lib/types/engine-codex/appserver/mapping.d.ts +67 -0
  32. package/lib/types/engine-codex/appserver/thread.d.ts +66 -0
  33. package/lib/types/engine-codex/appserver/types.d.ts +215 -0
  34. package/lib/types/engine-codex/loop.d.ts +92 -0
  35. package/lib/types/engine-codex/permission.d.ts +32 -0
  36. package/lib/types/engine-codex/skills.d.ts +29 -0
  37. package/lib/types/engine-codex/types.d.ts +19 -0
  38. package/lib/types/engine-pi/agent.d.ts +125 -0
  39. package/lib/types/engine-pi/loop.d.ts +96 -0
  40. package/lib/types/engine-pi/permission.d.ts +43 -0
  41. package/lib/types/engine-pi/rpc/client.d.ts +105 -0
  42. package/lib/types/engine-pi/rpc/mapping.d.ts +37 -0
  43. package/lib/types/engine-pi/rpc/types.d.ts +235 -0
  44. package/lib/types/engine-pi/skills.d.ts +55 -0
  45. package/lib/types/engine-pi/types.d.ts +27 -0
  46. package/lib/types/engine-record.d.ts +124 -0
  47. package/lib/types/index.d.ts +138 -0
  48. package/lib/types/invariant.d.ts +23 -0
  49. package/lib/types/llm-compat.d.ts +32 -0
  50. package/lib/types/namespace.d.ts +19 -0
  51. package/lib/types/patch-manager.d.ts +78 -0
  52. package/lib/types/router.d.ts +189 -0
  53. package/lib/types/rpc.d.ts +113 -0
  54. package/lib/types/settings.d.ts +29 -0
  55. package/lib/types/skills.d.ts +93 -0
  56. package/package.json +107 -0
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Reading the dsh session's durable permission knobs from the session log.
3
+ * Both the Claude Code and Codex drivers fold the same `sandbox/mode` and
4
+ * `approval/policy` events (pinned at creation, re-recorded on every switch)
5
+ * into per-query permission decisions; the knob readers are engine-free.
6
+ *
7
+ * @module dsh-agent-hub/driver-core/permission-knobs
8
+ */
9
+ import type { SessionEvent } from '@deepseek-ai/dsh-session';
10
+ /**
11
+ * Minimal structural shape of one session log event. The base `SessionEvent`
12
+ * union in this compilation does not carry the sandbox/approval packages'
13
+ * augmentation keys, so the fold reads the wire shape directly.
14
+ */
15
+ export type PermissionEvent = Pick<SessionEvent, 'data'> & {
16
+ readonly type: string;
17
+ };
18
+ /** dsh sandbox modes, mirrored inline to avoid a peer dep on @deepseek-ai/dsh-sandbox-policy. */
19
+ export type DshSandboxMode = 'read-only' | 'workspace-write' | 'danger-full-access';
20
+ /** dsh approval policies, mirrored inline to avoid a peer dep on @deepseek-ai/dsh-user-approval. */
21
+ export type DshApprovalPolicy = 'ask' | 'never';
22
+ /** The session's sandbox-mode override: the last `sandbox/mode` event, if any. */
23
+ export declare function sessionSandboxMode(events: readonly PermissionEvent[]): DshSandboxMode | undefined;
24
+ /** The session's approval-policy override: the last `approval/policy` event, if any. */
25
+ export declare function sessionApprovalPolicy(events: readonly PermissionEvent[]): DshApprovalPolicy | undefined;
26
+ //# sourceMappingURL=permission-knobs.d.ts.map
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Serialization of the durable session history into the prompt text of one
3
+ * hosted-engine query. Both the Claude Code and Codex drivers build their
4
+ * per-step input from the durable session log: the transcript is the log's
5
+ * exact projection, so a later replay of the same log derives the identical
6
+ * prompt (Model-visible ⟺ logged bridge).
7
+ *
8
+ * @module dsh-agent-hub/driver-core/prompt
9
+ */
10
+ import type { Message } from '@deepseek-ai/dsh-llm';
11
+ /** Model-facing stand-in for an image block that the hosted engines cannot consume as bytes. */
12
+ export declare const OMITTED_IMAGE_TEXT = "[image omitted: the driver does not transcribe images; read the file when a path is available]";
13
+ /**
14
+ * Serialize a derived conversation history into the prompt text of one hosted
15
+ * query. The last message is the live user request that triggered the step;
16
+ * every earlier message is durable replay context. The output is a pure
17
+ * function of the log prefix.
18
+ * @param messages - derived history, oldest first, as returned by
19
+ * `Session.deriveMessages()` at step time.
20
+ * @returns the prompt text to pass to the engine.
21
+ */
22
+ export declare function serializeHistory(messages: readonly Message[]): string;
23
+ //# sourceMappingURL=prompt.d.ts.map
@@ -0,0 +1,59 @@
1
+ /**
2
+ * Skill-injection helpers shared by the hosted engine drivers. Both the Claude
3
+ * Code and Codex agents replicate the dsh `/name` skill gesture scan and the
4
+ * XML `<skill_content>` rendering that the in-process engine's dsh-tool-skill
5
+ * handler would otherwise provide — their agent contexts do not descend from
6
+ * the agent-preset chain. These helpers are pure: they take user messages or a
7
+ * loaded skill and return the injected text, with no session or loop access.
8
+ *
9
+ * @module dsh-agent-hub/driver-core/skill-inject
10
+ */
11
+ import type { UserMessage } from '@deepseek-ai/dsh-session';
12
+ export declare function isSkillName(name: string): boolean;
13
+ /** Minimal shape of a loaded skill definition. */
14
+ export interface SkillDefinition {
15
+ readonly name: string;
16
+ readonly description: string;
17
+ readonly whenToUse?: string;
18
+ readonly invocation: {
19
+ readonly modelInvocable: boolean;
20
+ readonly userInvocable: boolean;
21
+ };
22
+ readonly source: string;
23
+ readonly provider: string;
24
+ readonly content: string;
25
+ readonly path?: string;
26
+ readonly resourceBase?: {
27
+ readonly kind: string;
28
+ readonly path: string;
29
+ };
30
+ }
31
+ /** Durable source for an injected user-explicit skill invocation (mirrors dsh-skill's). */
32
+ export interface SkillInvocationSource {
33
+ readonly kind: 'skill-invocation';
34
+ readonly name: string;
35
+ readonly form: 'instructions';
36
+ }
37
+ declare module '@deepseek-ai/dsh-llm' {
38
+ interface MessageSourceMap {
39
+ /** A user-explicit skill invocation injected by this driver. */
40
+ 'skill-invocation': SkillInvocationSource;
41
+ }
42
+ }
43
+ /** Minimal shape of the SkillRegistry service. */
44
+ export interface SkillsService {
45
+ get(name: string, options: {
46
+ cwd?: string;
47
+ signal?: AbortSignal;
48
+ scope?: unknown;
49
+ }): Promise<SkillDefinition | undefined>;
50
+ }
51
+ /** Escape text for inclusion in XML-like skill markup. */
52
+ export declare function escapeText(value: string): string;
53
+ /** Escape an XML-like attribute value. */
54
+ export declare function escapeAttr(value: string): string;
55
+ /** Render the `<skill_content>` block for a loaded skill. */
56
+ export declare function renderSkillContent(skill: SkillDefinition): string;
57
+ /** Collect `/name` gesture tokens from direct user messages, in first-seen order. */
58
+ export declare function invokedSkillNames(messages: readonly UserMessage[]): string[];
59
+ //# sourceMappingURL=skill-inject.d.ts.map
@@ -0,0 +1,116 @@
1
+ /**
2
+ * Claude Code loop Agent: drives one session through turn and step boundaries
3
+ * with one Claude Agent SDK query per step. Claude Code owns its prompt,
4
+ * tools, and permissions; the durable session log remains the source of truth
5
+ * and the query prompt is a pure serialization of it.
6
+ *
7
+ * @module dsh-agent-hub/engine-claude/agent
8
+ */
9
+ import type { Agent, AgentCancelCause, AgentOptions, AgentStatus, CancelOptions, InboxTarget } from '@deepseek-ai/dsh-agent';
10
+ import { Inbox } from '@deepseek-ai/dsh-agent';
11
+ import type { Scope } from '@deepseek-ai/dsh-scope';
12
+ import type { Session, SessionId, UserMessage } from '@deepseek-ai/dsh-session';
13
+ import type { Context } from '@deepseek-ai/cordis';
14
+ import type { ResolvedConfig } from './types.ts';
15
+ /** Drives one session through turn and step boundaries on Claude Code. */
16
+ export declare class ClaudeCodeAgent implements Agent {
17
+ private loopCtx;
18
+ readonly id: SessionId;
19
+ readonly options: AgentOptions;
20
+ readonly session: Session;
21
+ private readonly config;
22
+ readonly inbox: Inbox;
23
+ private phase;
24
+ private activityDone;
25
+ /** The agent-scoped registration boundary; the lifecycle owner unwinds it after the driver exits. */
26
+ readonly scope: Scope;
27
+ readonly ctx: Context;
28
+ /** Fused dispatcher, built once in the constructor so hot-path dispatches never allocate. */
29
+ private readonly dispatch;
30
+ /** Whether this loop instance has appended its initial/resume request anchor. */
31
+ private requestHeaderLogged;
32
+ constructor(loopCtx: Context, id: SessionId, options: AgentOptions, session: Session, config: ResolvedConfig);
33
+ get status(): AgentStatus;
34
+ /** Commit a phase and publish its externally visible status transition. */
35
+ private setPhase;
36
+ send(message: UserMessage, target: InboxTarget, wakeup: boolean): void;
37
+ /**
38
+ * Queue a message for the next turn and wake the driver.
39
+ * @param input - the user message to deliver.
40
+ */
41
+ followup(input: UserMessage): void;
42
+ /**
43
+ * Queue a message for the running step and wake the driver.
44
+ * @param input - the user message to deliver.
45
+ */
46
+ steer(input: UserMessage): void;
47
+ /**
48
+ * Queue a message for the running step without waking the driver.
49
+ * @param input - the user message to deliver.
50
+ */
51
+ inject(input: UserMessage): void;
52
+ cancel(cause: AgentCancelCause, options?: CancelOptions): void;
53
+ /**
54
+ * Run a maintenance job while the agent is idle.
55
+ * @param job - the maintenance operation, receiving the phase abort signal.
56
+ * @returns the maintenance result.
57
+ */
58
+ runMaintenance<T>(job: (signal: AbortSignal) => Promise<T>): Promise<T>;
59
+ /**
60
+ * Start one driver, or latch its wake behind maintenance or an aborted
61
+ * activity. A wake sent while idle always opens its turn boundary, even
62
+ * when its message was cleared; only a latched replay is suppressed when
63
+ * the queue no longer holds the wake.
64
+ * @param wakeAfterAbort - the {@link send} classification, captured before
65
+ * the inbox insertion so a reentrant cancel cannot reclassify it.
66
+ */
67
+ private wakeDriver;
68
+ whenIdle(): Promise<void>;
69
+ /** Report one failure at its live boundary, then preserve it for driver containment. */
70
+ private throwError;
71
+ private kick;
72
+ private preStep;
73
+ /**
74
+ * Scan the step's user messages for `/name` skill gestures, load each
75
+ * matching skill, and inject the rendered skill content into the message
76
+ * batch. This mirrors what dsh-tool-skill does for the in-process engine.
77
+ * @param messages - the current step's message batch.
78
+ * @param signal - cancellation signal (aborted loads are silently dropped).
79
+ * @returns the original batch when no skill was invoked, or an extended
80
+ * batch with injected skill-content messages appended.
81
+ */
82
+ private injectSkills;
83
+ /**
84
+ * Resolve the native permission handling for one query. A deployment-pinned
85
+ * mode wins outright; otherwise the session's durable dsh permission knobs
86
+ * decide per query (mid-session preset switches included): full access
87
+ * bypasses native checks, an `ask` policy forwards each native permission
88
+ * request to the dsh approval seam, and anything else fails closed with the
89
+ * unattended deny-all stance.
90
+ * @returns the permission fields of the query spec.
91
+ */
92
+ private queryPermission;
93
+ /** Open one turn before claiming its first proposed step. */
94
+ private turn;
95
+ /**
96
+ * Resolve the model one query runs on, session choice first.
97
+ *
98
+ * The web surface sets `AgentOptions.model` when a session picks a model, and
99
+ * `agentDefaultModel` holds the global default; reading both is what makes
100
+ * the dsh model picker mean something for this engine. The service is
101
+ * optional — a minimal profile may not mount it — so it is resolved through
102
+ * `ctx.get` rather than `inject`, and a faulting provider degrades to the
103
+ * next layer instead of failing the turn.
104
+ *
105
+ * @returns the chosen id (undefined leaves the CLI on its own default),
106
+ * its provider route, and the layer that chose it.
107
+ */
108
+ private resolveModel;
109
+ /** Model label recorded in the request header for one lifecycle. */
110
+ private modelLabel;
111
+ /** Append the request header snapshot once per loop instance. */
112
+ private assertRequestHeader;
113
+ /** Run one Claude Code query for the current step and map its transcript into the session log. */
114
+ private step;
115
+ }
116
+ //# sourceMappingURL=agent.d.ts.map
@@ -0,0 +1,99 @@
1
+ /**
2
+ * Claude Code loop engine module: hosts the AgentFactory that drives every
3
+ * session through the official Claude Agent SDK, one stateless query per dsh
4
+ * step, with the durable session log as the sole source of model context.
5
+ * dsh-agent-hub constructs this factory when the Claude Code engine is
6
+ * selected; this module is a library, not a Cordis plugin entry.
7
+ *
8
+ * @module dsh-agent-hub/engine-claude
9
+ */
10
+ import { Service } from '@deepseek-ai/cordis';
11
+ import type { Context } from '@deepseek-ai/cordis';
12
+ import z from '@deepseek-ai/schemastery';
13
+ import type { AgentFactory, AgentHandle, CreateAgentOptions, ResumeAgentOptions } from '@deepseek-ai/dsh-agent';
14
+ import type { ClaudeCodeBackend, ClaudeCodePermissionMode, ResolvedConfig } from './types.ts';
15
+ /** Deployment-selectable non-interactive Claude Code permission modes. */
16
+ export declare const CLAUDE_CODE_PERMISSION_MODES: readonly ClaudeCodePermissionMode[];
17
+ /** Provider backends the deployment can pin for the CLI child. */
18
+ export declare const CLAUDE_CODE_BACKENDS: readonly ClaudeCodeBackend[];
19
+ /** Deployment-owned configuration for the Claude Code loop plugin. */
20
+ export interface Config {
21
+ /**
22
+ * Native non-interactive permission handling for every query. When omitted,
23
+ * each query follows the session's dsh permission knobs (`sandbox/mode` and
24
+ * `approval/policy`): full access bypasses native checks, an `ask` policy
25
+ * forwards requests to the dsh approval seam, and anything else auto-denies.
26
+ * A pinned mode overrides the session for every query: `dontAsk` auto-denies,
27
+ * `acceptEdits` accepts edits, `auto` uses the native classifier, `plan`
28
+ * returns a plan without approving execution, and `bypassPermissions`
29
+ * explicitly skips permission checks.
30
+ */
31
+ permissionMode?: ClaudeCodePermissionMode;
32
+ /** Explicit environment entries layered over the credential-scrubbed parent environment. */
33
+ env?: Record<string, string>;
34
+ /** Model label for the logged request header; Claude Code native settings own the actual model. */
35
+ model?: string;
36
+ /**
37
+ * Provider backend for the CLI child. The CLI resolves backends by
38
+ * precedence, so a host holding credentials for two of them silently runs on
39
+ * the wrong one — pin this when the host is not single-homed. `auto` (the
40
+ * default) takes the first configured, preferring a relay over ambient cloud
41
+ * credentials.
42
+ */
43
+ backend?: ClaudeCodeBackend;
44
+ /** Grace in milliseconds for Claude Code process-tree termination. */
45
+ disposeGraceMs?: number;
46
+ /** Cap on the number of conversation turns before each query stops. */
47
+ maxTurns?: number;
48
+ }
49
+ /** Schema of the Claude Code loop plugin configuration. */
50
+ export declare const Config: z<Config>;
51
+ /** Host-face ctx key for the Claude Code loop service. */
52
+ declare module '@deepseek-ai/cordis' {
53
+ interface Context {
54
+ agentLoopClaudeCode: ClaudeCodeLoop;
55
+ }
56
+ }
57
+ /**
58
+ * Concrete AgentFactory and driver service of the Claude Code loop. Creation
59
+ * and resume follow the registry factory contract and the shared publication
60
+ * transaction: prepare, run setup, then publish through both registries,
61
+ * announce, and emit `agent/session-start`.
62
+ */
63
+ export declare class ClaudeCodeLoop extends Service implements AgentFactory {
64
+ /** Services the loop resolves through its own fiber; blessed identically to the package-level entry inject. */
65
+ static inject: string[];
66
+ /** Validated configuration owned by the loop plugin. */
67
+ readonly config: ResolvedConfig;
68
+ private readonly ownership;
69
+ /** Plain holder prevents Cordis from re-tracing the factory's dependency context through a caller shadow. */
70
+ private readonly runtime;
71
+ constructor(ctx: Context, config: Config);
72
+ /**
73
+ * Construct the driver, scope, and one memoized reverse teardown for a new
74
+ * agent. The teardown is registered with the factory and the owner fiber
75
+ * BEFORE publication, so a mid-setup unload rolls everything back; `signal`
76
+ * fuses caller cancellation with lifecycle teardown for setup awaits.
77
+ */
78
+ private prepare;
79
+ /** Prepare one Agent around an acquired Session, run setup, and publish it. */
80
+ private setupAndPublish;
81
+ /**
82
+ * Create an agent and session under one caller-supplied identity, owned by
83
+ * the accessing fiber.
84
+ * @param ownerCtx - caller context that structurally owns the lifecycle.
85
+ * @param options - identities, session seed/metadata, loop options, setup, and cancellation.
86
+ * @returns the published handle.
87
+ */
88
+ createAgent(ownerCtx: Context, options: CreateAgentOptions): Promise<AgentHandle>;
89
+ /**
90
+ * Resume an owned agent from the configured persistence service.
91
+ * @param ownerCtx - caller context that owns load, setup, and the live lifecycle.
92
+ * @param options - persisted identity, loop options, setup, and cancellation.
93
+ * @returns the published handle.
94
+ */
95
+ resume(ownerCtx: Context, options: ResumeAgentOptions): Promise<AgentHandle>;
96
+ /** Resume through an explicit persistence handle. */
97
+ private resumeWith;
98
+ }
99
+ //# sourceMappingURL=loop.d.ts.map
@@ -0,0 +1,84 @@
1
+ /**
2
+ * Pure translation from the Claude Agent SDK's message vocabulary to the dsh
3
+ * session-log vocabulary. Each function maps one SDK message to the durable
4
+ * event payloads the driver appends inside its current step, so the mapping
5
+ * stays unit-testable without any SDK process.
6
+ *
7
+ * @module dsh-agent-hub/engine-claude/mapping
8
+ */
9
+ import type { BetaMessage, BetaRawMessageStreamEvent, BetaUsage } from '@anthropic-ai/sdk/resources/beta/messages/messages.mjs';
10
+ import type { MessageParam } from '@anthropic-ai/sdk/resources';
11
+ import { type ContentBlock, type StreamChunk, type TokenUsage, type ToolResultMessage } from '@deepseek-ai/dsh-llm';
12
+ import { CallId } from '../llm-compat.ts';
13
+ /** One tool invocation surfaced from a Claude Code assistant message. */
14
+ export interface MappedToolCall {
15
+ /** SDK tool_use id, reused as the dsh call-id so results pair. */
16
+ readonly callId: CallId;
17
+ /** Tool name exactly as the SDK reported it. */
18
+ readonly name: string;
19
+ /** Raw JSON arguments string as the SDK produced them. */
20
+ readonly arguments: string;
21
+ }
22
+ /** Result of translating one SDK assistant message. */
23
+ export interface MappedAssistantMessage {
24
+ /** dsh content blocks: text verbatim, tool calls as tool-call blocks. */
25
+ readonly content: ContentBlock[];
26
+ /** Tool invocations surfaced as dsh tool/call events. */
27
+ readonly toolCalls: readonly MappedToolCall[];
28
+ /** Provider-reported token accounting, when present. */
29
+ readonly usage: TokenUsage | undefined;
30
+ /** Model id reported by the SDK message. */
31
+ readonly model: string;
32
+ }
33
+ /**
34
+ * Render an SDK tool input as the raw JSON string carried by a dsh tool-call
35
+ * block. Values that cannot be stringified (undefined, functions, cyclic
36
+ * graphs) fall back to a stable placeholder instead of failing the mapping.
37
+ * @param input - the SDK tool input value.
38
+ * @returns the JSON string, or a placeholder when the input is not JSON-serializable.
39
+ */
40
+ export declare function stringifyToolInput(input: unknown): string;
41
+ /**
42
+ * Translate one SDK assistant message into dsh content blocks and tool calls.
43
+ * Text blocks map verbatim; tool_use blocks map to tool-call blocks and
44
+ * surfaced calls; thinking blocks map to reasoning blocks; redacted-thinking
45
+ * and unknown blocks are dropped.
46
+ * @param message - the SDK assistant message.
47
+ * @returns the mapped content, calls, usage, and model.
48
+ */
49
+ export declare function mapAssistantMessage(message: BetaMessage): MappedAssistantMessage;
50
+ /**
51
+ * Translate the tool_result blocks of one SDK user message into dsh
52
+ * tool-result messages. Non-tool_result blocks are ignored: Claude Code user
53
+ * messages inside a query carry only tool outcomes.
54
+ * @param message - the SDK user message.
55
+ * @returns the mapped tool-result messages, in block order.
56
+ */
57
+ export declare function mapToolResults(message: MessageParam): ToolResultMessage[];
58
+ /**
59
+ * Translate SDK token accounting into the dsh token-usage shape. Cache
60
+ * breakpoints are optional; absent or null SDK counters stay absent.
61
+ * @param usage - SDK-reported usage for one assistant message.
62
+ * @returns dsh token accounting, omitting absent optional counters.
63
+ */
64
+ export declare function mapUsage(usage: BetaUsage): TokenUsage;
65
+ /** Per-block-index tool-call identity captured at `content_block_start`, reused by `input_json_delta`. */
66
+ export interface StreamToolCall {
67
+ readonly callId: CallId;
68
+ readonly name: string;
69
+ }
70
+ /**
71
+ * Translate one SDK raw stream event into the dsh assistant chunks that drive
72
+ * the live partial projection. Text blocks yield `block-start`/`text-delta`;
73
+ * thinking blocks yield `block-start`/`reasoning-delta`; tool_use blocks yield
74
+ * `block-start`/`tool-call-delta`. Redacted thinking, signature deltas,
75
+ * `content_block_stop`, and transport events yield nothing — the durable
76
+ * `assistant/message` is appended separately from the SDK's complete message,
77
+ * so the streamed chunks never have to carry the whole block.
78
+ * @param event - one raw stream event from an `includePartialMessages` query.
79
+ * @param toolCalls - per-block-index tool identity, mutated here at a tool
80
+ * `content_block_start` so later `input_json_delta` can name the call.
81
+ * @returns the chunks that change the visible partial (empty for non-visual events).
82
+ */
83
+ export declare function mapStreamEvent(event: BetaRawMessageStreamEvent, toolCalls: Map<number, StreamToolCall>): StreamChunk[];
84
+ //# sourceMappingURL=mapping.d.ts.map
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Mapping from the dsh session's durable permission knobs to one Claude Code
3
+ * query's native permission handling. The session log pins `sandbox/mode`
4
+ * and `approval/policy` events at creation and records every later switch;
5
+ * folding them per query keeps the Claude Code driver consistent with the
6
+ * permission preset the web surface shows, including mid-session switches.
7
+ *
8
+ * @module dsh-agent-hub/engine-claude/permission
9
+ */
10
+ import type { PermissionEvent } from '../driver-core/permission-knobs.ts';
11
+ /**
12
+ * The effective native permission stance for one query:
13
+ * - `bypass` — full access: skip every native permission check.
14
+ * - `ask` — forward each native permission request to the dsh approval seam.
15
+ * - `deny` — auto-deny every native permission request (unattended default).
16
+ */
17
+ export type SessionPermission = {
18
+ readonly kind: 'bypass';
19
+ } | {
20
+ readonly kind: 'ask';
21
+ } | {
22
+ readonly kind: 'deny';
23
+ };
24
+ /**
25
+ * Resolve the session's effective native permission stance. Full access wins
26
+ * outright (the web "full" preset pins it together with `never`); otherwise
27
+ * an `ask` policy forwards permission requests to the dsh approval seam and
28
+ * anything else — including a session with no recorded knobs — fails closed.
29
+ * @param events - the durable session log.
30
+ * @returns the stance one query should run under.
31
+ */
32
+ export declare function resolveSessionPermission(events: readonly PermissionEvent[]): SessionPermission;
33
+ /**
34
+ * Human-readable explanation of WHY a native permission request is asked,
35
+ * carrying a bounded excerpt of the exact tool input.
36
+ * @param toolName - the native tool being decided.
37
+ * @param input - the exact tool input.
38
+ * @returns the approval request's reason text.
39
+ */
40
+ export declare function approvalReason(toolName: string, input: Record<string, unknown>): string;
41
+ //# sourceMappingURL=permission.d.ts.map
@@ -0,0 +1,59 @@
1
+ /**
2
+ * Projection from the shared managed-process handle to the official Claude
3
+ * Agent SDK's custom-spawn process interface.
4
+ *
5
+ * @module dsh-agent-hub/engine-claude/process
6
+ */
7
+ import type { SpawnedProcess, SpawnOptions } from '@anthropic-ai/claude-agent-sdk';
8
+ import { type SubprocessHandle, type SubprocessOutcome, type SubprocessSpawnSpec } from '@deepseek-ai/dsh-subprocess';
9
+ /**
10
+ * Encode the SDK's complete child environment as a subprocess overlay.
11
+ * @param env - SDK-composed child environment after its removals and replacements.
12
+ * @returns explicit values plus tombstones for surviving ambient names the SDK removed.
13
+ */
14
+ export declare function sdkEnvironmentOverlay(env: SpawnOptions['env']): NodeJS.ProcessEnv;
15
+ /**
16
+ * Translate one official SDK spawn request to the shared process owner.
17
+ * @param options - command, arguments, workspace, environment, and forwarded signal from the SDK.
18
+ * @param graceMs - process-tree termination grace.
19
+ * @returns the fully explicit shared subprocess request.
20
+ */
21
+ export declare function claudeSpawnSpec(options: SpawnOptions, graceMs: number): SubprocessSpawnSpec;
22
+ /**
23
+ * SDK-facing view of one shared managed process. Protocol transport remains
24
+ * in the official SDK; this adapter only projects streams and exit events.
25
+ */
26
+ export declare class ManagedClaudeCodeProcess implements SpawnedProcess {
27
+ private readonly child;
28
+ readonly stdin: import("stream").Writable;
29
+ readonly stdout: import("stream").Readable;
30
+ private readonly events;
31
+ private outcomeValue;
32
+ private killRequested;
33
+ /**
34
+ * Project a managed process with piped stdin and stdout.
35
+ * @param child - shared handle that remains the process-tree authority.
36
+ */
37
+ constructor(child: SubprocessHandle);
38
+ /** Whether the SDK has requested managed tree termination. */
39
+ get killed(): boolean;
40
+ /** Direct-child exit code, or null while running or after signal exit. */
41
+ get exitCode(): number | null;
42
+ /** Direct-child terminating signal, if any. */
43
+ get signalCode(): NodeJS.Signals | null;
44
+ /** Exact managed-process outcome after exit, or undefined while running. */
45
+ get outcome(): SubprocessOutcome | undefined;
46
+ /**
47
+ * Route the SDK's termination request to the tree-scoped process owner.
48
+ * @param _signal - SDK-selected signal; the shared seam owns its escalation ladder.
49
+ * @returns false only after exit or a previous termination request.
50
+ */
51
+ kill(_signal: NodeJS.Signals): boolean;
52
+ /** Register a persistent process lifecycle listener. */
53
+ on(event: 'exit' | 'error', listener: ((code: number | null, signal: NodeJS.Signals | null) => void) | ((error: Error) => void)): void;
54
+ /** Register a one-shot process lifecycle listener. */
55
+ once(event: 'exit' | 'error', listener: ((code: number | null, signal: NodeJS.Signals | null) => void) | ((error: Error) => void)): void;
56
+ /** Remove a process lifecycle listener. */
57
+ off(event: 'exit' | 'error', listener: ((code: number | null, signal: NodeJS.Signals | null) => void) | ((error: Error) => void)): void;
58
+ }
59
+ //# sourceMappingURL=process.d.ts.map
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Derive the Claude Code child's provider environment from dsh's own LLM
3
+ * configuration, so a session reaches the same endpoint dsh itself would use.
4
+ *
5
+ * The alternative — re-inheriting `process.env` — only works when the host was
6
+ * launched from a shell that already exported provider credentials. A dsh
7
+ * started from a desktop launcher inherits none, the child falls back to the
8
+ * CLI's own login state, and the turn dies as a 403 far from its cause. dsh
9
+ * already knows the answer: `llm-pi-ai` holds the route's `baseURL` and the
10
+ * name of its credential, and `credentials` resolves that name to a secret.
11
+ * This module reads both and states the result as environment variables the
12
+ * Agent SDK understands.
13
+ *
14
+ * Only the route's *transport* is derived. Which model runs is settled earlier
15
+ * by the agent's own resolution (session choice, then `agentDefaultModel`), and
16
+ * is passed in rather than re-read here.
17
+ *
18
+ * Everything is resolved per call. `credentials.resolve` is contractually a
19
+ * per-call read — the store layers process env over `~/.dsh/.credentials.yaml`
20
+ * over `.env` files, any of which may change under a long-lived host — so a
21
+ * cached secret would outlive its source.
22
+ *
23
+ * @module dsh-agent-hub/engine-claude/provider-env
24
+ */
25
+ import type { Context } from '@deepseek-ai/cordis';
26
+ /** How a resolved route is carried to the child. */
27
+ export interface ProviderEnv {
28
+ /** Environment entries to lay over the child's environment. */
29
+ readonly env: Record<string, string>;
30
+ /** One line naming the route, for the session log. */
31
+ readonly diagnostic: string;
32
+ }
33
+ /**
34
+ * Build the child's provider environment from the route the selected model
35
+ * belongs to.
36
+ *
37
+ * Returns undefined — leaving the caller's existing behavior intact — whenever
38
+ * the route cannot be derived: no provider named, settings or credentials
39
+ * absent, the route unconfigured, its credential unset, or its protocol one the
40
+ * CLI cannot speak. Each of those is a profile that legitimately routes some
41
+ * other way, so none is an error here; the caller still falls back to inherited
42
+ * environment, and `backendDiagnostic` still reports when that leaves the child
43
+ * with nothing.
44
+ *
45
+ * @param ctx - context to resolve `settings` and `credentials` through.
46
+ * @param provider - route id from the resolved model selection.
47
+ * @returns the environment overlay and a diagnostic, or undefined.
48
+ */
49
+ export declare function deriveProviderEnv(ctx: Context, provider: string | undefined): Promise<ProviderEnv | undefined>;
50
+ //# sourceMappingURL=provider-env.d.ts.map
@@ -0,0 +1,101 @@
1
+ /**
2
+ * One Claude Agent SDK query: options assembly, process seam projection, and
3
+ * the headless interaction policy. The driver runs exactly one query per dsh
4
+ * step; this module owns no session state.
5
+ *
6
+ * @module dsh-agent-hub/engine-claude/sdk
7
+ */
8
+ import type { Options, PermissionMode } from '@anthropic-ai/claude-agent-sdk';
9
+ import type { SubprocessHandle, SubprocessSpawnSpec } from '@deepseek-ai/dsh-subprocess';
10
+ import type { ClaudeCodeBackend } from './types.ts';
11
+ /** Native lock-down mode fixed for every query unless deployment overrides it. */
12
+ export declare const DEFAULT_PERMISSION_MODE: "dontAsk";
13
+ /** Grace in milliseconds for Claude Code process-tree termination. */
14
+ export declare const DEFAULT_DISPOSE_GRACE_MS = 3000;
15
+ export type { PermissionMode };
16
+ /** Deployment-owned process-spawn capability handed over from the plugin. */
17
+ export type SpawnCapability = (spec: SubprocessSpawnSpec) => SubprocessHandle;
18
+ /** Everything one SDK query needs, resolved at step time. */
19
+ export interface ClaudeCodeQuerySpec {
20
+ /** Absolute workspace the Claude Code process runs in. */
21
+ readonly cwd: string;
22
+ /** Native permission handling for this query. */
23
+ readonly permissionMode: PermissionMode;
24
+ /** Explicit environment entries layered over the scrubbed parent environment. */
25
+ readonly env?: Record<string, string>;
26
+ /**
27
+ * Provider routing derived from dsh's own LLM configuration, when the model
28
+ * selection named a route this plugin could resolve.
29
+ *
30
+ * Kept separate from {@link env} because it does not merely add entries: a
31
+ * derived route is authoritative about which backend the child speaks, so
32
+ * every *other* backend's keys are removed rather than left to out-rank it.
33
+ * The deployment's `env` still layers on top, so an explicit override wins.
34
+ */
35
+ readonly providerEnv?: Record<string, string>;
36
+ /** Grace in milliseconds for process-tree termination. */
37
+ readonly disposeGraceMs: number;
38
+ /** Model override for the SDK, when a selection or the deployment pins one. */
39
+ readonly model?: string;
40
+ /** Provider route the model id belongs to, used to diagnose a backend mismatch. */
41
+ readonly provider?: string;
42
+ /** Provider backend the child is pointed at; defaults to `auto`. */
43
+ readonly backend?: ClaudeCodeBackend;
44
+ /** Cap on the number of conversation turns before the query stops. */
45
+ readonly maxTurns?: number;
46
+ /**
47
+ * Decide one native permission request through the dsh approval seam.
48
+ * When present, `canUseTool` forwards to it instead of auto-denying.
49
+ */
50
+ readonly onToolPermission?: (toolName: string, input: Record<string, unknown>, signal: AbortSignal) => Promise<'allow' | 'deny'>;
51
+ /** Spawn the Claude Code child under the shared process owner. */
52
+ readonly spawn: SpawnCapability;
53
+ /** Receive a human-readable denial or decline for one unattended interaction. */
54
+ readonly onUnattended?: (description: string) => void;
55
+ }
56
+ /**
57
+ * Diagnose one auto-answered interaction in headless mode.
58
+ * @param mode - permission mode in force.
59
+ * @param kind - what the interaction was.
60
+ * @param answer - what the driver did.
61
+ * @param why - reason the driver cannot forward the interaction.
62
+ * @returns a stable one-line diagnostic.
63
+ */
64
+ export declare function unattendedDiagnostic(mode: PermissionMode, kind: string, answer: string, why: string): string;
65
+ /**
66
+ * Describe the backend the child will actually run on.
67
+ *
68
+ * A misrouted child fails far from its cause: with nothing configured the CLI
69
+ * falls back to its own login state and reports "Not logged in", and with the
70
+ * wrong backend it reports a model that is "not available". Neither names the
71
+ * environment, so state the resolved routing up front.
72
+ *
73
+ * @param env - the composed child environment.
74
+ * @param backend - the deployment's choice.
75
+ * @returns a one-line diagnostic, or undefined when routing is unambiguous.
76
+ */
77
+ export declare function backendDiagnostic(env: Record<string, string>, backend: ClaudeCodeBackend): string | undefined;
78
+ /**
79
+ * Flag a model the active backend is unlikely to serve.
80
+ *
81
+ * The dsh selection names a provider route, and only a relay's endpoint is
82
+ * deployment-chosen — so a selection routed at some other provider reaching a
83
+ * cloud backend is a mismatch the child will discover as an opaque
84
+ * model-not-found. The id is still sent as-is: the caller asked for it, the
85
+ * provider lists it, and refusing here would substitute a model the user did
86
+ * not pick.
87
+ *
88
+ * @param model - the resolved model id.
89
+ * @param provider - the provider route the selection named, when it named one.
90
+ * @param env - the composed child environment.
91
+ * @returns a one-line diagnostic, or undefined when nothing looks wrong.
92
+ */
93
+ export declare function modelDiagnostic(model: string | undefined, provider: string | undefined, env: Record<string, string>): string | undefined;
94
+ /**
95
+ * Build the fixed official SDK options for one step's query.
96
+ * @param spec - workspace, environment, process seam, and disposal policy.
97
+ * @param controller - per-query cancellation owner.
98
+ * @returns the options for one stateless query.
99
+ */
100
+ export declare function claudeQueryOptions(spec: ClaudeCodeQuerySpec, controller: AbortController): Options;
101
+ //# sourceMappingURL=sdk.d.ts.map