groove-dev 0.27.196 → 0.27.198

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 (106) hide show
  1. package/axom-integration/Screenshot_2026-07-25_at_5.25.30_PM.png +0 -0
  2. package/axom-integration/Screenshot_2026-07-25_at_5.33.26_PM.png +0 -0
  3. package/axom-integration/Screenshot_2026-07-25_at_6.11.53_PM.png +0 -0
  4. package/node_modules/@groove-dev/cli/package.json +1 -1
  5. package/node_modules/@groove-dev/daemon/package.json +1 -1
  6. package/node_modules/@groove-dev/daemon/src/api.js +5 -5
  7. package/node_modules/@groove-dev/daemon/src/axom-connector.js +340 -0
  8. package/node_modules/@groove-dev/daemon/src/axom-install.js +140 -0
  9. package/node_modules/@groove-dev/daemon/src/axom-server.js +229 -0
  10. package/node_modules/@groove-dev/daemon/src/chatstore.js +104 -0
  11. package/node_modules/@groove-dev/daemon/src/federation.js +6 -0
  12. package/node_modules/@groove-dev/daemon/src/index.js +14 -2
  13. package/node_modules/@groove-dev/daemon/src/innerchat-docs.js +8 -1
  14. package/node_modules/@groove-dev/daemon/src/innerchat-relay.js +89 -0
  15. package/node_modules/@groove-dev/daemon/src/innerchat.js +261 -1
  16. package/node_modules/@groove-dev/daemon/src/introducer.js +1 -1
  17. package/node_modules/@groove-dev/daemon/src/network-guard.js +56 -0
  18. package/node_modules/@groove-dev/daemon/src/process.js +2 -2
  19. package/node_modules/@groove-dev/daemon/src/providers/axom.js +66 -0
  20. package/node_modules/@groove-dev/daemon/src/providers/index.js +2 -0
  21. package/node_modules/@groove-dev/daemon/src/routes/agents.js +1 -175
  22. package/node_modules/@groove-dev/daemon/src/routes/axom.js +196 -0
  23. package/node_modules/@groove-dev/daemon/src/routes/chat-history.js +34 -0
  24. package/node_modules/@groove-dev/daemon/src/routes/innerchat.js +152 -20
  25. package/node_modules/@groove-dev/daemon/test/axom-connector.test.js +412 -0
  26. package/node_modules/@groove-dev/daemon/test/axom-server.test.js +187 -0
  27. package/node_modules/@groove-dev/daemon/test/chatstore.test.js +86 -0
  28. package/node_modules/@groove-dev/daemon/test/innerchat-relay.test.js +251 -0
  29. package/node_modules/@groove-dev/gui/dist/assets/index-RbtaI6l7.css +1 -0
  30. package/node_modules/@groove-dev/gui/dist/assets/index-b9dKN6cq.js +1074 -0
  31. package/node_modules/@groove-dev/gui/dist/index.html +2 -2
  32. package/node_modules/@groove-dev/gui/package.json +1 -1
  33. package/node_modules/@groove-dev/gui/src/App.jsx +2 -2
  34. package/node_modules/@groove-dev/gui/src/app.css +53 -0
  35. package/node_modules/@groove-dev/gui/src/components/agents/agent-config.jsx +2 -2
  36. package/node_modules/@groove-dev/gui/src/components/agents/spawn-wizard.jsx +3 -3
  37. package/node_modules/@groove-dev/gui/src/components/layout/activity-bar.jsx +3 -3
  38. package/node_modules/@groove-dev/gui/src/components/layout/breadcrumb-bar.jsx +1 -1
  39. package/node_modules/@groove-dev/gui/src/components/layout/command-palette.jsx +1 -1
  40. package/node_modules/@groove-dev/gui/src/stores/groove.js +24 -163
  41. package/node_modules/@groove-dev/gui/src/stores/slices/agents-slice.js +52 -2
  42. package/node_modules/@groove-dev/gui/src/stores/slices/axom-slice.js +197 -0
  43. package/node_modules/@groove-dev/gui/src/views/axom.jsx +1060 -0
  44. package/node_modules/@groove-dev/gui/src/views/marketplace.jsx +1 -1
  45. package/node_modules/@groove-dev/gui/src/views/settings.jsx +178 -64
  46. package/package.json +2 -2
  47. package/packages/cli/package.json +1 -1
  48. package/packages/daemon/package.json +1 -1
  49. package/packages/daemon/src/api.js +5 -5
  50. package/packages/daemon/src/axom-connector.js +340 -0
  51. package/packages/daemon/src/axom-install.js +140 -0
  52. package/packages/daemon/src/axom-server.js +229 -0
  53. package/packages/daemon/src/chatstore.js +104 -0
  54. package/packages/daemon/src/federation.js +6 -0
  55. package/packages/daemon/src/index.js +14 -2
  56. package/packages/daemon/src/innerchat-docs.js +8 -1
  57. package/packages/daemon/src/innerchat-relay.js +89 -0
  58. package/packages/daemon/src/innerchat.js +261 -1
  59. package/packages/daemon/src/introducer.js +1 -1
  60. package/packages/daemon/src/network-guard.js +56 -0
  61. package/packages/daemon/src/process.js +2 -2
  62. package/packages/daemon/src/providers/axom.js +66 -0
  63. package/packages/daemon/src/providers/index.js +2 -0
  64. package/packages/daemon/src/routes/agents.js +1 -175
  65. package/packages/daemon/src/routes/axom.js +196 -0
  66. package/packages/daemon/src/routes/chat-history.js +34 -0
  67. package/packages/daemon/src/routes/innerchat.js +152 -20
  68. package/packages/gui/dist/assets/index-RbtaI6l7.css +1 -0
  69. package/packages/gui/dist/assets/index-b9dKN6cq.js +1074 -0
  70. package/packages/gui/dist/index.html +2 -2
  71. package/packages/gui/package.json +1 -1
  72. package/packages/gui/src/App.jsx +2 -2
  73. package/packages/gui/src/app.css +53 -0
  74. package/packages/gui/src/components/agents/agent-config.jsx +2 -2
  75. package/packages/gui/src/components/agents/spawn-wizard.jsx +3 -3
  76. package/packages/gui/src/components/layout/activity-bar.jsx +3 -3
  77. package/packages/gui/src/components/layout/breadcrumb-bar.jsx +1 -1
  78. package/packages/gui/src/components/layout/command-palette.jsx +1 -1
  79. package/packages/gui/src/stores/groove.js +24 -163
  80. package/packages/gui/src/stores/slices/agents-slice.js +52 -2
  81. package/packages/gui/src/stores/slices/axom-slice.js +197 -0
  82. package/packages/gui/src/views/axom.jsx +1060 -0
  83. package/packages/gui/src/views/marketplace.jsx +1 -1
  84. package/packages/gui/src/views/settings.jsx +178 -64
  85. package/node_modules/@groove-dev/daemon/src/conversations.js +0 -576
  86. package/node_modules/@groove-dev/gui/dist/assets/index-Cat5pJUx.css +0 -1
  87. package/node_modules/@groove-dev/gui/dist/assets/index-L8xSnvHj.js +0 -1070
  88. package/node_modules/@groove-dev/gui/src/components/chat/chat-header.jsx +0 -198
  89. package/node_modules/@groove-dev/gui/src/components/chat/chat-input.jsx +0 -367
  90. package/node_modules/@groove-dev/gui/src/components/chat/chat-messages.jsx +0 -527
  91. package/node_modules/@groove-dev/gui/src/components/chat/chat-view.jsx +0 -212
  92. package/node_modules/@groove-dev/gui/src/components/chat/conversation-list.jsx +0 -163
  93. package/node_modules/@groove-dev/gui/src/components/chat/model-picker.jsx +0 -201
  94. package/node_modules/@groove-dev/gui/src/stores/slices/chat-slice.js +0 -227
  95. package/node_modules/@groove-dev/gui/src/views/chat.jsx +0 -6
  96. package/packages/daemon/src/conversations.js +0 -576
  97. package/packages/gui/dist/assets/index-Cat5pJUx.css +0 -1
  98. package/packages/gui/dist/assets/index-L8xSnvHj.js +0 -1070
  99. package/packages/gui/src/components/chat/chat-header.jsx +0 -198
  100. package/packages/gui/src/components/chat/chat-input.jsx +0 -367
  101. package/packages/gui/src/components/chat/chat-messages.jsx +0 -527
  102. package/packages/gui/src/components/chat/chat-view.jsx +0 -212
  103. package/packages/gui/src/components/chat/conversation-list.jsx +0 -163
  104. package/packages/gui/src/components/chat/model-picker.jsx +0 -201
  105. package/packages/gui/src/stores/slices/chat-slice.js +0 -227
  106. package/packages/gui/src/views/chat.jsx +0 -6
