@rogatio/cli 5.0.0 → 5.1.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.
- package/README.md +21 -0
- package/dist/editor/index.js +485 -61
- package/dist/node/index.js +3741 -2951
- package/package.json +2 -2
package/dist/editor/index.js
CHANGED
|
@@ -214,6 +214,360 @@ var HTTP_METHODS = Object.freeze([
|
|
|
214
214
|
"TRACE"
|
|
215
215
|
]);
|
|
216
216
|
|
|
217
|
+
// packages/editor/src/ai-assist-panel.ts
|
|
218
|
+
function createAIAssistPanel(_container, editor, onApply, onClose) {
|
|
219
|
+
let visible = false;
|
|
220
|
+
let streamingContent = "";
|
|
221
|
+
let streamingMessageIndex = -1;
|
|
222
|
+
const messages = [];
|
|
223
|
+
const panel = document.createElement("div");
|
|
224
|
+
panel.className = "ai-assist-panel";
|
|
225
|
+
panel.style.cssText = `
|
|
226
|
+
position: fixed;
|
|
227
|
+
top: 0;
|
|
228
|
+
right: 0;
|
|
229
|
+
bottom: 0;
|
|
230
|
+
width: 400px;
|
|
231
|
+
max-width: 100vw;
|
|
232
|
+
background: #1e1e24;
|
|
233
|
+
border-left: 1px solid #333;
|
|
234
|
+
display: flex;
|
|
235
|
+
flex-direction: column;
|
|
236
|
+
z-index: 1000;
|
|
237
|
+
transform: translateX(100%);
|
|
238
|
+
transition: transform 0.2s ease;
|
|
239
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
|
240
|
+
font-size: 13px;
|
|
241
|
+
color: #e0e0e0;
|
|
242
|
+
`;
|
|
243
|
+
const header = document.createElement("div");
|
|
244
|
+
header.style.cssText = `
|
|
245
|
+
padding: 12px 16px;
|
|
246
|
+
border-bottom: 1px solid #333;
|
|
247
|
+
display: flex;
|
|
248
|
+
align-items: center;
|
|
249
|
+
justify-content: space-between;
|
|
250
|
+
background: #15151a;
|
|
251
|
+
`;
|
|
252
|
+
header.innerHTML = `
|
|
253
|
+
<div style="display: flex; align-items: center; gap: 8px;">
|
|
254
|
+
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
255
|
+
<path d="M12 2a10 10 0 1 0 10 10A10 10 0 0 0 12 2zm0 18a8 8 0 1 1 8-8 8 8 0 0 1-8 8z"/>
|
|
256
|
+
<path d="M12 6v6l4 2"/>
|
|
257
|
+
</svg>
|
|
258
|
+
<span style="font-weight: 600;">AI Assist</span>
|
|
259
|
+
</div>
|
|
260
|
+
<button class="ai-close-btn" style="
|
|
261
|
+
background: none;
|
|
262
|
+
border: none;
|
|
263
|
+
color: #888;
|
|
264
|
+
cursor: pointer;
|
|
265
|
+
padding: 4px;
|
|
266
|
+
border-radius: 4px;
|
|
267
|
+
">
|
|
268
|
+
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
269
|
+
<line x1="18" y1="6" x2="6" y2="18"/>
|
|
270
|
+
<line x1="6" y1="6" x2="18" y2="18"/>
|
|
271
|
+
</svg>
|
|
272
|
+
</button>
|
|
273
|
+
`;
|
|
274
|
+
const messagesContainer = document.createElement("div");
|
|
275
|
+
messagesContainer.style.cssText = `
|
|
276
|
+
flex: 1;
|
|
277
|
+
overflow-y: auto;
|
|
278
|
+
padding: 16px;
|
|
279
|
+
display: flex;
|
|
280
|
+
flex-direction: column;
|
|
281
|
+
gap: 12px;
|
|
282
|
+
`;
|
|
283
|
+
const inputContainer = document.createElement("div");
|
|
284
|
+
inputContainer.style.cssText = `
|
|
285
|
+
padding: 12px 16px;
|
|
286
|
+
border-top: 1px solid #333;
|
|
287
|
+
background: #15151a;
|
|
288
|
+
`;
|
|
289
|
+
const inputWrapper = document.createElement("div");
|
|
290
|
+
inputWrapper.style.cssText = `
|
|
291
|
+
display: flex;
|
|
292
|
+
gap: 8px;
|
|
293
|
+
margin-bottom: 8px;
|
|
294
|
+
`;
|
|
295
|
+
const textarea = document.createElement("textarea");
|
|
296
|
+
textarea.placeholder = "Ask AI to generate rules, fix issues, or explain...";
|
|
297
|
+
textarea.style.cssText = `
|
|
298
|
+
flex: 1;
|
|
299
|
+
background: #2a2a34;
|
|
300
|
+
border: 1px solid #3a3a48;
|
|
301
|
+
border-radius: 8px;
|
|
302
|
+
padding: 10px 12px;
|
|
303
|
+
color: #e0e0e0;
|
|
304
|
+
font-family: inherit;
|
|
305
|
+
font-size: 13px;
|
|
306
|
+
resize: none;
|
|
307
|
+
min-height: 60px;
|
|
308
|
+
max-height: 150px;
|
|
309
|
+
outline: none;
|
|
310
|
+
`;
|
|
311
|
+
const sendButton = document.createElement("button");
|
|
312
|
+
sendButton.textContent = "Send";
|
|
313
|
+
sendButton.style.cssText = `
|
|
314
|
+
background: #3b82f6;
|
|
315
|
+
color: white;
|
|
316
|
+
border: none;
|
|
317
|
+
border-radius: 8px;
|
|
318
|
+
padding: 10px 20px;
|
|
319
|
+
font-weight: 600;
|
|
320
|
+
cursor: pointer;
|
|
321
|
+
align-self: flex-end;
|
|
322
|
+
transition: background 0.2s;
|
|
323
|
+
`;
|
|
324
|
+
const statusText = document.createElement("div");
|
|
325
|
+
statusText.style.cssText = `
|
|
326
|
+
font-size: 11px;
|
|
327
|
+
color: #666;
|
|
328
|
+
text-align: center;
|
|
329
|
+
`;
|
|
330
|
+
inputWrapper.appendChild(textarea);
|
|
331
|
+
inputWrapper.appendChild(sendButton);
|
|
332
|
+
inputContainer.appendChild(inputWrapper);
|
|
333
|
+
inputContainer.appendChild(statusText);
|
|
334
|
+
panel.appendChild(header);
|
|
335
|
+
panel.appendChild(messagesContainer);
|
|
336
|
+
panel.appendChild(inputContainer);
|
|
337
|
+
const closeBtn = header.querySelector(".ai-close-btn");
|
|
338
|
+
function show() {
|
|
339
|
+
if (!visible) {
|
|
340
|
+
visible = true;
|
|
341
|
+
document.body.appendChild(panel);
|
|
342
|
+
requestAnimationFrame(() => {
|
|
343
|
+
panel.style.transform = "translateX(0)";
|
|
344
|
+
});
|
|
345
|
+
textarea.focus();
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
function hide() {
|
|
349
|
+
if (visible) {
|
|
350
|
+
visible = false;
|
|
351
|
+
panel.style.transform = "translateX(100%)";
|
|
352
|
+
setTimeout(() => {
|
|
353
|
+
if (!visible && panel.parentNode) {
|
|
354
|
+
panel.parentNode.removeChild(panel);
|
|
355
|
+
}
|
|
356
|
+
}, 200);
|
|
357
|
+
onClose();
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
function isVisible() {
|
|
361
|
+
return visible;
|
|
362
|
+
}
|
|
363
|
+
function addMessage(message) {
|
|
364
|
+
const messageEl = document.createElement("div");
|
|
365
|
+
messageEl.style.cssText = `
|
|
366
|
+
display: flex;
|
|
367
|
+
flex-direction: column;
|
|
368
|
+
gap: 8px;
|
|
369
|
+
max-width: 85%;
|
|
370
|
+
${message.role === "user" ? "align-self: flex-end;" : "align-self: flex-start;"}
|
|
371
|
+
`;
|
|
372
|
+
const bubble = document.createElement("div");
|
|
373
|
+
bubble.style.cssText = `
|
|
374
|
+
padding: 10px 14px;
|
|
375
|
+
border-radius: 16px;
|
|
376
|
+
${message.role === "user" ? "background: #3b82f6; color: white; border-bottom-right-radius: 4px;" : "background: #2a2a34; color: #e0e0e0; border-bottom-left-radius: 4px;"}
|
|
377
|
+
white-space: pre-wrap;
|
|
378
|
+
word-wrap: break-word;
|
|
379
|
+
`;
|
|
380
|
+
bubble.textContent = message.content;
|
|
381
|
+
messageEl.appendChild(bubble);
|
|
382
|
+
if (message.proposal) {
|
|
383
|
+
const proposalEl = createProposalElement(message.proposal);
|
|
384
|
+
messageEl.appendChild(proposalEl);
|
|
385
|
+
}
|
|
386
|
+
messagesContainer.appendChild(messageEl);
|
|
387
|
+
messagesContainer.scrollTop = messagesContainer.scrollHeight;
|
|
388
|
+
}
|
|
389
|
+
function createProposalElement(proposal) {
|
|
390
|
+
const container = document.createElement("div");
|
|
391
|
+
container.style.cssText = `
|
|
392
|
+
margin-top: 8px;
|
|
393
|
+
padding: 12px;
|
|
394
|
+
background: #1a1a24;
|
|
395
|
+
border: 1px solid #333;
|
|
396
|
+
border-radius: 8px;
|
|
397
|
+
`;
|
|
398
|
+
const explanation = document.createElement("div");
|
|
399
|
+
explanation.style.cssText = `
|
|
400
|
+
font-size: 12px;
|
|
401
|
+
color: #aaa;
|
|
402
|
+
margin-bottom: 12px;
|
|
403
|
+
line-height: 1.5;
|
|
404
|
+
`;
|
|
405
|
+
explanation.textContent = proposal.explanation;
|
|
406
|
+
container.appendChild(explanation);
|
|
407
|
+
const rulesList = document.createElement("div");
|
|
408
|
+
rulesList.style.cssText = `
|
|
409
|
+
display: flex;
|
|
410
|
+
flex-direction: column;
|
|
411
|
+
gap: 8px;
|
|
412
|
+
`;
|
|
413
|
+
for (const rule of proposal.rules) {
|
|
414
|
+
const ruleEl = document.createElement("div");
|
|
415
|
+
ruleEl.style.cssText = `
|
|
416
|
+
padding: 10px;
|
|
417
|
+
background: #2a2a34;
|
|
418
|
+
border-radius: 6px;
|
|
419
|
+
border: 1px solid #3a3a48;
|
|
420
|
+
`;
|
|
421
|
+
const ruleHeader = document.createElement("div");
|
|
422
|
+
ruleHeader.style.cssText = `
|
|
423
|
+
display: flex;
|
|
424
|
+
align-items: center;
|
|
425
|
+
gap: 8px;
|
|
426
|
+
margin-bottom: 8px;
|
|
427
|
+
`;
|
|
428
|
+
const kindBadge = document.createElement("span");
|
|
429
|
+
kindBadge.textContent = rule.kind;
|
|
430
|
+
kindBadge.style.cssText = `
|
|
431
|
+
font-size: 10px;
|
|
432
|
+
font-weight: 600;
|
|
433
|
+
text-transform: uppercase;
|
|
434
|
+
padding: 2px 8px;
|
|
435
|
+
border-radius: 4px;
|
|
436
|
+
background: #3b82f6;
|
|
437
|
+
color: white;
|
|
438
|
+
`;
|
|
439
|
+
const ruleName = document.createElement("span");
|
|
440
|
+
ruleName.textContent = rule.name;
|
|
441
|
+
ruleName.style.cssText = `
|
|
442
|
+
font-weight: 500;
|
|
443
|
+
flex: 1;
|
|
444
|
+
`;
|
|
445
|
+
ruleHeader.appendChild(kindBadge);
|
|
446
|
+
ruleHeader.appendChild(ruleName);
|
|
447
|
+
const ruleDetails = document.createElement("div");
|
|
448
|
+
ruleDetails.style.cssText = `
|
|
449
|
+
font-size: 11px;
|
|
450
|
+
color: #888;
|
|
451
|
+
display: grid;
|
|
452
|
+
grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
|
|
453
|
+
gap: 4px 12px;
|
|
454
|
+
`;
|
|
455
|
+
const addDetail = (label, value) => {
|
|
456
|
+
const detail = document.createElement("div");
|
|
457
|
+
detail.innerHTML = `<span style="color:#666;">${label}:</span> ${value}`;
|
|
458
|
+
ruleDetails.appendChild(detail);
|
|
459
|
+
};
|
|
460
|
+
addDetail("Regex", rule.urlRegex);
|
|
461
|
+
if (rule.origins?.length) addDetail("Origins", rule.origins.join(", "));
|
|
462
|
+
if (rule.resourceTypes?.length)
|
|
463
|
+
addDetail("Types", rule.resourceTypes.join(", "));
|
|
464
|
+
if (rule.priority !== void 0)
|
|
465
|
+
addDetail("Priority", rule.priority.toString());
|
|
466
|
+
if (rule.method) addDetail("Method", rule.method);
|
|
467
|
+
const actionBtn = document.createElement("button");
|
|
468
|
+
actionBtn.textContent = "Apply Rule";
|
|
469
|
+
actionBtn.style.cssText = `
|
|
470
|
+
margin-top: 10px;
|
|
471
|
+
width: 100%;
|
|
472
|
+
background: #22c55e;
|
|
473
|
+
color: white;
|
|
474
|
+
border: none;
|
|
475
|
+
border-radius: 6px;
|
|
476
|
+
padding: 8px;
|
|
477
|
+
font-weight: 600;
|
|
478
|
+
cursor: pointer;
|
|
479
|
+
transition: background 0.2s;
|
|
480
|
+
`;
|
|
481
|
+
actionBtn.addEventListener("click", () => {
|
|
482
|
+
onApply(proposal);
|
|
483
|
+
});
|
|
484
|
+
ruleEl.appendChild(ruleHeader);
|
|
485
|
+
ruleEl.appendChild(ruleDetails);
|
|
486
|
+
ruleEl.appendChild(actionBtn);
|
|
487
|
+
rulesList.appendChild(ruleEl);
|
|
488
|
+
}
|
|
489
|
+
container.appendChild(rulesList);
|
|
490
|
+
return container;
|
|
491
|
+
}
|
|
492
|
+
function clearMessages() {
|
|
493
|
+
messages.length = 0;
|
|
494
|
+
streamingContent = "";
|
|
495
|
+
streamingMessageIndex = -1;
|
|
496
|
+
messagesContainer.innerHTML = "";
|
|
497
|
+
}
|
|
498
|
+
function updateStreamingContent(content) {
|
|
499
|
+
if (streamingMessageIndex >= 0 && streamingMessageIndex < messages.length) {
|
|
500
|
+
const message = messages[streamingMessageIndex];
|
|
501
|
+
message.content = streamingContent + content;
|
|
502
|
+
const bubbles = messagesContainer.querySelectorAll(
|
|
503
|
+
"div > div:first-child"
|
|
504
|
+
);
|
|
505
|
+
if (bubbles[streamingMessageIndex]) {
|
|
506
|
+
bubbles[streamingMessageIndex].textContent = message.content;
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
function startStreaming(role) {
|
|
511
|
+
streamingContent = "";
|
|
512
|
+
const message = { role, content: "", isStreaming: true };
|
|
513
|
+
messages.push(message);
|
|
514
|
+
streamingMessageIndex = messages.length - 1;
|
|
515
|
+
addMessage(message);
|
|
516
|
+
}
|
|
517
|
+
function finishStreaming(proposal) {
|
|
518
|
+
if (streamingMessageIndex >= 0 && streamingMessageIndex < messages.length) {
|
|
519
|
+
const message = messages[streamingMessageIndex];
|
|
520
|
+
message.isStreaming = false;
|
|
521
|
+
if (proposal) message.proposal = proposal;
|
|
522
|
+
const messageEls = messagesContainer.children;
|
|
523
|
+
if (messageEls[streamingMessageIndex]) {
|
|
524
|
+
const existingProposal = messageEls[streamingMessageIndex].querySelector("div > div:last-child");
|
|
525
|
+
if (proposal) {
|
|
526
|
+
if (existingProposal) existingProposal.remove();
|
|
527
|
+
const proposalEl = createProposalElement(proposal);
|
|
528
|
+
messageEls[streamingMessageIndex].appendChild(
|
|
529
|
+
proposalEl
|
|
530
|
+
);
|
|
531
|
+
}
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
streamingContent = "";
|
|
535
|
+
streamingMessageIndex = -1;
|
|
536
|
+
}
|
|
537
|
+
function handleSend() {
|
|
538
|
+
const prompt = textarea.value.trim();
|
|
539
|
+
if (!prompt) return;
|
|
540
|
+
const _request = {
|
|
541
|
+
kind: "generate",
|
|
542
|
+
prompt,
|
|
543
|
+
context: {
|
|
544
|
+
project: editor.getDraft()
|
|
545
|
+
}
|
|
546
|
+
};
|
|
547
|
+
textarea.value = "";
|
|
548
|
+
textarea.style.height = "auto";
|
|
549
|
+
}
|
|
550
|
+
closeBtn.addEventListener("click", hide);
|
|
551
|
+
sendButton.addEventListener("click", handleSend);
|
|
552
|
+
textarea.addEventListener("keydown", (e) => {
|
|
553
|
+
if (e.key === "Enter" && !e.shiftKey) {
|
|
554
|
+
e.preventDefault();
|
|
555
|
+
handleSend();
|
|
556
|
+
}
|
|
557
|
+
});
|
|
558
|
+
return {
|
|
559
|
+
show,
|
|
560
|
+
hide,
|
|
561
|
+
isVisible,
|
|
562
|
+
addMessage,
|
|
563
|
+
clearMessages,
|
|
564
|
+
// Expose streaming methods for the aiAssist handler to use
|
|
565
|
+
startStreaming,
|
|
566
|
+
updateStreamingContent,
|
|
567
|
+
finishStreaming
|
|
568
|
+
};
|
|
569
|
+
}
|
|
570
|
+
|
|
217
571
|
// packages/editor/src/rule-types/mock.ts
|
|
218
572
|
function isRecord(value) {
|
|
219
573
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
@@ -340,7 +694,7 @@ function createMockRuleType() {
|
|
|
340
694
|
return stable(diagnostics);
|
|
341
695
|
},
|
|
342
696
|
mount(context) {
|
|
343
|
-
const { document, container } = context;
|
|
697
|
+
const { document: document2, container } = context;
|
|
344
698
|
const getCurrent = () => asMockAction(context.getField("mock"));
|
|
345
699
|
const setAction = (next) => {
|
|
346
700
|
context.setField("mock", next);
|
|
@@ -349,9 +703,9 @@ function createMockRuleType() {
|
|
|
349
703
|
const current = getCurrent();
|
|
350
704
|
container.replaceChildren();
|
|
351
705
|
if (current === void 0) return;
|
|
352
|
-
const statusLabel =
|
|
706
|
+
const statusLabel = document2.createElement("label");
|
|
353
707
|
statusLabel.textContent = "Status";
|
|
354
|
-
const statusInput =
|
|
708
|
+
const statusInput = document2.createElement("input");
|
|
355
709
|
statusInput.type = "number";
|
|
356
710
|
statusInput.min = String(LIMITS.minMockStatus);
|
|
357
711
|
statusInput.max = String(LIMITS.maxMockStatus);
|
|
@@ -365,9 +719,9 @@ function createMockRuleType() {
|
|
|
365
719
|
});
|
|
366
720
|
context.registerControl("/mock/status", statusInput);
|
|
367
721
|
statusLabel.append(statusInput);
|
|
368
|
-
const delayLabel =
|
|
722
|
+
const delayLabel = document2.createElement("label");
|
|
369
723
|
delayLabel.textContent = "Delay (ms)";
|
|
370
|
-
const delayInput =
|
|
724
|
+
const delayInput = document2.createElement("input");
|
|
371
725
|
delayInput.type = "number";
|
|
372
726
|
delayInput.min = "0";
|
|
373
727
|
delayInput.max = String(LIMITS.maxMockDelayMs);
|
|
@@ -383,20 +737,20 @@ function createMockRuleType() {
|
|
|
383
737
|
});
|
|
384
738
|
context.registerControl("/mock/delayMs", delayInput);
|
|
385
739
|
delayLabel.append(delayInput);
|
|
386
|
-
const sourceLabel =
|
|
740
|
+
const sourceLabel = document2.createElement("label");
|
|
387
741
|
sourceLabel.textContent = "Body source";
|
|
388
|
-
const sourceSelect =
|
|
742
|
+
const sourceSelect = document2.createElement("select");
|
|
389
743
|
sourceSelect.dataset.editorField = "true";
|
|
390
|
-
const bodyOption =
|
|
744
|
+
const bodyOption = document2.createElement("option");
|
|
391
745
|
bodyOption.value = "body";
|
|
392
746
|
bodyOption.textContent = "Inline body";
|
|
393
|
-
const fileOption =
|
|
747
|
+
const fileOption = document2.createElement("option");
|
|
394
748
|
fileOption.value = "file";
|
|
395
749
|
fileOption.textContent = "File snapshot";
|
|
396
750
|
sourceSelect.append(bodyOption, fileOption);
|
|
397
751
|
sourceSelect.value = typeof current.file === "string" ? "file" : "body";
|
|
398
752
|
context.registerControl("/mock/body-source", sourceSelect);
|
|
399
|
-
const bodyArea =
|
|
753
|
+
const bodyArea = document2.createElement("textarea");
|
|
400
754
|
bodyArea.value = typeof current.body === "string" ? current.body : "";
|
|
401
755
|
bodyArea.dataset.editorField = "true";
|
|
402
756
|
bodyArea.addEventListener("input", () => {
|
|
@@ -405,9 +759,9 @@ function createMockRuleType() {
|
|
|
405
759
|
setAction({ ...c, body: bodyArea.value, file: void 0 });
|
|
406
760
|
});
|
|
407
761
|
context.registerControl("/mock/body", bodyArea);
|
|
408
|
-
const fileLabel =
|
|
762
|
+
const fileLabel = document2.createElement("label");
|
|
409
763
|
fileLabel.textContent = "File path";
|
|
410
|
-
const fileInput =
|
|
764
|
+
const fileInput = document2.createElement("input");
|
|
411
765
|
fileInput.type = "text";
|
|
412
766
|
fileInput.value = typeof current.file === "string" ? current.file : "";
|
|
413
767
|
fileInput.dataset.editorField = "true";
|
|
@@ -425,8 +779,8 @@ function createMockRuleType() {
|
|
|
425
779
|
};
|
|
426
780
|
sourceSelect.addEventListener("change", syncSource);
|
|
427
781
|
syncSource();
|
|
428
|
-
const headersFieldset =
|
|
429
|
-
const headersLegend =
|
|
782
|
+
const headersFieldset = document2.createElement("fieldset");
|
|
783
|
+
const headersLegend = document2.createElement("legend");
|
|
430
784
|
headersLegend.textContent = "Response headers";
|
|
431
785
|
headersFieldset.append(headersLegend);
|
|
432
786
|
const renderHeaders = () => {
|
|
@@ -437,11 +791,11 @@ function createMockRuleType() {
|
|
|
437
791
|
});
|
|
438
792
|
const headers = c.headers ?? [];
|
|
439
793
|
headers.forEach((header, index) => {
|
|
440
|
-
const row =
|
|
794
|
+
const row = document2.createElement("div");
|
|
441
795
|
row.dataset.mockHeaderRow = String(index);
|
|
442
|
-
const nameLabel =
|
|
796
|
+
const nameLabel = document2.createElement("label");
|
|
443
797
|
nameLabel.textContent = "Name";
|
|
444
|
-
const nameInput =
|
|
798
|
+
const nameInput = document2.createElement("input");
|
|
445
799
|
nameInput.type = "text";
|
|
446
800
|
nameInput.value = header.name;
|
|
447
801
|
nameInput.dataset.editorField = "true";
|
|
@@ -455,9 +809,9 @@ function createMockRuleType() {
|
|
|
455
809
|
});
|
|
456
810
|
context.registerControl(`/mock/headers/${index}/name`, nameInput);
|
|
457
811
|
nameLabel.append(nameInput);
|
|
458
|
-
const valueLabel =
|
|
812
|
+
const valueLabel = document2.createElement("label");
|
|
459
813
|
valueLabel.textContent = "Value";
|
|
460
|
-
const valueInput =
|
|
814
|
+
const valueInput = document2.createElement("input");
|
|
461
815
|
valueInput.type = "text";
|
|
462
816
|
valueInput.value = header.value;
|
|
463
817
|
valueInput.dataset.editorField = "true";
|
|
@@ -471,7 +825,7 @@ function createMockRuleType() {
|
|
|
471
825
|
});
|
|
472
826
|
context.registerControl(`/mock/headers/${index}/value`, valueInput);
|
|
473
827
|
valueLabel.append(valueInput);
|
|
474
|
-
const remove =
|
|
828
|
+
const remove = document2.createElement("button");
|
|
475
829
|
remove.type = "button";
|
|
476
830
|
remove.textContent = "Remove";
|
|
477
831
|
remove.dataset.editorField = "true";
|
|
@@ -484,7 +838,7 @@ function createMockRuleType() {
|
|
|
484
838
|
row.append(nameLabel, valueLabel, remove);
|
|
485
839
|
headersFieldset.append(row);
|
|
486
840
|
});
|
|
487
|
-
const add =
|
|
841
|
+
const add = document2.createElement("button");
|
|
488
842
|
add.type = "button";
|
|
489
843
|
add.textContent = "Add header";
|
|
490
844
|
add.dataset.editorField = "true";
|
|
@@ -612,7 +966,7 @@ var queryRuleType = {
|
|
|
612
966
|
return stable2(diagnostics);
|
|
613
967
|
},
|
|
614
968
|
mount(context) {
|
|
615
|
-
const { document, container } = context;
|
|
969
|
+
const { document: document2, container } = context;
|
|
616
970
|
const getCurrent = () => asQueryAction(context.getField("action"));
|
|
617
971
|
const setAction = (next) => {
|
|
618
972
|
context.setField("action", next);
|
|
@@ -622,11 +976,11 @@ var queryRuleType = {
|
|
|
622
976
|
container.replaceChildren();
|
|
623
977
|
if (current === void 0) return;
|
|
624
978
|
current.params.forEach((param, index) => {
|
|
625
|
-
const row =
|
|
979
|
+
const row = document2.createElement("div");
|
|
626
980
|
row.dataset.queryParamRow = String(index);
|
|
627
|
-
const nameLabel =
|
|
981
|
+
const nameLabel = document2.createElement("label");
|
|
628
982
|
nameLabel.textContent = "Name";
|
|
629
|
-
const nameInput =
|
|
983
|
+
const nameInput = document2.createElement("input");
|
|
630
984
|
nameInput.type = "text";
|
|
631
985
|
nameInput.value = param.name;
|
|
632
986
|
nameInput.dataset.editorField = "true";
|
|
@@ -640,9 +994,9 @@ var queryRuleType = {
|
|
|
640
994
|
});
|
|
641
995
|
context.registerControl(`/action/params/${index}/name`, nameInput);
|
|
642
996
|
nameLabel.append(nameInput);
|
|
643
|
-
const valueLabel =
|
|
997
|
+
const valueLabel = document2.createElement("label");
|
|
644
998
|
valueLabel.textContent = "Value";
|
|
645
|
-
const valueInput =
|
|
999
|
+
const valueInput = document2.createElement("input");
|
|
646
1000
|
valueInput.type = "text";
|
|
647
1001
|
valueInput.value = param.value;
|
|
648
1002
|
valueInput.dataset.editorField = "true";
|
|
@@ -656,7 +1010,7 @@ var queryRuleType = {
|
|
|
656
1010
|
});
|
|
657
1011
|
context.registerControl(`/action/params/${index}/value`, valueInput);
|
|
658
1012
|
valueLabel.append(valueInput);
|
|
659
|
-
const remove =
|
|
1013
|
+
const remove = document2.createElement("button");
|
|
660
1014
|
remove.type = "button";
|
|
661
1015
|
remove.textContent = "Remove";
|
|
662
1016
|
remove.dataset.editorField = "true";
|
|
@@ -669,7 +1023,7 @@ var queryRuleType = {
|
|
|
669
1023
|
row.append(nameLabel, valueLabel, remove);
|
|
670
1024
|
container.append(row);
|
|
671
1025
|
});
|
|
672
|
-
const add =
|
|
1026
|
+
const add = document2.createElement("button");
|
|
673
1027
|
add.type = "button";
|
|
674
1028
|
add.textContent = "Add parameter";
|
|
675
1029
|
add.dataset.editorField = "true";
|
|
@@ -834,17 +1188,17 @@ function createRequestBodyRuleType() {
|
|
|
834
1188
|
return stable3(diagnostics);
|
|
835
1189
|
},
|
|
836
1190
|
mount(context) {
|
|
837
|
-
const { document, container } = context;
|
|
1191
|
+
const { document: document2, container } = context;
|
|
838
1192
|
const render = () => {
|
|
839
1193
|
const current = requestBodyOf(context.getField("requestBody"));
|
|
840
1194
|
container.replaceChildren();
|
|
841
1195
|
if (current === void 0) return;
|
|
842
|
-
const modeSelect =
|
|
1196
|
+
const modeSelect = document2.createElement("select");
|
|
843
1197
|
modeSelect.value = current.mode;
|
|
844
|
-
const replaceOption =
|
|
1198
|
+
const replaceOption = document2.createElement("option");
|
|
845
1199
|
replaceOption.value = "replace";
|
|
846
1200
|
replaceOption.textContent = "Replace body";
|
|
847
|
-
const regexOption =
|
|
1201
|
+
const regexOption = document2.createElement("option");
|
|
848
1202
|
regexOption.value = "regex";
|
|
849
1203
|
regexOption.textContent = "Regex replace";
|
|
850
1204
|
modeSelect.append(replaceOption, regexOption);
|
|
@@ -862,7 +1216,7 @@ function createRequestBodyRuleType() {
|
|
|
862
1216
|
context.registerControl("/requestBody/mode", modeSelect);
|
|
863
1217
|
container.append(modeSelect);
|
|
864
1218
|
if (current.mode === "replace") {
|
|
865
|
-
const bodyInput =
|
|
1219
|
+
const bodyInput = document2.createElement("textarea");
|
|
866
1220
|
bodyInput.value = current.body ?? "";
|
|
867
1221
|
bodyInput.placeholder = "Replacement body";
|
|
868
1222
|
bodyInput.addEventListener("input", () => {
|
|
@@ -872,7 +1226,7 @@ function createRequestBodyRuleType() {
|
|
|
872
1226
|
context.registerControl("/requestBody/body", bodyInput);
|
|
873
1227
|
container.append(bodyInput);
|
|
874
1228
|
} else {
|
|
875
|
-
const patternInput =
|
|
1229
|
+
const patternInput = document2.createElement("input");
|
|
876
1230
|
patternInput.type = "text";
|
|
877
1231
|
patternInput.value = current.pattern ?? "";
|
|
878
1232
|
patternInput.placeholder = "Regex pattern";
|
|
@@ -882,7 +1236,7 @@ function createRequestBodyRuleType() {
|
|
|
882
1236
|
});
|
|
883
1237
|
context.registerControl("/requestBody/pattern", patternInput);
|
|
884
1238
|
container.append(patternInput);
|
|
885
|
-
const replacementInput =
|
|
1239
|
+
const replacementInput = document2.createElement("input");
|
|
886
1240
|
replacementInput.type = "text";
|
|
887
1241
|
replacementInput.value = current.replacement ?? "";
|
|
888
1242
|
replacementInput.placeholder = "Replacement";
|
|
@@ -964,15 +1318,15 @@ function createResponseBodyRuleType() {
|
|
|
964
1318
|
return stable4(diagnostics);
|
|
965
1319
|
},
|
|
966
1320
|
mount(context) {
|
|
967
|
-
const { document, container } = context;
|
|
1321
|
+
const { document: document2, container } = context;
|
|
968
1322
|
const render = () => {
|
|
969
1323
|
const current = replacementsOf(context.getField("responseBody"));
|
|
970
1324
|
container.replaceChildren();
|
|
971
1325
|
if (current === void 0) return;
|
|
972
1326
|
current.forEach((entry, index) => {
|
|
973
|
-
const row =
|
|
1327
|
+
const row = document2.createElement("div");
|
|
974
1328
|
row.dataset.responseBodyReplacement = String(index);
|
|
975
|
-
const pattern =
|
|
1329
|
+
const pattern = document2.createElement("input");
|
|
976
1330
|
pattern.type = "text";
|
|
977
1331
|
pattern.value = entry.pattern;
|
|
978
1332
|
pattern.placeholder = "Pattern";
|
|
@@ -987,7 +1341,7 @@ function createResponseBodyRuleType() {
|
|
|
987
1341
|
`/responseBody/replacements/${index}/pattern`,
|
|
988
1342
|
pattern
|
|
989
1343
|
);
|
|
990
|
-
const replacement =
|
|
1344
|
+
const replacement = document2.createElement("input");
|
|
991
1345
|
replacement.type = "text";
|
|
992
1346
|
replacement.value = entry.replacement;
|
|
993
1347
|
replacement.placeholder = "Replacement";
|
|
@@ -1002,7 +1356,7 @@ function createResponseBodyRuleType() {
|
|
|
1002
1356
|
`/responseBody/replacements/${index}/replacement`,
|
|
1003
1357
|
replacement
|
|
1004
1358
|
);
|
|
1005
|
-
const remove =
|
|
1359
|
+
const remove = document2.createElement("button");
|
|
1006
1360
|
remove.type = "button";
|
|
1007
1361
|
remove.textContent = "Remove replacement";
|
|
1008
1362
|
remove.addEventListener("click", () => {
|
|
@@ -1013,7 +1367,7 @@ function createResponseBodyRuleType() {
|
|
|
1013
1367
|
row.append(pattern, replacement, remove);
|
|
1014
1368
|
container.append(row);
|
|
1015
1369
|
});
|
|
1016
|
-
const add =
|
|
1370
|
+
const add = document2.createElement("button");
|
|
1017
1371
|
add.type = "button";
|
|
1018
1372
|
add.textContent = "Add replacement";
|
|
1019
1373
|
add.addEventListener("click", () => {
|
|
@@ -1463,6 +1817,7 @@ var EditorControllerImpl = class {
|
|
|
1463
1817
|
testResult = void 0;
|
|
1464
1818
|
testRunning = false;
|
|
1465
1819
|
testRequestId = 0;
|
|
1820
|
+
aiAssistPanel = null;
|
|
1466
1821
|
constructor(options, initial, extensions) {
|
|
1467
1822
|
this.root = options.root;
|
|
1468
1823
|
this.document = options.root.ownerDocument;
|
|
@@ -1475,6 +1830,19 @@ var EditorControllerImpl = class {
|
|
|
1475
1830
|
if (initialDiagnostics.length > 0) {
|
|
1476
1831
|
throw new EditorInitializationError(initialDiagnostics);
|
|
1477
1832
|
}
|
|
1833
|
+
if (options.aiAssist) {
|
|
1834
|
+
this.aiAssistPanel = createAIAssistPanel(
|
|
1835
|
+
this.root,
|
|
1836
|
+
{
|
|
1837
|
+
getDraft: () => this.getDraft(),
|
|
1838
|
+
navigateToGroup: (groupId) => this.navigateToGroup(groupId)
|
|
1839
|
+
},
|
|
1840
|
+
(proposal) => this.applyAIProposal(proposal),
|
|
1841
|
+
() => {
|
|
1842
|
+
}
|
|
1843
|
+
// onClose
|
|
1844
|
+
);
|
|
1845
|
+
}
|
|
1478
1846
|
this.host = this.document.createElement("div");
|
|
1479
1847
|
this.host.className = "rogatio-editor";
|
|
1480
1848
|
this.host.dataset.rogatioEditor = "true";
|
|
@@ -1548,6 +1916,10 @@ var EditorControllerImpl = class {
|
|
|
1548
1916
|
destroy() {
|
|
1549
1917
|
if (this.destroyed) return;
|
|
1550
1918
|
this.destroyed = true;
|
|
1919
|
+
if (this.aiAssistPanel) {
|
|
1920
|
+
this.aiAssistPanel.hide();
|
|
1921
|
+
this.aiAssistPanel = null;
|
|
1922
|
+
}
|
|
1551
1923
|
this.cleanupExtensions();
|
|
1552
1924
|
this.host.removeEventListener("click", this.handleClick);
|
|
1553
1925
|
this.host.removeEventListener("input", this.handleInput);
|
|
@@ -1677,6 +2049,12 @@ var EditorControllerImpl = class {
|
|
|
1677
2049
|
}
|
|
1678
2050
|
};
|
|
1679
2051
|
dispatchCommand(command, element) {
|
|
2052
|
+
if (command === "ai-assist") {
|
|
2053
|
+
if (this.aiAssistPanel) {
|
|
2054
|
+
this.aiAssistPanel.show();
|
|
2055
|
+
}
|
|
2056
|
+
return;
|
|
2057
|
+
}
|
|
1680
2058
|
if (command === "validate") {
|
|
1681
2059
|
this.validate();
|
|
1682
2060
|
return;
|
|
@@ -2189,6 +2567,47 @@ var EditorControllerImpl = class {
|
|
|
2189
2567
|
this.focusRequest = failure.path;
|
|
2190
2568
|
this.render();
|
|
2191
2569
|
}
|
|
2570
|
+
applyAIProposal(proposal) {
|
|
2571
|
+
for (const ruleProposal of proposal.rules) {
|
|
2572
|
+
let group = this.groupById(ruleProposal.groupId);
|
|
2573
|
+
if (!group) {
|
|
2574
|
+
const groupId = ruleProposal.groupId;
|
|
2575
|
+
this.draft.groups.push({
|
|
2576
|
+
id: groupId,
|
|
2577
|
+
name: "AI Group",
|
|
2578
|
+
origins: [],
|
|
2579
|
+
rules: []
|
|
2580
|
+
});
|
|
2581
|
+
group = this.groupById(groupId);
|
|
2582
|
+
}
|
|
2583
|
+
if (!group) return;
|
|
2584
|
+
const ruleId = this.nextId("rule-ai");
|
|
2585
|
+
const rule = {
|
|
2586
|
+
id: ruleId,
|
|
2587
|
+
name: ruleProposal.name,
|
|
2588
|
+
urlRegex: ruleProposal.urlRegex,
|
|
2589
|
+
origins: ruleProposal.origins ?? [],
|
|
2590
|
+
resourceTypes: ruleProposal.resourceTypes ?? ["main_frame"],
|
|
2591
|
+
priority: ruleProposal.priority ?? 100
|
|
2592
|
+
};
|
|
2593
|
+
if (ruleProposal.method) {
|
|
2594
|
+
rule.method = ruleProposal.method;
|
|
2595
|
+
}
|
|
2596
|
+
const actionField = ruleProposal.kind === "redirect" || ruleProposal.kind === "mock" ? ruleProposal.kind : "action";
|
|
2597
|
+
rule[actionField] = ruleProposal.action;
|
|
2598
|
+
group.rules.push(rule);
|
|
2599
|
+
this.markChanged();
|
|
2600
|
+
this.focusRequest = pointer(
|
|
2601
|
+
"groups",
|
|
2602
|
+
this.groupIndex(group.id),
|
|
2603
|
+
"rules",
|
|
2604
|
+
group.rules.length - 1,
|
|
2605
|
+
"name"
|
|
2606
|
+
);
|
|
2607
|
+
}
|
|
2608
|
+
this.statusMessage = `Applied ${proposal.rules.length} rule${proposal.rules.length === 1 ? "" : "s"} from AI.`;
|
|
2609
|
+
this.render();
|
|
2610
|
+
}
|
|
2192
2611
|
addGroupOrigin(groupId) {
|
|
2193
2612
|
const group = this.groupById(groupId);
|
|
2194
2613
|
if (!group || this.saving) return;
|
|
@@ -2617,6 +3036,11 @@ var EditorControllerImpl = class {
|
|
|
2617
3036
|
renderCommandBar() {
|
|
2618
3037
|
this.commandBar.replaceChildren();
|
|
2619
3038
|
this.commandBar.setAttribute("aria-busy", this.saving ? "true" : "false");
|
|
3039
|
+
if (this.aiAssistPanel) {
|
|
3040
|
+
this.commandBar.append(
|
|
3041
|
+
this.createCommandButton("AI Assist", "ai-assist", this.saving)
|
|
3042
|
+
);
|
|
3043
|
+
}
|
|
2620
3044
|
this.commandBar.append(
|
|
2621
3045
|
this.createCommandButton("Validate", "validate", this.saving),
|
|
2622
3046
|
this.createCommandButton("Save", "save", this.saving || !this.isDirty()),
|
|
@@ -3596,10 +4020,10 @@ var HEADER_OPERATIONS = [
|
|
|
3596
4020
|
"append",
|
|
3597
4021
|
"remove"
|
|
3598
4022
|
];
|
|
3599
|
-
function createSelect(
|
|
3600
|
-
const select =
|
|
4023
|
+
function createSelect(document2, options, value, onChange) {
|
|
4024
|
+
const select = document2.createElement("select");
|
|
3601
4025
|
for (const option of options) {
|
|
3602
|
-
const opt =
|
|
4026
|
+
const opt = document2.createElement("option");
|
|
3603
4027
|
opt.value = option;
|
|
3604
4028
|
opt.textContent = option;
|
|
3605
4029
|
if (option === value) opt.selected = true;
|
|
@@ -3608,8 +4032,8 @@ function createSelect(document, options, value, onChange) {
|
|
|
3608
4032
|
select.addEventListener("change", () => onChange(select.value));
|
|
3609
4033
|
return select;
|
|
3610
4034
|
}
|
|
3611
|
-
function createInput(
|
|
3612
|
-
const input =
|
|
4035
|
+
function createInput(document2, value, onChange, maxLength) {
|
|
4036
|
+
const input = document2.createElement("input");
|
|
3613
4037
|
input.type = "text";
|
|
3614
4038
|
input.value = value;
|
|
3615
4039
|
if (maxLength !== void 0) input.maxLength = maxLength;
|
|
@@ -3624,16 +4048,16 @@ function createHeaderRuleType() {
|
|
|
3624
4048
|
return rule.type === "header";
|
|
3625
4049
|
},
|
|
3626
4050
|
mount(context) {
|
|
3627
|
-
const
|
|
3628
|
-
const fieldset =
|
|
3629
|
-
const legend =
|
|
4051
|
+
const document2 = context.document;
|
|
4052
|
+
const fieldset = document2.createElement("fieldset");
|
|
4053
|
+
const legend = document2.createElement("legend");
|
|
3630
4054
|
legend.textContent = "Header rule";
|
|
3631
4055
|
fieldset.append(legend);
|
|
3632
|
-
const directionLabel =
|
|
4056
|
+
const directionLabel = document2.createElement("label");
|
|
3633
4057
|
directionLabel.textContent = "Direction";
|
|
3634
4058
|
const directionValue = context.getField("headerDirection") ?? "request";
|
|
3635
4059
|
const directionSelect = createSelect(
|
|
3636
|
-
|
|
4060
|
+
document2,
|
|
3637
4061
|
HEADER_DIRECTIONS,
|
|
3638
4062
|
directionValue,
|
|
3639
4063
|
(value) => {
|
|
@@ -3643,11 +4067,11 @@ function createHeaderRuleType() {
|
|
|
3643
4067
|
context.registerControl("/headerDirection", directionSelect);
|
|
3644
4068
|
directionLabel.append(directionSelect);
|
|
3645
4069
|
fieldset.append(directionLabel);
|
|
3646
|
-
const operationLabel =
|
|
4070
|
+
const operationLabel = document2.createElement("label");
|
|
3647
4071
|
operationLabel.textContent = "Operation";
|
|
3648
4072
|
const operationValue = context.getField("headerOperation") ?? "set";
|
|
3649
4073
|
const operationSelect = createSelect(
|
|
3650
|
-
|
|
4074
|
+
document2,
|
|
3651
4075
|
HEADER_OPERATIONS,
|
|
3652
4076
|
operationValue,
|
|
3653
4077
|
(value) => {
|
|
@@ -3657,11 +4081,11 @@ function createHeaderRuleType() {
|
|
|
3657
4081
|
context.registerControl("/headerOperation", operationSelect);
|
|
3658
4082
|
operationLabel.append(operationSelect);
|
|
3659
4083
|
fieldset.append(operationLabel);
|
|
3660
|
-
const nameLabel =
|
|
4084
|
+
const nameLabel = document2.createElement("label");
|
|
3661
4085
|
nameLabel.textContent = "Header name";
|
|
3662
4086
|
const nameValue = context.getField("headerName") ?? "";
|
|
3663
4087
|
const nameInput = createInput(
|
|
3664
|
-
|
|
4088
|
+
document2,
|
|
3665
4089
|
nameValue,
|
|
3666
4090
|
(value) => {
|
|
3667
4091
|
context.setField("headerName", value);
|
|
@@ -3671,11 +4095,11 @@ function createHeaderRuleType() {
|
|
|
3671
4095
|
context.registerControl("/headerName", nameInput);
|
|
3672
4096
|
nameLabel.append(nameInput);
|
|
3673
4097
|
fieldset.append(nameLabel);
|
|
3674
|
-
const valueLabel =
|
|
4098
|
+
const valueLabel = document2.createElement("label");
|
|
3675
4099
|
valueLabel.textContent = "Header value";
|
|
3676
4100
|
const valueValue = context.getField("headerValue") ?? "";
|
|
3677
4101
|
const valueInput = createInput(
|
|
3678
|
-
|
|
4102
|
+
document2,
|
|
3679
4103
|
valueValue,
|
|
3680
4104
|
(value) => {
|
|
3681
4105
|
context.setField("headerValue", value);
|
|
@@ -3773,10 +4197,10 @@ function createRedirectRuleType() {
|
|
|
3773
4197
|
return rule.type === "redirect";
|
|
3774
4198
|
},
|
|
3775
4199
|
mount(context) {
|
|
3776
|
-
const
|
|
3777
|
-
const label =
|
|
4200
|
+
const document2 = context.document;
|
|
4201
|
+
const label = document2.createElement("label");
|
|
3778
4202
|
label.textContent = "Redirect destination URL";
|
|
3779
|
-
const input =
|
|
4203
|
+
const input = document2.createElement("input");
|
|
3780
4204
|
input.type = "text";
|
|
3781
4205
|
input.maxLength = 2048;
|
|
3782
4206
|
const existing = context.getField("redirect.destination");
|