@burdenoff/microfe-vibecontrols 2026.601.21 → 2026.601.22

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 (28) hide show
  1. package/dist/components/actions/ActionCard.js +77 -66
  2. package/dist/components/actions/ActionCard.js.map +1 -1
  3. package/dist/components/ai/AIContextsTab.js +186 -173
  4. package/dist/components/ai/AIContextsTab.js.map +1 -1
  5. package/dist/components/ai/AITemplatesTab.js +135 -125
  6. package/dist/components/ai/AITemplatesTab.js.map +1 -1
  7. package/dist/components/ai/InstructionFilesManager.js +151 -137
  8. package/dist/components/ai/InstructionFilesManager.js.map +1 -1
  9. package/dist/components/notes/NotesTabPanel.js +8 -8
  10. package/dist/components/sharing/EntityShareButton.js +58 -0
  11. package/dist/components/sharing/EntityShareButton.js.map +1 -0
  12. package/dist/components/sharing/entityShareOps.js +277 -0
  13. package/dist/components/sharing/entityShareOps.js.map +1 -0
  14. package/dist/components/sharing/index.js +3 -0
  15. package/dist/components/sharing/shareRegistry.js +25 -0
  16. package/dist/components/sharing/shareRegistry.js.map +1 -1
  17. package/dist/components/sharing/useEntityShareController.js +88 -0
  18. package/dist/components/sharing/useEntityShareController.js.map +1 -0
  19. package/dist/constants/permissions.js +5 -0
  20. package/dist/constants/permissions.js.map +1 -1
  21. package/dist/pages/ActionsPage.js +162 -162
  22. package/dist/pages/ActionsPage.js.map +1 -1
  23. package/dist/pages/VibeDeckPage.js +1 -1
  24. package/dist/pages/VibeDetailsPage.js +484 -484
  25. package/dist/pages/VibeDetailsPage.js.map +1 -1
  26. package/dist/pages/tunnels/TunnelDetailsPage.js +91 -77
  27. package/dist/pages/tunnels/TunnelDetailsPage.js.map +1 -1
  28. package/package.json +1 -1
@@ -1,10 +1,12 @@
1
1
  import { useCreateAgentInstructionFileMutation as e, useDeleteAgentInstructionFileMutation as t, useListAgentInstructionFilesQuery as n, useUpdateAgentInstructionFileMutation as r } from "../../generated/wspace-operations.js";
2
2
  import { InstructionFilename as i, InstructionScope as a, VibeVisibility as o } from "../../generated/wspace-types.js";
3
3
  import { LINK_TO_VIBE_DEFAULT as s, LinkToVibePanel as c } from "../shared/LinkToVibePanel.js";
4
- import { useMemo as l, useState as u } from "react";
5
- import { Fragment as d, jsx as f, jsxs as p } from "react/jsx-runtime";
4
+ import { EntityShareButton as l } from "../sharing/EntityShareButton.js";
5
+ import "../sharing/index.js";
6
+ import { useMemo as u, useState as d } from "react";
7
+ import { Fragment as f, jsx as p, jsxs as m } from "react/jsx-runtime";
6
8
  //#region src/components/ai/InstructionFilesManager.tsx
