glove-foundry 0.5.1 → 0.5.2
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/README.md +27 -15
- package/dist/{chunk-KBMD4RYU.js → chunk-6Q2LGPSC.js} +49 -198
- package/dist/{chunk-GKZLWD5M.js → chunk-7F7QVO6I.js} +4 -1
- package/dist/{chunk-SGF3CFUR.js → chunk-D2AHSYOB.js} +71 -8
- package/dist/{chunk-TH5ETCG2.js → chunk-MABLKZVO.js} +13 -4
- package/dist/{chunk-LW5PJ2FN.js → chunk-NHV64WNO.js} +1 -1
- package/dist/{chunk-5NFLGHOC.js → chunk-PVOKR4CN.js} +211 -29
- package/dist/cli.js +7 -5
- package/dist/{client-DcsnudMI.d.ts → client-CLTds1uV.d.ts} +13 -1
- package/dist/client.d.ts +1 -1
- package/dist/client.js +1 -1
- package/dist/execution-agent.js +4 -4
- package/dist/execution-daemon.js +1 -1
- package/dist/execution-loader.js +4 -4
- package/dist/index.d.ts +2 -2
- package/dist/index.js +14 -14
- package/docs/building-with-foundry.md +4 -2
- package/docs/release-verification.md +1 -1
- package/package.json +6 -6
- package/templates/minimal/README.md +34 -8
- package/templates/minimal/agents/assistant/agent.ts +24 -10
- package/templates/minimal/foundry.application.ts +11 -3
- package/templates/minimal/gitignore +1 -0
- package/templates/minimal/lib/file-store.ts +95 -0
- package/templates/travel-concierge/README.md +46 -12
- package/templates/travel-concierge/agents/concierge/agent.ts +10 -4
- package/templates/travel-concierge/agents/concierge/composition.ts +9 -2
- package/templates/travel-concierge/agents/concierge/flights.ts +43 -0
- package/templates/travel-concierge/agents/concierge/instances.ts +42 -0
- package/templates/travel-concierge/agents/concierge/memory/traveller.memory.ts +13 -8
- package/templates/travel-concierge/agents/concierge/tools/convert-currency.tool.ts +34 -0
- package/templates/travel-concierge/agents/concierge/workbench.ts +4 -1
- package/templates/travel-concierge/foundry.application.ts +15 -6
- package/templates/travel-concierge/gitignore +1 -0
- package/templates/travel-concierge/lib/demo-model.ts +89 -25
- package/templates/travel-concierge/lib/file-context.ts +60 -0
- package/templates/travel-concierge/lib/file-store.ts +95 -0
- package/templates/minimal/agents/assistant/tools/current-time.tool.ts +0 -17
- package/templates/travel-concierge/agents/concierge/tools/find-flights.tool.ts +0 -49
package/README.md
CHANGED
|
@@ -71,13 +71,15 @@ If installation fails, your generated project remains available with retry steps
|
|
|
71
71
|
|
|
72
72
|
### Before deploying
|
|
73
73
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
74
|
+
Every run executes in its own process, so nothing the next message needs can live
|
|
75
|
+
only in memory. Persist **four separate things**: Foundry runtime data
|
|
76
|
+
(instances, conversations, activations, workspace), Glove conversation
|
|
77
|
+
transcripts, structured memory, and working-environment files. Persisting one does
|
|
78
|
+
not persist the others. The starters keep all of them on disk under `.data/` with
|
|
79
|
+
single-host adapters (`FileFoundryDataAdapter`, a file-backed transcript store in
|
|
80
|
+
`lib/file-store.ts`, and — in the concierge — file-backed memory and VFS
|
|
81
|
+
persistence). Multi-host deployments need shared, transactional adapters. See
|
|
82
|
+
[Persistence](https://glove.dterminal.net/foundry/docs/persistence).
|
|
81
83
|
|
|
82
84
|
**Troubleshooting:** check `node --version` for engine errors, add a provider key
|
|
83
85
|
for the minimal starter, choose another `--port` if 4141 is occupied, and inspect a
|
|
@@ -317,21 +319,31 @@ projection is resolved only when the subagent is called, after instance
|
|
|
317
319
|
installations and message-dependent assembly have completed.
|
|
318
320
|
|
|
319
321
|
```ts
|
|
322
|
+
import { getToolJsonSchema } from "glove-core"
|
|
323
|
+
|
|
324
|
+
// Names of tools the parent has mounted that the delegate may use.
|
|
325
|
+
const READ_ONLY = new Set(["web_search", "web_read", "workspace_read_file"])
|
|
326
|
+
|
|
320
327
|
defineSubagent({
|
|
321
328
|
name: "researcher",
|
|
322
329
|
description: "Research one bounded question",
|
|
323
330
|
systemPrompt: "Return evidence, uncertainty, and a concise conclusion.",
|
|
324
|
-
tools: ({ parent }) =>
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
331
|
+
tools: ({ parent }) =>
|
|
332
|
+
parent.tools
|
|
333
|
+
.filter((tool) => READ_ONLY.has(tool.name))
|
|
334
|
+
.map((tool) => ({
|
|
335
|
+
name: tool.name,
|
|
336
|
+
description: tool.description,
|
|
337
|
+
jsonSchema: getToolJsonSchema(tool),
|
|
338
|
+
do: (input, _display, _agent, signal) => tool.run(input, undefined, signal),
|
|
339
|
+
})),
|
|
329
340
|
})
|
|
330
341
|
```
|
|
331
342
|
|
|
332
|
-
The child keeps its isolated store, compaction policy, model, prompt
|
|
333
|
-
layers
|
|
334
|
-
|
|
343
|
+
The child keeps its isolated store, compaction policy, model, prompt and skills.
|
|
344
|
+
Its `layers` and `subscribers` mount when the subagent is invoked and are
|
|
345
|
+
disposed when its request ends. Parent subscribers still receive the subagent
|
|
346
|
+
lifecycle bracket, so delegation remains visible in the same run trace.
|
|
335
347
|
|
|
336
348
|
## Programmatic tool workflows
|
|
337
349
|
|
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
import {
|
|
2
|
+
EMPTY_NATIVE_REGISTRY,
|
|
3
|
+
FOUNDRY_LAYER_BRAND,
|
|
4
|
+
FOUNDRY_SUBSCRIBER_BRAND,
|
|
2
5
|
bindFileIdentity,
|
|
3
6
|
defineAgentFromModule,
|
|
4
7
|
fileDefinitionKey,
|
|
5
8
|
fileDefinitionLabel,
|
|
6
9
|
fileIdentified,
|
|
7
10
|
internalAgentName
|
|
8
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-PVOKR4CN.js";
|
|
9
12
|
|
|
10
13
|
// src/application.ts
|
|
11
14
|
var FOUNDRY_APPLICATION_BRAND = /* @__PURE__ */ Symbol.for(
|
|
@@ -408,149 +411,6 @@ function isFoundryCapability(value) {
|
|
|
408
411
|
return object[FOUNDRY_SHARED_TOOL_BRAND] === true || object[FOUNDRY_AGENT_APPLICATION_BRAND] === true || object[FOUNDRY_MCP_BRAND] === true || object[FOUNDRY_MEMORY_BRAND] === true;
|
|
409
412
|
}
|
|
410
413
|
|
|
411
|
-
// src/surfaces.ts
|
|
412
|
-
import { Effect as Effect2 } from "effect";
|
|
413
|
-
var FOUNDRY_LAYER_BRAND = /* @__PURE__ */ Symbol.for("glove-foundry-layer");
|
|
414
|
-
var FOUNDRY_SUBSCRIBER_BRAND = /* @__PURE__ */ Symbol.for(
|
|
415
|
-
"glove-foundry-subscriber"
|
|
416
|
-
);
|
|
417
|
-
var SURFACE_ID = /^[a-z][a-z0-9-]*(?:\/[a-z][a-z0-9-]*)*$/;
|
|
418
|
-
function assertSurfaceId(id2, label) {
|
|
419
|
-
if (!SURFACE_ID.test(id2)) {
|
|
420
|
-
throw new Error(
|
|
421
|
-
`Invalid Foundry ${label} id "${id2}". Use lowercase path segments containing letters, digits, and hyphens.`
|
|
422
|
-
);
|
|
423
|
-
}
|
|
424
|
-
}
|
|
425
|
-
function defineLayer(options) {
|
|
426
|
-
if (options.id) assertSurfaceId(options.id, "layer");
|
|
427
|
-
const { id: id2, ...definition } = options;
|
|
428
|
-
return Object.freeze(fileIdentified({
|
|
429
|
-
...definition,
|
|
430
|
-
[FOUNDRY_LAYER_BRAND]: true
|
|
431
|
-
}, "layer", id2));
|
|
432
|
-
}
|
|
433
|
-
function configureLayer(layer, config) {
|
|
434
|
-
return Object.freeze({ layer, config });
|
|
435
|
-
}
|
|
436
|
-
function defineSubscriber(options) {
|
|
437
|
-
if (options.id) assertSurfaceId(options.id, "subscriber");
|
|
438
|
-
const { id: id2, ...definition } = options;
|
|
439
|
-
return Object.freeze(fileIdentified({
|
|
440
|
-
...definition,
|
|
441
|
-
[FOUNDRY_SUBSCRIBER_BRAND]: true
|
|
442
|
-
}, "subscriber", id2));
|
|
443
|
-
}
|
|
444
|
-
var EMPTY_NATIVE_REGISTRY = Object.freeze({
|
|
445
|
-
layers: Object.freeze([]),
|
|
446
|
-
subscribers: Object.freeze([])
|
|
447
|
-
});
|
|
448
|
-
function indexById(values, label) {
|
|
449
|
-
const indexed = /* @__PURE__ */ new Map();
|
|
450
|
-
for (const value of values) {
|
|
451
|
-
if (indexed.has(value.id)) {
|
|
452
|
-
throw new Error(`Duplicate Foundry ${label} id "${value.id}".`);
|
|
453
|
-
}
|
|
454
|
-
indexed.set(value.id, value);
|
|
455
|
-
}
|
|
456
|
-
return indexed;
|
|
457
|
-
}
|
|
458
|
-
async function mountFoundrySurfaces(options) {
|
|
459
|
-
const layers = indexById(options.registry.layers, "layer");
|
|
460
|
-
const subscribers = indexById(options.registry.subscribers, "subscriber");
|
|
461
|
-
const cleanup = [];
|
|
462
|
-
const disposeAll = async () => {
|
|
463
|
-
const failures = [];
|
|
464
|
-
for (const dispose of cleanup.reverse()) {
|
|
465
|
-
try {
|
|
466
|
-
const result = dispose();
|
|
467
|
-
if (Effect2.isEffect(result)) await Effect2.runPromise(result);
|
|
468
|
-
else await Promise.resolve(result);
|
|
469
|
-
} catch (cause) {
|
|
470
|
-
failures.push(cause);
|
|
471
|
-
}
|
|
472
|
-
}
|
|
473
|
-
if (failures.length > 0) {
|
|
474
|
-
throw new AggregateError(failures, "Foundry surface cleanup failed.");
|
|
475
|
-
}
|
|
476
|
-
};
|
|
477
|
-
try {
|
|
478
|
-
for (const selected of options.subscribers ?? []) {
|
|
479
|
-
let definition = selected;
|
|
480
|
-
if (typeof definition === "object" && definition !== null && FOUNDRY_SUBSCRIBER_BRAND in definition) {
|
|
481
|
-
const registered = subscribers.get(definition.id);
|
|
482
|
-
if (!registered) {
|
|
483
|
-
throw new Error(
|
|
484
|
-
`Agent "${options.context.agentId}" references unknown subscriber "${definition.id}".`
|
|
485
|
-
);
|
|
486
|
-
}
|
|
487
|
-
definition = registered;
|
|
488
|
-
}
|
|
489
|
-
let subscriber;
|
|
490
|
-
let subscriberId = "inline";
|
|
491
|
-
if (typeof definition === "object" && definition !== null && definition[FOUNDRY_SUBSCRIBER_BRAND] === true) {
|
|
492
|
-
const foundrySubscriber = definition;
|
|
493
|
-
const created = typeof foundrySubscriber.create === "function" ? foundrySubscriber.create(options.context) : foundrySubscriber.create;
|
|
494
|
-
subscriber = Effect2.isEffect(created) ? await Effect2.runPromise(created) : await Promise.resolve(created);
|
|
495
|
-
subscriberId = foundrySubscriber.id;
|
|
496
|
-
} else {
|
|
497
|
-
subscriber = definition;
|
|
498
|
-
}
|
|
499
|
-
options.context.glove.addSubscriber(subscriber);
|
|
500
|
-
cleanup.push(() => options.context.glove.removeSubscriber(subscriber));
|
|
501
|
-
options.context.emit({
|
|
502
|
-
type: "foundry.subscriber.mounted",
|
|
503
|
-
data: { id: subscriberId }
|
|
504
|
-
});
|
|
505
|
-
}
|
|
506
|
-
for (const selected of options.layers ?? []) {
|
|
507
|
-
const reference = FOUNDRY_LAYER_BRAND in selected ? { layer: selected } : selected;
|
|
508
|
-
const definition = layers.get(reference.layer.id);
|
|
509
|
-
if (!definition) {
|
|
510
|
-
throw new Error(
|
|
511
|
-
`Agent "${options.context.agentId}" references unknown layer "${reference.layer.id}".`
|
|
512
|
-
);
|
|
513
|
-
}
|
|
514
|
-
const referenceConfig = "config" in reference ? reference.config : void 0;
|
|
515
|
-
const parsed = definition.config ? definition.config.safeParse(referenceConfig ?? {}) : { success: true, data: referenceConfig };
|
|
516
|
-
if (!parsed.success) {
|
|
517
|
-
throw new Error(
|
|
518
|
-
`Invalid config for layer "${definition.id}": ${parsed.error.message}`
|
|
519
|
-
);
|
|
520
|
-
}
|
|
521
|
-
const dispose = await Effect2.runPromise(
|
|
522
|
-
definition.setup({ ...options.context, config: parsed.data })
|
|
523
|
-
);
|
|
524
|
-
if (dispose) cleanup.push(dispose);
|
|
525
|
-
options.context.emit({
|
|
526
|
-
type: "foundry.layer.mounted",
|
|
527
|
-
data: { id: definition.id }
|
|
528
|
-
});
|
|
529
|
-
}
|
|
530
|
-
} catch (cause) {
|
|
531
|
-
try {
|
|
532
|
-
await disposeAll();
|
|
533
|
-
} catch (cleanupCause) {
|
|
534
|
-
throw new AggregateError(
|
|
535
|
-
[cause, cleanupCause],
|
|
536
|
-
"Foundry surface mount and cleanup failed."
|
|
537
|
-
);
|
|
538
|
-
}
|
|
539
|
-
throw cause;
|
|
540
|
-
}
|
|
541
|
-
return disposeAll;
|
|
542
|
-
}
|
|
543
|
-
function isFoundryLayer(value) {
|
|
544
|
-
return Boolean(
|
|
545
|
-
value && typeof value === "object" && value[FOUNDRY_LAYER_BRAND] === true
|
|
546
|
-
);
|
|
547
|
-
}
|
|
548
|
-
function isFoundrySubscriber(value) {
|
|
549
|
-
return Boolean(
|
|
550
|
-
value && typeof value === "object" && value[FOUNDRY_SUBSCRIBER_BRAND] === true
|
|
551
|
-
);
|
|
552
|
-
}
|
|
553
|
-
|
|
554
414
|
// src/composition.ts
|
|
555
415
|
var composedToolBodies = /* @__PURE__ */ new WeakMap();
|
|
556
416
|
function isToolBody(value) {
|
|
@@ -1274,7 +1134,7 @@ function createManifest(agents) {
|
|
|
1274
1134
|
|
|
1275
1135
|
// src/primitives.ts
|
|
1276
1136
|
import { randomUUID } from "node:crypto";
|
|
1277
|
-
import { Effect as
|
|
1137
|
+
import { Effect as Effect3 } from "effect";
|
|
1278
1138
|
function toGloveMessage(input) {
|
|
1279
1139
|
if (typeof input === "string") {
|
|
1280
1140
|
return freezeGloveMessage({ sender: "user", text: input });
|
|
@@ -1346,13 +1206,13 @@ var MemoryFoundryDataAdapter = class {
|
|
|
1346
1206
|
this.pendingSubscriptions = [];
|
|
1347
1207
|
}
|
|
1348
1208
|
getAgent(id2) {
|
|
1349
|
-
return
|
|
1209
|
+
return Effect3.sync(() => {
|
|
1350
1210
|
this.materializeSeeds();
|
|
1351
1211
|
return this.agents.get(id2) ?? null;
|
|
1352
1212
|
});
|
|
1353
1213
|
}
|
|
1354
1214
|
putAgent(agent) {
|
|
1355
|
-
return
|
|
1215
|
+
return Effect3.sync(() => {
|
|
1356
1216
|
this.materializeSeeds();
|
|
1357
1217
|
const reconstructed = reconstructAgentInstance(agent);
|
|
1358
1218
|
const prior = this.agents.get(agent.id);
|
|
@@ -1366,13 +1226,13 @@ var MemoryFoundryDataAdapter = class {
|
|
|
1366
1226
|
});
|
|
1367
1227
|
}
|
|
1368
1228
|
listAgents(definitionId) {
|
|
1369
|
-
return
|
|
1229
|
+
return Effect3.sync(() => {
|
|
1370
1230
|
this.materializeSeeds();
|
|
1371
1231
|
return [...this.agents.values()].filter((item) => !definitionId || item.definitionId === definitionId);
|
|
1372
1232
|
});
|
|
1373
1233
|
}
|
|
1374
1234
|
provisionAgent(input) {
|
|
1375
|
-
return
|
|
1235
|
+
return Effect3.sync(() => {
|
|
1376
1236
|
this.materializeSeeds();
|
|
1377
1237
|
const existingId = this.agentsByProvisioningKey.get(input.provisioningKey);
|
|
1378
1238
|
if (existingId) return this.agents.get(existingId);
|
|
@@ -1386,34 +1246,34 @@ var MemoryFoundryDataAdapter = class {
|
|
|
1386
1246
|
});
|
|
1387
1247
|
}
|
|
1388
1248
|
getPlaybookSubscription(id2) {
|
|
1389
|
-
return
|
|
1249
|
+
return Effect3.sync(() => {
|
|
1390
1250
|
this.materializeSeeds();
|
|
1391
1251
|
return this.subscriptions.get(id2) ?? null;
|
|
1392
1252
|
});
|
|
1393
1253
|
}
|
|
1394
1254
|
putPlaybookSubscription(subscription) {
|
|
1395
|
-
return
|
|
1255
|
+
return Effect3.sync(() => {
|
|
1396
1256
|
this.materializeSeeds();
|
|
1397
1257
|
this.subscriptions.set(subscription.id, reconstructPlaybookSubscription(subscription));
|
|
1398
1258
|
});
|
|
1399
1259
|
}
|
|
1400
1260
|
deletePlaybookSubscription(id2) {
|
|
1401
|
-
return
|
|
1261
|
+
return Effect3.sync(() => {
|
|
1402
1262
|
this.materializeSeeds();
|
|
1403
1263
|
return this.subscriptions.delete(id2);
|
|
1404
1264
|
});
|
|
1405
1265
|
}
|
|
1406
1266
|
listPlaybookSubscriptions(workspaceId) {
|
|
1407
|
-
return
|
|
1267
|
+
return Effect3.sync(() => {
|
|
1408
1268
|
this.materializeSeeds();
|
|
1409
1269
|
return [...this.subscriptions.values()].filter((item) => !workspaceId || item.workspaceId === workspaceId);
|
|
1410
1270
|
});
|
|
1411
1271
|
}
|
|
1412
1272
|
getInboundDelivery(key) {
|
|
1413
|
-
return
|
|
1273
|
+
return Effect3.succeed(this.inboundDeliveries.get(key) ?? null);
|
|
1414
1274
|
}
|
|
1415
1275
|
claimInboundDelivery(key) {
|
|
1416
|
-
return
|
|
1276
|
+
return Effect3.sync(() => {
|
|
1417
1277
|
if (this.inboundDeliveries.has(key)) return false;
|
|
1418
1278
|
this.inboundDeliveries.set(key, Object.freeze({
|
|
1419
1279
|
key,
|
|
@@ -1425,7 +1285,7 @@ var MemoryFoundryDataAdapter = class {
|
|
|
1425
1285
|
});
|
|
1426
1286
|
}
|
|
1427
1287
|
completeInboundDelivery(key, runIds) {
|
|
1428
|
-
return
|
|
1288
|
+
return Effect3.sync(() => {
|
|
1429
1289
|
const prior = this.inboundDeliveries.get(key);
|
|
1430
1290
|
if (!prior) throw new Error(`Inbound delivery claim "${key}" does not exist.`);
|
|
1431
1291
|
this.inboundDeliveries.set(key, Object.freeze({
|
|
@@ -1437,46 +1297,46 @@ var MemoryFoundryDataAdapter = class {
|
|
|
1437
1297
|
});
|
|
1438
1298
|
}
|
|
1439
1299
|
releaseInboundDelivery(key) {
|
|
1440
|
-
return
|
|
1300
|
+
return Effect3.sync(() => {
|
|
1441
1301
|
if (this.inboundDeliveries.get(key)?.status === "pending") {
|
|
1442
1302
|
this.inboundDeliveries.delete(key);
|
|
1443
1303
|
}
|
|
1444
1304
|
});
|
|
1445
1305
|
}
|
|
1446
1306
|
getActivation(id2) {
|
|
1447
|
-
return
|
|
1307
|
+
return Effect3.succeed(this.activations.get(id2) ?? null);
|
|
1448
1308
|
}
|
|
1449
1309
|
putActivation(activation) {
|
|
1450
|
-
return
|
|
1310
|
+
return Effect3.sync(() => {
|
|
1451
1311
|
this.activations.set(activation.id, reconstructActivation(activation));
|
|
1452
1312
|
});
|
|
1453
1313
|
}
|
|
1454
1314
|
listActivations(workspaceId) {
|
|
1455
|
-
return
|
|
1315
|
+
return Effect3.succeed(
|
|
1456
1316
|
[...this.activations.values()].filter((item) => !workspaceId || item.workspaceId === workspaceId)
|
|
1457
1317
|
);
|
|
1458
1318
|
}
|
|
1459
1319
|
getConversation(id2) {
|
|
1460
|
-
return
|
|
1320
|
+
return Effect3.succeed(this.conversations.get(id2) ?? null);
|
|
1461
1321
|
}
|
|
1462
1322
|
putConversation(conversation) {
|
|
1463
|
-
return
|
|
1323
|
+
return Effect3.sync(() => {
|
|
1464
1324
|
this.conversations.set(conversation.id, Object.freeze({ ...conversation }));
|
|
1465
1325
|
});
|
|
1466
1326
|
}
|
|
1467
1327
|
listConversations(agentId) {
|
|
1468
|
-
return
|
|
1328
|
+
return Effect3.succeed([...this.conversations.values()].filter((item) => item.agentId === agentId));
|
|
1469
1329
|
}
|
|
1470
1330
|
getWorkspaceEntry(workspaceId, key) {
|
|
1471
|
-
return
|
|
1331
|
+
return Effect3.succeed(this.workspace.get(`${workspaceId}:${key}`) ?? null);
|
|
1472
1332
|
}
|
|
1473
1333
|
putWorkspaceEntry(entry) {
|
|
1474
|
-
return
|
|
1334
|
+
return Effect3.sync(() => {
|
|
1475
1335
|
this.workspace.set(`${entry.workspaceId}:${entry.key}`, Object.freeze({ ...entry }));
|
|
1476
1336
|
});
|
|
1477
1337
|
}
|
|
1478
1338
|
compareAndSetWorkspaceEntry(entry, expectedUpdatedAt) {
|
|
1479
|
-
return
|
|
1339
|
+
return Effect3.sync(() => {
|
|
1480
1340
|
const key = `${entry.workspaceId}:${entry.key}`;
|
|
1481
1341
|
const current = this.workspace.get(key);
|
|
1482
1342
|
if ((current?.updatedAt ?? null) !== expectedUpdatedAt) return false;
|
|
@@ -1488,16 +1348,16 @@ var MemoryFoundryDataAdapter = class {
|
|
|
1488
1348
|
});
|
|
1489
1349
|
}
|
|
1490
1350
|
listWorkspaceEntries(workspaceId) {
|
|
1491
|
-
return
|
|
1351
|
+
return Effect3.succeed([...this.workspace.values()].filter((item) => item.workspaceId === workspaceId));
|
|
1492
1352
|
}
|
|
1493
1353
|
getWorkingEnvironmentSnapshot(owner) {
|
|
1494
|
-
return
|
|
1354
|
+
return Effect3.sync(() => {
|
|
1495
1355
|
const snapshot = this.workingEnvironments.get(workingEnvironmentOwnerKey(owner));
|
|
1496
1356
|
return snapshot ? structuredClone(snapshot) : null;
|
|
1497
1357
|
});
|
|
1498
1358
|
}
|
|
1499
1359
|
putWorkingEnvironmentSnapshot(owner, snapshot) {
|
|
1500
|
-
return
|
|
1360
|
+
return Effect3.sync(() => {
|
|
1501
1361
|
this.workingEnvironments.set(
|
|
1502
1362
|
workingEnvironmentOwnerKey(owner),
|
|
1503
1363
|
structuredClone(snapshot)
|
|
@@ -1505,23 +1365,23 @@ var MemoryFoundryDataAdapter = class {
|
|
|
1505
1365
|
});
|
|
1506
1366
|
}
|
|
1507
1367
|
putInboxItem(item) {
|
|
1508
|
-
return
|
|
1368
|
+
return Effect3.sync(() => {
|
|
1509
1369
|
this.inbox.set(item.id, Object.freeze({ ...item }));
|
|
1510
1370
|
});
|
|
1511
1371
|
}
|
|
1512
1372
|
listInboxItems(workspaceId) {
|
|
1513
|
-
return
|
|
1373
|
+
return Effect3.succeed([...this.inbox.values()].filter((item) => item.workspaceId === workspaceId));
|
|
1514
1374
|
}
|
|
1515
1375
|
putTask(task) {
|
|
1516
|
-
return
|
|
1376
|
+
return Effect3.sync(() => {
|
|
1517
1377
|
this.tasks.set(task.id, Object.freeze({ ...task }));
|
|
1518
1378
|
});
|
|
1519
1379
|
}
|
|
1520
1380
|
listTasks(workspaceId) {
|
|
1521
|
-
return
|
|
1381
|
+
return Effect3.succeed([...this.tasks.values()].filter((item) => item.workspaceId === workspaceId));
|
|
1522
1382
|
}
|
|
1523
1383
|
listEnvironment(scope) {
|
|
1524
|
-
return
|
|
1384
|
+
return Effect3.succeed(this.environment.filter(
|
|
1525
1385
|
(item) => item.workspaceId === scope.workspaceId && (item.scope === "workspace" || item.scope === "agent" && item.agentId === scope.agentId || item.scope === "conversation" && item.conversationId === scope.conversationId)
|
|
1526
1386
|
));
|
|
1527
1387
|
}
|
|
@@ -1676,7 +1536,7 @@ function agentScheduleRevision(schedule) {
|
|
|
1676
1536
|
|
|
1677
1537
|
// src/core-tools.ts
|
|
1678
1538
|
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
1679
|
-
import { Effect as
|
|
1539
|
+
import { Effect as Effect4, JSONSchema as JSONSchema2, Schema as Schema2 } from "effect";
|
|
1680
1540
|
import { z } from "zod";
|
|
1681
1541
|
|
|
1682
1542
|
// src/core-command-result.ts
|
|
@@ -2036,7 +1896,7 @@ function createFoundryCoreTools(context, desiredSchedules = []) {
|
|
|
2036
1896
|
};
|
|
2037
1897
|
const scheduleView = async () => {
|
|
2038
1898
|
const records = new Map(
|
|
2039
|
-
[...context.activations, ...await
|
|
1899
|
+
[...context.activations, ...await Effect4.runPromise(context.data.listActivations(context.workspaceId))].filter((item) => item.kind === "scheduled" && item.agentId === context.agentId).map((item) => [item.id, item])
|
|
2040
1900
|
);
|
|
2041
1901
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
2042
1902
|
for (const desired of desiredSchedules) {
|
|
@@ -2354,7 +2214,7 @@ function createFoundryCoreTools(context, desiredSchedules = []) {
|
|
|
2354
2214
|
description: "List the conversations owned by this runtime agent instance.",
|
|
2355
2215
|
inputSchema: z.object({}),
|
|
2356
2216
|
async do() {
|
|
2357
|
-
return { status: "success", data: await
|
|
2217
|
+
return { status: "success", data: await Effect4.runPromise(context.data.listConversations(context.agentId)) };
|
|
2358
2218
|
}
|
|
2359
2219
|
},
|
|
2360
2220
|
{
|
|
@@ -2367,12 +2227,12 @@ function createFoundryCoreTools(context, desiredSchedules = []) {
|
|
|
2367
2227
|
]),
|
|
2368
2228
|
async do(input) {
|
|
2369
2229
|
if (input.action === "get") {
|
|
2370
|
-
return { status: "success", data: await
|
|
2230
|
+
return { status: "success", data: await Effect4.runPromise(context.data.getWorkspaceEntry(context.workspaceId, input.key)) };
|
|
2371
2231
|
}
|
|
2372
2232
|
if (input.action === "list") {
|
|
2373
|
-
return { status: "success", data: await
|
|
2233
|
+
return { status: "success", data: await Effect4.runPromise(context.data.listWorkspaceEntries(context.workspaceId)) };
|
|
2374
2234
|
}
|
|
2375
|
-
await
|
|
2235
|
+
await Effect4.runPromise(context.data.putWorkspaceEntry({
|
|
2376
2236
|
workspaceId: context.workspaceId,
|
|
2377
2237
|
key: input.key,
|
|
2378
2238
|
value: input.value,
|
|
@@ -2401,13 +2261,13 @@ function createFoundryCoreTools(context, desiredSchedules = []) {
|
|
|
2401
2261
|
]),
|
|
2402
2262
|
async do(input) {
|
|
2403
2263
|
if (input.action === "list") {
|
|
2404
|
-
return { status: "success", data: await
|
|
2264
|
+
return { status: "success", data: await Effect4.runPromise(context.data.listInboxItems(context.workspaceId)) };
|
|
2405
2265
|
}
|
|
2406
2266
|
if (input.action === "update") {
|
|
2407
|
-
const current = (await
|
|
2267
|
+
const current = (await Effect4.runPromise(context.data.listInboxItems(context.workspaceId))).find((item3) => item3.id === input.itemId);
|
|
2408
2268
|
if (!current) return { status: "error", data: null, error: `Shared inbox item "${input.itemId}" was not found.` };
|
|
2409
2269
|
const item2 = { ...current, status: input.status, updatedAt: (/* @__PURE__ */ new Date()).toISOString() };
|
|
2410
|
-
await
|
|
2270
|
+
await Effect4.runPromise(context.data.putInboxItem(item2));
|
|
2411
2271
|
return { status: "success", data: item2 };
|
|
2412
2272
|
}
|
|
2413
2273
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -2422,7 +2282,7 @@ function createFoundryCoreTools(context, desiredSchedules = []) {
|
|
|
2422
2282
|
createdAt: now,
|
|
2423
2283
|
updatedAt: now
|
|
2424
2284
|
};
|
|
2425
|
-
await
|
|
2285
|
+
await Effect4.runPromise(context.data.putInboxItem(item));
|
|
2426
2286
|
return { status: "success", data: item };
|
|
2427
2287
|
}
|
|
2428
2288
|
},
|
|
@@ -2440,13 +2300,13 @@ function createFoundryCoreTools(context, desiredSchedules = []) {
|
|
|
2440
2300
|
]),
|
|
2441
2301
|
async do(input) {
|
|
2442
2302
|
if (input.action === "list") {
|
|
2443
|
-
return { status: "success", data: await
|
|
2303
|
+
return { status: "success", data: await Effect4.runPromise(context.data.listTasks(context.workspaceId)) };
|
|
2444
2304
|
}
|
|
2445
2305
|
if (input.action === "update") {
|
|
2446
|
-
const current = (await
|
|
2306
|
+
const current = (await Effect4.runPromise(context.data.listTasks(context.workspaceId))).find((task3) => task3.id === input.taskId);
|
|
2447
2307
|
if (!current) return { status: "error", data: null, error: `Task "${input.taskId}" was not found.` };
|
|
2448
2308
|
const task2 = { ...current, status: input.status, updatedAt: (/* @__PURE__ */ new Date()).toISOString() };
|
|
2449
|
-
await
|
|
2309
|
+
await Effect4.runPromise(context.data.putTask(task2));
|
|
2450
2310
|
return { status: "success", data: task2 };
|
|
2451
2311
|
}
|
|
2452
2312
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -2461,7 +2321,7 @@ function createFoundryCoreTools(context, desiredSchedules = []) {
|
|
|
2461
2321
|
createdAt: now,
|
|
2462
2322
|
updatedAt: now
|
|
2463
2323
|
};
|
|
2464
|
-
await
|
|
2324
|
+
await Effect4.runPromise(context.data.putTask(task));
|
|
2465
2325
|
return { status: "success", data: task };
|
|
2466
2326
|
}
|
|
2467
2327
|
},
|
|
@@ -2472,7 +2332,7 @@ function createFoundryCoreTools(context, desiredSchedules = []) {
|
|
|
2472
2332
|
async do() {
|
|
2473
2333
|
return {
|
|
2474
2334
|
status: "success",
|
|
2475
|
-
data: await
|
|
2335
|
+
data: await Effect4.runPromise(context.data.listEnvironment({
|
|
2476
2336
|
workspaceId: context.workspaceId,
|
|
2477
2337
|
agentId: context.agentId,
|
|
2478
2338
|
conversationId: context.conversationId
|
|
@@ -2716,15 +2576,6 @@ export {
|
|
|
2716
2576
|
mountAgentDefinitionMemory,
|
|
2717
2577
|
installRegistry,
|
|
2718
2578
|
isFoundryCapability,
|
|
2719
|
-
FOUNDRY_LAYER_BRAND,
|
|
2720
|
-
FOUNDRY_SUBSCRIBER_BRAND,
|
|
2721
|
-
defineLayer,
|
|
2722
|
-
configureLayer,
|
|
2723
|
-
defineSubscriber,
|
|
2724
|
-
EMPTY_NATIVE_REGISTRY,
|
|
2725
|
-
mountFoundrySurfaces,
|
|
2726
|
-
isFoundryLayer,
|
|
2727
|
-
isFoundrySubscriber,
|
|
2728
2579
|
composeAgent,
|
|
2729
2580
|
EMPTY_AGENT_COMPOSITION,
|
|
2730
2581
|
FOUNDRY_CONNECTION_BRAND,
|
|
@@ -81,8 +81,11 @@ var FoundryClient = class {
|
|
|
81
81
|
return fetcher(input, { ...init, headers });
|
|
82
82
|
} : fetcher;
|
|
83
83
|
}
|
|
84
|
+
/** Resolves with `ok: false` when a subsystem is down (the server answers 503). */
|
|
84
85
|
async health() {
|
|
85
|
-
|
|
86
|
+
const response = await this.fetcher(`${this.baseUrl}/health`);
|
|
87
|
+
if (response.status === 503) return await response.json();
|
|
88
|
+
return readResponse(response);
|
|
86
89
|
}
|
|
87
90
|
agent(route) {
|
|
88
91
|
return {
|