@inixiative/foundry-core 0.1.0 → 0.3.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/package.json +1 -6
- package/src/action-prompt.ts +47 -28
- package/src/adapters/file-memory.ts +314 -122
- package/src/adapters/http-memory.ts +19 -24
- package/src/adapters/index.ts +4 -4
- package/src/adapters/markdown-docs.ts +15 -15
- package/src/adapters/sqlite-memory.ts +29 -27
- package/src/base-agent.ts +5 -7
- package/src/cache-lifecycle.ts +14 -14
- package/src/capability.ts +76 -83
- package/src/clarifier.ts +46 -0
- package/src/classifier.ts +6 -9
- package/src/context-layer.ts +125 -78
- package/src/context-stack.ts +15 -14
- package/src/credentials.ts +4 -2
- package/src/decider.ts +7 -8
- package/src/delivery-evidence.ts +206 -55
- package/src/event-stream.ts +34 -20
- package/src/executor.ts +81 -43
- package/src/harness.ts +225 -126
- package/src/hooks.ts +26 -26
- package/src/hydrator.ts +6 -8
- package/src/id.ts +3 -3
- package/src/index.ts +248 -218
- package/src/intervention.ts +21 -12
- package/src/messages.ts +73 -62
- package/src/middleware.ts +9 -19
- package/src/model-registry.ts +1587 -0
- package/src/native-evidence.ts +124 -30
- package/src/permission-middleware.ts +16 -28
- package/src/retry.ts +6 -6
- package/src/router.ts +5 -5
- package/src/signal.ts +16 -11
- package/src/thread.ts +138 -61
- package/src/token-counts.ts +9 -1
- package/src/token-tracker.ts +43 -34
- package/src/tools.ts +138 -95
- package/src/trace.ts +44 -23
- package/src/types.ts +33 -24
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@inixiative/foundry-core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "src/index.ts",
|
|
6
6
|
"types": "src/index.ts",
|
|
@@ -15,11 +15,6 @@
|
|
|
15
15
|
"dependencies": {
|
|
16
16
|
"uuidv7": "^1.0.2"
|
|
17
17
|
},
|
|
18
|
-
"devDependencies": {
|
|
19
|
-
"@types/bun": "^1.4.2",
|
|
20
|
-
"bun-types": "^1.4.2",
|
|
21
|
-
"typescript": "^5.7.0"
|
|
22
|
-
},
|
|
23
18
|
"description": "Foundry core engine: context layers, agents, middleware, signals, threads, harness and tracing primitives",
|
|
24
19
|
"license": "MIT",
|
|
25
20
|
"files": [
|
package/src/action-prompt.ts
CHANGED
|
@@ -14,9 +14,9 @@
|
|
|
14
14
|
// Types
|
|
15
15
|
// ---------------------------------------------------------------------------
|
|
16
16
|
|
|
17
|
-
export type PromptKind =
|
|
18
|
-
export type PromptUrgency =
|
|
19
|
-
export type PromptStatus =
|
|
17
|
+
export type PromptKind = 'approval' | 'choice' | 'input' | 'confirm';
|
|
18
|
+
export type PromptUrgency = 'low' | 'normal' | 'high' | 'critical';
|
|
19
|
+
export type PromptStatus = 'pending' | 'approved' | 'rejected' | 'expired' | 'auto-resolved';
|
|
20
20
|
|
|
21
21
|
export interface ActionOption {
|
|
22
22
|
readonly id: string;
|
|
@@ -27,7 +27,7 @@ export interface ActionOption {
|
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
export interface ActionResolution {
|
|
30
|
-
readonly by:
|
|
30
|
+
readonly by: 'human' | 'policy' | 'timeout';
|
|
31
31
|
readonly action: string; // "approved", "rejected", or an option ID
|
|
32
32
|
readonly input?: string; // for "input" kind prompts
|
|
33
33
|
readonly timestamp: number;
|
|
@@ -80,7 +80,10 @@ export type PromptPolicy = (prompt: ActionPrompt) => ActionResolution | null;
|
|
|
80
80
|
|
|
81
81
|
export class ActionQueue {
|
|
82
82
|
private _prompts = new Map<string, ActionPrompt>();
|
|
83
|
-
private _waiters = new Map<
|
|
83
|
+
private _waiters = new Map<
|
|
84
|
+
string,
|
|
85
|
+
{ resolve: (r: ActionResolution) => void; timer?: ReturnType<typeof setTimeout> }
|
|
86
|
+
>();
|
|
84
87
|
private _listeners: PromptListener[] = [];
|
|
85
88
|
private _settleListeners: PromptListener[] = [];
|
|
86
89
|
private _policies: PromptPolicy[] = [];
|
|
@@ -103,7 +106,11 @@ export class ActionQueue {
|
|
|
103
106
|
|
|
104
107
|
private _settled(prompt: ActionPrompt): void {
|
|
105
108
|
for (const fn of this._settleListeners) {
|
|
106
|
-
try {
|
|
109
|
+
try {
|
|
110
|
+
fn(prompt);
|
|
111
|
+
} catch {
|
|
112
|
+
/* listener errors don't block */
|
|
113
|
+
}
|
|
107
114
|
}
|
|
108
115
|
}
|
|
109
116
|
|
|
@@ -131,10 +138,10 @@ export class ActionQueue {
|
|
|
131
138
|
message: opts.message,
|
|
132
139
|
options: opts.options,
|
|
133
140
|
capability: opts.capability,
|
|
134
|
-
urgency: opts.urgency ??
|
|
141
|
+
urgency: opts.urgency ?? 'normal',
|
|
135
142
|
expiresAt: opts.timeoutMs ? Date.now() + opts.timeoutMs : undefined,
|
|
136
143
|
meta: opts.meta,
|
|
137
|
-
status:
|
|
144
|
+
status: 'pending',
|
|
138
145
|
};
|
|
139
146
|
|
|
140
147
|
this._prompts.set(id, prompt);
|
|
@@ -143,29 +150,25 @@ export class ActionQueue {
|
|
|
143
150
|
for (const policy of this._policies) {
|
|
144
151
|
const resolution = policy(prompt);
|
|
145
152
|
if (resolution) {
|
|
146
|
-
prompt.status =
|
|
153
|
+
prompt.status = 'auto-resolved';
|
|
147
154
|
prompt.resolution = resolution;
|
|
148
155
|
return resolution;
|
|
149
156
|
}
|
|
150
157
|
}
|
|
151
158
|
|
|
152
|
-
//
|
|
153
|
-
|
|
154
|
-
try { fn(prompt); } catch { /* listener errors don't block */ }
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
// Block until resolved
|
|
158
|
-
return new Promise<ActionResolution>((resolve) => {
|
|
159
|
+
// Register the waiter before notifying: a listener may resolve synchronously.
|
|
160
|
+
const settled = new Promise<ActionResolution>((resolve) => {
|
|
159
161
|
let timer: ReturnType<typeof setTimeout> | undefined;
|
|
160
162
|
|
|
161
163
|
if (opts.timeoutMs) {
|
|
162
164
|
timer = setTimeout(() => {
|
|
165
|
+
if (prompt.status !== 'pending') return;
|
|
163
166
|
const resolution: ActionResolution = {
|
|
164
|
-
by:
|
|
165
|
-
action:
|
|
167
|
+
by: 'timeout',
|
|
168
|
+
action: 'rejected',
|
|
166
169
|
timestamp: Date.now(),
|
|
167
170
|
};
|
|
168
|
-
prompt.status =
|
|
171
|
+
prompt.status = 'expired';
|
|
169
172
|
prompt.resolution = resolution;
|
|
170
173
|
this._waiters.delete(id);
|
|
171
174
|
resolve(resolution);
|
|
@@ -175,26 +178,42 @@ export class ActionQueue {
|
|
|
175
178
|
|
|
176
179
|
this._waiters.set(id, { resolve, timer });
|
|
177
180
|
});
|
|
181
|
+
|
|
182
|
+
// Notify listeners (viewer badge, event stream, etc.)
|
|
183
|
+
for (const fn of this._listeners) {
|
|
184
|
+
if (prompt.status !== 'pending') break;
|
|
185
|
+
try {
|
|
186
|
+
fn(prompt);
|
|
187
|
+
} catch {
|
|
188
|
+
/* listener errors don't block */
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
return settled;
|
|
178
193
|
}
|
|
179
194
|
|
|
180
195
|
/**
|
|
181
196
|
* Resolve a pending prompt. Called by the viewer UI or external systems.
|
|
182
197
|
*/
|
|
183
|
-
resolve(
|
|
198
|
+
resolve(
|
|
199
|
+
promptId: string,
|
|
200
|
+
action: string,
|
|
201
|
+
opts?: { by?: 'human' | 'policy'; input?: string },
|
|
202
|
+
): boolean {
|
|
184
203
|
const prompt = this._prompts.get(promptId);
|
|
185
|
-
if (!prompt || prompt.status !==
|
|
204
|
+
if (!prompt || prompt.status !== 'pending') return false;
|
|
186
205
|
|
|
187
206
|
const resolution: ActionResolution = {
|
|
188
|
-
by: opts?.by ??
|
|
207
|
+
by: opts?.by ?? 'human',
|
|
189
208
|
action,
|
|
190
209
|
input: opts?.input,
|
|
191
210
|
timestamp: Date.now(),
|
|
192
211
|
};
|
|
193
212
|
|
|
194
|
-
prompt.status = action ===
|
|
213
|
+
prompt.status = action === 'approved' || action === 'confirmed' ? 'approved' : 'rejected';
|
|
195
214
|
// For choice prompts, mark as approved if any option selected
|
|
196
|
-
if (prompt.kind ===
|
|
197
|
-
prompt.status =
|
|
215
|
+
if (prompt.kind === 'choice' && prompt.options?.some((o) => o.id === action)) {
|
|
216
|
+
prompt.status = 'approved';
|
|
198
217
|
}
|
|
199
218
|
prompt.resolution = resolution;
|
|
200
219
|
|
|
@@ -211,7 +230,7 @@ export class ActionQueue {
|
|
|
211
230
|
|
|
212
231
|
/** Get all pending prompts. */
|
|
213
232
|
pending(): ActionPrompt[] {
|
|
214
|
-
return [...this._prompts.values()].filter((p) => p.status ===
|
|
233
|
+
return [...this._prompts.values()].filter((p) => p.status === 'pending');
|
|
215
234
|
}
|
|
216
235
|
|
|
217
236
|
/** Get all prompts for a thread (including resolved). */
|
|
@@ -223,7 +242,7 @@ export class ActionQueue {
|
|
|
223
242
|
pendingCount(threadId?: string): number {
|
|
224
243
|
let count = 0;
|
|
225
244
|
for (const p of this._prompts.values()) {
|
|
226
|
-
if (p.status ===
|
|
245
|
+
if (p.status === 'pending' && (!threadId || p.threadId === threadId)) count++;
|
|
227
246
|
}
|
|
228
247
|
return count;
|
|
229
248
|
}
|
|
@@ -238,7 +257,7 @@ export class ActionQueue {
|
|
|
238
257
|
const cutoff = Date.now() - maxAgeMs;
|
|
239
258
|
let pruned = 0;
|
|
240
259
|
for (const [id, p] of this._prompts) {
|
|
241
|
-
if (p.status !==
|
|
260
|
+
if (p.status !== 'pending' && p.timestamp < cutoff) {
|
|
242
261
|
this._prompts.delete(id);
|
|
243
262
|
pruned++;
|
|
244
263
|
}
|