@sigrun/sigrun 0.1.6 → 0.2.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.
Files changed (137) hide show
  1. package/CHANGELOG.md +192 -0
  2. package/README.md +445 -42
  3. package/dist/blocks/build-stamp.json +13 -0
  4. package/dist/blocks/builders.d.ts +57 -0
  5. package/dist/blocks/images.d.ts +26 -0
  6. package/dist/blocks/index.d.ts +20 -0
  7. package/dist/blocks/limits.d.ts +25 -0
  8. package/dist/blocks/placements.d.ts +26 -0
  9. package/dist/blocks/schema.d.ts +38 -0
  10. package/dist/blocks/schema.js +9 -2
  11. package/dist/blocks/validate.d.ts +73 -0
  12. package/dist/blocks/validate.js +57 -8
  13. package/dist/cli.js +26 -2
  14. package/dist/config.js +67 -1
  15. package/dist/extension.d.ts +230 -22
  16. package/dist/harness/ambient.js +39 -185
  17. package/dist/harness/blocks/entries.js +47 -0
  18. package/dist/harness/blocks/state.js +58 -0
  19. package/dist/harness/blocks/tools.js +274 -0
  20. package/dist/harness/boot.js +259 -20
  21. package/dist/harness/builtins.js +15 -11
  22. package/dist/harness/event-bus.js +105 -10
  23. package/dist/harness/identity/accounts.js +186 -0
  24. package/dist/harness/identity/groups.js +14 -0
  25. package/dist/harness/identity/index.js +13 -6
  26. package/dist/harness/identity/json-store.js +15 -4
  27. package/dist/harness/identity/setup-code-check.js +9 -0
  28. package/dist/harness/identity/tokens.js +28 -5
  29. package/dist/harness/identity/users.js +111 -12
  30. package/dist/harness/interactions.js +292 -136
  31. package/dist/harness/loader.js +271 -17
  32. package/dist/harness/packages.js +1 -1
  33. package/dist/harness/reserved-sections.js +21 -0
  34. package/dist/harness/seam-host.js +92 -6
  35. package/dist/harness/sections/context-files.js +1 -1
  36. package/dist/harness/settings.js +63 -2
  37. package/dist/harness/stores.js +241 -4
  38. package/dist/harness/user-services.js +391 -0
  39. package/dist/harness/user-tools.js +187 -0
  40. package/dist/harness/workspace.js +61 -57
  41. package/dist/jobs/fire.js +10 -16
  42. package/dist/sandbox/availability.js +211 -0
  43. package/dist/sandbox/command-observer.js +59 -0
  44. package/dist/sandbox/grants.js +159 -0
  45. package/dist/sandbox/helper.js +29 -0
  46. package/dist/sandbox/isolation.js +29 -0
  47. package/dist/sandbox/launch.js +31 -0
  48. package/dist/sandbox/os-account.js +49 -0
  49. package/dist/sandbox/policy.js +274 -0
  50. package/dist/sandbox/pool.js +548 -0
  51. package/dist/sandbox/protocol.js +167 -0
  52. package/dist/sandbox/sandboxed-env.js +245 -0
  53. package/dist/sandbox/unavailable-env.js +49 -0
  54. package/dist/sandbox/worker.js +261 -0
  55. package/dist/serve.js +213 -25
  56. package/dist/server/auth/access-principal.js +16 -0
  57. package/dist/server/auth/pipeline.js +99 -36
  58. package/dist/server/blocks/answers.js +94 -0
  59. package/dist/server/blocks/chat-surfaces.js +393 -0
  60. package/dist/server/blocks/notes.js +216 -0
  61. package/dist/server/blocks/summaries.js +328 -0
  62. package/dist/server/commands.js +5 -0
  63. package/dist/server/content-parts-lazy.js +13 -0
  64. package/dist/server/conversation-handler.js +2 -5
  65. package/dist/server/conversation-ops.js +138 -37
  66. package/dist/server/helpers.js +18 -6
  67. package/dist/server/host-bridge.js +40 -20
  68. package/dist/server/images/cache.js +213 -0
  69. package/dist/server/images/convert.js +13 -0
  70. package/dist/server/images/fetch.js +302 -0
  71. package/dist/server/images/ranges.js +42 -0
  72. package/dist/server/images/rewrite.js +94 -0
  73. package/dist/server/images/sign.js +84 -0
  74. package/dist/server/images/sniff.js +62 -0
  75. package/dist/server/index.js +152 -4
  76. package/dist/server/login/flows.js +126 -0
  77. package/dist/server/login/http.js +31 -0
  78. package/dist/server/login/resolve.js +133 -0
  79. package/dist/server/login/setup-claim.js +55 -0
  80. package/dist/server/login/usernames.js +15 -0
  81. package/dist/server/notifications.js +21 -4
  82. package/dist/server/ownership.js +13 -0
  83. package/dist/server/routes/admin.js +58 -0
  84. package/dist/server/routes/auth.js +88 -2
  85. package/dist/server/routes/conversations.js +3 -6
  86. package/dist/server/routes/events.js +28 -3
  87. package/dist/server/routes/extensions.js +37 -5
  88. package/dist/server/routes/images.js +274 -0
  89. package/dist/server/routes/interactions.js +57 -68
  90. package/dist/server/routes/jobs.js +2 -8
  91. package/dist/server/routes/login.js +223 -0
  92. package/dist/server/routes/me.js +90 -0
  93. package/dist/server/routes/meta.js +19 -0
  94. package/dist/server/routes/onboarding.js +94 -84
  95. package/dist/server/routes/settings-sections.js +190 -0
  96. package/dist/server/routes/settings.js +16 -4
  97. package/dist/server/routes/submissions.js +1 -1
  98. package/dist/server/routes/surfaces.js +175 -23
  99. package/dist/server/routes/users.js +116 -20
  100. package/dist/server/schema-fixture.js +213 -0
  101. package/dist/server/session-meta.js +3 -0
  102. package/dist/server/shutdown.js +11 -4
  103. package/dist/server/static.js +18 -0
  104. package/dist/server/surfaces/dedup.js +9 -2
  105. package/dist/server/surfaces/service.js +181 -13
  106. package/dist/server/surfaces/settings-surfaces.js +597 -0
  107. package/dist/server/turns/submit-turn.js +26 -0
  108. package/dist/server/views.js +16 -0
  109. package/dist/settings/core-sections.js +532 -0
  110. package/dist/settings/pending.js +181 -0
  111. package/dist/settings/registry.js +453 -0
  112. package/dist/skills/index.js +6 -0
  113. package/node_modules/@sigrun/shared/CHANGELOG.md +11 -0
  114. package/node_modules/@sigrun/shared/dist/access.d.ts +4 -2
  115. package/node_modules/@sigrun/shared/dist/access.js +11 -4
  116. package/node_modules/@sigrun/shared/dist/ambient.d.ts +17 -74
  117. package/node_modules/@sigrun/shared/dist/ambient.js +8 -6
  118. package/node_modules/@sigrun/shared/dist/blocks/text.js +16 -2
  119. package/node_modules/@sigrun/shared/dist/blocks/transport.d.ts +4 -0
  120. package/node_modules/@sigrun/shared/dist/blocks/types.d.ts +21 -4
  121. package/node_modules/@sigrun/shared/dist/interactions.d.ts +22 -48
  122. package/node_modules/@sigrun/shared/dist/interactions.js +9 -7
  123. package/node_modules/@sigrun/shared/dist/settings.d.ts +27 -2
  124. package/node_modules/@sigrun/shared/dist/themes.d.ts +2 -3
  125. package/node_modules/@sigrun/shared/dist/themes.js +2 -3
  126. package/node_modules/@sigrun/shared/dist/turns.d.ts +14 -0
  127. package/node_modules/@sigrun/shared/dist/turns.js +53 -3
  128. package/node_modules/@sigrun/shared/dist/views.d.ts +202 -12
  129. package/node_modules/@sigrun/shared/dist/views.js +16 -0
  130. package/node_modules/@sigrun/shared/package.json +1 -1
  131. package/package.json +13 -9
  132. package/webui/dist/assets/index-SO2W4jjk.js +55 -0
  133. package/webui/dist/assets/index-yqkL6BSS.css +1 -0
  134. package/webui/dist/index.html +2 -2
  135. package/CONTEXT.md +0 -163
  136. package/webui/dist/assets/index-CiYInlLx.css +0 -1
  137. package/webui/dist/assets/index-JDfOQV9z.js +0 -52