@@ -0,0 +1,197 @@
1
+ // FSL-1.1-Apache-2.0 — see LICENSE
2
+ //
3
+ // Axom provider state. Everything rendered from this slice is
4
+ // telemetry-grounded: interrupt/stop UI states flip on EVENTS from the
5
+ // runtime, never on our own optimism (contract §2/§7 — fail-deceptive is
6
+ // worse than fail-open).
7
+
8
+ import { api } from '../../lib/api';
9
+
10
+ const EVENT_BUFFER = 2000;
11
+
12
+ const sessionKey = (endpoint, session) => `${endpoint}/${session}`;
13
+
14
+ export const createAxomSlice = (set, get) => ({
15
+ // ── Axom Provider ─────────────────────────────────────────
16
+ axomStatus: { endpoints: [] },
17
+ axomSelected: null, // { endpoint, session }
18
+ axomEvents: {}, // sessionKey -> [envelope] (bounded)
19
+ // Local interrupt ledger: id -> {text, state}. state: 'sent' (POST accepted,
20
+ // not yet seen on the stream) | 'heard' (interrupt event arrived) |
21
+ // 'acked' (interrupt_ack arrived). Rollup states come from pipeline_done.
22
+ axomInterrupts: {}, // sessionKey -> { [id]: {text, state, truncated} }
23
+ // Stop states: null | 'pending' (POST sent, nothing effected yet) |
24
+ // 'effected' (stop_effected seen) | 'resolved-before-stop' (§7 edge:
25
+ // pipeline_done arrived with no stop_effected).
26
+ axomStops: {}, // sessionKey -> state
27
+ // Contract-violation log (§8): e.g. an interrupt_ack without interrupt_id.
28
+ // A fallback that fires must announce itself — never degrade silently.
29
+ axomAnomalies: {}, // sessionKey -> [{eventId, message}]
30
+ axomInstances: [], // managed local instances (contract §11)
31
+ axomInstall: { phase: 'idle', file: null, receivedBytes: 0, totalBytes: 0, error: null },
32
+ axomHardware: null, // machine readiness report for local inference
33
+ axomMyEndpoint: null, // this GROOVE's own Axom endpoint (share/copy)
34
+
35
+ async fetchAxomStatus() {
36
+ try {
37
+ const data = await api.get('/axom/status');
38
+ set({ axomStatus: data || { endpoints: [] } });
39
+ const instances = await api.get('/axom/instances');
40
+ set({ axomInstances: instances || [] });
41
+ } catch { /* daemon predates the axom routes */ }
42
+ },
43
+
44
+ async fetchAxomHardware() {
45
+ try {
46
+ const data = await api.get('/axom/hardware');
47
+ set({ axomHardware: data });
48
+ } catch { /* daemon predates the route */ }
49
+ try {
50
+ const me = await api.get('/axom/my-endpoint');
51
+ set({ axomMyEndpoint: me });
52
+ } catch { /* daemon predates the route */ }
53
+ },
54
+
55
+ async startAxomInstall(manifestUrl) {
56
+ await api.post('/axom/install', manifestUrl ? { manifestUrl } : {});
57
+ },
58
+
59
+ async startAxomInstance(id = 'default') {
60
+ const instance = await api.post('/axom/instances', { id });
61
+ await get().fetchAxomStatus();
62
+ return instance;
63
+ },
64
+
65
+ async stopAxomInstance(id) {
66
+ await api.delete(`/axom/instances/${encodeURIComponent(id)}`);
67
+ await get().fetchAxomStatus();
68
+ },
69
+
70
+ async saveAxomEndpoints(endpoints) {
71
+ const data = await api.patch('/axom/config', { endpoints });
72
+ await get().fetchAxomStatus();
73
+ return data;
74
+ },
75
+
76
+ async selectAxomSession(endpoint, session) {
77
+ set({ axomSelected: { endpoint, session } });
78
+ // Backfill from the daemon's ring so a freshly opened tab has history.
79
+ try {
80
+ const data = await api.get(`/axom/sessions/${encodeURIComponent(session)}/events?endpoint=${encodeURIComponent(endpoint)}`);
81
+ const key = sessionKey(endpoint, session);
82
+ set((s) => {
83
+ const existing = s.axomEvents[key] || [];
84
+ const seen = new Set(existing.map((e) => e.id));
85
+ const merged = [...(data.events || []).filter((e) => !seen.has(e.id)), ...existing]
86
+ .sort((a, b) => (a.id < b.id ? -1 : 1))
87
+ .slice(-EVENT_BUFFER);
88
+ return { axomEvents: { ...s.axomEvents, [key]: merged } };
89
+ });
90
+ } catch { /* session may have no ring yet — live events still flow */ }
91
+ },
92
+
93
+ ingestAxomEvent(endpoint, session, envelope) {
94
+ const key = sessionKey(endpoint, session);
95
+ set((s) => {
96
+ const buf = s.axomEvents[key] || [];
97
+ if (buf.length && buf[buf.length - 1].id === envelope.id) return {}; // WS echo guard
98
+ const updates = {
99
+ axomEvents: { ...s.axomEvents, [key]: [...buf, envelope].slice(-EVENT_BUFFER) },
100
+ };
101
+
102
+ // Interrupt lifecycle — driven only by what the runtime says happened.
103
+ // §8 pins interrupt_ack.payload.interrupt_id as ALWAYS present; the
104
+ // oldest-pending fallback stays as defense but surfaces as an anomaly
105
+ // when it fires — an ack without an id is a runtime bug to expose.
106
+ if (envelope.kind === 'interrupt' || envelope.kind === 'interrupt_ack') {
107
+ const ledger = { ...(s.axomInterrupts[key] || {}) };
108
+ const evId = envelope.payload?.interrupt_id ?? envelope.payload?.id;
109
+ const nextState = envelope.kind === 'interrupt' ? 'heard' : 'acked';
110
+ if (evId && ledger[evId]) {
111
+ ledger[evId] = { ...ledger[evId], state: nextState };
112
+ } else if (evId) {
113
+ // Known id, not ours — an interrupt posted by another client (e.g.
114
+ // typed straight into the REPL). Normal; it lives in the ticker,
115
+ // our ledger stays untouched.
116
+ } else {
117
+ // No id at all — a shape violation per §8. Advance the oldest
118
+ // pending entry as defense, and announce that the fallback fired.
119
+ const pending = Object.entries(ledger).find(([, v]) => v.state !== nextState && v.state !== 'acked');
120
+ if (pending) ledger[pending[0]] = { ...pending[1], state: nextState };
121
+ updates.axomAnomalies = {
122
+ ...s.axomAnomalies,
123
+ [key]: [
124
+ ...(s.axomAnomalies[key] || []),
125
+ { eventId: envelope.id, message: `${envelope.kind} arrived without an interrupt id (§8 violation)${pending ? ` — fallback advanced "${pending[1].text?.slice(0, 40)}"` : ''}` },
126
+ ].slice(-50),
127
+ };
128
+ }
129
+ updates.axomInterrupts = { ...s.axomInterrupts, [key]: ledger };
130
+ }
131
+
132
+ if (envelope.kind === 'stop_effected' && s.axomStops[key] === 'pending') {
133
+ updates.axomStops = { ...s.axomStops, [key]: 'effected' };
134
+ }
135
+ // §7 stop edge: the run can resolve before stop lands. Release the
136
+ // sticky pressed state on pipeline_done and say what actually happened.
137
+ if (envelope.kind === 'pipeline_done' && s.axomStops[key] === 'pending') {
138
+ updates.axomStops = { ...s.axomStops, [key]: 'resolved-before-stop' };
139
+ }
140
+ return updates;
141
+ });
142
+ },
143
+
144
+ // §12: message starts a turn on a caller-chosen session id (first message
145
+ // creates the session). 409 means a turn is in flight — steer instead.
146
+ async sendAxomMessage(text) {
147
+ const sel = get().axomSelected;
148
+ if (!sel) throw new Error('No Axom session selected');
149
+ try {
150
+ await api.post(`/axom/sessions/${encodeURIComponent(sel.session)}/message`, {
151
+ endpoint: sel.endpoint, text,
152
+ });
153
+ await get().fetchAxomStatus();
154
+ return { ok: true };
155
+ } catch (err) {
156
+ if (err.status === 409) return { busy: true };
157
+ if (err.status === 413) return { tooLong: true, max: err.body?.max };
158
+ throw err;
159
+ }
160
+ },
161
+
162
+ async sendAxomInterrupt(text) {
163
+ const sel = get().axomSelected;
164
+ if (!sel) throw new Error('No Axom session selected');
165
+ const result = await api.post(`/axom/sessions/${encodeURIComponent(sel.session)}/interrupt`, {
166
+ endpoint: sel.endpoint, text,
167
+ });
168
+ const key = sessionKey(sel.endpoint, sel.session);
169
+ set((s) => ({
170
+ axomInterrupts: {
171
+ ...s.axomInterrupts,
172
+ [key]: {
173
+ ...(s.axomInterrupts[key] || {}),
174
+ [result.id]: { text, state: 'sent', truncated: !!result.truncated },
175
+ },
176
+ },
177
+ }));
178
+ return result;
179
+ },
180
+
181
+ async sendAxomStop() {
182
+ const sel = get().axomSelected;
183
+ if (!sel) throw new Error('No Axom session selected');
184
+ const key = sessionKey(sel.endpoint, sel.session);
185
+ set((s) => ({ axomStops: { ...s.axomStops, [key]: 'pending' } }));
186
+ try {
187
+ return await api.post(`/axom/sessions/${encodeURIComponent(sel.session)}/stop`, { endpoint: sel.endpoint });
188
+ } catch (err) {
189
+ // The POST failed — nothing was requested, so the button must not stay
190
+ // pressed pretending it was.
191
+ set((s) => ({ axomStops: { ...s.axomStops, [key]: null } }));
192
+ throw err;
193
+ }
194
+ },
195
+ });
196
+
197
+ export { sessionKey as axomSessionKey };