@kasenri/dsh-orbit 0.5.4 → 0.5.5

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/lib/activation.js CHANGED
@@ -1,15 +1,13 @@
1
1
  /**
2
- * Deterministic `/agent-orbit` activation.
2
+ * Deterministic Orbit activation.
3
3
  *
4
- * Two routes converge on the same tiny pre-step directive:
5
- * - a closed-namespace DSH host command for surfaces with command adjudication
6
- * (the Web GUI slash menu), and
7
- * - a strict genuine-user-message gesture boundary for headless/CLI surfaces
8
- * without one.
9
- *
10
- * Neither route creates an execution entry of its own: the directive only
11
- * states that activation is explicit, and the existing `orbit_controller`
12
- * tool + `OrbitService` + Supervisor remain the sole Orbit runtime.
4
+ * - `/agent-orbit` (host command or genuine-message gesture) keeps its explicit
5
+ * directive; the existing `orbit_controller` tool + `OrbitService` remain the
6
+ * runtime.
7
+ * - A Session whose toggle is ON hands every ordinary user message straight to
8
+ * `OrbitService`: the pre-step boundary consumes the turn (no parent model
9
+ * call, no parent mutation) and the host starts or resumes the run. The model
10
+ * never decides whether Orbit runs.
13
11
  */
14
12
  import { createUserMessage } from '@deepseek-ai/dsh-llm';
15
13
  import { ORBIT_TOGGLE_COMMAND, parseOrbitToggle } from "./session-state.js";
@@ -70,17 +68,6 @@ export function buildOrbitActivationDirective(goal) {
70
68
  : `Goal: ${goal}`);
71
69
  return lines.join('\n');
72
70
  }
73
- /**
74
- * The directive for a Session whose toggle is ON: an ordinary user message
75
- * becomes the Orbit goal without changing the activation machinery.
76
- */
77
- export function buildOrbitSessionDirective(goal) {
78
- return [
79
- 'Orbit is enabled for this chat, so treat this ordinary user message as the requested goal. Start or resume Orbit through the existing orbit_controller tool; do not ask the user to confirm the mode.',
80
- 'Use the message as the goal, without summarizing or rewriting it.',
81
- `Goal: ${goal}`,
82
- ].join('\n');
83
- }
84
71
  /**
85
72
  * Register the closed-namespace `/agent-orbit` host command.
86
73
  *
@@ -135,15 +122,13 @@ export function registerOrbitToggleCommand(ctx) {
135
122
  }), 'dsh-orbit: /orbit-toggle host command');
136
123
  }
137
124
  /**
138
- * Install the gesture boundary. It runs for every proposed step and injects
139
- * the activation directive once, for the step that carries the genuine user
140
- * message. The in-step guard keeps a step that already holds an Orbit
141
- * directive from gaining a second one, without any durable state.
125
+ * Install the gesture boundary. It runs for every proposed step.
142
126
  *
143
127
  * An explicit `/agent-orbit` always wins and always activates, whatever the
144
- * Session toggle says. Only when no explicit activation is present does the
145
- * Session toggle (when the composition provides it) promote an ordinary user
146
- * message into an Orbit goal.
128
+ * Session toggle says: it keeps the existing activation directive and the
129
+ * `orbit_controller` tool. Otherwise, an enabled Session hands the ordinary
130
+ * user message to Orbit directly — the step is consumed with no model call and
131
+ * the message stays in the conversation as durable history.
147
132
  */
