@gtc6244/immediacy-daemon 0.1.1 → 0.1.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 (77) hide show
  1. package/README.md +58 -25
  2. package/dist/src/agent/agent.d.ts +19 -6
  3. package/dist/src/agent/agent.js +3 -1
  4. package/dist/src/agent/agent.js.map +1 -1
  5. package/dist/src/agent/anthropic-probe.d.ts +24 -0
  6. package/dist/src/agent/anthropic-probe.js +81 -0
  7. package/dist/src/agent/anthropic-probe.js.map +1 -0
  8. package/dist/src/agent/claude.d.ts +4 -2
  9. package/dist/src/agent/claude.js +32 -4
  10. package/dist/src/agent/claude.js.map +1 -1
  11. package/dist/src/agent/codex.d.ts +1 -1
  12. package/dist/src/agent/codex.js +26 -3
  13. package/dist/src/agent/codex.js.map +1 -1
  14. package/dist/src/agent/images.d.ts +21 -0
  15. package/dist/src/agent/images.js +54 -0
  16. package/dist/src/agent/images.js.map +1 -0
  17. package/dist/src/agent/mock.d.ts +1 -1
  18. package/dist/src/agent/mock.js +28 -3
  19. package/dist/src/agent/mock.js.map +1 -1
  20. package/dist/src/agent/ollama-probe.d.ts +28 -0
  21. package/dist/src/agent/ollama-probe.js +76 -0
  22. package/dist/src/agent/ollama-probe.js.map +1 -0
  23. package/dist/src/agent/ollama.d.ts +42 -0
  24. package/dist/src/agent/ollama.js +64 -0
  25. package/dist/src/agent/ollama.js.map +1 -0
  26. package/dist/src/agent/openai-probe.d.ts +18 -0
  27. package/dist/src/agent/openai-probe.js +83 -0
  28. package/dist/src/agent/openai-probe.js.map +1 -0
  29. package/dist/src/agent/openrouter-probe.d.ts +21 -0
  30. package/dist/src/agent/openrouter-probe.js +77 -0
  31. package/dist/src/agent/openrouter-probe.js.map +1 -0
  32. package/dist/src/cli/paths.d.ts +2 -0
  33. package/dist/src/cli/paths.js +14 -7
  34. package/dist/src/cli/paths.js.map +1 -1
  35. package/dist/src/cli.js +40 -0
  36. package/dist/src/cli.js.map +1 -1
  37. package/dist/src/crypto.js +7 -2
  38. package/dist/src/crypto.js.map +1 -1
  39. package/dist/src/hub.d.ts +7 -0
  40. package/dist/src/hub.js +14 -0
  41. package/dist/src/hub.js.map +1 -1
  42. package/dist/src/index.d.ts +3 -0
  43. package/dist/src/index.js +35 -3
  44. package/dist/src/index.js.map +1 -1
  45. package/dist/src/jobs/scheduler.d.ts +1 -0
  46. package/dist/src/jobs/scheduler.js +1 -0
  47. package/dist/src/jobs/scheduler.js.map +1 -1
  48. package/dist/src/media-watch.d.ts +29 -0
  49. package/dist/src/media-watch.js +108 -0
  50. package/dist/src/media-watch.js.map +1 -0
  51. package/dist/src/media.d.ts +54 -0
  52. package/dist/src/media.js +156 -0
  53. package/dist/src/media.js.map +1 -0
  54. package/dist/src/model-efforts.d.ts +49 -0
  55. package/dist/src/model-efforts.js +107 -0
  56. package/dist/src/model-efforts.js.map +1 -0
  57. package/dist/src/models.d.ts +50 -17
  58. package/dist/src/models.js +119 -21
  59. package/dist/src/models.js.map +1 -1
  60. package/dist/src/projects.d.ts +7 -0
  61. package/dist/src/projects.js +14 -0
  62. package/dist/src/projects.js.map +1 -1
  63. package/dist/src/protocol.d.ts +163 -9
  64. package/dist/src/protocol.js +1 -1
  65. package/dist/src/server.js +141 -5
  66. package/dist/src/server.js.map +1 -1
  67. package/dist/src/types.d.ts +9 -0
  68. package/dist/src/updater.d.ts +78 -0
  69. package/dist/src/updater.js +240 -0
  70. package/dist/src/updater.js.map +1 -0
  71. package/dist/src/workspace.d.ts +25 -0
  72. package/dist/src/workspace.js +159 -6
  73. package/dist/src/workspace.js.map +1 -1
  74. package/package.json +4 -2
  75. package/dist/src/migrate-state-dir.d.ts +0 -1
  76. package/dist/src/migrate-state-dir.js +0 -47
  77. package/dist/src/migrate-state-dir.js.map +0 -1
@@ -177,6 +177,20 @@ export class ProjectStore {
177
177
  if (this.projects.delete(id))
178
178
  await this.persist();
179
179
  }
