@kasenri/dsh-orbit 0.5.8 → 0.5.9

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.md CHANGED
@@ -104,6 +104,9 @@ Orbit supports three activation styles:
104
104
 
105
105
  All three routes converge on the existing `orbit_controller` tool and
106
106
  `OrbitService`; the activation layer never starts a run of its own.
107
+ After a hard-activated run reaches `SUCCESS`, the initiating Session displays
108
+ the Final Commander's user-visible result directly, with the Commander's frozen
109
+ provider/model provenance. The parent model and parent tools remain bypassed.
107
110
 
108
111
  ## Model configuration (Web)
109
112
 
package/lib/activation.js CHANGED
@@ -116,7 +116,8 @@ export function registerOrbitToggleCommand(ctx) {
116
116
  * call while the message stays in the conversation as durable history.
117
117
  */
118
118
  export function installOrbitGestureBoundary(ctx, options = {}) {
119
- ctx.on('agent/pre-step', async ({ agent, messages, signal }, next) => {
119
+ ctx.on('agent/pre-step', async (payload, next) => {
120
+ const { agent, messages, signal } = payload;
120
121
  const decision = await next();
121
122
  if (decision.kind === 'reject')
122
123
  return decision;
@@ -134,7 +135,7 @@ export function installOrbitGestureBoundary(ctx, options = {}) {
134
135
  // `decision.messages`, which this path leaves empty.
135
136
  for (const message of messages)
136
137
  agent.session.append('user/message', message, { surfaceOp: 'append' });
137
- await activate(agent, goal, signal);
138
+ await activate(agent, goal, { turn: payload.turn, step: payload.step }, signal);
138
139
  return { kind: 'enter', messages: [] };
139
140
  });
140
141
  }
package/lib/client.js CHANGED
@@ -94,22 +94,22 @@ window.__ModuleLoader__.load({
94
94
  document.head.appendChild(tag);
95
95
  }
96
96
  var OrbitModelSelect_module_css_default = {
97
- "hint": "f77nca_hint",
98
- "rowValueActive": "f77nca_rowValueActive",
99
- "rowValue": "f77nca_rowValue",
97
+ "title": "f77nca_title",
98
+ "panel": "f77nca_panel",
100
99
  "switchControl": "f77nca_switchControl",
100
+ "error": "f77nca_error",
101
101
  "rowDetail": "f77nca_rowDetail",
102
- "rowLabel": "f77nca_rowLabel",
103
- "switchRow": "f77nca_switchRow",
104
- "separator": "f77nca_separator",
105
102
  "chevron": "f77nca_chevron",
106
- "row": "f77nca_row",
107
103
  "group": "f77nca_group",
108
- "error": "f77nca_error",
104
+ "row": "f77nca_row",
105
+ "switchRow": "f77nca_switchRow",
106
+ "hint": "f77nca_hint",
107
+ "rowValueActive": "f77nca_rowValueActive",
108
+ "rowValue": "f77nca_rowValue",
109
+ "rowLabel": "f77nca_rowLabel",
109
110
  "check": "f77nca_check",
110
- "title": "f77nca_title",
111
- "back": "f77nca_back",
112
- "panel": "f77nca_panel"
111
+ "separator": "f77nca_separator",
112
+ "back": "f77nca_back"
113
113
  };
114
114
  //#endregion
115
115
  //#region client/OrbitModelSelect.tsx
package/lib/dsh-host.js CHANGED
@@ -13,6 +13,9 @@ function contentToText(blocks) {
13
13
  .map((block) => (block.type === 'text' ? block.text : `[${block.type}]`))
14
14
  .join('\n');
15
15
  }
16
+ function visibleContentToText(blocks) {
17
+ return blocks?.flatMap((block) => block.type === 'text' && block.text.trim() !== '' ? [block.text] : []).join('\n') ?? '';
18
+ }
16
19
  /**
17
20
  * Wire the Orbit supervisor to DeepSeek Harness native Agent/Subagent services.
18
21
  *
@@ -81,6 +84,7 @@ export class DshOrbitHost {
81
84
  .then((value) => ({
82
85
  childId: run.id,
83
86
  output: contentToText(value.output),
87
+ visibleOutput: visibleContentToText(value.output),
84
88
  interrupted: value.stopReason !== 'completed',
85
89
  ...(value.stopReason !== 'completed' ? { reason: value.stopReason } : {}),
86
90
  ...(value.diagnostic ? { testSummary: [value.diagnostic] } : {}),
package/lib/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { boundContextSummary, createUserMessage } from '@deepseek-ai/dsh-llm';
1
+ import { AssistantStreamAccumulator, boundContextSummary, createAssistantMessage, createUserMessage } from '@deepseek-ai/dsh-llm';
2
2
  import z from '@deepseek-ai/schemastery';
3
3
  import { installOrbitGestureBoundary, registerOrbitCommand, registerOrbitToggleCommand } from "./activation.js";
4
4
  import { createOrbitPreExecuteHandler } from "./pipeline-guard.js";
@@ -120,7 +120,7 @@ export function apply(ctx, config) {
120
120
  });
121
121
  installOrbitGestureBoundary(ctx, {
122
122
  sessionEnabled: (session) => orbitEnabledOf(ctx, session),
123
- activate: async (agent, goal, signal) => {
123
+ activate: async (agent, goal, position, signal) => {
124
124
  const cwd = agent.session.header.cwd ?? process.cwd();
125
125
  let result;
126
126
  try {
@@ -135,6 +135,10 @@ export function apply(ctx, config) {
135
135
  appendOrbitNotice(agent.session, `Orbit 启动失败:${error instanceof Error ? error.message : String(error)}`);
136
136
  return;
137
137
  }
138
+ if (result.ok && result.phase === 'SUCCESS' && result.final_output !== undefined) {
139
+ appendOrbitFinalOutput(agent.session, position, result.final_output);
140
+ return;
141
+ }
138
142
  const notice = activationNotice(result);
139
143
  if (notice !== undefined)
140
144
  appendOrbitNotice(agent.session, notice);
@@ -168,6 +172,26 @@ export function apply(ctx, config) {
168
172
  ctx.on('tools/pre-execute', (exec, next) => handler(exec, next));
169
173
  }
170
174
  }
175
+ /** Append the existing Final Commander answer as this consumed turn's sole assistant result. */
176
+ function appendOrbitFinalOutput(session, position, output) {
177
+ const message = createAssistantMessage({
178
+ content: [{ type: 'text', text: output.text }],
179
+ source: { provider: output.provider, model: output.model },
180
+ });
181
+ const stream = new AssistantStreamAccumulator();
182
+ const time = Date.now();
183
+ stream.push({ time, chunk: { type: 'block-start', index: 0, blockType: 'text' } });
184
+ stream.push({ time, chunk: { type: 'text-delta', index: 0, text: output.text } });
185
+ stream.push({ time, chunk: { type: 'block-end', index: 0, block: { type: 'text', text: output.text } } });
186
+ stream.push({ time, chunk: { type: 'finish', reason: { kind: 'stop' } } });
187
+ session.append('step/start', position);
188
+ try {
189
+ session.append('assistant/message', { ...position, message, stream: [...stream.snapshot()] }, { surfaceOp: 'append' });
190
+ }
191
+ finally {
192
+ session.append('step/end', position);
193
+ }
194
+ }
171
195
  /**
172
196
  * One durable, user-visible Orbit notice. The DSH `plugin` + `form: 'notice'`
173
197
  * source renders as a collapsed notice row instead of a user message, and the
package/lib/supervisor.js CHANGED
@@ -328,7 +328,7 @@ export class OrbitSupervisor {
328
328
  return { kind: 'interrupted', reason: outcome.reason };
329
329
  try {
330
330
  const decision = assertCommanderDecision(outcome.structured, mode);
331
- return { kind: 'decision', decision };
331
+ return { kind: 'decision', decision, output: outcome.output };
332
332
  }
333
333
  catch (error) {
334
334
  // Invalid/temporary output is recoverable; it must not become NEEDS_USER.
@@ -387,7 +387,7 @@ export class OrbitSupervisor {
387
387
  if (raced.value.structured === undefined) {
388
388
  return { kind: 'interrupted', reason: `${mode}_STRUCTURED_OUTPUT_MISSING` };
389
389
  }
390
- return { kind: 'output', output: raced.value.output, structured: raced.value.structured };
390
+ return { kind: 'output', output: raced.value.visibleOutput ?? raced.value.output, structured: raced.value.structured };
391
391
  }
392
392
  if (raced.kind === 'aborted' || signal?.aborted) {
393
393
  await this.cancelHandle(handle, 'ORBIT_ABORTED');
@@ -586,7 +586,7 @@ export class OrbitSupervisor {
586
586
  if (decision.decision === 'SUCCESS') {
587
587
  applyFinalSuccess(state, decision.summary);
588
588
  this.store.writeState(state);
589
- return this.result(state, true);
589
+ return this.result(state, true, undefined, outcome.output);
590
590
  }
591
591
  if (decision.decision === 'PASS_CURRENT_STEP') {
592
592
  applyStepPass(state, step, decision.summary);
@@ -873,7 +873,7 @@ export class OrbitSupervisor {
873
873
  return { ok: false, action: 'status', message: 'ORBIT_RUN_NOT_FOUND: 没有 Run 状态。' };
874
874
  return this.result(state, true);
875
875
  }
876
- result(state, ok, message) {
876
+ result(state, ok, message, finalOutput) {
877
877
  // Tool output must be lossless JSON: optional state fields are omitted, not
878
878
  // emitted as `undefined`.
879
879
  const data = {
@@ -896,6 +896,7 @@ export class OrbitSupervisor {
896
896
  driver_ownership: state.driver_ownership,
897
897
  state_revision: state.state_revision,
898
898
  };
899
+ const displayText = state.phase === 'SUCCESS' ? finalOutput?.trim() || state.commander?.summary?.trim() : undefined;
899
900
  return {
900
901
  ok,
901
902
  action: 'run',
@@ -903,6 +904,13 @@ export class OrbitSupervisor {
903
904
  phase: state.phase,
904
905
  status: state.status,
905
906
  ...(message ? { message } : {}),
907
+ ...(displayText ? {
908
+ final_output: {
909
+ text: displayText,
910
+ provider: state.routes.commander.provider,
911
+ model: state.routes.commander.model,
912
+ },
913
+ } : {}),
906
914
  data: Object.fromEntries(Object.entries(data).filter(([, value]) => value !== undefined)),
907
915
  };
908
916
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kasenri/dsh-orbit",
3
- "version": "0.5.8",
3
+ "version": "0.5.9",
4
4
  "type": "module",
5
5
  "description": "Deterministic engineering orchestration for DeepSeek Harness with Commander, Executor, Smart Watchdog, bounded recovery and durable execution state.",
6
6
  "license": "MIT",