clay-server 4.1.0-beta.6 → 4.1.0-beta.7

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 (90) hide show
  1. package/LICENSE +661 -21
  2. package/LICENSES/MIT-legacy.txt +21 -0
  3. package/LICENSES/README.md +7 -0
  4. package/README.md +2 -2
  5. package/bin/cli.js +0 -2
  6. package/lib/daemon.js +0 -2
  7. package/lib/default-ai-runtime.js +117 -0
  8. package/lib/git-cli.js +1 -0
  9. package/lib/issue-work-session.js +10 -0
  10. package/lib/issues-comments.js +40 -0
  11. package/lib/issues-commit-verification.js +30 -0
  12. package/lib/issues-mcp-server.js +27 -0
  13. package/lib/issues-schema.js +119 -0
  14. package/lib/issues-service.js +339 -0
  15. package/lib/issues-store.js +210 -0
  16. package/lib/model-entry.js +15 -0
  17. package/lib/project-capsule-turn.js +1 -0
  18. package/lib/project-connection.js +2 -0
  19. package/lib/project-delegated-session.js +1 -0
  20. package/lib/project-filesystem.js +10 -10
  21. package/lib/project-issue-launch.js +154 -0
  22. package/lib/project-issues.js +58 -0
  23. package/lib/project-logs-mcp-server.js +8 -12
  24. package/lib/project-message-delivery.js +4 -2
  25. package/lib/project-models.js +71 -3
  26. package/lib/project-pending-message-queue.js +264 -0
  27. package/lib/project-scheduled-tasks.js +2 -4
  28. package/lib/project-sessions.js +82 -31
  29. package/lib/project-tool-llm-runtime.js +48 -0
  30. package/lib/project-user-message.js +178 -42
  31. package/lib/project-workspace-query.js +25 -0
  32. package/lib/project.js +102 -18
  33. package/lib/public/app.js +38 -4
  34. package/lib/public/css/default-ai.css +33 -0
  35. package/lib/public/css/input.css +89 -5
  36. package/lib/public/css/issues.css +101 -0
  37. package/lib/public/css/messages.css +19 -0
  38. package/lib/public/css/pending-message-queue.css +187 -0
  39. package/lib/public/css/scheduled-tasks.css +3 -4
  40. package/lib/public/index.html +25 -17
  41. package/lib/public/modules/app-connection.js +3 -0
  42. package/lib/public/modules/app-cursors.js +29 -12
  43. package/lib/public/modules/app-message-router.js +8 -0
  44. package/lib/public/modules/app-messages.js +12 -3
  45. package/lib/public/modules/clay-file-links.js +111 -0
  46. package/lib/public/modules/clay-issue-links.js +131 -0
  47. package/lib/public/modules/clay-log-links.js +2 -0
  48. package/lib/public/modules/cursor-sharing-preference.js +38 -0
  49. package/lib/public/modules/default-ai.js +377 -0
  50. package/lib/public/modules/filebrowser.js +43 -2
  51. package/lib/public/modules/input.js +7 -17
  52. package/lib/public/modules/issues-context.js +117 -0
  53. package/lib/public/modules/issues-render.js +29 -0
  54. package/lib/public/modules/issues.js +270 -0
  55. package/lib/public/modules/markdown.js +4 -0
  56. package/lib/public/modules/message-delivery.js +5 -3
  57. package/lib/public/modules/pending-message-image-editor.js +143 -0
  58. package/lib/public/modules/pending-message-queue-model.js +22 -0
  59. package/lib/public/modules/pending-message-queue.js +449 -0
  60. package/lib/public/modules/scheduled-task-engine.js +0 -50
  61. package/lib/public/modules/scheduled-tasks.js +7 -16
  62. package/lib/public/modules/sidebar-mobile.js +3 -0
  63. package/lib/public/modules/sticky-note-markdown.js +1 -0
  64. package/lib/public/modules/terminal.js +2 -0
  65. package/lib/public/modules/tool-palette-order.js +1 -0
  66. package/lib/public/style.css +2 -0
  67. package/lib/sdk-bridge.js +34 -11
  68. package/lib/server-cursor-sharing.js +65 -0
  69. package/lib/server-default-ai.js +265 -0
  70. package/lib/server-home-chat.js +29 -9
  71. package/lib/server-home-clay-entry.js +4 -1
  72. package/lib/server-home-debate-planning.js +32 -14
  73. package/lib/server-home-mate-creation.js +30 -11
  74. package/lib/server-home-models.js +14 -6
  75. package/lib/server-issue-links.js +18 -0
  76. package/lib/server.js +41 -0
  77. package/lib/session-notes-mcp-server.js +1 -1
  78. package/lib/session-search.js +4 -1
  79. package/lib/tool-llm.js +1 -0
  80. package/lib/users-default-ai-preferences.js +80 -0
  81. package/lib/users-preferences.js +35 -0
  82. package/lib/users.js +10 -0
  83. package/lib/workspace-query-projection.js +29 -0
  84. package/lib/workspace-query-service.js +19 -29
  85. package/lib/ws-schema.js +36 -1
  86. package/lib/yoke/adapters/claude-worker.js +4 -2
  87. package/lib/yoke/adapters/claude.js +5 -1
  88. package/lib/yoke/package.json +1 -1
  89. package/package.json +5 -6
  90. package/bin/claude-relay.js +0 -6
