@blokkli/editor 2.0.0-alpha.55 → 2.0.0-alpha.57

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 (42) hide show
  1. package/dist/module.json +1 -1
  2. package/dist/module.mjs +1 -1
  3. package/dist/modules/agent/runtime/app/composables/index.d.ts +3 -1
  4. package/dist/modules/agent/runtime/app/composables/index.js +1 -0
  5. package/dist/modules/agent/runtime/app/composables/useAgent.d.ts +6 -0
  6. package/dist/modules/agent/runtime/app/composables/useAgent.js +11 -0
  7. package/dist/modules/agent/runtime/app/features/agent/Container.vue +83 -88
  8. package/dist/modules/agent/runtime/app/helpers/buildPageContext.d.ts +7 -0
  9. package/dist/modules/agent/runtime/app/helpers/buildPageContext.js +81 -0
  10. package/dist/modules/agent/runtime/app/helpers/index.d.ts +15 -1
  11. package/dist/modules/agent/runtime/app/helpers/index.js +16 -0
  12. package/dist/modules/agent/runtime/app/helpers/injections.d.ts +3 -0
  13. package/dist/modules/agent/runtime/app/helpers/injections.js +3 -0
  14. package/dist/modules/agent/runtime/app/providers/agentProvider.d.ts +33 -0
  15. package/dist/modules/agent/runtime/app/providers/agentProvider.js +315 -0
  16. package/dist/modules/agent/runtime/app/providers/conversationProvider.d.ts +50 -0
  17. package/dist/modules/agent/runtime/app/providers/conversationProvider.js +263 -0
  18. package/dist/modules/agent/runtime/app/providers/planProvider.d.ts +15 -0
  19. package/dist/modules/agent/runtime/app/providers/planProvider.js +34 -0
  20. package/dist/modules/agent/runtime/app/providers/socketProvider.d.ts +17 -0
  21. package/dist/modules/agent/runtime/app/providers/socketProvider.js +110 -0
  22. package/dist/modules/agent/runtime/app/providers/toolsProvider.d.ts +44 -0
  23. package/dist/modules/agent/runtime/app/providers/toolsProvider.js +298 -0
  24. package/dist/modules/agent/runtime/app/types/index.d.ts +47 -0
  25. package/dist/modules/agent/runtime/app/types/index.js +3 -1
  26. package/dist/modules/agent/runtime/server/helpers.js +2 -1
  27. package/dist/modules/readability/index.mjs +1 -1
  28. package/dist/runtime/editor/components/DiffViewer/State.vue +51 -67
  29. package/dist/runtime/editor/components/EditProvider.vue +30 -10
  30. package/dist/runtime/editor/components/PreviewProvider.vue +14 -8
  31. package/dist/runtime/editor/css/output.css +1 -1
  32. package/dist/runtime/editor/events/index.d.ts +4 -3
  33. package/dist/runtime/editor/features/add-list/index.vue +2 -1
  34. package/dist/runtime/editor/features/changelog/changelog.json +8 -0
  35. package/dist/runtime/editor/features/dev-mode/index.vue +1 -10
  36. package/dist/runtime/editor/features/responsive-preview/Frame/index.vue +2 -2
  37. package/dist/runtime/editor/features/translations/index.vue +1 -0
  38. package/dist/runtime/editor/plugins/Sidebar/index.vue +9 -2
  39. package/dist/runtime/editor/providers/state.js +4 -1
  40. package/package.json +1 -1
  41. package/dist/modules/agent/runtime/app/composables/agentProvider.d.ts +0 -62
  42. package/dist/modules/agent/runtime/app/composables/agentProvider.js +0 -1048
package/dist/module.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@blokkli/editor",
3
3
  "configKey": "blokkli",
4
- "version": "2.0.0-alpha.55",
4
+ "version": "2.0.0-alpha.57",
5
5
  "compatibility": {
6
6
  "nuxt": ">=3.15.0"
7
7
  },
package/dist/module.mjs CHANGED
@@ -19,7 +19,7 @@ import 'typescript';
19
19
  import 'oxc-walker';
20
20
 
21
21
  const name = "@blokkli/editor";
22
- const version = "2.0.0-alpha.55";
22
+ const version = "2.0.0-alpha.57";
23
23
 
