living-ai-documentation 2.0.0 → 2.3.0

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 (31) hide show
  1. package/dist/src/frontend/agents.js +288 -0
  2. package/dist/src/frontend/config.js +3 -2
  3. package/dist/src/frontend/diagram/color-picker.js +72 -0
  4. package/dist/src/frontend/diagram/defaults-modal.js +302 -0
  5. package/dist/src/frontend/diagram/edge-panel.js +110 -11
  6. package/dist/src/frontend/diagram/main.js +5 -8
  7. package/dist/src/frontend/diagram/network.js +16 -7
  8. package/dist/src/frontend/diagram/node-panel.js +104 -2
  9. package/dist/src/frontend/diagram.html +52 -29
  10. package/dist/src/frontend/i18n/en.json +43 -1
  11. package/dist/src/frontend/i18n/fr.json +43 -1
  12. package/dist/src/frontend/index.html +156 -33
  13. package/dist/src/frontend/workspace/app.js +439 -67
  14. package/dist/src/frontend/workspace/app.js.map +1 -1
  15. package/dist/src/frontend/workspace/app.ts +582 -84
  16. package/dist/src/frontend/workspace/index.html +232 -82
  17. package/dist/src/frontend/workspace/persistence.js +61 -0
  18. package/dist/src/frontend/workspace/persistence.js.map +1 -1
  19. package/dist/src/frontend/workspace/persistence.ts +111 -0
  20. package/dist/src/frontend/workspace/styles.css +293 -34
  21. package/dist/src/lib/config.d.ts +23 -0
  22. package/dist/src/lib/config.d.ts.map +1 -1
  23. package/dist/src/lib/config.js +16 -0
  24. package/dist/src/lib/config.js.map +1 -1
  25. package/dist/src/routes/config.d.ts.map +1 -1
  26. package/dist/src/routes/config.js +13 -0
  27. package/dist/src/routes/config.js.map +1 -1
  28. package/dist/src/routes/workspace.d.ts.map +1 -1
  29. package/dist/src/routes/workspace.js +528 -6
  30. package/dist/src/routes/workspace.js.map +1 -1
  31. package/package.json +2 -2
@@ -4,7 +4,10 @@
4
4
  <meta charset="utf-8" />
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1" />
6
6
  <title>HTML-in-Canvas Configuration Experiment</title>
7
- <link rel="stylesheet" href="./styles.css?v=workspace-ts-1" />
7
+ <link
8
+ rel="stylesheet"
9
+ href="/workspace/styles.css?v=workspace-agent-panel-1"
10
+ />
8
11
  </head>
9
12
  <body>
10
13
  <main class="app-shell">
@@ -12,20 +15,13 @@
12
15
  <div class="brand-lockup">
13
16
  <span class="brand-mark" aria-hidden="true">LD</span>
14
17
  <div>
15
- <h1>Living Documentation Config Graph</h1>
16
- <p>Experimental graph-native configuration workspace</p>
18
+ <h1>Living AI Documentation</h1>
19
+ <p>Graph-native configuration workspace</p>
17
20
  </div>
18
21
  </div>
19
22
  <div class="status-row">
20
23
  <span id="apiStatus" class="status-pill">Detecting canvas API</span>
21
- <button
22
- id="resetButton"
23
- class="ghost-button"
24
- type="button"
25
- title="Reset workspace"
26
- >
27
- Reset
28
- </button>
24
+ <a href="/" class="ghost-button" title="Back to home">Home</a>
29
25
  </div>
30
26
  </header>
31
27
 
@@ -56,29 +52,26 @@
56
52
  <form id="configSurface" class="config-surface" autocomplete="off">
57
53
  <div class="panel-kicker">
58
54
  <span id="nodeTypeBadge">Provider</span>
59
- <span id="nodeHealthBadge">Ready</span>
60
- </div>
61
-
62
- <div class="panel-title-row">
63
- <div>
64
- <label class="eyebrow" for="nodeName">Node name</label>
65
- <input
66
- id="nodeName"
67
- name="nodeName"
68
- class="title-input"
69
- type="text"
70
- />
71
- </div>
72
55
  <button
73
- id="deleteNodeButton"
74
- class="icon-button danger"
56
+ id="closePanelButton"
57
+ class="icon-button close"
75
58
  type="button"
