@ixo/oracle-runtime-workers 0.12.0 → 0.15.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 +32 -10
- package/package.json +14 -9
- package/src/artifacts/config.ts +158 -0
- package/src/artifacts/crypto.ts +94 -0
- package/src/artifacts/routes.ts +73 -0
- package/src/artifacts/store.ts +238 -0
- package/src/artifacts/sweep.ts +200 -0
- package/src/artifacts/tool.ts +103 -0
- package/src/artifacts/viewer-page.ts +614 -0
- package/src/attachments/download.ts +168 -45
- package/src/attachments/index.ts +9 -0
- package/src/attachments/magic.ts +33 -0
- package/src/attachments/pipeline.ts +105 -49
- package/src/attachments/sandbox-archive.ts +9 -8
- package/src/attachments/view-cache.ts +142 -0
- package/src/attachments/view.ts +53 -12
- package/src/channels/auth.ts +267 -0
- package/src/channels/contract.ts +137 -0
- package/src/channels/turns.ts +270 -0
- package/src/core/budgeted-llm.ts +223 -0
- package/src/core/capability-router.ts +273 -0
- package/src/core/context-budget.ts +97 -10
- package/src/core/env.ts +111 -0
- package/src/core/execution-profile.ts +17 -0
- package/src/core/index.ts +267 -9
- package/src/core/llm.ts +30 -9
- package/src/core/main-agent-types.ts +41 -1
- package/src/core/main-agent.ts +367 -65
- package/src/core/manifest.ts +34 -0
- package/src/core/meta-tools.ts +128 -18
- package/src/core/middlewares/capability-gate.ts +130 -12
- package/src/core/middlewares/context-guard.ts +55 -24
- package/src/core/middlewares/index.ts +20 -2
- package/src/core/middlewares/page-context.ts +46 -2
- package/src/core/middlewares/return-direct-first.ts +47 -0
- package/src/core/middlewares/summarization.ts +152 -10
- package/src/core/middlewares/tool-execution.ts +323 -0
- package/src/core/middlewares/tool-repetition-guard.ts +202 -35
- package/src/core/middlewares/turn-boundary.ts +162 -0
- package/src/core/openrouter-pricing.ts +155 -22
- package/src/core/prompt-composer.ts +112 -7
- package/src/core/registries.ts +253 -48
- package/src/core/request-admission.ts +159 -0
- package/src/core/runtime-context.ts +107 -8
- package/src/core/state.ts +1 -1
- package/src/core/sub-agent-fallback.ts +21 -2
- package/src/core/subagent-as-tool.ts +78 -43
- package/src/core/tool-access.ts +189 -0
- package/src/core/tool-scheduler.ts +125 -0
- package/src/core/turn-budget.ts +205 -0
- package/src/core/turn-time-note.ts +43 -0
- package/src/core/user-kv.ts +446 -0
- package/src/core/wrap-plugin-tool.ts +20 -0
- package/src/delivery/plan.ts +278 -0
- package/src/delivery/profile.ts +161 -0
- package/src/delivery/prompt.ts +27 -0
- package/src/delivery/schema.ts +61 -0
- package/src/delivery/shaper.ts +389 -0
- package/src/delivery/types.ts +84 -0
- package/src/do/ambient.ts +51 -15
- package/src/do/contracts.ts +198 -6
- package/src/do/idle-eviction.ts +38 -0
- package/src/do/matrix-turn-ledger.ts +24 -5
- package/src/do/result-store-test-do.ts +137 -3
- package/src/do/result-store.ts +239 -58
- package/src/do/room-mirror.ts +29 -0
- package/src/do/run-buffer.ts +64 -9
- package/src/do/run-coordinator.ts +451 -76
- package/src/do/run-request.ts +2 -0
- package/src/do/run-store-test-do.ts +301 -1
- package/src/do/run-store.ts +385 -43
- package/src/do/secrets-adapter.ts +22 -3
- package/src/do/sse-stream.ts +60 -9
- package/src/do/transcript.ts +48 -5
- package/src/do/turn-body.ts +105 -5
- package/src/do/ucan-service.ts +204 -34
- package/src/do/user-oracle-do.ts +1883 -264
- package/src/feedback/config.ts +127 -0
- package/src/feedback/contract.ts +148 -0
- package/src/feedback/linear-sink.ts +285 -0
- package/src/feedback/privacy.ts +150 -0
- package/src/feedback/reservation.ts +298 -0
- package/src/feedback/submit.ts +247 -0
- package/src/index.ts +138 -6
- package/src/llm/byo-adapter.ts +27 -6
- package/src/llm/byo-catalog.ts +13 -0
- package/src/llm/byo-model-fallback.ts +248 -0
- package/src/llm/byo-service.ts +45 -8
- package/src/llm/provider-error.ts +139 -2
- package/src/matrix/gateway-do.ts +523 -111
- package/src/matrix/group-chat.ts +66 -23
- package/src/matrix/inbox-store.ts +16 -1
- package/src/matrix/ingest.ts +79 -14
- package/src/matrix/media-deadline.ts +130 -0
- package/src/matrix/replay-format.ts +5 -3
- package/src/matrix/reply-parts.ts +92 -0
- package/src/matrix/room-alias.ts +96 -0
- package/src/matrix/user-homeserver.ts +166 -7
- package/src/owner-store/ixo-vfs-store.ts +170 -43
- package/src/owner-store/migrating-store.ts +31 -15
- package/src/owner-store/types.ts +18 -3
- package/src/plugin-api/index.ts +43 -2
- package/src/plugin-api/oracle-plugin.ts +35 -0
- package/src/plugin-api/request-admission.ts +41 -0
- package/src/plugin-api/tool-helper.ts +25 -1
- package/src/plugin-api/tool-plane.ts +92 -0
- package/src/plugin-api/types.ts +194 -6
- package/src/plugins/agui/agui.plugin.ts +31 -16
- package/src/plugins/composio/composio-tools.ts +57 -6
- package/src/plugins/composio/composio-ucan.ts +3 -2
- package/src/plugins/composio/composio.plugin.ts +2 -0
- package/src/plugins/delegated-capabilities.ts +25 -0
- package/src/plugins/editor/content-session.ts +173 -83
- package/src/plugins/editor/content-tools.ts +76 -17
- package/src/plugins/editor/editor-mx.ts +28 -9
- package/src/plugins/editor/editor.plugin.ts +3 -1
- package/src/plugins/editor/failures.ts +28 -7
- package/src/plugins/editor/prompts.ts +2 -1
- package/src/plugins/editor/provider.ts +553 -40
- package/src/plugins/editor/standalone-editor-tool.ts +61 -18
- package/src/plugins/firecrawl/firecrawl-tools.ts +13 -5
- package/src/plugins/flows/action-metadata.ts +111 -11
- package/src/plugins/flows/actions.ts +18 -0
- package/src/plugins/flows/decision-context.ts +31 -0
- package/src/plugins/flows/edit.ts +223 -52
- package/src/plugins/flows/errors.ts +22 -1
- package/src/plugins/flows/flow-doc.ts +92 -9
- package/src/plugins/flows/flows.plugin.ts +11 -5
- package/src/plugins/flows/forms.ts +34 -0
- package/src/plugins/flows/index.ts +2 -0
- package/src/plugins/flows/input-policy.ts +140 -0
- package/src/plugins/flows/prompts.ts +14 -11
- package/src/plugins/flows/read.ts +49 -9
- package/src/plugins/flows/ref-syntax.ts +129 -0
- package/src/plugins/flows/test-homeserver.ts +245 -0
- package/src/plugins/flows/tools/authoring.ts +216 -112
- package/src/plugins/flows/tools/discovery.ts +4 -1
- package/src/plugins/flows/tools/forms.ts +21 -2
- package/src/plugins/flows/tools/settings.ts +34 -13
- package/src/plugins/flows/translator.ts +13 -10
- package/src/plugins/flows/types.ts +167 -42
- package/src/plugins/index.ts +11 -1
- package/src/plugins/ixo-transaction/chain-ids.ts +43 -0
- package/src/plugins/ixo-transaction/index.ts +2 -0
- package/src/plugins/ixo-transaction/ixo-transaction.plugin.ts +119 -0
- package/src/plugins/ixo-transaction/receipts.ts +99 -0
- package/src/plugins/ixo-transaction/tools.ts +329 -0
- package/src/plugins/ixo-transaction/wallet-signing.ts +202 -0
- package/src/plugins/mcp-tool-adapter.ts +23 -2
- package/src/plugins/memory/memory-tools.ts +7 -2
- package/src/plugins/memory/memory-ucan.ts +3 -2
- package/src/plugins/memory/memory.plugin.ts +2 -0
- package/src/plugins/pod-creator/blueprint-store.ts +163 -0
- package/src/plugins/pod-creator/blueprint-types.ts +61 -0
- package/src/plugins/pod-creator/bounded-map.ts +87 -0
- package/src/plugins/pod-creator/capsule-content-client.ts +285 -0
- package/src/plugins/pod-creator/chain-gateway.ts +110 -0
- package/src/plugins/pod-creator/config.ts +85 -0
- package/src/plugins/pod-creator/create-session-store.ts +180 -0
- package/src/plugins/pod-creator/create-tools.ts +538 -0
- package/src/plugins/pod-creator/design-pod-roles.ts +111 -0
- package/src/plugins/pod-creator/index.ts +65 -0
- package/src/plugins/pod-creator/orchestration-tools.ts +172 -0
- package/src/plugins/pod-creator/pod-creator.plugin.ts +190 -0
- package/src/plugins/pod-creator/stage.ts +201 -0
- package/src/plugins/pod-creator/sub-agents.ts +189 -0
- package/src/plugins/portal/action-log.ts +21 -1
- package/src/plugins/portal/declared-tools.ts +90 -0
- package/src/plugins/portal/portal.plugin.ts +42 -16
- package/src/plugins/sandbox/sandbox-bridge.ts +79 -10
- package/src/plugins/sandbox/sandbox-mcp.ts +3 -2
- package/src/plugins/sandbox/sandbox-write-blob.ts +11 -1
- package/src/plugins/sandbox/sandbox.plugin.ts +8 -16
- package/src/plugins/tasks/manifest.ts +1 -1
- package/src/plugins/tasks/middleware.ts +20 -7
- package/src/plugins/tasks/tasks-tools.ts +30 -3
- package/src/plugins/tasks/tasks.plugin.ts +64 -11
- package/src/plugins/user-preferences/schema.ts +12 -1
- package/src/plugins/user-preferences/user-preferences-store.ts +38 -13
- package/src/plugins/user-preferences/user-preferences-tool.ts +3 -2
- package/src/plugins/vfs/vfs-client.ts +250 -71
- package/src/plugins/vfs/vfs-content.ts +30 -11
- package/src/plugins/vfs/vfs-errors.ts +22 -0
- package/src/plugins/vfs/vfs-sandbox-tools.ts +12 -5
- package/src/plugins/vfs/vfs-tools.ts +60 -20
- package/src/realtime/frontend-call-registry.ts +228 -81
- package/src/realtime/realtime-endpoint.ts +215 -44
- package/src/realtime/session-socket-hub.ts +47 -2
- package/src/secrets/secrets-service.ts +9 -3
- package/src/shell/app.ts +529 -82
- package/src/shell/auth.ts +131 -37
- package/src/shell/turn-body-cap.ts +11 -13
- package/src/sqlite/blob-compactor.ts +61 -28
- package/src/sqlite/database.ts +156 -90
- package/src/sqlite/do-vfs.ts +416 -129
- package/src/sqlite/page-tier.ts +133 -40
- package/src/sqlite/serialization.ts +40 -0
- package/src/sqlite/sessions-store.ts +10 -2
- package/src/sqlite/sqlite-saver.ts +139 -19
- package/src/sqlite/user-kv-store.ts +317 -0
- package/src/tasks/schedule.ts +201 -12
- package/src/tasks/scheduler.ts +586 -98
- package/src/tasks/spec.ts +67 -3
- package/src/tasks/store.ts +292 -27
- package/src/tasks/topic-deliverables.ts +70 -0
|
@@ -8,7 +8,6 @@
|
|
|
8
8
|
* per tool.
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
|
-
import type { MatrixClient } from 'matrix-js-sdk';
|
|
12
11
|
import type * as Y from 'yjs';
|
|
13
12
|
import { z } from 'zod';
|
|
14
13
|
|
|
@@ -18,7 +17,7 @@ import {
|
|
|
18
17
|
markdownToBlockContainers,
|
|
19
18
|
markdownToInlineContent,
|
|
20
19
|
} from './blocknote-bridge';
|
|
21
|
-
import { applyDocumentEdit,
|
|
20
|
+
import { applyDocumentEdit, type DocumentSource } from './content-session';
|
|
22
21
|
import {
|
|
23
22
|
appendBlocks,
|
|
24
23
|
flattenBlocks,
|
|
@@ -47,16 +46,17 @@ import {
|
|
|
47
46
|
type EditorFailure,
|
|
48
47
|
} from './failures';
|
|
49
48
|
import {
|
|
49
|
+
classifyBlockType,
|
|
50
50
|
filterWritableProps,
|
|
51
51
|
isTextEditable,
|
|
52
52
|
redactProps,
|
|
53
53
|
} from './prop-policy';
|
|
54
|
-
import type { AppConfig } from './provider';
|
|
55
|
-
|
|
56
54
|
export interface ContentToolsOptions {
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
55
|
+
/**
|
|
56
|
+
* The one document every tool reads and writes, shared across the calls of
|
|
57
|
+
* one `call_editor_agent` run.
|
|
58
|
+
*/
|
|
59
|
+
documents: DocumentSource;
|
|
60
60
|
}
|
|
61
61
|
|
|
62
62
|
const DEFAULT_READ_LIMIT = 60;
|
|
@@ -84,6 +84,45 @@ function redactFlat(block: FlatDocumentBlock): FlatDocumentBlock {
|
|
|
84
84
|
return { ...block, props: redactProps(block.type, block.props) };
|
|
85
85
|
}
|
|
86
86
|
|
|
87
|
+
/**
|
|
88
|
+
* The first locked block (`secrets`, `skills`) in `blockId`'s subtree,
|
|
89
|
+
* itself included. Deleting or moving a block rewrites its whole subtree, so
|
|
90
|
+
* a locked block nested anywhere inside refuses the operation.
|
|
91
|
+
*/
|
|
92
|
+
function findLockedBlock(
|
|
93
|
+
doc: Y.Doc,
|
|
94
|
+
blockId: string,
|
|
95
|
+
): { id: string; type: string } | undefined {
|
|
96
|
+
const visit = (block: DocumentBlock): DocumentBlock | undefined => {
|
|
97
|
+
if (classifyBlockType(block.type) === 'locked') return block;
|
|
98
|
+
for (const child of block.children) {
|
|
99
|
+
const hit = visit(child);
|
|
100
|
+
if (hit) return hit;
|
|
101
|
+
}
|
|
102
|
+
return undefined;
|
|
103
|
+
};
|
|
104
|
+
const root = readBlockById(doc, blockId);
|
|
105
|
+
const hit = root ? visit(root) : undefined;
|
|
106
|
+
return hit ? { id: hit.id, type: hit.type } : undefined;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/** The refusal for a delete/move that would touch a locked block. */
|
|
110
|
+
function lockedBlockRefusal(
|
|
111
|
+
blockId: string,
|
|
112
|
+
blockType: string,
|
|
113
|
+
locked: { id: string; type: string },
|
|
114
|
+
verb: 'deleted' | 'moved',
|
|
115
|
+
): EditorFailure {
|
|
116
|
+
const where =
|
|
117
|
+
locked.id === blockId ? '' : ` (block ${locked.id} is nested inside it)`;
|
|
118
|
+
return propNotEditable(blockId, blockType, [
|
|
119
|
+
{
|
|
120
|
+
prop: 'block',
|
|
121
|
+
reason: `'${locked.type}' blocks are never editable by the assistant, so this block cannot be ${verb}${where}`,
|
|
122
|
+
},
|
|
123
|
+
]);
|
|
124
|
+
}
|
|
125
|
+
|
|
87
126
|
/** Case-insensitive substring match. */
|
|
88
127
|
function matches(haystack: string, needle: string): boolean {
|
|
89
128
|
return haystack.toLowerCase().includes(needle.toLowerCase());
|
|
@@ -118,7 +157,7 @@ function createReadDocumentTool(options: ContentToolsOptions): PluginTool {
|
|
|
118
157
|
const start = args.start ?? 0;
|
|
119
158
|
const limit = args.limit ?? DEFAULT_READ_LIMIT;
|
|
120
159
|
|
|
121
|
-
const result = await
|
|
160
|
+
const result = await options.documents.use(async (session) => {
|
|
122
161
|
const blocks = flattenBlocks(readDocumentBlocks(session.doc)).map(
|
|
123
162
|
redactFlat,
|
|
124
163
|
);
|
|
@@ -161,7 +200,7 @@ function createReadBlockTool(options: ContentToolsOptions): PluginTool {
|
|
|
161
200
|
return pluginTool(
|
|
162
201
|
async (rawArgs) => {
|
|
163
202
|
const args = schema.parse(rawArgs);
|
|
164
|
-
const result = await
|
|
203
|
+
const result = await options.documents.use(async (session) => {
|
|
165
204
|
const block = readBlockById(session.doc, args.block_id);
|
|
166
205
|
if (!block) return blockNotFound(args.block_id);
|
|
167
206
|
return {
|
|
@@ -199,7 +238,7 @@ function createSearchDocumentTool(options: ContentToolsOptions): PluginTool {
|
|
|
199
238
|
const args = schema.parse(rawArgs);
|
|
200
239
|
const limit = args.limit ?? 20;
|
|
201
240
|
|
|
202
|
-
const result = await
|
|
241
|
+
const result = await options.documents.use(async (session) => {
|
|
203
242
|
const blocks = flattenBlocks(readDocumentBlocks(session.doc)).map(
|
|
204
243
|
redactFlat,
|
|
205
244
|
);
|
|
@@ -292,7 +331,7 @@ function createInsertContentTool(options: ContentToolsOptions): PluginTool {
|
|
|
292
331
|
);
|
|
293
332
|
}
|
|
294
333
|
|
|
295
|
-
const result = await
|
|
334
|
+
const result = await options.documents.use(async (session) =>
|
|
296
335
|
applyDocumentEdit(session, {
|
|
297
336
|
plan: (doc) => {
|
|
298
337
|
// Anchored inserts need a live reference; end/start do not.
|
|
@@ -395,7 +434,7 @@ function createEditBlockTool(options: ContentToolsOptions): PluginTool {
|
|
|
395
434
|
parsedText.set(index, await markdownToInlineContent(edit.text));
|
|
396
435
|
}
|
|
397
436
|
|
|
398
|
-
const result = await
|
|
437
|
+
const result = await options.documents.use(async (session) =>
|
|
399
438
|
applyDocumentEdit(session, {
|
|
400
439
|
plan: (doc): PreparedEdit[] | EditorFailure => {
|
|
401
440
|
const prepared: PreparedEdit[] = [];
|
|
@@ -484,7 +523,7 @@ function createDeleteBlockTool(options: ContentToolsOptions): PluginTool {
|
|
|
484
523
|
async (rawArgs) => {
|
|
485
524
|
const args = schema.parse(rawArgs);
|
|
486
525
|
|
|
487
|
-
const result = await
|
|
526
|
+
const result = await options.documents.use(async (session) =>
|
|
488
527
|
applyDocumentEdit(session, {
|
|
489
528
|
plan: (doc) => {
|
|
490
529
|
const located = locateBlock(
|
|
@@ -493,7 +532,17 @@ function createDeleteBlockTool(options: ContentToolsOptions): PluginTool {
|
|
|
493
532
|
);
|
|
494
533
|
if (!located) return blockNotFound(args.block_id);
|
|
495
534
|
const content = getContentElement(located.container);
|
|
496
|
-
|
|
535
|
+
const blockType = content?.nodeName ?? 'unknown';
|
|
536
|
+
const locked = findLockedBlock(doc, args.block_id);
|
|
537
|
+
if (locked) {
|
|
538
|
+
return lockedBlockRefusal(
|
|
539
|
+
args.block_id,
|
|
540
|
+
blockType,
|
|
541
|
+
locked,
|
|
542
|
+
'deleted',
|
|
543
|
+
);
|
|
544
|
+
}
|
|
545
|
+
return { blockType };
|
|
497
546
|
},
|
|
498
547
|
apply: (doc, plan) => {
|
|
499
548
|
const removed = removeBlock(doc, args.block_id);
|
|
@@ -537,13 +586,23 @@ function createMoveBlockTool(options: ContentToolsOptions): PluginTool {
|
|
|
537
586
|
async (rawArgs) => {
|
|
538
587
|
const args = schema.parse(rawArgs);
|
|
539
588
|
|
|
540
|
-
const result = await
|
|
589
|
+
const result = await options.documents.use(async (session) =>
|
|
541
590
|
applyDocumentEdit(session, {
|
|
542
591
|
plan: (doc) => {
|
|
543
592
|
const fragment = doc.getXmlFragment(DOCUMENT_FRAGMENT_NAME);
|
|
544
|
-
|
|
593
|
+
const source = locateBlock(fragment, args.block_id);
|
|
594
|
+
if (!source) {
|
|
545
595
|
return blockNotFound(args.block_id);
|
|
546
596
|
}
|
|
597
|
+
const locked = findLockedBlock(doc, args.block_id);
|
|
598
|
+
if (locked) {
|
|
599
|
+
return lockedBlockRefusal(
|
|
600
|
+
args.block_id,
|
|
601
|
+
getContentElement(source.container)?.nodeName ?? 'unknown',
|
|
602
|
+
locked,
|
|
603
|
+
'moved',
|
|
604
|
+
);
|
|
605
|
+
}
|
|
547
606
|
if (!locateBlock(fragment, args.reference_block_id)) {
|
|
548
607
|
return blockNotFound(args.reference_block_id);
|
|
549
608
|
}
|
|
@@ -619,7 +678,7 @@ function createReplaceTextTool(options: ContentToolsOptions): PluginTool {
|
|
|
619
678
|
async (rawArgs) => {
|
|
620
679
|
const args = schema.parse(rawArgs);
|
|
621
680
|
|
|
622
|
-
const result = await
|
|
681
|
+
const result = await options.documents.use(async (session) =>
|
|
623
682
|
applyDocumentEdit(session, {
|
|
624
683
|
plan: (doc) => {
|
|
625
684
|
if (args.block_id) {
|
|
@@ -11,7 +11,8 @@ export interface EditorMatrixClientConfig {
|
|
|
11
11
|
const logger = createConsoleLogger({ module: 'editor-mx' });
|
|
12
12
|
|
|
13
13
|
/**
|
|
14
|
-
* Per-isolate
|
|
14
|
+
* Per-isolate wrapper around a `matrix-js-sdk` `MatrixClient`, one live
|
|
15
|
+
* instance per set of credentials (see {@link EditorMatrixClient.getInstance}). Used
|
|
15
16
|
* by `@ixo/matrix-crdt` to read/write BlockNote Y.js documents.
|
|
16
17
|
*
|
|
17
18
|
* No `startClient()` / sync is performed — matrix-crdt's `MatrixReader`
|
|
@@ -35,15 +36,32 @@ export class EditorMatrixClient {
|
|
|
35
36
|
}
|
|
36
37
|
|
|
37
38
|
/**
|
|
38
|
-
* Get the
|
|
39
|
-
*
|
|
40
|
-
*
|
|
39
|
+
* Get the isolate's instance for these credentials. Callers pass the
|
|
40
|
+
* credentials the gateway handed out for the current request; when they
|
|
41
|
+
* differ from the cached instance's (the gateway re-minted the device
|
|
42
|
+
* token, or the homeserver or user changed) a new instance replaces it, so
|
|
43
|
+
* a warm isolate never keeps sending a revoked token. Requests already
|
|
44
|
+
* holding the previous client finish with it; it runs no sync loop, so
|
|
45
|
+
* nothing needs stopping.
|
|
41
46
|
*/
|
|
42
47
|
public static getInstance(cfg: EditorMatrixClientConfig): EditorMatrixClient {
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
48
|
+
const current = EditorMatrixClient.instance;
|
|
49
|
+
if (current && current.hasCredentials(cfg)) return current;
|
|
50
|
+
const next = new EditorMatrixClient({
|
|
51
|
+
baseUrl: cfg.baseUrl,
|
|
52
|
+
userId: cfg.userId,
|
|
53
|
+
accessToken: cfg.accessToken,
|
|
54
|
+
});
|
|
55
|
+
EditorMatrixClient.instance = next;
|
|
56
|
+
return next;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
private hasCredentials(cfg: EditorMatrixClientConfig): boolean {
|
|
60
|
+
return (
|
|
61
|
+
this.cfg.baseUrl === cfg.baseUrl &&
|
|
62
|
+
this.cfg.userId === cfg.userId &&
|
|
63
|
+
this.cfg.accessToken === cfg.accessToken
|
|
64
|
+
);
|
|
47
65
|
}
|
|
48
66
|
|
|
49
67
|
/**
|
|
@@ -113,7 +131,8 @@ export class EditorMatrixClient {
|
|
|
113
131
|
/**
|
|
114
132
|
* Resolve the `MatrixClient` used by editor tools. Prefers the
|
|
115
133
|
* `matrixClient` from the plugin's runtime config (host/test-provided);
|
|
116
|
-
* otherwise lazily constructs the internal
|
|
134
|
+
* otherwise lazily constructs the internal instance, rebuilt whenever the
|
|
135
|
+
* credentials passed in differ from the ones it was built with.
|
|
117
136
|
*
|
|
118
137
|
* Centralised so every call site (standalone-editor-tool, the flows plugin's
|
|
119
138
|
* flow-doc) goes through one resolution path.
|
|
@@ -133,7 +133,9 @@ export class EditorPlugin extends OraclePlugin {
|
|
|
133
133
|
// the import, so only the first turn in an isolate pays for it.
|
|
134
134
|
const { createStandaloneEditorTool } =
|
|
135
135
|
await import('./standalone-editor-tool');
|
|
136
|
-
return [
|
|
136
|
+
return [
|
|
137
|
+
createStandaloneEditorTool({ toolsConfig, pluginName: this.name }),
|
|
138
|
+
];
|
|
137
139
|
} catch (error) {
|
|
138
140
|
const detail = error instanceof Error ? error.message : String(error);
|
|
139
141
|
rtCtx.logger.error(`[editor] failed to build standalone tool: ${detail}`);
|
|
@@ -16,7 +16,7 @@ export type EditorFailureCode =
|
|
|
16
16
|
| 'block_not_found'
|
|
17
17
|
| 'not_a_member'
|
|
18
18
|
| 'no_document'
|
|
19
|
-
| '
|
|
19
|
+
| 'write_not_saved'
|
|
20
20
|
| 'error';
|
|
21
21
|
|
|
22
22
|
export interface EditorFailure {
|
|
@@ -120,19 +120,40 @@ export function notAMember(roomId: string): EditorFailure {
|
|
|
120
120
|
};
|
|
121
121
|
}
|
|
122
122
|
|
|
123
|
-
/**
|
|
124
|
-
|
|
123
|
+
/**
|
|
124
|
+
* The write was made locally but its delivery could not be confirmed: the
|
|
125
|
+
* homeserver kept failing (5xx, timeouts, network) until the retry budget ran
|
|
126
|
+
* out, so the change may or may not have been stored. Not an access problem —
|
|
127
|
+
* the assistant may write here.
|
|
128
|
+
*/
|
|
129
|
+
export function writeNotSaved(roomId: string, detail: string): EditorFailure {
|
|
125
130
|
return {
|
|
126
131
|
ok: false,
|
|
127
|
-
code: '
|
|
132
|
+
code: 'write_not_saved',
|
|
128
133
|
roomId,
|
|
129
134
|
message:
|
|
130
|
-
`The edit could not be confirmed as saved
|
|
131
|
-
`
|
|
132
|
-
`
|
|
135
|
+
`The edit could not be confirmed as saved — the document service did ` +
|
|
136
|
+
`not acknowledge it (${detail}), so it may or may not have landed. Do ` +
|
|
137
|
+
`not claim it succeeded. It can be retried: in a later request, read ` +
|
|
138
|
+
`the document first, then apply it again only if it is missing.`,
|
|
133
139
|
};
|
|
134
140
|
}
|
|
135
141
|
|
|
142
|
+
/**
|
|
143
|
+
* The homeserver refused the write outright (an oversized change, a revoked
|
|
144
|
+
* token, a malformed request): nothing was stored, and sending the same
|
|
145
|
+
* change again fails the same way. Not an access problem in the room.
|
|
146
|
+
*/
|
|
147
|
+
export function writeRefused(roomId: string, detail: string): EditorFailure {
|
|
148
|
+
return editorError(
|
|
149
|
+
`The edit was NOT saved — the document service refused it (${detail}). ` +
|
|
150
|
+
`Nothing was stored. Do not claim it succeeded, and do not send the ` +
|
|
151
|
+
`same change again: if it was a large change, split it into smaller ` +
|
|
152
|
+
`edits.`,
|
|
153
|
+
roomId,
|
|
154
|
+
);
|
|
155
|
+
}
|
|
156
|
+
|
|
136
157
|
/**
|
|
137
158
|
* Nothing to act on: no document is open and the call named no `room_id`.
|
|
138
159
|
* Distinct from `not_a_member` — there is no room to be a member of yet.
|
|
@@ -42,7 +42,8 @@ Tool results carry a \`code\` you must act on:
|
|
|
42
42
|
- \`block_not_found\` — the id is stale. Re-read the document and use current ids.
|
|
43
43
|
- \`not_a_member\` — the document is not the user's. Say so plainly. Do not retry.
|
|
44
44
|
- \`no_document\` — no document is open and no room id was given. Return the code; do not invent a room id.
|
|
45
|
-
- \`
|
|
45
|
+
- \`write_not_saved\` — the edit could **not** be confirmed as saved: the document service did not acknowledge it, so it may or may not have landed. Say so; do not claim it succeeded. Do not repeat it in this task — further edits in this task are refused too. In a later request, re-read the document first and apply the edit again only if it is missing.
|
|
46
|
+
- \`error\` after an edit — the document service refused it outright (for example, the change was too large): nothing was stored. Say so; do not claim it succeeded, and never send the same change again unchanged — split a large change into smaller edits.
|
|
46
47
|
|
|
47
48
|
Never present a refusal as a success, and never silently retry a refusal.`;
|
|
48
49
|
|