@@ -37,8 +37,8 @@
37
37
  import type { JsonObject } from "./json.js";
38
38
  import type { Sharing } from "./access.js";
39
39
  import type { JobWire } from "./jobs.js";
40
- import type { InteractionAnswer, InteractionBody, InteractionDiff, InteractionField, InteractionOption, InteractionRecord, InteractionStatus } from "./interactions.js";
41
- import type { AmbientBody, AmbientGauge, AmbientLedgerEntry, AmbientLine, AmbientMetrics, AmbientRecord, AmbientRow } from "./ambient.js";
40
+ import type { InteractionAnswer, InteractionRecord, InteractionStatus } from "./interactions.js";
41
+ import type { AmbientRecord } from "./ambient.js";
42
42
  import type { EffectiveServerSetting, SettingsFile } from "./settings.js";
43
43
  /** A model reference as served on the wire (pi-durable `ModelRef`). */
44
44
  export interface ModelRefWire {
@@ -345,8 +345,7 @@ export type AmbientWire = AmbientRecord;
345
345
  export interface AmbientList {
346
346
  readonly ambient: readonly AmbientWire[];
347
347
  }
348
- export type { InteractionAnswer, InteractionBody, InteractionDiff, InteractionField, InteractionOption, InteractionStatus, };
349
- export type { AmbientBody, AmbientGauge, AmbientLedgerEntry, AmbientLine, AmbientMetrics, AmbientRow, };
348
+ export type { InteractionAnswer, InteractionStatus, };
350
349
  /**
351
350
  * The `GET/PATCH /v1/settings` payload (Task 8b): the settings file's
352
351
  * effective contents — the `HarnessSettings` pass-throughs plus the
@@ -362,6 +361,23 @@ export type { AmbientBody, AmbientGauge, AmbientLedgerEntry, AmbientLine, Ambien
362
361
  export interface SettingsResponse extends SettingsFile {
363
362
  /** The live registry snapshot's composed tool names, deduplicated. */
364
363
  readonly toolRoster: readonly string[];
364
+ /**
365
+ * The restart keys whose stored value differs from the boot snapshot
366
+ * (UI-blocks U4, spec §13.2): the pending-restart callout's key list.
367
+ * Computed per request over the fresh file read; `[]` when nothing
368
+ * waits for a restart. NOT a settable key: the store's validation
369
+ * rejects it on PATCH (400 `invalid_field`), and the wire patch type
370
+ * Omits it.
371
+ */
372
+ readonly pendingRestart: readonly string[];
373
+ /**
374
+ * The write's own classification (§13.1) — present ONLY on a PATCH
375
+ * response: which touched keys applied live vs. which are pending a
376
+ * restart. NOT a settable key; absent on GET.
377
+ */
378
+ readonly applied?: readonly string[];
379
+ /** The restart-pending companion of {@link applied}. PATCH responses only. */
380
+ readonly pending?: readonly string[];
365
381
  /**
366
382
  * The resolved server section per flattened dotted key
367
383
  * (`"server.port"`, `"server.compaction.reserveTokens"`, …), each
@@ -387,11 +403,38 @@ export type WorkerStatus = {
387
403
  readonly lastError?: string;
388
404
  };
389
405
  /** The `GET /v1/meta` payload (spec §5; the health block is Task 9e). */
406
+ /**
407
+ * The measured listener facts (release-readiness Task 1, serving spec §2):
408
+ * captured ONCE when the listener goes live (never probed per request) and
409
+ * retained on the server context; `GET /v1/meta` projects them verbatim.
410
+ */
411
+ export interface ListenerInfo {
412
+ /** The effective host string supplied to `listen` — never a resolved peer. */
413
+ readonly host: string;
414
+ /** The configured/selected port the listener bound. */
415
+ readonly port: number;
416
+ /**
417
+ * The address families the listener accepts, in stable `ipv4`, `ipv6`
418
+ * order. Literal binds report the bound socket's family; the `::`
419
+ * wildcard reports exactly the loopback families a startup reachability
420
+ * check connected on (measured, never inferred from the wildcard
421
+ * spelling). Empty on a server that never listened (a hand-built test
422
+ * server projecting intent only).
423
+ */
424
+ readonly families: readonly ("ipv4" | "ipv6")[];
425
+ }
390
426
  export interface MetaResponse {
391
427
  /** The sigrun server's own version (the package manifest). */
392
428
  readonly version: string;
393
429
  readonly harnessVersion: string;
394
430
  readonly schemaVersion: string;
431
+ /**
432
+ * The listener facts (release-readiness Task 1, serving spec §2). A
433
+ * REQUIRED field on this type; OLDER SERVERS (≤0.2.0) omit it on the
434
+ * wire, so clients consuming it must tolerate its absence during
435
+ * mixed-version upgrades.
436
+ */
437
+ readonly listener: ListenerInfo;
395
438
  readonly extensions: readonly {
396
439
  readonly name: string;
397
440
  readonly status: string;
@@ -472,6 +515,25 @@ export interface MetaResponse {
472
515
  * U4 — a boot constant, like the rest of meta.
473
516
  */
474
517
  readonly dev: boolean;
518
+ /** The boot-time execution-jail decision (multi-user M1). */
519
+ readonly isolation: {
520
+ readonly mode: "auto" | "always" | "off";
521
+ /** Whether enforcement is active; filled by the later enforcement task. */
522
+ readonly active: boolean;
523
+ readonly available: boolean;
524
+ readonly abi: number;
525
+ readonly reason?: string;
526
+ readonly osUsers: "available" | "off" | string;
527
+ };
528
+ /**
529
+ * The supervised flag (UI-blocks U4 Task 2, spec §13.3): `true` when
530
+ * the deployment guarantees the process is restarted after an
531
+ * intentional `exit 0` (the Helm chart and docker compose set
532
+ * `SIGRUN_SUPERVISED=1`; a bare `docker run` does not). The §13.2
533
+ * pendingRestart callout renders its Restart button only for a
534
+ * supervised admin; otherwise it says "Restart sigrun to apply".
535
+ */
536
+ readonly supervised: boolean;
475
537
  /**
476
538
  * The seam inventory (docs/approval-ux-seams.md): per extension, the
477
539
  * interaction kinds / ambient surface keys its factory declared.
@@ -584,6 +646,13 @@ export interface AuthCheckResponse {
584
646
  * every served entry, empty when the extension declared none). The
585
647
  * webui's Extensions settings section renders this list.
586
648
  */
649
+ export interface ServiceStatusWire {
650
+ readonly slug: string;
651
+ readonly name: string;
652
+ readonly user: string;
653
+ readonly state: "running" | "idle" | "failed";
654
+ readonly lastError?: string;
655
+ }
587
656
  export interface ExtensionInfo {
588
657
  readonly name: string;
589
658
  readonly status: string;
@@ -597,6 +666,8 @@ export interface ExtensionInfo {
597
666
  readonly workers: readonly WorkerStatus[];
598
667
  /** The declared HTTP routes, one `{method, path, auth}` each (W5 Task 2). */
599
668
  routes?: readonly ExtensionRouteInfo[];
669
+ /** Per-user service states; admin-only inventory. */
670
+ readonly services: readonly ServiceStatusWire[];
600
671
  /** The declared surfaces, one `{id, title, icon, placement}` each (U3 Task 1); absent when none. */
601
672
  surfaces?: readonly ExtensionSurfaceInfo[];
602
673
  /**
@@ -616,7 +687,7 @@ export interface ExtensionInfo {
616
687
  readonly inert?: "no gateway";
617
688
  /**
618
689
  * Built-in extensions (Task 2, pi parity): `true` marks a core-shipped
619
- * built-in (codemode / MCP / tool search); ABSENT on configured
690
+ * built-in (codemode / MCP / tool search / OAuth); ABSENT on configured
620
691
  * extensions. A replaced built-in reports its row with `builtin: true`
621
692
  * and `replacedBy` (its status is the skip, never `"ok"`); a disabled
622
693
  * built-in is absent from the list entirely.
@@ -656,6 +727,52 @@ export interface ExtensionSurfaceInfo {
656
727
  export interface ExtensionsResponse {
657
728
  readonly extensions: readonly ExtensionInfo[];
658
729
  }
730
+ /**
731
+ * The `GET /v1/settings/sections` payload (UI-blocks U4 Task 4, spec
732
+ * §13.4): the settings panel's nav list + the search index. Core's
733
+ * sections come first (slug `core`), then the loaded extensions'
734
+ * sections ordered by slug. The index covers every searchable row —
735
+ * a section title, a core settings key, an extension section's field —
736
+ * with the section id a hit jumps to.
737
+ */
738
+ export interface SettingsSectionsResponse {
739
+ readonly sections: readonly SettingsSectionEntry[];
740
+ readonly index: readonly SettingsSectionIndexEntry[];
741
+ }
742
+ /** One nav entry: the section's mount (slug + id) and its display. */
743
+ export interface SettingsSectionEntry {
744
+ readonly slug: string;
745
+ readonly id: string;
746
+ readonly title: string;
747
+ readonly icon: string;
748
+ /** Personal sections group under My settings and store caller-owned data. */
749
+ readonly scope?: "user";
750
+ /** Explicit admin gate (user sections are otherwise non-admin by default). */
751
+ readonly admin?: boolean;
752
+ }
753
+ /** One search-index row (the label search's hit shape, spec §13.4). */
754
+ export interface SettingsSectionIndexEntry {
755
+ /** The section the hit belongs to (the nav target). */
756
+ readonly slug: string;
757
+ readonly sectionId: string;
758
+ /** The row kind: a core settings key, an extension form field, or a section title. */
759
+ readonly kind: "core-key" | "field" | "section";
760
+ /** The searchable text (the field/section label). */
761
+ readonly label: string;
762
+ /** The field's help string, when it declares one. */
763
+ readonly help?: string;
764
+ /** The core key path / the field's form name, when the row has one. */
765
+ readonly key?: string;
766
+ }
767
+ /**
768
+ * The settings search's filter (UI-blocks U4 Task 4 round-2): the ONE
769
+ * implementation both channels run — the webui panel and the TUI view
770
+ * previously carried byte-identical copies, which drifted apart once
771
+ * (the TUI's lacked the key match). Case-insensitive over label + help
772
+ * + key; an empty query filters to nothing (the picker carries the
773
+ * full list).
774
+ */
775
+ export declare function filterSettingsIndex(index: readonly SettingsSectionIndexEntry[], query: string): readonly SettingsSectionIndexEntry[];
659
776
  /**
660
777
  * A `GET /v1/extensions/:slug/secrets` entry: the key and its winning
661
778
  * source — NEVER the value (the API lists and writes secrets; it never
@@ -669,6 +786,18 @@ export interface ExtensionSecret {
669
786
  export interface ExtensionSecretsResponse {
670
787
  readonly secrets: readonly ExtensionSecret[];
671
788
  }
789
+ /**
790
+ * The `GET`/`PUT /v1/extensions/:slug/settings` payload (UI-blocks U4,
791
+ * spec §13.2): the stored object verbatim under `settings`, plus the
792
+ * pending-restart slot. Extension-declared fields default to LIVE
793
+ * (§13.1), so `pendingRestart` is `[]` today; the field exists so the
794
+ * §13.4 callout renders from one shape across core and extension
795
+ * settings.
796
+ */
797
+ export interface ExtensionSettingsResponse {
798
+ readonly settings: Record<string, unknown>;
799
+ readonly pendingRestart: readonly string[];
800
+ }
672
801
  export type { CommandsResponse, CommandRunResponse, SlashCommand } from "./commands.js";
673
802
  export type { SessionMeta, SessionMetaPatch } from "./session-meta.js";
674
803
  /**
@@ -685,9 +814,16 @@ export interface WhoamiResponse {
685
814
  readonly user?: string;
686
815
  readonly name?: string;
687
816
  readonly email?: string;
817
+ /** The caller's own workspace/grants; never another directory user's. */
818
+ readonly workspace?: string;
819
+ readonly grants?: readonly {
820
+ readonly path: string;
821
+ readonly access: "ro" | "rw";
822
+ }[];
688
823
  readonly admin: boolean;
689
824
  readonly service: boolean;
690
- readonly method: "none" | "token" | "proxy" | "host";
825
+ readonly method: "none" | "token" | "session" | "proxy" | "host";
826
+ readonly provider?: string;
691
827
  }
692
828
  /**
693
829
  * The `GET /v1/onboarding` payload (core hardening W1 Task 4, spec
@@ -712,20 +848,29 @@ export interface OnboardingState {
712
848
  * admin-visible material and the routes that serve this type are
713
849
  * admin-gated. `createdAt` is epoch ms.
714
850
  *
715
- * `admin` is the STORED flag (the users-admin UI toggles it); the proxy
716
- * group grant rides separately as `groupAdmin` (gateway C8): effective
717
- * admin is `admin || groupAdmin === true`, and the last-admin guard
718
- * counts `admin` alone.
851
+ * `admin` is the STORED flag (the users-admin UI toggles it); `groups`
852
+ * is the deduplicated union of stored source memberships. `groupAdmin`
853
+ * is DERIVED from those groups and `server.auth.adminGroups`, retained
854
+ * for one release for the users UI; the last-admin guard counts `admin`
855
+ * alone.
719
856
  */
720
857
  export interface UserWire {
721
858
  readonly user: string;
722
859
  readonly name?: string;
723
860
  readonly email?: string;
724
861
  readonly admin: boolean;
725
- /** The persisted proxy-group grant — present only under `adminGroups`. */
862
+ /** DERIVED from stored groups and configured adminGroups; never persisted. */
726
863
  readonly groupAdmin?: boolean;
864
+ /** The deduplicated union of groups stored by authenticating sources. */
865
+ readonly groups?: readonly string[];
866
+ readonly workspace?: string;
867
+ readonly grants?: readonly {
868
+ readonly path: string;
869
+ readonly access: "ro" | "rw";
870
+ }[];
871
+ readonly osUser?: string;
727
872
  readonly createdAt: number;
728
- readonly source: "proxy" | "invite" | "cli";
873
+ readonly source: "proxy" | "invite" | "cli" | "login";
729
874
  }
730
875
  /** The `POST /v1/onboarding/claim` payload (Task 4): the user (plus the
731
876
  * minted token when `issueToken` was requested — shown once, never
@@ -751,6 +896,8 @@ export interface TokenWire {
751
896
  readonly name: string;
752
897
  readonly user: string;
753
898
  readonly createdAt: number;
899
+ readonly kind?: "api" | "session";
900
+ readonly expiresAt?: number;
754
901
  }
755
902
  /** The `POST /v1/auth/tokens` payload (Task 4): the secret once, the
756
903
  * digest-free record alongside it. */
@@ -758,6 +905,29 @@ export interface TokenCreateResponse {
758
905
  readonly token: string;
759
906
  readonly record: TokenWire;
760
907
  }
908
+ /**
909
+ * One external identity linked to a directory user (multi-user §11.3):
910
+ * the `accounts.json` record verbatim. `provider` is `chat:<channel>` or
911
+ * `login:<slug>:<id>`; `subject` is the provider's stable subject
912
+ * (numeric id, `+E.164`, email-shaped — opaque to sigrun).
913
+ *
914
+ * Served to extensions as `host.accounts` and to users as
915
+ * `GET /v1/auth/accounts`.
916
+ */
917
+ export interface AccountLinkWire {
918
+ readonly provider: string;
919
+ readonly subject: string;
920
+ readonly user: string;
921
+ readonly linkedAt: number;
922
+ readonly via: "login" | "self" | "pairing" | "admin";
923
+ }
924
+ /**
925
+ * The `GET /v1/auth/accounts` payload (multi-user §11.3): the caller's
926
+ * links, or one named user's for an admin.
927
+ */
928
+ export interface AccountsResponse {
929
+ readonly accounts: readonly AccountLinkWire[];
930
+ }
761
931
  /**
762
932
  * One host event on the `GET /v1/events` SSE wire: `event: <type>` plus
763
933
  * this object as the single-line `data:` JSON. Conversation-scoped
@@ -811,6 +981,20 @@ export type HostEventWire = {
811
981
  /** W4 Task 4 (§8.4): the changed job's summary, WITHOUT `access` — the events stream computes `accessOf` per principal and adds it before delivery (a hidden job's event is withheld entirely). */
812
982
  readonly type: "job.changed";
813
983
  readonly job: Omit<JobWire, "access">;
984
+ } | {
985
+ /** UI-blocks U4 (spec §13.2): a settings write landed. `scope` is
986
+ * `"server"` for `PATCH /v1/settings` or `{extension: slug}` for
987
+ * an extension's settings PUT; `keys` are the flattened paths the
988
+ * write touched (dotted, the §13.1 registry vocabulary — extension
989
+ * writes name their own top-level object keys). Delivered to
990
+ * ADMINS only (settings are operator surface; the events route's
991
+ * exhaustive switch enforces it).
992
+ */
993
+ readonly type: "settings.changed";
994
+ readonly scope: "server" | {
995
+ readonly extension: string;
996
+ };
997
+ readonly keys: readonly string[];
814
998
  } | {
815
999
  /** UI-blocks U3 Task 4 (spec §7.3): one surface instance changed. `k` is the hashed instance key (sha256(slug + "\0" + id + "\0" + key) hex) — the event NEVER carries params or data (render/data are principal-specific; the watcher refetches as itself). Delivered only to streams in the watcher registry whose stored access is not `"none"`. */
816
1000
  readonly type: "surface.changed";
@@ -819,4 +1003,10 @@ export type HostEventWire = {
819
1003
  readonly k: string;
820
1004
  readonly rev: number;
821
1005
  readonly treeRev: number;
1006
+ } | {
1007
+ /** UI-blocks U5 Task 2 (spec §8.2): one CHAT block surface changed. The chat address is `(conversationId, entryId)` — no secret to watchers of that conversation (unlike params) — so the event names them directly instead of the hashed `k`. Delivered through the conversation-scoped path: the events route re-snapshots the SessionMeta and checks `accessOf` per event (hidden conversations see nothing). */
1008
+ readonly type: "surface.changed";
1009
+ readonly conversationId: number;
1010
+ readonly entryId: string;
1011
+ readonly rev: number;
822
1012
  };
@@ -36,3 +36,19 @@
36
36
  */
37
37
  /** The `Content-Type` of the JSONL export/import wire (Task 5b/5c). */
38
38
  export const JSONL_CONTENT_TYPE = "application/x-ndjson";
39
+ /**
40
+ * The settings search's filter (UI-blocks U4 Task 4 round-2): the ONE
41
+ * implementation both channels run — the webui panel and the TUI view
42
+ * previously carried byte-identical copies, which drifted apart once
43
+ * (the TUI's lacked the key match). Case-insensitive over label + help
44
+ * + key; an empty query filters to nothing (the picker carries the
45
+ * full list).
46
+ */
47
+ export function filterSettingsIndex(index, query) {
48
+ const q = query.trim().toLowerCase();
49
+ if (q === "")
50
+ return [];
51
+ return index.filter((entry) => entry.label.toLowerCase().includes(q) ||
52
+ (entry.help ?? "").toLowerCase().includes(q) ||
53
+ (entry.key ?? "").toLowerCase().includes(q));
54
+ }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sigrun/shared",
3
- "version": "0.1.2",
3
+ "version": "0.2.1",
4
4
  "description": "sigrun shared leaf package \u2014 theme tokens, turn/conversation shaping, and the channel wire types (pure leaf, zero dependencies)",
5
5
  "type": "module",
6
6
  "exports": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sigrun/sigrun",
3
- "version": "0.1.6",
3
+ "version": "0.2.1",
4
4
  "description": "Durable personal assistant on pi-durable",
5
5
  "type": "module",
6
6
  "exports": {
@@ -30,7 +30,7 @@
30
30
  "test": "vitest run",
31
31
  "typecheck": "tsc --noEmit",
32
32
  "build:shared": "npm --workspace @sigrun/shared run build",
33
- "build": "npm run build:shared && tsc -p tsconfig.build.json && tsc -p tsconfig.extension.json && node -e \"require('node:fs').rmSync('dist/extension.js',{force:true})\"",
33
+ "build": "npm run build:shared && tsc -p tsconfig.build.json && tsc -p tsconfig.extension.json && node scripts/stamp-block-build.mjs && node -e \"require('node:fs').rmSync('dist/extension.js',{force:true})\"",
34
34
  "build:webui": "npm --workspace @sigrun/webui run build",
35
35
  "typecheck:webui": "npm --workspace @sigrun/webui run typecheck",
36
36
  "test:e2e": "npm run build:webui && npm --workspace @sigrun/webui run test:e2e",
@@ -44,19 +44,24 @@
44
44
  "@earendil-works/pi-durable": "1.3.0",
45
45
  "@earendil-works/pi-tui": "^1.3.0",
46
46
  "@fastify/static": "^10.1.7",
47
- "@sigrun/ext-codemode": "0.1.0",
48
- "@sigrun/ext-mcp": "0.2.0",
49
- "@sigrun/ext-tool-search": "0.1.0",
50
- "@sigrun/shared": "0.1.2",
47
+ "@sigrun/ext-codemode": "0.1.1",
48
+ "@sigrun/ext-gateway": "0.1.2",
49
+ "@sigrun/ext-mcp": "0.2.1",
50
+ "@sigrun/ext-tool-search": "0.1.1",
51
+ "@sigrun/oauth": "0.1.1",
52
+ "@sigrun/shared": "0.2.1",
51
53
  "croner": "^10.0.1",
52
54
  "fastify": "^5.12.7",
55
+ "sharp": "^0.35.5",
53
56
  "typebox": "1.3.27"
54
57
  },
55
58
  "bundleDependencies": [
56
59
  "@sigrun/shared"
57
60
  ],
58
61
  "optionalDependencies": {
59
- "@sigrun/tui": "0.1.1"
62
+ "@sigrun/sandbox-linux-arm64": "0.2.1",
63
+ "@sigrun/sandbox-linux-x64": "0.2.1",
64
+ "@sigrun/tui": "0.2.1"
60
65
  },
61
66
  "devDependencies": {
62
67
  "@types/node": "^26.6.4",
@@ -85,8 +90,7 @@
85
90
  "THIRD_PARTY_NOTICES.md",
86
91
  "README.md",
87
92
  "LICENSE",
88
- "CHANGELOG.md",
89
- "CONTEXT.md"
93
+ "CHANGELOG.md"
90
94
  ],
91
95
  "allowScripts": {
92
96
  "@google/genai@2.21.0": true,