76
- title="Delete node"
59
+ title="Close panel"
77
60
  >
78
61
  ×
79
62
  </button>
80
63
  </div>
81
64
 
65
+ <div class="panel-title-row">
66
+ <label class="eyebrow" for="nodeName">Node name</label>
67
+ <input
68
+ id="nodeName"
69
+ name="nodeName"
70
+ class="title-input"
71
+ type="text"
72
+ />
73
+ </div>
74
+
82
75
  <div class="form-grid">
83
76
  <label class="field">
84
77
  <span>Kind</span>
@@ -90,65 +83,120 @@
90
83
  </select>
91
84
  </label>
92
85
 
93
- <label class="field">
94
- <span>Environment</span>
95
- <select id="nodeEnvironment" name="nodeEnvironment">
96
- <option value="local">Local</option>
97
- <option value="staging">Staging</option>
98
- <option value="production">Production</option>
99
- </select>
100
- </label>
86
+ <div id="llmFields" class="contents">
87
+ <label class="field wide">
88
+ <span>Endpoint</span>
89
+ <input
90
+ id="nodeEndpoint"
91
+ name="nodeEndpoint"
92
+ type="url"
93
+ placeholder="http://localhost:11434"
94
+ />
95
+ </label>
96
+
97
+ <label class="field wide">
98
+ <span>API token</span>
99
+ <input
100
+ id="nodeToken"
101
+ name="nodeToken"
102
+ type="password"
103
+ placeholder="Optional bearer token"
104
+ />
105
+ </label>
106
+
107
+ <div class="field wide model-field-row">
108
+ <span>Model</span>
109
+ <div class="model-select-wrap">
110
+ <select id="nodeModel" name="nodeModel">
111
+ <option value="" disabled selected>
112
+ — click ↻ to load models —
113
+ </option>
114
+ </select>
115
+ <button
116
+ id="loadModelsButton"
117
+ class="icon-button"
118
+ type="button"
119
+ title="Load models from endpoint"
120
+ >
121
+
122
+ </button>
123
+ </div>
124
+ </div>
125
+
126
+ <label class="field">
127
+ <span>Timeout</span>
128
+ <input
129
+ id="nodeTimeout"
130
+ name="nodeTimeout"
131
+ type="number"
132
+ min="1"
133
+ max="600"
134
+ step="1"
135
+ />
136
+ </label>
137
+ </div>
101
138
 
102
139
  <label class="field wide">
103
- <span>Endpoint</span>
104
- <input
105
- id="nodeEndpoint"
106
- name="nodeEndpoint"
107
- type="url"
108
- placeholder="https://api.example.com/v1"
109
- />
140
+ <span>Description</span>
141
+ <textarea
142
+ id="nodeDescription"
143
+ name="nodeDescription"
144
+ rows="3"
145
+ ></textarea>
110
146
  </label>
147
+ </div>
111
148
 
112
- <label class="field wide">
113
- <span>API token</span>
149
+ <section id="agentSection" class="agent-section" hidden>
150
+ <label id="agentWorkspaceField" class="field wide">
151
+ <span>Workspace folder</span>
114
152
  <input
115
- id="nodeToken"
116
- name="nodeToken"
117
- type="password"
118
- placeholder="Stored outside the diagram model"
153
+ id="nodeWorkspaceFolder"
154
+ name="nodeWorkspaceFolder"
155
+ type="text"
156
+ readonly
119
157
  />
120
158
  </label>
121
159
 
122
- <label class="field">
123
- <span>Timeout</span>
160
+ <label class="field wide">
161
+ <span>System prompt</span>
162
+ <textarea
163
+ id="nodeSystemPrompt"
164
+ name="nodeSystemPrompt"
165
+ rows="5"
166
+ placeholder="You are a helpful assistant…"
167
+ ></textarea>
168
+ </label>
169
+ <label class="field wide checkbox-field">
124
170
  <input
125
- id="nodeTimeout"
126
- name="nodeTimeout"
127
- type="number"
128
- min="1"
129
- max="120"
130
- step="1"
171
+ id="nodeRequiresUserInput"
172
+ name="nodeRequiresUserInput"
173
+ type="checkbox"
131
174
  />
175
+ <span>Require a user input</span>
132
176
  </label>
