@sjhmars/happy-bridge 0.3.5 → 0.3.7

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/client.js CHANGED
@@ -17,21 +17,21 @@ window.__ModuleLoader__.load({
17
17
  document.head.appendChild(tag);
18
18
  }
19
19
  var HappyBridgeCard_module_css_default = {
20
- "error": "l9rBEq_error",
21
- "status": "l9rBEq_status",
22
- "header": "l9rBEq_header",
23
- "row": "l9rBEq_row",
24
- "card": "l9rBEq_card",
25
- "label": "l9rBEq_label",
26
- "button": "l9rBEq_button",
27
20
  "headText": "l9rBEq_headText",
28
21
  "name": "l9rBEq_name",
29
- "chevron": "l9rBEq_chevron",
30
- "checkbox": "l9rBEq_checkbox",
31
- "body": "l9rBEq_body",
22
+ "card": "l9rBEq_card",
23
+ "status": "l9rBEq_status",
24
+ "description": "l9rBEq_description",
25
+ "header": "l9rBEq_header",
26
+ "error": "l9rBEq_error",
32
27
  "select": "l9rBEq_select",
28
+ "button": "l9rBEq_button",
33
29
  "qr": "l9rBEq_qr",
34
- "description": "l9rBEq_description"
30
+ "body": "l9rBEq_body",
31
+ "checkbox": "l9rBEq_checkbox",
32
+ "label": "l9rBEq_label",
33
+ "row": "l9rBEq_row",
34
+ "chevron": "l9rBEq_chevron"
35
35
  };
36
36
  //#endregion
37
37
  //#region src/client/HappyBridgeCard.tsx
package/lib/index.js CHANGED
@@ -303,11 +303,12 @@ async function buildSessionMetadata(ctx, source, machineId, title, selection, _g
303
303
  resume: false,
304
304
  rpcMethods: [
305
305
  "permission",
306
+ "communication",
306
307
  "killSession",
307
308
  "abort"
308
309
  ],
309
310
  shell: false,
310
- steering: false
311
+ steering: true
311
312
  },
312
313
  currentOperatingModeCode: currentPreset === "custom" ? operatingModes[0]?.code ?? "workspace-write" : currentPreset,
313
314
  ...selected === void 0 ? {} : {
@@ -3787,11 +3788,13 @@ var HappyBridge = class {
3787
3788
  const model = messageModelCode(meta);
3788
3789
  const effort = messageEffort(meta);
3789
3790
  const permissionMode = meta.permissionMode;
3790
- const publishedModel = this.lastPublished.get(agent.id)?.model;
3791
- if (model !== void 0 && publishedModel !== void 0 && sameCatalogPick({ model: publishedModel }, { model })) {} else if (model !== void 0) {
3791
+ const published = this.lastPublished.get(agent.id);
3792
+ const modelIsEcho = model !== void 0 && published?.model !== void 0 && sameCatalogPick({ model: published.model }, { model });
3793
+ const effortIsEcho = effort !== void 0 && published?.effort != null && effort === published.effort;
3794
+ if (model !== void 0 && !modelIsEcho) {
3792
3795
  if (!grantAtLeast(this.config.remoteGrant, "full")) link.socket.sendText("service", "改模型需要远程档「完整」,这条消息仍会发出。");
3793
3796
  else this.applyModel(agent, model, typeof effort === "string" ? effort : effort === null ? null : void 0);
3794
- } else if (effort === null || typeof effort === "string") {
3797
+ } else if ((effort === null || typeof effort === "string") && !effortIsEcho) {
3795
3798
  if (!grantAtLeast(this.config.remoteGrant, "full")) link.socket.sendText("service", "改思考强度需要远程档「完整」,这条消息仍会发出。");
3796
3799
  else if (effort === null) {
3797
3800
  const current = this.currentModel(agent);
@@ -3953,6 +3956,9 @@ var HappyBridge = class {
3953
3956
  * Queue the phone text as a user followup. The App already shows the typed
3954
3957
  * bubble; do not send a second user envelope. Images ride as DSH
3955
3958
  * attachments; other files land under `happy-inbox` for Harness `read`.
3959
+ * A turn that is still running gets the text as steering (`agent.steer`),
3960
+ * matching the `steering: true` capability we advertise — otherwise the
3961
+ * App unlocks the composer only to have the message wait a whole turn.
3956
3962
  */
3957
3963
  async followup(link, agent, text, files) {
3958
3964
  const blocks = [];
@@ -3977,10 +3983,12 @@ var HappyBridge = class {
3977
3983
  if (blocks.length === 0) return;
3978
3984
  link.skipNextUser += 1;
3979
3985
  link.agent = agent;
3980
- agent.followup(createUserMessage({
3986
+ const message = createUserMessage({
3981
3987
  content: blocks,
3982
3988
  source: { kind: "user" }
3983
- }));
3989
+ });
3990
+ if (agent.status === "running" && link.pendingHuman === void 0) agent.steer(message);
3991
+ else agent.followup(message);
3984
3992
  }
3985
3993
  /**
3986
3994
  * Claim every download started before this text, wait, keep the successes.
@@ -188,6 +188,9 @@ export declare class HappyBridge {
188
188
  * Queue the phone text as a user followup. The App already shows the typed
189
189
  * bubble; do not send a second user envelope. Images ride as DSH
190
190
  * attachments; other files land under `happy-inbox` for Harness `read`.
191
+ * A turn that is still running gets the text as steering (`agent.steer`),
192
+ * matching the `steering: true` capability we advertise — otherwise the
193
+ * App unlocks the composer only to have the message wait a whole turn.
191
194
  */
192
195
  private followup;
193
196
  /**
@@ -92,7 +92,8 @@ export interface SessionMetadata {
92
92
  resume: false;
93
93
  rpcMethods: string[];
94
94
  shell: false;
95
- steering: false;
95
+ /** True: mid-turn phone text steers the running turn (`agent.steer`). */
96
+ steering: boolean;
96
97
  };
97
98
  tools?: string[];
98
99
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sjhmars/happy-bridge",
3
- "version": "0.3.5",
3
+ "version": "0.3.7",
4
4
  "description": "Remote-control bridge: pair a running dsh web/desktop client with the Happy mobile app by QR code, then remote-control the same harness sessions from the phone (send messages, read replies, approve tool calls, switch models)",
5
5
  "keywords": [
6
6
  "deepseek-harness",