@lotics/app-sdk 0.61.0 → 0.61.1

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.
@@ -104,8 +104,6 @@ export interface PendingChoice {
104
104
  toolCallId: string;
105
105
  questions: ChoiceQuestion[];
106
106
  }
107
- /** The run's pending `ask_user_choice`, parsed for rendering (a `ClarifyWizard`
108
- * maps 1:1) — non-null exactly while the run is parked awaiting the answer. */
109
107
  export declare function pendingInteractiveCall(state: AgentRunState): PendingChoice | null;
110
108
  /**
111
109
  * Fold the user's picks into the tool's output shape — `answers` aligns to
@@ -66,6 +66,15 @@ export function adoptSettledRun(state, settled) {
66
66
  }
67
67
  /** The run's pending `ask_user_choice`, parsed for rendering (a `ClarifyWizard`
68
68
  * maps 1:1) — non-null exactly while the run is parked awaiting the answer. */
69
+ /** Untrusted model output — a non-JSON string is data, not an exception. */
70
+ function decodeJson(raw) {
71
+ try {
72
+ return JSON.parse(raw);
73
+ }
74
+ catch {
75
+ return null;
76
+ }
77
+ }
69
78
  export function pendingInteractiveCall(state) {
70
79
  if (state.status !== "awaiting_input")
71
80
  return null;
@@ -81,9 +90,16 @@ export function pendingInteractiveCall(state) {
81
90
  return null;
82
91
  }
83
92
  function parseChoiceQuestions(input) {
84
- if (!input || typeof input !== "object")
93
+ // A model may hand the tool its arguments as a JSON STRING rather than an
94
+ // object. The SERVER accepts either and parks the run, so refusing the string
95
+ // here strands a live `awaiting_input` run: the question exists, the run is
96
+ // answerable, and the UI reports it as unrecoverable. Parse before validating
97
+ // — a string that isn't JSON falls through to the same empty result as any
98
+ // other malformed input, which `adoptGuarded` surfaces loudly and retryably.
99
+ const decoded = typeof input === "string" ? decodeJson(input) : input;
100
+ if (!decoded || typeof decoded !== "object")
85
101
  return [];
86
- const record = input;
102
+ const record = decoded;
87
103
  if (!Array.isArray(record.questions))
88
104
  return [];
89
105
  const questions = [];
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@lotics/app-sdk",
3
- "version": "0.61.0",
4
- "description": "Runtime SDK for Lotics custom-code apps \u2014 typed hooks, postMessage bridge, mount entry point",
3
+ "version": "0.61.1",
4
+ "description": "Runtime SDK for Lotics custom-code apps typed hooks, postMessage bridge, mount entry point",
5
5
  "type": "module",
6
6
  "exports": {
7
7
  ".": {