133
-
134
- <label class="field">
135
- <span>Retry policy</span>
136
- <select id="nodeRetryPolicy" name="nodeRetryPolicy">
137
- <option value="none">None</option>
138
- <option value="linear">Linear</option>
139
- <option value="exponential">Exponential</option>
140
- </select>
141
- </label>
142
-
143
- <label class="field wide">
144
- <span>Description</span>
177
+ <label
178
+ id="agentUserInputDescriptionField"
179
+ class="field wide"
180
+ hidden
181
+ >
182
+ <span>Describe User input</span>
145
183
  <textarea
146
- id="nodeDescription"
147
- name="nodeDescription"
184
+ id="nodeUserInputDescription"
185
+ name="nodeUserInputDescription"
148
186
  rows="3"
187
+ placeholder="Describe exactly what the user must provide before running this agent."
149
188
  ></textarea>
150
189
  </label>
151
- </div>
190
+ <label class="field wide">
191
+ <span>Required output marker</span>
192
+ <input
193
+ id="nodeExpectedOutputMarker"
194
+ name="nodeExpectedOutputMarker"
195
+ type="text"
196
+ placeholder="Optional, e.g. ```mermaid"
197
+ />
198
+ </label>
199
+ </section>
152
200
 
153
201
  <section id="mcpInventory" class="mcp-inventory" hidden>
154
202
  <div class="inventory-header">
@@ -193,16 +241,24 @@
193
241
  </section>
194
242
 
195
243
  <footer class="panel-actions">
196
- <button
197
- id="testNodeButton"
198
- class="secondary-button"
199
- type="button"
200
- >
201
- Test
202
- </button>
203
- <button id="saveNodeButton" class="primary-button" type="submit">
204
- Apply
205
- </button>
244
+ <div class="panel-actions-left">
245
+ <button
246
+ id="testNodeButton"
247
+ class="secondary-button"
248
+ type="button"
249
+ >
250
+ Test
251
+ </button>
252
+ </div>
253
+ <div class="panel-actions-right">
254
+ <button
255
+ id="deleteNodeButton"
256
+ class="danger-button"
257
+ type="button"
258
+ >
259
+ Delete
260
+ </button>
261
+ </div>
206
262
  </footer>
207
263
  </form>
208
264
  </canvas>
@@ -210,6 +266,37 @@
210
266
  <div id="fallbackPanelHost" class="fallback-panel-host" hidden></div>
211
267
  </section>
212
268
 
269
+ <div id="renameConfirmOverlay" class="confirm-overlay" hidden>
270
+ <section
271
+ class="confirm-dialog"
272
+ role="dialog"
273
+ aria-modal="true"
274
+ aria-labelledby="renameConfirmTitle"
275
+ >
276
+ <div>
277
+ <p class="confirm-kicker">Renommage de dossier</p>
278
+ <h2 id="renameConfirmTitle">Renommer le dossier ?</h2>
279
+ <p id="renameConfirmMessage" class="confirm-message"></p>
280
+ </div>
281
+ <footer class="confirm-actions">
282
+ <button
283
+ id="cancelRenameButton"
284
+ class="secondary-button"
285
+ type="button"
286
+ >
287
+ Annuler
288
+ </button>
289
+ <button
290
+ id="confirmRenameButton"
291
+ class="primary-button"
292
+ type="button"
293
+ >
294
+ Renommer
295
+ </button>
296
+ </footer>
297
+ </section>
298
+ </div>
299
+
213
300
  <div id="deleteConfirmOverlay" class="confirm-overlay" hidden>
214
301
  <section
215
302
  class="confirm-dialog"
@@ -240,8 +327,71 @@
240
327
  </footer>
241
328
  </section>
242
329
  </div>