148
133
  export function installOrbitGestureBoundary(ctx, options = {}) {
149
134
  ctx.on('agent/pre-step', async ({ agent, messages, signal }, next) => {
@@ -153,25 +138,31 @@ export function installOrbitGestureBoundary(ctx, options = {}) {
153
138
  if (decision.messages.some((message) => message.source.kind === 'orbit-command'))
154
139
  return decision;
155
140
  const explicit = invokedOrbitActivation(messages);
156
- const implicit = explicit === undefined && options.sessionEnabled?.(agent.session) === true
157
- ? invokedOrbitMessage(messages)
158
- : undefined;
159
- if (explicit === undefined && implicit === undefined)
141
+ if (explicit !== undefined) {
142
+ signal.throwIfAborted();
143
+ return {
144
+ kind: 'enter',
145
+ messages: [
146
+ ...decision.messages,
147
+ createUserMessage({
148
+ content: [{ type: 'text', text: buildOrbitActivationDirective(explicit.goal) }],
149
+ source: { kind: 'orbit-command', ...(explicit.goal === '' ? {} : { goal: explicit.goal }) },
150
+ }),
151
+ ],
152
+ };
153
+ }
154
+ if (options.sessionEnabled?.(agent.session) !== true)
155
+ return decision;
156
+ const ordinary = invokedOrbitMessage(messages);
157
+ const activate = options.activate;
158
+ if (ordinary === undefined || activate === undefined)
160
159
  return decision;
161
160
  signal.throwIfAborted();
162
- const activation = explicit ?? implicit ?? { goal: '' };
163
- const directive = explicit === undefined
164
- ? buildOrbitSessionDirective(activation.goal)
165
- : buildOrbitActivationDirective(activation.goal);
166
- return {
167
- kind: 'enter',
168
- messages: [
169
- ...decision.messages,
170
- createUserMessage({
171
- content: [{ type: 'text', text: directive }],
172
- source: { kind: 'orbit-command', ...(activation.goal === '' ? {} : { goal: activation.goal }) },
173
- }),
174
- ],
175
- };
161
+ // The claimed batch enters the conversation exactly once: the loop commits
162
+ // `decision.messages`, which this path leaves empty.
163
+ for (const message of messages)
164
+ agent.session.append('user/message', message, { surfaceOp: 'append' });
165
+ await activate(agent, ordinary.goal, signal);
166
+ return { kind: 'enter', messages: [] };
176
167
  });
177
168
  }
package/lib/client.js CHANGED
@@ -133,21 +133,21 @@ window.__ModuleLoader__.load({
133
133
  }
134
134
  var OrbitModelSelect_module_css_default = {
135
135
  "check": "f77nca_check",
136
- "back": "f77nca_back",
136
+ "switchControl": "f77nca_switchControl",
137
137
  "switchRow": "f77nca_switchRow",
138
- "hint": "f77nca_hint",
139
138
  "rowDetail": "f77nca_rowDetail",
140
- "group": "f77nca_group",
141
- "switchControl": "f77nca_switchControl",
142
- "rowValue": "f77nca_rowValue",
143
- "chevron": "f77nca_chevron",
144
139
  "title": "f77nca_title",
145
- "error": "f77nca_error",
146
- "rowLabel": "f77nca_rowLabel",
147
- "separator": "f77nca_separator",
148
140
  "panel": "f77nca_panel",
149
141
  "row": "f77nca_row",
150
- "rowValueActive": "f77nca_rowValueActive"
142
+ "rowLabel": "f77nca_rowLabel",
143
+ "group": "f77nca_group",
144
+ "error": "f77nca_error",
145
+ "rowValueActive": "f77nca_rowValueActive",
146
+ "separator": "f77nca_separator",
147
+ "chevron": "f77nca_chevron",
148
+ "rowValue": "f77nca_rowValue",
149
+ "back": "f77nca_back",
150
+ "hint": "f77nca_hint"
151
151
  };
152
152
  //#endregion
153
153
  //#region client/OrbitModelSelect.tsx
package/lib/index.js CHANGED
@@ -1,10 +1,18 @@
1
1
  import z from '@deepseek-ai/schemastery';
2
2
  import { installOrbitGestureBoundary, registerOrbitCommand, registerOrbitToggleCommand } from "./activation.js";
3
+ import { estimateLoopCount } from "./kernel.js";
3
4
  import { createOrbitPreExecuteHandler } from "./pipeline-guard.js";
4
5
  import { resolveEffectiveRoutes, sessionSelectionOf } from "./routes.js";
5
6
  import { installOrbitSessionProjection, orbitEnabledOf } from "./session-state.js";
6
7
  import { OrbitService } from "./service.js";
7
8
  import { createOrbitTool } from "./tool.js";
9
+ /**
10
+ * Minimum loop budget for a hard-activated run. The Commander is asked for a
11
+ * 2-5 step plan and every executed step consumes one loop slot, so the host
12
+ * must grant a budget that can finish a full plan; the goal complexity
13
+ * estimate raises it further when the goal asks for more.
14
+ */
15
+ const HARD_ACTIVATION_MIN_LOOPS = 5;
8
16
  export const name = 'dsh-orbit';
9
17
  export const inject = ['tools', 'agents', 'subagents'];
10
18
  const Route = z.object({
@@ -117,6 +125,21 @@ export function apply(ctx, config) {
117
125
  });
118
126
  installOrbitGestureBoundary(ctx, {
119
127
  sessionEnabled: (session) => orbitEnabledOf(ctx, session),
128
+ activate: async (agent, goal, signal) => {
129
+ const cwd = agent.session.header.cwd ?? process.cwd();
130
+ try {
131
+ // The initiator scope makes the run's children belong to this Agent;
132
+ // the parent model is never asked to decide or to run the task.
133
+ await ctx.agents.withInitiator(agent, () => service.run({
134
+ goal,
135
+ approved_loop_count: Math.max(estimateLoopCount(goal), HARD_ACTIVATION_MIN_LOOPS),
136
+ }, cwd, signal));
137
+ }
138
+ catch {
139
+ // Durable run state owns failure reporting; a takeover failure must
140
+ // not fail the consumed parent turn.
141
+ }
142
+ },
120
143
  });
121
144
  }
122
145
  // Per-Session Orbit enable state: natively durable through the Session log
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kasenri/dsh-orbit",
3
- "version": "0.5.4",
3
+ "version": "0.5.5",
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",