@burdenoff/microfe-vibecontrols 2026.602.2 → 2026.602.4
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.
- package/dist/components/actions/ActionCard.js +87 -74
- package/dist/components/actions/ActionCard.js.map +1 -1
- package/dist/components/ai/InstructionFilesManager.js +149 -141
- package/dist/components/ai/InstructionFilesManager.js.map +1 -1
- package/dist/components/sessions/SessionShareDialog.js +24 -462
- package/dist/components/sessions/SessionShareDialog.js.map +1 -1
- package/dist/components/shared/EntityVibeLinkControl.js +204 -0
- package/dist/components/shared/EntityVibeLinkControl.js.map +1 -0
- package/dist/components/shared/index.js +1 -0
- package/dist/components/sharing/entityShareOps.js +106 -0
- package/dist/components/sharing/entityShareOps.js.map +1 -1
- package/dist/components/sharing/shareRegistry.js +3 -3
- package/dist/components/sharing/shareRegistry.js.map +1 -1
- package/dist/components/tunnels/TunnelCard.js +51 -43
- package/dist/components/tunnels/TunnelCard.js.map +1 -1
- package/dist/components/vibe/VibeLinkedEntitiesPanel.js +117 -89
- package/dist/components/vibe/VibeLinkedEntitiesPanel.js.map +1 -1
- package/dist/components/vibedeck/VibeDeckShareDialog.js +19 -335
- package/dist/components/vibedeck/VibeDeckShareDialog.js.map +1 -1
- package/dist/constants/permissions.js +1 -0
- package/dist/constants/permissions.js.map +1 -1
- package/dist/generated/wspace-operations.js +1618 -1593
- package/dist/generated/wspace-operations.js.map +1 -1
- package/dist/generated/wspace-types.js +10 -10
- package/dist/generated/wspace-types.js.map +1 -1
- package/dist/index.js +10 -10
- package/dist/pages/SessionsPage.js +1011 -1007
- package/dist/pages/SessionsPage.js.map +1 -1
- package/dist/pages/VibeDeckPage.js +218 -210
- package/dist/pages/VibeDeckPage.js.map +1 -1
- package/package.json +1 -1
- package/dist/utils/shareUrl.js +0 -41
- package/dist/utils/shareUrl.js.map +0 -1
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import { useCreateAgentInstructionFileMutation as e, useDeleteAgentInstructionFileMutation as t, useListAgentInstructionFilesQuery as n, useUpdateAgentInstructionFileMutation as r } from "../../generated/wspace-operations.js";
|
|
2
|
-
import { InstructionFilename as i, InstructionScope as a,
|
|
3
|
-
import { LINK_TO_VIBE_DEFAULT as
|
|
4
|
-
import {
|
|
2
|
+
import { InstructionFilename as i, InstructionScope as a, VibeEntityType as o, VibeVisibility as s } from "../../generated/wspace-types.js";
|
|
3
|
+
import { LINK_TO_VIBE_DEFAULT as c, LinkToVibePanel as l } from "../shared/LinkToVibePanel.js";
|
|
4
|
+
import { EntityVibeLinkControl as u } from "../shared/EntityVibeLinkControl.js";
|
|
5
|
+
import { EntityShareButton as d } from "../sharing/EntityShareButton.js";
|
|
5
6
|
import "../sharing/index.js";
|
|
6
|
-
import { useMemo as
|
|
7
|
-
import { Fragment as
|
|
7
|
+
import { useMemo as f, useState as p } from "react";
|
|
8
|
+
import { Fragment as m, jsx as h, jsxs as g } from "react/jsx-runtime";
|
|
8
9
|
//#region src/components/ai/InstructionFilesManager.tsx
|
|
9
|
-
var
|
|
10
|
+
var _ = [
|
|
10
11
|
{
|
|
11
12
|
value: i.AgentsMd,
|
|
12
13
|
label: "AGENTS.md"
|
|
@@ -23,29 +24,29 @@ var h = [
|
|
|
23
24
|
value: i.Custom,
|
|
24
25
|
label: "Custom"
|
|
25
26
|
}
|
|
26
|
-
],
|
|
27
|
+
], v = [{
|
|
27
28
|
value: a.Agent,
|
|
28
29
|
label: "Agent"
|
|
29
30
|
}, {
|
|
30
31
|
value: a.Vibe,
|
|
31
32
|
label: "Vibe"
|
|
32
|
-
}],
|
|
33
|
-
function
|
|
33
|
+
}], y = "w-full rounded-md border border-border-default bg-bg-surface px-3 py-2 text-sm text-text-primary", b = "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", x = "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", S = "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", C = "inline-flex items-center rounded bg-bg-sunken px-2 py-0.5 text-xs text-text-secondary";
|
|
34
|
+
function w() {
|
|
34
35
|
return {
|
|
35
36
|
filename: i.AgentsMd,
|
|
36
37
|
customName: "",
|
|
37
38
|
scope: a.Agent,
|
|
38
39
|
content: "",
|
|
39
|
-
link:
|
|
40
|
+
link: c
|
|
40
41
|
};
|
|
41
42
|
}
|
|
42
|
-
function
|
|
43
|
-
return e ===
|
|
43
|
+
function T(e) {
|
|
44
|
+
return e === s.SharedWithVibe ? "SHARED_WITH_VIBE" : "PRIVATE";
|
|
44
45
|
}
|
|
45
|
-
function
|
|
46
|
-
return e === "SHARED_WITH_VIBE" ?
|
|
46
|
+
function E(e) {
|
|
47
|
+
return e === "SHARED_WITH_VIBE" ? s.SharedWithVibe : s.Private;
|
|
47
48
|
}
|
|
48
|
-
function
|
|
49
|
+
function D(e) {
|
|
49
50
|
return {
|
|
50
51
|
filename: e.filename,
|
|
51
52
|
customName: e.customName ?? "",
|
|
@@ -53,276 +54,283 @@ function T(e) {
|
|
|
53
54
|
content: e.content,
|
|
54
55
|
link: {
|
|
55
56
|
vibeId: e.vibeId ?? null,
|
|
56
|
-
visibility:
|
|
57
|
+
visibility: T(e.visibility)
|
|
57
58
|
}
|
|
58
59
|
};
|
|
59
60
|
}
|
|
60
|
-
function
|
|
61
|
+
function O(e) {
|
|
61
62
|
let t = new Date(e);
|
|
62
63
|
return Number.isNaN(t.getTime()) ? e : t.toLocaleString();
|
|
63
64
|
}
|
|
64
|
-
function
|
|
65
|
-
let { data:
|
|
65
|
+
function k({ agentId: c }) {
|
|
66
|
+
let { data: T, loading: k, error: A } = n({
|
|
66
67
|
variables: {
|
|
67
|
-
filter:
|
|
68
|
+
filter: c ? { agentId: c } : void 0,
|
|
68
69
|
pagination: {
|
|
69
70
|
limit: 100,
|
|
70
71
|
offset: 0
|
|
71
72
|
}
|
|
72
73
|
},
|
|
73
74
|
fetchPolicy: "cache-and-network"
|
|
74
|
-
}), [
|
|
75
|
-
|
|
76
|
-
},
|
|
77
|
-
|
|
78
|
-
},
|
|
79
|
-
|
|
80
|
-
},
|
|
81
|
-
if (
|
|
82
|
-
|
|
75
|
+
}), [j, { loading: M }] = e({ refetchQueries: ["ListAgentInstructionFiles"] }), [N, { loading: P }] = r({ refetchQueries: ["ListAgentInstructionFiles"] }), [F, { loading: I }] = t({ refetchQueries: ["ListAgentInstructionFiles"] }), [L, R] = p(!1), [z, B] = p(null), [V, H] = p(w), [U, W] = p(null), [G, K] = p(null), q = f(() => T?.agentInstructionFiles?.items ?? [], [T?.agentInstructionFiles?.items]), J = M || P, Y = () => {
|
|
76
|
+
B(null), H(w()), K(null), R(!0);
|
|
77
|
+
}, X = (e) => {
|
|
78
|
+
B(e.id), H(D(e)), K(null), R(!0);
|
|
79
|
+
}, Z = () => {
|
|
80
|
+
R(!1), B(null), H(w()), K(null);
|
|
81
|
+
}, Q = async () => {
|
|
82
|
+
if (K(null), V.filename === i.Custom && V.customName.trim() === "") {
|
|
83
|
+
K("Please provide a name for the custom instruction file.");
|
|
83
84
|
return;
|
|
84
85
|
}
|
|
85
|
-
if (
|
|
86
|
-
|
|
86
|
+
if (V.content.trim() === "") {
|
|
87
|
+
K("Instruction file content cannot be empty.");
|
|
87
88
|
return;
|
|
88
89
|
}
|
|
89
|
-
let e =
|
|
90
|
+
let e = V.filename === i.Custom ? V.customName.trim() : null;
|
|
90
91
|
try {
|
|
91
|
-
if (
|
|
92
|
-
id:
|
|
92
|
+
if (z) await N({ variables: {
|
|
93
|
+
id: z,
|
|
93
94
|
input: {
|
|
94
|
-
content:
|
|
95
|
-
filename:
|
|
95
|
+
content: V.content,
|
|
96
|
+
filename: V.filename,
|
|
96
97
|
customName: e
|
|
97
98
|
}
|
|
98
99
|
} });
|
|
99
100
|
else {
|
|
100
|
-
if (
|
|
101
|
-
|
|
101
|
+
if (V.scope === a.Vibe && !V.link.vibeId) {
|
|
102
|
+
K("Pick a vibe to link before saving a vibe-scoped file.");
|
|
102
103
|
return;
|
|
103
104
|
}
|
|
104
105
|
let t = {
|
|
105
|
-
filename:
|
|
106
|
+
filename: V.filename,
|
|
106
107
|
customName: e,
|
|
107
|
-
content:
|
|
108
|
-
scope:
|
|
108
|
+
content: V.content,
|
|
109
|
+
scope: V.scope
|
|
109
110
|
};
|
|
110
|
-
|
|
111
|
+
V.scope === a.Vibe && V.link.vibeId ? (t.vibeId = V.link.vibeId, t.visibility = E(V.link.visibility)) : t.agentId = c ?? null, await j({ variables: { input: t } });
|
|
111
112
|
}
|
|
112
|
-
|
|
113
|
+
Z();
|
|
113
114
|
} catch (e) {
|
|
114
|
-
|
|
115
|
+
K(e instanceof Error ? e.message : "Failed to save the instruction file.");
|
|
115
116
|
}
|
|
116
|
-
},
|
|
117
|
+
}, $ = async (e) => {
|
|
117
118
|
try {
|
|
118
|
-
await
|
|
119
|
+
await F({ variables: { id: e } });
|
|
119
120
|
} finally {
|
|
120
|
-
|
|
121
|
+
W(null);
|
|
121
122
|
}
|
|
122
123
|
};
|
|
123
|
-
return /* @__PURE__ */
|
|
124
|
+
return /* @__PURE__ */ g("section", {
|
|
124
125
|
"data-testid": "instruction-files-manager",
|
|
125
126
|
className: "space-y-4 rounded-lg border border-border-default bg-bg-surface p-4",
|
|
126
127
|
children: [
|
|
127
|
-
/* @__PURE__ */
|
|
128
|
+
/* @__PURE__ */ g("header", {
|
|
128
129
|
className: "flex flex-wrap items-start justify-between gap-3",
|
|
129
|
-
children: [/* @__PURE__ */
|
|
130
|
+
children: [/* @__PURE__ */ g("div", {
|
|
130
131
|
className: "space-y-1",
|
|
131
|
-
children: [/* @__PURE__ */
|
|
132
|
+
children: [/* @__PURE__ */ h("h2", {
|
|
132
133
|
className: "text-lg font-semibold text-text-primary",
|
|
133
134
|
children: "Instruction files"
|
|
134
|
-
}), /* @__PURE__ */
|
|
135
|
+
}), /* @__PURE__ */ h("p", {
|
|
135
136
|
className: "max-w-2xl text-sm text-text-secondary",
|
|
136
137
|
children: "AGENTS.md / CLAUDE.md / GEMINI.md maintained centrally and pushed to your agent on chat open."
|
|
137
138
|
})]
|
|
138
|
-
}), /* @__PURE__ */
|
|
139
|
+
}), /* @__PURE__ */ h("button", {
|
|
139
140
|
type: "button",
|
|
140
141
|
"data-testid": "instruction-file-new",
|
|
141
|
-
className:
|
|
142
|
-
onClick:
|
|
143
|
-
children:
|
|
142
|
+
className: b,
|
|
143
|
+
onClick: L && !z ? Z : Y,
|
|
144
|
+
children: L && !z ? "Close" : "New file"
|
|
144
145
|
})]
|
|
145
146
|
}),
|
|
146
|
-
|
|
147
|
+
L && /* @__PURE__ */ g("div", {
|
|
147
148
|
className: "space-y-4 rounded-md border border-border-default bg-bg-elevated p-4",
|
|
148
149
|
children: [
|
|
149
|
-
/* @__PURE__ */
|
|
150
|
+
/* @__PURE__ */ h("h3", {
|
|
150
151
|
className: "text-sm font-medium text-text-primary",
|
|
151
|
-
children:
|
|
152
|
+
children: z ? "Edit instruction file" : "New instruction file"
|
|
152
153
|
}),
|
|
153
|
-
/* @__PURE__ */
|
|
154
|
+
/* @__PURE__ */ g("div", {
|
|
154
155
|
className: "grid gap-4 sm:grid-cols-2",
|
|
155
|
-
children: [/* @__PURE__ */
|
|
156
|
+
children: [/* @__PURE__ */ g("label", {
|
|
156
157
|
className: "space-y-1.5",
|
|
157
|
-
children: [/* @__PURE__ */
|
|
158
|
+
children: [/* @__PURE__ */ h("span", {
|
|
158
159
|
className: "block text-sm font-medium text-text-secondary",
|
|
159
160
|
children: "Filename"
|
|
160
|
-
}), /* @__PURE__ */
|
|
161
|
-
className:
|
|
162
|
-
value:
|
|
163
|
-
onChange: (e) =>
|
|
161
|
+
}), /* @__PURE__ */ h("select", {
|
|
162
|
+
className: y,
|
|
163
|
+
value: V.filename,
|
|
164
|
+
onChange: (e) => H((t) => ({
|
|
164
165
|
...t,
|
|
165
166
|
filename: e.target.value
|
|
166
167
|
})),
|
|
167
|
-
children:
|
|
168
|
+
children: _.map((e) => /* @__PURE__ */ h("option", {
|
|
168
169
|
value: e.value,
|
|
169
170
|
children: e.label
|
|
170
171
|
}, e.value))
|
|
171
172
|
})]
|
|
172
|
-
}), /* @__PURE__ */
|
|
173
|
+
}), /* @__PURE__ */ g("label", {
|
|
173
174
|
className: "space-y-1.5",
|
|
174
|
-
children: [/* @__PURE__ */
|
|
175
|
+
children: [/* @__PURE__ */ h("span", {
|
|
175
176
|
className: "block text-sm font-medium text-text-secondary",
|
|
176
177
|
children: "Scope"
|
|
177
|
-
}), /* @__PURE__ */
|
|
178
|
-
className:
|
|
179
|
-
value:
|
|
180
|
-
disabled:
|
|
181
|
-
onChange: (e) =>
|
|
178
|
+
}), /* @__PURE__ */ h("select", {
|
|
179
|
+
className: y,
|
|
180
|
+
value: V.scope,
|
|
181
|
+
disabled: z !== null,
|
|
182
|
+
onChange: (e) => H((t) => ({
|
|
182
183
|
...t,
|
|
183
184
|
scope: e.target.value
|
|
184
185
|
})),
|
|
185
|
-
children:
|
|
186
|
+
children: v.map((e) => /* @__PURE__ */ h("option", {
|
|
186
187
|
value: e.value,
|
|
187
188
|
children: e.label
|
|
188
189
|
}, e.value))
|
|
189
190
|
})]
|
|
190
191
|
})]
|
|
191
192
|
}),
|
|
192
|
-
|
|
193
|
+
V.filename === i.Custom && /* @__PURE__ */ g("label", {
|
|
193
194
|
className: "space-y-1.5",
|
|
194
|
-
children: [/* @__PURE__ */
|
|
195
|
+
children: [/* @__PURE__ */ h("span", {
|
|
195
196
|
className: "block text-sm font-medium text-text-secondary",
|
|
196
197
|
children: "Custom name"
|
|
197
|
-
}), /* @__PURE__ */
|
|
198
|
+
}), /* @__PURE__ */ h("input", {
|
|
198
199
|
type: "text",
|
|
199
|
-
className:
|
|
200
|
+
className: y,
|
|
200
201
|
placeholder: "e.g. CONTRIBUTING.md",
|
|
201
|
-
value:
|
|
202
|
-
onChange: (e) =>
|
|
202
|
+
value: V.customName,
|
|
203
|
+
onChange: (e) => H((t) => ({
|
|
203
204
|
...t,
|
|
204
205
|
customName: e.target.value
|
|
205
206
|
}))
|
|
206
207
|
})]
|
|
207
208
|
}),
|
|
208
|
-
!
|
|
209
|
-
value:
|
|
210
|
-
onChange: (e) =>
|
|
209
|
+
!z && V.scope === a.Vibe && /* @__PURE__ */ h(l, {
|
|
210
|
+
value: V.link,
|
|
211
|
+
onChange: (e) => H((t) => ({
|
|
211
212
|
...t,
|
|
212
213
|
link: e
|
|
213
214
|
})),
|
|
214
|
-
disabled:
|
|
215
|
+
disabled: J
|
|
215
216
|
}),
|
|
216
|
-
/* @__PURE__ */
|
|
217
|
+
/* @__PURE__ */ g("label", {
|
|
217
218
|
className: "space-y-1.5",
|
|
218
|
-
children: [/* @__PURE__ */
|
|
219
|
+
children: [/* @__PURE__ */ h("span", {
|
|
219
220
|
className: "block text-sm font-medium text-text-secondary",
|
|
220
221
|
children: "Content"
|
|
221
|
-
}), /* @__PURE__ */
|
|
222
|
-
className: `${
|
|
222
|
+
}), /* @__PURE__ */ h("textarea", {
|
|
223
|
+
className: `${y} min-h-56 font-mono`,
|
|
223
224
|
placeholder: "# Project instructions…",
|
|
224
|
-
value:
|
|
225
|
-
onChange: (e) =>
|
|
225
|
+
value: V.content,
|
|
226
|
+
onChange: (e) => H((t) => ({
|
|
226
227
|
...t,
|
|
227
228
|
content: e.target.value
|
|
228
229
|
}))
|
|
229
230
|
})]
|
|
230
231
|
}),
|
|
231
|
-
|
|
232
|
+
G && /* @__PURE__ */ h("p", {
|
|
232
233
|
className: "text-sm text-action-danger-text",
|
|
233
234
|
role: "alert",
|
|
234
|
-
children:
|
|
235
|
+
children: G
|
|
235
236
|
}),
|
|
236
|
-
/* @__PURE__ */
|
|
237
|
+
/* @__PURE__ */ g("div", {
|
|
237
238
|
className: "flex items-center gap-2",
|
|
238
|
-
children: [/* @__PURE__ */
|
|
239
|
+
children: [/* @__PURE__ */ h("button", {
|
|
239
240
|
type: "button",
|
|
240
241
|
"data-testid": "instruction-file-save",
|
|
241
|
-
className:
|
|
242
|
-
disabled:
|
|
242
|
+
className: b,
|
|
243
|
+
disabled: J,
|
|
243
244
|
onClick: () => {
|
|
244
|
-
|
|
245
|
+
Q();
|
|
245
246
|
},
|
|
246
|
-
children:
|
|
247
|
-
}), /* @__PURE__ */
|
|
247
|
+
children: J ? "Saving…" : "Save"
|
|
248
|
+
}), /* @__PURE__ */ h("button", {
|
|
248
249
|
type: "button",
|
|
249
|
-
className:
|
|
250
|
-
disabled:
|
|
251
|
-
onClick:
|
|
250
|
+
className: x,
|
|
251
|
+
disabled: J,
|
|
252
|
+
onClick: Z,
|
|
252
253
|
children: "Cancel"
|
|
253
254
|
})]
|
|
254
255
|
})
|
|
255
256
|
]
|
|
256
257
|
}),
|
|
257
|
-
|
|
258
|
+
A ? /* @__PURE__ */ g("p", {
|
|
258
259
|
className: "rounded-md border border-border-default bg-bg-sunken p-4 text-sm text-action-danger-text",
|
|
259
|
-
children: ["Could not load instruction files: ",
|
|
260
|
-
}) :
|
|
260
|
+
children: ["Could not load instruction files: ", A.message]
|
|
261
|
+
}) : k && q.length === 0 ? /* @__PURE__ */ h("p", {
|
|
261
262
|
className: "rounded-md border border-border-default bg-bg-sunken p-4 text-sm text-text-secondary",
|
|
262
263
|
children: "Loading instruction files…"
|
|
263
|
-
}) :
|
|
264
|
+
}) : q.length === 0 ? /* @__PURE__ */ h("p", {
|
|
264
265
|
className: "rounded-md border border-border-default bg-bg-sunken p-4 text-sm text-text-secondary",
|
|
265
266
|
children: "No instruction files yet. Create one to share it with your agent."
|
|
266
|
-
}) : /* @__PURE__ */
|
|
267
|
+
}) : /* @__PURE__ */ h("ul", {
|
|
267
268
|
className: "space-y-2",
|
|
268
|
-
children:
|
|
269
|
-
let t =
|
|
270
|
-
return /* @__PURE__ */
|
|
269
|
+
children: q.map((e) => {
|
|
270
|
+
let t = U === e.id, n = e.visibility === s.SharedWithVibe, r = e.scope === a.Vibe ? "Vibe" : "Agent";
|
|
271
|
+
return /* @__PURE__ */ g("li", {
|
|
271
272
|
"data-testid": "instruction-file-row",
|
|
272
273
|
className: "flex flex-wrap items-center justify-between gap-3 rounded-md border border-border-default bg-bg-elevated p-3",
|
|
273
|
-
children: [/* @__PURE__ */
|
|
274
|
+
children: [/* @__PURE__ */ g("div", {
|
|
274
275
|
className: "min-w-0 space-y-1",
|
|
275
|
-
children: [/* @__PURE__ */
|
|
276
|
+
children: [/* @__PURE__ */ g("div", {
|
|
276
277
|
className: "flex flex-wrap items-center gap-2",
|
|
277
278
|
children: [
|
|
278
|
-
/* @__PURE__ */
|
|
279
|
+
/* @__PURE__ */ h("span", {
|
|
279
280
|
className: "font-mono text-sm font-bold text-text-primary",
|
|
280
281
|
children: e.effectiveFilename
|
|
281
282
|
}),
|
|
282
|
-
/* @__PURE__ */
|
|
283
|
-
className:
|
|
283
|
+
/* @__PURE__ */ h("span", {
|
|
284
|
+
className: C,
|
|
284
285
|
children: r
|
|
285
286
|
}),
|
|
286
|
-
/* @__PURE__ */
|
|
287
|
-
className:
|
|
287
|
+
/* @__PURE__ */ h("span", {
|
|
288
|
+
className: C,
|
|
288
289
|
children: n ? "Shared" : "Private"
|
|
289
290
|
})
|
|
290
291
|
]
|
|
291
|
-
}), /* @__PURE__ */
|
|
292
|
+
}), /* @__PURE__ */ g("p", {
|
|
292
293
|
className: "text-xs text-text-tertiary",
|
|
293
|
-
children: ["Updated ",
|
|
294
|
+
children: ["Updated ", O(e.updatedAt)]
|
|
294
295
|
})]
|
|
295
|
-
}), /* @__PURE__ */
|
|
296
|
+
}), /* @__PURE__ */ h("div", {
|
|
296
297
|
className: "flex items-center gap-2",
|
|
297
|
-
children: t ? /* @__PURE__ */ m
|
|
298
|
-
/* @__PURE__ */
|
|
298
|
+
children: t ? /* @__PURE__ */ g(m, { children: [
|
|
299
|
+
/* @__PURE__ */ h("span", {
|
|
299
300
|
className: "text-xs text-text-secondary",
|
|
300
301
|
children: "Delete this file?"
|
|
301
302
|
}),
|
|
302
|
-
/* @__PURE__ */
|
|
303
|
+
/* @__PURE__ */ h("button", {
|
|
303
304
|
type: "button",
|
|
304
|
-
className:
|
|
305
|
-
disabled:
|
|
305
|
+
className: S,
|
|
306
|
+
disabled: I,
|
|
306
307
|
onClick: () => {
|
|
307
|
-
|
|
308
|
+
$(e.id);
|
|
308
309
|
},
|
|
309
|
-
children:
|
|
310
|
+
children: I ? "Deleting…" : "Confirm"
|
|
310
311
|
}),
|
|
311
|
-
/* @__PURE__ */
|
|
312
|
+
/* @__PURE__ */ h("button", {
|
|
312
313
|
type: "button",
|
|
313
|
-
className:
|
|
314
|
-
disabled:
|
|
315
|
-
onClick: () =>
|
|
314
|
+
className: x,
|
|
315
|
+
disabled: I,
|
|
316
|
+
onClick: () => W(null),
|
|
316
317
|
children: "Cancel"
|
|
317
318
|
})
|
|
318
|
-
] }) : /* @__PURE__ */ m
|
|
319
|
-
/* @__PURE__ */
|
|
319
|
+
] }) : /* @__PURE__ */ g(m, { children: [
|
|
320
|
+
/* @__PURE__ */ h("button", {
|
|
320
321
|
type: "button",
|
|
321
|
-
className:
|
|
322
|
-
onClick: () =>
|
|
322
|
+
className: x,
|
|
323
|
+
onClick: () => X(e),
|
|
323
324
|
children: "Edit"
|
|
324
325
|
}),
|
|
325
|
-
/* @__PURE__ */
|
|
326
|
+
/* @__PURE__ */ h(u, {
|
|
327
|
+
entityType: o.InstructionFile,
|
|
328
|
+
entityId: e.id,
|
|
329
|
+
currentVibeId: e.vibeId ?? null,
|
|
330
|
+
currentVisibility: e.visibility,
|
|
331
|
+
refetchQueries: ["ListAgentInstructionFiles"]
|
|
332
|
+
}),
|
|
333
|
+
/* @__PURE__ */ h(d, {
|
|
326
334
|
entity: "instructionfile",
|
|
327
335
|
resource: {
|
|
328
336
|
id: e.id,
|
|
@@ -331,10 +339,10 @@ function D({ agentId: s }) {
|
|
|
331
339
|
},
|
|
332
340
|
label: "Share"
|
|
333
341
|
}),
|
|
334
|
-
/* @__PURE__ */
|
|
342
|
+
/* @__PURE__ */ h("button", {
|
|
335
343
|
type: "button",
|
|
336
|
-
className:
|
|
337
|
-
onClick: () =>
|
|
344
|
+
className: S,
|
|
345
|
+
onClick: () => W(e.id),
|
|
338
346
|
children: "Delete"
|
|
339
347
|
})
|
|
340
348
|
] })
|
|
@@ -346,6 +354,6 @@ function D({ agentId: s }) {
|
|
|
346
354
|
});
|
|
347
355
|
}
|
|
348
356
|
//#endregion
|
|
349
|
-
export {
|
|
357
|
+
export { k as InstructionFilesManager };
|
|
350
358
|
|
|
351
359
|
//# 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';\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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"}
|
|
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 VibeEntityType,\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 { EntityVibeLinkControl } from '@/components/shared/EntityVibeLinkControl';\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 <EntityVibeLinkControl\n entityType={VibeEntityType.InstructionFile}\n entityId={file.id}\n currentVibeId={file.vibeId ?? null}\n currentVisibility={file.visibility}\n refetchQueries={['ListAgentInstructionFiles']}\n />\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":";;;;;;;;;AAkDA,IAAM,IAAiF;CACrF;EAAE,OAAO,EAAoB;EAAU,OAAO;EAAa;CAC3D;EAAE,OAAO,EAAoB;EAAU,OAAO;EAAa;CAC3D;EAAE,OAAO,EAAoB;EAAU,OAAO;EAAa;CAC3D;EAAE,OAAO,EAAoB;EAAQ,OAAO;EAAU;CACvD,EAEK,IAA2E,CAC/E;CAAE,OAAO,EAAiB;CAAO,OAAO;CAAS,EACjD;CAAE,OAAO,EAAiB;CAAM,OAAO;CAAQ,CAChD,EAEK,IACJ,oGAEI,IACJ,wKAEI,IACJ,qJAEI,IACJ,qIAEI,IACJ;AAWF,SAAS,IAA4B;AACnC,QAAO;EACL,UAAU,EAAoB;EAC9B,YAAY;EACZ,OAAO,EAAiB;EACxB,SAAS;EACT,MAAM;EACP;;AAIH,SAAS,EAAiB,GAAkD;AAC1E,QAAO,MAAe,EAAe,iBAAiB,qBAAqB;;AAI7E,SAAS,EAAiB,GAAkD;AAC1E,QAAO,MAAe,qBAAqB,EAAe,iBAAiB,EAAe;;AAG5F,SAAS,EAAkB,GAAkC;AAC3D,QAAO;EACL,UAAU,EAAK;EACf,YAAY,EAAK,cAAc;EAC/B,OAAO,EAAK;EACZ,SAAS,EAAK;EACd,MAAM;GACJ,QAAQ,EAAK,UAAU;GACvB,YAAY,EAAiB,EAAK,WAAW;GAC9C;EACF;;AAGH,SAAS,EAAgB,GAAuB;CAC9C,IAAM,IAAS,IAAI,KAAK,EAAM;AAI9B,QAHI,OAAO,MAAM,EAAO,SAAS,CAAC,GACzB,IAEF,EAAO,gBAAgB;;AAGhC,SAAgB,EAAwB,EACtC,cACmD;CACnD,IAAM,EAAE,SAAM,YAAS,aAAU,EAAkC;EACjE,WAAW;GACT,QAAQ,IAAU,EAAE,YAAS,GAAG,KAAA;GAChC,YAAY;IAAE,OAAO;IAAK,QAAQ;IAAG;GACtC;EACD,aAAa;EACd,CAAC,EAEI,CAAC,GAAY,EAAE,SAAS,OAAc,EAAsC,EAChF,gBAAgB,CAAC,4BAA4B,EAC9C,CAAC,EACI,CAAC,GAAY,EAAE,SAAS,OAAc,EAAsC,EAChF,gBAAgB,CAAC,4BAA4B,EAC9C,CAAC,EACI,CAAC,GAAY,EAAE,SAAS,OAAc,EAAsC,EAChF,gBAAgB,CAAC,4BAA4B,EAC9C,CAAC,EAEI,CAAC,GAAU,KAAe,EAAS,GAAM,EACzC,CAAC,GAAW,KAAgB,EAAwB,KAAK,EACzD,CAAC,GAAM,KAAW,EAAoB,EAAe,EACrD,CAAC,GAAiB,KAAsB,EAAwB,KAAK,EACrE,CAAC,GAAW,KAAgB,EAAwB,KAAK,EAEzD,IAAQ,QACN,GAAM,uBAAuB,SAAS,EAAE,EAC9C,CAAC,GAAM,uBAAuB,MAAM,CACrC,EAEK,IAAa,KAAY,GAEzB,UAA6B;AAIjC,EAHA,EAAa,KAAK,EAClB,EAAQ,GAAgB,CAAC,EACzB,EAAa,KAAK,EAClB,EAAY,GAAK;IAGb,KAAgB,MAAgC;AAIpD,EAHA,EAAa,EAAK,GAAG,EACrB,EAAQ,EAAkB,EAAK,CAAC,EAChC,EAAa,KAAK,EAClB,EAAY,GAAK;IAGb,UAAwB;AAI5B,EAHA,EAAY,GAAM,EAClB,EAAa,KAAK,EAClB,EAAQ,GAAgB,CAAC,EACzB,EAAa,KAAK;IAGd,IAAe,YAA2B;AAG9C,MAFA,EAAa,KAAK,EAEd,EAAK,aAAa,EAAoB,UAAU,EAAK,WAAW,MAAM,KAAK,IAAI;AACjF,KAAa,yDAAyD;AACtE;;AAEF,MAAI,EAAK,QAAQ,MAAM,KAAK,IAAI;AAC9B,KAAa,4CAA4C;AACzD;;EAGF,IAAM,IAAa,EAAK,aAAa,EAAoB,SAAS,EAAK,WAAW,MAAM,GAAG;AAE3F,MAAI;AACF,OAAI,EAOF,OAAM,EAAW,EAAE,WAAW;IAAE,IAAI;IAAW,OALA;KAC7C,SAAS,EAAK;KACd,UAAU,EAAK;KACf;KACD;IACqD,EAAE,CAAC;QACpD;AACL,QAAI,EAAK,UAAU,EAAiB,QAAQ,CAAC,EAAK,KAAK,QAAQ;AAC7D,OAAa,wDAAwD;AACrE;;IAGF,IAAM,IAAyC;KAC7C,UAAU,EAAK;KACf;KACA,SAAS,EAAK;KACd,OAAO,EAAK;KACb;AASD,IAPI,EAAK,UAAU,EAAiB,QAAQ,EAAK,KAAK,UACpD,EAAM,SAAS,EAAK,KAAK,QACzB,EAAM,aAAa,EAAiB,EAAK,KAAK,WAAW,IAEzD,EAAM,UAAU,KAAW,MAG7B,MAAM,EAAW,EAAE,WAAW,EAAE,UAAO,EAAE,CAAC;;AAE5C,MAAW;WACJ,GAAW;AAClB,KACE,aAAqB,QAAQ,EAAU,UAAU,uCAClD;;IAIC,IAAe,OAAO,MAA8B;AACxD,MAAI;AACF,SAAM,EAAW,EAAE,WAAW,EAAE,OAAI,EAAE,CAAC;YAC/B;AACR,KAAmB,KAAK;;;AAI5B,QACE,kBAAC,WAAD;EACE,eAAY;EACZ,WAAU;YAFZ;GAIE,kBAAC,UAAD;IAAQ,WAAU;cAAlB,CACE,kBAAC,OAAD;KAAK,WAAU;eAAf,CACE,kBAAC,MAAD;MAAI,WAAU;gBAA0C;MAAsB,CAAA,EAC9E,kBAAC,KAAD;MAAG,WAAU;gBAAwC;MAGjD,CAAA,CACA;QACN,kBAAC,UAAD;KACE,MAAK;KACL,eAAY;KACZ,WAAW;KACX,SAAS,KAAY,CAAC,IAAY,IAAY;eAE7C,KAAY,CAAC,IAAY,UAAU;KAC7B,CAAA,CACF;;GAER,KACC,kBAAC,OAAD;IAAK,WAAU;cAAf;KACE,kBAAC,MAAD;MAAI,WAAU;gBACX,IAAY,0BAA0B;MACpC,CAAA;KAEL,kBAAC,OAAD;MAAK,WAAU;gBAAf,CACE,kBAAC,SAAD;OAAO,WAAU;iBAAjB,CACE,kBAAC,QAAD;QAAM,WAAU;kBAAgD;QAAe,CAAA,EAC/E,kBAAC,UAAD;QACE,WAAW;QACX,OAAO,EAAK;QACZ,WAAW,MACT,GAAS,OAAU;SACjB,GAAG;SACH,UAAU,EAAE,OAAO;SACpB,EAAE;kBAGJ,EAAiB,KAAK,MACrB,kBAAC,UAAD;SAAwB,OAAO,EAAI;mBAChC,EAAI;SACE,EAFI,EAAI,MAER,CACT;QACK,CAAA,CACH;UAER,kBAAC,SAAD;OAAO,WAAU;iBAAjB,CACE,kBAAC,QAAD;QAAM,WAAU;kBAAgD;QAAY,CAAA,EAC5E,kBAAC,UAAD;QACE,WAAW;QACX,OAAO,EAAK;QACZ,UAAU,MAAc;QACxB,WAAW,MACT,GAAS,OAAU;SACjB,GAAG;SACH,OAAO,EAAE,OAAO;SACjB,EAAE;kBAGJ,EAAc,KAAK,MAClB,kBAAC,UAAD;SAAwB,OAAO,EAAI;mBAChC,EAAI;SACE,EAFI,EAAI,MAER,CACT;QACK,CAAA,CACH;SACJ;;KAEL,EAAK,aAAa,EAAoB,UACrC,kBAAC,SAAD;MAAO,WAAU;gBAAjB,CACE,kBAAC,QAAD;OAAM,WAAU;iBAAgD;OAAkB,CAAA,EAClF,kBAAC,SAAD;OACE,MAAK;OACL,WAAW;OACX,aAAY;OACZ,OAAO,EAAK;OACZ,WAAW,MAAM,GAAS,OAAU;QAAE,GAAG;QAAM,YAAY,EAAE,OAAO;QAAO,EAAE;OAC7E,CAAA,CACI;;KAGT,CAAC,KAAa,EAAK,UAAU,EAAiB,QAC7C,kBAAC,GAAD;MACE,OAAO,EAAK;MACZ,WAAW,MAAS,GAAS,OAAU;OAAE,GAAG;OAAM;OAAM,EAAE;MAC1D,UAAU;MACV,CAAA;KAGJ,kBAAC,SAAD;MAAO,WAAU;gBAAjB,CACE,kBAAC,QAAD;OAAM,WAAU;iBAAgD;OAAc,CAAA,EAC9E,kBAAC,YAAD;OACE,WAAW,GAAG,EAAY;OAC1B,aAAY;OACZ,OAAO,EAAK;OACZ,WAAW,MAAM,GAAS,OAAU;QAAE,GAAG;QAAM,SAAS,EAAE,OAAO;QAAO,EAAE;OAC1E,CAAA,CACI;;KAEP,KACC,kBAAC,KAAD;MAAG,WAAU;MAAkC,MAAK;gBACjD;MACC,CAAA;KAGN,kBAAC,OAAD;MAAK,WAAU;gBAAf,CACE,kBAAC,UAAD;OACE,MAAK;OACL,eAAY;OACZ,WAAW;OACX,UAAU;OACV,eAAe;AACR,WAAc;;iBAGpB,IAAa,YAAY;OACnB,CAAA,EACT,kBAAC,UAAD;OACE,MAAK;OACL,WAAW;OACX,UAAU;OACV,SAAS;iBACV;OAEQ,CAAA,CACL;;KACF;;GAGP,IACC,kBAAC,KAAD;IAAG,WAAU;cAAb,CAAwG,sCACnE,EAAM,QACvC;QACF,KAAW,EAAM,WAAW,IAC9B,kBAAC,KAAD;IAAG,WAAU;cAAuF;IAEhG,CAAA,GACF,EAAM,WAAW,IACnB,kBAAC,KAAD;IAAG,WAAU;cAAuF;IAEhG,CAAA,GAEJ,kBAAC,MAAD;IAAI,WAAU;cACX,EAAM,KAAK,MAAS;KACnB,IAAM,IAAe,MAAoB,EAAK,IACxC,IAAW,EAAK,eAAe,EAAe,gBAC9C,IAAa,EAAK,UAAU,EAAiB,OAAO,SAAS;AACnE,YACE,kBAAC,MAAD;MAEE,eAAY;MACZ,WAAU;gBAHZ,CAKE,kBAAC,OAAD;OAAK,WAAU;iBAAf,CACE,kBAAC,OAAD;QAAK,WAAU;kBAAf;SACE,kBAAC,QAAD;UAAM,WAAU;oBACb,EAAK;UACD,CAAA;SACP,kBAAC,QAAD;UAAM,WAAW;oBAAc;UAAkB,CAAA;SACjD,kBAAC,QAAD;UAAM,WAAW;oBAAc,IAAW,WAAW;UAAiB,CAAA;SAClE;WACN,kBAAC,KAAD;QAAG,WAAU;kBAAb,CAA0C,YAC/B,EAAgB,EAAK,UAAU,CACtC;UACA;UAEN,kBAAC,OAAD;OAAK,WAAU;iBACZ,IACC,kBAAA,GAAA,EAAA,UAAA;QACE,kBAAC,QAAD;SAAM,WAAU;mBAA8B;SAAwB,CAAA;QACtE,kBAAC,UAAD;SACE,MAAK;SACL,WAAW;SACX,UAAU;SACV,eAAe;AACR,YAAa,EAAK,GAAG;;mBAG3B,IAAW,cAAc;SACnB,CAAA;QACT,kBAAC,UAAD;SACE,MAAK;SACL,WAAW;SACX,UAAU;SACV,eAAe,EAAmB,KAAK;mBACxC;SAEQ,CAAA;QACR,EAAA,CAAA,GAEH,kBAAA,GAAA,EAAA,UAAA;QACE,kBAAC,UAAD;SACE,MAAK;SACL,WAAW;SACX,eAAe,EAAa,EAAK;mBAClC;SAEQ,CAAA;QACT,kBAAC,GAAD;SACE,YAAY,EAAe;SAC3B,UAAU,EAAK;SACf,eAAe,EAAK,UAAU;SAC9B,mBAAmB,EAAK;SACxB,gBAAgB,CAAC,4BAA4B;SAC7C,CAAA;QACF,kBAAC,GAAD;SACE,QAAO;SACP,UAAU;UACR,IAAI,EAAK;UACT,MAAM,EAAK;UACX,QAAQ,EAAK,UAAU;UACxB;SACD,OAAM;SACN,CAAA;QACF,kBAAC,UAAD;SACE,MAAK;SACL,WAAW;SACX,eAAe,EAAmB,EAAK,GAAG;mBAC3C;SAEQ,CAAA;QACR,EAAA,CAAA;OAED,CAAA,CACH;QA3EE,EAAK,GA2EP;MAEP;IACC,CAAA;GAEC"}
|