330
+
331
+ <div id="agentRunOverlay" class="confirm-overlay" hidden>
332
+ <section
333
+ class="agent-run-dialog"
334
+ role="dialog"
335
+ aria-modal="true"
336
+ aria-labelledby="agentRunTitle"
337
+ >
338
+ <div>
339
+ <p class="confirm-kicker">Agent test</p>
340
+ <h2 id="agentRunTitle">Run agent</h2>
341
+ <p id="agentRunHint" class="confirm-message"></p>
342
+ </div>
343
+
344
+ <label
345
+ id="agentRunInputField"
346
+ class="field wide agent-run-input-field"
347
+ >
348
+ <span>User input</span>
349
+ <textarea
350
+ id="agentRunInput"
351
+ name="agentRunInput"
352
+ rows="6"
353
+ placeholder="Document ID, question, or any input for the agent…"
354
+ ></textarea>
355
+ </label>
356
+
357
+ <div id="agentRunResult" class="agent-run-result" hidden></div>
358
+
359
+ <footer class="confirm-actions">
360
+ <button
361
+ id="cancelAgentRunButton"
362
+ class="secondary-button"
363
+ type="button"
364
+ >
365
+ Close
366
+ </button>
367
+ <button
368
+ id="executeAgentRunButton"
369
+ class="primary-button"
370
+ type="button"
371
+ >
372
+ Run
373
+ </button>
374
+ </footer>
375
+ </section>
376
+ </div>
243
377
  </main>
244
378
 
245
- <script type="module" src="./app.js?v=workspace-persistence-1"></script>
379
+ <div
380
+ id="workspaceToast"
381
+ class="workspace-toast"
382
+ role="status"
383
+ aria-live="polite"
384
+ hidden
385
+ >
386
+ <span id="workspaceToastIcon" class="toast-icon" aria-hidden="true"
387
+ >✓</span
388
+ >
389
+ <span id="workspaceToastMessage">Workspace saved</span>
390
+ </div>
391
+
392
+ <script
393
+ type="module"
394
+ src="/workspace/app.js?v=workspace-agent-panel-1"
395
+ ></script>
246
396
  </body>
247
397
  </html>
@@ -34,4 +34,65 @@ export async function saveWorkspaceState(document) {
34
34
  return null;
35
35
  }
36
36
  }
37
+ export async function listLlmModels(input) {
38
+ try {
39
+ const response = await fetch(`${WORKSPACE_API_URL}/list-models`, {
40
+ method: "POST",
41
+ headers: {
42
+ Accept: "application/json",
43
+ "Content-Type": "application/json",
44
+ },
45
+ body: JSON.stringify(input),
46
+ });
47
+ return (await response.json());
48
+ }
49
+ catch (error) {
50
+ return {
51
+ ok: false,
52
+ error: error instanceof Error ? error.message : "Failed to list models",
53
+ };
54
+ }
55
+ }
56
+ export async function runAgentPrompt(input) {
57
+ try {
58
+ const response = await fetch(`${WORKSPACE_API_URL}/run-agent`, {
59
+ method: "POST",
60
+ headers: {
61
+ Accept: "application/json",
62
+ "Content-Type": "application/json",
63
+ },
64
+ body: JSON.stringify(input),
65
+ });
66
+ return (await response.json());
67
+ }
68
+ catch (error) {
69
+ return {
70
+ ok: false,
71
+ error: error instanceof Error ? error.message : "Agent run failed",
72
+ };
73
+ }
74
+ }
75
+ export async function testLlmConnection(input) {
76
+ try {
77
+ const response = await fetch(`${WORKSPACE_API_URL}/test-llm`, {
78
+ method: "POST",
79
+ headers: {
80
+ Accept: "application/json",
81
+ "Content-Type": "application/json",
82
+ },
83
+ body: JSON.stringify(input),
84
+ });
85
+ const result = (await response.json());
86
+ return {
87
+ ...result,
88
+ ok: response.ok && result.ok === true,
89
+ };
90
+ }
91
+ catch (error) {
92
+ return {
93
+ ok: false,
94
+ error: error instanceof Error ? error.message : "Connection test failed",
95
+ };
96
+ }
97
+ }
37
98
  //# sourceMappingURL=persistence.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"persistence.js","sourceRoot":"","sources":["persistence.ts"],"names":[],"mappings":"AAAA,MAAM,iBAAiB,GAAG,gBAAgB,CAAC;AAa3C,MAAM,CAAC,KAAK,UAAU,kBAAkB;IACtC,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,iBAAiB,EAAE;YAC9C,OAAO,EAAE,EAAE,MAAM,EAAE,kBAAkB,EAAE;SACxC,CAAC,CAAC;QACH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,MAAM,IAAI,KAAK,CAAC,8BAA8B,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;QACnE,CAAC;QACD,OAAO,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAA+B,CAAC;IAC/D,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,IAAI,CAAC,yBAAyB,EAAE,KAAK,CAAC,CAAC;QAC/C,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,QAAoC;IAEpC,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,iBAAiB,EAAE;YAC9C,MAAM,EAAE,KAAK;YACb,OAAO,EAAE;gBACP,MAAM,EAAE,kBAAkB;gBAC1B,cAAc,EAAE,kBAAkB;aACnC;YACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC;SAC/B,CAAC,CAAC;QACH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,MAAM,IAAI,KAAK,CAAC,8BAA8B,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;QACnE,CAAC;QACD,OAAO,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAA+B,CAAC;IAC/D,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,IAAI,CAAC,yBAAyB,EAAE,KAAK,CAAC,CAAC;QAC/C,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"persistence.js","sourceRoot":"","sources":["persistence.ts"],"names":[],"mappings":"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"}