7
- var m = [
9
+ var h = [
8
10
  {
9
11
  value: i.AgentsMd,
10
12
  label: "AGENTS.md"
@@ -21,14 +23,14 @@ var m = [
21
23
  value: i.Custom,
22
24
  label: "Custom"
23
25
  }
24
- ], h = [{
26
+ ], g = [{
25
27
  value: a.Agent,
26
28
  label: "Agent"
27
29
  }, {
28
30
  value: a.Vibe,
29
31
  label: "Vibe"
30
- }], g = "w-full rounded-md border border-border-default bg-bg-surface px-3 py-2 text-sm text-text-primary", _ = "inline-flex items-center rounded-md bg-action-primary-bg px-3 py-2 text-sm font-medium text-action-primary-text hover:bg-action-primary-bg-hover disabled:opacity-50", v = "inline-flex items-center rounded-md border border-border-default bg-bg-surface px-3 py-2 text-sm font-medium text-text-primary hover:bg-bg-sunken", y = "inline-flex items-center rounded-md bg-action-danger-bg px-3 py-2 text-sm font-medium text-action-danger-text disabled:opacity-50", b = "inline-flex items-center rounded bg-bg-sunken px-2 py-0.5 text-xs text-text-secondary";
31
- function x() {
32
+ }], _ = "w-full rounded-md border border-border-default bg-bg-surface px-3 py-2 text-sm text-text-primary", v = "inline-flex items-center rounded-md bg-action-primary-bg px-3 py-2 text-sm font-medium text-action-primary-text hover:bg-action-primary-bg-hover disabled:opacity-50", y = "inline-flex items-center rounded-md border border-border-default bg-bg-surface px-3 py-2 text-sm font-medium text-text-primary hover:bg-bg-sunken", b = "inline-flex items-center rounded-md bg-action-danger-bg px-3 py-2 text-sm font-medium text-action-danger-text disabled:opacity-50", x = "inline-flex items-center rounded bg-bg-sunken px-2 py-0.5 text-xs text-text-secondary";
33
+ function S() {
32
34
  return {
33
35
  filename: i.AgentsMd,
34
36
  customName: "",
@@ -37,13 +39,13 @@ function x() {
37
39
  link: s
38
40
  };
39
41
  }
40
- function S(e) {
42
+ function C(e) {
41
43
  return e === o.SharedWithVibe ? "SHARED_WITH_VIBE" : "PRIVATE";
42
44
  }
43
- function C(e) {
45
+ function w(e) {
44
46
  return e === "SHARED_WITH_VIBE" ? o.SharedWithVibe : o.Private;
45
47
  }
46
- function w(e) {
48
+ function T(e) {
47
49
  return {
48
50
  filename: e.filename,
49
51
  customName: e.customName ?? "",
@@ -51,16 +53,16 @@ function w(e) {
51
53
  content: e.content,
52
54
  link: {
53
55
  vibeId: e.vibeId ?? null,
54
- visibility: S(e.visibility)
56
+ visibility: C(e.visibility)
55
57
  }
56
58
  };
57
59
  }
58
- function T(e) {
60
+ function E(e) {
59
61
  let t = new Date(e);
60
62
  return Number.isNaN(t.getTime()) ? e : t.toLocaleString();
61
63
  }
62
- function E({ agentId: s }) {
63
- let { data: S, loading: E, error: D } = n({
64
+ function D({ agentId: s }) {
65
+ let { data: C, loading: D, error: O } = n({
64
66
  variables: {
65
67
  filter: s ? { agentId: s } : void 0,
66
68
  pagination: {
@@ -69,261 +71,273 @@ function E({ agentId: s }) {
69
71
  }
70
72
  },
71
73
  fetchPolicy: "cache-and-network"
72
- }), [O, { loading: k }] = e({ refetchQueries: ["ListAgentInstructionFiles"] }), [A, { loading: j }] = r({ refetchQueries: ["ListAgentInstructionFiles"] }), [M, { loading: N }] = t({ refetchQueries: ["ListAgentInstructionFiles"] }), [P, F] = u(!1), [I, L] = u(null), [R, z] = u(x), [B, V] = u(null), [H, U] = u(null), W = l(() => S?.agentInstructionFiles?.items ?? [], [S?.agentInstructionFiles?.items]), G = k || j, K = () => {
73
- L(null), z(x()), U(null), F(!0);
74
- }, q = (e) => {
75
- L(e.id), z(w(e)), U(null), F(!0);
76
- }, J = () => {
77
- F(!1), L(null), z(x()), U(null);
78
- }, Y = async () => {
79
- if (U(null), R.filename === i.Custom && R.customName.trim() === "") {
80
- U("Please provide a name for the custom instruction file.");
74
+ }), [k, { loading: A }] = e({ refetchQueries: ["ListAgentInstructionFiles"] }), [j, { loading: M }] = r({ refetchQueries: ["ListAgentInstructionFiles"] }), [N, { loading: P }] = t({ refetchQueries: ["ListAgentInstructionFiles"] }), [F, I] = d(!1), [L, R] = d(null), [z, B] = d(S), [V, H] = d(null), [U, W] = d(null), G = u(() => C?.agentInstructionFiles?.items ?? [], [C?.agentInstructionFiles?.items]), K = A || M, q = () => {
75
+ R(null), B(S()), W(null), I(!0);
76
+ }, J = (e) => {
77
+ R(e.id), B(T(e)), W(null), I(!0);
78
+ }, Y = () => {
79
+ I(!1), R(null), B(S()), W(null);
80
+ }, X = async () => {
81
+ if (W(null), z.filename === i.Custom && z.customName.trim() === "") {
82
+ W("Please provide a name for the custom instruction file.");
81
83
  return;
82
84
  }
83
- if (R.content.trim() === "") {
84
- U("Instruction file content cannot be empty.");
85
+ if (z.content.trim() === "") {
86
+ W("Instruction file content cannot be empty.");
85
87
  return;
86
88
  }
87
- let e = R.filename === i.Custom ? R.customName.trim() : null;
89
+ let e = z.filename === i.Custom ? z.customName.trim() : null;
88
90
  try {
89
- if (I) await A({ variables: {
90
- id: I,
91
+ if (L) await j({ variables: {
92
+ id: L,
91
93
  input: {
92
- content: R.content,
93
- filename: R.filename,
94
+ content: z.content,
95
+ filename: z.filename,
94
96
  customName: e
95
97
  }
96
98
  } });
97
99
  else {
98
- if (R.scope === a.Vibe && !R.link.vibeId) {
99
- U("Pick a vibe to link before saving a vibe-scoped file.");
100
+ if (z.scope === a.Vibe && !z.link.vibeId) {
101
+ W("Pick a vibe to link before saving a vibe-scoped file.");
100
102
  return;
101
103
  }
102
104
  let t = {
103
- filename: R.filename,
105
+ filename: z.filename,
104
106
  customName: e,
105
- content: R.content,
106
- scope: R.scope
107
+ content: z.content,
108
+ scope: z.scope
107
109
  };
108
- R.scope === a.Vibe && R.link.vibeId ? (t.vibeId = R.link.vibeId, t.visibility = C(R.link.visibility)) : t.agentId = s ?? null, await O({ variables: { input: t } });
110
+ z.scope === a.Vibe && z.link.vibeId ? (t.vibeId = z.link.vibeId, t.visibility = w(z.link.visibility)) : t.agentId = s ?? null, await k({ variables: { input: t } });
109
111
  }
110
- J();
112
+ Y();
111
113
  } catch (e) {
112
- U(e instanceof Error ? e.message : "Failed to save the instruction file.");
114
+ W(e instanceof Error ? e.message : "Failed to save the instruction file.");
113
115
  }
114
- }, X = async (e) => {
116
+ }, Z = async (e) => {
115
117
  try {
116
- await M({ variables: { id: e } });
118
+ await N({ variables: { id: e } });
117
119
  } finally {
118
- V(null);
120
+ H(null);
119
121
  }
120
122
  };
121
- return /* @__PURE__ */ p("section", {
123
+ return /* @__PURE__ */ m("section", {
122
124
  "data-testid": "instruction-files-manager",
123
125
  className: "space-y-4 rounded-lg border border-border-default bg-bg-surface p-4",
124
126
  children: [
125
- /* @__PURE__ */ p("header", {
127
+ /* @__PURE__ */ m("header", {
126
128
  className: "flex flex-wrap items-start justify-between gap-3",
127
- children: [/* @__PURE__ */ p("div", {
129
+ children: [/* @__PURE__ */ m("div", {
128
130
  className: "space-y-1",
129
- children: [/* @__PURE__ */ f("h2", {
131
+ children: [/* @__PURE__ */ p("h2", {
130
132
  className: "text-lg font-semibold text-text-primary",
131
133
  children: "Instruction files"
132
- }), /* @__PURE__ */ f("p", {
134
+ }), /* @__PURE__ */ p("p", {
133
135
  className: "max-w-2xl text-sm text-text-secondary",
134
136
  children: "AGENTS.md / CLAUDE.md / GEMINI.md maintained centrally and pushed to your agent on chat open."
135
137
  })]
136
- }), /* @__PURE__ */ f("button", {
138
+ }), /* @__PURE__ */ p("button", {
137
139
  type: "button",
138
140
  "data-testid": "instruction-file-new",
139
- className: _,
140
- onClick: P && !I ? J : K,
141
- children: P && !I ? "Close" : "New file"
141
+ className: v,
142
+ onClick: F && !L ? Y : q,
143
+ children: F && !L ? "Close" : "New file"
142
144
  })]
143
145
  }),
144
- P && /* @__PURE__ */ p("div", {
146
+ F && /* @__PURE__ */ m("div", {
145
147
  className: "space-y-4 rounded-md border border-border-default bg-bg-elevated p-4",
146
148
  children: [
147
- /* @__PURE__ */ f("h3", {
149
+ /* @__PURE__ */ p("h3", {
148
150
  className: "text-sm font-medium text-text-primary",
149
- children: I ? "Edit instruction file" : "New instruction file"
151
+ children: L ? "Edit instruction file" : "New instruction file"
150
152
  }),
151
- /* @__PURE__ */ p("div", {
153
+ /* @__PURE__ */ m("div", {
152
154
  className: "grid gap-4 sm:grid-cols-2",
153
- children: [/* @__PURE__ */ p("label", {
155
+ children: [/* @__PURE__ */ m("label", {
154
156
  className: "space-y-1.5",
155
- children: [/* @__PURE__ */ f("span", {
157
+ children: [/* @__PURE__ */ p("span", {
156
158
  className: "block text-sm font-medium text-text-secondary",
157
159
  children: "Filename"
158
- }), /* @__PURE__ */ f("select", {
159
- className: g,
160
- value: R.filename,
161
- onChange: (e) => z((t) => ({
160
+ }), /* @__PURE__ */ p("select", {
161
+ className: _,
162
+ value: z.filename,
163
+ onChange: (e) => B((t) => ({
162
164
  ...t,
163
165
  filename: e.target.value
164
166
  })),
165
- children: m.map((e) => /* @__PURE__ */ f("option", {
167
+ children: h.map((e) => /* @__PURE__ */ p("option", {
166
168
  value: e.value,
167
169
  children: e.label
168
170
  }, e.value))
169
171
  })]
170
- }), /* @__PURE__ */ p("label", {
172
+ }), /* @__PURE__ */ m("label", {
171
173
  className: "space-y-1.5",
172
- children: [/* @__PURE__ */ f("span", {
174
+ children: [/* @__PURE__ */ p("span", {
173
175
  className: "block text-sm font-medium text-text-secondary",
174
176
  children: "Scope"
175
- }), /* @__PURE__ */ f("select", {
176
- className: g,
177
- value: R.scope,
178
- disabled: I !== null,
179
- onChange: (e) => z((t) => ({
177
+ }), /* @__PURE__ */ p("select", {
178
+ className: _,
179
+ value: z.scope,
180
+ disabled: L !== null,
181
+ onChange: (e) => B((t) => ({
180
182
  ...t,
181
183
  scope: e.target.value
182
184
  })),
183
- children: h.map((e) => /* @__PURE__ */ f("option", {
185
+ children: g.map((e) => /* @__PURE__ */ p("option", {
184
186
  value: e.value,
185
187
  children: e.label
186
188
  }, e.value))
187
189
  })]
188
190
  })]
189
191
  }),
190
- R.filename === i.Custom && /* @__PURE__ */ p("label", {
192
+ z.filename === i.Custom && /* @__PURE__ */ m("label", {
191
193
  className: "space-y-1.5",
192
- children: [/* @__PURE__ */ f("span", {
194
+ children: [/* @__PURE__ */ p("span", {
193
195
  className: "block text-sm font-medium text-text-secondary",
194
196
  children: "Custom name"
195
- }), /* @__PURE__ */ f("input", {
197
+ }), /* @__PURE__ */ p("input", {
196
198
  type: "text",
197
- className: g,
199
+ className: _,
198
200
  placeholder: "e.g. CONTRIBUTING.md",
199
- value: R.customName,
200
- onChange: (e) => z((t) => ({
201
+ value: z.customName,
202
+ onChange: (e) => B((t) => ({
201
203
  ...t,
202
204
  customName: e.target.value
203
205
  }))
204
206
  })]
205
207
  }),
206
- !I && R.scope === a.Vibe && /* @__PURE__ */ f(c, {
207
- value: R.link,
208
- onChange: (e) => z((t) => ({
208
+ !L && z.scope === a.Vibe && /* @__PURE__ */ p(c, {
209
+ value: z.link,
210
+ onChange: (e) => B((t) => ({
209
211
  ...t,
210
212
  link: e
211
213
  })),
212
- disabled: G
214
+ disabled: K
213
215
  }),
214
- /* @__PURE__ */ p("label", {
216
+ /* @__PURE__ */ m("label", {
215
217
  className: "space-y-1.5",
216
- children: [/* @__PURE__ */ f("span", {
218
+ children: [/* @__PURE__ */ p("span", {
217
219
  className: "block text-sm font-medium text-text-secondary",
218
220
  children: "Content"
219
- }), /* @__PURE__ */ f("textarea", {
220
- className: `${g} min-h-56 font-mono`,
221
+ }), /* @__PURE__ */ p("textarea", {
222
+ className: `${_} min-h-56 font-mono`,
221
223
  placeholder: "# Project instructions…",
222
- value: R.content,
223
- onChange: (e) => z((t) => ({
224
+ value: z.content,
225
+ onChange: (e) => B((t) => ({
224
226
  ...t,
225
227
  content: e.target.value
226
228
  }))
227
229
  })]
228
230
  }),
229
- H && /* @__PURE__ */ f("p", {
231
+ U && /* @__PURE__ */ p("p", {
230
232
  className: "text-sm text-action-danger-text",
231
233
  role: "alert",
232
- children: H
234
+ children: U
233
235
  }),
234
- /* @__PURE__ */ p("div", {
236
+ /* @__PURE__ */ m("div", {
235
237
  className: "flex items-center gap-2",
236
- children: [/* @__PURE__ */ f("button", {
238
+ children: [/* @__PURE__ */ p("button", {
237
239
  type: "button",
238
240
  "data-testid": "instruction-file-save",
239
- className: _,
240
- disabled: G,
241
+ className: v,
242
+ disabled: K,
241
243
  onClick: () => {
242
- Y();
244
+ X();
243
245
  },
244
- children: G ? "Saving…" : "Save"
245
- }), /* @__PURE__ */ f("button", {
246
+ children: K ? "Saving…" : "Save"
247
+ }), /* @__PURE__ */ p("button", {
246
248
  type: "button",
247
- className: v,
248
- disabled: G,
249
- onClick: J,
249
+ className: y,
250
+ disabled: K,
251
+ onClick: Y,
250
252
  children: "Cancel"
251
253
  })]
252
254
  })
253
255
  ]
254
256
  }),
255
- D ? /* @__PURE__ */ p("p", {
257
+ O ? /* @__PURE__ */ m("p", {
256
258
  className: "rounded-md border border-border-default bg-bg-sunken p-4 text-sm text-action-danger-text",
257
- children: ["Could not load instruction files: ", D.message]
258
- }) : E && W.length === 0 ? /* @__PURE__ */ f("p", {
259
+ children: ["Could not load instruction files: ", O.message]
260
+ }) : D && G.length === 0 ? /* @__PURE__ */ p("p", {
259
261
  className: "rounded-md border border-border-default bg-bg-sunken p-4 text-sm text-text-secondary",
260
262
  children: "Loading instruction files…"
261
- }) : W.length === 0 ? /* @__PURE__ */ f("p", {
263
+ }) : G.length === 0 ? /* @__PURE__ */ p("p", {
262
264
  className: "rounded-md border border-border-default bg-bg-sunken p-4 text-sm text-text-secondary",
263
265
  children: "No instruction files yet. Create one to share it with your agent."
264
- }) : /* @__PURE__ */ f("ul", {
266
+ }) : /* @__PURE__ */ p("ul", {
265
267
  className: "space-y-2",
266
- children: W.map((e) => {
267
- let t = B === e.id, n = e.visibility === o.SharedWithVibe, r = e.scope === a.Vibe ? "Vibe" : "Agent";
268
- return /* @__PURE__ */ p("li", {
268
+ children: G.map((e) => {
269
+ let t = V === e.id, n = e.visibility === o.SharedWithVibe, r = e.scope === a.Vibe ? "Vibe" : "Agent";
270
+ return /* @__PURE__ */ m("li", {
269
271
  "data-testid": "instruction-file-row",
270
272
  className: "flex flex-wrap items-center justify-between gap-3 rounded-md border border-border-default bg-bg-elevated p-3",
271
- children: [/* @__PURE__ */ p("div", {
273
+ children: [/* @__PURE__ */ m("div", {
272
274
  className: "min-w-0 space-y-1",
273
- children: [/* @__PURE__ */ p("div", {
275
+ children: [/* @__PURE__ */ m("div", {
274
276
  className: "flex flex-wrap items-center gap-2",
275
277
  children: [
276
- /* @__PURE__ */ f("span", {
278
+ /* @__PURE__ */ p("span", {
277
279
  className: "font-mono text-sm font-bold text-text-primary",
278
280
  children: e.effectiveFilename
279
281
  }),
280
- /* @__PURE__ */ f("span", {
281
- className: b,
282
+ /* @__PURE__ */ p("span", {
283
+ className: x,
282
284
  children: r
283
285
  }),
284
- /* @__PURE__ */ f("span", {
285
- className: b,
286
+ /* @__PURE__ */ p("span", {
287
+ className: x,
286
288
  children: n ? "Shared" : "Private"
287
289
  })
288
290
  ]
289
- }), /* @__PURE__ */ p("p", {
291
+ }), /* @__PURE__ */ m("p", {
290
292
  className: "text-xs text-text-tertiary",
291
- children: ["Updated ", T(e.updatedAt)]
293
+ children: ["Updated ", E(e.updatedAt)]
292
294
  })]
293
- }), /* @__PURE__ */ f("div", {
295
+ }), /* @__PURE__ */ p("div", {
294
296
  className: "flex items-center gap-2",
295
- children: t ? /* @__PURE__ */ p(d, { children: [
296
- /* @__PURE__ */ f("span", {
297
+ children: t ? /* @__PURE__ */ m(f, { children: [
298
+ /* @__PURE__ */ p("span", {
297
299
  className: "text-xs text-text-secondary",
298
300
  children: "Delete this file?"
299
301
  }),
300
- /* @__PURE__ */ f("button", {
302
+ /* @__PURE__ */ p("button", {
301
303
  type: "button",
302
- className: y,
303
- disabled: N,
304
+ className: b,
305
+ disabled: P,
304
306
  onClick: () => {
305
- X(e.id);
307
+ Z(e.id);
306
308
  },
307
- children: N ? "Deleting…" : "Confirm"
309
+ children: P ? "Deleting…" : "Confirm"
308
310
  }),
309
- /* @__PURE__ */ f("button", {
311
+ /* @__PURE__ */ p("button", {
310
312
  type: "button",
311
- className: v,
312
- disabled: N,
313
- onClick: () => V(null),
313
+ className: y,
314
+ disabled: P,
315
+ onClick: () => H(null),
314
316
  children: "Cancel"
315
317
  })
316
- ] }) : /* @__PURE__ */ p(d, { children: [/* @__PURE__ */ f("button", {
317
- type: "button",
318
- className: v,
319
- onClick: () => q(e),
320
- children: "Edit"
321
- }), /* @__PURE__ */ f("button", {
322
- type: "button",
323
- className: y,
324
- onClick: () => V(e.id),
325
- children: "Delete"
326
- })] })
318
+ ] }) : /* @__PURE__ */ m(f, { children: [
319
+ /* @__PURE__ */ p("button", {
320
+ type: "button",
321
+ className: y,
322
+ onClick: () => J(e),
323
+ children: "Edit"
324
+ }),
325
+ /* @__PURE__ */ p(l, {
326
+ entity: "instructionfile",
327
+ resource: {
328
+ id: e.id,
329
+ name: e.effectiveFilename,
330
+ vibeId: e.vibeId ?? null
331
+ },
332
+ label: "Share"
333
+ }),
334
+ /* @__PURE__ */ p("button", {
335
+ type: "button",
336
+ className: b,
337
+ onClick: () => H(e.id),
338
+ children: "Delete"
339
+ })
340
+ ] })
327
341
  })]
328
342
  }, e.id);
329
343
  })
@@ -332,6 +346,6 @@ function E({ agentId: s }) {
332
346
  });
333
347
  }
334
348
  //#endregion
335
- export { E as InstructionFilesManager };
349
+ export { D as InstructionFilesManager };
336
350
 
337
351
  //# sourceMappingURL=InstructionFilesManager.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"InstructionFilesManager.js","names":[],"sources":["../../../src/components/ai/InstructionFilesManager.tsx"],"sourcesContent":["import { useMemo, useState } from 'react';\nimport {\n useListAgentInstructionFilesQuery,\n useCreateAgentInstructionFileMutation,\n useUpdateAgentInstructionFileMutation,\n useDeleteAgentInstructionFileMutation,\n} from '@/generated/wspace-operations';\nimport {\n InstructionFilename,\n InstructionScope,\n VibeVisibility,\n type CreateAgentInstructionFileInput,\n type UpdateAgentInstructionFileInput,\n} from '@/generated/wspace-types';\nimport {\n LinkToVibePanel,\n LINK_TO_VIBE_DEFAULT,\n type LinkToVibeValue,\n type LinkToVibeVisibility,\n} from '@/components/shared/LinkToVibePanel';\n\n/**\n * Shape of a single instruction file as returned by ListAgentInstructionFiles.\n * Mirrors the InstructionFileFields fragment in wspace-operations.\n */\ninterface InstructionFile {\n id: string;\n workspaceId: string;\n filename: InstructionFilename;\n customName?: string | null;\n effectiveFilename: string;\n content: string;\n scope: InstructionScope;\n agentId?: string | null;\n tags: string[];\n vibeId?: string | null;\n visibility: VibeVisibility;\n createdBy: string;\n createdAt: string;\n updatedAt: string;\n}\n\ninterface InstructionFilesManagerProps {\n /** Default AGENT-scope target for newly-created files. */\n agentId?: string | null;\n}\n\nconst FILENAME_OPTIONS: ReadonlyArray<{ value: InstructionFilename; label: string }> = [\n { value: InstructionFilename.AgentsMd, label: 'AGENTS.md' },\n { value: InstructionFilename.ClaudeMd, label: 'CLAUDE.md' },\n { value: InstructionFilename.GeminiMd, label: 'GEMINI.md' },\n { value: InstructionFilename.Custom, label: 'Custom' },\n];\n\nconst SCOPE_OPTIONS: ReadonlyArray<{ value: InstructionScope; label: string }> = [\n { value: InstructionScope.Agent, label: 'Agent' },\n { value: InstructionScope.Vibe, label: 'Vibe' },\n];\n\nconst INPUT_CLASS =\n 'w-full rounded-md border border-border-default bg-bg-surface px-3 py-2 text-sm text-text-primary';\n\nconst PRIMARY_BTN_CLASS =\n 'inline-flex items-center rounded-md bg-action-primary-bg px-3 py-2 text-sm font-medium text-action-primary-text hover:bg-action-primary-bg-hover disabled:opacity-50';\n\nconst SECONDARY_BTN_CLASS =\n 'inline-flex items-center rounded-md border border-border-default bg-bg-surface px-3 py-2 text-sm font-medium text-text-primary hover:bg-bg-sunken';\n\nconst DANGER_BTN_CLASS =\n 'inline-flex items-center rounded-md bg-action-danger-bg px-3 py-2 text-sm font-medium text-action-danger-text disabled:opacity-50';\n\nconst BADGE_CLASS =\n 'inline-flex items-center rounded bg-bg-sunken px-2 py-0.5 text-xs text-text-secondary';\n\n/** Internal state for the create/edit form. */\ninterface FormState {\n filename: InstructionFilename;\n customName: string;\n scope: InstructionScope;\n content: string;\n link: LinkToVibeValue;\n}\n\nfunction emptyFormState(): FormState {\n return {\n filename: InstructionFilename.AgentsMd,\n customName: '',\n scope: InstructionScope.Agent,\n content: '',\n link: LINK_TO_VIBE_DEFAULT,\n };\n}\n\n/** Map the file's stored visibility enum onto the LinkToVibePanel string union. */\nfunction toLinkVisibility(visibility: VibeVisibility): LinkToVibeVisibility {\n return visibility === VibeVisibility.SharedWithVibe ? 'SHARED_WITH_VIBE' : 'PRIVATE';\n}\n\n/** Map the LinkToVibePanel string union back onto the generated enum. */\nfunction toVibeVisibility(visibility: LinkToVibeVisibility): VibeVisibility {\n return visibility === 'SHARED_WITH_VIBE' ? VibeVisibility.SharedWithVibe : VibeVisibility.Private;\n}\n\nfunction formStateFromFile(file: InstructionFile): FormState {\n return {\n filename: file.filename,\n customName: file.customName ?? '',\n scope: file.scope,\n content: file.content,\n link: {\n vibeId: file.vibeId ?? null,\n visibility: toLinkVisibility(file.visibility),\n },\n };\n}\n\nfunction formatTimestamp(value: string): string {\n const parsed = new Date(value);\n if (Number.isNaN(parsed.getTime())) {\n return value;\n }\n return parsed.toLocaleString();\n}\n\nexport function InstructionFilesManager({\n agentId,\n}: InstructionFilesManagerProps): React.ReactElement {\n const { data, loading, error } = useListAgentInstructionFilesQuery({\n variables: {\n filter: agentId ? { agentId } : undefined,\n pagination: { limit: 100, offset: 0 },\n },\n fetchPolicy: 'cache-and-network',\n });\n\n const [createFile, { loading: creating }] = useCreateAgentInstructionFileMutation({\n refetchQueries: ['ListAgentInstructionFiles'],\n });\n const [updateFile, { loading: updating }] = useUpdateAgentInstructionFileMutation({\n refetchQueries: ['ListAgentInstructionFiles'],\n });\n const [deleteFile, { loading: deleting }] = useDeleteAgentInstructionFileMutation({\n refetchQueries: ['ListAgentInstructionFiles'],\n });\n\n const [formOpen, setFormOpen] = useState(false);\n const [editingId, setEditingId] = useState<string | null>(null);\n const [form, setForm] = useState<FormState>(emptyFormState);\n const [confirmDeleteId, setConfirmDeleteId] = useState<string | null>(null);\n const [formError, setFormError] = useState<string | null>(null);\n\n const items = useMemo<InstructionFile[]>(\n () => data?.agentInstructionFiles?.items ?? [],\n [data?.agentInstructionFiles?.items]\n );\n\n const submitting = creating || updating;\n\n const openCreateForm = (): void => {\n setEditingId(null);\n setForm(emptyFormState());\n setFormError(null);\n setFormOpen(true);\n };\n\n const openEditForm = (file: InstructionFile): void => {\n setEditingId(file.id);\n setForm(formStateFromFile(file));\n setFormError(null);\n setFormOpen(true);\n };\n\n const closeForm = (): void => {\n setFormOpen(false);\n setEditingId(null);\n setForm(emptyFormState());\n setFormError(null);\n };\n\n const handleSubmit = async (): Promise<void> => {\n setFormError(null);\n\n if (form.filename === InstructionFilename.Custom && form.customName.trim() === '') {\n setFormError('Please provide a name for the custom instruction file.');\n return;\n }\n if (form.content.trim() === '') {\n setFormError('Instruction file content cannot be empty.');\n return;\n }\n\n const customName = form.filename === InstructionFilename.Custom ? form.customName.trim() : null;\n\n try {\n if (editingId) {\n // On edit only content / filename / customName / tags are updatable.\n const input: UpdateAgentInstructionFileInput = {\n content: form.content,\n filename: form.filename,\n customName,\n };\n await updateFile({ variables: { id: editingId, input } });\n } else {\n if (form.scope === InstructionScope.Vibe && !form.link.vibeId) {\n setFormError('Pick a vibe to link before saving a vibe-scoped file.');\n return;\n }\n\n const input: CreateAgentInstructionFileInput = {\n filename: form.filename,\n customName,\n content: form.content,\n scope: form.scope,\n };\n\n if (form.scope === InstructionScope.Vibe && form.link.vibeId) {\n input.vibeId = form.link.vibeId;\n input.visibility = toVibeVisibility(form.link.visibility);\n } else {\n input.agentId = agentId ?? null;\n }\n\n await createFile({ variables: { input } });\n }\n closeForm();\n } catch (submitErr) {\n setFormError(\n submitErr instanceof Error ? submitErr.message : 'Failed to save the instruction file.'\n );\n }\n };\n\n const handleDelete = async (id: string): Promise<void> => {\n try {\n await deleteFile({ variables: { id } });\n } finally {\n setConfirmDeleteId(null);\n }\n };\n\n return (\n <section\n data-testid=\"instruction-files-manager\"\n className=\"space-y-4 rounded-lg border border-border-default bg-bg-surface p-4\"\n >\n <header className=\"flex flex-wrap items-start justify-between gap-3\">\n <div className=\"space-y-1\">\n <h2 className=\"text-lg font-semibold text-text-primary\">Instruction files</h2>\n <p className=\"max-w-2xl text-sm text-text-secondary\">\n AGENTS.md / CLAUDE.md / GEMINI.md maintained centrally and pushed to your agent on chat\n open.\n </p>\n </div>\n <button\n type=\"button\"\n data-testid=\"instruction-file-new\"\n className={PRIMARY_BTN_CLASS}\n onClick={formOpen && !editingId ? closeForm : openCreateForm}\n >\n {formOpen && !editingId ? 'Close' : 'New file'}\n </button>\n </header>\n\n {formOpen && (\n <div className=\"space-y-4 rounded-md border border-border-default bg-bg-elevated p-4\">\n <h3 className=\"text-sm font-medium text-text-primary\">\n {editingId ? 'Edit instruction file' : 'New instruction file'}\n </h3>\n\n <div className=\"grid gap-4 sm:grid-cols-2\">\n <label className=\"space-y-1.5\">\n <span className=\"block text-sm font-medium text-text-secondary\">Filename</span>\n <select\n className={INPUT_CLASS}\n value={form.filename}\n onChange={(e) =>\n setForm((prev) => ({\n ...prev,\n filename: e.target.value as InstructionFilename,\n }))\n }\n >\n {FILENAME_OPTIONS.map((opt) => (\n <option key={opt.value} value={opt.value}>\n {opt.label}\n </option>\n ))}\n </select>\n </label>\n\n <label className=\"space-y-1.5\">\n <span className=\"block text-sm font-medium text-text-secondary\">Scope</span>\n <select\n className={INPUT_CLASS}\n value={form.scope}\n disabled={editingId !== null}\n onChange={(e) =>\n setForm((prev) => ({\n ...prev,\n scope: e.target.value as InstructionScope,\n }))\n }\n >\n {SCOPE_OPTIONS.map((opt) => (\n <option key={opt.value} value={opt.value}>\n {opt.label}\n </option>\n ))}\n </select>\n </label>\n </div>\n\n {form.filename === InstructionFilename.Custom && (\n <label className=\"space-y-1.5\">\n <span className=\"block text-sm font-medium text-text-secondary\">Custom name</span>\n <input\n type=\"text\"\n className={INPUT_CLASS}\n placeholder=\"e.g. CONTRIBUTING.md\"\n value={form.customName}\n onChange={(e) => setForm((prev) => ({ ...prev, customName: e.target.value }))}\n />\n </label>\n )}\n\n {!editingId && form.scope === InstructionScope.Vibe && (\n <LinkToVibePanel\n value={form.link}\n onChange={(link) => setForm((prev) => ({ ...prev, link }))}\n disabled={submitting}\n />\n )}\n\n <label className=\"space-y-1.5\">\n <span className=\"block text-sm font-medium text-text-secondary\">Content</span>\n <textarea\n className={`${INPUT_CLASS} min-h-56 font-mono`}\n placeholder=\"# Project instructions…\"\n value={form.content}\n onChange={(e) => setForm((prev) => ({ ...prev, content: e.target.value }))}\n />\n </label>\n\n {formError && (\n <p className=\"text-sm text-action-danger-text\" role=\"alert\">\n {formError}\n </p>\n )}\n\n <div className=\"flex items-center gap-2\">\n <button\n type=\"button\"\n data-testid=\"instruction-file-save\"\n className={PRIMARY_BTN_CLASS}\n disabled={submitting}\n onClick={() => {\n void handleSubmit();\n }}\n >\n {submitting ? 'Saving…' : 'Save'}\n </button>\n <button\n type=\"button\"\n className={SECONDARY_BTN_CLASS}\n disabled={submitting}\n onClick={closeForm}\n >\n Cancel\n </button>\n </div>\n </div>\n )}\n\n {error ? (\n <p className=\"rounded-md border border-border-default bg-bg-sunken p-4 text-sm text-action-danger-text\">\n Could not load instruction files: {error.message}\n </p>\n ) : loading && items.length === 0 ? (\n <p className=\"rounded-md border border-border-default bg-bg-sunken p-4 text-sm text-text-secondary\">\n Loading instruction files…\n </p>\n ) : items.length === 0 ? (\n <p className=\"rounded-md border border-border-default bg-bg-sunken p-4 text-sm text-text-secondary\">\n No instruction files yet. Create one to share it with your agent.\n </p>\n ) : (\n <ul className=\"space-y-2\">\n {items.map((file) => {\n const isConfirming = confirmDeleteId === file.id;\n const isShared = file.visibility === VibeVisibility.SharedWithVibe;\n const scopeLabel = file.scope === InstructionScope.Vibe ? 'Vibe' : 'Agent';\n return (\n <li\n key={file.id}\n data-testid=\"instruction-file-row\"\n className=\"flex flex-wrap items-center justify-between gap-3 rounded-md border border-border-default bg-bg-elevated p-3\"\n >\n <div className=\"min-w-0 space-y-1\">\n <div className=\"flex flex-wrap items-center gap-2\">\n <span className=\"font-mono text-sm font-bold text-text-primary\">\n {file.effectiveFilename}\n </span>\n <span className={BADGE_CLASS}>{scopeLabel}</span>\n <span className={BADGE_CLASS}>{isShared ? 'Shared' : 'Private'}</span>\n </div>\n <p className=\"text-xs text-text-tertiary\">\n Updated {formatTimestamp(file.updatedAt)}\n </p>\n </div>\n\n <div className=\"flex items-center gap-2\">\n {isConfirming ? (\n <>\n <span className=\"text-xs text-text-secondary\">Delete this file?</span>\n <button\n type=\"button\"\n className={DANGER_BTN_CLASS}\n disabled={deleting}\n onClick={() => {\n void handleDelete(file.id);\n }}\n >\n {deleting ? 'Deleting…' : 'Confirm'}\n </button>\n <button\n type=\"button\"\n className={SECONDARY_BTN_CLASS}\n disabled={deleting}\n onClick={() => setConfirmDeleteId(null)}\n >\n Cancel\n </button>\n </>\n ) : (\n <>\n <button\n type=\"button\"\n className={SECONDARY_BTN_CLASS}\n onClick={() => openEditForm(file)}\n >\n Edit\n </button>\n <button\n type=\"button\"\n className={DANGER_BTN_CLASS}\n onClick={() => setConfirmDeleteId(file.id)}\n >\n Delete\n </button>\n </>\n )}\n </div>\n </li>\n );\n })}\n </ul>\n )}\n </section>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"InstructionFilesManager.js","names":[],"sources":["../../../src/components/ai/InstructionFilesManager.tsx"],"sourcesContent":["import { useMemo, useState } from 'react';\nimport {\n useListAgentInstructionFilesQuery,\n useCreateAgentInstructionFileMutation,\n useUpdateAgentInstructionFileMutation,\n useDeleteAgentInstructionFileMutation,\n} from '@/generated/wspace-operations';\nimport {\n InstructionFilename,\n InstructionScope,\n VibeVisibility,\n type CreateAgentInstructionFileInput,\n type UpdateAgentInstructionFileInput,\n} from '@/generated/wspace-types';\nimport {\n LinkToVibePanel,\n LINK_TO_VIBE_DEFAULT,\n type LinkToVibeValue,\n type LinkToVibeVisibility,\n} from '@/components/shared/LinkToVibePanel';\nimport { EntityShareButton } from '@/components/sharing';\n\n/**\n * Shape of a single instruction file as returned by ListAgentInstructionFiles.\n * Mirrors the InstructionFileFields fragment in wspace-operations.\n */\ninterface InstructionFile {\n id: string;\n workspaceId: string;\n filename: InstructionFilename;\n customName?: string | null;\n effectiveFilename: string;\n content: string;\n scope: InstructionScope;\n agentId?: string | null;\n tags: string[];\n vibeId?: string | null;\n visibility: VibeVisibility;\n createdBy: string;\n createdAt: string;\n updatedAt: string;\n}\n\ninterface InstructionFilesManagerProps {\n /** Default AGENT-scope target for newly-created files. */\n agentId?: string | null;\n}\n\nconst FILENAME_OPTIONS: ReadonlyArray<{ value: InstructionFilename; label: string }> = [\n { value: InstructionFilename.AgentsMd, label: 'AGENTS.md' },\n { value: InstructionFilename.ClaudeMd, label: 'CLAUDE.md' },\n { value: InstructionFilename.GeminiMd, label: 'GEMINI.md' },\n { value: InstructionFilename.Custom, label: 'Custom' },\n];\n\nconst SCOPE_OPTIONS: ReadonlyArray<{ value: InstructionScope; label: string }> = [\n { value: InstructionScope.Agent, label: 'Agent' },\n { value: InstructionScope.Vibe, label: 'Vibe' },\n];\n\nconst INPUT_CLASS =\n 'w-full rounded-md border border-border-default bg-bg-surface px-3 py-2 text-sm text-text-primary';\n\nconst PRIMARY_BTN_CLASS =\n 'inline-flex items-center rounded-md bg-action-primary-bg px-3 py-2 text-sm font-medium text-action-primary-text hover:bg-action-primary-bg-hover disabled:opacity-50';\n\nconst SECONDARY_BTN_CLASS =\n 'inline-flex items-center rounded-md border border-border-default bg-bg-surface px-3 py-2 text-sm font-medium text-text-primary hover:bg-bg-sunken';\n\nconst DANGER_BTN_CLASS =\n 'inline-flex items-center rounded-md bg-action-danger-bg px-3 py-2 text-sm font-medium text-action-danger-text disabled:opacity-50';\n\nconst BADGE_CLASS =\n 'inline-flex items-center rounded bg-bg-sunken px-2 py-0.5 text-xs text-text-secondary';\n\n/** Internal state for the create/edit form. */\ninterface FormState {\n filename: InstructionFilename;\n customName: string;\n scope: InstructionScope;\n content: string;\n link: LinkToVibeValue;\n}\n\nfunction emptyFormState(): FormState {\n return {\n filename: InstructionFilename.AgentsMd,\n customName: '',\n scope: InstructionScope.Agent,\n content: '',\n link: LINK_TO_VIBE_DEFAULT,\n };\n}\n\n/** Map the file's stored visibility enum onto the LinkToVibePanel string union. */\nfunction toLinkVisibility(visibility: VibeVisibility): LinkToVibeVisibility {\n return visibility === VibeVisibility.SharedWithVibe ? 'SHARED_WITH_VIBE' : 'PRIVATE';\n}\n\n/** Map the LinkToVibePanel string union back onto the generated enum. */\nfunction toVibeVisibility(visibility: LinkToVibeVisibility): VibeVisibility {\n return visibility === 'SHARED_WITH_VIBE' ? VibeVisibility.SharedWithVibe : VibeVisibility.Private;\n}\n\nfunction formStateFromFile(file: InstructionFile): FormState {\n return {\n filename: file.filename,\n customName: file.customName ?? '',\n scope: file.scope,\n content: file.content,\n link: {\n vibeId: file.vibeId ?? null,\n visibility: toLinkVisibility(file.visibility),\n },\n };\n}\n\nfunction formatTimestamp(value: string): string {\n const parsed = new Date(value);\n if (Number.isNaN(parsed.getTime())) {\n return value;\n }\n return parsed.toLocaleString();\n}\n\nexport function InstructionFilesManager({\n agentId,\n}: InstructionFilesManagerProps): React.ReactElement {\n const { data, loading, error } = useListAgentInstructionFilesQuery({\n variables: {\n filter: agentId ? { agentId } : undefined,\n pagination: { limit: 100, offset: 0 },\n },\n fetchPolicy: 'cache-and-network',\n });\n\n const [createFile, { loading: creating }] = useCreateAgentInstructionFileMutation({\n refetchQueries: ['ListAgentInstructionFiles'],\n });\n const [updateFile, { loading: updating }] = useUpdateAgentInstructionFileMutation({\n refetchQueries: ['ListAgentInstructionFiles'],\n });\n const [deleteFile, { loading: deleting }] = useDeleteAgentInstructionFileMutation({\n refetchQueries: ['ListAgentInstructionFiles'],\n });\n\n const [formOpen, setFormOpen] = useState(false);\n const [editingId, setEditingId] = useState<string | null>(null);\n const [form, setForm] = useState<FormState>(emptyFormState);\n const [confirmDeleteId, setConfirmDeleteId] = useState<string | null>(null);\n const [formError, setFormError] = useState<string | null>(null);\n\n const items = useMemo<InstructionFile[]>(\n () => data?.agentInstructionFiles?.items ?? [],\n [data?.agentInstructionFiles?.items]\n );\n\n const submitting = creating || updating;\n\n const openCreateForm = (): void => {\n setEditingId(null);\n setForm(emptyFormState());\n setFormError(null);\n setFormOpen(true);\n };\n\n const openEditForm = (file: InstructionFile): void => {\n setEditingId(file.id);\n setForm(formStateFromFile(file));\n setFormError(null);\n setFormOpen(true);\n };\n\n const closeForm = (): void => {\n setFormOpen(false);\n setEditingId(null);\n setForm(emptyFormState());\n setFormError(null);\n };\n\n const handleSubmit = async (): Promise<void> => {\n setFormError(null);\n\n if (form.filename === InstructionFilename.Custom && form.customName.trim() === '') {\n setFormError('Please provide a name for the custom instruction file.');\n return;\n }\n if (form.content.trim() === '') {\n setFormError('Instruction file content cannot be empty.');\n return;\n }\n\n const customName = form.filename === InstructionFilename.Custom ? form.customName.trim() : null;\n\n try {\n if (editingId) {\n // On edit only content / filename / customName / tags are updatable.\n const input: UpdateAgentInstructionFileInput = {\n content: form.content,\n filename: form.filename,\n customName,\n };\n await updateFile({ variables: { id: editingId, input } });\n } else {\n if (form.scope === InstructionScope.Vibe && !form.link.vibeId) {\n setFormError('Pick a vibe to link before saving a vibe-scoped file.');\n return;\n }\n\n const input: CreateAgentInstructionFileInput = {\n filename: form.filename,\n customName,\n content: form.content,\n scope: form.scope,\n };\n\n if (form.scope === InstructionScope.Vibe && form.link.vibeId) {\n input.vibeId = form.link.vibeId;\n input.visibility = toVibeVisibility(form.link.visibility);\n } else {\n input.agentId = agentId ?? null;\n }\n\n await createFile({ variables: { input } });\n }\n closeForm();\n } catch (submitErr) {\n setFormError(\n submitErr instanceof Error ? submitErr.message : 'Failed to save the instruction file.'\n );\n }\n };\n\n const handleDelete = async (id: string): Promise<void> => {\n try {\n await deleteFile({ variables: { id } });\n } finally {\n setConfirmDeleteId(null);\n }\n };\n\n return (\n <section\n data-testid=\"instruction-files-manager\"\n className=\"space-y-4 rounded-lg border border-border-default bg-bg-surface p-4\"\n >\n <header className=\"flex flex-wrap items-start justify-between gap-3\">\n <div className=\"space-y-1\">\n <h2 className=\"text-lg font-semibold text-text-primary\">Instruction files</h2>\n <p className=\"max-w-2xl text-sm text-text-secondary\">\n AGENTS.md / CLAUDE.md / GEMINI.md maintained centrally and pushed to your agent on chat\n open.\n </p>\n </div>\n <button\n type=\"button\"\n data-testid=\"instruction-file-new\"\n className={PRIMARY_BTN_CLASS}\n onClick={formOpen && !editingId ? closeForm : openCreateForm}\n >\n {formOpen && !editingId ? 'Close' : 'New file'}\n </button>\n </header>\n\n {formOpen && (\n <div className=\"space-y-4 rounded-md border border-border-default bg-bg-elevated p-4\">\n <h3 className=\"text-sm font-medium text-text-primary\">\n {editingId ? 'Edit instruction file' : 'New instruction file'}\n </h3>\n\n <div className=\"grid gap-4 sm:grid-cols-2\">\n <label className=\"space-y-1.5\">\n <span className=\"block text-sm font-medium text-text-secondary\">Filename</span>\n <select\n className={INPUT_CLASS}\n value={form.filename}\n onChange={(e) =>\n setForm((prev) => ({\n ...prev,\n filename: e.target.value as InstructionFilename,\n }))\n }\n >\n {FILENAME_OPTIONS.map((opt) => (\n <option key={opt.value} value={opt.value}>\n {opt.label}\n </option>\n ))}\n </select>\n </label>\n\n <label className=\"space-y-1.5\">\n <span className=\"block text-sm font-medium text-text-secondary\">Scope</span>\n <select\n className={INPUT_CLASS}\n value={form.scope}\n disabled={editingId !== null}\n onChange={(e) =>\n setForm((prev) => ({\n ...prev,\n scope: e.target.value as InstructionScope,\n }))\n }\n >\n {SCOPE_OPTIONS.map((opt) => (\n <option key={opt.value} value={opt.value}>\n {opt.label}\n </option>\n ))}\n </select>\n </label>\n </div>\n\n {form.filename === InstructionFilename.Custom && (\n <label className=\"space-y-1.5\">\n <span className=\"block text-sm font-medium text-text-secondary\">Custom name</span>\n <input\n type=\"text\"\n className={INPUT_CLASS}\n placeholder=\"e.g. CONTRIBUTING.md\"\n value={form.customName}\n onChange={(e) => setForm((prev) => ({ ...prev, customName: e.target.value }))}\n />\n </label>\n )}\n\n {!editingId && form.scope === InstructionScope.Vibe && (\n <LinkToVibePanel\n value={form.link}\n onChange={(link) => setForm((prev) => ({ ...prev, link }))}\n disabled={submitting}\n />\n )}\n\n <label className=\"space-y-1.5\">\n <span className=\"block text-sm font-medium text-text-secondary\">Content</span>\n <textarea\n className={`${INPUT_CLASS} min-h-56 font-mono`}\n placeholder=\"# Project instructions…\"\n value={form.content}\n onChange={(e) => setForm((prev) => ({ ...prev, content: e.target.value }))}\n />\n </label>\n\n {formError && (\n <p className=\"text-sm text-action-danger-text\" role=\"alert\">\n {formError}\n </p>\n )}\n\n <div className=\"flex items-center gap-2\">\n <button\n type=\"button\"\n data-testid=\"instruction-file-save\"\n className={PRIMARY_BTN_CLASS}\n disabled={submitting}\n onClick={() => {\n void handleSubmit();\n }}\n >\n {submitting ? 'Saving…' : 'Save'}\n </button>\n <button\n type=\"button\"\n className={SECONDARY_BTN_CLASS}\n disabled={submitting}\n onClick={closeForm}\n >\n Cancel\n </button>\n </div>\n </div>\n )}\n\n {error ? (\n <p className=\"rounded-md border border-border-default bg-bg-sunken p-4 text-sm text-action-danger-text\">\n Could not load instruction files: {error.message}\n </p>\n ) : loading && items.length === 0 ? (\n <p className=\"rounded-md border border-border-default bg-bg-sunken p-4 text-sm text-text-secondary\">\n Loading instruction files…\n </p>\n ) : items.length === 0 ? (\n <p className=\"rounded-md border border-border-default bg-bg-sunken p-4 text-sm text-text-secondary\">\n No instruction files yet. Create one to share it with your agent.\n </p>\n ) : (\n <ul className=\"space-y-2\">\n {items.map((file) => {\n const isConfirming = confirmDeleteId === file.id;\n const isShared = file.visibility === VibeVisibility.SharedWithVibe;\n const scopeLabel = file.scope === InstructionScope.Vibe ? 'Vibe' : 'Agent';\n return (\n <li\n key={file.id}\n data-testid=\"instruction-file-row\"\n className=\"flex flex-wrap items-center justify-between gap-3 rounded-md border border-border-default bg-bg-elevated p-3\"\n >\n <div className=\"min-w-0 space-y-1\">\n <div className=\"flex flex-wrap items-center gap-2\">\n <span className=\"font-mono text-sm font-bold text-text-primary\">\n {file.effectiveFilename}\n </span>\n <span className={BADGE_CLASS}>{scopeLabel}</span>\n <span className={BADGE_CLASS}>{isShared ? 'Shared' : 'Private'}</span>\n </div>\n <p className=\"text-xs text-text-tertiary\">\n Updated {formatTimestamp(file.updatedAt)}\n </p>\n </div>\n\n <div className=\"flex items-center gap-2\">\n {isConfirming ? (\n <>\n <span className=\"text-xs text-text-secondary\">Delete this file?</span>\n <button\n type=\"button\"\n className={DANGER_BTN_CLASS}\n disabled={deleting}\n onClick={() => {\n void handleDelete(file.id);\n }}\n >\n {deleting ? 'Deleting…' : 'Confirm'}\n </button>\n <button\n type=\"button\"\n className={SECONDARY_BTN_CLASS}\n disabled={deleting}\n onClick={() => setConfirmDeleteId(null)}\n >\n Cancel\n </button>\n </>\n ) : (\n <>\n <button\n type=\"button\"\n className={SECONDARY_BTN_CLASS}\n onClick={() => openEditForm(file)}\n >\n Edit\n </button>\n <EntityShareButton\n entity=\"instructionfile\"\n resource={{\n id: file.id,\n name: file.effectiveFilename,\n vibeId: file.vibeId ?? null,\n }}\n label=\"Share\"\n />\n <button\n type=\"button\"\n className={DANGER_BTN_CLASS}\n onClick={() => setConfirmDeleteId(file.id)}\n >\n Delete\n </button>\n </>\n )}\n </div>\n </li>\n );\n })}\n </ul>\n )}\n </section>\n );\n}\n"],"mappings":"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"}
@@ -9,12 +9,12 @@ import { SearchInput as ue } from "../shared/SearchInput.js";
9
9
  import { FilterDropdown as s } from "../shared/FilterDropdown.js";
10
10
  import "../shared/index.js";
11
11
  import { VIBE_PERMISSIONS as c } from "../../constants/permissions.js";
12
- import { NoteCard as de } from "./NoteCard.js";
13
- import { NoteList as fe } from "./NoteList.js";
14
- import { NoteEditor as pe } from "./NoteEditor.js";
15
12
  import { SHARE_REGISTRY as l } from "../sharing/shareRegistry.js";
16
- import { NoteShareDialog as me } from "../sharing/NoteShareDialog.js";
13
+ import { NoteShareDialog as de } from "../sharing/NoteShareDialog.js";
17
14
  import "../sharing/index.js";
15
+ import { NoteCard as fe } from "./NoteCard.js";
16
+ import { NoteList as pe } from "./NoteList.js";
17
+ import { NoteEditor as me } from "./NoteEditor.js";
18
18
  import { useMemo as u, useState as d } from "react";
19
19
  import { useI18n as he } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
20
20
  import { FileText as ge, Globe as _e, Grid as ve, List as ye, Lock as be, Pin as xe, Plus as f, RefreshCw as Se } from "lucide-react";
@@ -394,7 +394,7 @@ function h({ context: h, vibeId: g, agentVibes: _ = [] }) {
394
394
  children: K.length > 0 ? A === "grid" ? /* @__PURE__ */ p(je, {
395
395
  stagger: .04,
396
396
  className: "grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4",
397
- children: K.map((e) => /* @__PURE__ */ p(Ae, { children: /* @__PURE__ */ p(de, {
397
+ children: K.map((e) => /* @__PURE__ */ p(Ae, { children: /* @__PURE__ */ p(fe, {
398
398
  note: e,
399
399
  onOpen: q,
400
400
  onEdit: q,
@@ -404,7 +404,7 @@ function h({ context: h, vibeId: g, agentVibes: _ = [] }) {
404
404
  onShare: tt,
405
405
  onShareAccess: Z
406
406
  }) }, e.id))
407
- }, "grid") : /* @__PURE__ */ p(fe, {
407
+ }, "grid") : /* @__PURE__ */ p(pe, {
408
408
  notes: K,
409
409
  onOpen: q,
410
410
  onEdit: q,
@@ -425,7 +425,7 @@ function h({ context: h, vibeId: g, agentVibes: _ = [] }) {
425
425
  }) : void 0
426
426
  })
427
427
  }),
428
- Ue && /* @__PURE__ */ p(pe, {
428
+ Ue && /* @__PURE__ */ p(me, {
429
429
  note: We || void 0,
430
430
  vibeOptions: nt,
431
431
  defaultVibeId: h === "vibe" ? g : void 0,
@@ -442,7 +442,7 @@ function h({ context: h, vibeId: g, agentVibes: _ = [] }) {
442
442
  title: "Note Quota Reached",
443
443
  message: "You've used all available note quota on your current plan. Upgrade your plan to create or update more notes."
444
444
  }),
445
- S && /* @__PURE__ */ p(me, {
445
+ S && /* @__PURE__ */ p(de, {
446
446
  note: {
447
447
  id: S.id,
448
448
  title: S.title,