@driftengine/ai 3.61.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.
Files changed (82) hide show
  1. package/LICENSE +202 -0
  2. package/NOTICE +9 -0
  3. package/README.md +103 -0
  4. package/dist/adapters/local.d.ts +29 -0
  5. package/dist/adapters/local.js +24 -0
  6. package/dist/adapters/proxy.d.ts +28 -0
  7. package/dist/adapters/proxy.js +138 -0
  8. package/dist/bridges/authority.d.ts +153 -0
  9. package/dist/bridges/authority.js +179 -0
  10. package/dist/bridges/navigation.d.ts +100 -0
  11. package/dist/bridges/navigation.js +139 -0
  12. package/dist/budget/budget.d.ts +34 -0
  13. package/dist/budget/budget.js +57 -0
  14. package/dist/command/apply.d.ts +24 -0
  15. package/dist/command/apply.js +40 -0
  16. package/dist/command/log.d.ts +55 -0
  17. package/dist/command/log.js +50 -0
  18. package/dist/context/assemble.d.ts +48 -0
  19. package/dist/context/assemble.js +55 -0
  20. package/dist/context/continuation.d.ts +14 -0
  21. package/dist/context/continuation.js +36 -0
  22. package/dist/describe/manifest.d.ts +70 -0
  23. package/dist/describe/manifest.js +99 -0
  24. package/dist/entities/context.d.ts +52 -0
  25. package/dist/entities/context.js +83 -0
  26. package/dist/index.d.ts +61 -0
  27. package/dist/index.js +40 -0
  28. package/dist/policy/types.d.ts +55 -0
  29. package/dist/policy/types.js +26 -0
  30. package/dist/policy/utility.d.ts +18 -0
  31. package/dist/policy/utility.js +47 -0
  32. package/dist/provider/create.d.ts +16 -0
  33. package/dist/provider/create.js +57 -0
  34. package/dist/provider/latency.d.ts +27 -0
  35. package/dist/provider/latency.js +52 -0
  36. package/dist/provider/types.d.ts +90 -0
  37. package/dist/provider/types.js +8 -0
  38. package/dist/realtime/session.d.ts +35 -0
  39. package/dist/realtime/session.js +34 -0
  40. package/dist/session/agent.d.ts +217 -0
  41. package/dist/session/agent.js +506 -0
  42. package/dist/session/replay.d.ts +32 -0
  43. package/dist/session/replay.js +81 -0
  44. package/dist/session/states.d.ts +28 -0
  45. package/dist/session/states.js +33 -0
  46. package/dist/session/usage.d.ts +43 -0
  47. package/dist/session/usage.js +38 -0
  48. package/dist/testing/deterministic.d.ts +65 -0
  49. package/dist/testing/deterministic.js +150 -0
  50. package/dist/tools/policy.d.ts +47 -0
  51. package/dist/tools/policy.js +84 -0
  52. package/dist/tools/registry.d.ts +69 -0
  53. package/dist/tools/registry.js +75 -0
  54. package/dist/tools/validate.d.ts +24 -0
  55. package/dist/tools/validate.js +80 -0
  56. package/package.json +59 -0
  57. package/src/adapters/local.ts +64 -0
  58. package/src/adapters/proxy.ts +187 -0
  59. package/src/bridges/authority.ts +244 -0
  60. package/src/bridges/navigation.ts +207 -0
  61. package/src/budget/budget.ts +73 -0
  62. package/src/command/apply.ts +52 -0
  63. package/src/command/log.ts +81 -0
  64. package/src/context/assemble.ts +104 -0
  65. package/src/context/continuation.ts +39 -0
  66. package/src/describe/manifest.ts +148 -0
  67. package/src/entities/context.ts +112 -0
  68. package/src/index.ts +94 -0
  69. package/src/policy/types.ts +70 -0
  70. package/src/policy/utility.ts +53 -0
  71. package/src/provider/create.ts +70 -0
  72. package/src/provider/latency.ts +57 -0
  73. package/src/provider/types.ts +96 -0
  74. package/src/realtime/session.ts +63 -0
  75. package/src/session/agent.ts +622 -0
  76. package/src/session/replay.ts +96 -0
  77. package/src/session/states.ts +63 -0
  78. package/src/session/usage.ts +66 -0
  79. package/src/testing/deterministic.ts +204 -0
  80. package/src/tools/policy.ts +114 -0
  81. package/src/tools/registry.ts +122 -0
  82. package/src/tools/validate.ts +92 -0