@@ -47,3 +47,114 @@ export async function saveWorkspaceState(
47
47
  return null;
48
48
  }
49
49
  }
50
+
51
+ export interface LlmConnectionTestInput {
52
+ endpoint: string;
53
+ token: string;
54
+ model: string;
55
+ timeout: number;
56
+ }
57
+
58
+ export interface LlmConnectionTestResult {
59
+ ok: boolean;
60
+ status?: number;
61
+ statusText?: string;
62
+ url?: string;
63
+ detail?: string;
64
+ error?: string;
65
+ }
66
+
67
+ export interface LlmListModelsInput {
68
+ endpoint: string;
69
+ token: string;
70
+ }
71
+
72
+ export interface LlmListModelsResult {
73
+ ok: boolean;
74
+ models?: string[];
75
+ error?: string;
76
+ }
77
+
78
+ export async function listLlmModels(
79
+ input: LlmListModelsInput,
80
+ ): Promise<LlmListModelsResult> {
81
+ try {
82
+ const response = await fetch(`${WORKSPACE_API_URL}/list-models`, {
83
+ method: "POST",
84
+ headers: {
85
+ Accept: "application/json",
86
+ "Content-Type": "application/json",
87
+ },
88
+ body: JSON.stringify(input),
89
+ });
90
+ return (await response.json()) as LlmListModelsResult;
91
+ } catch (error) {
92
+ return {
93
+ ok: false,
94
+ error: error instanceof Error ? error.message : "Failed to list models",
95
+ };
96
+ }
97
+ }
98
+
99
+ export interface AgentRunInput {
100
+ endpoint: string;
101
+ token: string;
102
+ model: string;
103
+ systemPrompt: string;
104
+ userInput?: string;
105
+ timeout: number;
106
+ mcpEndpoint?: string;
107
+ expectedOutputMarker?: string;
108
+ }
109
+
110
+ export interface AgentRunResult {
111
+ ok: boolean;
112
+ content?: string;
113
+ error?: string;
114
+ }
115
+
116
+ export async function runAgentPrompt(
117
+ input: AgentRunInput,
118
+ ): Promise<AgentRunResult> {
119
+ try {
120
+ const response = await fetch(`${WORKSPACE_API_URL}/run-agent`, {
121
+ method: "POST",
122
+ headers: {
123
+ Accept: "application/json",
124
+ "Content-Type": "application/json",
125
+ },
126
+ body: JSON.stringify(input),
127
+ });
128
+ return (await response.json()) as AgentRunResult;
129
+ } catch (error) {
130
+ return {
131
+ ok: false,
132
+ error: error instanceof Error ? error.message : "Agent run failed",
133
+ };
134
+ }
135
+ }
136
+
137
+ export async function testLlmConnection(
138
+ input: LlmConnectionTestInput,
139
+ ): Promise<LlmConnectionTestResult> {
140
+ try {
141
+ const response = await fetch(`${WORKSPACE_API_URL}/test-llm`, {
142
+ method: "POST",
143
+ headers: {
144
+ Accept: "application/json",
145
+ "Content-Type": "application/json",
146
+ },
147
+ body: JSON.stringify(input),
148
+ });
149
+ const result = (await response.json()) as LlmConnectionTestResult;
150
+ return {
151
+ ...result,
152
+ ok: response.ok && result.ok === true,
153
+ };
154
+ } catch (error) {
155
+ return {
156
+ ok: false,
157
+ error: error instanceof Error ? error.message : "Connection test failed",
158
+ };
159
+ }
160
+ }