24
24
  function validateOption(optionKey, option, icons) {
25
25
  const errors = [];
@@ -1,4 +1,6 @@
1
1
  export { defineBlokkliAgentTool } from './defineBlokkliAgentTool.js';
2
2
  export { defineBlokkliAgentPrompt } from './defineBlokkliAgentPrompt.js';
3
- export type { AgentProvider, AgentProviderOptions, PendingMutationState, PendingToolCall, } from './agentProvider.js';
3
+ export { useAgent } from './useAgent.js';
4
+ export type { PendingMutationState, PendingToolCall, } from '../providers/toolsProvider.js';
5
+ export type { AgentApp } from '../types/index.js';
4
6
  export type { AgentConversationData, AgentConversationSummary, } from '../features/agent/types.js';
@@ -1,2 +1,3 @@
1
1
  export { defineBlokkliAgentTool } from "./defineBlokkliAgentTool.js";
2
2
  export { defineBlokkliAgentPrompt } from "./defineBlokkliAgentPrompt.js";
3
+ export { useAgent } from "./useAgent.js";
@@ -0,0 +1,6 @@
1
+ import type { AgentApp } from '#blokkli/agent/app/types';
2
+ /**
3
+ * Access the agent app from any component below the agent Container.
4
+ * Mirrors `useBlokkli()` for the editor.
5
+ */
6
+ export declare function useAgent(): AgentApp;
@@ -0,0 +1,11 @@
1
+ import { inject } from "#imports";
2
+ import { INJECT_AGENT_APP } from "#blokkli/agent/app/helpers/injections";
3
+ export function useAgent() {
4
+ const app = inject(INJECT_AGENT_APP);
5
+ if (!app) {
6
+ throw new Error(
7
+ "useAgent() called outside the agent Container \u2014 make sure the agent feature is mounted."
8
+ );
9
+ }
10
+ return app;
11
+ }
@@ -2,57 +2,57 @@
2
2
  <AgentPanel
3
3
  :is-shown
4
4
  :agent-name
5
- :conversation
6
- :active-item
7
- :is-thinking
8
- :is-processing
9
- :is-connected
10
- :has-been-ready
11
- :pending-tool-call
12
- :pending-mutation
13
- :auto-approve
14
- :conversation-list
15
- :show-conversation-list
16
- :plan
17
- :tool-details
18
- :usage-turns="usageTurns"
19
- :page-context="pageContext"
5
+ :conversation="conversation.items.value"
6
+ :active-item="conversation.activeItem.value"
7
+ :is-thinking="agent.isThinking.value"
8
+ :is-processing="agent.isProcessing.value"
9
+ :is-connected="socket.isConnected.value"
10
+ :has-been-ready="agent.hasBeenReady.value"
11
+ :pending-tool-call="tools.pendingToolCall.value"
12
+ :pending-mutation="tools.pendingMutation.value"
13
+ :auto-approve="tools.autoApprove.value"
14
+ :conversation-list="conversation.conversationList.value"
15
+ :show-conversation-list="conversation.showConversationList.value"
16
+ :plan="plan.plan.value"
17
+ :tool-details="conversation.toolDetails"
18
+ :usage-turns="conversation.usageTurns.value"
19
+ :page-context="tools.pageContext.value"
20
20
  :supports-feedback="!!adapter.submitConversationFeedback"
21
- :feedback-item-ids="feedbackItemIds"
22
- @connect="connect"
23
- @send-prompt="sendPrompt"
24
- @retry="retry"
25
- @cancel="cancel"
26
- @approve="approve"
27
- @reject="reject"
28
- @set-auto-approve="setAutoApprove"
29
- @new-conversation="newConversation"
30
- @get-transcript="getTranscript"
31
- @tool-component-done="onToolComponentDone"
32
- @switch-conversation="switchConversation"
33
- @delete-conversation="deleteConversation"
21
+ :feedback-item-ids="conversation.feedbackItemIds.value"
22
+ @connect="agent.connect"
23
+ @send-prompt="agent.sendPrompt"
24
+ @retry="agent.retry"
25
+ @cancel="agent.cancel"
26
+ @approve="tools.approve"
27
+ @reject="tools.reject"
28
+ @set-auto-approve="tools.setAutoApprove"
29
+ @new-conversation="agent.newConversation"
30
+ @get-transcript="agent.getTranscript"
31
+ @tool-component-done="tools.onComponentDone"
32
+ @switch-conversation="agent.switchConversation"
33
+ @delete-conversation="agent.deleteConversation"
34
34
  @submit-feedback="onSubmitFeedback"
35
35
  @feedback-done="onFeedbackDone"
36
36
  @show-conversations="onShowConversations"
37
37
  @hide-conversations="onHideConversations"
38
- @approve-plan="approvePlan"
39
- @reject-plan="rejectPlan"
38
+ @approve-plan="plan.approve"
39
+ @reject-plan="plan.reject"
40
40
  />
41
41
 
42
42
  <Teleport :to="ui.mainLayoutElement.value">
43
43
  <BlokkliTransition name="slide-up">
44
44
  <DialogModal
45
- v-if="showTranscript"
45
+ v-if="conversation.showTranscript.value"
46
46
  id="agent-transcript"
47
47
  title="Agent Transcript"
48
48
  :width="900"
49
49
  hide-buttons
50
50
  full-screen
51
- @cancel="showTranscript = false"
51
+ @cancel="conversation.showTranscript.value = false"
52
52
  >
53
53
  <AgentTranscript
54
- v-if="transcriptContent"
55
- :transcript="transcriptContent"
54
+ v-if="conversation.transcriptContent.value"
55
+ :transcript="conversation.transcriptContent.value"
56
56
  />
57
57
  </DialogModal>
58
58
  </BlokkliTransition>
@@ -64,10 +64,16 @@ import {
64
64
  useBlokkli,
65
65
  onBeforeUnmount,
66
66
  watch,
67
+ provide,
67
68
  defineAsyncComponent
68
69
  } from "#imports";
69
70
  import { DialogModal, BlokkliTransition } from "#blokkli/editor/components";
70
- import agentProvider from "#blokkli/agent/app/composables/agentProvider";
71
+ import socketProvider from "#blokkli/agent/app/providers/socketProvider";
72
+ import conversationProvider from "#blokkli/agent/app/providers/conversationProvider";
73
+ import planProvider from "#blokkli/agent/app/providers/planProvider";
74
+ import toolsProvider from "#blokkli/agent/app/providers/toolsProvider";
75
+ import agentProvider from "#blokkli/agent/app/providers/agentProvider";
76
+ import { INJECT_AGENT_APP } from "#blokkli/agent/app/helpers/injections";
71
77
  import AgentPanel from "./Panel/index.vue";
72
78
  const AgentTranscript = defineAsyncComponent(
73
79
  () => import("./Transcript/index.vue")
@@ -79,54 +85,43 @@ const props = defineProps({
79
85
  pendingPromptRequest: { type: [Object, null], required: true }
80
86
  });
81
87
  const emit = defineEmits(["consumed"]);
82
- const app = useBlokkli();
83
- const { ui } = app;
84
- const {
85
- connect,
86
- disconnect,
88
+ const blokkli = useBlokkli();
89
+ const { ui } = blokkli;
90
+ const socket = socketProvider();
91
+ const conversation = conversationProvider({ adapter: props.adapter });
92
+ const plan = planProvider({ socket, conversation });
93
+ const tools = toolsProvider({
94
+ app: blokkli,
95
+ adapter: props.adapter,
96
+ socket,
97
+ conversation
98
+ });
99
+ const agent = agentProvider({
100
+ app: blokkli,
101
+ adapter: props.adapter,
102
+ agentName: props.agentName,
103
+ socket,
87
104
  conversation,
88
- activeItem,
89
- isProcessing,
90
- isThinking,
91
- isConnected,
92
- hasBeenReady,
93
- autoApprove,
94
- pendingMutation,
95
- pendingToolCall,
96
105
  plan,
97
- approvePlan,
98
- rejectPlan,
99
- usageTurns,
100
- sendPrompt,
101
- runToolForPrompt,
102
- retry,
103
- approve,
104
- reject,
105
- setAutoApprove,
106
- cancel,
107
- newConversation,
108
- getTranscript,
109
- onToolComponentDone,
110
- transcriptContent,
111
- showTranscript,
112
- toolDetails,
113
- conversationList,
114
- showConversationList,
115
- switchConversation,
116
- deleteConversation,
117
- refreshConversationList,
118
- activeConversationId,
119
- feedbackItemIds,
120
- pageContext
121
- } = agentProvider(app, props.adapter, props.agentName);
106
+ tools
107
+ });
108
+ const adapter = props.adapter;
109
+ const agentApp = {
110
+ socket,
111
+ conversation,
112
+ plan,
113
+ tools,
114
+ ...agent
115
+ };
116
+ provide(INJECT_AGENT_APP, agentApp);
122
117
  async function onSubmitFeedback(rating, comment) {
123
- if (!props.adapter.submitConversationFeedback) return;
124
- const conversationId = activeConversationId.value;
118
+ if (!adapter.submitConversationFeedback) return;
119
+ const conversationId = conversation.activeConversationId.value;
125
120
  if (!conversationId) return;
126
- const lastItem = conversation.value[conversation.value.length - 1];
121
+ const lastItem = conversation.items.value[conversation.items.value.length - 1];
127
122
  if (!lastItem) return;
128
123
  try {
129
- await props.adapter.submitConversationFeedback({
124
+ await adapter.submitConversationFeedback({
130
125
  conversationId,
131
126
  rating,
132
127
  lastItemId: lastItem.id,
@@ -137,17 +132,17 @@ async function onSubmitFeedback(rating, comment) {
137
132
  }
138
133
  }
139
134
  function onFeedbackDone() {
140
- const lastItem = conversation.value[conversation.value.length - 1];
135
+ const lastItem = conversation.items.value[conversation.items.value.length - 1];
141
136
  if (lastItem) {
142
- feedbackItemIds.value.add(lastItem.id);
137
+ conversation.feedbackItemIds.value.add(lastItem.id);
143
138
  }
144
139
  }
145
140
  async function onShowConversations() {
146
- await refreshConversationList();
147
- showConversationList.value = true;
141
+ await agent.refreshConversationList();
142
+ conversation.showConversationList.value = true;
148
143
  }
149
144
  function onHideConversations() {
150
- showConversationList.value = false;
145
+ conversation.showConversationList.value = false;
151
146
  }
152
147
  watch(
153
148
  () => props.pendingPromptRequest,
@@ -155,22 +150,22 @@ watch(
155
150
  if (!request) return;
156
151
  emit("consumed");
157
152
  const { prompt, selectedUuids } = request;
158
- const promptText = prompt.getPrompt(app);
159
- const userPromptText = prompt.getUserPrompt?.(app);
153
+ const promptText = prompt.getPrompt(blokkli);
154
+ const userPromptText = prompt.getUserPrompt?.(blokkli);
160
155
  let preSeededResults = void 0;
161
156
  let autoExecuteTools = void 0;
162
157
  if (prompt.preExecute) {
163
158
  const preResult = await prompt.preExecute({
164
- app,
159
+ app: blokkli,
165
160
  selectedUuids,
166
- runTool: runToolForPrompt
161
+ runTool: tools.runForPrompt
167
162
  });
168
163
  if (preResult) {
169
164
  preSeededResults = preResult.preSeededResults;
170
165
  autoExecuteTools = preResult.autoExecuteTools;
171
166
  }
172
167
  }
173
- sendPrompt(
168
+ agent.sendPrompt(
174
169
  promptText,
175
170
  userPromptText,
176
171
  selectedUuids,
@@ -184,7 +179,7 @@ watch(
184
179
  { immediate: true }
185
180
  );
186
181
  onBeforeUnmount(() => {
187
- disconnect();
182
+ agent.disconnect();
188
183
  });
189
184
  </script>
190
185
 
@@ -0,0 +1,7 @@
1
+ import type { BlokkliApp } from '#blokkli/editor/types/app';
2
+ import type { PageContext } from '#blokkli/agent/shared/types';
3
+ /**
4
+ * Build the PageContext sent to the agent server on init. Pure builder over
5
+ * the BlokkliApp providers — no closures, no refs.
6
+ */
7
+ export declare function buildPageContext(app: BlokkliApp, contentSearchTabs?: PageContext['contentSearchTabs']): Promise<PageContext>;
@@ -0,0 +1,81 @@
1
+ import { itemEntityType } from "#blokkli-build/config";
2
+ export async function buildPageContext(app, contentSearchTabs) {
3
+ const { types, definitions, context, state, ui, $t, analyze } = app;
4
+ const bundles = [];
5
+ for (const bundle of types.generallyAvailableBundles) {
6
+ const contentFields = [
7
+ ...types.editableFieldConfig.forEntityTypeAndBundle(itemEntityType, bundle.id).filter((f) => f.type !== "table").map((f) => ({
8
+ name: f.name,
9
+ label: f.label,
10
+ type: f.type === "frame" || f.type === "markup" ? "markup" : "plain"
11
+ })),
12
+ ...types.droppableFieldConfig.forEntityTypeAndBundle(itemEntityType, bundle.id).map((f) => ({
13
+ name: f.name,
14
+ label: f.label,
15
+ type: f.type,
16
+ allowed: f.allowed
17
+ }))
18
+ ];
19
+ const paragraphFields = types.fieldConfig.forEntityTypeAndBundle(itemEntityType, bundle.id).map((f) => ({
20
+ name: f.name,
21
+ label: f.label,
22
+ allowedBundles: f.allowedBundles,
23
+ cardinality: f.cardinality
24
+ }));
25
+ bundles.push({
26
+ id: bundle.id,
27
+ label: bundle.label,
28
+ description: bundle.description,
29
+ contentFields,
30
+ paragraphFields
31
+ });
32
+ }
33
+ const fragments = definitions.fragmentDefinitions.value.map((f) => ({
34
+ name: f.name,
35
+ label: f.label,
36
+ description: f.description
37
+ }));
38
+ const entityContentFields = [
39
+ ...types.editableFieldConfig.forEntityTypeAndBundle(
40
+ context.value.entityType,
41
+ context.value.entityBundle
42
+ ).filter((f) => f.type !== "table").map((f) => ({
43
+ name: f.name,
44
+ label: f.label,
45
+ type: f.type === "frame" || f.type === "markup" ? "markup" : "plain"
46
+ })),
47
+ ...types.droppableFieldConfig.forEntityTypeAndBundle(
48
+ context.value.entityType,
49
+ context.value.entityBundle
50
+ ).map((f) => ({
51
+ name: f.name,
52
+ label: f.label,
53
+ type: f.type,
54
+ allowed: f.allowed
55
+ }))
56
+ ];
57
+ await analyze.ensureInitialized();
58
+ const analyzersList = analyze.analyzers.value.filter((a) => !a.requireRawPage).map((a) => ({
59
+ id: a.id,
60
+ type: a.type,
61
+ label: typeof a.label === "function" ? a.label(context.value.language, $t) : a.label,
62
+ description: typeof a.description === "function" ? a.description(context.value.language, $t) : a.description
63
+ }));
64
+ return {
65
+ title: state.entity.value.label || "",
66
+ entityType: context.value.entityType,
67
+ entityUuid: context.value.entityUuid,
68
+ entityBundle: context.value.entityBundle,
69
+ bundleLabel: state.entity.value.bundleLabel || "",
70
+ itemEntityType,
71
+ bundles,
72
+ interfaceLanguage: ui.interfaceLanguage.value,
73
+ entityLanguage: context.value.language,
74
+ isPublished: state.entity.value.status ?? null,
75
+ editMode: state.editMode.value,
76
+ fragments,
77
+ entityContentFields,
78
+ ...contentSearchTabs?.length ? { contentSearchTabs } : {},
79
+ ...analyzersList.length ? { analyzers: analyzersList } : {}
80
+ };
81
+ }
@@ -1,7 +1,21 @@
1
- import type { McpToolDefinition, McpToolContext, McpToolCategory, MutationAction, QueryResult, ToolError } from '#blokkli/agent/app/types';
1
+ import type { McpToolDefinition, McpToolContext, McpToolCategory, MutationAction, QueryResult, ToolError, ToolMeta } from '#blokkli/agent/app/types';
2
2
  import type { BlokkliAdapter } from '#blokkli/editor/adapter';
3
3
  import type { BlokkliApp } from '#blokkli/editor/types/app';
4
4
  import type { EditMode } from '#blokkli/editor/types/state';
5
+ /**
6
+ * Narrow an `unknown` to a plain record. One cast at the boundary so call
7
+ * sites can read `obj.foo` without scattering casts everywhere.
8
+ */
9
+ export declare function asRecord(value: unknown): Record<string, unknown> | null;
10
+ /**
11
+ * Pull component side-channel meta (`_details`, `_usage`, `_skipLlmResponse`)
12
+ * off an emitted tool result so the LLM-facing payload can be sent without
13
+ * them.
14
+ */
15
+ export declare function splitMeta(raw: unknown): {
16
+ payload: unknown;
17
+ meta: ToolMeta;
18
+ };
5
19
  /**
6
20
  * Create a map of tool name to tool definition for quick lookup.
7
21
  */
@@ -1,3 +1,19 @@
1
+ export function asRecord(value) {
2
+ return typeof value === "object" && value !== null ? value : null;
3
+ }
4
+ export function splitMeta(raw) {
5
+ const obj = asRecord(raw);
6
+ if (!obj) return { payload: raw, meta: {} };
7
+ const meta = {};
8
+ if (obj._details !== void 0) meta.details = obj._details;
9
+ if (obj._usage) meta.usage = obj._usage;
10
+ if (obj._skipLlmResponse === true) meta.skipLlmResponse = true;
11
+ if (Object.keys(meta).length === 0) {
12
+ return { payload: raw, meta };
13
+ }
14
+ const { _details: _, _usage: __, _skipLlmResponse: ___, ...payload } = obj;
15
+ return { payload, meta };
16
+ }
1
17
  export function createToolMap(tools) {
2
18
  return Object.fromEntries(tools.map((t) => [t.name, t]));
3
19
  }
@@ -0,0 +1,3 @@
1
+ import type { InjectionKey } from '#imports';
2
+ import type { AgentApp } from '#blokkli/agent/app/types';
3
+ export declare const INJECT_AGENT_APP: InjectionKey<AgentApp>;
@@ -0,0 +1,3 @@
1
+ export const INJECT_AGENT_APP = Symbol(
2
+ "blokkli_agent_app"
3
+ );
@@ -0,0 +1,33 @@
1
+ import { type Ref } from '#imports';
2
+ import type { Attachment, PreSeededToolResult, AutoExecuteTool } from '#blokkli/agent/app/types';
3
+ import type { BlokkliApp } from '#blokkli/editor/types/app';
4
+ import type { FullBlokkliAdapter } from '#blokkli/editor/adapter';
5
+ import type { SocketProvider } from './socketProvider.js';
6
+ import type { ConversationProvider } from './conversationProvider.js';
7
+ import type { PlanProvider } from './planProvider.js';
8
+ import type { ToolsProvider } from './toolsProvider.js';
9
+ export type AgentOrchestrator = {
10
+ isReady: Ref<boolean>;
11
+ hasBeenReady: Ref<boolean>;
12
+ isProcessing: Ref<boolean>;
13
+ isThinking: Ref<boolean>;
14
+ connect: () => void;
15
+ disconnect: () => void;
16
+ sendPrompt: (prompt: string, displayPrompt?: string, selectedUuids?: string[], attachments?: Attachment[], autoLoadTools?: string[], autoLoadSkills?: string[], preSeededResults?: PreSeededToolResult[], autoExecuteTools?: AutoExecuteTool[]) => void;
17
+ retry: () => void;
18
+ cancel: () => void;
19
+ newConversation: () => void;
20
+ getTranscript: () => void;
21
+ switchConversation: (id: string) => Promise<void>;
22
+ deleteConversation: (id: string) => Promise<void>;
23
+ refreshConversationList: () => Promise<void>;
24
+ };
25
+ export default function agentProvider({ app, adapter, agentName, socket, conversation, plan, tools, }: {
26
+ app: BlokkliApp;
27
+ adapter: FullBlokkliAdapter<any>;
28
+ agentName: string;
29
+ socket: SocketProvider;
30
+ conversation: ConversationProvider;
31
+ plan: PlanProvider;
32
+ tools: ToolsProvider;
33
+ }): AgentOrchestrator;