@ai-composer/core 0.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/LICENSE +21 -0
- package/README.md +6 -0
- package/dist/commands/builtins.d.ts +41 -0
- package/dist/commands/builtins.d.ts.map +1 -0
- package/dist/commands/builtins.js +116 -0
- package/dist/commands/builtins.js.map +1 -0
- package/dist/commands/registry.d.ts +27 -0
- package/dist/commands/registry.d.ts.map +1 -0
- package/dist/commands/registry.js +29 -0
- package/dist/commands/registry.js.map +1 -0
- package/dist/editor.d.ts +185 -0
- package/dist/editor.d.ts.map +1 -0
- package/dist/editor.js +558 -0
- package/dist/editor.js.map +1 -0
- package/dist/errors.d.ts +15 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +22 -0
- package/dist/errors.js.map +1 -0
- package/dist/events/event-bus.d.ts +19 -0
- package/dist/events/event-bus.d.ts.map +1 -0
- package/dist/events/event-bus.js +51 -0
- package/dist/events/event-bus.js.map +1 -0
- package/dist/events/events.d.ts +94 -0
- package/dist/events/events.d.ts.map +1 -0
- package/dist/events/events.js +6 -0
- package/dist/events/events.js.map +1 -0
- package/dist/factory.d.ts +17 -0
- package/dist/factory.d.ts.map +1 -0
- package/dist/factory.js +18 -0
- package/dist/factory.js.map +1 -0
- package/dist/history/history.d.ts +48 -0
- package/dist/history/history.d.ts.map +1 -0
- package/dist/history/history.js +71 -0
- package/dist/history/history.js.map +1 -0
- package/dist/index.d.ts +43 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +30 -0
- package/dist/index.js.map +1 -0
- package/dist/model/document.d.ts +54 -0
- package/dist/model/document.d.ts.map +1 -0
- package/dist/model/document.js +177 -0
- package/dist/model/document.js.map +1 -0
- package/dist/model/nodes.d.ts +80 -0
- package/dist/model/nodes.d.ts.map +1 -0
- package/dist/model/nodes.js +64 -0
- package/dist/model/nodes.js.map +1 -0
- package/dist/model/selection.d.ts +40 -0
- package/dist/model/selection.d.ts.map +1 -0
- package/dist/model/selection.js +79 -0
- package/dist/model/selection.js.map +1 -0
- package/dist/nodes/registry.d.ts +39 -0
- package/dist/nodes/registry.d.ts.map +1 -0
- package/dist/nodes/registry.js +93 -0
- package/dist/nodes/registry.js.map +1 -0
- package/dist/package.json +21 -0
- package/dist/plugins/registry.d.ts +53 -0
- package/dist/plugins/registry.d.ts.map +1 -0
- package/dist/plugins/registry.js +102 -0
- package/dist/plugins/registry.js.map +1 -0
- package/dist/serialization/builtins.d.ts +30 -0
- package/dist/serialization/builtins.d.ts.map +1 -0
- package/dist/serialization/builtins.js +102 -0
- package/dist/serialization/builtins.js.map +1 -0
- package/dist/serialization/index.d.ts +4 -0
- package/dist/serialization/index.d.ts.map +1 -0
- package/dist/serialization/index.js +3 -0
- package/dist/serialization/index.js.map +1 -0
- package/dist/serialization/registry.d.ts +17 -0
- package/dist/serialization/registry.d.ts.map +1 -0
- package/dist/serialization/registry.js +35 -0
- package/dist/serialization/registry.js.map +1 -0
- package/dist/serialization/serializers.d.ts +12 -0
- package/dist/serialization/serializers.d.ts.map +1 -0
- package/dist/serialization/serializers.js +3 -0
- package/dist/serialization/serializers.js.map +1 -0
- package/dist/state/state.d.ts +54 -0
- package/dist/state/state.d.ts.map +1 -0
- package/dist/state/state.js +6 -0
- package/dist/state/state.js.map +1 -0
- package/dist/triggers/engine.d.ts +102 -0
- package/dist/triggers/engine.d.ts.map +1 -0
- package/dist/triggers/engine.js +235 -0
- package/dist/triggers/engine.js.map +1 -0
- package/dist/types.d.ts +37 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +3 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/html.d.ts +3 -0
- package/dist/utils/html.d.ts.map +1 -0
- package/dist/utils/html.js +10 -0
- package/dist/utils/html.js.map +1 -0
- package/package.json +20 -0
- package/project.json +56 -0
- package/src/commands/builtins.ts +142 -0
- package/src/commands/registry.ts +53 -0
- package/src/commands.test.ts +118 -0
- package/src/editor.test.ts +311 -0
- package/src/editor.ts +826 -0
- package/src/errors.ts +25 -0
- package/src/events/event-bus.test.ts +62 -0
- package/src/events/event-bus.ts +72 -0
- package/src/events/events.ts +120 -0
- package/src/factory.ts +21 -0
- package/src/history/history.ts +108 -0
- package/src/index.ts +201 -0
- package/src/model/document.test.ts +130 -0
- package/src/model/document.ts +207 -0
- package/src/model/nodes.ts +151 -0
- package/src/model/selection.ts +107 -0
- package/src/nodes/registry.ts +142 -0
- package/src/plugins/registry.ts +163 -0
- package/src/serialization/builtins.ts +123 -0
- package/src/serialization/index.ts +20 -0
- package/src/serialization/registry.ts +49 -0
- package/src/serialization/serializers.ts +15 -0
- package/src/state/state.ts +57 -0
- package/src/triggers/engine.ts +317 -0
- package/src/triggers.test.ts +138 -0
- package/src/types.ts +42 -0
- package/src/utils/html.ts +9 -0
- package/tsconfig.json +15 -0
- package/tsconfig.lib.json +15 -0
- package/tsconfig.spec.json +16 -0
- package/vitest.config.ts +11 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@ai-composer/core",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"sideEffects": false,
|
|
7
|
+
"main": "./dist/index.js",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
|
+
"default": "./dist/index.js"
|
|
13
|
+
},
|
|
14
|
+
"./package.json": "./package.json"
|
|
15
|
+
},
|
|
16
|
+
"peerDependencies": {},
|
|
17
|
+
"devDependencies": {
|
|
18
|
+
"vitest": "^2.1.8"
|
|
19
|
+
},
|
|
20
|
+
"module": "./index.js"
|
|
21
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Plugin architecture (ADR-0004). Plugins are plain objects with declarative
|
|
3
|
+
* contributions plus an optional `setup()` for imperative wiring. They receive
|
|
4
|
+
* a scoped context — never raw editor internals.
|
|
5
|
+
*/
|
|
6
|
+
import type { Unsubscribe, EventBus } from '../events/event-bus';
|
|
7
|
+
import type { AIComposerEventMap } from '../events/events';
|
|
8
|
+
import type { AIComposerCommand } from '../commands/registry';
|
|
9
|
+
import type { AIComposerTrigger } from '../triggers/engine';
|
|
10
|
+
import type { NodeDefinition } from '../nodes/registry';
|
|
11
|
+
import type { Serializer } from '../serialization/serializers';
|
|
12
|
+
import type { CommandRegistry } from '../commands/registry';
|
|
13
|
+
import type { TriggerRegistry } from '../triggers/engine';
|
|
14
|
+
import type { NodeRegistry } from '../nodes/registry';
|
|
15
|
+
import type { SerializerRegistry } from '../serialization/registry';
|
|
16
|
+
import type { AIComposer } from '../editor';
|
|
17
|
+
import type { AIComposerConfig } from '../types';
|
|
18
|
+
/** Controlled capabilities exposed to plugins. */
|
|
19
|
+
export interface PluginContext {
|
|
20
|
+
editor: AIComposer;
|
|
21
|
+
getConfig(): AIComposerConfig;
|
|
22
|
+
commands: CommandRegistry;
|
|
23
|
+
triggers: TriggerRegistry;
|
|
24
|
+
nodes: NodeRegistry;
|
|
25
|
+
serializers: SerializerRegistry;
|
|
26
|
+
/** Subscribe to editor events (emit is intentionally not handed out). */
|
|
27
|
+
events: Pick<EventBus<AIComposerEventMap>, 'on' | 'once' | 'off'>;
|
|
28
|
+
/** Register cleanup run when the plugin is destroyed. */
|
|
29
|
+
onCleanup(cleanup: () => void): void;
|
|
30
|
+
}
|
|
31
|
+
export interface AIComposerPlugin {
|
|
32
|
+
/** Unique plugin name. */
|
|
33
|
+
name: string;
|
|
34
|
+
version?: string;
|
|
35
|
+
/** Imperative wiring — called once when the plugin is attached. */
|
|
36
|
+
setup?(context: PluginContext): void;
|
|
37
|
+
commands?: AIComposerCommand[];
|
|
38
|
+
triggers?: AIComposerTrigger[];
|
|
39
|
+
nodeTypes?: NodeDefinition[];
|
|
40
|
+
serializers?: Serializer[];
|
|
41
|
+
/** Called when the plugin is removed or the editor destroyed. */
|
|
42
|
+
destroy?(): void;
|
|
43
|
+
}
|
|
44
|
+
export interface PluginRegistry {
|
|
45
|
+
add(plugin: AIComposerPlugin): Unsubscribe;
|
|
46
|
+
get(name: string): AIComposerPlugin | undefined;
|
|
47
|
+
list(): AIComposerPlugin[];
|
|
48
|
+
/** Set up a plugin immediately with the given context (used by the factory). */
|
|
49
|
+
install(plugin: AIComposerPlugin, context: PluginContext): Unsubscribe;
|
|
50
|
+
destroyAll(): void;
|
|
51
|
+
}
|
|
52
|
+
export declare function createPluginRegistry(): PluginRegistry;
|
|
53
|
+
//# sourceMappingURL=registry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/plugins/registry.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AACjE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAC3D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAC9D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAC5D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,8BAA8B,CAAC;AAC/D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AACpE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAC5C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAEjD,kDAAkD;AAClD,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,UAAU,CAAC;IACnB,SAAS,IAAI,gBAAgB,CAAC;IAC9B,QAAQ,EAAE,eAAe,CAAC;IAC1B,QAAQ,EAAE,eAAe,CAAC;IAC1B,KAAK,EAAE,YAAY,CAAC;IACpB,WAAW,EAAE,kBAAkB,CAAC;IAChC,yEAAyE;IACzE,MAAM,EAAE,IAAI,CAAC,QAAQ,CAAC,kBAAkB,CAAC,EAAE,IAAI,GAAG,MAAM,GAAG,KAAK,CAAC,CAAC;IAClE,yDAAyD;IACzD,SAAS,CAAC,OAAO,EAAE,MAAM,IAAI,GAAG,IAAI,CAAC;CACtC;AAED,MAAM,WAAW,gBAAgB;IAC/B,0BAA0B;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,mEAAmE;IACnE,KAAK,CAAC,CAAC,OAAO,EAAE,aAAa,GAAG,IAAI,CAAC;IACrC,QAAQ,CAAC,EAAE,iBAAiB,EAAE,CAAC;IAC/B,QAAQ,CAAC,EAAE,iBAAiB,EAAE,CAAC;IAC/B,SAAS,CAAC,EAAE,cAAc,EAAE,CAAC;IAC7B,WAAW,CAAC,EAAE,UAAU,EAAE,CAAC;IAC3B,iEAAiE;IACjE,OAAO,CAAC,IAAI,IAAI,CAAC;CAClB;AAOD,MAAM,WAAW,cAAc;IAC7B,GAAG,CAAC,MAAM,EAAE,gBAAgB,GAAG,WAAW,CAAC;IAC3C,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,gBAAgB,GAAG,SAAS,CAAC;IAChD,IAAI,IAAI,gBAAgB,EAAE,CAAC;IAC3B,gFAAgF;IAChF,OAAO,CAAC,MAAM,EAAE,gBAAgB,EAAE,OAAO,EAAE,aAAa,GAAG,WAAW,CAAC;IACvE,UAAU,IAAI,IAAI,CAAC;CACpB;AAED,wBAAgB,oBAAoB,IAAI,cAAc,CAqGrD"}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Plugin architecture (ADR-0004). Plugins are plain objects with declarative
|
|
3
|
+
* contributions plus an optional `setup()` for imperative wiring. They receive
|
|
4
|
+
* a scoped context — never raw editor internals.
|
|
5
|
+
*/
|
|
6
|
+
export function createPluginRegistry() {
|
|
7
|
+
const installed = [];
|
|
8
|
+
const teardown = (entry) => {
|
|
9
|
+
for (const dispose of entry.disposers.splice(0)) {
|
|
10
|
+
try {
|
|
11
|
+
dispose();
|
|
12
|
+
}
|
|
13
|
+
catch (error) {
|
|
14
|
+
console.error(`[ai-composer] plugin "${entry.plugin.name}" cleanup failed`, error);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
try {
|
|
18
|
+
entry.plugin.destroy?.();
|
|
19
|
+
}
|
|
20
|
+
catch (error) {
|
|
21
|
+
console.error(`[ai-composer] plugin "${entry.plugin.name}" destroy failed`, error);
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
const registry = {
|
|
25
|
+
add(plugin) {
|
|
26
|
+
const entry = { plugin, disposers: [] };
|
|
27
|
+
installed.push(entry);
|
|
28
|
+
return () => {
|
|
29
|
+
const index = installed.indexOf(entry);
|
|
30
|
+
if (index >= 0) {
|
|
31
|
+
installed.splice(index, 1);
|
|
32
|
+
teardown(entry);
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
},
|
|
36
|
+
get(name) {
|
|
37
|
+
return installed.find((entry) => entry.plugin.name === name)?.plugin;
|
|
38
|
+
},
|
|
39
|
+
list() {
|
|
40
|
+
return installed.map((entry) => entry.plugin);
|
|
41
|
+
},
|
|
42
|
+
install(plugin, context) {
|
|
43
|
+
const entry = { plugin, disposers: [] };
|
|
44
|
+
installed.push(entry);
|
|
45
|
+
const scoped = {
|
|
46
|
+
...context,
|
|
47
|
+
onCleanup: (cleanup) => {
|
|
48
|
+
entry.disposers.push(cleanup);
|
|
49
|
+
},
|
|
50
|
+
events: {
|
|
51
|
+
on: (type, handler) => {
|
|
52
|
+
const off = context.events.on(type, handler);
|
|
53
|
+
entry.disposers.push(off);
|
|
54
|
+
return off;
|
|
55
|
+
},
|
|
56
|
+
once: (type, handler) => {
|
|
57
|
+
const off = context.events.once(type, handler);
|
|
58
|
+
entry.disposers.push(off);
|
|
59
|
+
return off;
|
|
60
|
+
},
|
|
61
|
+
off: (type, handler) => context.events.off(type, handler),
|
|
62
|
+
},
|
|
63
|
+
};
|
|
64
|
+
for (const command of plugin.commands ?? []) {
|
|
65
|
+
entry.disposers.push(context.commands.register(command));
|
|
66
|
+
}
|
|
67
|
+
for (const trigger of plugin.triggers ?? []) {
|
|
68
|
+
entry.disposers.push(context.triggers.register(trigger));
|
|
69
|
+
}
|
|
70
|
+
for (const nodeType of plugin.nodeTypes ?? []) {
|
|
71
|
+
entry.disposers.push(context.nodes.register(nodeType));
|
|
72
|
+
}
|
|
73
|
+
for (const serializer of plugin.serializers ?? []) {
|
|
74
|
+
entry.disposers.push(context.serializers.register(serializer));
|
|
75
|
+
}
|
|
76
|
+
try {
|
|
77
|
+
plugin.setup?.(scoped);
|
|
78
|
+
}
|
|
79
|
+
catch (error) {
|
|
80
|
+
// roll this plugin back; the editor stays alive
|
|
81
|
+
const index = installed.indexOf(entry);
|
|
82
|
+
if (index >= 0)
|
|
83
|
+
installed.splice(index, 1);
|
|
84
|
+
teardown(entry);
|
|
85
|
+
throw error;
|
|
86
|
+
}
|
|
87
|
+
return () => {
|
|
88
|
+
const index = installed.indexOf(entry);
|
|
89
|
+
if (index >= 0) {
|
|
90
|
+
installed.splice(index, 1);
|
|
91
|
+
teardown(entry);
|
|
92
|
+
}
|
|
93
|
+
};
|
|
94
|
+
},
|
|
95
|
+
destroyAll() {
|
|
96
|
+
for (const entry of installed.splice(0))
|
|
97
|
+
teardown(entry);
|
|
98
|
+
},
|
|
99
|
+
};
|
|
100
|
+
return registry;
|
|
101
|
+
}
|
|
102
|
+
//# sourceMappingURL=registry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/plugins/registry.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Built-in serializers. Every projection goes through the node registry so
|
|
3
|
+
* plugins control how their custom nodes serialize.
|
|
4
|
+
*/
|
|
5
|
+
import type { AIComposerDocument } from '../model/document';
|
|
6
|
+
import type { AIComposerNode } from '../model/nodes';
|
|
7
|
+
import type { Serializer, SerializerContext } from './serializers';
|
|
8
|
+
/** Structured payload handed to AI providers — provider-neutral by design (see docs). */
|
|
9
|
+
export interface AIComposerPayload {
|
|
10
|
+
text: string;
|
|
11
|
+
entities: Array<{
|
|
12
|
+
type: string;
|
|
13
|
+
key: string;
|
|
14
|
+
id?: string;
|
|
15
|
+
label?: string;
|
|
16
|
+
name?: string;
|
|
17
|
+
data?: unknown;
|
|
18
|
+
}>;
|
|
19
|
+
metadata?: Record<string, unknown>;
|
|
20
|
+
}
|
|
21
|
+
/** Plain-text projection of a single node. */
|
|
22
|
+
export declare function nodeToText(node: AIComposerNode, context: SerializerContext): string;
|
|
23
|
+
export declare function documentToText(document: AIComposerDocument, context: SerializerContext): string;
|
|
24
|
+
export declare function createJsonSerializer(): Serializer;
|
|
25
|
+
export declare function createTextSerializer(): Serializer;
|
|
26
|
+
export declare function createMarkdownSerializer(): Serializer;
|
|
27
|
+
export declare function createHtmlSerializer(): Serializer;
|
|
28
|
+
export declare function createAiSerializer(): Serializer;
|
|
29
|
+
export declare function createDefaultSerializers(): Serializer[];
|
|
30
|
+
//# sourceMappingURL=builtins.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"builtins.d.ts","sourceRoot":"","sources":["../../src/serialization/builtins.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAC5D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAErD,OAAO,KAAK,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAEnE,yFAAyF;AACzF,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,KAAK,CAAC;QACd,IAAI,EAAE,MAAM,CAAC;QACb,GAAG,EAAE,MAAM,CAAC;QACZ,EAAE,CAAC,EAAE,MAAM,CAAC;QACZ,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,IAAI,CAAC,EAAE,OAAO,CAAC;KAChB,CAAC,CAAC;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACpC;AAMD,8CAA8C;AAC9C,wBAAgB,UAAU,CAAC,IAAI,EAAE,cAAc,EAAE,OAAO,EAAE,iBAAiB,GAAG,MAAM,CAKnF;AAED,wBAAgB,cAAc,CAAC,QAAQ,EAAE,kBAAkB,EAAE,OAAO,EAAE,iBAAiB,GAAG,MAAM,CAE/F;AAcD,wBAAgB,oBAAoB,IAAI,UAAU,CAQjD;AAED,wBAAgB,oBAAoB,IAAI,UAAU,CAOjD;AAED,wBAAgB,wBAAwB,IAAI,UAAU,CAOrD;AAED,wBAAgB,oBAAoB,IAAI,UAAU,CAQjD;AAED,wBAAgB,kBAAkB,IAAI,UAAU,CAqB/C;AAED,wBAAgB,wBAAwB,IAAI,UAAU,EAAE,CAQvD"}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Built-in serializers. Every projection goes through the node registry so
|
|
3
|
+
* plugins control how their custom nodes serialize.
|
|
4
|
+
*/
|
|
5
|
+
import { escapeHtml } from '../utils/html';
|
|
6
|
+
function definitionOf(context, node) {
|
|
7
|
+
return context.nodes.get(node.type);
|
|
8
|
+
}
|
|
9
|
+
/** Plain-text projection of a single node. */
|
|
10
|
+
export function nodeToText(node, context) {
|
|
11
|
+
const def = definitionOf(context, node);
|
|
12
|
+
if (def?.toText)
|
|
13
|
+
return def.toText(node);
|
|
14
|
+
if (node.type === 'text')
|
|
15
|
+
return node.text;
|
|
16
|
+
return '';
|
|
17
|
+
}
|
|
18
|
+
export function documentToText(document, context) {
|
|
19
|
+
return document.nodes.map((node) => nodeToText(node, context)).join('');
|
|
20
|
+
}
|
|
21
|
+
function nodeToMarkdown(node, context) {
|
|
22
|
+
const def = definitionOf(context, node);
|
|
23
|
+
if (def?.toMarkdown)
|
|
24
|
+
return def.toMarkdown(node);
|
|
25
|
+
return nodeToText(node, context);
|
|
26
|
+
}
|
|
27
|
+
function nodeToHtml(node, context) {
|
|
28
|
+
const def = definitionOf(context, node);
|
|
29
|
+
if (def?.toHtml)
|
|
30
|
+
return def.toHtml(node);
|
|
31
|
+
return escapeHtml(nodeToText(node, context));
|
|
32
|
+
}
|
|
33
|
+
export function createJsonSerializer() {
|
|
34
|
+
return {
|
|
35
|
+
format: 'json',
|
|
36
|
+
serialize(document) {
|
|
37
|
+
// Round-trip safe: plain JSON structures only.
|
|
38
|
+
return JSON.parse(JSON.stringify(document));
|
|
39
|
+
},
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
export function createTextSerializer() {
|
|
43
|
+
return {
|
|
44
|
+
format: 'text',
|
|
45
|
+
serialize(document, context) {
|
|
46
|
+
return documentToText(document, context);
|
|
47
|
+
},
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
export function createMarkdownSerializer() {
|
|
51
|
+
return {
|
|
52
|
+
format: 'markdown',
|
|
53
|
+
serialize(document, context) {
|
|
54
|
+
return document.nodes.map((node) => nodeToMarkdown(node, context)).join('');
|
|
55
|
+
},
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
export function createHtmlSerializer() {
|
|
59
|
+
return {
|
|
60
|
+
format: 'html',
|
|
61
|
+
serialize(document, context) {
|
|
62
|
+
const body = document.nodes.map((node) => nodeToHtml(node, context)).join('');
|
|
63
|
+
return `<div data-aic-document>${body}</div>`;
|
|
64
|
+
},
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
export function createAiSerializer() {
|
|
68
|
+
return {
|
|
69
|
+
format: 'ai',
|
|
70
|
+
serialize(document, context) {
|
|
71
|
+
return {
|
|
72
|
+
text: documentToText(document, context),
|
|
73
|
+
entities: document.nodes
|
|
74
|
+
.filter((node) => node.type !== 'text')
|
|
75
|
+
.map((node) => {
|
|
76
|
+
const base = { type: node.type, key: node.key };
|
|
77
|
+
const record = node;
|
|
78
|
+
if (typeof record.id === 'string')
|
|
79
|
+
base.id = record.id;
|
|
80
|
+
if (typeof record.label === 'string')
|
|
81
|
+
base.label = record.label;
|
|
82
|
+
if (typeof record.name === 'string')
|
|
83
|
+
base.name = record.name;
|
|
84
|
+
if (node.type === 'custom')
|
|
85
|
+
base.data = record.data;
|
|
86
|
+
return base;
|
|
87
|
+
}),
|
|
88
|
+
...(document.metadata ? { metadata: document.metadata } : {}),
|
|
89
|
+
};
|
|
90
|
+
},
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
export function createDefaultSerializers() {
|
|
94
|
+
return [
|
|
95
|
+
createJsonSerializer(),
|
|
96
|
+
createTextSerializer(),
|
|
97
|
+
createMarkdownSerializer(),
|
|
98
|
+
createHtmlSerializer(),
|
|
99
|
+
createAiSerializer(),
|
|
100
|
+
];
|
|
101
|
+
}
|
|
102
|
+
//# sourceMappingURL=builtins.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"builtins.js","sourceRoot":"","sources":["../../src/serialization/builtins.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export type { SerializationFormat, Serializer, SerializerContext, } from './serializers';
|
|
2
|
+
export { createSerializerRegistry, type SerializerRegistry, } from './registry';
|
|
3
|
+
export { createAiSerializer, createDefaultSerializers, createHtmlSerializer, createJsonSerializer, createMarkdownSerializer, createTextSerializer, documentToText, nodeToText, type AIComposerPayload, } from './builtins';
|
|
4
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/serialization/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,mBAAmB,EACnB,UAAU,EACV,iBAAiB,GAClB,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,wBAAwB,EACxB,KAAK,kBAAkB,GACxB,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,kBAAkB,EAClB,wBAAwB,EACxB,oBAAoB,EACpB,oBAAoB,EACpB,wBAAwB,EACxB,oBAAoB,EACpB,cAAc,EACd,UAAU,EACV,KAAK,iBAAiB,GACvB,MAAM,YAAY,CAAC"}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export { createSerializerRegistry, } from './registry';
|
|
2
|
+
export { createAiSerializer, createDefaultSerializers, createHtmlSerializer, createJsonSerializer, createMarkdownSerializer, createTextSerializer, documentToText, nodeToText, } from './builtins';
|
|
3
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/serialization/index.ts"],"names":[],"mappings":"AAKA,OAAO,EACL,wBAAwB,GAEzB,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,kBAAkB,EAClB,wBAAwB,EACxB,oBAAoB,EACpB,oBAAoB,EACpB,wBAAwB,EACxB,oBAAoB,EACpB,cAAc,EACd,UAAU,GAEX,MAAM,YAAY,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Serializer registry (ADR-0006). Built-in formats: json, text, markdown,
|
|
3
|
+
* html, ai. Plugins can add formats or override built-ins by re-registering
|
|
4
|
+
* the same format id (last registration wins).
|
|
5
|
+
*/
|
|
6
|
+
import type { Unsubscribe } from '../events/event-bus';
|
|
7
|
+
import type { AIComposerDocument } from '../model/document';
|
|
8
|
+
import type { SerializationFormat, Serializer, SerializerContext } from './serializers';
|
|
9
|
+
export interface SerializerRegistry {
|
|
10
|
+
register(serializer: Serializer): Unsubscribe;
|
|
11
|
+
get(format: SerializationFormat): Serializer | undefined;
|
|
12
|
+
formats(): SerializationFormat[];
|
|
13
|
+
serialize(format: SerializationFormat, document: AIComposerDocument, context: SerializerContext): unknown;
|
|
14
|
+
clear(): void;
|
|
15
|
+
}
|
|
16
|
+
export declare function createSerializerRegistry(): SerializerRegistry;
|
|
17
|
+
//# sourceMappingURL=registry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/serialization/registry.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAEvD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAC5D,OAAO,KAAK,EAAE,mBAAmB,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAExF,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,UAAU,EAAE,UAAU,GAAG,WAAW,CAAC;IAC9C,GAAG,CAAC,MAAM,EAAE,mBAAmB,GAAG,UAAU,GAAG,SAAS,CAAC;IACzD,OAAO,IAAI,mBAAmB,EAAE,CAAC;IACjC,SAAS,CAAC,MAAM,EAAE,mBAAmB,EAAE,QAAQ,EAAE,kBAAkB,EAAE,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC;IAC1G,KAAK,IAAI,IAAI,CAAC;CACf;AAED,wBAAgB,wBAAwB,IAAI,kBAAkB,CA6B7D"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Serializer registry (ADR-0006). Built-in formats: json, text, markdown,
|
|
3
|
+
* html, ai. Plugins can add formats or override built-ins by re-registering
|
|
4
|
+
* the same format id (last registration wins).
|
|
5
|
+
*/
|
|
6
|
+
import { AIComposerError } from '../errors';
|
|
7
|
+
export function createSerializerRegistry() {
|
|
8
|
+
const serializers = new Map();
|
|
9
|
+
return {
|
|
10
|
+
register(serializer) {
|
|
11
|
+
serializers.set(serializer.format, serializer);
|
|
12
|
+
return () => {
|
|
13
|
+
if (serializers.get(serializer.format) === serializer)
|
|
14
|
+
serializers.delete(serializer.format);
|
|
15
|
+
};
|
|
16
|
+
},
|
|
17
|
+
get(format) {
|
|
18
|
+
return serializers.get(format);
|
|
19
|
+
},
|
|
20
|
+
formats() {
|
|
21
|
+
return [...serializers.keys()];
|
|
22
|
+
},
|
|
23
|
+
serialize(format, document, context) {
|
|
24
|
+
const serializer = serializers.get(format);
|
|
25
|
+
if (!serializer) {
|
|
26
|
+
throw new AIComposerError('UNKNOWN_FORMAT', `No serializer registered for "${format}". Registered: ${[...serializers.keys()].join(', ') || 'none'}`);
|
|
27
|
+
}
|
|
28
|
+
return serializer.serialize(document, context);
|
|
29
|
+
},
|
|
30
|
+
clear() {
|
|
31
|
+
serializers.clear();
|
|
32
|
+
},
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=registry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/serialization/registry.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAY5C,MAAM,UAAU,wBAAwB;IACtC,MAAM,WAAW,GAAG,IAAI,GAAG,EAAmC,CAAC;IAC/D,OAAO;QACL,QAAQ,CAAC,UAAU;YACjB,WAAW,CAAC,GAAG,CAAC,UAAU,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;YAC/C,OAAO,GAAG,EAAE;gBACV,IAAI,WAAW,CAAC,GAAG,CAAC,UAAU,CAAC,MAAM,CAAC,KAAK,UAAU;oBAAE,WAAW,CAAC,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;YAC/F,CAAC,CAAC;QACJ,CAAC;QACD,GAAG,CAAC,MAAM;YACR,OAAO,WAAW,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QACjC,CAAC;QACD,OAAO;YACL,OAAO,CAAC,GAAG,WAAW,CAAC,IAAI,EAAE,CAAC,CAAC;QACjC,CAAC;QACD,SAAS,CAAC,MAAM,EAAE,QAAQ,EAAE,OAAO;YACjC,MAAM,UAAU,GAAG,WAAW,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;YAC3C,IAAI,CAAC,UAAU,EAAE,CAAC;gBAChB,MAAM,IAAI,eAAe,CACvB,gBAAgB,EAChB,iCAAiC,MAAM,kBAAkB,CAAC,GAAG,WAAW,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,MAAM,EAAE,CACxG,CAAC;YACJ,CAAC;YACD,OAAO,UAAU,CAAC,SAAS,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QACjD,CAAC;QACD,KAAK;YACH,WAAW,CAAC,KAAK,EAAE,CAAC;QACtB,CAAC;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/** Serializer contracts. Built-in implementations live in ./builtins.ts. */
|
|
2
|
+
import type { AIComposerDocument } from '../model/document';
|
|
3
|
+
import type { NodeRegistry } from '../nodes/registry';
|
|
4
|
+
export type SerializationFormat = 'json' | 'text' | 'markdown' | 'html' | 'ai';
|
|
5
|
+
export interface SerializerContext {
|
|
6
|
+
nodes: NodeRegistry;
|
|
7
|
+
}
|
|
8
|
+
export interface Serializer {
|
|
9
|
+
format: SerializationFormat;
|
|
10
|
+
serialize(document: AIComposerDocument, context: SerializerContext): unknown;
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=serializers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"serializers.d.ts","sourceRoot":"","sources":["../../src/serialization/serializers.ts"],"names":[],"mappings":"AAAA,4EAA4E;AAE5E,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAC5D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEtD,MAAM,MAAM,mBAAmB,GAAG,MAAM,GAAG,MAAM,GAAG,UAAU,GAAG,MAAM,GAAG,IAAI,CAAC;AAE/E,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,YAAY,CAAC;CACrB;AAED,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,mBAAmB,CAAC;IAC5B,SAAS,CAAC,QAAQ,EAAE,kBAAkB,EAAE,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC;CAC9E"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"serializers.js","sourceRoot":"","sources":["../../src/serialization/serializers.ts"],"names":[],"mappings":"AAAA,4EAA4E"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Observable, framework-neutral editor state. Adapters expose it as
|
|
3
|
+
* React hooks state, Angular signals, Vue refs, Svelte stores — core stays UI-free.
|
|
4
|
+
*/
|
|
5
|
+
import type { AIComposerDocument } from '../model/document';
|
|
6
|
+
import type { AttachmentNode } from '../model/nodes';
|
|
7
|
+
import type { SelectionState } from '../model/selection';
|
|
8
|
+
/** One entry of a trigger's suggestion list. */
|
|
9
|
+
export interface SuggestionItem {
|
|
10
|
+
id: string;
|
|
11
|
+
label: string;
|
|
12
|
+
description?: string;
|
|
13
|
+
/** Optional grouping heading in the suggestion UI. */
|
|
14
|
+
group?: string;
|
|
15
|
+
/** Icon name/URL — rendering is up to the UI layer. */
|
|
16
|
+
icon?: string;
|
|
17
|
+
/** Plugin-specific payload handed back on select. */
|
|
18
|
+
data?: Record<string, unknown>;
|
|
19
|
+
}
|
|
20
|
+
/** Live trigger session, e.g. while the user types "@jo". */
|
|
21
|
+
export interface TriggerState {
|
|
22
|
+
triggerId: string;
|
|
23
|
+
/** Text typed after the trigger character. */
|
|
24
|
+
query: string;
|
|
25
|
+
/** Index of the text node containing the trigger run. */
|
|
26
|
+
nodeIndex: number;
|
|
27
|
+
/** Offset of the trigger character within that text node. */
|
|
28
|
+
triggerOffset: number;
|
|
29
|
+
/** Offset where the query ends (the caret at scan time). */
|
|
30
|
+
endOffset: number;
|
|
31
|
+
}
|
|
32
|
+
export interface AIComposerState {
|
|
33
|
+
/** Current document value. */
|
|
34
|
+
value: AIComposerDocument;
|
|
35
|
+
focused: boolean;
|
|
36
|
+
disabled: boolean;
|
|
37
|
+
readonly: boolean;
|
|
38
|
+
/** True while an async submit handler is running. */
|
|
39
|
+
submitting: boolean;
|
|
40
|
+
selection: SelectionState;
|
|
41
|
+
activeTrigger: TriggerState | null;
|
|
42
|
+
suggestions: SuggestionItem[];
|
|
43
|
+
/** Highlighted suggestion (-1 when none). */
|
|
44
|
+
activeSuggestionIndex: number;
|
|
45
|
+
/** Convenience view of attachment nodes inside the document. */
|
|
46
|
+
attachments: AttachmentNode[];
|
|
47
|
+
canUndo: boolean;
|
|
48
|
+
canRedo: boolean;
|
|
49
|
+
/** Active presentation mode / preset name (e.g. 'chat'). */
|
|
50
|
+
mode: string;
|
|
51
|
+
placeholder: string;
|
|
52
|
+
empty: boolean;
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=state.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"state.d.ts","sourceRoot":"","sources":["../../src/state/state.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAC5D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AACrD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAEzD,gDAAgD;AAChD,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,sDAAsD;IACtD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,uDAAuD;IACvD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,qDAAqD;IACrD,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAChC;AAED,6DAA6D;AAC7D,MAAM,WAAW,YAAY;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,8CAA8C;IAC9C,KAAK,EAAE,MAAM,CAAC;IACd,yDAAyD;IACzD,SAAS,EAAE,MAAM,CAAC;IAClB,6DAA6D;IAC7D,aAAa,EAAE,MAAM,CAAC;IACtB,4DAA4D;IAC5D,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,eAAe;IAC9B,8BAA8B;IAC9B,KAAK,EAAE,kBAAkB,CAAC;IAC1B,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,OAAO,CAAC;IAClB,QAAQ,EAAE,OAAO,CAAC;IAClB,qDAAqD;IACrD,UAAU,EAAE,OAAO,CAAC;IACpB,SAAS,EAAE,cAAc,CAAC;IAC1B,aAAa,EAAE,YAAY,GAAG,IAAI,CAAC;IACnC,WAAW,EAAE,cAAc,EAAE,CAAC;IAC9B,6CAA6C;IAC7C,qBAAqB,EAAE,MAAM,CAAC;IAC9B,gEAAgE;IAChE,WAAW,EAAE,cAAc,EAAE,CAAC;IAC9B,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,OAAO,CAAC;IACjB,4DAA4D;IAC5D,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,OAAO,CAAC;CAChB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"state.js","sourceRoot":"","sources":["../../src/state/state.ts"],"names":[],"mappings":"AAAA;;;GAGG"}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Trigger system — detects trigger characters (`@`, `/`, `#`, `$`, `:` …)
|
|
3
|
+
* typed before the caret, runs the owning trigger's search, and manages the
|
|
4
|
+
* suggestion session in editor state.
|
|
5
|
+
*/
|
|
6
|
+
import type { Unsubscribe } from '../events/event-bus';
|
|
7
|
+
import { type AIComposerNode } from '../model/nodes';
|
|
8
|
+
import type { AIComposerDocument } from '../model/document';
|
|
9
|
+
import type { SelectionState } from '../model/selection';
|
|
10
|
+
import type { SuggestionItem, TriggerState } from '../state/state';
|
|
11
|
+
import type { AIComposer } from '../editor';
|
|
12
|
+
import type { AIComposerBus } from '../events/events';
|
|
13
|
+
export interface TriggerSearchContext {
|
|
14
|
+
query: string;
|
|
15
|
+
document: AIComposerDocument;
|
|
16
|
+
selection: SelectionState;
|
|
17
|
+
/** Aborted when a newer keystroke superseded this search. */
|
|
18
|
+
signal?: AbortSignal;
|
|
19
|
+
}
|
|
20
|
+
export interface TriggerSelectContext {
|
|
21
|
+
editor: AIComposer;
|
|
22
|
+
document: AIComposerDocument;
|
|
23
|
+
/** Text node index containing the trigger run. */
|
|
24
|
+
nodeIndex: number;
|
|
25
|
+
/** Offset of the trigger character. */
|
|
26
|
+
triggerOffset: number;
|
|
27
|
+
/** Offset where the query ends. */
|
|
28
|
+
endOffset: number;
|
|
29
|
+
query: string;
|
|
30
|
+
item: SuggestionItem;
|
|
31
|
+
}
|
|
32
|
+
export interface AIComposerTrigger {
|
|
33
|
+
id: string;
|
|
34
|
+
/** Character that activates the trigger, e.g. '@'. */
|
|
35
|
+
character: string;
|
|
36
|
+
/** Node type produced by the default select behavior ('mention' by default). */
|
|
37
|
+
type?: string;
|
|
38
|
+
/** Allow spaces inside the query (default false). */
|
|
39
|
+
allowSpaces?: boolean;
|
|
40
|
+
/** Allow the trigger character mid-word, e.g. "user@x" (default false). */
|
|
41
|
+
allowMidWord?: boolean;
|
|
42
|
+
/** Provide suggestions for the current query. */
|
|
43
|
+
search(context: TriggerSearchContext): SuggestionItem[] | Promise<SuggestionItem[]>;
|
|
44
|
+
/**
|
|
45
|
+
* Handle selection. When omitted, the trigger run is replaced with an
|
|
46
|
+
* atomic node built from the item (see createNodeFromSuggestion).
|
|
47
|
+
*/
|
|
48
|
+
select?(item: SuggestionItem, context: TriggerSelectContext): void;
|
|
49
|
+
}
|
|
50
|
+
export interface TriggerRegistry {
|
|
51
|
+
register(trigger: AIComposerTrigger): Unsubscribe;
|
|
52
|
+
get(id: string): AIComposerTrigger | undefined;
|
|
53
|
+
list(): AIComposerTrigger[];
|
|
54
|
+
clear(): void;
|
|
55
|
+
}
|
|
56
|
+
export declare function createTriggerRegistry(): TriggerRegistry;
|
|
57
|
+
/** Build the atomic node a trigger inserts for a chosen suggestion. */
|
|
58
|
+
export declare function createNodeFromSuggestion(trigger: AIComposerTrigger, item: SuggestionItem): AIComposerNode;
|
|
59
|
+
/** Narrow host surface the engine needs from the editor (keeps the engine testable). */
|
|
60
|
+
export interface TriggerHost {
|
|
61
|
+
readonly editor: AIComposer;
|
|
62
|
+
readonly document: AIComposerDocument;
|
|
63
|
+
readonly selection: SelectionState;
|
|
64
|
+
readonly triggers: TriggerRegistry;
|
|
65
|
+
readonly events: AIComposerBus;
|
|
66
|
+
patchState(patch: {
|
|
67
|
+
activeTrigger?: TriggerState | null;
|
|
68
|
+
suggestions?: SuggestionItem[];
|
|
69
|
+
activeSuggestionIndex?: number;
|
|
70
|
+
}): void;
|
|
71
|
+
/** Replace the trigger run with nodes as one history step; caret lands after the run. */
|
|
72
|
+
replaceRun(state: TriggerState, nodes: AIComposerNode[], options?: {
|
|
73
|
+
trailingSpace?: boolean;
|
|
74
|
+
source?: 'api' | 'plugin' | 'user';
|
|
75
|
+
}): void;
|
|
76
|
+
}
|
|
77
|
+
export declare class TriggerEngine {
|
|
78
|
+
private readonly host;
|
|
79
|
+
private active;
|
|
80
|
+
private items;
|
|
81
|
+
private activeIndex;
|
|
82
|
+
private searchToken;
|
|
83
|
+
constructor(host: TriggerHost);
|
|
84
|
+
get activeTrigger(): TriggerState | null;
|
|
85
|
+
get suggestions(): SuggestionItem[];
|
|
86
|
+
get activeSuggestionIndex(): number;
|
|
87
|
+
/** Re-evaluate the trigger context after a document change. */
|
|
88
|
+
handleDocumentChange(): void;
|
|
89
|
+
handleSelectionChange(): void;
|
|
90
|
+
/** Move the highlighted suggestion (ArrowUp/ArrowDown). */
|
|
91
|
+
moveSelection(delta: number): void;
|
|
92
|
+
/** Accept a suggestion (click, Enter/Tab, or programmatic). */
|
|
93
|
+
accept(item?: SuggestionItem): Promise<void>;
|
|
94
|
+
/** Close the active trigger session. */
|
|
95
|
+
close(reason: 'select' | 'escape' | 'blur' | 'input' | 'manual' | 'editor-destroy'): void;
|
|
96
|
+
private evaluate;
|
|
97
|
+
private runSearch;
|
|
98
|
+
private setSuggestions;
|
|
99
|
+
}
|
|
100
|
+
/** Convenience factory used by tests and plugins to build triggers quickly. */
|
|
101
|
+
export declare function defineTrigger(trigger: AIComposerTrigger): AIComposerTrigger;
|
|
102
|
+
//# sourceMappingURL=engine.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../../src/triggers/engine.ts"],"names":[],"mappings":"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"}
|