@rogatio/cli 5.15.0 → 5.16.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/dist/editor/index.js +162 -16
- package/package.json +1 -1
package/dist/editor/index.js
CHANGED
|
@@ -231,7 +231,7 @@ function hasLoneSurrogate(value) {
|
|
|
231
231
|
}
|
|
232
232
|
|
|
233
233
|
// packages/editor/src/ai-assist-panel.ts
|
|
234
|
-
function createAIAssistPanel(_container, _editor, onApply, onClose) {
|
|
234
|
+
function createAIAssistPanel(_container, _editor, onApply, onClose, onSend) {
|
|
235
235
|
let visible = false;
|
|
236
236
|
let streamingContent = "";
|
|
237
237
|
let streamingMessageIndex = -1;
|
|
@@ -351,6 +351,7 @@ function createAIAssistPanel(_container, _editor, onApply, onClose) {
|
|
|
351
351
|
panel.appendChild(messagesContainer);
|
|
352
352
|
panel.appendChild(inputContainer);
|
|
353
353
|
const closeBtn = header.querySelector(".ai-close-btn");
|
|
354
|
+
let sending = false;
|
|
354
355
|
function show() {
|
|
355
356
|
if (!visible) {
|
|
356
357
|
visible = true;
|
|
@@ -373,10 +374,17 @@ function createAIAssistPanel(_container, _editor, onApply, onClose) {
|
|
|
373
374
|
onClose();
|
|
374
375
|
}
|
|
375
376
|
}
|
|
377
|
+
function destroy() {
|
|
378
|
+
visible = false;
|
|
379
|
+
if (panel.parentNode) {
|
|
380
|
+
panel.parentNode.removeChild(panel);
|
|
381
|
+
}
|
|
382
|
+
onClose();
|
|
383
|
+
}
|
|
376
384
|
function isVisible() {
|
|
377
385
|
return visible;
|
|
378
386
|
}
|
|
379
|
-
function
|
|
387
|
+
function renderMessage(message) {
|
|
380
388
|
const messageEl = document.createElement("div");
|
|
381
389
|
messageEl.style.cssText = `
|
|
382
390
|
display: flex;
|
|
@@ -402,6 +410,10 @@ function createAIAssistPanel(_container, _editor, onApply, onClose) {
|
|
|
402
410
|
messagesContainer.appendChild(messageEl);
|
|
403
411
|
messagesContainer.scrollTop = messagesContainer.scrollHeight;
|
|
404
412
|
}
|
|
413
|
+
function addMessage(message) {
|
|
414
|
+
messages.push(message);
|
|
415
|
+
renderMessage(message);
|
|
416
|
+
}
|
|
405
417
|
function createProposalElement(proposal) {
|
|
406
418
|
const container = document.createElement("div");
|
|
407
419
|
container.style.cssText = `
|
|
@@ -513,22 +525,22 @@ function createAIAssistPanel(_container, _editor, onApply, onClose) {
|
|
|
513
525
|
}
|
|
514
526
|
function updateStreamingContent(content) {
|
|
515
527
|
if (streamingMessageIndex >= 0 && streamingMessageIndex < messages.length) {
|
|
528
|
+
streamingContent += content;
|
|
516
529
|
const message = messages[streamingMessageIndex];
|
|
517
|
-
message.content = streamingContent
|
|
518
|
-
const
|
|
519
|
-
|
|
520
|
-
)
|
|
521
|
-
|
|
522
|
-
bubbles[streamingMessageIndex].textContent = message.content;
|
|
530
|
+
message.content = streamingContent;
|
|
531
|
+
const messageEl = messagesContainer.children[streamingMessageIndex];
|
|
532
|
+
const bubble = messageEl?.firstElementChild;
|
|
533
|
+
if (bubble instanceof HTMLElement) {
|
|
534
|
+
bubble.textContent = message.content;
|
|
523
535
|
}
|
|
536
|
+
messagesContainer.scrollTop = messagesContainer.scrollHeight;
|
|
524
537
|
}
|
|
525
538
|
}
|
|
526
539
|
function startStreaming(role) {
|
|
527
540
|
streamingContent = "";
|
|
528
541
|
const message = { role, content: "", isStreaming: true };
|
|
529
|
-
messages.push(message);
|
|
530
|
-
streamingMessageIndex = messages.length - 1;
|
|
531
542
|
addMessage(message);
|
|
543
|
+
streamingMessageIndex = messages.length - 1;
|
|
532
544
|
}
|
|
533
545
|
function finishStreaming(proposal) {
|
|
534
546
|
if (streamingMessageIndex >= 0 && streamingMessageIndex < messages.length) {
|
|
@@ -552,9 +564,16 @@ function createAIAssistPanel(_container, _editor, onApply, onClose) {
|
|
|
552
564
|
}
|
|
553
565
|
function handleSend() {
|
|
554
566
|
const prompt = textarea.value.trim();
|
|
555
|
-
if (!prompt) return;
|
|
567
|
+
if (!prompt || sending) return;
|
|
568
|
+
sending = true;
|
|
569
|
+
sendButton.disabled = true;
|
|
556
570
|
textarea.value = "";
|
|
557
571
|
textarea.style.height = "auto";
|
|
572
|
+
addMessage({ role: "user", content: prompt });
|
|
573
|
+
void Promise.resolve(onSend(prompt)).finally(() => {
|
|
574
|
+
sending = false;
|
|
575
|
+
sendButton.disabled = false;
|
|
576
|
+
});
|
|
558
577
|
}
|
|
559
578
|
closeBtn.addEventListener("click", hide);
|
|
560
579
|
sendButton.addEventListener("click", handleSend);
|
|
@@ -567,6 +586,7 @@ function createAIAssistPanel(_container, _editor, onApply, onClose) {
|
|
|
567
586
|
return {
|
|
568
587
|
show,
|
|
569
588
|
hide,
|
|
589
|
+
destroy,
|
|
570
590
|
isVisible,
|
|
571
591
|
addMessage,
|
|
572
592
|
clearMessages,
|
|
@@ -1966,6 +1986,69 @@ function displayName(value, fallback) {
|
|
|
1966
1986
|
function isHTMLElement(value) {
|
|
1967
1987
|
return value !== null && typeof value === "object" && value.nodeType === 1 && typeof value.appendChild === "function";
|
|
1968
1988
|
}
|
|
1989
|
+
function isAsyncIterable(value) {
|
|
1990
|
+
return value !== null && typeof value === "object" && Symbol.asyncIterator in value && typeof value[Symbol.asyncIterator] === "function";
|
|
1991
|
+
}
|
|
1992
|
+
function aiAssistErrorMessage(error) {
|
|
1993
|
+
if (error instanceof Error && error.message.length > 0) return error.message;
|
|
1994
|
+
if (typeof error === "string" && error.length > 0) return error;
|
|
1995
|
+
return "AI Assist failed.";
|
|
1996
|
+
}
|
|
1997
|
+
function ownString(record, ...keys) {
|
|
1998
|
+
for (const key of keys) {
|
|
1999
|
+
if (!Object.hasOwn(record, key)) continue;
|
|
2000
|
+
if (FORBIDDEN_EXTENSION_FIELDS.has(key)) continue;
|
|
2001
|
+
const value = record[key];
|
|
2002
|
+
if (typeof value === "string") return value;
|
|
2003
|
+
}
|
|
2004
|
+
return void 0;
|
|
2005
|
+
}
|
|
2006
|
+
function applyRuleProposalAction(rule, ruleProposal) {
|
|
2007
|
+
const action = ruleProposal.action;
|
|
2008
|
+
switch (ruleProposal.kind) {
|
|
2009
|
+
case "redirect": {
|
|
2010
|
+
rule.type = "redirect";
|
|
2011
|
+
const snap = snapshotOwnData(action);
|
|
2012
|
+
if (snap.valid) rule.redirect = snap.value;
|
|
2013
|
+
return;
|
|
2014
|
+
}
|
|
2015
|
+
case "query": {
|
|
2016
|
+
rule.type = "query";
|
|
2017
|
+
const snap = snapshotOwnData(action);
|
|
2018
|
+
if (snap.valid) rule.action = snap.value;
|
|
2019
|
+
return;
|
|
2020
|
+
}
|
|
2021
|
+
case "header": {
|
|
2022
|
+
rule.type = "header";
|
|
2023
|
+
if (!isRecord4(action)) return;
|
|
2024
|
+
const direction = ownString(action, "headerDirection", "direction");
|
|
2025
|
+
const operation = ownString(action, "headerOperation", "operation");
|
|
2026
|
+
const name = ownString(action, "headerName", "name");
|
|
2027
|
+
const value = ownString(action, "headerValue", "value");
|
|
2028
|
+
if (direction !== void 0) rule.headerDirection = direction;
|
|
2029
|
+
if (operation !== void 0) rule.headerOperation = operation;
|
|
2030
|
+
if (name !== void 0) rule.headerName = name;
|
|
2031
|
+
if (value !== void 0) rule.headerValue = value;
|
|
2032
|
+
return;
|
|
2033
|
+
}
|
|
2034
|
+
case "response-body": {
|
|
2035
|
+
rule.type = "response-body";
|
|
2036
|
+
const snap = snapshotOwnData(action);
|
|
2037
|
+
if (snap.valid) rule.responseBody = snap.value;
|
|
2038
|
+
return;
|
|
2039
|
+
}
|
|
2040
|
+
case "request-body": {
|
|
2041
|
+
rule.type = "request-body";
|
|
2042
|
+
const snap = snapshotOwnData(action);
|
|
2043
|
+
if (snap.valid) rule.requestBody = snap.value;
|
|
2044
|
+
return;
|
|
2045
|
+
}
|
|
2046
|
+
default: {
|
|
2047
|
+
const _exhaustive = ruleProposal.kind;
|
|
2048
|
+
void _exhaustive;
|
|
2049
|
+
}
|
|
2050
|
+
}
|
|
2051
|
+
}
|
|
1969
2052
|
function normalizeExtensions(value) {
|
|
1970
2053
|
const ids = /* @__PURE__ */ new Set();
|
|
1971
2054
|
const merged = [...builtInRuleTypes];
|
|
@@ -2042,6 +2125,7 @@ var EditorControllerImpl = class {
|
|
|
2042
2125
|
testRunning = false;
|
|
2043
2126
|
testRequestId = 0;
|
|
2044
2127
|
aiAssistPanel = null;
|
|
2128
|
+
aiAssistInFlight = false;
|
|
2045
2129
|
constructor(options, initial, extensions) {
|
|
2046
2130
|
this.root = options.root;
|
|
2047
2131
|
this.document = options.root.ownerDocument;
|
|
@@ -2064,8 +2148,8 @@ var EditorControllerImpl = class {
|
|
|
2064
2148
|
},
|
|
2065
2149
|
(proposal) => this.applyAIProposal(proposal),
|
|
2066
2150
|
() => {
|
|
2067
|
-
}
|
|
2068
|
-
|
|
2151
|
+
},
|
|
2152
|
+
(prompt) => this.runAIAssist(prompt)
|
|
2069
2153
|
);
|
|
2070
2154
|
}
|
|
2071
2155
|
this.host = this.document.createElement("div");
|
|
@@ -2142,7 +2226,7 @@ var EditorControllerImpl = class {
|
|
|
2142
2226
|
if (this.destroyed) return;
|
|
2143
2227
|
this.destroyed = true;
|
|
2144
2228
|
if (this.aiAssistPanel) {
|
|
2145
|
-
this.aiAssistPanel.
|
|
2229
|
+
this.aiAssistPanel.destroy();
|
|
2146
2230
|
this.aiAssistPanel = null;
|
|
2147
2231
|
}
|
|
2148
2232
|
this.cleanupExtensions();
|
|
@@ -2916,8 +3000,7 @@ var EditorControllerImpl = class {
|
|
|
2916
3000
|
if (ruleProposal.method) {
|
|
2917
3001
|
rule.method = ruleProposal.method;
|
|
2918
3002
|
}
|
|
2919
|
-
|
|
2920
|
-
rule[actionField] = ruleProposal.action;
|
|
3003
|
+
applyRuleProposalAction(rule, ruleProposal);
|
|
2921
3004
|
group.rules.push(rule);
|
|
2922
3005
|
this.markChanged();
|
|
2923
3006
|
const groupIdStr = String(group.id);
|
|
@@ -2932,6 +3015,69 @@ var EditorControllerImpl = class {
|
|
|
2932
3015
|
this.statusMessage = `Applied ${proposal.rules.length} rule${proposal.rules.length === 1 ? "" : "s"} from AI.`;
|
|
2933
3016
|
this.render();
|
|
2934
3017
|
}
|
|
3018
|
+
async runAIAssist(prompt) {
|
|
3019
|
+
const handler = this.options.aiAssist;
|
|
3020
|
+
const panel = this.aiAssistPanel;
|
|
3021
|
+
if (!handler || !panel || this.aiAssistInFlight || this.destroyed) return;
|
|
3022
|
+
this.aiAssistInFlight = true;
|
|
3023
|
+
const diagnostics = this.validateCurrent();
|
|
3024
|
+
const hasErrors = diagnostics.some(
|
|
3025
|
+
(diagnostic2) => diagnostic2.severity === "error"
|
|
3026
|
+
);
|
|
3027
|
+
const request = {
|
|
3028
|
+
kind: hasErrors ? "fix" : "generate",
|
|
3029
|
+
prompt,
|
|
3030
|
+
context: {
|
|
3031
|
+
project: this.getDraft(),
|
|
3032
|
+
activeGroupId: this.currentGroupId(),
|
|
3033
|
+
diagnostics: diagnostics.length > 0 ? diagnostics : void 0
|
|
3034
|
+
}
|
|
3035
|
+
};
|
|
3036
|
+
panel.startStreaming("assistant");
|
|
3037
|
+
try {
|
|
3038
|
+
const result = handler(request);
|
|
3039
|
+
if (isAsyncIterable(result)) {
|
|
3040
|
+
let proposal;
|
|
3041
|
+
for await (const chunk of result) {
|
|
3042
|
+
if (this.destroyed) return;
|
|
3043
|
+
const handled = this.consumeAIAssistChunk(panel, chunk);
|
|
3044
|
+
if (handled === "error") return;
|
|
3045
|
+
if (handled.proposal) proposal = handled.proposal;
|
|
3046
|
+
}
|
|
3047
|
+
panel.finishStreaming(proposal);
|
|
3048
|
+
return;
|
|
3049
|
+
}
|
|
3050
|
+
const response = await result;
|
|
3051
|
+
if (this.destroyed) return;
|
|
3052
|
+
panel.finishStreaming(response.proposal);
|
|
3053
|
+
} catch (error) {
|
|
3054
|
+
if (this.destroyed) return;
|
|
3055
|
+
panel.finishStreaming();
|
|
3056
|
+
panel.addMessage({
|
|
3057
|
+
role: "system",
|
|
3058
|
+
content: aiAssistErrorMessage(error)
|
|
3059
|
+
});
|
|
3060
|
+
} finally {
|
|
3061
|
+
this.aiAssistInFlight = false;
|
|
3062
|
+
}
|
|
3063
|
+
}
|
|
3064
|
+
consumeAIAssistChunk(panel, chunk) {
|
|
3065
|
+
if (chunk.type === "token") {
|
|
3066
|
+
if (typeof chunk.content === "string" && chunk.content.length > 0) {
|
|
3067
|
+
panel.updateStreamingContent(chunk.content);
|
|
3068
|
+
}
|
|
3069
|
+
return {};
|
|
3070
|
+
}
|
|
3071
|
+
if (chunk.type === "error") {
|
|
3072
|
+
panel.finishStreaming();
|
|
3073
|
+
panel.addMessage({
|
|
3074
|
+
role: "system",
|
|
3075
|
+
content: chunk.error?.message ?? "AI Assist failed."
|
|
3076
|
+
});
|
|
3077
|
+
return "error";
|
|
3078
|
+
}
|
|
3079
|
+
return { proposal: chunk.proposal };
|
|
3080
|
+
}
|
|
2935
3081
|
addGroupOrigin(groupId) {
|
|
2936
3082
|
const group = this.groupById(groupId);
|
|
2937
3083
|
if (!group || this.saving) return;
|
package/package.json
CHANGED