180
+ /**
181
+ * Rename a project — display name only. The on-disk managed dir (`slugFor`) is
182
+ * derived from the name at create time and never recomputed, so it is left as
183
+ * is (matching existing behavior). No-op on an unknown id, a blank name, or an
184
+ * unchanged name; persists only when the name actually changes.
185
+ */
186
+ async rename(id, name) {
187
+ const r = this.projects.get(id);
188
+ const next = name.trim();
189
+ if (!r || !next || r.name === next)
190
+ return;
191
+ r.name = next;
192
+ await this.persist();
193
+ }
180
194
  /**
181
195
  * Rewrite the stored project order. `list()` returns projects in Map insertion
182
196
  * order, so we rebuild the Map in the requested order. Unknown ids are ignored;
@@ -1 +1 @@
1
- {"version":3,"file":"projects.js","sourceRoot":"","sources":["../../src/projects.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"projects.js","sourceRoot":"","sources":["../../src/projects.ts"],"names":[],"mappings":"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"}
@@ -12,7 +12,7 @@
12
12
  * `payload` is encrypted in the E2E layer (slice 5); until then it travels as
13
13
  * plain JSON.
14
14
  */
15
- export declare const PROTOCOL_VERSION: 1;
15
+ export declare const PROTOCOL_VERSION: 2;
16
16
  /** Workspace lifecycle status, surfaced as a badge in the client. */
17
17
  export type WorkspaceStatus = "idle" | "running" | "awaiting_permission" | "done" | "error";
18
18
  /** Generic envelope. `T` is the message `type`; `P` its payload shape. */
@@ -25,9 +25,9 @@ export interface Envelope<T extends MessageType = MessageType> {
25
25
  payload: PayloadFor<T>;
26
26
  }
27
27
  /** Client → daemon. */
28
- export type ClientMessageType = "project.list" | "project.create" | "project.delete" | "project.reorder" | "project.branches" | "project.pulls" | "project.issues" | "issue.create" | "workspace.list" | "workspace.create" | "workspace.delete" | "workspace.archive" | "workspace.action" | "delete.batch" | "prompt.send" | "agent.stop" | "permission.respond" | "question.respond" | "allowlist.list" | "allowlist.revoke" | "allowlist.clear" | "terminal.input" | "terminal.resize" | "terminal.snapshot" | "forward.list" | "forward.open" | "forward.data" | "forward.close" | "git.status" | "git.commit" | "git.push" | "git.resolve" | "git.merge" | "pr.create" | "pr.merge" | "workspace.open" | "diff.get" | "tree.get" | "file.get" | "file.set" | "chat.history" | "github.status" | "github.repos" | "models.list" | "job.list" | "job.create" | "job.update" | "job.delete" | "job.run" | "job.runs" | "settings.get" | "settings.set" | "config.set" | "log.tail" | "hello" | "pair.info" | "daemon.get" | "daemon.rename" | "ping" | "echo";
28
+ export type ClientMessageType = "project.list" | "project.create" | "project.delete" | "project.rename" | "project.reorder" | "project.branches" | "project.pulls" | "project.issues" | "issue.create" | "workspace.list" | "workspace.create" | "workspace.delete" | "workspace.archive" | "workspace.rename" | "workspace.action" | "delete.batch" | "prompt.send" | "agent.stop" | "permission.respond" | "question.respond" | "allowlist.list" | "allowlist.revoke" | "allowlist.clear" | "terminal.input" | "terminal.resize" | "terminal.snapshot" | "forward.list" | "forward.open" | "forward.data" | "forward.close" | "git.status" | "git.commit" | "git.push" | "git.resolve" | "git.merge" | "pr.create" | "pr.merge" | "workspace.open" | "diff.get" | "tree.get" | "file.get" | "file.set" | "media.get" | "chat.history" | "github.status" | "github.repos" | "models.list" | "job.list" | "job.create" | "job.update" | "job.delete" | "job.run" | "job.runs" | "settings.get" | "settings.set" | "config.set" | "log.tail" | "client.hello" | "hello" | "pair.info" | "daemon.get" | "daemon.rename" | "daemon.update.check" | "daemon.update" | "ping" | "echo";
29
29
  /** Daemon → client. */
30
- export type DaemonMessageType = "project.list.result" | "project.branches.result" | "project.pulls.result" | "project.issues.result" | "workspace.list.result" | "workspace.created" | "workspace.renamed" | "delete.batch.result" | "event.assistant_message" | "event.tool_use" | "event.permission_request" | "event.permission_resolved" | "event.ask_question" | "event.session" | "event.agent_done" | "event.session_limit" | "terminal.data" | "terminal.snapshot.result" | "forward.available" | "git.status.result" | "git.result" | "diff.result" | "tree.result" | "file.result" | "file.saved" | "chat.history.result" | "github.status.result" | "github.repos.result" | "models.list.result" | "job.list.result" | "job.runs.result" | "event.job_run" | "settings.result" | "allowlist.result" | "log.tail.result" | "log.event" | "hello.ok" | "pair.info.result" | "daemon.info" | "pong" | "error" | "echo.result";
30
+ export type DaemonMessageType = "project.list.result" | "project.branches.result" | "project.pulls.result" | "project.issues.result" | "workspace.list.result" | "workspace.created" | "workspace.renamed" | "delete.batch.result" | "event.assistant_message" | "event.assistant_image" | "event.tool_use" | "event.permission_request" | "event.permission_resolved" | "event.ask_question" | "event.question_resolved" | "event.session" | "event.agent_done" | "event.session_limit" | "terminal.data" | "terminal.snapshot.result" | "forward.available" | "git.status.result" | "git.result" | "diff.result" | "tree.result" | "file.result" | "file.saved" | "media.result" | "chat.history.result" | "github.status.result" | "github.repos.result" | "models.list.result" | "job.list.result" | "job.runs.result" | "event.job_run" | "settings.result" | "allowlist.result" | "log.tail.result" | "log.event" | "hello.ok" | "pair.info.result" | "daemon.info" | "daemon.update.result" | "pong" | "error" | "echo.result";
31
31
  export type MessageType = ClientMessageType | DaemonMessageType;
