@dot-ai/core 0.9.0 → 0.11.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/dist/boot-cache.d.ts +1 -1
- package/dist/boot-cache.d.ts.map +1 -1
- package/dist/extension-api.d.ts +10 -9
- package/dist/extension-api.d.ts.map +1 -1
- package/dist/extension-loader.d.ts +9 -2
- package/dist/extension-loader.d.ts.map +1 -1
- package/dist/extension-loader.js +179 -55
- package/dist/extension-loader.js.map +1 -1
- package/dist/extension-runner.d.ts +9 -4
- package/dist/extension-runner.d.ts.map +1 -1
- package/dist/extension-runner.js +34 -13
- package/dist/extension-runner.js.map +1 -1
- package/dist/extension-types.d.ts +15 -115
- package/dist/extension-types.d.ts.map +1 -1
- package/dist/extension-types.js +1 -88
- package/dist/extension-types.js.map +1 -1
- package/dist/format.d.ts +21 -0
- package/dist/format.d.ts.map +1 -1
- package/dist/format.js +74 -0
- package/dist/format.js.map +1 -1
- package/dist/index.d.ts +6 -7
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -4
- package/dist/index.js.map +1 -1
- package/dist/package-manager.d.ts +28 -5
- package/dist/package-manager.d.ts.map +1 -1
- package/dist/package-manager.js +126 -20
- package/dist/package-manager.js.map +1 -1
- package/dist/runtime.d.ts +31 -43
- package/dist/runtime.d.ts.map +1 -1
- package/dist/runtime.js +79 -177
- package/dist/runtime.js.map +1 -1
- package/package.json +1 -1
- package/src/__tests__/extension-loader.test.ts +154 -11
- package/src/__tests__/extension-runner.test.ts +245 -32
- package/src/__tests__/fixtures/extensions/ctx-aware.js +12 -3
- package/src/__tests__/fixtures/extensions/smart-context.js +12 -3
- package/src/__tests__/format.test.ts +178 -1
- package/src/__tests__/package-manager.test.ts +237 -0
- package/src/__tests__/runtime.test.ts +38 -10
- package/src/boot-cache.ts +1 -1
- package/src/extension-api.ts +10 -15
- package/src/extension-loader.ts +187 -57
- package/src/extension-runner.ts +44 -15
- package/src/extension-types.ts +26 -195
- package/src/format.ts +100 -0
- package/src/index.ts +5 -13
- package/src/package-manager.ts +146 -23
- package/src/runtime.ts +96 -222
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
|
|
2
|
+
import { mkdir, writeFile, rm, readFile } from 'node:fs/promises';
|
|
3
|
+
import { join } from 'node:path';
|
|
4
|
+
import { tmpdir } from 'node:os';
|
|
5
|
+
import {
|
|
6
|
+
listPackages,
|
|
7
|
+
resolvePackages,
|
|
8
|
+
ensurePackagesInstalled,
|
|
9
|
+
} from '../package-manager.js';
|
|
10
|
+
|
|
11
|
+
// Use temp directory for test fixtures
|
|
12
|
+
const testDir = join(tmpdir(), 'dot-ai-pkg-test-' + Date.now());
|
|
13
|
+
|
|
14
|
+
beforeEach(async () => {
|
|
15
|
+
await mkdir(join(testDir, '.ai', 'packages'), { recursive: true });
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
afterEach(async () => {
|
|
19
|
+
await rm(testDir, { recursive: true, force: true });
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
// ── Helper: create a fake installed package ─────────────────────────────────
|
|
23
|
+
async function createFakePackage(
|
|
24
|
+
name: string,
|
|
25
|
+
version: string,
|
|
26
|
+
dotAi?: { extensions?: string[] },
|
|
27
|
+
) {
|
|
28
|
+
const installDir = join(testDir, '.ai', 'packages');
|
|
29
|
+
const pkgDir = join(installDir, 'node_modules', name);
|
|
30
|
+
await mkdir(pkgDir, { recursive: true });
|
|
31
|
+
|
|
32
|
+
// Write package.json for installed package
|
|
33
|
+
const pkgJson: Record<string, unknown> = { name, version };
|
|
34
|
+
if (dotAi) pkgJson['dot-ai'] = dotAi;
|
|
35
|
+
await writeFile(join(pkgDir, 'package.json'), JSON.stringify(pkgJson));
|
|
36
|
+
|
|
37
|
+
// Create extension files if declared
|
|
38
|
+
if (dotAi?.extensions) {
|
|
39
|
+
for (const ext of dotAi.extensions) {
|
|
40
|
+
const extPath = join(pkgDir, ext);
|
|
41
|
+
await mkdir(join(extPath, '..'), { recursive: true });
|
|
42
|
+
await writeFile(extPath, 'export default function() {}');
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// Update the packages/package.json dependencies
|
|
47
|
+
const depsPkgPath = join(installDir, 'package.json');
|
|
48
|
+
let deps: Record<string, string> = {};
|
|
49
|
+
try {
|
|
50
|
+
const raw = await readFile(depsPkgPath, 'utf-8');
|
|
51
|
+
const existing = JSON.parse(raw);
|
|
52
|
+
deps = existing.dependencies ?? {};
|
|
53
|
+
} catch { /* no file yet */ }
|
|
54
|
+
|
|
55
|
+
deps[name] = version;
|
|
56
|
+
await writeFile(depsPkgPath, JSON.stringify({ dependencies: deps }));
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
describe('listPackages', () => {
|
|
60
|
+
it('returns empty array when no packages installed', async () => {
|
|
61
|
+
const result = await listPackages(testDir);
|
|
62
|
+
expect(result).toEqual([]);
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
it('lists installed packages with dot-ai field', async () => {
|
|
66
|
+
await createFakePackage('@dot-ai/ext-memory', '1.0.0', {
|
|
67
|
+
extensions: ['./dist/extension.js'],
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
const result = await listPackages(testDir);
|
|
71
|
+
expect(result).toHaveLength(1);
|
|
72
|
+
expect(result[0].name).toBe('@dot-ai/ext-memory');
|
|
73
|
+
expect(result[0].version).toBe('1.0.0');
|
|
74
|
+
expect(result[0].dotAi?.extensions).toEqual(['./dist/extension.js']);
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
it('lists packages without dot-ai field', async () => {
|
|
78
|
+
await createFakePackage('some-lib', '2.0.0');
|
|
79
|
+
|
|
80
|
+
const result = await listPackages(testDir);
|
|
81
|
+
expect(result).toHaveLength(1);
|
|
82
|
+
expect(result[0].name).toBe('some-lib');
|
|
83
|
+
expect(result[0].dotAi).toBeUndefined();
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
it('lists multiple packages', async () => {
|
|
87
|
+
await createFakePackage('@dot-ai/ext-memory', '1.0.0', {
|
|
88
|
+
extensions: ['./dist/extension.js'],
|
|
89
|
+
});
|
|
90
|
+
await createFakePackage('@dot-ai/ext-identity', '1.0.0', {
|
|
91
|
+
extensions: ['./dist/index.js'],
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
const result = await listPackages(testDir);
|
|
95
|
+
expect(result).toHaveLength(2);
|
|
96
|
+
});
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
describe('resolvePackages', () => {
|
|
100
|
+
it('returns empty when no packages', async () => {
|
|
101
|
+
const result = await resolvePackages(testDir);
|
|
102
|
+
expect(result.extensions).toEqual([]);
|
|
103
|
+
expect(result.skills).toEqual([]);
|
|
104
|
+
expect(result.providers).toEqual([]);
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
it('resolves extension paths from packages with dot-ai field', async () => {
|
|
108
|
+
await createFakePackage('@dot-ai/ext-memory', '1.0.0', {
|
|
109
|
+
extensions: ['./dist/extension.js'],
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
const result = await resolvePackages(testDir);
|
|
113
|
+
expect(result.extensions).toHaveLength(1);
|
|
114
|
+
expect(result.extensions[0]).toContain('ext-memory');
|
|
115
|
+
expect(result.extensions[0]).toContain('dist/extension.js');
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
it('skips packages without dot-ai field', async () => {
|
|
119
|
+
await createFakePackage('some-lib', '2.0.0');
|
|
120
|
+
|
|
121
|
+
const result = await resolvePackages(testDir);
|
|
122
|
+
expect(result.extensions).toHaveLength(0);
|
|
123
|
+
});
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
describe('ensurePackagesInstalled', () => {
|
|
127
|
+
it('skips already installed packages', async () => {
|
|
128
|
+
await createFakePackage('@dot-ai/ext-memory', '1.0.0', {
|
|
129
|
+
extensions: ['./dist/extension.js'],
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
const result = await ensurePackagesInstalled(
|
|
133
|
+
testDir,
|
|
134
|
+
['@dot-ai/ext-memory'],
|
|
135
|
+
);
|
|
136
|
+
|
|
137
|
+
expect(result.skipped).toContain('@dot-ai/ext-memory');
|
|
138
|
+
expect(result.installed).toHaveLength(0);
|
|
139
|
+
expect(result.errors).toHaveLength(0);
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
it('skips packages when onMissing returns skip', async () => {
|
|
143
|
+
const result = await ensurePackagesInstalled(
|
|
144
|
+
testDir,
|
|
145
|
+
['@dot-ai/ext-not-there'],
|
|
146
|
+
async () => 'skip',
|
|
147
|
+
);
|
|
148
|
+
|
|
149
|
+
expect(result.skipped).toContain('@dot-ai/ext-not-there');
|
|
150
|
+
expect(result.installed).toHaveLength(0);
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
it('errors when onMissing returns error', async () => {
|
|
154
|
+
const result = await ensurePackagesInstalled(
|
|
155
|
+
testDir,
|
|
156
|
+
['@dot-ai/ext-not-there'],
|
|
157
|
+
async () => 'error',
|
|
158
|
+
);
|
|
159
|
+
|
|
160
|
+
expect(result.errors).toHaveLength(1);
|
|
161
|
+
expect(result.errors[0].source).toBe('@dot-ai/ext-not-there');
|
|
162
|
+
expect(result.errors[0].error).toContain('Missing package');
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
it('reports errors for failed installs', async () => {
|
|
166
|
+
// Use an impossible package name that npm will fail to find
|
|
167
|
+
const result = await ensurePackagesInstalled(
|
|
168
|
+
testDir,
|
|
169
|
+
['@dot-ai-fake-nonexistent-pkg-xyz/no-exist'],
|
|
170
|
+
);
|
|
171
|
+
|
|
172
|
+
expect(result.errors).toHaveLength(1);
|
|
173
|
+
expect(result.errors[0].source).toBe('@dot-ai-fake-nonexistent-pkg-xyz/no-exist');
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
it('handles npm: prefix in source', async () => {
|
|
177
|
+
await createFakePackage('@dot-ai/ext-memory', '1.0.0', {
|
|
178
|
+
extensions: ['./dist/extension.js'],
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
const result = await ensurePackagesInstalled(
|
|
182
|
+
testDir,
|
|
183
|
+
['npm:@dot-ai/ext-memory@1.0.0'],
|
|
184
|
+
);
|
|
185
|
+
|
|
186
|
+
// npm:@dot-ai/ext-memory@1.0.0 → name = @dot-ai/ext-memory → already installed
|
|
187
|
+
expect(result.skipped).toContain('npm:@dot-ai/ext-memory@1.0.0');
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
it('handles multiple packages', async () => {
|
|
191
|
+
await createFakePackage('@dot-ai/ext-memory', '1.0.0', {
|
|
192
|
+
extensions: ['./dist/extension.js'],
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
const result = await ensurePackagesInstalled(
|
|
196
|
+
testDir,
|
|
197
|
+
['@dot-ai/ext-memory', '@dot-ai/ext-not-there'],
|
|
198
|
+
async (source) => source.includes('not-there') ? 'skip' : 'install',
|
|
199
|
+
);
|
|
200
|
+
|
|
201
|
+
expect(result.skipped).toContain('@dot-ai/ext-memory');
|
|
202
|
+
expect(result.skipped).toContain('@dot-ai/ext-not-there');
|
|
203
|
+
});
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
describe('parsePackageSource (via ensurePackagesInstalled)', () => {
|
|
207
|
+
// We test parsePackageSource indirectly through ensurePackagesInstalled
|
|
208
|
+
|
|
209
|
+
it('handles scoped package with version', async () => {
|
|
210
|
+
await createFakePackage('@dot-ai/ext-memory', '1.0.0');
|
|
211
|
+
|
|
212
|
+
const result = await ensurePackagesInstalled(testDir, ['@dot-ai/ext-memory@1.0.0']);
|
|
213
|
+
// Should find it as already installed (strips version to get name)
|
|
214
|
+
expect(result.skipped).toContain('@dot-ai/ext-memory@1.0.0');
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
it('handles scoped package without version', async () => {
|
|
218
|
+
await createFakePackage('@dot-ai/ext-memory', '1.0.0');
|
|
219
|
+
|
|
220
|
+
const result = await ensurePackagesInstalled(testDir, ['@dot-ai/ext-memory']);
|
|
221
|
+
expect(result.skipped).toContain('@dot-ai/ext-memory');
|
|
222
|
+
});
|
|
223
|
+
|
|
224
|
+
it('handles unscoped package with version', async () => {
|
|
225
|
+
await createFakePackage('my-ext', '2.0.0');
|
|
226
|
+
|
|
227
|
+
const result = await ensurePackagesInstalled(testDir, ['my-ext@2.0.0']);
|
|
228
|
+
expect(result.skipped).toContain('my-ext@2.0.0');
|
|
229
|
+
});
|
|
230
|
+
|
|
231
|
+
it('handles npm: prefix with scoped package', async () => {
|
|
232
|
+
await createFakePackage('@dot-ai/ext-memory', '1.0.0');
|
|
233
|
+
|
|
234
|
+
const result = await ensurePackagesInstalled(testDir, ['npm:@dot-ai/ext-memory']);
|
|
235
|
+
expect(result.skipped).toContain('npm:@dot-ai/ext-memory');
|
|
236
|
+
});
|
|
237
|
+
});
|
|
@@ -26,23 +26,24 @@ describe('DotAiRuntime', () => {
|
|
|
26
26
|
});
|
|
27
27
|
|
|
28
28
|
describe('processPrompt', () => {
|
|
29
|
-
it('returns sections, labels,
|
|
29
|
+
it('returns sections, labels, routing', async () => {
|
|
30
30
|
const runtime = new DotAiRuntime({ workspaceRoot: '/tmp/nonexistent' });
|
|
31
31
|
await runtime.boot();
|
|
32
32
|
const result = await runtime.processPrompt('hello world');
|
|
33
|
-
expect(result.formatted).toBeDefined();
|
|
34
|
-
expect(result.enriched).toBeDefined();
|
|
35
|
-
expect(result.capabilities).toBeDefined();
|
|
36
33
|
expect(result.labels).toBeDefined();
|
|
37
34
|
expect(result.sections).toBeDefined();
|
|
35
|
+
expect(Array.isArray(result.sections)).toBe(true);
|
|
36
|
+
expect(result.routing).toBeDefined();
|
|
38
37
|
});
|
|
39
|
-
});
|
|
40
38
|
|
|
41
|
-
|
|
42
|
-
it('fires agent_end without throwing', async () => {
|
|
39
|
+
it('includes core system section', async () => {
|
|
43
40
|
const runtime = new DotAiRuntime({ workspaceRoot: '/tmp/nonexistent' });
|
|
44
41
|
await runtime.boot();
|
|
45
|
-
await runtime.
|
|
42
|
+
const result = await runtime.processPrompt('hello');
|
|
43
|
+
const systemSection = result.sections.find(s => s.id === 'dot-ai:system');
|
|
44
|
+
expect(systemSection).toBeDefined();
|
|
45
|
+
expect(systemSection!.priority).toBe(95);
|
|
46
|
+
expect(systemSection!.source).toBe('core');
|
|
46
47
|
});
|
|
47
48
|
});
|
|
48
49
|
|
|
@@ -74,6 +75,19 @@ describe('DotAiRuntime', () => {
|
|
|
74
75
|
});
|
|
75
76
|
});
|
|
76
77
|
|
|
78
|
+
describe('executeTool', () => {
|
|
79
|
+
it('throws when not booted', async () => {
|
|
80
|
+
const runtime = new DotAiRuntime({ workspaceRoot: '/tmp/nonexistent' });
|
|
81
|
+
await expect(runtime.executeTool('test', {})).rejects.toThrow('Runtime not booted');
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
it('throws for unknown tool', async () => {
|
|
85
|
+
const runtime = new DotAiRuntime({ workspaceRoot: '/tmp/nonexistent' });
|
|
86
|
+
await runtime.boot();
|
|
87
|
+
await expect(runtime.executeTool('nonexistent', {})).rejects.toThrow('Tool not found');
|
|
88
|
+
});
|
|
89
|
+
});
|
|
90
|
+
|
|
77
91
|
describe('shutdown', () => {
|
|
78
92
|
it('fires session_end and flushes', async () => {
|
|
79
93
|
const flushFn = vi.fn().mockResolvedValue(undefined);
|
|
@@ -122,12 +136,26 @@ describe('DotAiRuntime', () => {
|
|
|
122
136
|
expect(runtime.commands).toEqual([]);
|
|
123
137
|
});
|
|
124
138
|
|
|
125
|
-
it('
|
|
139
|
+
it('skills returns empty array when no extensions', async () => {
|
|
140
|
+
const runtime = new DotAiRuntime({ workspaceRoot: '/tmp/nonexistent' });
|
|
141
|
+
await runtime.boot();
|
|
142
|
+
expect(runtime.skills).toEqual([]);
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
it('identities returns empty array when no extensions', async () => {
|
|
146
|
+
const runtime = new DotAiRuntime({ workspaceRoot: '/tmp/nonexistent' });
|
|
147
|
+
await runtime.boot();
|
|
148
|
+
expect(runtime.identities).toEqual([]);
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
it('diagnostics include vocabulary size and counts', async () => {
|
|
126
152
|
const runtime = new DotAiRuntime({ workspaceRoot: '/tmp/nonexistent' });
|
|
127
153
|
await runtime.boot();
|
|
128
154
|
const diag = runtime.diagnostics;
|
|
129
155
|
expect(diag.vocabularySize).toBeDefined();
|
|
130
|
-
expect(diag.capabilityCount).toBe(0);
|
|
156
|
+
expect(diag.capabilityCount).toBe(0);
|
|
157
|
+
expect(diag.skillCount).toBe(0);
|
|
158
|
+
expect(diag.identityCount).toBe(0);
|
|
131
159
|
expect(diag.extensions).toEqual([]);
|
|
132
160
|
});
|
|
133
161
|
|
package/src/boot-cache.ts
CHANGED
|
@@ -11,7 +11,7 @@ export interface BootCacheData {
|
|
|
11
11
|
version: 1;
|
|
12
12
|
/** Checksum of inputs that produced this cache */
|
|
13
13
|
checksum: string;
|
|
14
|
-
/** Label vocabulary from
|
|
14
|
+
/** Label vocabulary from registered resources */
|
|
15
15
|
vocabulary: string[];
|
|
16
16
|
/** Extension paths that were loaded */
|
|
17
17
|
extensionPaths: string[];
|
package/src/extension-api.ts
CHANGED
|
@@ -1,22 +1,19 @@
|
|
|
1
1
|
import type {
|
|
2
|
-
ContextInjectEvent, ContextInjectResult,
|
|
3
|
-
ContextModifyEvent, ContextModifyResult,
|
|
4
2
|
ToolCallEvent, ToolCallResult,
|
|
5
3
|
ToolResultEvent,
|
|
6
4
|
AgentEndEvent,
|
|
7
5
|
ToolDefinition,
|
|
8
6
|
ExtensionContext,
|
|
9
|
-
ResourcesDiscoverResult,
|
|
10
7
|
LabelExtractEvent,
|
|
11
8
|
ContextEnrichEvent, ContextEnrichResult,
|
|
12
9
|
RouteEvent, RouteResult,
|
|
13
10
|
InputEvent, InputResult,
|
|
14
11
|
CommandDefinition,
|
|
15
12
|
} from './extension-types.js';
|
|
16
|
-
import type { Label } from './types.js';
|
|
13
|
+
import type { Label, Skill, Identity } from './types.js';
|
|
17
14
|
|
|
18
15
|
/**
|
|
19
|
-
*
|
|
16
|
+
* v7 Extension Context — passed as second argument to every event handler.
|
|
20
17
|
* Extends the base ExtensionContext with labels and optional agent capabilities.
|
|
21
18
|
*/
|
|
22
19
|
export interface ExtensionContextV6 extends ExtensionContext {
|
|
@@ -39,8 +36,6 @@ export interface ExtensionContextV6 extends ExtensionContext {
|
|
|
39
36
|
export interface ExtensionAPI {
|
|
40
37
|
// ── Event subscription ──
|
|
41
38
|
|
|
42
|
-
/** Resource discovery: extensions declare resources and contribute labels */
|
|
43
|
-
on(event: 'resources_discover', handler: (e: undefined, ctx: ExtensionContextV6) => Promise<ResourcesDiscoverResult | void>): void;
|
|
44
39
|
/** Label extraction: extensions can add custom labels (chain-transform) */
|
|
45
40
|
on(event: 'label_extract', handler: (e: LabelExtractEvent, ctx: ExtensionContextV6) => Promise<Label[] | void>): void;
|
|
46
41
|
/** Context enrichment: extensions return sections for context injection */
|
|
@@ -58,28 +53,28 @@ export interface ExtensionAPI {
|
|
|
58
53
|
|
|
59
54
|
on(event: 'session_start', handler: (e: undefined, ctx: ExtensionContextV6) => Promise<void>): void;
|
|
60
55
|
on(event: 'session_end', handler: (e: undefined, ctx: ExtensionContextV6) => Promise<void>): void;
|
|
56
|
+
on(event: 'session_compact', handler: (e: undefined, ctx: ExtensionContextV6) => Promise<void>): void;
|
|
61
57
|
on(event: 'agent_start', handler: (e: undefined, ctx: ExtensionContextV6) => Promise<void>): void;
|
|
62
58
|
on(event: 'agent_end', handler: (e: AgentEndEvent, ctx: ExtensionContextV6) => Promise<void>): void;
|
|
63
59
|
on(event: 'turn_start', handler: (e: undefined, ctx: ExtensionContextV6) => Promise<void>): void;
|
|
64
60
|
on(event: 'turn_end', handler: (e: undefined, ctx: ExtensionContextV6) => Promise<void>): void;
|
|
65
61
|
|
|
66
|
-
// ── Legacy events (kept for transition) ──
|
|
67
|
-
|
|
68
|
-
/** @deprecated Use context_enrich instead */
|
|
69
|
-
on(event: 'context_inject', handler: (e: ContextInjectEvent, ctx: ExtensionContextV6) => Promise<ContextInjectResult | void>): void;
|
|
70
|
-
/** @deprecated Use context_enrich instead */
|
|
71
|
-
on(event: 'context_modify', handler: (e: ContextModifyEvent, ctx: ExtensionContextV6) => Promise<ContextModifyResult | void>): void;
|
|
72
|
-
|
|
73
62
|
// ── Catch-all for custom/Pi-specific events ──
|
|
74
63
|
|
|
75
64
|
on(event: string, handler: (e: any, ctx: ExtensionContextV6) => Promise<any>): void;
|
|
76
65
|
|
|
77
|
-
// ──
|
|
66
|
+
// ── Resource registration ──
|
|
78
67
|
|
|
79
68
|
/** Register a tool that the agent can invoke */
|
|
80
69
|
registerTool(tool: ToolDefinition): void;
|
|
81
70
|
/** Register a command (slash command, etc.) */
|
|
82
71
|
registerCommand(command: CommandDefinition): void;
|
|
72
|
+
/** Register a skill for context enrichment and discovery */
|
|
73
|
+
registerSkill(skill: Skill): void;
|
|
74
|
+
/** Register an identity document */
|
|
75
|
+
registerIdentity(identity: Identity): void;
|
|
76
|
+
/** Contribute labels to the global vocabulary (for label matching) */
|
|
77
|
+
contributeLabels(labels: string[]): void;
|
|
83
78
|
|
|
84
79
|
// ── Inter-extension communication ──
|
|
85
80
|
|