@@ -0,0 +1,96 @@
1
+ /**
2
+ * The provider seam. Provider-specific concerns stay behind adapters.
3
+ *
4
+ * Capability is **declared rather than assumed**, so a session refuses an
5
+ * unsupported requirement early and in words instead of discovering it in
6
+ * production at whatever a failed request costs.
7
+ */
8
+
9
+ /**
10
+ * What a provider says it can do.
11
+ *
12
+ * Declared by the adapter rather than probed, except where a probe is cheap and
13
+ * honest — `createLocalProvider` runs one, because a local model's availability is
14
+ * a property of the device rather than of the configuration.
15
+ */
16
+ export interface AiProviderCapabilities {
17
+ readonly text: boolean;
18
+ readonly streamingText: boolean;
19
+ readonly structuredOutput: boolean;
20
+ readonly toolCalling: boolean;
21
+ readonly realtimeAudio: boolean;
22
+ readonly imageInput: boolean;
23
+ readonly local: boolean;
24
+ }
25
+
26
+ /**
27
+ * Context assembled for one request.
28
+ *
29
+ * Declared minimally here and widened where it is built. What the seam needs is
30
+ * the capture tick: a model must be able to know its snapshot may be stale, and a
31
+ * buffered agent widens that gap on purpose.
32
+ */
33
+ export interface AssembledContextLike {
34
+ readonly capturedAtTick: number;
35
+ }
36
+
37
+ export type AiEvent =
38
+ | { readonly kind: 'text'; readonly text: string }
39
+ | {
40
+ readonly kind: 'toolCall';
41
+ readonly callId: string;
42
+ readonly toolId: string;
43
+ readonly args: unknown;
44
+ }
45
+ | { readonly kind: 'usage'; readonly inputTokens: number; readonly outputTokens: number }
46
+ | {
47
+ readonly kind: 'done';
48
+ readonly reason: 'complete' | 'aborted' | 'error';
49
+ readonly message?: string;
50
+ };
51
+
52
+ export interface AiRequest {
53
+ readonly preamble: string;
54
+ readonly context: AssembledContextLike;
55
+ readonly toolIds: readonly string[];
56
+ readonly signal: AbortSignal;
57
+ }
58
+
59
+ export interface AiSessionOptions {
60
+ readonly model: string;
61
+ readonly systemPrompt?: string;
62
+ readonly maxOutputTokens?: number;
63
+ readonly temperature?: number;
64
+ }
65
+
66
+ export interface AiSession {
67
+ run(request: AiRequest): AsyncIterable<AiEvent>;
68
+ abort(reason?: string): void;
69
+ }
70
+
71
+ export interface AiProvider {
72
+ readonly id: string;
73
+ readonly capabilities: AiProviderCapabilities;
74
+ createSession(options: AiSessionOptions): AiSession;
75
+ }
76
+
77
+ export interface AiProviderConfig {
78
+ readonly kind: 'proxy' | 'local' | 'deterministic';
79
+ readonly session: AiSessionOptions;
80
+ /**
81
+ * The provider itself, where the caller already has one.
82
+ *
83
+ * Adapters that must be constructed — a local model that has to probe the device —
84
+ * are built by their own factory and handed here, so this function does one job:
85
+ * comparing what is declared against what is required.
86
+ */
87
+ readonly provider?: AiProvider;
88
+ /** Adapter-specific, and never a credential — see `adapters/proxy.ts`. */
89
+ readonly adapter?: Readonly<Record<string, unknown>>;
90
+ }
91
+
92
+ export interface AiProviderResult {
93
+ readonly provider: AiProvider | null;
94
+ /** Always a sentence, on both paths. An empty reason is the silent no-op. */
95
+ readonly reason: string;
96
+ }
@@ -0,0 +1,63 @@
1
+ import type { AiEvent, AiProvider, AiRequest, AiSession } from '../provider/types.ts';
2
+
3
+ /**
4
+ * A realtime transport, emitting the same events every other session emits.
5
+ *
6
+ * **Additive.** Nothing downstream branches on transport: the buffered loop, the floor,
7
+ * the admission guards and the command log all see the same `AiEvent` union they
8
+ * already see. A session with realtime configured still has exactly one request in
9
+ * flight, because the state machine does not know what a transport is.
10
+ *
11
+ * **Audio stays bridged, not coupled.** This module imports nothing from
12
+ * `@driftengine/audio`, and the package declares no dependency on it. A consumer wires
13
+ * its own microphone and speaker to whatever this yields, because the moment an AI
14
+ * package owned an audio graph it would be an AI package that knew what a mix was.
15
+ */
16
+ export interface RealtimeOptions {
17
+ readonly model: string;
18
+ /** Frames a consumer pushes in. Text here, because audio is the consumer's to carry. */
19
+ readonly input?: AsyncIterable<string>;
20
+ }
21
+
22
+ export type RealtimeResult =
23
+ | { readonly session: AiSession; readonly reason: string }
24
+ | { readonly session: null; readonly reason: string };
25
+
26
+ /**
27
+ * Open a realtime session, or refuse before connecting.
28
+ *
29
+ * Refused **before** any transport is opened, in the shape §32 requires of every other
30
+ * provider decision: a socket opened against a provider that cannot hold a realtime
31
+ * conversation is a socket that fails later and more expensively than a string
32
+ * comparison.
33
+ */
34
+ export function createRealtimeSession(
35
+ provider: AiProvider,
36
+ options: RealtimeOptions,
37
+ ): RealtimeResult {
38
+ if (!provider.capabilities.realtimeAudio) {
39
+ return {
40
+ session: null,
41
+ reason: `provider "${provider.id}" declares no realtime transport — a session cannot be opened against it`,
42
+ };
43
+ }
44
+
45
+ const inner = provider.createSession({ model: options.model });
46
+ let disposed = false;
47
+
48
+ return {
49
+ session: {
50
+ run(request: AiRequest): AsyncIterable<AiEvent> {
51
+ return inner.run(request);
52
+ },
53
+ abort(reason?: string): void {
54
+ /* A second disposal is a no-op rather than an error. Disposal races a scene
55
+ replacement and a hot reload, and both may reach the same session. */
56
+ if (disposed) return;
57
+ disposed = true;
58
+ inner.abort(reason ?? 'realtime session disposed');
59
+ },
60
+ },
61
+ reason: `realtime session open against "${provider.id}"`,
62
+ };
63
+ }