@huynle/hub 0.9.2 → 0.10.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.
- package/CHANGELOG.md +320 -0
- package/Dockerfile +5 -1
- package/README.md +154 -77
- package/package.json +7 -4
- package/packages/claude-code/package.json +1 -1
- package/packages/cli/dist/hub-cli.js +534 -261
- package/packages/cli/package.json +1 -1
- package/packages/cli/src/cli.ts +36 -1
- package/packages/cli/src/subscriptions.ts +49 -0
- package/packages/codex/package.json +1 -1
- package/packages/codex/src/sessions.ts +10 -6
- package/packages/codex/src/spoke.ts +2 -1
- package/packages/node/package.json +1 -1
- package/packages/preset/package.json +1 -1
- package/packages/protocol/package.json +1 -1
- package/packages/protocol/schema/app-delivery/v1.schema.json +7 -5
- package/packages/protocol/schema/app-front/v1.schema.json +410 -0
- package/packages/protocol/src/app-front.ts +293 -0
- package/packages/protocol/src/concierge.ts +10 -1
- package/packages/protocol/src/context-cards.ts +59 -0
- package/packages/protocol/src/credentials.ts +39 -2
- package/packages/protocol/src/index.ts +81 -11
- package/packages/runtime-openshell/package.json +1 -1
- package/packages/runtime-sdk/package.json +1 -1
- package/packages/sdk/package.json +1 -1
- package/packages/sdk/src/app-front.ts +524 -0
- package/packages/sdk/src/client.ts +37 -4
- package/packages/sdk/src/envelope.ts +9 -2
- package/packages/sdk/src/errors.ts +1 -0
- package/packages/sdk/src/index.ts +1 -0
- package/packages/sdk/src/types.ts +39 -1
- package/packages/spoke-sdk/package.json +1 -1
- package/packages/spoke-sdk/src/delivery.ts +17 -1
- package/packages/spoke-sdk/src/harness-spoke.ts +4 -3
- package/packages/voice-client/README.md +146 -0
- package/packages/voice-client/src/vad/LICENSE +21 -0
- package/src/central/agent/acting-routes.ts +17 -3
- package/src/central/agent/acting.ts +12 -3
- package/src/central/agent/actor.ts +6 -1
- package/src/central/agent/app-decisions.ts +146 -0
- package/src/central/agent/app-tokens.ts +9 -3
- package/src/central/agent/audit.ts +3 -0
- package/src/central/agent/connect-routes.ts +64 -0
- package/src/central/agent/connect.ts +868 -0
- package/src/central/agent/conversation.ts +625 -0
- package/src/central/agent/decisions.ts +71 -6
- package/src/central/agent/delivery.ts +3 -0
- package/src/central/agent/directory.ts +5 -0
- package/src/central/agent/errors.ts +2 -0
- package/src/central/agent/grant-requests.ts +46 -9
- package/src/central/agent/grants.ts +13 -2
- package/src/central/agent/message-limits.ts +2 -2
- package/src/central/agent/message-routes.ts +13 -4
- package/src/central/agent/read-routes.ts +16 -2
- package/src/central/agent/routes.ts +108 -6
- package/src/central/agent/speech-routes.ts +316 -0
- package/src/central/agent/subscription-routes.ts +174 -0
- package/src/central/agent/subscriptions.ts +980 -0
- package/src/central/agent-data.ts +43 -1
- package/src/central/backend/memory-counters.ts +2 -2
- package/src/central/backend/types.ts +5 -2
- package/src/central/backend/valkey-counters.ts +5 -4
- package/src/central/client-address.ts +16 -0
- package/src/central/concierge/board-render.ts +52 -1
- package/src/central/concierge/board-routes.ts +25 -2
- package/src/central/concierge/board.ts +11 -1
- package/src/central/concierge/context.ts +29 -8
- package/src/central/concierge/grant-request.ts +216 -0
- package/src/central/concierge/prompt.ts +49 -2
- package/src/central/concierge/session-routes.ts +3 -0
- package/src/central/config.ts +64 -3
- package/src/central/context-cards/budget.ts +121 -0
- package/src/central/context-cards/changes.ts +29 -0
- package/src/central/context-cards/config.ts +145 -0
- package/src/central/context-cards/engine.ts +379 -0
- package/src/central/context-cards/inputs.ts +111 -0
- package/src/central/context-cards/pickup.ts +134 -0
- package/src/central/context-cards/registry.ts +89 -0
- package/src/central/context-cards/routes.ts +37 -0
- package/src/central/context-cards/service.ts +367 -0
- package/src/central/context-cards/store.ts +67 -0
- package/src/central/context-cards/types.ts +88 -0
- package/src/central/fetcher.ts +10 -2
- package/src/central/front-relays.ts +423 -0
- package/src/central/http.ts +547 -58
- package/src/central/human-activity.ts +453 -0
- package/src/central/llm/chat.ts +133 -0
- package/src/central/registry.ts +162 -9
- package/src/central/speech/service.ts +9 -0
- package/src/central/spoke-ws.ts +13 -0
- package/src/central/store.ts +9 -12
- package/src/config.ts +30 -13
- package/src/index.ts +45 -43
- package/src/rpc.ts +33 -4
- package/src/spoke/concierge-agent.ts +1 -1
- package/src/spoke/conversation.ts +6 -75
- package/src/spoke/deliver.ts +18 -8
- package/src/spoke/hub-rpc.ts +7 -2
- package/src/spoke/hub-tool-subscriptions.ts +82 -0
- package/src/spoke/hub-tool-title.ts +89 -0
- package/src/spoke/hub-tool.ts +56 -18
- package/src/spoke/session-context.ts +10 -2
- package/src/spoke/spoke.ts +227 -237
- package/src/spoke/summary.ts +36 -1
- package/src/spoke/taskboard.ts +5 -6
- package/src/spoke/voice-front.ts +323 -30
- package/src/spoke/who-teams.ts +51 -2
- package/src/tui-messaging.ts +24 -10
- package/src/tui.ts +6 -6
- package/web/dist/assets/{ArtifactPage-BKISN-Qj.js → ArtifactPage-CsPjam8D.js} +1 -1
- package/web/dist/assets/{ArtifactPane-CKOiAUNH.js → ArtifactPane-B9weO8L6.js} +1 -1
- package/web/dist/assets/ArtifactWorkbench-DzKhMs3l.js +6 -0
- package/web/dist/assets/{Diagram-vdpmp3xu.css → Diagram-7y8kg3og.css} +1 -1
- package/web/dist/assets/Diagram-CuRIffka.js +1 -0
- package/web/dist/assets/{Library-CcjZXsfF.js → Library-rv5DGtrm.js} +2 -2
- package/web/dist/assets/Lightbox-BlbivCkd.js +1 -0
- package/web/dist/assets/MediaImage-Ch3ryIdR.js +4 -0
- package/web/dist/assets/ProfilesDestination-DUuQ9jmd.js +1 -0
- package/web/dist/assets/{TeamsPage-CDyjrK-I.js → TeamsPage-D_17MkvN.js} +1 -1
- package/web/dist/assets/{Watchtower-DYwoUWME.js → Watchtower-DlrNOJ7X.js} +2 -2
- package/web/dist/assets/{artifacts-DU9uRgs1.js → artifacts-But87Jfo.js} +1 -1
- package/web/dist/assets/index-bX8B6NLo.js +33 -0
- package/web/dist/assets/index-rW6LKQj1.css +1 -0
- package/web/dist/assets/{live-ycZ_aQZO.js → live-BGLA-peO.js} +2 -2
- package/web/dist/assets/{pane-layout-0RrLHGDr.js → pane-layout-BW0RdX5a.js} +1 -1
- package/web/dist/assets/{renderer2d-BIwbgRoX.js → renderer2d-DyANQ1WS.js} +1 -1
- package/web/dist/assets/{renderer3d-C1a7eYGQ.js → renderer3d-vYYKFAJq.js} +1 -1
- package/web/dist/assets/{safe-area-DHhPy61Q.js → safe-area-B2Bk__FK.js} +1 -1
- package/web/dist/assets/{source-BWlvaODa.js → source-C-De8L3s.js} +1 -1
- package/web/dist/assets/toast-CXTwTvDw.js +9 -0
- package/web/dist/assets/vad-worklet-BfxJhrXy.js +27 -0
- package/web/dist/index.html +6 -6
- package/web/dist/assets/ArtifactWorkbench-d7R1o-rs.js +0 -6
- package/web/dist/assets/Diagram-azw2B_QH.js +0 -1
- package/web/dist/assets/Lightbox-Du56MXGX.js +0 -1
- package/web/dist/assets/MediaImage-Ds_JUx3a.js +0 -4
- package/web/dist/assets/ProfilesDestination-DdzbzmeK.js +0 -1
- package/web/dist/assets/index-C3ci5UtY.css +0 -1
- package/web/dist/assets/index-LNMZCqgE.js +0 -36
- package/web/dist/assets/toast-Cuu2K0hx.js +0 -1
- /package/{web/src/voice → packages/voice-client/src}/turn/LICENSE +0 -0
|
@@ -34,6 +34,7 @@ export * from "./hub-workspace.ts"
|
|
|
34
34
|
export * from "./concierge.ts"
|
|
35
35
|
export * from "./profiles.ts"
|
|
36
36
|
export * from "./artifacts.ts"
|
|
37
|
+
export * from "./context-cards.ts"
|
|
37
38
|
export * from "./embedded-media.ts"
|
|
38
39
|
export * from "./media.ts"
|
|
39
40
|
export * from "./media-allowlist.ts"
|
|
@@ -41,6 +42,7 @@ export * from "./preview-bundle.ts"
|
|
|
41
42
|
export * from "./teams.ts"
|
|
42
43
|
export * from "./graph.ts"
|
|
43
44
|
export * from "./voice-recording.ts"
|
|
45
|
+
export * from "./app-front.ts"
|
|
44
46
|
export { HUB_URL_MAX_CHARS, isHubURL, MAX_FRAME, MAX_RETRY_AFTER_MS }
|
|
45
47
|
|
|
46
48
|
export const PROTOCOL_VERSION = 1
|
|
@@ -84,7 +86,9 @@ export interface ModelSelection {
|
|
|
84
86
|
}
|
|
85
87
|
|
|
86
88
|
export interface SessionModelPrefs {
|
|
89
|
+
/** The voice front's model for this session. */
|
|
87
90
|
readonly voice?: ModelSelection
|
|
91
|
+
/** Obsolete (the removed voice agent's worker model): older hubs and spokes still send it; it is ignored. */
|
|
88
92
|
readonly worker?: ModelSelection
|
|
89
93
|
}
|
|
90
94
|
|
|
@@ -323,11 +327,16 @@ export const FORWARDED_EVENTS: ReadonlySet<string> = new Set([
|
|
|
323
327
|
export const INBOX_ORIGINS = ["user", "hub"] as const
|
|
324
328
|
export type InboxOrigin = (typeof INBOX_ORIGINS)[number]
|
|
325
329
|
|
|
326
|
-
/**
|
|
330
|
+
/**
|
|
331
|
+
* `session.inbox.delivered` data as forwarded. `origin` is optional: older spokes do not send it. `carried` (feature
|
|
332
|
+
* "inboxCarried"): a user item the hub carried itself (a console turn or steer, a Voice utterance, a launch's prompt),
|
|
333
|
+
* never a prompt typed in the terminal.
|
|
334
|
+
*/
|
|
327
335
|
export interface InboxDeliveredData {
|
|
328
336
|
readonly sessionID: string
|
|
329
337
|
readonly inboxID: string
|
|
330
338
|
readonly origin?: InboxOrigin
|
|
339
|
+
readonly carried?: true
|
|
331
340
|
}
|
|
332
341
|
|
|
333
342
|
/**
|
|
@@ -466,8 +475,15 @@ export const IMPLIED_OPENCODE_FEATURES = [
|
|
|
466
475
|
* carry media refs (user files' `ref`, tool and assistant rows' `media`).
|
|
467
476
|
* "previewBundle": it answers previewBundle (preview-bundle.ts): a local HTML page an assistant message names and the
|
|
468
477
|
* files it refers to, under the media path policy, paged under the frame limit.
|
|
478
|
+
* "conciergeFront" (voice front P2): it puts a voice front in front of a locked (Concierge) session when the hub asks
|
|
479
|
+
* with `front`, serves frontUpdate, and takes the session-context part "frontBoard" (the front's compact board).
|
|
480
|
+
* "inboxCarried": its session.inbox.delivered marks a user item the hub carried (`carried: true`), so every other
|
|
481
|
+
* user item is a prompt typed in the terminal. Spokes of harnesses that report the hub's prompts as origin "hub"
|
|
482
|
+
* need not announce it.
|
|
483
|
+
* "setModel": it sets the session's own model (setModel op) the way the harness keeps it for every later turn of
|
|
484
|
+
* that session (OpenCode: session.switchModel, stored on the session), whoever prompts it next.
|
|
469
485
|
*/
|
|
470
|
-
const OPTIONAL_SPOKE_FEATURES = [...IMPLIED_OPENCODE_FEATURES, "autoName", "sessionTokens", "deliver", "hubPrompt", "permissionMessage", "actTokens", "launch", "fork", "revert", "dismissError", "timelineMedia", PREVIEW_BUNDLE_FEATURE, "voiceFront"] as const
|
|
486
|
+
const OPTIONAL_SPOKE_FEATURES = [...IMPLIED_OPENCODE_FEATURES, "autoName", "sessionTokens", "deliver", "hubPrompt", "permissionMessage", "actTokens", "launch", "fork", "revert", "dismissError", "timelineMedia", PREVIEW_BUNDLE_FEATURE, "voiceFront", "conciergeFront", "inboxCarried", "setModel"] as const
|
|
471
487
|
|
|
472
488
|
/**
|
|
473
489
|
* The core ops. An OpenCode spoke serves them all without announcing them; a spoke of another harness announces
|
|
@@ -503,11 +519,12 @@ export const SPOKE_FEATURES: readonly SpokeFeature[] = [...OPTIONAL_SPOKE_FEATUR
|
|
|
503
519
|
* "pendingReplay": the hub takes a re-announced permission.asked / form.created (after a spoke reconnects) without
|
|
504
520
|
* notifying again, and honours `unlisted: true` on form.cancelled / permission.replied (only that process stops
|
|
505
521
|
* holding it). Spokes re-send permissions the hub was told already only to a hub that announces it.
|
|
522
|
+
* "frontRelay" (voice front P2): it serves the spoke request relayToSession (a Concierge front's relay_to_session).
|
|
506
523
|
*/
|
|
507
|
-
export const KNOWN_HUB_FEATURES = ["harness", "messaging", "nodes", "launches", "pendingReplay"] as const
|
|
524
|
+
export const KNOWN_HUB_FEATURES = ["harness", "messaging", "nodes", "launches", "pendingReplay", "frontRelay"] as const
|
|
508
525
|
export type HubFeature = (typeof KNOWN_HUB_FEATURES)[number]
|
|
509
526
|
/** What this hub announces ("launches": the /api/agent/launches routes). */
|
|
510
|
-
export const HUB_FEATURES: readonly HubFeature[] = ["harness", "messaging", "nodes", "launches", "pendingReplay"]
|
|
527
|
+
export const HUB_FEATURES: readonly HubFeature[] = ["harness", "messaging", "nodes", "launches", "pendingReplay", "frontRelay"]
|
|
511
528
|
|
|
512
529
|
/** A spoke's harness, version and evidence level; a hello without `harness` is an OpenCode native spoke. */
|
|
513
530
|
export function helloHarness(hello: Hello): { readonly harness: string; readonly harnessVersion: string; readonly evidence: EvidenceLevel | "unknown" } {
|
|
@@ -548,6 +565,21 @@ export type SpokeRequest =
|
|
|
548
565
|
/** A one-time sign-in link to a session's page, or to the home page without a session. */
|
|
549
566
|
/** `voice`: land on the session with Voice mode starting (`?voice=1`). */
|
|
550
567
|
| { readonly op: "openLink"; readonly sessionID?: string; readonly voice?: boolean }
|
|
568
|
+
/**
|
|
569
|
+
* (hub feature "frontRelay", voice front P2) A Concierge front's relay_to_session: the user's spoken request, as a
|
|
570
|
+
* message to `session` (@name or session ID), one of the user's own sessions. The hub checks the front, the
|
|
571
|
+
* utterance it answers and the target; a refusal is ok:false with the reason the front reads. The hub delivers the
|
|
572
|
+
* user's own words (its record of the utterance), never `text`: `text` is the front's short note, sent along only
|
|
573
|
+
* when every content word in it is one the user said. `previous` (a redirect, "no, the other one"): the user's
|
|
574
|
+
* utterance before this one goes first. `confirm` (guard tuning): one retry after the hub's soft refusal of a question
|
|
575
|
+
* with a work verb, for the same utterance and session.
|
|
576
|
+
*/
|
|
577
|
+
| { readonly op: "relayToSession"; readonly frontID: string; readonly session: string; readonly text: string; readonly previous?: boolean; readonly confirm?: boolean }
|
|
578
|
+
|
|
579
|
+
/** The longest relay text (as an utterance). */
|
|
580
|
+
export const RELAY_TEXT_MAX = 4000
|
|
581
|
+
/** The longest front update text. */
|
|
582
|
+
export const FRONT_UPDATE_MAX = 8000
|
|
551
583
|
|
|
552
584
|
// ---------- server → spoke ----------
|
|
553
585
|
|
|
@@ -659,18 +691,23 @@ export type ServerRequest =
|
|
|
659
691
|
/** One changed file's patch in the session's directory. */
|
|
660
692
|
| { readonly op: "diff"; readonly sessionID: string; readonly file: string }
|
|
661
693
|
/**
|
|
662
|
-
*
|
|
663
|
-
* "voiceFront", sent only to spokes that list it):
|
|
664
|
-
*
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
* `front` (feature "voiceFront"): put a hidden voice front in front of the session. `frontID`: the front the hub
|
|
668
|
-
* knows for it (a resend to a restarted spoke): re-linked if it still exists, instead of creating another.
|
|
694
|
+
* Conversation (Voice) mode on or off. The session's agent and model are never switched (older spokes switched it
|
|
695
|
+
* to a "voice" agent). `front` (feature "voiceFront", sent only to spokes that list it): put a hidden voice front in
|
|
696
|
+
* front of the session (docs/plans/2026-11-06-voice-front-p1-contract.md); without it, or when no front can be made,
|
|
697
|
+
* the hub talks to the session itself and its turns are voice-styled. `frontID`: the front the hub knows for it (a
|
|
698
|
+
* resend to a restarted spoke): re-linked if it still exists, instead of creating another.
|
|
669
699
|
*/
|
|
670
700
|
| { readonly op: "conversation"; readonly sessionID: string; readonly on: boolean; readonly front?: boolean; readonly frontID?: string }
|
|
671
701
|
| { readonly op: "models"; readonly sessionID: string }
|
|
672
702
|
| { readonly op: "modelPrefs"; readonly sessionID: string }
|
|
703
|
+
/** `worker` is obsolete: older hubs send it, current spokes ignore it. */
|
|
673
704
|
| { readonly op: "setModelPrefs"; readonly sessionID: string; readonly voice?: ModelSelection | null; readonly worker?: ModelSelection | null }
|
|
705
|
+
/**
|
|
706
|
+
* (feature "setModel") Set the session's own model: every later turn of the session runs on it, whoever prompts it
|
|
707
|
+
* (the console, the terminal, a voice relay). One of the session's catalog models (models op); no variant: the
|
|
708
|
+
* model's default. The Voice model (setModelPrefs) is separate and never changes it.
|
|
709
|
+
*/
|
|
710
|
+
| { readonly op: "setModel"; readonly sessionID: string; readonly model: ModelSelection }
|
|
674
711
|
| { readonly op: "timeline"; readonly sessionID: string; readonly limit?: number; readonly cursor?: string; readonly order?: "asc" | "desc"; readonly before?: string }
|
|
675
712
|
| { readonly op: "timelinePart"; readonly sessionID: string; readonly messageID: string; readonly partID: string }
|
|
676
713
|
/** One image attached to a user message (its position in the message's files). */
|
|
@@ -750,6 +787,11 @@ export type ServerRequest =
|
|
|
750
787
|
| { readonly op: "removeFront"; readonly sessionID: string }
|
|
751
788
|
/** Forget the session's last run failure: the user dismissed it (feature "dismissError"). */
|
|
752
789
|
| { readonly op: "dismissError"; readonly sessionID: string }
|
|
790
|
+
/**
|
|
791
|
+
* (feature "conciergeFront", voice front P2) An update for the voice front of `sessionID` (the Concierge session)
|
|
792
|
+
* about a session it relayed to: queued as its next wake. `finished`: a successful turn end.
|
|
793
|
+
*/
|
|
794
|
+
| { readonly op: "frontUpdate"; readonly sessionID: string; readonly text: string; readonly finished?: boolean }
|
|
753
795
|
|
|
754
796
|
/**
|
|
755
797
|
* The feature a spoke must serve (spokeFeatures) for the hub to send `op`: the op itself for a core op (CORE_OPS,
|
|
@@ -765,6 +807,8 @@ export function featureForOp(op: ServerRequest["op"]): SpokeFeature {
|
|
|
765
807
|
return "revert"
|
|
766
808
|
case "removeFront":
|
|
767
809
|
return "voiceFront"
|
|
810
|
+
case "frontUpdate":
|
|
811
|
+
return "conciergeFront"
|
|
768
812
|
default:
|
|
769
813
|
return op
|
|
770
814
|
}
|
|
@@ -831,10 +875,23 @@ export interface FilePatch extends ChangedFile {
|
|
|
831
875
|
}
|
|
832
876
|
|
|
833
877
|
/** Right-rail data for a session; each part is absent when OpenCode could not provide it. */
|
|
878
|
+
/**
|
|
879
|
+
* The model a session runs on, as its spoke knows it (the console's model chip). Voice never changes it: the voice
|
|
880
|
+
* front is a separate session. `name` from the model catalog; `variant` only when explicit. `source`: `chosen`, the
|
|
881
|
+
* model selected for the session; `reply`, nothing selected, the model its latest reply ran on (the default resolved);
|
|
882
|
+
* `default`, nothing selected and no reply yet, the default model.
|
|
883
|
+
*/
|
|
884
|
+
export interface SessionModel extends ModelSelection {
|
|
885
|
+
readonly name?: string
|
|
886
|
+
readonly source: "chosen" | "reply" | "default"
|
|
887
|
+
}
|
|
888
|
+
|
|
834
889
|
export interface SessionSummary {
|
|
835
890
|
readonly directory: string
|
|
836
891
|
readonly branch?: string
|
|
837
892
|
readonly context?: ContextUsage
|
|
893
|
+
/** The model the session runs on (absent when nothing is known, or from older spokes). */
|
|
894
|
+
readonly model?: SessionModel
|
|
838
895
|
readonly mcp?: readonly McpStatus[]
|
|
839
896
|
readonly changes?: SessionChanges
|
|
840
897
|
}
|
|
@@ -871,6 +928,8 @@ export interface ResultFor {
|
|
|
871
928
|
models: { readonly models: readonly AvailableModel[] }
|
|
872
929
|
modelPrefs: { readonly prefs: SessionModelPrefs; readonly defaults: SessionModelPrefs }
|
|
873
930
|
setModelPrefs: { readonly prefs: SessionModelPrefs; readonly defaults: SessionModelPrefs }
|
|
931
|
+
/** `model`: the session's model now (source "chosen"). */
|
|
932
|
+
setModel: { readonly model: SessionModel }
|
|
874
933
|
timeline: TimelinePage
|
|
875
934
|
timelinePart: { readonly detail: unknown }
|
|
876
935
|
/** No `file` when the message has no image at that index; `tooLarge` when its bytes would not fit in a frame. */
|
|
@@ -896,6 +955,10 @@ export interface ResultFor {
|
|
|
896
955
|
/** `dismissed`: the spoke had a failure of the session to forget. */
|
|
897
956
|
dismissError: { readonly dismissed: boolean }
|
|
898
957
|
removeFront: { readonly removed: boolean }
|
|
958
|
+
/** `queued`: false when the session has no linked front in this process. */
|
|
959
|
+
frontUpdate: { readonly queued: boolean }
|
|
960
|
+
/** The session the relay reached, its title, and how: steered into its running turn, or a new turn. */
|
|
961
|
+
relayToSession: { readonly sessionID: string; readonly title?: string; readonly mode: "steer" | "turn" }
|
|
899
962
|
}
|
|
900
963
|
|
|
901
964
|
// ---------- both directions ----------
|
|
@@ -1120,6 +1183,9 @@ function isSpokeRequest(v: unknown): v is SpokeRequest {
|
|
|
1120
1183
|
if (v.op === "pairCode") return true
|
|
1121
1184
|
if (v.op === "handoff") return nonEmpty(v.sessionID)
|
|
1122
1185
|
if (v.op === "openLink") return (v.sessionID === undefined || nonEmpty(v.sessionID)) && (v.voice === undefined || typeof v.voice === "boolean")
|
|
1186
|
+
if (v.op === "relayToSession") {
|
|
1187
|
+
return nonEmpty(v.frontID) && v.frontID.length <= 300 && nonEmpty(v.session) && v.session.length <= 300 && str(v.text) && v.text.trim().length > 0 && v.text.length <= RELAY_TEXT_MAX && (v.previous === undefined || typeof v.previous === "boolean") && (v.confirm === undefined || typeof v.confirm === "boolean")
|
|
1188
|
+
}
|
|
1123
1189
|
return false
|
|
1124
1190
|
}
|
|
1125
1191
|
|
|
@@ -1212,6 +1278,8 @@ function isServerRequest(v: unknown): v is ServerRequest {
|
|
|
1212
1278
|
(v.worker === undefined || v.worker === null || isModelSelection(v.worker)) &&
|
|
1213
1279
|
(v.voice !== undefined || v.worker !== undefined)
|
|
1214
1280
|
)
|
|
1281
|
+
case "setModel":
|
|
1282
|
+
return nonEmpty(v.sessionID) && isModelSelection(v.model)
|
|
1215
1283
|
case "timeline":
|
|
1216
1284
|
return (
|
|
1217
1285
|
nonEmpty(v.sessionID) &&
|
|
@@ -1272,6 +1340,8 @@ function isServerRequest(v: unknown): v is ServerRequest {
|
|
|
1272
1340
|
case "dismissError":
|
|
1273
1341
|
case "removeFront":
|
|
1274
1342
|
return nonEmpty(v.sessionID)
|
|
1343
|
+
case "frontUpdate":
|
|
1344
|
+
return nonEmpty(v.sessionID) && str(v.text) && v.text.trim().length > 0 && v.text.length <= FRONT_UPDATE_MAX && (v.finished === undefined || typeof v.finished === "boolean")
|
|
1275
1345
|
default:
|
|
1276
1346
|
return false
|
|
1277
1347
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@huynle/hub-runtime-openshell",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.10.1",
|
|
4
4
|
"private": true,
|
|
5
5
|
"description": "The `openshell` runtime of `hub node`: launches in NVIDIA OpenShell sandboxes, driven through the openshell CLI (internal; shipped inside @huynle/hub, not published on its own).",
|
|
6
6
|
"license": "MIT",
|