32
32
  export interface ProjectListPayload {
33
33
  }
@@ -112,6 +112,11 @@ export interface WorkspaceCreatePayload {
112
112
  initialPrompt?: string;
113
113
  /** Model id from the catalog (see models.list); omitted → daemon default. */
114
114
  model?: string;
115
+ /**
116
+ * Reasoning-effort id for the chosen model (one of its `efforts`); omitted
117
+ * when the model has no effort knob or the client left it at the default.
118
+ */
119
+ effort?: string;
115
120
  }
116
121
  /** Request the branches a new worktree can be based on, for one project. */
117
122
  export interface ProjectBranchesPayload {
@@ -149,6 +154,11 @@ export interface WorkspaceDeletePayload {
149
154
  export interface WorkspaceArchivePayload {
150
155
  ws: string;
151
156
  }
157
+ /** Rename a workspace's sidebar label (display name only). */
158
+ export interface WorkspaceRenamePayload {
159
+ ws: string;
160
+ name: string;
161
+ }
152
162
  /**
153
163
  * A prompt-backed agent action. Each kind maps to a built-in base instruction
154
164
  * plus the matching `prompts.*` custom text (see AppConfig): `code_review` →
@@ -380,6 +390,11 @@ export interface FileGetPayload {
380
390
  ws: string;
381
391
  path: string;
382
392
  }
393
+ /** Fetch the bytes of an agent-produced image by id (see event.assistant_image). */
394
+ export interface MediaGetPayload {
395
+ ws: string;
396
+ id: string;
397
+ }
383
398
  /** Write new UTF-8 contents to one worktree-relative file (in-app editor save). */
384
399
  export interface FileSetPayload {
385
400
  ws: string;
@@ -399,6 +414,21 @@ export interface PingPayload {
399
414
  export interface EchoPayload {
400
415
  text: string;
401
416
  }
417
+ /**
418
+ * Client → daemon: the version handshake, sent as the client's first app-level
419
+ * frame right after it connects. The mirror of the daemon's `daemon.info`: it
420
+ * lets the daemon compare the client's `PROTOCOL_VERSION` to its own and warn
421
+ * (in the log) on a skew. A mismatch never rejects the connection — the two may
422
+ * still interoperate — it only surfaces a heads-up on both ends.
423
+ */
424
+ export interface ClientHelloPayload {
425
+ /** The PROTOCOL_VERSION this client speaks (compared to the daemon's). */
426
+ protocolVersion: number;
427
+ /** The client's release version (display/diagnostics only); may be empty. */
428
+ version?: string;
429
+ /** Optional human label for the client kind (e.g. "phone", "web", "macOS"). */
430
+ label?: string;
431
+ }
402
432
  /**
403
433
  * A registered project: one repo, the group worktrees hang under in the
404
434
  * sidebar. Persists even with zero worktrees so it stays a stable "+ new
@@ -499,6 +529,8 @@ export interface WorkspaceSummary {
499
529
  kind?: "worktree" | "chat";
500
530
  /** Model id backing this workspace's agent (see models.list). */
501
531
  model?: string;
532
+ /** Reasoning-effort id backing this workspace's agent (see the model's `efforts`). */
533
+ effort?: string;
502
534
  /** Lines added vs the base branch (uncommitted + committed); omitted if 0. */
503
535
  added?: number;
504
536
  /** Lines removed vs the base branch; omitted if 0. */
@@ -513,13 +545,34 @@ export interface WorkspaceSummary {
513
545
  repoUrl?: string;
514
546
  }
515
547
  /** Which agent backend runs a model. */
516
- export type ModelProvider = "claude" | "codex" | "openrouter";
548
+ export type ModelProvider = "claude" | "codex" | "openrouter" | "ollama";
549
+ /**
550
+ * One reasoning-effort level a model can run at (e.g. Claude's
551
+ * low/medium/high/xhigh/max, or a Codex/GPT reasoning effort). `id` is the exact
552
+ * token handed to the backend; `label` is the human-readable name.
553
+ */
554
+ export interface ModelEffort {
555
+ id: string;
556
+ label: string;
557
+ }
517
558
  /** One selectable model, surfaced to the client via models.list.result. */
518
559
  export interface ModelInfo {
519
560
  id: string;
520
561
  label: string;
521
562
  provider: ModelProvider;
522
563
  default?: boolean;
564
+ /**
565
+ * Reasoning-effort levels this model supports, in ascending order. Omitted or
566
+ * empty when the model has no effort knob (the client shows no effort picker).
567
+ */
568
+ efforts?: ModelEffort[];
569
+ /** Effort id preselected when this model is chosen (one of `efforts`). */
570
+ defaultEffort?: string;
571
+ /**
572
+ * When the model was released, ISO-8601 (from the provider's model API). Used
573
+ * only for the 12-month discovery window / display; absent for Ollama.
574
+ */
575
+ released?: string;
523
576
  }
524
577
  export interface ModelsListResultPayload {
525
578
  models: ModelInfo[];
@@ -648,6 +701,22 @@ export interface EventAssistantMessagePayload {
648
701
  ws: string;
649
702
  text: string;
650
703
  }
704
+ /**
705
+ * An agent-produced image was surfaced. Metadata only — the bytes are fetched
706
+ * on demand via `media.get` (`id` is the content hash / stable cache key). Kept
707
+ * out of the event so multi-MB screenshots don't bloat broadcasts or the E2E
708
+ * channel. `source` distinguishes an image returned by a tool from one the
709
+ * agent wrote into the worktree (`name` is then its relative path).
710
+ */
711
+ export interface EventAssistantImagePayload {
712
+ ws: string;
713
+ id: string;
714
+ name: string;
715
+ mediaType: string;
716
+ size: number;
717
+ source: "tool" | "file";
718
+ tool?: string;
719
+ }
651
720
  export interface EventToolUsePayload {
652
721
  ws: string;
653
722
  tool: string;
@@ -660,16 +729,31 @@ export interface EventPermissionRequestPayload {
660
729
  inputSummary: string;
661
730
  }
662
731
  /**
663
- * A previously-broadcast permission request was resolved without the client
664
- * answering it — a new "allow all" rule retroactively covered it — so clients
665
- * collapse its card. Emitted by the retroactive-release sweep (see
666
- * ClaudeAgent.releaseCoveredPending).
732
+ * A previously-broadcast permission request was resolved. Broadcast to ALL
733
+ * clients whenever a decision lands — whether a user answered it here
734
+ * (allow/deny/allow_all), or a new "allow all" rule retroactively covered it
735
+ * (see ClaudeAgent.releaseCoveredPending). Clients collapse the matching card
736
+ * and disable its controls so a request answered on one device becomes
737
+ * non-actionable everywhere. Idempotent: resolving an already-resolved card is
738
+ * a no-op on every client.
667
739
  */
668
740
  export interface EventPermissionResolvedPayload {
669
741
  ws: string;
670
742
  requestId: string;
671
743
  decision: "allow" | "deny";
672
744
  }
745
+ /**
746
+ * A previously-broadcast question (see event.ask_question) was answered on some
747
+ * device. Broadcast to ALL clients so stale question cards on other devices
748
+ * collapse into their answered summary and can no longer be submitted twice.
749
+ * Idempotent on every client.
750
+ */
751
+ export interface EventQuestionResolvedPayload {
752
+ ws: string;
753
+ requestId: string;
754
+ answers: QuestionAnswers;
755
+ response?: string;
756
+ }
673
757
  /**
674
758
  * The model asked one or more clarifying questions via `AskUserQuestion`. The
675
759
  * client renders an interactive card and replies with `question.respond`
@@ -825,7 +909,7 @@ export interface GitResultPayload {
825
909
  url?: string;
826
910
  }
827
911
  /** Role of a persisted transcript entry — mirrors the client's ChatRole. */
828
- export type ChatEntryRole = "user" | "assistant" | "tool" | "permission" | "question" | "limit" | "system";
912
+ export type ChatEntryRole = "user" | "assistant" | "assistant_image" | "tool" | "permission" | "question" | "limit" | "system";
829
913
  /**
830
914
  * One durable line in a workspace's transcript. The daemon appends these to a
831
915
  * per-workspace running log as prompts and events flow, so the whole
@@ -848,12 +932,26 @@ export interface ChatEntry {
848
932
  * an "📎 name" chip on replay without carrying the payload in the log.
849
933
  */
850
934
  attachments?: ChatAttachmentMeta[];
935
+ /**
936
+ * assistant_image-only: reference to an agent-produced image persisted in the
937
+ * media store. Only metadata is kept in the transcript (never the bytes); the
938
+ * client fetches bytes via `media.get` on replay, keyed by the content-hash id.
939
+ */
940
+ media?: ChatMediaMeta;
851
941
  }
852
942
  /** Lightweight attachment descriptor persisted in the transcript (no bytes). */
853
943
  export interface ChatAttachmentMeta {
854
944
  name: string;
855
945
  mediaType: string;
856
946
  }
947
+ /** Reference to a stored agent-produced image, persisted in the transcript. */
948
+ export interface ChatMediaMeta {
949
+ id: string;
950
+ name: string;
951
+ mediaType: string;
952
+ size: number;
953
+ source: "tool" | "file";
954
+ }
857
955
  export interface ChatHistoryResultPayload {
858
956
  ws: string;
859
957
  entries: ChatEntry[];
@@ -883,6 +981,18 @@ export interface FileResultPayload {
883
981
  truncated: boolean;
884
982
  binary: boolean;
885
983
  }
984
+ /**
985
+ * Bytes for an agent-produced image, in reply to `media.get`. `data` is base64
986
+ * (no data: URI prefix); `notFound` marks a missing/evicted id so the client can
987
+ * drop the reference instead of retrying.
988
+ */
989
+ export interface MediaResultPayload {
990
+ ws: string;
991
+ id: string;
992
+ mediaType: string;
993
+ data: string;
994
+ notFound?: boolean;
995
+ }
886
996
  /** Acknowledges a successful in-app editor save (file.set). */
887
997
  export interface FileSavedPayload {
888
998
  ws: string;
@@ -955,6 +1065,39 @@ export interface DaemonInfoPayload {
955
1065
  /** The PROTOCOL_VERSION this daemon speaks, for future skew detection. */
956
1066
  protocolVersion: number;
957
1067
  }
1068
+ /** Client → daemon: check the npm registry for a newer daemon (read-only). */
1069
+ export interface DaemonUpdateCheckPayload {
1070
+ }
1071
+ /**
1072
+ * Client → daemon: install a newer daemon from npm and restart to load it.
1073
+ * `version` pins a specific release; omit it to take the registry `latest`.
1074
+ */
1075
+ export interface DaemonUpdatePayload {
1076
+ version?: string;
1077
+ }
1078
+ /**
1079
+ * Daemon → client: the result of a `daemon.update.check` (`phase: "check"`) or
1080
+ * a `daemon.update` (`phase: "update"`). For a check, `latestVersion` /
1081
+ * `updateAvailable` are the interesting fields. For an update, `ok` reports the
1082
+ * install result and `restarting` says whether the service is being restarted
1083
+ * to load it (false on platforms without a managed service — restart by hand).
1084
+ * On any failure `error` is set.
1085
+ */
1086
+ export interface DaemonUpdateResultPayload {
1087
+ phase: "check" | "update";
1088
+ /** The version currently running. */
1089
+ currentVersion: string;
1090
+ /** Registry `latest` (check), or the requested target spec (update). */
1091
+ latestVersion?: string | null;
1092
+ /** Check only: registry latest is strictly newer than the running version. */
1093
+ updateAvailable?: boolean;
1094
+ /** Update only: whether `npm install -g` succeeded. */
1095
+ ok?: boolean;
1096
+ /** Update only: whether a service restart was scheduled to load the update. */
1097
+ restarting?: boolean;
1098
+ /** Set on any failure (registry unreachable, install non-zero exit, …). */
1099
+ error?: string;
1100
+ }
958
1101
  export interface ErrorPayload {
959
1102
  code: string;
960
1103
  message: string;
@@ -1008,6 +1151,8 @@ export interface EphemeralTarget {
1008
1151
  };
1009
1152
  branchBase?: string;
1010
1153
  model?: string;
1154
+ /** Reasoning-effort id for the ephemeral workspace's model (see model `efforts`). */
1155
+ effort?: string;
1011
1156
  /** Base name for the throwaway workspace (defaults to the job name). */
1012
1157
  name?: string;
1013
1158
  }
@@ -1132,6 +1277,7 @@ export interface PayloadMap {
1132
1277
  "workspace.create": WorkspaceCreatePayload;
1133
1278
  "workspace.delete": WorkspaceDeletePayload;
1134
1279
  "workspace.archive": WorkspaceArchivePayload;
1280
+ "workspace.rename": WorkspaceRenamePayload;
1135
1281
  "workspace.action": WorkspaceActionPayload;
1136
1282
  "delete.batch": DeleteBatchPayload;
1137
1283
  "prompt.send": PromptSendPayload;
@@ -1160,6 +1306,7 @@ export interface PayloadMap {
1160
1306
  "tree.get": TreeGetPayload;
1161
1307
  "file.get": FileGetPayload;
1162
1308
  "file.set": FileSetPayload;
1309
+ "media.get": MediaGetPayload;
1163
1310
  "chat.history": ChatHistoryPayload;
1164
1311
  "github.status": GithubStatusPayload;
1165
1312
  "github.repos": GithubReposPayload;
@@ -1174,10 +1321,13 @@ export interface PayloadMap {
1174
1321
  "settings.set": SettingsSetPayload;
1175
1322
  "config.set": ConfigSetPayload;
1176
1323
  "log.tail": LogTailPayload;
1324
+ "client.hello": ClientHelloPayload;
1177
1325
  hello: HelloPayload;
1178
1326
  "pair.info": PairInfoPayload;
1179
1327
  "daemon.get": DaemonGetPayload;
1180
1328
  "daemon.rename": DaemonRenamePayload;
1329
+ "daemon.update.check": DaemonUpdateCheckPayload;
1330
+ "daemon.update": DaemonUpdatePayload;
1181
1331
  ping: PingPayload;
1182
1332
  echo: EchoPayload;
1183
1333
  "project.list.result": ProjectListResultPayload;
@@ -1189,10 +1339,12 @@ export interface PayloadMap {
1189
1339
  "workspace.renamed": WorkspaceRenamedPayload;
1190
1340
  "delete.batch.result": DeleteBatchResultPayload;
1191
1341
  "event.assistant_message": EventAssistantMessagePayload;
1342
+ "event.assistant_image": EventAssistantImagePayload;
1192
1343
  "event.tool_use": EventToolUsePayload;
1193
1344
  "event.permission_request": EventPermissionRequestPayload;
1194
1345
  "event.permission_resolved": EventPermissionResolvedPayload;
1195
1346
  "event.ask_question": EventAskQuestionPayload;
1347
+ "event.question_resolved": EventQuestionResolvedPayload;
1196
1348
  "event.session": EventSessionPayload;
1197
1349
  "event.agent_done": EventAgentDonePayload;
1198
1350
  "event.session_limit": EventSessionLimitPayload;
@@ -1205,6 +1357,7 @@ export interface PayloadMap {
1205
1357
  "tree.result": TreeResultPayload;
1206
1358
  "file.result": FileResultPayload;
1207
1359
  "file.saved": FileSavedPayload;
1360
+ "media.result": MediaResultPayload;
1208
1361
  "chat.history.result": ChatHistoryResultPayload;
1209
1362
  "github.status.result": GithubStatusResultPayload;
1210
1363
  "github.repos.result": GithubReposResultPayload;
@@ -1219,6 +1372,7 @@ export interface PayloadMap {
1219
1372
  "hello.ok": HelloOkPayload;
1220
1373
  "pair.info.result": PairInfoResultPayload;
1221
1374
  "daemon.info": DaemonInfoPayload;
1375
+ "daemon.update.result": DaemonUpdateResultPayload;
1222
1376
  pong: PongPayload;
1223
1377
  error: ErrorPayload;
1224
1378
  "echo.result": EchoResultPayload;
@@ -12,5 +12,5 @@
12
12
  * `payload` is encrypted in the E2E layer (slice 5); until then it travels as
13
13
  * plain JSON.
14
14
  */
15
- export const PROTOCOL_VERSION = 1;
15
+ export const PROTOCOL_VERSION = 2;
16
16
  //# sourceMappingURL=protocol.js.map
@@ -12,6 +12,7 @@ import { stat } from "node:fs/promises";
12
12
  import { fileURLToPath } from "node:url";
13
13
  import { dirname, extname, join, normalize, resolve, sep } from "node:path";
14
14
  import { WebSocketServer } from "ws";
15
+ import { PROTOCOL_VERSION } from "./protocol.js";
15
16
  import { make, ProtocolError } from "./envelope.js";
16
17
  import { addPeer, boxCodec, isValidPublicKeyB64 } from "./crypto.js";
17
18
  import { Hub } from "./hub.js";
@@ -21,13 +22,14 @@ import { ForwardManager } from "./forward.js";
21
22
  import { AppConfigStore } from "./config.js";
22
23
  import { CredentialsStore } from "./credentials.js";
23
24
  import { DaemonIdentity } from "./daemon-identity.js";
25
+ import { checkForUpdate, performUpdate, scheduleRestart } from "./updater.js";
24
26
  import { originUrl } from "./gitops.js";
25
27
  import { AllowlistStore } from "./allowlist.js";
26
28
  import { SystemEvents } from "./events.js";
27
29
  import { JobStore } from "./jobs/store.js";
28
30
  import { JobScheduler } from "./jobs/scheduler.js";
29
31
  import { status as githubStatus, listRepos } from "./github.js";
30
- import { MODELS, DEFAULT_MODEL } from "./models.js";
32
+ import { allModels, defaultModel, refreshAllModels } from "./models.js";
31
33
  import { logger } from "./log.js";
32
34
  const startedAt = Date.now();
33
35
  /**
@@ -101,6 +103,42 @@ async function serveStatic(reqUrl, method, res) {
101
103
  return false;
102
104
  }
103
105
  }
106
+ /**
107
+ * Serve agent-produced image bytes at `/media/<ws>/<id>` with immutable caching.
108
+ * The id is the content hash, so a cached response is valid forever. Bounds are
109
+ * enforced by the MediaStore (id must be sha256 hex; ws is traversal-guarded).
110
+ */
111
+ async function serveMedia(reqUrl, method, res, workspaces) {
112
+ let pathname;
113
+ try {
114
+ pathname = decodeURIComponent(new URL(reqUrl, "http://localhost").pathname);
115
+ }
116
+ catch {
117
+ res.writeHead(400).end();
118
+ return;
119
+ }
120
+ const parts = pathname.split("/").filter(Boolean); // ["media", <ws>, <id>]
121
+ if (parts.length !== 3 || parts[0] !== "media") {
122
+ res.writeHead(404, { "cache-control": "no-store" }).end();
123
+ return;
124
+ }
125
+ const bytes = await workspaces.getMedia(parts[1], parts[2]).catch(() => null);
126
+ if (!bytes) {
127
+ res.writeHead(404, { "cache-control": "no-store" }).end();
128
+ return;
129
+ }
130
+ const buf = Buffer.from(bytes.data, "base64");
131
+ res.writeHead(200, {
132
+ "content-type": bytes.mediaType || "application/octet-stream",
133
+ "content-length": buf.length,
134
+ "cache-control": "public, max-age=31536000, immutable",
135
+ });
136
+ if (method === "HEAD") {
137
+ res.end();
138
+ return;
139
+ }
140
+ res.end(buf);
141
+ }
104
142
  export async function startServer(opts) {
105
143
  // E2E on ⇒ require a sealed channel before fanning broadcasts to a socket, so
106
144
  // an un-handshaked device can't be sent cleartext payloads over the tunnel.
@@ -128,7 +166,10 @@ export async function startServer(opts) {
128
166
  await allowlist.load();
129
167
  // Default chatlog (2nd arg undefined → its default) + event bus + credentials
130
168
  // + app config + allowlist.
131
- const workspaces = new WorkspaceManager(hub, undefined, events, undefined, credentials, appConfig, allowlist);
169
+ const workspaces = new WorkspaceManager(hub, undefined, // chatlog → default
170
+ undefined, // media → default
171
+ events, undefined, // projects → default
172
+ credentials, appConfig, allowlist);
132
173
  await workspaces.load();
133
174
  // Cron/scheduled jobs. The scheduler drives runs through the WorkspaceManager
134
175
  // (which structurally satisfies its JobRunnerHost) and listens on the same
@@ -170,6 +211,14 @@ export async function startServer(opts) {
170
211
  res.end(body);
171
212
  return;
172
213
  }
214
+ // Agent-produced image bytes for the web client: same-origin, Access-cookie
215
+ // authorized, and immutably cacheable (the id is the content hash, so the URL
216
+ // never changes meaning). E2E clients use the sealed `media.get` WS path
217
+ // instead; this endpoint is the web app's simpler, natively-cached route.
218
+ if ((req.method === "GET" || req.method === "HEAD") && req.url?.startsWith("/media/")) {
219
+ void serveMedia(req.url, req.method, res, workspaces);
220
+ return;
221
+ }
173
222
  // Serve the browser client (webApp/) on GET/HEAD from the same origin the
174
223
  // tunnel dials, so the Access cookie authorizes both the page and its WS.
175
224
  if ((req.method === "GET" || req.method === "HEAD") && req.url) {
@@ -314,6 +363,25 @@ async function handleFrame(socket, raw, connId, crypto, hub, workspaces, jobs, c
314
363
  const reply = (env2) => hub.send(socket, env2);
315
364
  try {
316
365
  switch (env.type) {
366
+ case "client.hello": {
367
+ // Version handshake (mirror of the daemon.info the daemon pushes back).
368
+ // The client reports the protocol version it speaks; we compare it to
369
+ // ours and warn on a skew. A mismatch is a heads-up, never fatal — the
370
+ // socket keeps serving — so there is no reply frame and no reject.
371
+ const p = env.payload;
372
+ const clientProto = typeof p.protocolVersion === "number" ? p.protocolVersion : undefined;
373
+ const clientVersion = typeof p.version === "string" ? p.version : undefined;
374
+ const label = typeof p.label === "string" ? p.label : undefined;
375
+ if (clientProto !== undefined && clientProto !== PROTOCOL_VERSION) {
376
+ logger.warn("conn", `client protocol v${clientProto} does not match daemon v${PROTOCOL_VERSION} — some features may misbehave`, { data: { clientProtocol: clientProto, daemonProtocol: PROTOCOL_VERSION, clientVersion, label } });
377
+ }
378
+ else {
379
+ logger.info("conn", "client handshake", {
380
+ data: { protocolVersion: clientProto, clientVersion, label },
381
+ });
382
+ }
383
+ return;
384
+ }
317
385
  case "hello": {
318
386
  // Multi-device pairing handshake. The client announces its public key
319
387
  // (cleartext, but already inside the Access-authenticated tunnel — the
@@ -363,6 +431,41 @@ async function handleFrame(socket, raw, connId, crypto, hub, workspaces, jobs, c
363
431
  hub.broadcast("daemon.info", null, identity.info());
364
432
  return;
365
433
  }
434
+ case "daemon.update.check": {
435
+ const status = await checkForUpdate();
436
+ reply(make("daemon.update.result", null, {
437
+ phase: "check",
438
+ currentVersion: status.currentVersion,
439
+ latestVersion: status.latestVersion,
440
+ updateAvailable: status.updateAvailable,
441
+ error: status.error,
442
+ }));
443
+ return;
444
+ }
445
+ case "daemon.update": {
446
+ const p = env.payload;
447
+ const version = typeof p.version === "string" && p.version.trim()
448
+ ? p.version.trim()
449
+ : undefined;
450
+ const result = await performUpdate(version);
451
+ const willRestart = result.ok && result.canRestart;
452
+ const done = make("daemon.update.result", null, {
453
+ phase: "update",
454
+ currentVersion: result.fromVersion,
455
+ latestVersion: result.target,
456
+ ok: result.ok,
457
+ restarting: willRestart,
458
+ error: result.error,
459
+ });
460
+ // On success this process is about to be re-exec'd by the supervisor.
461
+ // Arm the restart only once the reply has flushed to the socket, so the
462
+ // client always learns the outcome before the connection drops.
463
+ if (willRestart)
464
+ hub.sendThen(socket, done, () => scheduleRestart());
465
+ else
466
+ reply(done);
467
+ return;
468
+ }
366
469
  case "ping":
367
470
  reply(make("pong", env.ws, {}));
368
471
  return;
@@ -394,6 +497,16 @@ async function handleFrame(socket, raw, connId, crypto, hub, workspaces, jobs, c
394
497
  hub.broadcast("project.list.result", null, { projects: await projects(workspaces) });
395
498
  return;
396
499
  }
500
+ case "project.rename": {
501
+ const p = env.payload;
502
+ if (!p.id || !p.name?.trim()) {
503
+ reply(make("error", null, { code: "bad_args", message: "id and name are required" }));
504
+ return;
505
+ }
506
+ await workspaces.renameProject(p.id, p.name);
507
+ hub.broadcast("project.list.result", null, { projects: await projects(workspaces) });
508
+ return;
509
+ }
397
510
  case "project.reorder": {
398
511
  const p = env.payload;
399
512
  const ids = Array.isArray(p.ids)
@@ -472,9 +585,13 @@ async function handleFrame(socket, raw, connId, crypto, hub, workspaces, jobs, c
472
585
  void workspaces.syncAllReposAndRefresh();
473
586
  return;
474
587
  case "models.list":
588
+ // Re-probe every provider (TTL-cached) so newly-available online models
589
+ // and freshly-pulled local Ollama models appear without a daemon
590
+ // restart; never blocks longer than the probe timeouts.
591
+ await refreshAllModels(credentials);
475
592
  reply(make("models.list.result", null, {
476
- models: MODELS,
477
- defaultModel: DEFAULT_MODEL.id,
593
+ models: allModels(),
594
+ defaultModel: defaultModel().id,
478
595
  }));
479
596
  return;
480
597
  case "workspace.create": {
@@ -482,7 +599,7 @@ async function handleFrame(socket, raw, connId, crypto, hub, workspaces, jobs, c
482
599
  // A chat is repo-less: no project/repo/github required — the daemon
483
600
  // spins up a private scratch dir instead of a worktree.
484
601
  if (p.kind === "chat") {
485
- await workspaces.createChat({ model: p.model });
602
+ await workspaces.createChat({ model: p.model, effort: p.effort });
486
603
  await workspaces.broadcastWorkspaceList();
487
604
  return;
488
605
  }
@@ -500,6 +617,7 @@ async function handleFrame(socket, raw, connId, crypto, hub, workspaces, jobs, c
500
617
  sourcePr: p.sourcePr,
501
618
  initialPrompt: p.initialPrompt,
502
619
  model: p.model,
620
+ effort: p.effort,
503
621
  });
504
622
  // Broadcast fresh lists so every client converges. Projects too: the
505
623
  // legacy bare-repo path may have just registered a new one.
@@ -539,6 +657,12 @@ async function handleFrame(socket, raw, connId, crypto, hub, workspaces, jobs, c
539
657
  await workspaces.broadcastWorkspaceList();
540
658
  return;
541
659
  }
660
+ case "workspace.rename": {
661
+ const p = env.payload;
662
+ if (p.ws && typeof p.name === "string")
663
+ await workspaces.rename(p.ws, p.name);
664
+ return;
665
+ }
542
666
  case "workspace.action": {
543
667
  const p = env.payload;
544
668
  if (!p.ws || !isWorkspaceActionKind(p.kind)) {
@@ -809,6 +933,18 @@ async function handleFrame(socket, raw, connId, crypto, hub, workspaces, jobs, c
809
933
  reply(make("file.result", p.ws, { ws: p.ws, ...file }));
810
934
  return;
811
935
  }
936
+ case "media.get": {
937
+ const p = env.payload;
938
+ if (!p.ws || typeof p.id !== "string")
939
+ return;
940
+ const bytes = await workspaces.getMedia(p.ws, p.id);
941
+ if (!bytes) {
942
+ reply(make("media.result", p.ws, { ws: p.ws, id: p.id, mediaType: "", data: "", notFound: true }));
943
+ return;
944
+ }
945
+ reply(make("media.result", p.ws, { ws: p.ws, id: p.id, ...bytes }));
946
+ return;
947
+ }
812
948
  case "file.set": {
813
949
  const p = env.payload;
814
950
  if (!p.ws || typeof p.path !== "string" || typeof p.content !== "string")