@frockbot/client-core 0.3.1 → 0.3.3

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 (2) hide show
  1. package/package.json +5 -5
  2. package/src/index.ts +38 -4
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@frockbot/client-core",
3
- "version": "0.3.1",
3
+ "version": "0.3.3",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "exports": {
@@ -13,10 +13,10 @@
13
13
  "typecheck": "tsc --noEmit -p tsconfig.json"
14
14
  },
15
15
  "dependencies": {
16
- "@frockbot/configuration-core": "0.3.1",
17
- "@frockbot/connection-core": "0.3.1",
18
- "@frockbot/kernel-contracts": "0.3.1",
19
- "@frockbot/protocol": "0.3.1",
16
+ "@frockbot/configuration-core": "0.3.3",
17
+ "@frockbot/connection-core": "0.3.3",
18
+ "@frockbot/kernel-contracts": "0.3.3",
19
+ "@frockbot/protocol": "0.3.3",
20
20
  "vue": "3.5.41"
21
21
  },
22
22
  "devDependencies": {
package/src/index.ts CHANGED
@@ -23,6 +23,7 @@ import {
23
23
  defineComponent,
24
24
  Fragment,
25
25
  h,
26
+ shallowReactive,
26
27
  type App,
27
28
  type Component,
28
29
  type ComputedRef,
@@ -32,7 +33,7 @@ import {
32
33
 
33
34
  export interface ClientTurnEvent {
34
35
  type: string;
35
- call?: { id: string; name: string };
36
+ call?: { id: string; name: string; input?: unknown };
36
37
  callId?: string;
37
38
  content?: string;
38
39
  isError?: boolean;
@@ -121,11 +122,18 @@ export interface ClientRun {
121
122
  | "completed"
122
123
  | "failed"
123
124
  | "cancelled"
125
+ | "superseded"
124
126
  | "reconciliation-required";
125
127
  responseText?: string;
126
128
  failure?: string;
127
129
  /** Durable Stop intent, projected independently of the run status. */
128
130
  stopRequestedAt?: string;
131
+ /**
132
+ * True while the Turn is admitted and waiting rather than running: the User
133
+ * sent it while the Bot was still on the previous one. The thread draws it
134
+ * as an ordinary message it has not reached yet.
135
+ */
136
+ queued?: true;
129
137
  recovery?: { action: "resume"; message: string };
130
138
  }
131
139
 
@@ -142,6 +150,12 @@ export interface AgentTransport {
142
150
  * transport that has no composer — a Routine's, a test's — needs no change.
143
151
  */
144
152
  skills?: readonly SkillRefV1[],
153
+ /**
154
+ * The Turn this message replaces, when the User sent it while one was
155
+ * running. Absent means the ordinary case, where a second command in
156
+ * flight is still refused.
157
+ */
158
+ supersedes?: { runId?: string },
145
159
  ): Promise<ClientTurnResponse>;
146
160
  /**
147
161
  * The Bot's invocable Skills, for the composer's `/` and `@` popover.
@@ -250,12 +264,16 @@ function decodeTurnEvent(value: unknown): ClientTurnEvent {
250
264
  decoded.call = {
251
265
  id: responseString(event, "occurrenceId", "turn event"),
252
266
  name: responseString(event, "name", "turn event"),
267
+ ...(event.name === "call_dynamic_tool" ? { input: event.input } : {}),
253
268
  };
254
269
  } else if (event.call !== undefined) {
255
270
  const call = responseRecord(event.call, "tool call");
256
271
  decoded.call = {
257
272
  id: responseString(call, "id", "tool call"),
258
273
  name: responseString(call, "name", "tool call"),
274
+ ...(call.name === "call_dynamic_tool" && Object.hasOwn(call, "input")
275
+ ? { input: call.input }
276
+ : {}),
259
277
  };
260
278
  }
261
279
  if (event.type === "tool/result" && event.occurrenceId !== undefined) {
@@ -376,6 +394,12 @@ export interface ClientSlotRegistration {
376
394
  slot: string;
377
395
  order: number;
378
396
  component: Component;
397
+ /**
398
+ * A stable key for one filler, so a slot whose fillers come from data —
399
+ * a Package's declared entries, say — keeps each filler's element across a
400
+ * re-render instead of reusing the one that happens to share its order.
401
+ */
402
+ key?: string;
379
403
  }
380
404
 
381
405
  export interface ClientSurfaceRegistration {
@@ -428,7 +452,15 @@ function disposeResult(result: ClientPluginResult): void {
428
452
  }
429
453
 
430
454
  export class ClientApplication {
431
- private readonly registrations: ClientSlotRegistration[] = [];
455
+ /*
456
+ * Reactive, because a slot filler is not always known at install time: a
457
+ * Package's declarative entries arrive with the Bot's Composition and are
458
+ * registered and disposed as it changes. A plain array would leave the
459
+ * sidebar showing the entries of whichever Bot was selected first.
460
+ */
461
+ private readonly registrations: ClientSlotRegistration[] = shallowReactive(
462
+ [],
463
+ );
432
464
  private readonly providers: ProviderRegistration[] = [];
433
465
  private readonly pluginDisposers: (() => void)[] = [];
434
466
  private app: App | undefined;
@@ -464,9 +496,11 @@ export class ClientApplication {
464
496
  setup: (props: { name: string }) => () =>
465
497
  h(
466
498
  Fragment,
467
- this.slots(props.name).map((registration) =>
499
+ this.slots(props.name).map((registration, index) =>
468
500
  h(registration.component, {
469
- key: `${props.name}:${registration.order}`,
501
+ key:
502
+ registration.key ??
503
+ `${props.name}:${registration.order}:${index}`,
470
504
  }),
471
505
  ),
472
506
  ),