@@ -0,0 +1,101 @@
1
+ #issues-panel { position: relative; width: 48%; max-width: 760px; min-width: 360px; height: calc(100% - 16px); margin: 8px; align-self: center; display: flex; flex-direction: column; background: var(--bg); color: var(--text); border: 1px solid var(--border); border-radius: 12px; overflow: hidden; flex-shrink: 0; }
2
+ #issues-panel.hidden { display: none; }
3
+ #issues-panel.issues-wide { width: 70%; max-width: 1200px; }
4
+ #issues-panel.panel-fullscreen { width: 100%; max-width: none; height: 100%; margin: 0; }
5
+ #issues-panel header { height: 48px; box-sizing: border-box; display: flex; align-items: center; gap: 12px; padding: 0 16px; border-bottom: 1px solid var(--border-subtle); flex: 0 0 auto; }
6
+ #issues-panel .issues-title { display: inline-flex; align-items: center; gap: 7px; font-weight: 700; }
7
+ #issues-panel .issues-title .lucide { width: 15px; color: var(--accent); }
8
+ #issues-panel .issues-subtitle { flex: 1; color: var(--text-dimmer); font-size: 12px; }
9
+ #issues-panel .issues-window-actions { display: inline-flex; align-items: center; gap: 6px; margin-left: auto; }
10
+ #issues-panel .issues-icon-btn { width: 30px; height: 30px; display: inline-flex; align-items: center; justify-content: center; padding: 0; border-radius: 7px; background: var(--bg-alt); color: var(--text-secondary); }
11
+ #issues-panel .issues-icon-btn .lucide { width: 15px; }
12
+ #issues-panel .issues-icon-btn.hidden { display: none; }
13
+ #issues-panel .issues-icon-btn[aria-pressed="true"] { border-color: var(--accent); color: var(--accent); }
14
+ #issues-panel button, #issues-panel input, #issues-panel textarea, #issues-panel select { font: inherit; color: inherit; background: var(--bg); border: 1px solid var(--border); border-radius: 6px; padding: 8px 10px; }
15
+ #issues-panel button { cursor: pointer; }
16
+ #issues-panel button:hover { background: var(--bg-hover, rgba(128,128,128,.12)); }
17
+ #issues-panel button:disabled { opacity: .5; cursor: wait; }
18
+ #issues-panel :focus-visible { outline: 2px solid var(--accent, #b98655); outline-offset: 2px; }
19
+ .issues-filters { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; padding: 12px 14px; border-bottom: 1px solid var(--border-subtle); background: color-mix(in srgb, var(--bg-alt) 72%, transparent); }
20
+ .issues-search { flex: 1; min-width: 120px; height: 36px; display: flex; align-items: center; gap: 8px; padding: 0 10px; border: 1px solid var(--border); border-radius: 6px; background: var(--bg); color: var(--text-dimmer); }
21
+ .issues-search .lucide { width: 14px; }
22
+ #issues-panel .issues-search input { width: 100%; min-width: 0; border: 0 !important; outline: 0; background: transparent !important; padding: 0 !important; font-size: 12px; line-height: 1.6; }
23
+ #issues-panel .issues-filters select { font-size: 12px; line-height: normal; }
24
+ .issues-content { flex: 1; overflow: auto; padding: 0; min-height: 0; }
25
+ .issues-notice { margin: 0; padding: 0 16px; font-size: 12px; color: var(--text-muted); }
26
+ .issue-row { display: block; width: 100%; text-align: left; margin: 0; padding: 15px 18px 14px !important; border: 0 !important; border-bottom: 1px solid var(--border-subtle) !important; border-left: 2px solid transparent !important; border-radius: 0 !important; background: transparent !important; }
27
+ .issue-row:hover { background: color-mix(in srgb, var(--accent) 5%, transparent) !important; border-left-color: var(--accent) !important; }
28
+ .issue-row-head { display: flex; align-items: center; gap: 8px; margin-bottom: 7px; }
29
+ .issue-type { padding: 2px 7px; border-radius: 999px; background: rgba(var(--overlay-rgb), .08); color: var(--text-secondary); font-size: 10px; font-weight: 700; text-transform: uppercase; }
30
+ .issue-row strong { display: block; font-size: 14px; }
31
+ .issue-row p { margin: 7px 0 0; color: var(--text-secondary); font-size: 12.5px; line-height: 1.55; }
32
+ .issue-row small, .issue-detail small { color: var(--text-muted); }
33
+ .issue-row small { font-size: 10.5px; font-family: var(--font-mono); }
34
+ .issue-status { display: inline-flex; align-items: center; gap: 6px; font-size: 11px; letter-spacing: .03em; }
35
+ .issue-status::before { content: ''; width: 7px; height: 7px; border: 1px solid currentColor; border-radius: 50%; }
36
+ [data-status="in_progress"] { color: #bd923f; }
37
+ [data-status="resolved"] { color: #479b77; }
38
+ [data-status="closed"] { color: var(--text-muted); }
39
+ .issue-detail { max-width: 760px; margin: 0 auto; padding: 32px 28px 52px; }
40
+ .issue-detail h2 { margin: 10px 0; font-family: var(--font-display); font-size: clamp(24px, 2.8vw, 34px); line-height: 1.12; }
41
+ .issue-detail > p { font-size: 14px; line-height: 1.6; }
42
+ .issue-detail > small { font-size: 11px; font-family: var(--font-mono); }
43
+ .issue-detail .markdown-body { margin: 24px 0; }
44
+ .issue-detail .markdown-body { font-size: 14px; line-height: 1.75; }
45
+ .issue-detail section { margin-top: 24px; overflow-wrap: anywhere; }
46
+ .issue-detail h3 { font-size: 12px; color: var(--text-muted); }
47
+ #issues-panel .issue-discussion { border-top: 1px solid var(--border-subtle); }
48
+ #issues-panel .issue-comment { padding: 12px 0; border-bottom: 1px solid var(--border-subtle); }
49
+ #issues-panel .issue-comment-meta { color: var(--text-muted); font: 10.5px/1.4 var(--font-mono); }
50
+ #issues-panel .issue-comment p { margin: 6px 0 0; font-size: 13px; line-height: 1.55; white-space: pre-wrap; overflow-wrap: anywhere; }
51
+ #issues-panel .issue-comment small { display: block; margin-top: 7px; color: var(--text-dimmer); font-size: 11px; }
52
+ #issues-panel .issue-discussion-empty { color: var(--text-muted); font-size: 13px; }
53
+ #issues-panel #issue-comment-form { margin-top: 16px; }
54
+ #issues-panel #issue-comment-form label { display: block; margin-bottom: 6px; color: var(--text-muted); font-size: 11px; }
55
+ #issues-panel #issue-comment-input { width: 100%; box-sizing: border-box; min-height: 76px; resize: vertical; font-size: 13px; line-height: 1.55; }
56
+ #issues-panel .issue-comment-status { min-height: 1.4em; margin: 6px 0; color: var(--text-muted); font-size: 11px; }
57
+ #issues-panel .issues-delete-dialog { position: absolute; inset: 0; z-index: 2; display: grid; place-items: center; padding: 24px; background: rgba(0, 0, 0, .38); }
58
+ #issues-panel .issues-delete-dialog.hidden { display: none; }
59
+ #issues-panel .issues-delete-card { width: min(360px, 100%); box-sizing: border-box; padding: 22px; border: 1px solid var(--border); border-radius: 10px; background: var(--bg); box-shadow: 0 14px 40px rgba(0, 0, 0, .24); }
60
+ #issues-panel .issues-delete-card h2 { margin: 0 0 8px; font-family: var(--font-display); font-size: 18px; }
61
+ #issues-panel .issues-delete-card p { margin: 8px 0; color: var(--text-secondary); font-size: 13px; line-height: 1.5; }
62
+ #issues-panel .issues-delete-card .issues-delete-title { color: var(--text); font-weight: 700; overflow-wrap: anywhere; }
63
+ #issues-panel .issues-delete-status { min-height: 1.4em; color: var(--text-muted); font-size: 11px; }
64
+ #issues-panel .issues-delete-card > div { display: flex; justify-content: flex-end; gap: 8px; margin-top: 18px; }
65
+ .issue-actions, .issue-fields { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 16px; }
66
+ #issues-panel .issue-detail .issue-actions button { font-size: 12px; line-height: normal; }
67
+ #issue-form label { display: flex; flex-direction: column; gap: 6px; margin-bottom: 14px; font-size: 12px; }
68
+ #issue-form textarea { resize: vertical; min-height: 60px; }
69
+ #issue-form input, #issue-form textarea { width: 100%; box-sizing: border-box; }
70
+ #issues-panel [hidden] { display: none !important; }
71
+ .issues-empty { padding: 48px 12px; text-align: center; color: var(--text-muted); }
72
+ .issues-empty .lucide { width: 28px; color: var(--accent); }
73
+ .issues-empty h2 { margin: 12px 0 6px; font-family: var(--font-display); color: var(--text); }
74
+ .issues-empty p { max-width: 300px; margin: 0 auto 18px; line-height: 1.6; }
75
+ .issues-empty button { border-color: var(--accent) !important; background: var(--accent) !important; color: #fff !important; font-weight: 700; }
76
+ .issues-edit-note { margin: 0 0 18px; padding: 10px 12px; border-left: 2px solid var(--accent); background: rgba(var(--overlay-rgb), .04); color: var(--text-secondary); font-size: 12px; line-height: 1.55; }
77
+ #issues-panel #issue-form { box-sizing: border-box; padding: 8px 28px 24px; }
78
+ .issues-content > h2 { padding: 0 28px; }
79
+ .issues-content > h2 { margin: 0 0 10px; font-family: var(--font-display); font-size: 14px; line-height: 1.2; }
80
+ .issues-history-note { margin: 0; padding: 14px 18px; border-bottom: 1px solid var(--border-subtle); color: var(--text-dimmer); font-size: 11px; font-family: var(--font-mono); }
81
+ .clayos-issue-link { display: inline-flex; max-width: 100%; border: 1px solid var(--border); border-radius: 5px; background: var(--bg); color: inherit; font: inherit; font-size: .85em; padding: 2px 7px; cursor: pointer; vertical-align: baseline; overflow-wrap: anywhere; }
82
+ @media (max-width: 1023px) { #issues-panel, #issues-panel.issues-wide { position: fixed; inset: 0; z-index: 150; width: 100%; max-width: none; min-width: 0; height: 100%; margin: 0; border-radius: 0; padding-top: var(--safe-top, 0px); padding-bottom: var(--safe-bottom, 0px); box-sizing: border-box; } #issues-panel button { min-height: 36px; } }
83
+ @media (max-width: 390px) {
84
+ #issues-panel header { gap: 4px; padding: 8px; }
85
+ #issues-panel header button { padding: 7px; }
86
+ #issues-panel [data-issues-wide], #issues-panel [data-issues-full] { display: none; }
87
+ .issues-filters { display: grid; grid-template-columns: 1fr 1fr; padding: 8px; }
88
+ .issues-filters .issues-search { grid-column: 1 / -1; width: 100%; box-sizing: border-box; }
89
+ .issues-content { padding: 10px; }
90
+ .issue-row { padding: 12px !important; }
91
+ .issue-detail h2 { font-size: 20px; }
92
+ }
93
+ @media (max-width: 768px) {
94
+ #issues-panel .issues-subtitle { display: none; }
95
+ #issues-panel header { gap: 8px; padding: 0 12px; }
96
+ .issues-filters { padding: 10px 12px; }
97
+ .issue-row { padding: 14px 14px 13px !important; }
98
+ #issues-panel #issue-form { padding-right: 18px; padding-left: 18px; }
99
+ .issues-content > h2 { padding-right: 18px; padding-left: 18px; }
100
+ .issue-detail { padding: 24px 18px 38px; }
101
+ }
@@ -489,6 +489,25 @@ pre:hover .code-copy-btn { opacity: 1; }
489
489
  text-decoration: underline;
490
490
  }
491
491
 
492
+ .clay-file-link {
493
+ display: inline-flex;
494
+ align-items: center;
495
+ gap: 5px;
496
+ max-width: 100%;
497
+ padding: 2px 7px;
498
+ border: 1px solid var(--border-subtle);
499
+ border-radius: 6px;
500
+ background: rgba(var(--overlay-rgb), 0.05);
501
+ color: var(--link);
502
+ font: inherit;
503
+ cursor: pointer;
504
+ vertical-align: baseline;
505
+ }
506
+ .clay-file-link:hover, .clay-file-link:focus-visible { background: var(--accent-bg); color: var(--link-hover); }
507
+ .clay-file-link-icon { width: 14px; height: 14px; flex: 0 0 14px; }
508
+ .clay-file-link-label { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
509
+ .clay-file-link-notice { margin-top: 5px; color: var(--text-secondary); font-size: 12px; }
510
+
492
511
  .md-content ul, .md-content ol {
493
512
  padding-left: 24px;
494
513
  margin: 10px 0;
@@ -0,0 +1,187 @@
1
+ #pending-message-queue {
2
+ margin: 0 7px 8px;
3
+ padding: 8px;
4
+ border: 1px solid color-mix(in srgb, var(--border) 82%, var(--accent));
5
+ border-radius: 13px;
6
+ background: color-mix(in srgb, var(--bg-alt) 74%, transparent);
7
+ box-shadow: inset 3px 0 0 color-mix(in srgb, var(--accent) 70%, transparent);
8
+ }
9
+
10
+ #pending-message-queue.hidden { display: none; }
11
+
12
+ .pending-message-head {
13
+ display: flex;
14
+ align-items: center;
15
+ justify-content: space-between;
16
+ min-height: 24px;
17
+ padding: 0 3px 6px 8px;
18
+ }
19
+
20
+ .pending-message-eyebrow {
21
+ color: var(--text-muted);
22
+ font-size: 10px;
23
+ font-weight: 700;
24
+ letter-spacing: 0.11em;
25
+ text-transform: uppercase;
26
+ }
27
+
28
+ .pending-message-count {
29
+ display: inline-flex;
30
+ align-items: center;
31
+ justify-content: center;
32
+ min-width: 18px;
33
+ height: 18px;
34
+ margin-left: 7px;
35
+ padding: 0 5px;
36
+ border-radius: 9px;
37
+ background: rgba(var(--overlay-rgb), 0.08);
38
+ color: var(--text-secondary);
39
+ font-size: 10px;
40
+ font-weight: 700;
41
+ }
42
+
43
+ .pending-message-resume {
44
+ display: inline-flex;
45
+ align-items: center;
46
+ gap: 5px;
47
+ height: 25px;
48
+ padding: 0 9px;
49
+ border: 1px solid color-mix(in srgb, var(--accent) 50%, var(--border));
50
+ border-radius: 8px;
51
+ background: color-mix(in srgb, var(--accent) 12%, transparent);
52
+ color: var(--accent);
53
+ font: inherit;
54
+ font-size: 11px;
55
+ font-weight: 650;
56
+ cursor: pointer;
57
+ }
58
+
59
+ .pending-message-resume .lucide { width: 12px; height: 12px; fill: currentColor; }
60
+ .pending-message-resume:hover { background: color-mix(in srgb, var(--accent) 19%, transparent); }
61
+
62
+ .pending-message-list {
63
+ display: flex;
64
+ flex-direction: column;
65
+ gap: 5px;
66
+ max-height: min(230px, 28vh);
67
+ overflow-y: auto;
68
+ overscroll-behavior: contain;
69
+ scrollbar-width: thin;
70
+ }
71
+
72
+ .pending-message-chip {
73
+ display: grid;
74
+ grid-template-columns: 22px 24px minmax(0, 1fr) auto;
75
+ align-items: center;
76
+ flex: 0 0 auto;
77
+ min-height: 46px;
78
+ border: 1px solid var(--border-subtle);
79
+ border-radius: 10px;
80
+ background: color-mix(in srgb, var(--bg) 90%, var(--bg-alt));
81
+ transition: border-color 120ms ease, background 120ms ease, transform 120ms ease;
82
+ }
83
+
84
+ .pending-message-chip:hover { border-color: var(--border); }
85
+ .pending-message-chip.is-claimed { background: color-mix(in srgb, var(--accent) 5%, var(--bg)); }
86
+ .pending-message-chip.is-dragging { opacity: 0.62; transform: scale(0.992); }
87
+ .pending-message-chip.is-drop-target { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 8%, var(--bg)); }
88
+
89
+ .pending-message-number {
90
+ align-self: stretch;
91
+ display: flex;
92
+ align-items: center;
93
+ justify-content: center;
94
+ border-right: 1px solid var(--border-subtle);
95
+ color: var(--text-dimmer);
96
+ font-size: 10px;
97
+ font-variant-numeric: tabular-nums;
98
+ }
99
+
100
+ .pending-message-drag,
101
+ .pending-message-actions button {
102
+ display: inline-flex;
103
+ align-items: center;
104
+ justify-content: center;
105
+ width: 24px;
106
+ height: 28px;
107
+ padding: 0;
108
+ border: 0;
109
+ border-radius: 7px;
110
+ background: transparent;
111
+ color: var(--text-dimmer);
112
+ }
113
+
114
+ button.pending-message-drag { cursor: grab; touch-action: none; }
115
+ button.pending-message-drag:active { cursor: grabbing; }
116
+ .pending-message-drag.is-static { pointer-events: none; }
117
+ .pending-message-drag .lucide,
118
+ .pending-message-actions .lucide { width: 14px; height: 14px; }
119
+ .pending-message-chip.is-claimed .pending-message-drag .lucide { animation: spin 1.2s linear infinite; }
120
+
121
+ .pending-message-content { min-width: 0; padding: 7px 7px 7px 3px; overflow: visible; }
122
+ .pending-message-preview { overflow: hidden; color: var(--text); font-size: 12px; line-height: 1.3; text-overflow: ellipsis; white-space: nowrap; }
123
+ .pending-message-image-strip,
124
+ .pending-message-image-editor { display: flex; flex-wrap: wrap; gap: 5px; min-height: 36px; margin-top: 6px; align-items: center; }
125
+ .pending-message-image-thumb { display: inline-flex; width: 38px; height: 30px; padding: 0; overflow: hidden; border: 1px solid var(--border); border-radius: 6px; background: var(--bg); cursor: zoom-in; }
126
+ .pending-message-image-thumb img { width: 100%; height: 100%; object-fit: cover; }
127
+ .pending-message-image-item { display: inline-flex; align-items: center; gap: 3px; }
128
+ .pending-message-image-item button:not(.pending-message-image-thumb), .pending-message-add-image { border: 1px solid var(--border); border-radius: 6px; padding: 3px 5px; background: transparent; color: var(--text-secondary); font: inherit; font-size: 9px; cursor: pointer; }
129
+ .pending-message-image-item button:last-child { color: var(--error); }
130
+ .pending-message-image-reading { margin-top: 4px; color: var(--text-dimmer); font-size: 10px; }
131
+ .pending-message-image-backdrop { position: fixed; z-index: 1000; inset: 0; display: flex; align-items: center; justify-content: center; padding: 24px; background: rgba(0, 0, 0, .78); }
132
+ .pending-message-image-backdrop img { max-width: min(92vw, 1100px); max-height: 86vh; object-fit: contain; border-radius: 8px; box-shadow: 0 18px 60px rgba(0,0,0,.4); }
133
+ .pending-message-image-close { position: fixed; top: 18px; right: 18px; border: 1px solid rgba(255,255,255,.35); border-radius: 7px; padding: 6px 10px; background: rgba(0,0,0,.35); color: white; cursor: pointer; }
134
+ .pending-message-meta { display: flex; gap: 8px; margin-top: 3px; color: var(--text-dimmer); font-size: 9px; line-height: 1.2; }
135
+ .pending-message-meta span + span::before { content: "·"; margin-right: 8px; }
136
+ .pending-message-sending { color: var(--accent); font-weight: 650; }
137
+
138
+ .pending-message-actions { display: flex; align-items: center; gap: 1px; padding-right: 5px; }
139
+ .pending-message-actions button { cursor: pointer; }
140
+ .pending-message-actions button:hover { background: rgba(var(--overlay-rgb), 0.07); color: var(--text); }
141
+ .pending-message-actions button:last-child:hover { color: var(--error); }
142
+
143
+ .pending-message-editor {
144
+ display: block;
145
+ width: 100%;
146
+ min-height: 48px;
147
+ resize: vertical;
148
+ border: 1px solid var(--accent);
149
+ border-radius: 7px;
150
+ outline: 0;
151
+ padding: 6px 8px;
152
+ background: var(--bg);
153
+ color: var(--text);
154
+ font: inherit;
155
+ font-size: 12px;
156
+ line-height: 1.35;
157
+ }
158
+
159
+ .pending-message-editor:focus { box-shadow: 0 0 0 2px color-mix(in srgb, var(--accent) 16%, transparent); }
160
+ .pending-message-edit-actions { display: flex; justify-content: flex-end; gap: 5px; margin-top: 6px; }
161
+ .pending-message-edit-actions button { border: 1px solid var(--border); border-radius: 7px; padding: 4px 8px; background: transparent; color: var(--text-secondary); font: inherit; font-size: 10px; cursor: pointer; }
162
+ .pending-message-edit-actions button.is-primary { border-color: var(--accent); background: var(--accent); color: var(--accent-text, white); }
163
+ .pending-message-error,
164
+ .pending-message-banner-error { color: var(--error); font-size: 10px; line-height: 1.35; }
165
+ .pending-message-error { margin-top: 4px; }
166
+ .pending-message-banner-error { padding: 0 8px 6px; }
167
+
168
+ .pending-message-drag:focus-visible,
169
+ .pending-message-actions button:focus-visible,
170
+ .pending-message-resume:focus-visible,
171
+ .pending-message-edit-actions button:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
172
+
173
+ @media (max-width: 600px) {
174
+ #pending-message-queue { margin: 0 3px 6px; padding: 6px; border-radius: 12px; }
175
+ .pending-message-head { padding-left: 6px; }
176
+ .pending-message-list { max-height: min(196px, 24vh); }
177
+ .pending-message-chip { grid-template-columns: 20px 28px minmax(0, 1fr) auto; min-height: 44px; }
178
+ .pending-message-drag { width: 28px; height: 34px; }
179
+ .pending-message-actions button { width: 30px; height: 34px; }
180
+ .pending-message-meta { gap: 5px; }
181
+ .pending-message-meta span + span::before { margin-right: 5px; }
182
+ }
183
+
184
+ @media (prefers-reduced-motion: reduce) {
185
+ .pending-message-chip { transition: none; }
186
+ .pending-message-chip.is-claimed .pending-message-drag .lucide { animation: none; }
187
+ }
@@ -27,9 +27,8 @@
27
27
  .scheduled-tasks-create-menu.hidden { display: none; }
28
28
  .scheduled-tasks-create-menu button { width: 100%; padding: 8px 9px; border: 0; border-radius: 5px; background: transparent; color: var(--text); font: inherit; font-size: 12px; text-align: left; cursor: pointer; }
29
29
  .scheduled-tasks-create-menu button:hover, .scheduled-tasks-create-menu button:focus-visible { outline: 0; background: var(--bg-alt); }
30
- .scheduled-task-engine { display: grid; grid-template-columns: auto minmax(86px, .7fr) minmax(120px, 1.4fr) minmax(96px, .8fr); align-items: center; gap: 7px; padding: 8px 14px; border-bottom: 1px solid var(--border-subtle); background: var(--bg-alt); }
31
- .scheduled-task-engine > span { color: var(--text-dimmer); font-size: 10px; font-weight: 800; letter-spacing: .05em; text-transform: uppercase; }
32
- .scheduled-task-engine select { box-sizing: border-box; min-width: 0; height: 30px; padding: 0 26px 0 8px; border: 1px solid var(--border); border-radius: 7px; background: var(--bg); color: var(--text-secondary); font: inherit; font-size: 11px; }
30
+ .scheduled-task-default-ai { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 9px 14px; border-bottom: 1px solid var(--border-subtle); background: var(--bg-alt); color: var(--text-dimmer); font-size: 11px; }
31
+ .scheduled-task-default-ai button { border: 0; background: transparent; color: var(--accent); font: inherit; font-weight: 700; cursor: pointer; }
33
32
  .scheduled-tasks-list { flex: 1; min-height: 0; overflow-y: auto; }
34
33
  .scheduled-task-row { border-bottom: 1px solid var(--border-subtle); border-left: 2px solid transparent; }
35
34
  .scheduled-task-row:not(.paused) { border-left-color: var(--brand-green); }
@@ -120,4 +119,4 @@ label.scheduled-task-checkbox small { grid-column: 2; color: var(--text-dimmer);
120
119
  .scheduled-task-delete-confirm { display: grid; gap: 7px; padding: 13px; border: 1px solid color-mix(in srgb, var(--danger) 35%, var(--border)); border-radius: 8px; background: color-mix(in srgb, var(--danger) 5%, var(--bg)); color: var(--text); font-size: 12px; }
121
120
  .scheduled-task-delete-confirm > div { display: flex; justify-content: flex-end; gap: 7px; }
122
121
  .scheduled-tasks-empty { max-width: 330px; margin: 54px auto; padding: 20px; border-top: 1px solid var(--border); border-bottom: 1px solid var(--border); color: var(--text-dimmer); font-size: 12px; text-align: center; line-height: 1.7; }
123
- @media (max-width: 700px) { .scheduled-tasks-topbar { gap: 6px; padding: 0 8px; } .scheduled-tasks-title { font-size: 13px; } .scheduled-tasks-new { padding: 0 8px; } .scheduled-task-engine { grid-template-columns: 1fr 1fr; padding: 8px; } .scheduled-task-engine > span { grid-column: 1 / -1; } .scheduled-task-engine [data-engine="model"] { grid-column: 1 / -1; } .scheduled-task-summary { grid-template-columns: 9px minmax(0,1fr) 18px; padding: 11px 10px; } .scheduled-task-summary-meta { display: grid; gap: 2px; } .scheduled-task-detail { padding-left: 29px; padding-right: 10px; } .scheduled-task-date-time { grid-template-columns: minmax(0, 1fr) minmax(100px, .65fr); } .scheduled-task-repeat-controls { grid-template-columns: 1fr; } .scheduled-task-repeat-controls > label, .scheduled-task-repeat-controls [data-repeat-control] { grid-column: 1 / -1; } .scheduled-task-weekdays { gap: 3px; } .scheduled-task-weekdays span { min-height: 27px; } .scheduled-task-runtime-row { grid-template-areas: "role vendor vendor" ". model effort"; grid-template-columns: 88px minmax(0,1fr) minmax(96px,.72fr); } }
122
+ @media (max-width: 700px) { .scheduled-tasks-topbar { gap: 6px; padding: 0 8px; } .scheduled-tasks-title { font-size: 13px; } .scheduled-tasks-new { padding: 0 8px; } .scheduled-task-default-ai { padding: 8px; } .scheduled-task-summary { grid-template-columns: 9px minmax(0,1fr) 18px; padding: 11px 10px; } .scheduled-task-summary-meta { display: grid; gap: 2px; } .scheduled-task-detail { padding-left: 29px; padding-right: 10px; } .scheduled-task-date-time { grid-template-columns: minmax(0, 1fr) minmax(100px, .65fr); } .scheduled-task-repeat-controls { grid-template-columns: 1fr; } .scheduled-task-repeat-controls > label, .scheduled-task-repeat-controls [data-repeat-control] { grid-column: 1 / -1; } .scheduled-task-weekdays { gap: 3px; } .scheduled-task-weekdays span { min-height: 27px; } .scheduled-task-runtime-row { grid-template-areas: "role vendor vendor" ". model effort"; grid-template-columns: 88px minmax(0,1fr) minmax(96px,.72fr); } }
@@ -32,6 +32,7 @@
32
32
  </script>
33
33
  <script>if(window.navigator.standalone||window.matchMedia("(display-mode:standalone)").matches){document.documentElement.classList.add("pwa-standalone")}</script>
34
34
  <link rel="stylesheet" href="style.css?v=20260913-scheduled-tasks4">
35
+ <link rel="stylesheet" href="css/default-ai.css">
35
36
  <style>
36
37
  @media(max-width:768px){
37
38
  /* User messages: vertical stack, avatar on top, right-aligned */
@@ -57,7 +58,7 @@
57
58
  <div class="top-bar-left-pills">
58
59
  <button id="pwa-install-pill" class="top-bar-install-btn hidden" title="Open as app"><i data-lucide="download"></i> Open as app</button>
59
60
  <div id="ext-pill-wrap" class="ext-pill-wrap">
60
- <button id="ext-pill" class="top-bar-ext-btn" title="Chrome Extension"><i data-lucide="puzzle"></i> Extension</button>
61
+ <button id="ext-pill" class="top-bar-ext-btn hidden" title="Chrome Extension"><i data-lucide="puzzle"></i> Extension</button>
61
62
  <div id="ext-popover" class="ext-popover">
62
63
  <div class="ext-popover-header">
63
64
  <div class="ext-popover-title">Clay for Chrome <span class="ext-experimental">Experimental</span></div>
@@ -522,6 +523,7 @@
522
523
  <button id="new-msg-btn" class="hidden" aria-label="Scroll to bottom"></button>
523
524
  <div id="input-area">
524
525
  <div id="input-wrapper">
526
+ <section id="pending-message-queue" class="hidden" aria-label="Pending message queue" aria-live="polite"></section>
525
527
  <div id="autonomous-run-status" class="autonomous-run-status hidden" role="status">
526
528
  <button id="autonomous-run-toggle" type="button" class="autonomous-run-summary" aria-label="Show Loop details">
527
529
  <span class="autonomous-run-mark" aria-hidden="true"></span>
@@ -553,23 +555,30 @@
553
555
  </div>
554
556
  <div id="input-bottom">
555
557
  <div id="attach-wrap">
556
- <button id="input-more-btn" type="button" aria-label="More options" title="More options" class="mobile-only"><i data-lucide="plus"></i></button>
557
- <button id="attach-file-btn" type="button" aria-label="Attach file" title="Attach file" class="desktop-only"><i data-lucide="paperclip"></i></button>
558
- <button id="attach-image-btn" type="button" aria-label="Attach image" title="Attach image" class="desktop-only"><i data-lucide="image"></i></button>
559
- <button id="shell-command-btn" type="button" aria-label="Run shell command" aria-pressed="false" title="Run a shell command and add its output to the next agent message" class="desktop-only"><i data-lucide="square-terminal"></i></button>
560
- <button id="stt-btn" type="button" aria-label="Voice input" title="Voice input"><i data-lucide="mic"></i></button>
561
- <button id="schedule-btn" type="button" aria-label="Schedule message" title="Schedule message"><i data-lucide="clock"></i></button>
562
- <button id="ask-mate-btn" type="button" aria-label="Ask Mate" title="Ask a Mate for advice on this session"><i data-lucide="at-sign"></i></button>
563
- <div id="context-sources-btn-wrap" class="desktop-only">
564
- <button id="context-sources-add" type="button" aria-label="Add context" title="Add context sources"><i data-lucide="library"></i></button>
565
- <div id="context-sources-picker" class="hidden">
566
- <div class="context-picker-section" id="context-picker-email"></div>
567
- <div class="context-picker-section" id="context-picker-terminals"></div>
568
- <div class="context-picker-section" id="context-picker-tabs"></div>
558
+ <div class="composer-tool-group composer-tool-group-inputs" role="group" aria-label="Inputs and context">
559
+ <button id="input-more-btn" type="button" aria-label="More options" title="More options" class="mobile-only"><i data-lucide="plus"></i></button>
560
+ <button id="attach-file-btn" type="button" aria-label="Attach file" title="Attach file" class="desktop-only"><i data-lucide="paperclip"></i></button>
561
+ <button id="attach-image-btn" type="button" aria-label="Attach image" title="Attach image" class="desktop-only"><i data-lucide="image"></i></button>
562
+ <button id="stt-btn" type="button" aria-label="Voice input" title="Voice input"><i data-lucide="mic"></i></button>
563
+ <div id="context-sources-btn-wrap" class="desktop-only">
564
+ <button id="context-sources-add" type="button" aria-label="Add context" title="Add context sources"><i data-lucide="library"></i></button>
565
+ <div id="context-sources-picker" class="hidden">
566
+ <div class="context-picker-section" id="context-picker-email"></div>
567
+ <div class="context-picker-section" id="context-picker-terminals"></div>
568
+ <div class="context-picker-section" id="context-picker-tabs"></div>
569
+ </div>
569
570
  </div>
570
571
  </div>
571
- <button id="composer-add-worker-btn" type="button" class="composer-session-action desktop-only" aria-label="Add Split Worker" title="Add Split Worker"><i data-lucide="bot"></i></button>
572
- <button id="composer-handoff-btn" type="button" class="composer-session-action desktop-only" aria-label="Continue in another agent" title="Continue in another agent"><i data-lucide="send"></i></button>
572
+ <div class="composer-tool-group composer-tool-group-collaboration" role="group" aria-label="Collaboration">
573
+ <button id="ask-mate-btn" type="button" aria-label="Ask Mate" title="Ask a Mate for advice on this session"><i data-lucide="at-sign"></i></button>
574
+ <button id="composer-add-worker-btn" type="button" class="composer-session-action desktop-only" aria-label="Add Split Worker" title="Add Split Worker"><i data-lucide="bot"></i></button>
575
+ <button id="composer-handoff-btn" type="button" class="composer-session-action desktop-only" aria-label="Continue in another agent" title="Continue in another agent"><i data-lucide="send"></i></button>
576
+ </div>
577
+ <div class="composer-tool-group composer-tool-group-execution" role="group" aria-label="Execution">
578
+ <button id="shell-command-btn" type="button" aria-label="Run shell command" aria-pressed="false" title="Run a shell command and add its output to the next agent message" class="desktop-only"><i data-lucide="square-terminal"></i></button>
579
+ <button id="schedule-btn" type="button" aria-label="Schedule message" title="Schedule message"><i data-lucide="clock"></i></button>
580
+ <button id="loop-interview-btn" type="button" class="composer-session-action hidden" aria-label="Start Loop interview" title="Start a Loop interview with the Driver"><i data-lucide="repeat-2"></i></button>
581
+ </div>
573
582
  </div>
574
583
  <div id="input-bottom-right">
575
584
  <div id="active-vendor-indicator" class="hidden" title="Session vendor">
@@ -626,7 +635,6 @@
626
635
  </div>
627
636
  </div>
628
637
  </div>
629
- <button id="loop-interview-btn" type="button" class="composer-session-action hidden" aria-label="Start Loop interview" title="Start a Loop interview with the Driver"><i data-lucide="repeat-2"></i></button>
630
638
  <button id="send-btn" disabled aria-label="Send"><i data-lucide="arrow-up"></i></button>
631
639
  </div>
632
640
  </div>
@@ -16,6 +16,7 @@ import { requestHomeDockPreference } from './home-dock.js';
16
16
  import { resumeHomeChat } from './home-mate-chat.js';
17
17
  import { requestHomeSurfacePreference } from './home-surface.js';
18
18
  import { isHomeDebatesSurface } from './home-sub-surface.js';
19
+ import { beginDefaultAiConnection, requestDefaultAi } from './default-ai.js';
19
20
 
20
21
  var reconnectTimer = null;
21
22
  var reconnectDelay = 1000;
@@ -274,6 +275,8 @@ export function connect() {
274
275
  };
275
276
 
276
277
  onConnected();
278
+ beginDefaultAiConnection();
279
+ requestDefaultAi();
277
280
  };
278
281
 
279
282
  newWs.onclose = function (e) {
@@ -8,7 +8,6 @@ import { getMessagesEl } from './dom-refs.js';
8
8
  import { registerTooltip } from './tooltip.js';
9
9
 
10
10
  // --- Module-owned state ---
11
- var cursorSharingEnabled = localStorage.getItem("cursorSharing") !== "off";
12
11
  var remoteCursors = {}; // userId -> { el, indicator, timer, lastY, active }
13
12
  var cursorThrottleTimer = null;
14
13
  var CURSOR_THROTTLE_MS = 30;
@@ -217,7 +216,7 @@ export function initCursorToggle() {
217
216
  }
218
217
 
219
218
  function updateToggleStyle() {
220
- if (cursorSharingEnabled) {
219
+ if (store.get("cursorSharingHydrated") && store.get("cursorSharingEnabled")) {
221
220
  btn.classList.remove("off");
222
221
  btn.classList.add("on");
223
222
  registerTooltip(btn, "Cursor sharing on");
@@ -228,18 +227,21 @@ export function initCursorToggle() {
228
227
  }
229
228
  }
230
229
 
230
+ store.subscribe(function (state, prev) {
231
+ if (state.cursorSharingEnabled !== prev.cursorSharingEnabled || state.cursorSharingHydrated !== prev.cursorSharingHydrated) {
232
+ updateToggleStyle();
233
+ }
234
+ });
235
+
231
236
  updateToggleStyle();
232
237
  lucide.createIcons({ nodes: [btn] });
233
238
 
234
239
  btn.addEventListener("click", function () {
235
- cursorSharingEnabled = !cursorSharingEnabled;
236
- localStorage.setItem("cursorSharing", cursorSharingEnabled ? "on" : "off");
237
- updateToggleStyle();
240
+ if (!store.get("cursorSharingHydrated")) return;
241
+ var next = !store.get("cursorSharingEnabled");
238
242
  var ws = getWs();
239
- if (!cursorSharingEnabled && ws && ws.readyState === 1) {
240
- ws.send(JSON.stringify({ type: "cursor_leave" }));
241
- ws.send(JSON.stringify({ type: "text_select", ranges: [] }));
242
- }
243
+ if (!ws || ws.readyState !== 1) return;
244
+ ws.send(JSON.stringify({ type: "cursor_sharing_set", enabled: next, requestId: "cursor-sharing-" + Date.now() }));
243
245
  });
244
246
  }
245
247
 
@@ -384,11 +386,26 @@ export function clearRemoteCursors() {
384
386
  export function initCursors() {
385
387
  var messagesEl = getMessagesEl();
386
388
 
389
+ store.subscribe(function (state, prev) {
390
+ var disconnected = state.connected === false && prev.connected !== false;
391
+ var identityChanged = state.myUserId !== prev.myUserId;
392
+ if (disconnected || identityChanged) {
393
+ if (cursorThrottleTimer) { clearTimeout(cursorThrottleTimer); cursorThrottleTimer = null; }
394
+ if (selectionThrottleTimer) { clearTimeout(selectionThrottleTimer); selectionThrottleTimer = null; }
395
+ lastSelectionKey = "";
396
+ store.set({ cursorSharingEnabled: false, cursorSharingHydrated: false, cursorSharingAccountId: null });
397
+ if (identityChanged && state.myUserId && state.connected) {
398
+ var ws = getWs();
399
+ if (ws && ws.readyState === 1) ws.send(JSON.stringify({ type: "cursor_sharing_get", requestId: "cursor-sharing-refresh-" + Date.now() }));
400
+ }
401
+ }
402
+ });
403
+
387
404
  initCursorToggle();
388
405
 
389
406
  // Track local cursor and send to server
390
407
  messagesEl.addEventListener("mousemove", function (e) {
391
- if (!cursorSharingEnabled) return;
408
+ if (!store.get("cursorSharingHydrated") || !store.get("cursorSharingEnabled")) return;
392
409
  var ws = getWs();
393
410
  if (!ws || ws.readyState !== 1) return;
394
411
  if (cursorThrottleTimer) return;
@@ -412,7 +429,7 @@ export function initCursors() {
412
429
  });
413
430
 
414
431
  messagesEl.addEventListener("mouseleave", function () {
415
- if (!cursorSharingEnabled) return;
432
+ if (!store.get("cursorSharingHydrated") || !store.get("cursorSharingEnabled")) return;
416
433
  var ws = getWs();
417
434
  if (!ws || ws.readyState !== 1) return;
418
435
  ws.send(JSON.stringify({ type: "cursor_leave" }));
@@ -429,7 +446,7 @@ export function initCursors() {
429
446
 
430
447
  // Track local text selection and send to server
431
448
  document.addEventListener("selectionchange", function () {
432
- if (!cursorSharingEnabled) return;
449
+ if (!store.get("cursorSharingHydrated") || !store.get("cursorSharingEnabled")) return;
433
450
  var ws = getWs();
434
451
  if (!ws || ws.readyState !== 1) return;
435
452
  if (selectionThrottleTimer) return;
@@ -1,3 +1,4 @@
1
+ import { handleIssueReference } from './clay-issue-links.js';
1
2
  // Narrow pre-router for Home and Capsule protocol responses kept out of the legacy router.
2
3
 
3
4
  import { processMessage as processAppMessage } from './app-messages.js';
@@ -10,8 +11,12 @@ import { renderProjectWorkspaceAssignment, showProjectWorkspaceAssignmentError }
10
11
  import { isHomeWorkspaceAssignmentMessage } from './workspace-assignment-routing.js';
11
12
  import { handleSearchClayMessage } from './search-clay-chat.js';
12
13
  import { handleClaySessionTarget } from './command-palette.js';
14
+ import { handleDefaultAiMessage } from './default-ai.js';
15
+ import { handleCursorSharingMessage } from './cursor-sharing-preference.js';
16
+ import { handlePendingMessageQueueMessage } from './pending-message-queue.js';
13
17
 
14
18
  export function handleHomeProtocolMessage(msg) {
19
+ if (handleIssueReference(msg)) return true;
15
20
  if (handleClaySessionTarget(msg)) return true;
16
21
  if (isHomeWorkspaceAssignmentMessage(msg)) {
17
22
  handleHomeWorkspaceAssignment(msg);
@@ -77,6 +82,9 @@ export function handleHomeProtocolMessage(msg) {
77
82
  }
78
83
 
79
84
  export function processMessage(msg) {
85
+ if (handlePendingMessageQueueMessage(msg)) return;
86
+ if (handleDefaultAiMessage(msg)) return;
87
+ if (handleCursorSharingMessage(msg)) return;
80
88
  var searchHandled = handleSearchClayMessage(msg);
81
89
  if (searchHandled && (msg.type === "home_clay_activity" || msg.type === "home_mate_stopping" || msg.type.indexOf("home_mate_permission_") === 0)) return;
82
90
  if (handleHomeProtocolMessage(msg)) return;
@@ -1,3 +1,4 @@
1
+ import { handleIssuesMessageInContext as handleIssuesMessage } from './issues-context.js';
1
2
  // app-messages.js - WebSocket message router
2
3
  // Extracted from app.js (PR-23)
3
4
  // All dependencies are direct imports; no context injection needed.
@@ -27,7 +28,7 @@ import { syncPaneTitles, maybeRestoreSplitGroup, openGroup } from './split-view.
27
28
  import { showPairDialog, handlePairCreated, handleSplitDelegation, showWorkerDelegationNotice, hideWorkerDelegationNotice } from './split-pair-ui.js';
28
29
  import { handleSessionActionMessage } from './session-actions.js';
29
30
  import { renderWorkerProposal, updateWorkerProposal } from './worker-proposal.js';
30
- import { handleInputSync, autoResize, builtinCommands, setScheduleBtnDisabled, sendShellResultToAgent } from './input.js';
31
+ import { handleInputSync, autoResize, builtinCommands, setScheduleBtnDisabled, sendShellResultToAgent, handleAcceptedOrdinaryMessage } from './input.js';
31
32
  import { startThinking, appendThinking, stopThinking, resetThinkingGroup, createToolItem, updateToolExecuting, updateToolResult, markAllToolsDone, closeToolGroup, removeToolFromGroup, resetToolState, getTools, getPlanContent, setPlanContent, renderPlanBanner, renderPlanCard, getTodoTools, handleTodoWrite, handleTaskCreate, handleTaskUpdate, applyDeadSessionTodoCompaction, isPlanFilePath, enableMainInput, addTurnMeta, updateSubagentActivity, addSubagentToolEntry, markSubagentDone, initSubagentStop, updateSubagentProgress, updateSubagentTaskStatus, renderAskUserQuestion, markAskUserAnswered, renderPermissionRequest, markPermissionCancelled, markPermissionResolved, renderElicitationRequest, markElicitationResolved, renderUserDialogRequest, markUserDialogResolved, updateThinkingTokens } from './tools.js';
32
33
  import { finishThinkingTurn, resumeThinkingAfterReplay } from './thinking-lifecycle.js';
33
34
  import { showDoneNotification, playDoneSound, isNotifAlertEnabled, isNotifSoundEnabled } from './notifications.js';
@@ -93,6 +94,7 @@ var inputEl = document.getElementById("input");
93
94
  var connectOverlay = document.getElementById("connect-overlay");
94
95
 
95
96
  export function processMessage(msg) {
97
+ if (handleIssuesMessage(msg)) return;
96
98
  if (handleAutonomousRunMessage(msg)) return;
97
99
  if (handleLoopInterviewMessage(msg)) return;
98
100
  if (handleScheduledTaskMessage(msg)) return;
@@ -177,17 +179,21 @@ export function processMessage(msg) {
177
179
 
178
180
  switch (msg.type) {
179
181
  case "message_ack":
182
+ var acknowledgedEntry = acknowledgeMessage(msg.clientMessageId);
183
+ var acknowledgedContext = acknowledgedEntry && acknowledgedEntry.projectSlug === store.get('currentSlug') && String(acknowledgedEntry.sessionId) === String(store.get('activeSessionId'));
184
+ if (msg.projectSlug && msg.projectSlug !== store.get('currentSlug')) acknowledgedContext = false;
185
+ if (msg.sessionId != null && String(msg.sessionId) !== String(store.get('activeSessionId'))) acknowledgedContext = false;
180
186
  var acknowledgedEl = msg.clientMessageId
181
187
  ? messagesEl.querySelector('[data-client-message-id="' + msg.clientMessageId + '"]')
182
188
  : null;
183
- acknowledgeMessage(msg.clientMessageId);
184
- if (!acknowledgedEl && msg.message) {
189
+ if (acknowledgedContext && !acknowledgedEl && msg.message) {
185
190
  addUserMessage(msg.message.text, msg.message.images || null, msg.message.pastes || null, msg.message.from, msg.message.fromName);
186
191
  var acknowledgedUsers = messagesEl.querySelectorAll(".msg-user");
187
192
  if (acknowledgedUsers.length > 0) {
188
193
  acknowledgedUsers[acknowledgedUsers.length - 1].dataset.clientMessageId = msg.clientMessageId;
189
194
  }
190
195
  }
196
+ if (acknowledgedContext && msg.message) handleAcceptedOrdinaryMessage();
191
197
  break;
192
198
 
193
199
  case "history_meta":
@@ -915,6 +921,9 @@ export function processMessage(msg) {
915
921
 
916
922
  case "user_message":
917
923
  if (msg._internal) break;
924
+ if (msg.projectSlug && msg.projectSlug !== store.get('currentSlug')) break;
925
+ if (msg.sessionId != null && String(msg.sessionId) !== String(store.get('activeSessionId'))) break;
926
+ if (msg.clientMessageId && messagesEl.querySelector('[data-client-message-id="' + msg.clientMessageId + '"]')) break;
918
927
  if (!store.get('replayingHistory')) beginMarkdownTurn();
919
928
  resetThinkingGroup();
920
929
  if (msg.planContent) {