@dot-agent/kernel-dsl 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 ADDED
@@ -0,0 +1,178 @@
1
+ Apache License
2
+ Version 2.0, January 2004
3
+ http://www.apache.org/licenses/
4
+
5
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
+
7
+ 1. Definitions.
8
+
9
+ "License" shall mean the terms and conditions for use, reproduction,
10
+ and distribution as defined by Sections 1 through 9 of this document.
11
+
12
+ "Licensor" shall mean the copyright owner or entity authorized by
13
+ the copyright owner that is granting the License.
14
+
15
+ "Legal Entity" shall mean the union of the acting entity and all
16
+ other entities that control, are controlled by, or are under common
17
+ control with that entity. For the purposes of this definition,
18
+ "control" means (i) the power, direct or indirect, to cause the
19
+ direction or management of such entity, whether by contract or
20
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
21
+ outstanding shares, or (iii) beneficial ownership of such entity.
22
+
23
+ "You" (or "Your") shall mean an individual or Legal Entity
24
+ exercising permissions granted by this License.
25
+
26
+ "Source" form shall mean the preferred form for making modifications,
27
+ including but not limited to software source code, documentation
28
+ source, and configuration files.
29
+
30
+ "Object" form shall mean any form resulting from mechanical
31
+ transformation or translation of a Source form, including but
32
+ not limited to compiled object code, generated documentation,
33
+ and conversions to other media types.
34
+
35
+ "Work" shall mean the work of authorship made available under
36
+ the License, as indicated by a copyright notice that is included in
37
+ or attached to the work (an example is provided in the Appendix below).
38
+
39
+ "Derivative Works" shall mean any work, whether in Source or Object
40
+ form, that is based on (or derived from) the Work and for which the
41
+ editorial revisions, annotations, elaborations, or other modifications
42
+ represent, as a whole, an original work of authorship. For the purposes
43
+ of this License, Derivative Works shall not include works that remain
44
+ separable from, or merely link (or bind by name) to the interfaces of,
45
+ the Work and Derivative Works thereof.
46
+
47
+ "Contribution" shall mean, as submitted to the Licensor for inclusion
48
+ in the Work by the copyright owner or by an individual or Legal Entity
49
+ authorized to submit on behalf of the copyright owner. For the purposes
50
+ of this definition, "submitted" means any form of electronic, verbal,
51
+ or written communication sent to the Licensor or its representatives,
52
+ including but not limited to communication on electronic mailing lists,
53
+ source code control systems, and issue tracking systems that are managed
54
+ by, or on behalf of, the Licensor for the purpose of discussing and
55
+ improving the Work, but excluding communication that is conspicuously
56
+ marked or designated in writing by the copyright owner as "Not a
57
+ Contribution."
58
+
59
+ "Contributor" shall mean Licensor and any Legal Entity on behalf of
60
+ whom a Contribution has been received by the Licensor and included
61
+ within the Work.
62
+
63
+ 2. Grant of Copyright License. Subject to the terms and conditions of
64
+ this License, each Contributor hereby grants to You a perpetual,
65
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
66
+ copyright license to reproduce, prepare Derivative Works of,
67
+ publicly display, publicly perform, sublicense, and distribute the
68
+ Work and such Derivative Works in Source or Object form.
69
+
70
+ 3. Grant of Patent License. Subject to the terms and conditions of
71
+ this License, each Contributor hereby grants to You a perpetual,
72
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
73
+ (except as stated in this section) patent license to make, have made,
74
+ use, offer to sell, sell, import, and otherwise transfer the Work,
75
+ where such license applies only to those patent licenses granted to
76
+ You under this License for that Work shall terminate as of the date
77
+ such litigation is filed.
78
+
79
+ 4. Redistribution. You may reproduce and distribute copies of the
80
+ Work or Derivative Works thereof in any medium, with or without
81
+ modifications, and in Source or Object form, provided that You
82
+ meet the following conditions:
83
+
84
+ (a) You must give any other recipients of the Work or Derivative
85
+ Works a copy of this License; and
86
+
87
+ (b) You must cause any modified files to carry prominent notices
88
+ stating that You changed the files; and
89
+
90
+ (c) You must retain, in the Source form of any Derivative Works
91
+ that You distribute, all copyright, patent, trademark, and
92
+ attribution notices from the Source form of the Work,
93
+ excluding those notices that do not pertain to any part of
94
+ the Derivative Works; and
95
+
96
+ (d) If the Work includes a "NOTICE" text file as part of its
97
+ distribution, You must include a readable copy of the
98
+ attribution notices contained within such NOTICE file, in
99
+ at least one of the following places: within a NOTICE text
100
+ file distributed as part of the Derivative Works; within
101
+ the Source form or documentation, if provided along with the
102
+ Derivative Works; or, within a display generated by the
103
+ Derivative Works, if and wherever such third-party notices
104
+ normally appear. The contents of the NOTICE file are for
105
+ informational purposes only and do not modify the License.
106
+ You may add Your own attribution notices within Derivative
107
+ Works that You distribute, alongside or as an addendum to
108
+ the NOTICE text from the Work, provided that such additional
109
+ attribution notices cannot be construed as modifying the License.
110
+
111
+ You may add Your own license statement for Your modifications and
112
+ may provide additional grant of rights to use, copy, modify, merge,
113
+ publish, distribute, sublicense, and/or sell copies of the
114
+ Contribution, either in combined form with the Work or separate from
115
+ the Work. If You choose to provide additional grant of rights, You
116
+ must do so in a manner consistent with the terms of this License.
117
+
118
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
119
+ any Contribution intentionally submitted for inclusion in the Work
120
+ by You to the Licensor shall be under the terms and conditions of
121
+ this License, without any additional terms or conditions.
122
+ Notwithstanding the above, nothing herein shall supersede or modify
123
+ the terms of any separate license agreement you may have executed
124
+ with Licensor regarding such Contributions.
125
+
126
+ 6. Trademarks. This License does not grant permission to use the trade
127
+ names, trademarks, service marks, or product names of the Licensor,
128
+ except as required for reasonable and customary use in describing the
129
+ origin of the Work and reproducing the content of the NOTICE file.
130
+
131
+ 7. Disclaimer of Warranty. Unless required by applicable law or
132
+ agreed to in writing, Licensor provides the Work (and each
133
+ Contributor provides its Contributions) on an "AS IS" BASIS,
134
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
135
+ implied, including, without limitation, any warranties or conditions
136
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
137
+ PARTICULAR PURPOSE. You are solely responsible for determining the
138
+ appropriateness of using or reproducing the Work and assume any
139
+ risks associated with Your exercise of permissions under this License.
140
+
141
+ 8. Limitation of Liability. In no event and under no legal theory,
142
+ whether in tort (including negligence), contract, or otherwise,
143
+ unless required by applicable law (such as deliberate and grossly
144
+ negligent acts) or agreed to in writing, shall any Contributor be
145
+ liable to You for damages, including any direct, indirect, special,
146
+ incidental, or exemplary damages of any character arising as a
147
+ result of this License or out of the use or inability to use the
148
+ Work (including but not limited to damages for loss of goodwill,
149
+ work stoppage, computer failure or malfunction, or all other
150
+ commercial damages or losses), even if such Contributor has been
151
+ advised of the possibility of such damages.
152
+
153
+ 9. Accepting Warranty or Additional Liability. While redistributing
154
+ the Work or Derivative Works thereof, You may choose to offer,
155
+ and charge a fee for, acceptance of support, warranty, indemnity,
156
+ or other liability obligations and/or rights consistent with this
157
+ License. However, in accepting such obligations, You may act only
158
+ on Your own behalf and on Your sole responsibility, not on behalf
159
+ of any other Contributor, and only if You agree to indemnify,
160
+ defend, and hold each Contributor harmless for any liability
161
+ incurred by, or claims asserted against, such Contributor by reason
162
+ of your accepting any such warranty or additional liability.
163
+
164
+ END OF TERMS AND CONDITIONS
165
+
166
+ Copyright (c) 2026 Danilo Borges (https://github.com/daniloborges)
167
+
168
+ Licensed under the Apache License, Version 2.0 (the "License");
169
+ you may not use this file except in compliance with the License.
170
+ You may obtain a copy of the License at
171
+
172
+ http://www.apache.org/licenses/LICENSE-2.0
173
+
174
+ Unless required by applicable law or agreed to in writing, software
175
+ distributed under the License is distributed on an "AS IS" BASIS,
176
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
177
+ See the License for the specific language governing permissions and
178
+ limitations under the License.
package/README.md ADDED
@@ -0,0 +1,244 @@
1
+ # @dot-agent/kernel-dsl
2
+
3
+ Execution engine for the **agent behavior DSL** (`.description` and `.behavior` files), written in Rust and compiled to **WebAssembly**. Implements a Finite State Machine (FSM) that interprets `.behavior` files according to the full dot-agent-spec, running entirely in-memory on the client side (browser or Node.js).
4
+
5
+ ## Quick Start
6
+
7
+ ### Installation
8
+
9
+ ```bash
10
+ npm install @dot-agent/kernel-dsl
11
+ ```
12
+
13
+ ### Basic Usage
14
+
15
+ ```javascript
16
+ import { AgentDSLKernel, init } from '@dot-agent/kernel-dsl';
17
+
18
+ // Initialize WASM once
19
+ await init();
20
+
21
+ // Create kernel instance
22
+ const kernel = new AgentDSLKernel();
23
+
24
+ // Load behavior DSL
25
+ const behavior = `
26
+ state welcome
27
+ goal "Help the user"
28
+ interact
29
+ on intent "help" transition to helping
30
+
31
+ state helping
32
+ goal "Provide assistance"
33
+ `;
34
+
35
+ kernel.load_behavior(behavior);
36
+
37
+ // Get current state
38
+ console.log(kernel.get_current_state()); // "welcome"
39
+
40
+ // Listen to state changes and effects
41
+ kernel.observe((effect) => {
42
+ console.log('Effect:', effect);
43
+
44
+ switch (effect.type) {
45
+ case 'goal':
46
+ console.log('Goal:', effect.text);
47
+ break;
48
+ case 'transition':
49
+ console.log('Transitioned to:', effect.to);
50
+ break;
51
+ }
52
+ });
53
+
54
+ // Send intents
55
+ kernel.send_intent("help");
56
+
57
+ // Get state graph
58
+ const graph = kernel.get_graph();
59
+ console.log('States:', graph.states);
60
+ console.log('Transitions:', graph.transitions);
61
+ ```
62
+
63
+ ### React Integration
64
+
65
+ ```typescript
66
+ import { AgentDSLKernel, init } from '@dot-agent/kernel-dsl';
67
+ import { useEffect, useState } from 'react';
68
+
69
+ export function AgentPanel() {
70
+ const [engine, setEngine] = useState<AgentDSLKernel | null>(null);
71
+ const [currentState, setCurrentState] = useState('');
72
+
73
+ useEffect(() => {
74
+ (async () => {
75
+ await init();
76
+ const kernel = new AgentDSLKernel();
77
+
78
+ kernel.observe((effect) => {
79
+ if (effect.type === 'transition') {
80
+ setCurrentState(effect.to);
81
+ }
82
+ });
83
+
84
+ setEngine(kernel);
85
+ })();
86
+ }, []);
87
+
88
+ if (!engine) return <div>Loading...</div>;
89
+
90
+ return (
91
+ <div>
92
+ <p>Current State: {currentState}</p>
93
+ <button onClick={() => engine.send_intent('help')}>Help</button>
94
+ </div>
95
+ );
96
+ }
97
+ ```
98
+
99
+ ## WASM Runtime Requirements
100
+
101
+ The kernel-dsl WASM binary requires a complete runtime environment. See [`WASM_SHIM_ARCHITECTURE.md`](./WASM_SHIM_ARCHITECTURE.md) for:
102
+ - Why a shim is necessary
103
+ - Complete list of 31 required functions
104
+ - How to extend implementations (time, random, environment)
105
+ - Post-build patching process
106
+
107
+ **Note**: Initialization is handled automatically by the `init()` function. No manual setup needed.
108
+
109
+ ## Architecture
110
+
111
+ ```
112
+ src/
113
+ ā”œā”€ā”€ lib.rs — Public WASM API (#[wasm_bindgen], no business logic)
114
+ ā”œā”€ā”€ effect.rs — Effect enum + MemValue (serialized return types for JS)
115
+ ā”œā”€ā”€ parser/
116
+ │ ā”œā”€ā”€ mod.rs — parse_behavior(text) → BehaviorFile via tree-sitter
117
+ │ └── ast.rs — AST types (BehaviorFile, StateDef, Statement, …) with serde
118
+ └── engine/
119
+ ā”œā”€ā”€ mod.rs — AgentDSLKernel: orchestrates parser + FSM + memory
120
+ ā”œā”€ā”€ fsm.rs — State execution, intent dispatch, conditionals, get_graph()
121
+ └── memory.rs — MemoryStore: 4 domains (context/session/worksession/user)
122
+
123
+ build.rs — Code generation: extracts node kinds from tree-sitter grammar
124
+ ```
125
+
126
+ The parser uses **tree-sitter** for robust parsing. The grammar is maintained in the [`dot-agent-tree-sitter`](https://github.com/daniloborges/dot-agent-tree-sitter) crate. `build.rs` automatically extracts node kinds from `tree-sitter/node-types.json` to keep parsing logic in sync with the grammar — when the grammar changes, simply update the tree-sitter crate version and rebuild.
127
+
128
+ ## Supported constructs
129
+
130
+ The parser and FSM cover the full `.agent DSL`:
131
+
132
+ | Construct | Example |
133
+ |-----------|---------|
134
+ | State | `state responsive` |
135
+ | Goal / Guide / Teach | `goal "text"` |
136
+ | Interact | `interact` |
137
+ | Inline intent | `on intent "planning" transition to planning` |
138
+ | Block intent | `on intent "search"` + indented block |
139
+ | Offtopic | `on offtopic` + block |
140
+ | Global event | `on event "session.ended"` + block |
141
+ | Memory assign | `set context.phase = "planning"` |
142
+ | Compound assign | `+=` / `-=` across all domains |
143
+ | Conditional | `if session.ready == true` + optional `else` |
144
+ | Transition | `transition to planning` |
145
+ | Run | `run script "file.js" silent` / `run subagent "agent.behavior" in background` |
146
+ | Temporal | `after 3 prompts guide "…"` |
147
+ | Parallel | `parallel` + block |
148
+ | UI | `apply css "…"` / `remove html "…"` |
149
+ | Merge | `merge "other.behavior"` (recorded in AST, resolved by external runtime) |
150
+ | Async completion | `on complete` / `on failed` + block |
151
+
152
+ ## Build
153
+
154
+ ```bash
155
+ rustup target add wasm32-unknown-unknown
156
+ cargo install wasm-pack
157
+ wasm-pack build --target bundler
158
+ ```
159
+
160
+ The generated `pkg/` directory is consumed via the package root:
161
+
162
+ ```bash
163
+ npm install @dot-agent/kernel-dsl
164
+ ```
165
+
166
+ ## API
167
+
168
+ All methods return a **JSON array of `Effect` objects**, letting JS react to flow actions without polling.
169
+
170
+ ```typescript
171
+ const engine = new AgentDSLKernel();
172
+
173
+ // Load a .behavior file and receive the entry effects of the first state
174
+ const effects = engine.load_behavior(behaviorText);
175
+ // → [{ type: "goal", text: "…" }, { type: "request_interact" }]
176
+
177
+ // Dispatch an intent (name classified by the LLM layer)
178
+ engine.send_intent("planning");
179
+
180
+ // Flow handlers
181
+ engine.send_offtopic();
182
+ engine.send_event("session.ended");
183
+
184
+ // Async operation completion
185
+ engine.send_complete();
186
+ engine.send_failed();
187
+
188
+ // Temporal triggers — call once per processed prompt
189
+ engine.tick_prompt();
190
+
191
+ // State reads
192
+ engine.get_current_state(); // string
193
+ engine.get_valid_intents(); // Array<string>
194
+
195
+ // Memory
196
+ engine.get_memory(); // [{ domain, key, value }]
197
+ engine.set_memory("session", "lang", '"pt"'); // value as JSON string
198
+
199
+ // State graph (for VS Code Flow Graph panel)
200
+ engine.get_graph();
201
+ // → { states: ["responsive", "planning"], transitions: [{from, to, label}], current: "responsive" }
202
+ ```
203
+
204
+ ### Effect types
205
+
206
+ ```typescript
207
+ type Effect =
208
+ | { type: "goal"; text: string }
209
+ | { type: "guide"; text: string }
210
+ | { type: "teach"; text: string }
211
+ | { type: "request_interact" }
212
+ | { type: "transition"; from: string; to: string }
213
+ | { type: "run_script"; target: string; label: string | null; silent: boolean }
214
+ | { type: "run_subagent"; target: string; label: string | null; background: boolean }
215
+ | { type: "run_tool"; target: string; label: string | null }
216
+ | { type: "set_memory"; domain: string; key: string; value: string | number | boolean | null }
217
+ | { type: "apply_css"; value: string }
218
+ | { type: "remove_css"; value: string }
219
+ | { type: "apply_html"; value: string }
220
+ | { type: "remove_html"; value: string }
221
+ | { type: "apply_video"; value: string }
222
+ | { type: "remove_video"; value: string }
223
+ | { type: "parse_error"; message: string }
224
+ ```
225
+
226
+ For the full API reference — all effect types, handler implementation examples, memory domains, TypeScript types, and a React hook — see [API.md](API.md).
227
+
228
+ ### Dynamic import (Next.js / SSR)
229
+
230
+ ```javascript
231
+ import("@dot-agent/kernel-dsl").then(module => {
232
+ const engine = new module.AgentDSLKernel();
233
+ const effects = engine.load_behavior(behaviorText);
234
+ console.log(effects);
235
+ });
236
+ ```
237
+
238
+ ---
239
+
240
+ ## License
241
+
242
+ Copyright (c) 2026 Danilo Borges (https://github.com/daniloborges)
243
+
244
+ Licensed under the **Apache License, Version 2.0** — see [`LICENSE`](LICENSE).
package/index.js ADDED
@@ -0,0 +1,111 @@
1
+ let _initialized = false;
2
+ let _module = null;
3
+
4
+ // Complete WASI + Rust runtime shim - 31 functions required
5
+ const wasiShim = {
6
+ // WASI file descriptor operations (5)
7
+ fd_write: () => 0,
8
+ fd_close: () => 0,
9
+ fd_seek: () => 0,
10
+ fd_prestat_get: () => 0,
11
+ fd_prestat_dir_name: () => 0,
12
+
13
+ // WASI environment (2)
14
+ environ_get: () => 0,
15
+ environ_sizes_get: () => 0,
16
+
17
+ // WASI time (1)
18
+ clock_time_get: () => 0,
19
+
20
+ // WASI misc (1)
21
+ random_get: () => 0,
22
+ proc_exit: () => 0,
23
+
24
+ // Rust UB Sanitizer handlers (11)
25
+ __ubsan_handle_type_mismatch_v1: () => 0,
26
+ __ubsan_handle_alignment_assumption: () => 0,
27
+ __ubsan_handle_out_of_bounds: () => 0,
28
+ __ubsan_handle_nonnull_arg: () => 0,
29
+ __ubsan_handle_load_invalid_value: () => 0,
30
+ __ubsan_handle_builtin_unreachable: () => 0,
31
+ __ubsan_handle_add_overflow: () => 0,
32
+ __ubsan_handle_sub_overflow: () => 0,
33
+ __ubsan_handle_mul_overflow: () => 0,
34
+ __ubsan_handle_divrem_overflow: () => 0,
35
+ __ubsan_handle_shift_out_of_bounds: () => 0,
36
+ __ubsan_handle_pointer_overflow: () => 0,
37
+
38
+ // wasm-bindgen JS interop (8)
39
+ __wbg_call_9c758de292015997: () => 0,
40
+ __wbg_new_d90091b82fdf5b91: () => 0,
41
+ __wbg_new_ce1ab61c1c2b300d: () => 0,
42
+ __wbg_push_a6822215aa43e71c: () => 0,
43
+ __wbg_set_6be42768c690e380: () => 0,
44
+ __wbg_set_dca99999bba88a9a: () => 0,
45
+ __wbg___wbindgen_throw_1506f2235d1bdba0: () => 0,
46
+
47
+ // wasm-bindgen internal (3)
48
+ __wbindgen_init_externref_table: () => 0,
49
+ __wbindgen_cast_0000000000000001: () => 0,
50
+ __wbindgen_cast_0000000000000002: () => 0,
51
+ };
52
+
53
+ export class AgentDSLKernel {
54
+ constructor() {
55
+ if (!_initialized) throw new Error('Must call init() first');
56
+ this._kernel = new _module.AgentDSLKernel();
57
+ }
58
+
59
+ get_current_state() { return this._kernel.get_current_state(); }
60
+ get_graph() { return this._kernel.get_graph(); }
61
+ get_memory() { return this._kernel.get_memory(); }
62
+ get_valid_intents() { return this._kernel.get_valid_intents(); }
63
+ load_behavior(text) { return this._kernel.load_behavior(text); }
64
+ observe(callback) { return this._kernel.observe(callback); }
65
+ send_complete() { return this._kernel.send_complete(); }
66
+ send_event(event) { return this._kernel.send_event(event); }
67
+ send_failed() { return this._kernel.send_failed(); }
68
+ send_fallback() { return this._kernel.send_fallback(); }
69
+ send_intent(intent) { return this._kernel.send_intent(intent); }
70
+ send_offtopic() { return this._kernel.send_offtopic(); }
71
+ tick_prompt() { return this._kernel.tick_prompt(); }
72
+ free() { return this._kernel.free(); }
73
+ }
74
+
75
+ export async function init() {
76
+ if (_initialized) return;
77
+
78
+ try {
79
+ const bgModule = await import('./pkg/dot_agent_kernel_dsl_bg.js');
80
+
81
+ // Load WASM buffer: fetch in browser, fs.readFile in Node.js
82
+ let wasmBuffer;
83
+ if (typeof window !== 'undefined') {
84
+ // Browser environment
85
+ const wasmPath = new URL('./pkg/dot_agent_kernel_dsl_bg.wasm', import.meta.url);
86
+ const wasmResponse = await fetch(wasmPath);
87
+ wasmBuffer = await wasmResponse.arrayBuffer();
88
+ } else {
89
+ // Node.js environment
90
+ const { readFile } = await import('node:fs/promises');
91
+ const { fileURLToPath } = await import('node:url');
92
+ const wasmPath = fileURLToPath(new URL('./pkg/dot_agent_kernel_dsl_bg.wasm', import.meta.url));
93
+ wasmBuffer = await readFile(wasmPath);
94
+ }
95
+
96
+ const importObject = {
97
+ env: wasiShim,
98
+ wasi_snapshot_preview1: wasiShim,
99
+ './dot_agent_kernel_dsl_bg.js': { ...bgModule }
100
+ };
101
+
102
+ const wasmModule = await WebAssembly.instantiate(wasmBuffer, importObject);
103
+ bgModule.__wbg_set_wasm(wasmModule.instance.exports);
104
+ _module = await import('./pkg/dot_agent_kernel_dsl.js');
105
+
106
+ _initialized = true;
107
+ } catch (err) {
108
+ console.error('Failed to initialize wasm:', err);
109
+ throw err;
110
+ }
111
+ }
package/package.json ADDED
@@ -0,0 +1,69 @@
1
+ {
2
+ "name": "@dot-agent/kernel-dsl",
3
+ "version": "0.1.0",
4
+ "description": "WASM kernel for parsing and executing the agent behavior DSL",
5
+ "type": "module",
6
+ "main": "./index.js",
7
+ "types": "./pkg/dot_agent_kernel_dsl.d.ts",
8
+ "license": "Apache-2.0",
9
+ "author": {
10
+ "name": "Danilo Borges",
11
+ "email": "contato@daniloborg.es",
12
+ "url": "https://daniloborg.es"
13
+ },
14
+ "contributors": [
15
+ {
16
+ "name": "Danilo Borges",
17
+ "email": "contato@daniloborg.es"
18
+ }
19
+ ],
20
+ "homepage": "https://github.com/dot-agent-spec/kernel-dsl",
21
+ "repository": {
22
+ "type": "git",
23
+ "url": "https://github.com/dot-agent-spec/kernel-dsl"
24
+ },
25
+ "bugs": {
26
+ "url": "https://github.com/dot-agent-spec/kernel-dsl/issues"
27
+ },
28
+ "keywords": [
29
+ "wasm",
30
+ "agent",
31
+ "dsl",
32
+ "behavior",
33
+ "fsm",
34
+ "state-machine",
35
+ "parser",
36
+ "webassembly"
37
+ ],
38
+ "files": [
39
+ "index.js",
40
+ "scripts/discover-wasm-imports.js",
41
+ "scripts/patch-wasm-bindgen.js",
42
+ "pkg/dot_agent_kernel_dsl.js",
43
+ "pkg/dot_agent_kernel_dsl.d.ts",
44
+ "pkg/dot_agent_kernel_dsl_bg.wasm",
45
+ "pkg/dot_agent_kernel_dsl_bg.wasm.d.ts",
46
+ "pkg/package.json"
47
+ ],
48
+ "exports": {
49
+ ".": {
50
+ "import": "./index.js",
51
+ "types": "./pkg/dot_agent_kernel_dsl.d.ts"
52
+ }
53
+ },
54
+ "engines": {
55
+ "node": ">=16.0.0"
56
+ },
57
+ "scripts": {
58
+ "build": "./scripts/build-wasm.sh && node scripts/patch-wasm-bindgen.js",
59
+ "build:release": "RELEASE=true ./scripts/build-wasm.sh && node scripts/patch-wasm-bindgen.js",
60
+ "patch": "node -e \"const fs=require('fs'),p=require('./pkg/package.json');p.name='@dot-agent/kernel-dsl';p.publishConfig={access:'public'};fs.writeFileSync('./pkg/package.json',JSON.stringify(p,null,2)+'\\n')\"",
61
+ "test:node": "node --test tests/node-compat.test.js",
62
+ "prepublishOnly": "npm run build:release && npm run patch"
63
+ },
64
+ "publishConfig": {
65
+ "access": "public"
66
+ },
67
+ "dependencies": {
68
+ }
69
+ }
@@ -0,0 +1,95 @@
1
+ /* tslint:disable */
2
+ /* eslint-disable */
3
+
4
+ export class AgentDSLKernel {
5
+ free(): void;
6
+ [Symbol.dispose](): void;
7
+ /**
8
+ * Return the name of the current state.
9
+ */
10
+ get_current_state(): string;
11
+ /**
12
+ * Return the state graph as { states, transitions, current }.
13
+ *
14
+ * Use this to render the Flow Graph panel in VS Code or any diagram tool.
15
+ */
16
+ get_graph(): any;
17
+ /**
18
+ * Return the full memory store as a JSON array of { domain, key, value } entries.
19
+ */
20
+ get_memory(): any;
21
+ /**
22
+ * Return an array of intent strings declared in the current state.
23
+ *
24
+ * Use this to build the list of valid intent names to pass to the LLM classifier.
25
+ */
26
+ get_valid_intents(): Array<any>;
27
+ /**
28
+ * Parse and load a .behavior DSL text.
29
+ *
30
+ * Fires the observer for each entry effect of the first state (typically goal +
31
+ * request_interact). Also returns the effects array for imperative call sites.
32
+ * On parse error, fires and returns a single ParseError effect.
33
+ */
34
+ load_behavior(text: string): any;
35
+ constructor();
36
+ /**
37
+ * Register a callback that WASM will call once per Effect as they are produced.
38
+ *
39
+ * This is the primary integration point — the equivalent of the importObject in a
40
+ * raw WebAssembly.instantiate call. The callback receives a single Effect object
41
+ * per invocation and must implement all WASM→JS directives (goal, guide, teach,
42
+ * run_script, run_subagent, run_tool, apply_css, …).
43
+ *
44
+ * Only one observer can be active at a time; calling observe() again replaces it.
45
+ */
46
+ observe(callback: Function): void;
47
+ /**
48
+ * Signal that the last async operation (run_script, run_subagent, run_tool) completed successfully.
49
+ *
50
+ * Fires the observer with the effects of the current state's `on complete` block.
51
+ */
52
+ send_complete(): any;
53
+ /**
54
+ * Signal that the runtime could not resolve the current action.
55
+ * Dispatch a named global event (e.g. "session.ended", "script.done").
56
+ *
57
+ * Matches top-level `on event "…"` declarations. Use this to notify the FSM
58
+ * when an async operation triggered by run_script / run_subagent / run_tool completes.
59
+ */
60
+ send_event(event: string): any;
61
+ /**
62
+ * Signal that the last async operation (run_script, run_subagent, run_tool) failed.
63
+ *
64
+ * Fires the observer with the effects of the current state's `on failed` block.
65
+ */
66
+ send_failed(): any;
67
+ /**
68
+ * Dispatch a named intent to the FSM.
69
+ *
70
+ * Call this after the LLM classifies the user's message into an intent name that
71
+ * matches one of the `on intent "…"` declarations in the current state.
72
+ * Fires the observer with transition + any entry effects of the new state.
73
+ */
74
+ send_intent(intent: string): any;
75
+ /**
76
+ * Signal that the current message is off-topic.
77
+ *
78
+ * Fires the observer with the effects of the current state's `on offtopic` block.
79
+ */
80
+ send_offtopic(): any;
81
+ /**
82
+ * Set a value in the memory store from JS.
83
+ *
84
+ * domain: "context" | "session" | "worksession" | "user"
85
+ * value_json: value serialized as a JSON primitive ("text", 42, true, null)
86
+ */
87
+ set_memory(domain: string, key: string, value_json: string): void;
88
+ /**
89
+ * Notify the engine that a prompt turn was processed.
90
+ *
91
+ * Call once per LLM completion. Triggers any matching `after N prompts` handlers
92
+ * in the current state, firing their effects through the observer.
93
+ */
94
+ tick_prompt(): any;
95
+ }
@@ -0,0 +1,6 @@
1
+ /* @ts-self-types"./dot_agent_kernel_dsl.d.ts" */
2
+ /* MODIFIED: WASM is loaded manually by index.js to avoid webpack parse errors */
3
+
4
+ export {
5
+ AgentDSLKernel
6
+ } from "./dot_agent_kernel_dsl_bg.js";
Binary file
@@ -0,0 +1,25 @@
1
+ /* tslint:disable */
2
+ /* eslint-disable */
3
+ export const memory: WebAssembly.Memory;
4
+ export const __wbg_agentdslkernel_free: (a: number, b: number) => void;
5
+ export const agentdslkernel_get_current_state: (a: number) => [number, number];
6
+ export const agentdslkernel_get_graph: (a: number) => any;
7
+ export const agentdslkernel_get_memory: (a: number) => any;
8
+ export const agentdslkernel_get_valid_intents: (a: number) => any;
9
+ export const agentdslkernel_load_behavior: (a: number, b: number, c: number) => any;
10
+ export const agentdslkernel_new: () => number;
11
+ export const agentdslkernel_observe: (a: number, b: any) => void;
12
+ export const agentdslkernel_send_complete: (a: number) => any;
13
+ export const agentdslkernel_send_event: (a: number, b: number, c: number) => any;
14
+ export const agentdslkernel_send_failed: (a: number) => any;
15
+ export const agentdslkernel_send_intent: (a: number, b: number, c: number) => any;
16
+ export const agentdslkernel_send_offtopic: (a: number) => any;
17
+ export const agentdslkernel_set_memory: (a: number, b: number, c: number, d: number, e: number, f: number, g: number) => void;
18
+ export const agentdslkernel_tick_prompt: (a: number) => any;
19
+ export const __wbindgen_exn_store_command_export: (a: number) => void;
20
+ export const __externref_table_alloc_command_export: () => number;
21
+ export const __wbindgen_externrefs: WebAssembly.Table;
22
+ export const __wbindgen_free_command_export: (a: number, b: number, c: number) => void;
23
+ export const __wbindgen_malloc_command_export: (a: number, b: number) => number;
24
+ export const __wbindgen_realloc_command_export: (a: number, b: number, c: number, d: number) => number;
25
+ export const __wbindgen_start: () => void;
package/pkg/index.js ADDED
@@ -0,0 +1,99 @@
1
+ let _initialized = false;
2
+ let _module = null;
3
+
4
+ // Complete WASI + Rust runtime shim - 31 functions required
5
+ const wasiShim = {
6
+ // WASI file descriptor operations (5)
7
+ fd_write: () => 0,
8
+ fd_close: () => 0,
9
+ fd_seek: () => 0,
10
+ fd_prestat_get: () => 0,
11
+ fd_prestat_dir_name: () => 0,
12
+
13
+ // WASI environment (2)
14
+ environ_get: () => 0,
15
+ environ_sizes_get: () => 0,
16
+
17
+ // WASI time (1)
18
+ clock_time_get: () => 0,
19
+
20
+ // WASI misc (1)
21
+ random_get: () => 0,
22
+ proc_exit: () => 0,
23
+
24
+ // Rust UB Sanitizer handlers (11)
25
+ __ubsan_handle_type_mismatch_v1: () => 0,
26
+ __ubsan_handle_alignment_assumption: () => 0,
27
+ __ubsan_handle_out_of_bounds: () => 0,
28
+ __ubsan_handle_nonnull_arg: () => 0,
29
+ __ubsan_handle_load_invalid_value: () => 0,
30
+ __ubsan_handle_builtin_unreachable: () => 0,
31
+ __ubsan_handle_add_overflow: () => 0,
32
+ __ubsan_handle_sub_overflow: () => 0,
33
+ __ubsan_handle_mul_overflow: () => 0,
34
+ __ubsan_handle_divrem_overflow: () => 0,
35
+ __ubsan_handle_shift_out_of_bounds: () => 0,
36
+ __ubsan_handle_pointer_overflow: () => 0,
37
+
38
+ // wasm-bindgen JS interop (8)
39
+ __wbg_call_9c758de292015997: () => 0,
40
+ __wbg_new_d90091b82fdf5b91: () => 0,
41
+ __wbg_new_ce1ab61c1c2b300d: () => 0,
42
+ __wbg_push_a6822215aa43e71c: () => 0,
43
+ __wbg_set_6be42768c690e380: () => 0,
44
+ __wbg_set_dca99999bba88a9a: () => 0,
45
+ __wbg___wbindgen_throw_1506f2235d1bdba0: () => 0,
46
+
47
+ // wasm-bindgen internal (3)
48
+ __wbindgen_init_externref_table: () => 0,
49
+ __wbindgen_cast_0000000000000001: () => 0,
50
+ __wbindgen_cast_0000000000000002: () => 0,
51
+ };
52
+
53
+ export class AgentDSLKernel {
54
+ constructor() {
55
+ if (!_initialized) throw new Error('Must call init() first');
56
+ this._kernel = new _module.AgentDSLKernel();
57
+ }
58
+
59
+ get_current_state() { return this._kernel.get_current_state(); }
60
+ get_graph() { return this._kernel.get_graph(); }
61
+ get_memory() { return this._kernel.get_memory(); }
62
+ get_valid_intents() { return this._kernel.get_valid_intents(); }
63
+ load_behavior(text) { return this._kernel.load_behavior(text); }
64
+ observe(callback) { return this._kernel.observe(callback); }
65
+ send_complete() { return this._kernel.send_complete(); }
66
+ send_event(event) { return this._kernel.send_event(event); }
67
+ send_failed() { return this._kernel.send_failed(); }
68
+ send_fallback() { return this._kernel.send_fallback(); }
69
+ send_intent(intent) { return this._kernel.send_intent(intent); }
70
+ send_offtopic() { return this._kernel.send_offtopic(); }
71
+ tick_prompt() { return this._kernel.tick_prompt(); }
72
+ free() { return this._kernel.free(); }
73
+ }
74
+
75
+ export async function init() {
76
+ if (_initialized) return;
77
+
78
+ try {
79
+ const bgModule = await import('./pkg/dot_agent_kernel_dsl_bg.js');
80
+ const wasmPath = new URL('./pkg/dot_agent_kernel_dsl_bg.wasm', import.meta.url);
81
+ const wasmResponse = await fetch(wasmPath);
82
+ const wasmBuffer = await wasmResponse.arrayBuffer();
83
+
84
+ const importObject = {
85
+ env: wasiShim,
86
+ wasi_snapshot_preview1: wasiShim,
87
+ './dot_agent_kernel_dsl_bg.js': { ...bgModule }
88
+ };
89
+
90
+ const wasmModule = await WebAssembly.instantiate(wasmBuffer, importObject);
91
+ bgModule.__wbg_set_wasm(wasmModule.instance.exports);
92
+ _module = await import('./pkg/dot_agent_kernel_dsl.js');
93
+
94
+ _initialized = true;
95
+ } catch (err) {
96
+ console.error('Failed to initialize wasm:', err);
97
+ throw err;
98
+ }
99
+ }
@@ -0,0 +1,10 @@
1
+ {
2
+ "name": "@dot-agent/kernel-dsl",
3
+ "version": "0.1.0",
4
+ "type": "module",
5
+ "main": "dot_agent_kernel_dsl.js",
6
+ "types": "dot_agent_kernel_dsl.d.ts",
7
+ "publishConfig": {
8
+ "access": "public"
9
+ }
10
+ }
@@ -0,0 +1,113 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * WASM Import Discovery Tool
4
+ *
5
+ * Discovers all functions required by the kernel-dsl WASM binary
6
+ * by attempting instantiation with a Proxy that tracks all accesses.
7
+ *
8
+ * Usage: node scripts/discover-wasm-imports.js
9
+ */
10
+
11
+ import fs from 'fs';
12
+ import path from 'path';
13
+ import { fileURLToPath } from 'url';
14
+
15
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
16
+
17
+ const accessedFunctions = new Set();
18
+ const functionCallCounts = new Map();
19
+
20
+ // Create proxy to track all accessed functions
21
+ const handler = {
22
+ get: (target, prop) => {
23
+ if (typeof prop === 'string') {
24
+ accessedFunctions.add(prop);
25
+ functionCallCounts.set(prop, (functionCallCounts.get(prop) || 0) + 1);
26
+ }
27
+ return (...args) => 0;
28
+ }
29
+ };
30
+
31
+ const wasiShimProxy = new Proxy({}, handler);
32
+
33
+ async function discoverImports() {
34
+ try {
35
+ const wasmPath = path.join(__dirname, '../pkg/dot_agent_kernel_dsl_bg.wasm');
36
+
37
+ if (!fs.existsSync(wasmPath)) {
38
+ console.error(`āŒ WASM file not found: ${wasmPath}`);
39
+ console.error('Run: npm run build');
40
+ process.exit(1);
41
+ }
42
+
43
+ const wasmBuffer = fs.readFileSync(wasmPath);
44
+
45
+ // Try to instantiate with proxy that captures all accesses
46
+ const importObject = {
47
+ env: wasiShimProxy,
48
+ wasi_snapshot_preview1: wasiShimProxy,
49
+ './dot_agent_kernel_dsl_bg.js': wasiShimProxy
50
+ };
51
+
52
+ try {
53
+ await WebAssembly.instantiate(wasmBuffer, importObject);
54
+ } catch (e) {
55
+ // Expected to fail, but we've captured the function accesses
56
+ console.log('ā„¹ļø WASM instantiation attempt complete (may have failed, but functions were captured)');
57
+ }
58
+
59
+ } catch (err) {
60
+ console.error('Error during discovery:', err.message);
61
+ process.exit(1);
62
+ }
63
+
64
+ // Report findings
65
+ console.log('\nšŸ“Š DISCOVERED FUNCTIONS:\n');
66
+
67
+ const sorted = Array.from(accessedFunctions).sort();
68
+
69
+ console.log(`Total unique functions accessed: ${sorted.length}\n`);
70
+
71
+ // Group by category
72
+ const groups = {
73
+ 'WASI (fd_*)': [],
74
+ 'WASI (environ_*)': [],
75
+ 'WASI (args_*)': [],
76
+ 'WASI (clock/sched)': [],
77
+ 'UBSAN (__ubsan_*)': [],
78
+ 'wasm-bindgen (__wbg_*)': [],
79
+ 'wasm-bindgen internal (__wbindgen_*)': [],
80
+ 'Other': []
81
+ };
82
+
83
+ sorted.forEach(fn => {
84
+ if (fn.startsWith('fd_')) groups['WASI (fd_*)'].push(fn);
85
+ else if (fn.startsWith('environ_')) groups['WASI (environ_*)'].push(fn);
86
+ else if (fn.startsWith('args_')) groups['WASI (args_*)'].push(fn);
87
+ else if (fn.match(/^(clock|sched)/)) groups['WASI (clock/sched)'].push(fn);
88
+ else if (fn.startsWith('__ubsan_')) groups['UBSAN (__ubsan_*)'].push(fn);
89
+ else if (fn.startsWith('__wbg_') && !fn.startsWith('__wbindgen_')) groups['wasm-bindgen (__wbg_*)'].push(fn);
90
+ else if (fn.startsWith('__wbindgen_')) groups['wasm-bindgen internal (__wbindgen_*)'].push(fn);
91
+ else groups['Other'].push(fn);
92
+ });
93
+
94
+ Object.entries(groups).forEach(([category, fns]) => {
95
+ if (fns.length > 0) {
96
+ console.log(`\n${category}:`);
97
+ fns.forEach(fn => {
98
+ const count = functionCallCounts.get(fn);
99
+ console.log(` ${fn}: ${count} ${count === 1 ? 'call' : 'calls'}`);
100
+ });
101
+ }
102
+ });
103
+
104
+ // Generate JavaScript code
105
+ console.log('\n\nšŸ“ GENERATED CODE FOR SHIM:\n');
106
+ console.log('const wasiShim = {');
107
+ sorted.forEach(fn => {
108
+ console.log(` ${fn}: () => 0,`);
109
+ });
110
+ console.log('};');
111
+ }
112
+
113
+ discoverImports();
@@ -0,0 +1,45 @@
1
+ #!/usr/bin/env node
2
+ import fs from 'fs';
3
+ import path from 'path';
4
+ import { fileURLToPath } from 'url';
5
+
6
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
7
+ const filePath = path.join(__dirname, '../pkg/dot_agent_kernel_dsl.js');
8
+
9
+ console.log('šŸ“ Patching WASM-bindgen output...');
10
+
11
+ if (!fs.existsSync(filePath)) {
12
+ console.warn(`āš ļø File not found: ${filePath}`);
13
+ process.exit(0);
14
+ }
15
+
16
+ let content = fs.readFileSync(filePath, 'utf-8');
17
+
18
+ // Check if already patched
19
+ if (content.includes('MODIFIED: WASM is loaded manually')) {
20
+ console.log('āœ… Already patched');
21
+ process.exit(0);
22
+ }
23
+
24
+ // Remove the problematic import lines that cause webpack parse errors
25
+ content = content
26
+ .replace(/import \* as wasm from ["']\.\/dot_agent_kernel_dsl_bg\.wasm["'];?\n/g, '')
27
+ .replace(/import { __wbg_set_wasm } from ["']\.\/dot_agent_kernel_dsl_bg\.js["'];?\n/g, '')
28
+ .replace(/^__wbg_set_wasm\(wasm\);\n/m, '')
29
+ .replace(/^wasm\.__wbindgen_start\(\);\n/m, '');
30
+
31
+ // Add comment explaining the change
32
+ if (!content.includes('MODIFIED:')) {
33
+ content = content.replace(
34
+ /\/\* @ts-self-types=/,
35
+ '/* @ts-self-types'
36
+ );
37
+ const tsLine = content.match(/\/\* @ts-self-types[^\n]*\n/)[0];
38
+ content = content.replace(
39
+ tsLine,
40
+ tsLine + '/* MODIFIED: WASM is loaded manually by index.js to avoid webpack parse errors */\n'
41
+ );
42
+ }
43
+
44
+ fs.writeFileSync(filePath, content, 'utf-8');
45
+ console.log('āœ… Patched successfully');