dsh-loop-engine-allinone 0.0.0-stage → 0.4.0

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 (143) hide show
  1. package/CHANGELOG.md +100 -0
  2. package/CONTRIBUTING.md +78 -0
  3. package/LICENSE +23 -0
  4. package/NOTICE +45 -0
  5. package/README.md +221 -2
  6. package/README.zh.md +89 -0
  7. package/SECURITY.md +39 -0
  8. package/cordis.patch.yml +3 -0
  9. package/lib/client.js +2166 -0
  10. package/lib/index.js +11621 -0
  11. package/lib/invariant.js +453 -0
  12. package/lib/types/agent-preset-ids.d.ts +276 -0
  13. package/lib/types/client/LoopEngineBadge.d.ts +71 -0
  14. package/lib/types/client/LoopEngineComposerSelect.d.ts +126 -0
  15. package/lib/types/client/LoopEngineSection.d.ts +35 -0
  16. package/lib/types/client/engine-marks.d.ts +87 -0
  17. package/lib/types/client/index.d.ts +39 -0
  18. package/lib/types/client/locales.d.ts +182 -0
  19. package/lib/types/client/reload.d.ts +135 -0
  20. package/lib/types/client/session-engine.d.ts +508 -0
  21. package/lib/types/client/store.d.ts +103 -0
  22. package/lib/types/client/turn-status.d.ts +234 -0
  23. package/lib/types/client/use-session-engine.d.ts +74 -0
  24. package/lib/types/commands.d.ts +77 -0
  25. package/lib/types/compat.d.ts +25 -0
  26. package/lib/types/driver-acp/agent.d.ts +289 -0
  27. package/lib/types/driver-acp/approval.d.ts +27 -0
  28. package/lib/types/driver-acp/capabilities.d.ts +200 -0
  29. package/lib/types/driver-acp/client.d.ts +297 -0
  30. package/lib/types/driver-acp/executable.d.ts +53 -0
  31. package/lib/types/driver-acp/mapping.d.ts +76 -0
  32. package/lib/types/driver-acp/profile.d.ts +126 -0
  33. package/lib/types/driver-acp/runtime.d.ts +45 -0
  34. package/lib/types/driver-acp/subprocess.d.ts +19 -0
  35. package/lib/types/driver-acp/terminal.d.ts +98 -0
  36. package/lib/types/driver-acp/transport.d.ts +43 -0
  37. package/lib/types/driver-acp/types.d.ts +152 -0
  38. package/lib/types/driver-cli/capability.d.ts +42 -0
  39. package/lib/types/driver-cli/cli-agent.d.ts +258 -0
  40. package/lib/types/driver-cli/cli-loop.d.ts +46 -0
  41. package/lib/types/driver-cli/flatten.d.ts +35 -0
  42. package/lib/types/driver-cli/frames.d.ts +128 -0
  43. package/lib/types/driver-cli/ndjson.d.ts +106 -0
  44. package/lib/types/driver-cli/session-sink.d.ts +333 -0
  45. package/lib/types/driver-cli/stream-json.d.ts +61 -0
  46. package/lib/types/driver-cli/text.d.ts +66 -0
  47. package/lib/types/driver-cli/transport.d.ts +84 -0
  48. package/lib/types/driver-core/agents-md-skill-provider.d.ts +72 -0
  49. package/lib/types/driver-core/assistant-stream.d.ts +68 -0
  50. package/lib/types/driver-core/context-files.d.ts +62 -0
  51. package/lib/types/driver-core/host-servers.d.ts +119 -0
  52. package/lib/types/driver-core/hosted-engine-runtime.d.ts +190 -0
  53. package/lib/types/driver-core/hosted-tool-vocabulary.d.ts +78 -0
  54. package/lib/types/driver-core/idle-child.d.ts +57 -0
  55. package/lib/types/driver-core/image-access.d.ts +25 -0
  56. package/lib/types/driver-core/inbox.d.ts +104 -0
  57. package/lib/types/driver-core/model-handover.d.ts +134 -0
  58. package/lib/types/driver-core/ownership.d.ts +41 -0
  59. package/lib/types/driver-core/permission-knobs.d.ts +26 -0
  60. package/lib/types/driver-core/prompt.d.ts +64 -0
  61. package/lib/types/driver-core/session-lifetime.d.ts +62 -0
  62. package/lib/types/driver-core/session-model.d.ts +128 -0
  63. package/lib/types/driver-core/skill-inject.d.ts +59 -0
  64. package/lib/types/driver-core/step-close.d.ts +49 -0
  65. package/lib/types/driver-core/step-images.d.ts +62 -0
  66. package/lib/types/driver-core/step-tools.d.ts +43 -0
  67. package/lib/types/driver-core/system-head.d.ts +43 -0
  68. package/lib/types/engine-agy/agent.d.ts +67 -0
  69. package/lib/types/engine-agy/frames.d.ts +90 -0
  70. package/lib/types/engine-agy/loop.d.ts +64 -0
  71. package/lib/types/engine-agy/process.d.ts +173 -0
  72. package/lib/types/engine-claude/agent.d.ts +186 -0
  73. package/lib/types/engine-claude/loop.d.ts +73 -0
  74. package/lib/types/engine-claude/mapping.d.ts +108 -0
  75. package/lib/types/engine-claude/permission.d.ts +41 -0
  76. package/lib/types/engine-claude/process.d.ts +59 -0
  77. package/lib/types/engine-claude/sdk.d.ts +67 -0
  78. package/lib/types/engine-claude/types.d.ts +28 -0
  79. package/lib/types/engine-codex/agent.d.ts +216 -0
  80. package/lib/types/engine-codex/appserver/client.d.ts +80 -0
  81. package/lib/types/engine-codex/appserver/mapping.d.ts +67 -0
  82. package/lib/types/engine-codex/appserver/thread.d.ts +66 -0
  83. package/lib/types/engine-codex/appserver/types.d.ts +225 -0
  84. package/lib/types/engine-codex/loop.d.ts +75 -0
  85. package/lib/types/engine-codex/model-handover.d.ts +56 -0
  86. package/lib/types/engine-codex/permission.d.ts +126 -0
  87. package/lib/types/engine-codex/skills.d.ts +28 -0
  88. package/lib/types/engine-codex/types.d.ts +36 -0
  89. package/lib/types/engine-drivers.d.ts +132 -0
  90. package/lib/types/engine-grok/agent.d.ts +24 -0
  91. package/lib/types/engine-grok/loop.d.ts +61 -0
  92. package/lib/types/engine-grok/process.d.ts +46 -0
  93. package/lib/types/engine-grok/profile.d.ts +82 -0
  94. package/lib/types/engine-hermes/agent.d.ts +47 -0
  95. package/lib/types/engine-hermes/loop.d.ts +56 -0
  96. package/lib/types/engine-hermes/process.d.ts +92 -0
  97. package/lib/types/engine-kimi/acp/client.d.ts +123 -0
  98. package/lib/types/engine-kimi/acp/mapping.d.ts +73 -0
  99. package/lib/types/engine-kimi/acp/types.d.ts +143 -0
  100. package/lib/types/engine-kimi/agent.d.ts +24 -0
  101. package/lib/types/engine-kimi/commands.d.ts +44 -0
  102. package/lib/types/engine-kimi/loop.d.ts +62 -0
  103. package/lib/types/engine-kimi/model-handover.d.ts +32 -0
  104. package/lib/types/engine-kimi/permission.d.ts +28 -0
  105. package/lib/types/engine-kimi/process.d.ts +47 -0
  106. package/lib/types/engine-kimi/profile.d.ts +19 -0
  107. package/lib/types/engine-kimi/skills.d.ts +52 -0
  108. package/lib/types/engine-kimi/types.d.ts +25 -0
  109. package/lib/types/engine-minimaxcode/agent.d.ts +24 -0
  110. package/lib/types/engine-minimaxcode/loop.d.ts +83 -0
  111. package/lib/types/engine-minimaxcode/process.d.ts +53 -0
  112. package/lib/types/engine-minimaxcode/profile.d.ts +72 -0
  113. package/lib/types/engine-of-session.d.ts +97 -0
  114. package/lib/types/engine-pi/agent.d.ts +230 -0
  115. package/lib/types/engine-pi/loop.d.ts +72 -0
  116. package/lib/types/engine-pi/model-handover.d.ts +84 -0
  117. package/lib/types/engine-pi/permission.d.ts +47 -0
  118. package/lib/types/engine-pi/rpc/client.d.ts +107 -0
  119. package/lib/types/engine-pi/rpc/mapping.d.ts +37 -0
  120. package/lib/types/engine-pi/rpc/types.d.ts +249 -0
  121. package/lib/types/engine-pi/skills.d.ts +47 -0
  122. package/lib/types/engine-pi/types.d.ts +36 -0
  123. package/lib/types/engine-qoderclicn/agent.d.ts +59 -0
  124. package/lib/types/engine-qoderclicn/loop.d.ts +51 -0
  125. package/lib/types/engine-qoderclicn/process.d.ts +113 -0
  126. package/lib/types/engine-registry.d.ts +584 -0
  127. package/lib/types/engine-remote.d.ts +192 -0
  128. package/lib/types/engine-surface.d.ts +36 -0
  129. package/lib/types/engine-zcode/agent.d.ts +50 -0
  130. package/lib/types/engine-zcode/loop.d.ts +47 -0
  131. package/lib/types/engine-zcode/process.d.ts +111 -0
  132. package/lib/types/index.d.ts +205 -0
  133. package/lib/types/invariant.d.ts +26 -0
  134. package/lib/types/model-selection-reset.d.ts +271 -0
  135. package/lib/types/namespace.d.ts +25 -0
  136. package/lib/types/patch-manager.d.ts +104 -0
  137. package/lib/types/preset.d.ts +254 -0
  138. package/lib/types/provider-route.d.ts +245 -0
  139. package/lib/types/router-loop.d.ts +458 -0
  140. package/lib/types/session-engine-store.d.ts +138 -0
  141. package/lib/types/settings.d.ts +60 -0
  142. package/lib/types/skills.d.ts +85 -0
  143. package/package.json +150 -4
