@snrraptopack/auwgent-sdk 0.1.0-alpha.1

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/Cargo.toml ADDED
@@ -0,0 +1,18 @@
1
+ [package]
2
+ name = "auwgent-napi"
3
+ version = "0.1.0"
4
+ edition = "2024"
5
+
6
+ [lib]
7
+ crate-type = ["cdylib"]
8
+
9
+ [dependencies]
10
+ ir-runtime = { path = "../../ir-runtime" }
11
+ napi = { version = "2", features = ["async", "napi8", "serde-json"] }
12
+ napi-derive = "2"
13
+ tokio = { version = "1.43", features = ["full"] }
14
+ serde_json = "1.0"
15
+ futures-util = "0.3"
16
+
17
+ [build-dependencies]
18
+ napi-build = "2"
@@ -0,0 +1,264 @@
1
+ /**
2
+ * Integration test for the Auwgent napi-rs FFI bridge.
3
+ *
4
+ * Tests:
5
+ * 1. Native binding loads correctly
6
+ * 2. IR parsing works
7
+ * 3. Tool registration works
8
+ * 4. Type-safe wrapper enforces tool completeness
9
+ * 5. Prompt generation works
10
+ * 6. Session export/import round-trips
11
+ * 7. onIntent callback works
12
+ */
13
+ import { describe, it, expect } from 'bun:test';
14
+ import { Auwgent } from '../index.js'; // Native binding
15
+ import { createAuwgent, parseIR, type AgentIRShape } from '../auwgent.js';
16
+
17
+ // ── Minimal IR for testing ───────────────────────────────────────────────
18
+ const TEST_IR = {
19
+ name: 'test-agent',
20
+ modelConfig: [
21
+ {
22
+ defaultConfig: {
23
+ model: { type: 'gemini', modelName: 'gemini-2.0-flash', config: null },
24
+ prompt: { type: 'literal', value: 'You are a test agent.' },
25
+ },
26
+ namedConfig: null,
27
+ },
28
+ ],
29
+ input: null,
30
+ output: {
31
+ type: 'object',
32
+ properties: {
33
+ response: { type: 'string', description: 'Agent response' },
34
+ },
35
+ },
36
+ context: null,
37
+ tools: [
38
+ {
39
+ name: 'greet',
40
+ description: 'Greet a user by name',
41
+ params: {
42
+ type: 'object',
43
+ properties: {
44
+ name: { type: 'string', description: 'Name to greet' },
45
+ },
46
+ },
47
+ returns: {
48
+ type: 'object',
49
+ properties: {
50
+ message: { type: 'string' },
51
+ },
52
+ },
53
+ },
54
+ {
55
+ name: 'search',
56
+ description: 'Search for something',
57
+ params: {
58
+ type: 'object',
59
+ properties: {
60
+ query: { type: 'string', description: 'Search query' },
61
+ },
62
+ },
63
+ returns: {
64
+ type: 'object',
65
+ properties: {
66
+ results: { type: 'array', items: { type: 'string' } },
67
+ },
68
+ },
69
+ },
70
+ ],
71
+ workflows: [],
72
+ helpers: [],
73
+ tests: [],
74
+ } as const;
75
+
76
+ const IR_JSON = JSON.stringify(TEST_IR);
77
+
78
+ // ═══════════════════════════════════════════════════════════════════════════
79
+ // NATIVE BINDING TESTS
80
+ // ═══════════════════════════════════════════════════════════════════════════
81
+
82
+ describe('Native Auwgent', () => {
83
+ it('loads the native binding', () => {
84
+ expect(Auwgent).toBeDefined();
85
+ expect(typeof Auwgent).toBe('function');
86
+ });
87
+
88
+ it('creates an engine from IR JSON', () => {
89
+ const agent = new Auwgent(IR_JSON);
90
+ expect(agent).toBeDefined();
91
+ });
92
+
93
+ it('rejects invalid IR JSON', () => {
94
+ expect(() => new Auwgent('not json')).toThrow();
95
+ });
96
+
97
+ it('returns tool names from IR', () => {
98
+ const agent = new Auwgent(IR_JSON);
99
+ const names = agent.getToolNames();
100
+ expect(names).toEqual(['greet', 'search']);
101
+ });
102
+
103
+ it('returns tool schemas', () => {
104
+ const agent = new Auwgent(IR_JSON);
105
+ const schemas = JSON.parse(agent.getToolSchemas());
106
+ expect(schemas).toHaveLength(2);
107
+ expect(schemas[0].name).toBe('greet');
108
+ expect(schemas[1].name).toBe('search');
109
+ expect(schemas[0].params.properties.name.type).toBe('string');
110
+ });
111
+
112
+ it('registers a tool callback', () => {
113
+ const agent = new Auwgent(IR_JSON);
114
+ agent.registerTool('greet', async (args: any) => {
115
+ return { message: `Hello, ${args.name}!` };
116
+ });
117
+ // No error means success
118
+ });
119
+
120
+ it('generates a prompt', () => {
121
+ const agent = new Auwgent(IR_JSON);
122
+ const prompt = agent.generatePrompt();
123
+ expect(prompt).toContain('You are a test agent');
124
+ });
125
+
126
+ it('exports and imports session state', () => {
127
+ const agent = new Auwgent(IR_JSON);
128
+ const exported = agent.exportSession();
129
+ const state = JSON.parse(exported);
130
+ expect(state).toBeDefined();
131
+ expect(state.turns).toBeDefined();
132
+
133
+ // Round-trip
134
+ agent.importSession(exported);
135
+ const exported2 = agent.exportSession();
136
+ expect(JSON.parse(exported2)).toEqual(state);
137
+ });
138
+
139
+ it('clears session', () => {
140
+ const agent = new Auwgent(IR_JSON);
141
+ agent.clearSession();
142
+ const state = JSON.parse(agent.exportSession());
143
+ expect(state.turns).toEqual([]);
144
+ });
145
+
146
+ it('registers an onIntent callback', () => {
147
+ const agent = new Auwgent(IR_JSON);
148
+ agent.onIntent((name: string, value: any) => {
149
+ // Just observe
150
+ console.log(`[${name}]`, value);
151
+ });
152
+ // No error means success
153
+ });
154
+ });
155
+
156
+ // ═══════════════════════════════════════════════════════════════════════════
157
+ // TYPE-SAFE WRAPPER TESTS
158
+ // ═══════════════════════════════════════════════════════════════════════════
159
+
160
+ describe('TypedAuwgent', () => {
161
+ it('creates a typed agent with all tools', () => {
162
+ const agent = createAuwgent(TEST_IR, {
163
+ tools: {
164
+ greet: async (args) => ({ message: `Hello, ${args.name}!` }),
165
+ search: async (args) => ({ results: [`Result for ${args.query}`] }),
166
+ },
167
+ });
168
+ expect(agent).toBeDefined();
169
+ });
170
+
171
+ it('returns typed tool names', () => {
172
+ const agent = createAuwgent(TEST_IR, {
173
+ tools: {
174
+ greet: async () => ({ message: 'hi' }),
175
+ search: async () => ({ results: [] }),
176
+ },
177
+ });
178
+ const names = agent.getToolNames();
179
+ expect(names).toContain('greet');
180
+ expect(names).toContain('search');
181
+ });
182
+
183
+ it('generates prompt through wrapper', () => {
184
+ const agent = createAuwgent(TEST_IR, {
185
+ tools: {
186
+ greet: async () => ({ message: 'hi' }),
187
+ search: async () => ({ results: [] }),
188
+ },
189
+ });
190
+ const prompt = agent.generatePrompt();
191
+ expect(typeof prompt).toBe('string');
192
+ expect(prompt.length).toBeGreaterThan(0);
193
+ });
194
+
195
+ it('exports typed session without steps', () => {
196
+ const agent = createAuwgent(TEST_IR, {
197
+ tools: {
198
+ greet: async () => ({ message: 'hi' }),
199
+ search: async () => ({ results: [] }),
200
+ },
201
+ });
202
+ const session = agent.exportSession();
203
+ expect(session.turns).toBeDefined();
204
+ expect(Array.isArray(session.turns)).toBe(true);
205
+ // Steps should NOT exist anymore
206
+ expect((session as any).steps).toBeUndefined();
207
+ });
208
+
209
+ it('round-trips session through wrapper', () => {
210
+ const agent = createAuwgent(TEST_IR, {
211
+ tools: {
212
+ greet: async () => ({ message: 'hi' }),
213
+ search: async () => ({ results: [] }),
214
+ },
215
+ });
216
+ const session = agent.exportSession();
217
+ agent.importSession(session);
218
+ const after = agent.exportSession();
219
+ expect(after).toEqual(session);
220
+ });
221
+
222
+ it('registers onIntent through wrapper', () => {
223
+ const agent = createAuwgent(TEST_IR, {
224
+ tools: {
225
+ greet: async () => ({ message: 'hi' }),
226
+ search: async () => ({ results: [] }),
227
+ },
228
+ });
229
+
230
+ const events: Array<{ name: string; value: unknown }> = [];
231
+ agent.onIntent((name, value) => {
232
+ events.push({ name, value });
233
+ });
234
+ // onIntent registered successfully — events will fire during run()
235
+ expect(events).toEqual([]);
236
+ });
237
+
238
+ it('parseIR returns typed IR', () => {
239
+ const ir = parseIR(IR_JSON);
240
+ expect(ir.name).toBe('test-agent');
241
+ expect(ir.tools).toHaveLength(2);
242
+ });
243
+ });
244
+
245
+ // ═══════════════════════════════════════════════════════════════════════════
246
+ // TYPE SAFETY COMPILE-TIME CHECKS (these are TS-only, not runtime)
247
+ // ═══════════════════════════════════════════════════════════════════════════
248
+
249
+ describe('Type safety (compile-time)', () => {
250
+ it('TypeScript would error if a tool is missing (documented)', () => {
251
+ // This test documents the type safety behavior.
252
+ // If you uncomment the following, TypeScript WILL error:
253
+ //
254
+ // createAuwgent(TEST_IR, {
255
+ // tools: {
256
+ // greet: async () => ({ message: 'hi' }),
257
+ // // search is MISSING — TS error: Property 'search' is missing
258
+ // },
259
+ // });
260
+ //
261
+ // This proves that ToolRegistry<IR> enforces completeness.
262
+ expect(true).toBe(true);
263
+ });
264
+ });
Binary file