@@ -0,0 +1,128 @@
1
+ /**
2
+ * The dsh model selection a hosted engine is handed, and the ONE judgement that
3
+ * decides it.
4
+ *
5
+ * A session's model seat is the harness's own per-session fact: the host writes
6
+ * a `model/selection` event when the user picks a model, and derives the
7
+ * session's selection from the newest pending selection, else the logged
8
+ * `request/header` (`packages/api/session-controller/src/agent.ts`,
9
+ * `selectionFor`). A hosted engine owns its model natively, but it can still be
10
+ * handed a real dsh model when the session selected one — that is what this
11
+ * module answers.
12
+ *
13
+ * Three cases, decided once here and consumed by every hosted driver:
14
+ *
15
+ * - NO selection, or one whose provider is a hosted engine route label
16
+ * ({@link isHostedProviderRoute}: today's shared `external`, or a label an
17
+ * earlier build logged) → `undefined`. The engine keeps its own native
18
+ * default or the model the deployment pinned in its composition; nothing is
19
+ * sent, so the engine is not asked a question it never had an opinion on.
20
+ * - a REAL dsh model (any other provider) → `{ provider, model }`. Each engine
21
+ * renders that into its own interface: Pi's `--model <provider>/<model>`,
22
+ * Claude Code's `Options.model`, Codex's `thread/start` `model`, and Kimi's
23
+ * ACP `session/set_model`. Whether the engine can actually serve the model is
24
+ * the engine's own business: a refusal is reported, never swallowed.
25
+ *
26
+ * The read is the host's own ({@link currentSelection}), so the value an engine
27
+ * gets is the value the host would install for the session — and it is taken
28
+ * fresh on every step, because a session's model can change mid-conversation.
29
+ *
30
+ * @module dsh-loop-engine-allinone/driver-core/session-model
31
+ */
32
+ import type { Context } from '@deepseek-ai/cordis';
33
+ import type { Session } from '@deepseek-ai/dsh-session';
34
+ import type { HostedEngineId } from '../engine-registry.ts';
35
+ import type { SessionModelSelection, SessionProjectionsService } from './host-servers.ts';
36
+ /** The model a session's own selection asks a hosted engine to run. */
37
+ export interface SessionModelOverride {
38
+ /** Provider route the selection names, in the engine's own provider vocabulary. */
39
+ readonly provider: string;
40
+ /** Provider-owned model id the selection names. */
41
+ readonly model: string;
42
+ }
43
+ /**
44
+ * The selection the host will use for this session, by the host's own read
45
+ * (`ApiSessionAgentController.selectionFor`): a pending selection — one
46
+ * appended, not yet consumed by a matching recorded request — outranks the
47
+ * logged header, and the header answers when nothing is pending.
48
+ *
49
+ * A deployment with no session-projection registry is not an error: the read
50
+ * simply skips the pending half and answers from the logged header, exactly as
51
+ * a session whose log carries only a header would.
52
+ * @param session - the session whose selection is being read.
53
+ * @param projections - the host session-projection registry, when composed.
54
+ * @returns the current selection, or undefined when the log records none.
55
+ */
56
+ export declare function currentSelection(session: Session, projections: SessionProjectionsService | undefined): SessionModelSelection | undefined;
57
+ /**
58
+ * The model one hosted engine should be handed for this selection, or
59
+ * `undefined` to leave the engine to its own default (or the deployment's pin).
60
+ *
61
+ * The provider is the whole test: a hosted engine route label — the shared
62
+ * `external` this plugin serves as a placeholder, or a per-engine label an
63
+ * earlier build logged — means "the engine decides", not a model to send. Any
64
+ * other provider is a real dsh model, and the plugin passes it through rather
65
+ * than second-guessing whether the engine can serve it: a rejection is the
66
+ * engine's to report, and this plugin surfaces it.
67
+ * @param selection - the session's current selection, or undefined when none.
68
+ * @returns the model to hand over, or undefined to send nothing.
69
+ */
70
+ export declare function sessionModelOverride(selection: SessionModelSelection | undefined): SessionModelOverride | undefined;
71
+ /**
72
+ * The model override for one session, read live from its log and judged by
73
+ * {@link sessionModelOverride}.
74
+ *
75
+ * The four drivers' single entry: each calls this at the top of every step, so a
76
+ * model picked mid-conversation lands on the engine's next request rather than
77
+ * being frozen when the agent was built.
78
+ * @param ctx - the driver's context, carrying the session-projection registry.
79
+ * @param session - the session whose selection is being resolved.
80
+ * @returns the model to hand the engine, or undefined to send nothing.
81
+ */
82
+ export declare function sessionModelOverrideOf(ctx: Context, session: Session): SessionModelOverride | undefined;
83
+ /**
84
+ * The ENGINE-NATIVE model one session's selection asks for, if any.
85
+ *
86
+ * A hosted engine's route normally answers `default`, meaning "the engine
87
+ * decides" — and {@link sessionModelOverride} correctly reports that as "send
88
+ * nothing". But an engine that declares its own catalog
89
+ * (`EngineDescriptor.models`) owns a route of its own, and selecting one of those
90
+ * entries names a model from the engine's own subscription. That is a third
91
+ * case, and it is NOT a dsh model: the id is the engine's vocabulary, so it must
92
+ * be handed over alone (`--model gemini-3.8-flash-high`), never as
93
+ * `provider/model`, and never routed through the endpoint handover.
94
+ *
95
+ * Kept beside {@link sessionModelOverride} rather than folded into it, so the
96
+ * four original drivers keep seeing exactly the answer they saw before.
97
+ * @param selection - the session's current selection, or undefined when none.
98
+ * @param engine - the engine this session is running.
99
+ * @returns the engine-native model id, or undefined when the selection is not one.
100
+ */
101
+ export declare function nativeModelOf(selection: SessionModelSelection | undefined, engine: HostedEngineId): string | undefined;
102
+ /**
103
+ * The refusal a driver owes when a session picked a model that belongs to a
104
+ * DIFFERENT engine, or undefined when the selection is fine.
105
+ *
106
+ * The model catalog is built per Host generation, so every engine's group is in
107
+ * every session's menu. Picking `agy`'s `gemini-3.8-flash-high` while the session
108
+ * runs Codex is therefore reachable, and silently ignoring it would leave the
109
+ * seat showing a model that is not in force — the exact class of lie this plugin
110
+ * exists to prevent. The driver refuses instead, naming both engines.
111
+ * @param selection - the session's current selection, or undefined when none.
112
+ * @param engine - the engine this session is running.
113
+ * @param engineLabel - that engine's display label, for the message.
114
+ * @returns the refusal message, or undefined.
115
+ */
116
+ export declare function foreignHostedModelRefusal(selection: SessionModelSelection | undefined, engine: HostedEngineId, engineLabel: string): string | undefined;
117
+ /**
118
+ * The model a driver should actually pass, resolved in one place.
119
+ *
120
+ * Three answers, in precedence order: an engine-native pick from this engine's
121
+ * own catalog; the deployment's pinned model; the engine's own default.
122
+ * @param selection - the session's current selection, or undefined when none.
123
+ * @param engine - the engine this session runs.
124
+ * @param pinned - the deployment's `model` knob for this engine, if any.
125
+ * @returns the model id to pass, or undefined to pass nothing.
126
+ */
127
+ export declare function modelForStep(selection: SessionModelSelection | undefined, engine: HostedEngineId, pinned: string | undefined): string | undefined;
128
+ //# sourceMappingURL=session-model.d.ts.map
@@ -0,0 +1,59 @@
1
+ /**
2
+ * Skill-injection helpers shared by the hosted engine drivers. Each hosted
3
+ * engine's agent replicates 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-loop-engine-allinone/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,49 @@
1
+ /**
2
+ * Closing one step of a hosted driver's transcript.
3
+ *
4
+ * A step may not end while a call it announced has no result (v4:
5
+ * `step/end leaves unresolved tool call …`), and an engine can leave one
6
+ * unanswered for reasons no driver controls — it announced several calls in one
7
+ * model turn and reported fewer outcomes, or the query ended mid-flight, or the
8
+ * step is aborting. The harness closes an interrupted turn the same way and with
9
+ * the same vocabulary (`openTurnClosers` in `@deepseek-ai/dsh-session/repair`):
10
+ * a synthetic ERROR result states the fact to the model, so the transcript stays
11
+ * valid and the next model turn knows the call's outcome is unknown rather than
12
+ * silently believing it succeeded.
13
+ *
14
+ * It is deliberately a closer, not a repair of history: it fixes the step being
15
+ * closed and nothing else.
16
+ *
17
+ * @module dsh-loop-engine-allinone/driver-core/step-close
18
+ */
19
+ import type { Session } from '@deepseek-ai/dsh-session';
20
+ import type { ToolCallId } from '@deepseek-ai/dsh-llm';
21
+ import type { StepTools } from './step-tools.ts';
22
+ /**
23
+ * End one step, closing every call it announced and never resolved.
24
+ *
25
+ * Synthetic results are appended BEFORE `step/end`, in announcement order, each
26
+ * citing nothing but its own call id — the driver has no `tool/call` event to
27
+ * cite because the call was announced by the assistant message that carried it.
28
+ * @param session - the session whose transcript is being written.
29
+ * @param tools - the step's call bookkeeping.
30
+ * @param turn - the turn the step belongs to.
31
+ * @param step - the step being closed.
32
+ */
33
+ export declare function closeStep(session: Session, tools: StepTools, turn: number, step: number): void;
34
+ /**
35
+ * Write one call's result, unless this step already has one for it.
36
+ *
37
+ * Every driver learns about a result from its engine's stream, and an engine can
38
+ * report the same outcome twice (the Claude Agent SDK redelivers each result
39
+ * ~57 ms later; Pi reports an execution from both `tool_execution_end` and its
40
+ * closing `turn_end`). v4 deletes a call's pending entry on its first result, so
41
+ * the second write is what it refuses (`tool/result … has no advertised tool
42
+ * lifecycle`) — the write goes through {@link StepTools.settle} instead, and the
43
+ * caller supplies only the durable write it would otherwise have made.
44
+ * @param tools - the step's call bookkeeping.
45
+ * @param callId - the call the result answers.
46
+ * @param write - the durable write, run at most once per call per step.
47
+ */
48
+ export declare function settleResult(tools: StepTools, callId: ToolCallId, write: () => void): void;
49
+ //# sourceMappingURL=step-close.d.ts.map
@@ -0,0 +1,62 @@
1
+ /**
2
+ * The images one STEP hands to an engine that has a native image channel.
3
+ *
4
+ * The durable log is the model context, and a serialized prompt can only carry
5
+ * an image as placeholder text naming the file ({@link serializeHistory}). An
6
+ * engine whose protocol accepts image bytes should not be told to read the file
7
+ * itself: {@link stepImages} resolves each image block of the step's own
8
+ * messages through the attachment service's host path, reads that normalized
9
+ * file, and returns it base64-encoded under the block's own media type. An
10
+ * engine whose protocol takes the file's PATH instead shares the walk and the
11
+ * resolution but reads nothing ({@link stepImagePaths}) — codex's app-server
12
+ * opens the image itself.
13
+ *
14
+ * Only the messages this step delivers are claimed — a long session must not
15
+ * re-upload its whole history every step. Older images stay in the transcript
16
+ * as path-bearing placeholders, which the engine's own file tool can still read.
17
+ *
18
+ * @module dsh-loop-engine-allinone/driver-core/step-images
19
+ */
20
+ import type { ContentBlock, ImageAttachmentAccessResolver, Message } from '@deepseek-ai/dsh-llm';
21
+ /** The durable reference an image block carries, derived from the block union so this module states no dependency on the attachment package. */
22
+ type ImageBlock = Extract<ContentBlock, {
23
+ type: 'image';
24
+ }>;
25
+ /**
26
+ * The media types a durable image reference can carry, taken from the block
27
+ * union so this module names no attachment-package symbol. It is the exact set
28
+ * every byte-accepting engine protocol declares (Anthropic's base64 image
29
+ * source among them), so a caller may hand this value straight to one.
30
+ */
31
+ type ImageMediaType = ImageBlock['attachment']['mediaType'];
32
+ /** One image of a step, as an engine that accepts image bytes takes it. */
33
+ export interface StepImage {
34
+ /** Base64-encoded normalized bytes. */
35
+ readonly data: string;
36
+ /** The image's own media type, from the durable reference. */
37
+ readonly mimeType: ImageMediaType;
38
+ }
39
+ /**
40
+ * Collect the images a step's messages carry, in message order.
41
+ *
42
+ * An image whose path does not resolve, or whose file cannot be read, is
43
+ * skipped: the transcript already names its path, so the model still has a route
44
+ * to it, and one missing file must not fail a step.
45
+ * @param messages - the messages this step delivers, oldest first.
46
+ * @param imageAccess - resolves an image block's read-only host path, when the host composes the attachment service.
47
+ * @returns the images to send, empty when there are none.
48
+ */
49
+ export declare function stepImages(messages: readonly Message[], imageAccess?: ImageAttachmentAccessResolver): Promise<readonly StepImage[]>;
50
+ /**
51
+ * The readable host path of each image the step delivers, in order.
52
+ *
53
+ * Nothing is opened: an engine that takes a path reads the file itself, so a
54
+ * path is returned even when no file is there — whether the path is usable is
55
+ * the engine's answer, not this walk's.
56
+ * @param messages - the messages this step delivers, oldest first.
57
+ * @param imageAccess - resolves an image block's read-only host path, when the host composes the attachment service.
58
+ * @returns the paths to send, empty when there are none.
59
+ */
60
+ export declare function stepImagePaths(messages: readonly Message[], imageAccess?: ImageAttachmentAccessResolver): readonly string[];
61
+ export {};
62
+ //# sourceMappingURL=step-images.d.ts.map
@@ -0,0 +1,43 @@
1
+ /**
2
+ * The tool calls one STEP has announced, and which of them already carry a
3
+ * result.
4
+ *
5
+ * Session format v4 requires every call a step announced to be resolved before
6
+ * that step ends (`step/end leaves unresolved tool call …`,
7
+ * `packages/session/session-format-v3-to-v4/src/relationships.ts`). A hosted
8
+ * driver learns about calls from the engine's stream, one assistant message at
9
+ * a time, and learns about results from a different stream of messages — so
10
+ * "which calls of THIS step are still open" is state the driver has to keep,
11
+ * not something the transcript position can be trusted to imply.
12
+ *
13
+ * Two facts live here, and they are the two directions of the same rule:
14
+ * `settle` keeps a call from being given a SECOND result in one step (the
15
+ * shape v4 rejects as `tool/result … has no advertised tool lifecycle`), and
16
+ * {@link StepTools.pending} is what a step must close before it ends.
17
+ *
18
+ * @module dsh-loop-engine-allinone/driver-core/step-tools
19
+ */
20
+ import type { ToolCallId } from '@deepseek-ai/dsh-llm';
21
+ /** One step's announced calls and their results. */
22
+ export interface StepTools {
23
+ /** Record a call this step announced. */
24
+ announce(callId: ToolCallId): void;
25
+ /**
26
+ * Record a result this step wrote.
27
+ * @returns `false` when that call was already settled in this step, i.e.
28
+ * when writing another result for it would be the duplicate v4 refuses.
29
+ */
30
+ settle(callId: ToolCallId): boolean;
31
+ /** Whether every call this step announced now has a result. */
32
+ readonly balanced: boolean;
33
+ /** The calls still owed a result, in the order they were announced. */
34
+ readonly pending: readonly ToolCallId[];
35
+ /** Forget everything: the next step owns a new set. */
36
+ clear(): void;
37
+ }
38
+ /**
39
+ * Build one step's call bookkeeping.
40
+ * @returns the set, empty and ready for its step.
41
+ */
42
+ export declare function createStepTools(): StepTools;
43
+ //# sourceMappingURL=step-tools.d.ts.map
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Give a session started on a hosted engine the protected system head the
3
+ * harness's own loop would have logged.
4
+ *
5
+ * The harness loop logs the rendered system prompt as a `system/message` on a
6
+ * session's first step (`packages/core/agent-loop/src/agent.ts`:
7
+ * `systemPrompt.project` → `session.append('system/message', …)`). A hosted
8
+ * engine's external CLI owns its own system prompt, so these drivers log no dsh
9
+ * system message at all: a session that STARTS on a hosted engine has no surface
10
+ * head, and if it is later served by the in-process loop the harness logs its
11
+ * system message MID-log. Session format v4 requires the system message — when
12
+ * one exists — to be the FIRST surface event, so such a mixed session is refused
13
+ * on the v3→v4 migration (`packages/session/session-format-v3-to-v4/src/
14
+ * relationships.ts` `foldSurface`: "system/message requires a protected first
15
+ * surface head").
16
+ *
17
+ * Appending an EMPTY system message as the session's first surface event closes
18
+ * that hole: the head is protected from the start (a later in-process system
19
+ * message REPLACES it rather than arriving misplaced), and empty content is
20
+ * dropped from the derived history (`deriveEventMessage` yields `null`), so no
21
+ * system prompt is injected into what the engine is handed — the drivers build
22
+ * their prompt from `serializeHistory`, which ignores the `system` role too.
23
+ *
24
+ * Conservative and idempotent: it appends ONLY while the session has no surface
25
+ * event of its own, so a session the harness loop created (or one already
26
+ * carrying history) is left exactly as it is. A mid-surface system head would be
27
+ * refused by the SAME v4 rule and is never produced here.
28
+ *
29
+ * @module dsh-loop-engine-allinone/driver-core/system-head
30
+ */
31
+ import type { Session } from '@deepseek-ai/dsh-session';
32
+ /**
33
+ * Append an empty `system/message` head when the session has no surface event
34
+ * yet, so a hosted-engine session carries the protected head format v4 expects.
35
+ *
36
+ * A no-op once any surface event exists: the head can only ever be the FIRST
37
+ * surface event, and a later one would be refused on migration.
38
+ * @param session - the session a hosted driver is about to run a step on.
39
+ * @param turn - the open turn's number.
40
+ * @param step - the open step's number.
41
+ */
42
+ export declare function appendSystemHeadIfMissing(session: Session, turn: number, step: number): void;
43
+ //# sourceMappingURL=system-head.d.ts.map
@@ -0,0 +1,67 @@
1
+ /**
2
+ * Antigravity agent: one `agy --input-format stream-json --output-format
3
+ * stream-json --print=` child per dsh step, with the durable session log as the
4
+ * sole source of model context.
5
+ *
6
+ * The engine-specific surface is `runStep`: serialize the transcript, write it to
7
+ * the child's stdin as one NDJSON user message, decode the `event`-tagged reply
8
+ * stream, and let the shared sink write the durable log. See
9
+ * `./process.ts` for the argument-position trap that shapes the argv and for the
10
+ * one protocol fact the probe could not reach (a signed-in host was unavailable),
11
+ * and `./frames.ts` for how the mapper stays correct under both worlds.
12
+ *
13
+ * @module dsh-loop-engine-allinone/engine-agy/agent
14
+ */
15
+ import type { AgentOptions } from '@deepseek-ai/dsh-agent';
16
+ import type { Session, SessionId, UserMessage } from '@deepseek-ai/dsh-session';
17
+ import type { Context } from '@deepseek-ai/cordis';
18
+ import type { HostedEngineId } from '../engine-registry.ts';
19
+ import { CliHostedAgent } from '../driver-cli/cli-agent.ts';
20
+ import type { SinkPosition } from '../driver-cli/session-sink.ts';
21
+ import type { CliSpawnCapability } from '../driver-cli/transport.ts';
22
+ import type { AgyEffort, AgyMode } from './process.ts';
23
+ /** Deployment-resolved configuration for the Antigravity engine. */
24
+ export interface ResolvedAgyConfig {
25
+ /** Pinned auto-approve flag, overriding the session's dsh knobs. */
26
+ readonly dangerouslySkipPermissions: boolean | undefined;
27
+ /** Pinned executable, when the deployment named one. */
28
+ readonly bin: string | undefined;
29
+ /** Explicit environment entries layered over the scrubbed parent environment. */
30
+ readonly env: Record<string, string>;
31
+ /** Pinned model. */
32
+ readonly model: string | undefined;
33
+ /** Pinned execution mode. */
34
+ readonly mode: AgyMode | undefined;
35
+ /** Pinned reasoning effort. */
36
+ readonly effort: AgyEffort | undefined;
37
+ /** Pinned sandbox flag, overriding the session's knobs. */
38
+ readonly sandbox: boolean | undefined;
39
+ }
40
+ /** The engine id this driver registers under. */
41
+ export declare const AGY_ENGINE: HostedEngineId;
42
+ /** Drives one session through turn and step boundaries on Antigravity. */
43
+ export declare class AgyAgent extends CliHostedAgent {
44
+ private readonly config;
45
+ private readonly spawn;
46
+ constructor(loopCtx: Context, id: SessionId, options: AgentOptions, session: Session, config: ResolvedAgyConfig, spawn: CliSpawnCapability);
47
+ protected runStep(messages: readonly UserMessage[], position: SinkPosition, signal: AbortSignal): Promise<{
48
+ kind: 'completed';
49
+ } | null>;
50
+ /**
51
+ * The session's current model selection, read the way the host reads it.
52
+ * @returns the selection, or undefined when the log records none.
53
+ */
54
+ private selection;
55
+ /**
56
+ * Whether the child should run with terminal restrictions (`--sandbox`).
57
+ *
58
+ * Antigravity's `--sandbox` restricts the CLI's own terminal use, which is not
59
+ * the same thing as the permission switch (see
60
+ * `agyDangerouslySkipPermissions`). It is requested whenever the session is NOT
61
+ * at full access: the subprocess seam already bounds the child, and asking the
62
+ * CLI to restrict itself as well is the fail-closed direction.
63
+ * @returns whether to pass `--sandbox`.
64
+ */
65
+ private sandboxRequested;
66
+ }
67
+ //# sourceMappingURL=agent.d.ts.map
@@ -0,0 +1,90 @@
1
+ /**
2
+ * The Antigravity frame mapper — now written against REAL frames.
3
+ *
4
+ * The first version of this module was written while the probe host's Google
5
+ * credential was expired, so only the `result` envelope could be observed and
6
+ * the streaming vocabulary was left UNKNOWN. Re-probing after the host signed in
7
+ * produced the whole protocol, and this is that protocol:
8
+ *
9
+ * ```
10
+ * {"event":"init","conversation_id":"f3b26f65-…",
11
+ * "init":{"cwd":"…","tools":[…],"permission_mode":"request-review"}}
12
+ *
13
+ * {"event":"step_update","step_update":{
14
+ * "conversation_id":"…","step_index":1,"state":"ACTIVE",
15
+ * "step_type":"agent_response","text_delta":"Source code turns to byt"}}
16
+ * {"event":"step_update","step_update":{
17
+ * "conversation_id":"…","step_index":1,"state":"DONE","step_type":"agent_response",
18
+ * "text_delta":"\n","duration_seconds":8.2,
19
+ * "usage":{"input_tokens":11707,"output_tokens":881,"thinking_tokens":864,
20
+ * "cache_read_tokens":0,"total_tokens":12588}}}
21
+ *
22
+ * {"event":"step_update","step_update":{
23
+ * "conversation_id":"…","step_index":2,"state":"ACTIVE","step_type":"tool",
24
+ * "tool_name":"run_command","tool_info":{"name":"run_command",
25
+ * "parameters":{"CommandLine":"echo hi"}}}}
26
+ * {"event":"step_update","step_update":{
27
+ * "conversation_id":"…","step_index":2,"state":"DONE","step_type":"tool",
28
+ * "tool_name":"run_command","duration_seconds":0.75,
29
+ * "tool_info":{"name":"run_command","parameters":{"CommandLine":"echo hi"},
30
+ * "output":"hi\r\n"}}}
31
+ *
32
+ * {"event":"result","result":{"conversation_id":"…","status":"SUCCESS",
33
+ * "response":"Source code turns to bytes,\nSyntax checked and optimized,\nSilicon wakes up.\n",
34
+ * "duration_seconds":…,"num_turns":…,"usage":{…}}}
35
+ * ```
36
+ *
37
+ * ## The four things this shapes
38
+ *
39
+ * 1. **`step_update` is the universal frame.** `step_type` says what the update
40
+ * is about — `user_input` (the echo of what we sent), `agent_response`
41
+ * (streamed answer text) or `tool` (an announced call, then its result) — and
42
+ * `state` says whether it is ACTIVE (in flight) or DONE (settled).
43
+ * 2. **Answer text streams.** `text_delta` arrives incrementally on ACTIVE
44
+ * frames, and `result.response` repeats the concatenation at the end. Both
45
+ * are read; the envelope is emitted ONLY when no delta ever arrived, so the
46
+ * answer cannot land twice.
47
+ * 3. **Tool calls need a synthesized id.** The protocol carries NO call id — a
48
+ * tool is identified by its `step_index` inside the conversation. dsh keys
49
+ * its pending-tool map by id and requires exactly one result per id, so the
50
+ * id is built as `<conversation_id>-tool-<step_index>`, which is unique
51
+ * because every driver run opens a fresh conversation (the driver never
52
+ * passes `--conversation`).
53
+ * 4. **A tool result carries no error flag.** `tool_info` has `name`,
54
+ * `parameters` and `output`; a failure is read from an `error` member when
55
+ * one appears and otherwise treated as a success, because inventing a
56
+ * failure would be worse than reporting a successful-but-empty one.
57
+ *
58
+ * Anything unrecognized is dropped, which is what lets a protocol that grows a
59
+ * new event keep working. The one rule that is NOT best-effort: a `result` whose
60
+ * status is not success is reported as a failure carrying the CLI's own words,
61
+ * because a failed run must never read as an empty answer.
62
+ *
63
+ * @module dsh-loop-engine-allinone/engine-agy/frames
64
+ */
65
+ import type { CliFrame } from '../driver-cli/frames.ts';
66
+ /** What the mapper learned about the run beyond its frames. */
67
+ export interface AgyRun {
68
+ /** The conversation id the CLI reported, when it reported one. */
69
+ conversationId: string | undefined;
70
+ /**
71
+ * Whether the streamed deltas already delivered the answer.
72
+ *
73
+ * The `result` envelope repeats the whole response, so this is what keeps the
74
+ * answer from being committed twice.
75
+ */
76
+ answered: boolean;
77
+ /** The last `agent_response` step index a segment was opened for. */
78
+ openStep: number | undefined;
79
+ }
80
+ /** Create a fresh run accumulator. */
81
+ export declare function newAgyRun(): AgyRun;
82
+ /**
83
+ * Map one parsed Antigravity document to frames.
84
+ * @param document - the parsed document.
85
+ * @param accept - frame sink.
86
+ * @param run - the run accumulator, updated in place.
87
+ * @returns the frames to accept — empty, because this mapper pushes directly.
88
+ */
89
+ export declare function mapAgyDocument(document: unknown, accept: (frame: CliFrame) => void, run: AgyRun): readonly CliFrame[];
90
+ //# sourceMappingURL=frames.d.ts.map
@@ -0,0 +1,64 @@
1
+ /**
2
+ * Antigravity loop engine module: drives every session it is handed through one
3
+ * `agy` stream-json child per dsh step, with the durable session log as the sole
4
+ * source of model context. The router routes a session here on the plugin's own
5
+ * engine record, else its agent preset; this module is a library, not a Cordis
6
+ * plugin entry.
7
+ *
8
+ * Authentication is entirely the CLI's: the plugin never reads, writes or
9
+ * refreshes Antigravity's Google credential — the child inherits the standard
10
+ * user environment and finds it itself, which is what makes a session run on the
11
+ * user's own subscription rather than on any credential this plugin holds.
12
+ *
13
+ * @module dsh-loop-engine-allinone/engine-agy
14
+ */
15
+ import type { Context } from '@deepseek-ai/cordis';
16
+ import z from '@deepseek-ai/schemastery';
17
+ import type { AgentOptions } from '@deepseek-ai/dsh-agent';
18
+ import type { Session, SessionId } from '@deepseek-ai/dsh-session';
19
+ import { CliEngineRuntime } from '../driver-cli/cli-loop.ts';
20
+ import { AgyAgent, type ResolvedAgyConfig } from './agent.ts';
21
+ import type { AgyEffort, AgyMode } from './process.ts';
22
+ /** Deployment-owned configuration for the Antigravity engine. */
23
+ export interface Config {
24
+ /** Model for the CLI (`--model`); Antigravity's own settings own the model when omitted. */
25
+ model?: string;
26
+ /** Explicit environment entries passed to the child. */
27
+ env?: Record<string, string>;
28
+ /** The `agy` executable; the CLI's own install location (and PATH) when not pinned. */
29
+ bin?: string;
30
+ /** The execution mode (`--mode`); omitted lets the CLI use its own default. */
31
+ mode?: AgyMode;
32
+ /** Reasoning effort (`--effort`). */
33
+ effort?: AgyEffort;
34
+ /** Pinned terminal-restriction flag, overriding the session's permission knobs. */
35
+ sandbox?: boolean;
36
+ /**
37
+ * Pinned auto-approve flag (`--dangerously-skip-permissions`), overriding the
38
+ * session's sandbox knob.
39
+ *
40
+ * Set this to `true` to give Antigravity the same room as
41
+ * `danger-full-access` without changing the session's own permission preset.
42
+ */
43
+ dangerouslySkipPermissions?: boolean;
44
+ }
45
+ /** Schema of the Antigravity engine configuration. */
46
+ export declare const Config: z<Config>;
47
+ /** Host-face ctx key this engine's runtime is registered under. */
48
+ export declare const AGY_ENGINE_LABEL = "agentLoopAgy";
49
+ declare module '@deepseek-ai/cordis' {
50
+ interface Context {
51
+ agentLoopAgy: AgyLoop;
52
+ }
53
+ }
54
+ /**
55
+ * Creation/resume machinery for the Antigravity engine. The process-wide
56
+ * AgentFactory slot belongs to the router, which delegates each session to the
57
+ * engine its preset names; this class is that engine's driver, not a plugin.
58
+ */
59
+ export declare class AgyLoop extends CliEngineRuntime<ResolvedAgyConfig, AgyAgent> {
60
+ constructor(ctx: Context, config: Config);
61
+ /** Construct the Antigravity driver for one prepared session. */
62
+ protected buildAgent(loopCtx: Context, id: SessionId, options: AgentOptions, session: Session): AgyAgent;
63
+ }
64
+ //# sourceMappingURL=loop.d.ts.map