glove-foundry 0.5.0 → 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.
Files changed (39) hide show
  1. package/README.md +27 -15
  2. package/dist/{chunk-KBMD4RYU.js → chunk-6Q2LGPSC.js} +49 -198
  3. package/dist/{chunk-GKZLWD5M.js → chunk-7F7QVO6I.js} +4 -1
  4. package/dist/{chunk-SGF3CFUR.js → chunk-D2AHSYOB.js} +71 -8
  5. package/dist/{chunk-TH5ETCG2.js → chunk-MABLKZVO.js} +13 -4
  6. package/dist/{chunk-LW5PJ2FN.js → chunk-NHV64WNO.js} +1 -1
  7. package/dist/{chunk-5NFLGHOC.js → chunk-PVOKR4CN.js} +211 -29
  8. package/dist/cli.js +7 -5
  9. package/dist/{client-DcsnudMI.d.ts → client-CLTds1uV.d.ts} +13 -1
  10. package/dist/client.d.ts +1 -1
  11. package/dist/client.js +1 -1
  12. package/dist/execution-agent.js +4 -4
  13. package/dist/execution-daemon.js +1 -1
  14. package/dist/execution-loader.js +4 -4
  15. package/dist/index.d.ts +2 -2
  16. package/dist/index.js +14 -14
  17. package/docs/building-with-foundry.md +4 -2
  18. package/docs/release-verification.md +1 -1
  19. package/package.json +9 -9
  20. package/templates/minimal/README.md +34 -8
  21. package/templates/minimal/agents/assistant/agent.ts +24 -10
  22. package/templates/minimal/foundry.application.ts +11 -3
  23. package/templates/minimal/gitignore +1 -0
  24. package/templates/minimal/lib/file-store.ts +95 -0
  25. package/templates/travel-concierge/README.md +46 -12
  26. package/templates/travel-concierge/agents/concierge/agent.ts +10 -4
  27. package/templates/travel-concierge/agents/concierge/composition.ts +9 -2
  28. package/templates/travel-concierge/agents/concierge/flights.ts +43 -0
  29. package/templates/travel-concierge/agents/concierge/instances.ts +42 -0
  30. package/templates/travel-concierge/agents/concierge/memory/traveller.memory.ts +13 -8
  31. package/templates/travel-concierge/agents/concierge/tools/convert-currency.tool.ts +34 -0
  32. package/templates/travel-concierge/agents/concierge/workbench.ts +4 -1
  33. package/templates/travel-concierge/foundry.application.ts +15 -6
  34. package/templates/travel-concierge/gitignore +1 -0
  35. package/templates/travel-concierge/lib/demo-model.ts +89 -25
  36. package/templates/travel-concierge/lib/file-context.ts +60 -0
  37. package/templates/travel-concierge/lib/file-store.ts +95 -0
  38. package/templates/minimal/agents/assistant/tools/current-time.tool.ts +0 -17
  39. package/templates/travel-concierge/agents/concierge/tools/find-flights.tool.ts +0 -49
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { F as FoundryDataAdapter, E as EnvironmentValue, A as AgentInstance, C as Conversation, P as PlaybookSubscription, a as FoundryActivationRecord, b as ProvisionAgentOptions, I as InboundDeliveryClaim, W as WorkspaceEntry, c as FoundryWorkingEnvironmentSnapshotOwner, S as SharedInboxItem, d as FoundryTask, e as AgentPlaybook, f as FoundryRuntime, D as DiscoveredAgent, g as FoundryManifest, h as AnyFoundryTransmission, i as AccountReference, j as InferAccountMetadata, k as AgentBinding, l as FoundryAgentApplication, m as InboundRoute, O as OutboundRoute, n as CapabilityDefinition, o as InferInboundConfig, p as InferOutboundConfig } from './client-DcsnudMI.js';
2
- export { q as AccountContract, r as AccountDirectory, s as AccountFilter, t as AccountId, u as AccountNotFound, v as AccountSessionAdapter, w as AccountSessionRequest, x as AccountSessionUnavailable, y as AccountSummary, z as AgentApplicationContribution, B as AgentApplicationInstallContext, G as AgentApplicationOptions, H as AgentAssemblyContext, J as AgentAssemblyOptions, K as AgentDefinitionId, L as AgentDefinitionSurfaceContext, M as AgentFactoryContext, N as AgentHandlerContext, Q as AgentId, R as AgentInstallContext, T as AgentInstallation, U as AgentInstallationKind, V as AgentPlaybookInput, X as AgentProvisioningPolicy, Y as AgentRuntimeControls, Z as AnyFoundryAgent, _ as ApplicationConnectionContext, $ as ApplicationConnectionState, a0 as ApplicationConnectionStatus, a1 as BindingFilter, a2 as BindingId, a3 as BindingNotFound, a4 as CapabilityId, a5 as ComposedAgentPlaybook, a6 as ComposedAgentPlaybookInput, a7 as ConnectionReceiveInput, a8 as CreateAgentInstanceOptions, a9 as CreateConversationOptions, aa as CustomProvisionedAgent, ab as CustomProvisioningContext, ac as DefineAgentOptions, ad as DefineConnectionOptions, ae as DefineFoundryReplOptions, af as DefineFoundryScheduleOptions, ag as DefineFoundrySubagentOptions, ah as DefineFoundryWorkingEnvironmentOptions, ai as DefinePlaybookSubscriptionOptions, aj as DefinitionConfigInput, ak as EMPTY_AGENT_COMPOSITION, al as EMPTY_CAPABILITY_REGISTRY, am as EMPTY_FOUNDRY_APPLICATION, an as EMPTY_NATIVE_REGISTRY, ao as EgressAdapter, ap as EgressContext, aq as EventFilter, ar as EventId, as as EventNotFound, at as EventReference, au as EventStore, av as FOUNDRY_AGENT_APPLICATION_BRAND, aw as FOUNDRY_AGENT_BRAND, ax as FOUNDRY_AGENT_DEFINITION_BRAND, ay as FOUNDRY_AGENT_FILE_ENV, az as FOUNDRY_AGENT_ROUTE_ENV, aA as FOUNDRY_APPLICATION_BRAND, aB as FOUNDRY_APPLICATION_ENV, aC as FOUNDRY_APPROVAL_DIRECTORY_ENV, aD as FOUNDRY_COMPOSED_PLAYBOOK_BRAND, aE as FOUNDRY_CONNECTION_BRAND, aF as FOUNDRY_CORE_COMMAND_EVENT, aG as FOUNDRY_EVENT_PREFIX, aH as FOUNDRY_EXECUTION_MARKER, aI as FOUNDRY_LAYER_BRAND, aJ as FOUNDRY_MCP_BRAND, aK as FOUNDRY_MEMORY_BRAND, aL as FOUNDRY_PLAYBOOK_ACTION_BRAND, aM as FOUNDRY_REPL_BRAND, aN as FOUNDRY_SCHEDULE_BRAND, aO as FOUNDRY_SHARED_TOOL_BRAND, aP as FOUNDRY_SUBSCRIBER_BRAND, aQ as FOUNDRY_TRANSMISSION_BRAND, aR as FOUNDRY_TRANSMISSION_EVENT_BRAND, aS as FOUNDRY_TRANSMISSION_PREDICATE_BRAND, aT as FOUNDRY_WORKING_ENVIRONMENT_BRAND, aU as FoundryAccountSessionAdapter, aV as FoundryAgent, aW as FoundryAgentComponent, aX as FoundryAgentComposition, aY as FoundryAgentConventionModule, aZ as FoundryAgentDefinition, a_ as FoundryAgentMode, a$ as FoundryApp, b0 as FoundryApplication, b1 as FoundryApplicationConnection, b2 as FoundryApplicationManifest, b3 as FoundryApplicationOptions, b4 as FoundryApproval, b5 as FoundryApprovalDecision, b6 as FoundryApprovalDisplayManager, b7 as FoundryApprovalStatus, b8 as FoundryCall, b9 as FoundryCallContext, ba as FoundryCallOptions, bb as FoundryCapabilityKind, bc as FoundryCapabilityManifest, bd as FoundryCapabilityManifestEntry, be as FoundryCapabilityRegistry, bf as FoundryClient, bg as FoundryClientAuthorizationAdapter, bh as FoundryClientOptions, bi as FoundryCompositionSource, bj as FoundryConversationTranscript, bk as FoundryCoreCommand, bl as FoundryDomainError, bm as FoundryEvent, bn as FoundryEventCategory, bo as FoundryExecutionContext, bp as FoundryFactsOptions, bq as FoundryFormsOptions, br as FoundryGoalsOptions, bs as FoundryGuidanceHandles, bt as FoundryGuidanceScope, bu as FoundryHealth, bv as FoundryHookDefinition, bw as FoundryInstallable, bx as FoundryInstanceProvisioner, by as FoundryJavaScriptReplDefinition, bz as FoundryLayer, bA as FoundryLayerOptions, bB as FoundryLayerReference, bC as FoundryLayerSelection, bD as FoundryLispReplDefinition, bE as FoundryListResolver, bF as FoundryManifestAgent, bG as FoundryManifestCapability, bH as FoundryManifestTransmission, bI as FoundryMcp, bJ as FoundryMcpOptions, bK as FoundryMemoryProfile, bL as FoundryMemoryProfileOptions, bM as FoundryMemoryReference, bN as FoundryMemorySelection, bO as FoundryMeshConfig, bP as FoundryMessageInput, bQ as FoundryMountedRepl, bR as FoundryNativeManifest, bS as FoundryNativeManifestEntry, bT as FoundryNativeRegistry, bU as FoundryObservabilityAdapter, bV as FoundryPlaybookAction, bW as FoundryProgrammaticToolContext, bX as FoundryProgrammaticToolSelection, bY as FoundryProgrammaticTools, bZ as FoundryPythonReplDefinition, b_ as FoundryReplDefinition, b$ as FoundryRequest, c0 as FoundryRequestAuthorizationAdapter, c1 as FoundryRequestAuthorizationInput, c2 as FoundryResolvedMcp, c3 as FoundryResolver, c4 as FoundryResult, c5 as FoundryRouteMap, c6 as FoundryRun, c7 as FoundryRunHandle, c8 as FoundryRuntimeError, c9 as FoundryRuntimeOptions, ca as FoundryScheduleDefinition, cb as FoundryScheduleTiming, cc as FoundryScheduleTimingInput, cd as FoundrySharedTool, ce as FoundrySteerHandleResult, cf as FoundrySteerResult, cg as FoundrySubagentToolContext, ch as FoundrySubscriber, ci as FoundrySubscriberOptions, cj as FoundrySubscriberSelection, ck as FoundrySurfaceContext, cl as FoundryToolBody, cm as FoundryTransmission, cn as FoundryTransmissionEvent, co as FoundryTransmissionPredicate, cp as FoundryVfs, cq as FoundryVfsHandle, cr as FoundryWorkingEnvironmentCreateContext, cs as FoundryWorkingEnvironmentDefinition, ct as FoundryWorkingEnvironmentPersistenceAdapter, cu as FoundryWorkingEnvironmentPersistenceContext, cv as GrantResolutionError, cw as GrantResolver, cx as InboundContract, cy as InferAgentInput, cz as InferAgentOutput, cA as InferInboundEvent, cB as InferOutboundInput, cC as InferOutboundOutput, cD as IngressAdapter, cE as IngressContext, cF as InstallationSelection, cG as ManifestCompilationError, cH as McpAdapterFactory, cI as MemoryFoundryDataAdapter, cJ as MemoryObservabilityAdapter, cK as OutboundContract, cL as PlaybookActionOptions, cM as PlaybookDirective, cN as PlaybookDirectiveInput, cO as PlaybookMatch, cP as PlaybookMatchInput, cQ as PlaybookOutboundDirective, cR as PlaybookOutboundInput, cS as PlaybookSubscriptionTarget, cT as PlaybookSubscriptionTargetInput, cU as ReplyPolicy, cV as ResolveGrantRequest, cW as Route, cX as RouteFilter, cY as RouteId, cZ as RouteNotFound, c_ as RunGrant, c$ as RunId, d0 as SharedToolOptions, d1 as TopologyConflict, d2 as TopologyStore, d3 as TransmissionEventDirection, d4 as TransmissionEventOptions, d5 as TransmissionId, d6 as TransmissionOptions, d7 as TransmissionPredicateOptions, d8 as TransmissionSerializationContext, d9 as UpdateAgentInstanceOptions, da as UpdateConversationOptions, db as WaitOptions, dc as compileApplicationManifest, dd as composeAgent, de as composePlaybook, df as configureLayer, dg as configureMemory, dh as createAgentInstance, di as createConversation, dj as createFoundryApproval, dk as createFoundryClient, dl as createFoundryCoreTools, dm as createInstalledApplicationTransmissionTools, dn as createManifest, dp as defineAgent, dq as defineAgentApplication, dr as defineAgentFromModule, ds as defineAgentInstance, dt as defineApp, du as defineApplication, dv as defineCall, dw as defineConnection, dx as defineFacts, dy as defineForms, dz as defineGoals, dA as defineLayer, dB as defineMcp, dC as defineMemory, dD as definePlaybookAction, dE as definePlaybookSubscription, dF as defineRepl, dG as defineRoutes, dH as defineSchedule, dI as defineSharedTool, dJ as defineSubagent, dK as defineSubscriber, dL as defineTransmission, dM as defineTransmissionEvent, dN as defineTransmissionPredicate, dO as defineWorkingEnvironment, dP as discoverAgents, dQ as findAgentFiles, dR as foundryDataEnvironmentPersistence, dS as foundryGuidanceSubject, dT as grantResolverLive, dU as install, dV as installRegistry, dW as installationKey, dX as installedApplicationTransmissionToolName, dY as internalAgentName, dZ as isFoundryAgent, d_ as isFoundryAgentDefinition, d$ as isFoundryApplication, e0 as isFoundryCapability, e1 as isFoundryLayer, e2 as isFoundrySchedule, e3 as isFoundrySubscriber, e4 as isFoundryTransmission, e5 as isInboxCapableStore, e6 as listFoundryApprovals, e7 as memoryAccountDirectory, e8 as memoryEventStore, e9 as memoryTopologyStore, ea as mountAgentDefinitionMemory, eb as mountFoundrySurfaces, ec as reconstructAgentInstance, ed as reconstructPlaybook, ee as reconstructPlaybookSubscription, ef as resolveFoundryApproval, eg as routeFromAgentFile, eh as routeFromInternalAgentName, ei as toGloveMessage, ej as toGloveRequestInput, ek as transmissionPredicate, el as withFoundryPermissions } from './client-DcsnudMI.js';
1
+ import { F as FoundryDataAdapter, E as EnvironmentValue, A as AgentInstance, C as Conversation, P as PlaybookSubscription, a as FoundryActivationRecord, b as ProvisionAgentOptions, I as InboundDeliveryClaim, W as WorkspaceEntry, c as FoundryWorkingEnvironmentSnapshotOwner, S as SharedInboxItem, d as FoundryTask, e as AgentPlaybook, f as FoundryRuntime, D as DiscoveredAgent, g as FoundryManifest, h as AnyFoundryTransmission, i as AccountReference, j as InferAccountMetadata, k as AgentBinding, l as FoundryAgentApplication, m as InboundRoute, O as OutboundRoute, n as CapabilityDefinition, o as InferInboundConfig, p as InferOutboundConfig } from './client-CLTds1uV.js';
2
+ export { q as AccountContract, r as AccountDirectory, s as AccountFilter, t as AccountId, u as AccountNotFound, v as AccountSessionAdapter, w as AccountSessionRequest, x as AccountSessionUnavailable, y as AccountSummary, z as AgentApplicationContribution, B as AgentApplicationInstallContext, G as AgentApplicationOptions, H as AgentAssemblyContext, J as AgentAssemblyOptions, K as AgentDefinitionId, L as AgentDefinitionSurfaceContext, M as AgentFactoryContext, N as AgentHandlerContext, Q as AgentId, R as AgentInstallContext, T as AgentInstallation, U as AgentInstallationKind, V as AgentPlaybookInput, X as AgentProvisioningPolicy, Y as AgentRuntimeControls, Z as AnyFoundryAgent, _ as ApplicationConnectionContext, $ as ApplicationConnectionState, a0 as ApplicationConnectionStatus, a1 as BindingFilter, a2 as BindingId, a3 as BindingNotFound, a4 as CapabilityId, a5 as ComposedAgentPlaybook, a6 as ComposedAgentPlaybookInput, a7 as ConnectionReceiveInput, a8 as CreateAgentInstanceOptions, a9 as CreateConversationOptions, aa as CustomProvisionedAgent, ab as CustomProvisioningContext, ac as DefineAgentOptions, ad as DefineConnectionOptions, ae as DefineFoundryReplOptions, af as DefineFoundryScheduleOptions, ag as DefineFoundrySubagentOptions, ah as DefineFoundryWorkingEnvironmentOptions, ai as DefinePlaybookSubscriptionOptions, aj as DefinitionConfigInput, ak as EMPTY_AGENT_COMPOSITION, al as EMPTY_CAPABILITY_REGISTRY, am as EMPTY_FOUNDRY_APPLICATION, an as EMPTY_NATIVE_REGISTRY, ao as EgressAdapter, ap as EgressContext, aq as EventFilter, ar as EventId, as as EventNotFound, at as EventReference, au as EventStore, av as FOUNDRY_AGENT_APPLICATION_BRAND, aw as FOUNDRY_AGENT_BRAND, ax as FOUNDRY_AGENT_DEFINITION_BRAND, ay as FOUNDRY_AGENT_FILE_ENV, az as FOUNDRY_AGENT_ROUTE_ENV, aA as FOUNDRY_APPLICATION_BRAND, aB as FOUNDRY_APPLICATION_ENV, aC as FOUNDRY_APPROVAL_DIRECTORY_ENV, aD as FOUNDRY_COMPOSED_PLAYBOOK_BRAND, aE as FOUNDRY_CONNECTION_BRAND, aF as FOUNDRY_CORE_COMMAND_EVENT, aG as FOUNDRY_EVENT_PREFIX, aH as FOUNDRY_EXECUTION_MARKER, aI as FOUNDRY_LAYER_BRAND, aJ as FOUNDRY_MCP_BRAND, aK as FOUNDRY_MEMORY_BRAND, aL as FOUNDRY_PLAYBOOK_ACTION_BRAND, aM as FOUNDRY_REPL_BRAND, aN as FOUNDRY_SCHEDULE_BRAND, aO as FOUNDRY_SHARED_TOOL_BRAND, aP as FOUNDRY_SUBSCRIBER_BRAND, aQ as FOUNDRY_TRANSMISSION_BRAND, aR as FOUNDRY_TRANSMISSION_EVENT_BRAND, aS as FOUNDRY_TRANSMISSION_PREDICATE_BRAND, aT as FOUNDRY_WORKING_ENVIRONMENT_BRAND, aU as FoundryAccountSessionAdapter, aV as FoundryAgent, aW as FoundryAgentComponent, aX as FoundryAgentComposition, aY as FoundryAgentConventionModule, aZ as FoundryAgentDefinition, a_ as FoundryAgentMode, a$ as FoundryApp, b0 as FoundryApplication, b1 as FoundryApplicationConnection, b2 as FoundryApplicationManifest, b3 as FoundryApplicationOptions, b4 as FoundryApproval, b5 as FoundryApprovalDecision, b6 as FoundryApprovalDisplayManager, b7 as FoundryApprovalStatus, b8 as FoundryCall, b9 as FoundryCallContext, ba as FoundryCallOptions, bb as FoundryCapabilityKind, bc as FoundryCapabilityManifest, bd as FoundryCapabilityManifestEntry, be as FoundryCapabilityRegistry, bf as FoundryClient, bg as FoundryClientAuthorizationAdapter, bh as FoundryClientOptions, bi as FoundryCompositionSource, bj as FoundryConversationTranscript, bk as FoundryCoreCommand, bl as FoundryDomainError, bm as FoundryEvent, bn as FoundryEventCategory, bo as FoundryExecutionContext, bp as FoundryFactsOptions, bq as FoundryFormsOptions, br as FoundryGoalsOptions, bs as FoundryGuidanceHandles, bt as FoundryGuidanceScope, bu as FoundryHealth, bv as FoundryHookDefinition, bw as FoundryInstallable, bx as FoundryInstanceProvisioner, by as FoundryJavaScriptReplDefinition, bz as FoundryLayer, bA as FoundryLayerOptions, bB as FoundryLayerReference, bC as FoundryLayerSelection, bD as FoundryLispReplDefinition, bE as FoundryListResolver, bF as FoundryManifestAgent, bG as FoundryManifestCapability, bH as FoundryManifestTransmission, bI as FoundryMcp, bJ as FoundryMcpOptions, bK as FoundryMemoryProfile, bL as FoundryMemoryProfileOptions, bM as FoundryMemoryReference, bN as FoundryMemorySelection, bO as FoundryMeshConfig, bP as FoundryMessageInput, bQ as FoundryMountedRepl, bR as FoundryNativeManifest, bS as FoundryNativeManifestEntry, bT as FoundryNativeRegistry, bU as FoundryObservabilityAdapter, bV as FoundryPlaybookAction, bW as FoundryProgrammaticToolContext, bX as FoundryProgrammaticToolSelection, bY as FoundryProgrammaticTools, bZ as FoundryPythonReplDefinition, b_ as FoundryReplDefinition, b$ as FoundryRequest, c0 as FoundryRequestAuthorizationAdapter, c1 as FoundryRequestAuthorizationInput, c2 as FoundryResolvedMcp, c3 as FoundryResolver, c4 as FoundryResult, c5 as FoundryRouteMap, c6 as FoundryRun, c7 as FoundryRunHandle, c8 as FoundryRuntimeError, c9 as FoundryRuntimeOptions, ca as FoundryScheduleDefinition, cb as FoundryScheduleTiming, cc as FoundryScheduleTimingInput, cd as FoundrySharedTool, ce as FoundrySteerHandleResult, cf as FoundrySteerResult, cg as FoundrySubagentToolContext, ch as FoundrySubscriber, ci as FoundrySubscriberOptions, cj as FoundrySubscriberSelection, ck as FoundrySurfaceContext, cl as FoundryToolBody, cm as FoundryTransmission, cn as FoundryTransmissionEvent, co as FoundryTransmissionPredicate, cp as FoundryVfs, cq as FoundryVfsHandle, cr as FoundryWorkingEnvironmentCreateContext, cs as FoundryWorkingEnvironmentDefinition, ct as FoundryWorkingEnvironmentPersistenceAdapter, cu as FoundryWorkingEnvironmentPersistenceContext, cv as GrantResolutionError, cw as GrantResolver, cx as InboundContract, cy as InferAgentInput, cz as InferAgentOutput, cA as InferInboundEvent, cB as InferOutboundInput, cC as InferOutboundOutput, cD as IngressAdapter, cE as IngressContext, cF as InstallationSelection, cG as ManifestCompilationError, cH as McpAdapterFactory, cI as MemoryFoundryDataAdapter, cJ as MemoryObservabilityAdapter, cK as OutboundContract, cL as PlaybookActionOptions, cM as PlaybookDirective, cN as PlaybookDirectiveInput, cO as PlaybookMatch, cP as PlaybookMatchInput, cQ as PlaybookOutboundDirective, cR as PlaybookOutboundInput, cS as PlaybookSubscriptionTarget, cT as PlaybookSubscriptionTargetInput, cU as ReplyPolicy, cV as ResolveGrantRequest, cW as Route, cX as RouteFilter, cY as RouteId, cZ as RouteNotFound, c_ as RunGrant, c$ as RunId, d0 as SharedToolOptions, d1 as TopologyConflict, d2 as TopologyStore, d3 as TransmissionEventDirection, d4 as TransmissionEventOptions, d5 as TransmissionId, d6 as TransmissionOptions, d7 as TransmissionPredicateOptions, d8 as TransmissionSerializationContext, d9 as UpdateAgentInstanceOptions, da as UpdateConversationOptions, db as WaitOptions, dc as compileApplicationManifest, dd as composeAgent, de as composePlaybook, df as configureLayer, dg as configureMemory, dh as createAgentInstance, di as createConversation, dj as createFoundryApproval, dk as createFoundryClient, dl as createFoundryCoreTools, dm as createInstalledApplicationTransmissionTools, dn as createManifest, dp as defineAgent, dq as defineAgentApplication, dr as defineAgentFromModule, ds as defineAgentInstance, dt as defineApp, du as defineApplication, dv as defineCall, dw as defineConnection, dx as defineFacts, dy as defineForms, dz as defineGoals, dA as defineLayer, dB as defineMcp, dC as defineMemory, dD as definePlaybookAction, dE as definePlaybookSubscription, dF as defineRepl, dG as defineRoutes, dH as defineSchedule, dI as defineSharedTool, dJ as defineSubagent, dK as defineSubscriber, dL as defineTransmission, dM as defineTransmissionEvent, dN as defineTransmissionPredicate, dO as defineWorkingEnvironment, dP as discoverAgents, dQ as findAgentFiles, dR as foundryDataEnvironmentPersistence, dS as foundryGuidanceSubject, dT as grantResolverLive, dU as install, dV as installRegistry, dW as installationKey, dX as installedApplicationTransmissionToolName, dY as internalAgentName, dZ as isFoundryAgent, d_ as isFoundryAgentDefinition, d$ as isFoundryApplication, e0 as isFoundryCapability, e1 as isFoundryLayer, e2 as isFoundrySchedule, e3 as isFoundrySubscriber, e4 as isFoundryTransmission, e5 as isInboxCapableStore, e6 as listFoundryApprovals, e7 as memoryAccountDirectory, e8 as memoryEventStore, e9 as memoryTopologyStore, ea as mountAgentDefinitionMemory, eb as mountFoundrySurfaces, ec as reconstructAgentInstance, ed as reconstructPlaybook, ee as reconstructPlaybookSubscription, ef as resolveFoundryApproval, eg as routeFromAgentFile, eh as routeFromInternalAgentName, ei as toGloveMessage, ej as toGloveRequestInput, ek as transmissionPredicate, el as withFoundryPermissions } from './client-CLTds1uV.js';
3
3
  import { Effect } from 'effect';
4
4
  import { EnvSnapshot } from 'glove-working-environment';
5
5
  import { AddressInfo } from 'node:net';
package/dist/index.js CHANGED
@@ -43,12 +43,12 @@ import {
43
43
  memoryTopologyStore,
44
44
  serializeInboundTransmissionXml,
45
45
  writeGeneratedTypes
46
- } from "./chunk-SGF3CFUR.js";
46
+ } from "./chunk-D2AHSYOB.js";
47
47
  import {
48
48
  FoundryClient,
49
49
  FoundryRunHandle,
50
50
  createFoundryClient
51
- } from "./chunk-GKZLWD5M.js";
51
+ } from "./chunk-7F7QVO6I.js";
52
52
  import {
53
53
  defineConfig
54
54
  } from "./chunk-ZFNMFE3T.js";
@@ -63,25 +63,22 @@ import {
63
63
  defineWorkingEnvironment,
64
64
  foundryDataEnvironmentPersistence,
65
65
  foundryGuidanceSubject
66
- } from "./chunk-LW5PJ2FN.js";
66
+ } from "./chunk-NHV64WNO.js";
67
67
  import {
68
68
  EMPTY_AGENT_COMPOSITION,
69
69
  EMPTY_CAPABILITY_REGISTRY,
70
70
  EMPTY_FOUNDRY_APPLICATION,
71
- EMPTY_NATIVE_REGISTRY,
72
71
  FOUNDRY_AGENT_APPLICATION_BRAND,
73
72
  FOUNDRY_APPLICATION_BRAND,
74
73
  FOUNDRY_APPROVAL_DIRECTORY_ENV,
75
74
  FOUNDRY_COMPOSED_PLAYBOOK_BRAND,
76
75
  FOUNDRY_CONNECTION_BRAND,
77
76
  FOUNDRY_CORE_COMMAND_EVENT,
78
- FOUNDRY_LAYER_BRAND,
79
77
  FOUNDRY_MCP_BRAND,
80
78
  FOUNDRY_MEMORY_BRAND,
81
79
  FOUNDRY_PLAYBOOK_ACTION_BRAND,
82
80
  FOUNDRY_SCHEDULE_BRAND,
83
81
  FOUNDRY_SHARED_TOOL_BRAND,
84
- FOUNDRY_SUBSCRIBER_BRAND,
85
82
  FOUNDRY_TRANSMISSION_BRAND,
86
83
  FOUNDRY_TRANSMISSION_EVENT_BRAND,
87
84
  FOUNDRY_TRANSMISSION_PREDICATE_BRAND,
@@ -89,7 +86,6 @@ import {
89
86
  MemoryFoundryDataAdapter,
90
87
  composeAgent,
91
88
  composePlaybook,
92
- configureLayer,
93
89
  configureMemory,
94
90
  createAgentInstance,
95
91
  createConversation,
@@ -102,14 +98,12 @@ import {
102
98
  defineApp,
103
99
  defineApplication,
104
100
  defineConnection,
105
- defineLayer,
106
101
  defineMcp,
107
102
  defineMemory,
108
103
  definePlaybookAction,
109
104
  definePlaybookSubscription,
110
105
  defineSchedule,
111
106
  defineSharedTool,
112
- defineSubscriber,
113
107
  defineTransmission,
114
108
  defineTransmissionEvent,
115
109
  defineTransmissionPredicate,
@@ -121,14 +115,11 @@ import {
121
115
  installedApplicationTransmissionToolName,
122
116
  isFoundryApplication,
123
117
  isFoundryCapability,
124
- isFoundryLayer,
125
118
  isFoundrySchedule,
126
- isFoundrySubscriber,
127
119
  isFoundryTransmission,
128
120
  isInboxCapableStore,
129
121
  listFoundryApprovals,
130
122
  mountAgentDefinitionMemory,
131
- mountFoundrySurfaces,
132
123
  reconstructAgentInstance,
133
124
  reconstructPlaybook,
134
125
  reconstructPlaybookSubscription,
@@ -138,8 +129,9 @@ import {
138
129
  toGloveRequestInput,
139
130
  transmissionPredicate,
140
131
  withFoundryPermissions
141
- } from "./chunk-KBMD4RYU.js";
132
+ } from "./chunk-6Q2LGPSC.js";
142
133
  import {
134
+ EMPTY_NATIVE_REGISTRY,
143
135
  FOUNDRY_AGENT_BRAND,
144
136
  FOUNDRY_AGENT_DEFINITION_BRAND,
145
137
  FOUNDRY_AGENT_FILE_ENV,
@@ -147,16 +139,24 @@ import {
147
139
  FOUNDRY_APPLICATION_ENV,
148
140
  FOUNDRY_EVENT_PREFIX,
149
141
  FOUNDRY_EXECUTION_MARKER,
142
+ FOUNDRY_LAYER_BRAND,
143
+ FOUNDRY_SUBSCRIBER_BRAND,
144
+ configureLayer,
150
145
  defineAgent,
151
146
  defineAgentFromModule,
152
147
  defineCall,
148
+ defineLayer,
153
149
  defineRoutes,
154
150
  defineSubagent,
151
+ defineSubscriber,
155
152
  internalAgentName,
156
153
  isFoundryAgent,
157
154
  isFoundryAgentDefinition,
155
+ isFoundryLayer,
156
+ isFoundrySubscriber,
157
+ mountFoundrySurfaces,
158
158
  routeFromInternalAgentName
159
- } from "./chunk-5NFLGHOC.js";
159
+ } from "./chunk-PVOKR4CN.js";
160
160
 
161
161
  // src/file-data.ts
162
162
  import { randomUUID } from "node:crypto";
@@ -38,7 +38,7 @@ Native Glove media parts may include a human-facing `name`. A custom `run` handl
38
38
  persist or normalize those parts and then call `context.defaultRun(enrichedMessage)`
39
39
  to keep the standard Glove loop and conversation semantics.
40
40
 
41
- The generated project depends on the exact Glove versions the `glove-foundry` that created it was built against. That is not tidiness: a narrower range makes the package manager install a second copy of `glove-js`, and the two `JsSession` classes then fail to type-match.
41
+ The generated project depends on caret ranges of the Glove versions the `glove-foundry` that created it was built against (for example `^0.4.2` when it was built with `glove-js@0.4.2`). That is not tidiness: an older range makes the package manager install a second copy of `glove-js`, and the two `JsSession` classes then fail to type-match.
42
42
 
43
43
  ### Templates
44
44
 
@@ -63,11 +63,13 @@ A directory holding a Next.js app is detected, so `--target` is usually unnecess
63
63
  | `foundry/agents/**` | The agents |
64
64
  | `foundry/foundry.application.ts` | Data adapter, accounts, routes |
65
65
  | `foundry/package.json` | `{"type":"module"}`, scoping ESM to the agents |
66
+ | `foundry/lib/**` | The template's helpers, such as the durable transcript store |
67
+ | `foundry/.gitignore` | Ignores `foundry/.data/`, where runtime data, transcripts and memory are written |
66
68
  | `foundry.config.mts` | Points the runtime at `foundry/agents` |
67
69
  | `lib/foundry.ts` | A typed client your app imports |
68
70
  | `app/api/<agent>/route.ts` | An example route handler |
69
71
 
70
- Your `package.json` keeps its name, scripts, and dependencies; it gains `foundry:dev`, `foundry:start`, and the Glove packages. Nothing it already owns is overwritten.
72
+ Your `package.json` keeps its name, scripts, and unrelated dependencies; it gains `foundry:dev` and `foundry:start`. The Glove packages, `effect` and `zod` are set to the ranges this Foundry requires, replacing any version the app already declared (an app on `zod@3` is moved to `zod@4`). Every other file the app owns is left untouched; Foundry's runtime data goes to `foundry/.data/`, ignored by `foundry/.gitignore`.
71
73
 
72
74
  The runtime is a separate process from `next dev`, deliberately — it holds durable state and should not restart when a component changes. The app reaches it over HTTP through `lib/foundry.ts`, so no part of the agent graph is bundled into your app, and `FoundryRoutes` stays a type-only import.
73
75
 
@@ -38,7 +38,7 @@ The Glove Foundry and Glove skills guided integration against native primitives
38
38
 
39
39
  | Surface | Result |
40
40
  | --- | --- |
41
- | Entire publish build graph | Passed, including ordered legacy Glovebox dependencies; no publishing command run |
41
+ | Entire publish build graph | Passed; no publishing command run |
42
42
  | Foundry runtime suite | 80 passed, including real completed/cancelled worker process cleanup |
43
43
  | New initializer and existing scaffold tests | 11 passed; terminal policy, flags, piped setup, invalid options, Next.js preservation, versions, and all four package-manager dispatch paths |
44
44
  | Interactive terminal | Selected minimal starter and npm; confirmed generation; separately cancelled with Ctrl+C and verified no output directory |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "glove-foundry",
3
- "version": "0.5.0",
3
+ "version": "0.5.2",
4
4
  "description": "An Effect-native, file-routed framework for typed, observable Glove agent applications",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -72,15 +72,15 @@
72
72
  "station-client": "^3.0.0",
73
73
  "station-beacon": "^3.0.0",
74
74
  "station-broadcast": "^3.0.0",
75
- "glove-core": "4.2.0",
76
- "glove-facts": "0.1.3",
77
- "glove-memory": "2.2.1",
78
- "glove-lisp": "0.5.1",
79
- "glove-js": "0.5.1",
80
- "glove-mesh": "0.1.6",
81
- "glove-python": "0.4.1",
75
+ "glove-js": "0.5.2",
76
+ "glove-core": "4.3.0",
77
+ "glove-lisp": "0.5.2",
78
+ "glove-memory": "2.2.3",
79
+ "glove-facts": "0.1.4",
80
+ "glove-mcp": "1.2.2",
82
81
  "glove-working-environment": "0.7.0",
83
- "glove-mcp": "1.2.1"
82
+ "glove-python": "0.4.2",
83
+ "glove-mesh": "0.1.7"
84
84
  },
85
85
  "devDependencies": {
86
86
  "@types/node": "^25.2.3",
@@ -17,7 +17,9 @@ cp .env.example .env.local # add your OPENROUTER_API_KEY
17
17
 
18
18
  Then open **http://127.0.0.1:4141** and press **Start a run**.
19
19
 
20
- Choose **assistant**, send a short request, and open the run to inspect its events.
20
+ Choose **assistant**, ask "What time is it?", and open the run to inspect its events —
21
+ including the `current_time` tool call. Send a follow-up in the same conversation
22
+ (the **Chat** page is easiest): the assistant remembers the earlier turn.
21
23
  Edit `agents/assistant/agent.ts`, save, and run again. The dev server reloads your
22
24
  definition. Run `{{typecheckCommand}}` and `{{lintCommand}}` after changes.
23
25
 
@@ -26,14 +28,22 @@ yourself and restart the dev server. Do not commit the key. If a run fails, chec
26
28
  the trace for authentication or rate-limit errors. If port 4141 is occupied, use
27
29
  the local `glove foundry dev --port 4142` command.
28
30
 
29
- ## Before using real data
31
+ ## Where state lives
30
32
 
31
- The starter uses disposable in-memory storage. Configure durable Foundry runtime
32
- data, a durable Glove conversation store, native memory adapters, and VFS
33
- persistence independently. For a single host, Foundry includes
34
- `FileFoundryDataAdapter`; `glove-memory/sqlite` supports Node 22.13+. Use your own
35
- transactional adapters across hosts. A non-loopback listener requires an
33
+ Foundry runs every message in a fresh process, so nothing an agent needs on the
34
+ next message can live only in memory. The starter keeps it on disk under `.data/`
35
+ (git-ignored):
36
+
37
+ | What | Where | Wired in |
38
+ | --- | --- | --- |
39
+ | Instances, conversations, schedules, workspace data | `.data/foundry.json` | `foundry.application.ts` (`FileFoundryDataAdapter`) |
40
+ | Conversation transcripts | `.data/transcripts/` | `agents/assistant/agent.ts` (`store`, using `lib/file-store.ts`) |
41
+
42
+ State therefore survives the restart `{{devCommand}}` performs on every save. Delete
43
+ `.data/` to start fresh. Both adapters are single-host: use database-backed
44
+ adapters when several hosts share one runtime. A non-loopback listener requires an
36
45
  application-owned `requestAuthorization` adapter and a deliberate network boundary.
46
+ See https://glove.dterminal.net/foundry/docs/persistence.
37
47
 
38
48
  ## The one idea to understand first
39
49
 
@@ -58,7 +68,23 @@ Any file matching these names under an agent folder is discovered automatically.
58
68
  | `layers/*.layer.ts` | Native Glove setup | `defineLayer` |
59
69
  | `subscribers/*.subscriber.ts` | An observer | `defineSubscriber` |
60
70
 
61
- Create the file, add it to `composeAgent(...)`, and the dev server picks it up and regenerates types.
71
+ ### Two ways to add a tool
72
+
73
+ - **Every instance has it:** add a tool object to the agent's `tools` array, like
74
+ `current_time` in `agents/assistant/agent.ts`. Save, and the next run has it.
75
+ - **Instances opt in:** create `agents/assistant/tools/<name>.tool.ts` with
76
+ `defineSharedTool`, list it in the agent's `components: composeAgent(...)`, then
77
+ install it on an instance. Composing makes it *available*, not mounted:
78
+
79
+ ```bash
80
+ curl -X PUT http://127.0.0.1:4141/api/installations \
81
+ -H 'content-type: application/json' \
82
+ -d '{"agentId":"<instance-id>","kind":"tool","id":"<name>"}'
83
+ ```
84
+
85
+ You can also install with `install(...)` when creating an instance in code, or
86
+ `client.install(...)`. The inspector shows installations but does not change them.
87
+ Apps and MCP servers work the same way.
62
88
 
63
89
  Schedules are data, not auto-discovered file routes. You may keep a `defineSchedule`
64
90
  value in an ordinary colocated module and import it into the agent's lazy
@@ -1,28 +1,42 @@
1
- import { MemoryStore } from "glove-core";
2
1
  import { createAdapter } from "glove-core/models/providers";
3
- import { composeAgent, defineAgent } from "glove-foundry";
4
- import currentTime from "./tools/current-time.tool.js";
2
+ import { defineAgent } from "glove-foundry";
3
+ import { z } from "zod";
4
+ import { FileStore } from "../../lib/file-store.js";
5
5
 
6
6
  /**
7
7
  * The file path is the identity: this is the agent `assistant`.
8
8
  *
9
9
  * Every field may be a value or a function; a function is called per run with
10
- * the request context. Add capabilities as sibling files — `tools/*.tool.ts`,
11
- * `apps/*.app.ts`, `memory/*.memory.ts` — and compose them below.
10
+ * the request context. Each run executes in its own process, so state that must
11
+ * outlive one message — like the conversation below — lives on disk.
12
12
  */
13
13
  export default defineAgent({
14
14
  description: "A general-purpose Glove assistant",
15
- components: composeAgent(currentTime),
16
- store: ({ conversationId }) => new MemoryStore(`assistant:${conversationId}`),
17
15
  model: () => createAdapter({
18
16
  provider: "openrouter",
19
17
  model: process.env.OPENROUTER_MODEL ?? "openai/gpt-4.1-mini",
20
18
  stream: true,
21
19
  }),
22
- systemPrompt: (_agent, { message, history }) => [
20
+
21
+ // Durable history: without it the assistant forgets the previous message.
22
+ store: ({ conversationId }) => FileStore.open(conversationId),
23
+
24
+ systemPrompt: (_agent, { history }) => [
23
25
  "You are a precise, practical assistant.",
24
- `Current request: ${message.text}`,
25
- `Prior messages: ${history.length}`,
26
+ `Prior messages in this conversation: ${history.length}.`,
26
27
  ].join("\n"),
28
+
29
+ // Tools listed here are on every instance of this agent. To make a tool
30
+ // installable per instance instead, put it in tools/<name>.tool.ts with
31
+ // defineSharedTool, add it to composeAgent(...), and install it (see README).
32
+ tools: [{
33
+ name: "current_time",
34
+ description: "Return the current ISO timestamp",
35
+ inputSchema: z.object({}),
36
+ async do() {
37
+ return { status: "success", data: new Date().toISOString() };
38
+ },
39
+ }],
40
+
27
41
  compactionInstructions: () => "Preserve decisions, open work, and important context.",
28
42
  });
@@ -1,7 +1,15 @@
1
- import { MemoryFoundryDataAdapter, defineApplication } from "glove-foundry";
1
+ import { FileFoundryDataAdapter, defineApplication } from "glove-foundry";
2
+ import { fileURLToPath } from "node:url";
2
3
 
3
- /** Swap this adapter for your own to persist instances across restarts. */
4
- export const data = new MemoryFoundryDataAdapter();
4
+ /**
5
+ * Instances, conversations, schedules and workspace data are saved to
6
+ * `.data/foundry.json`, so they survive restarts — including the restart
7
+ * `dev` performs every time you save a file. Delete `.data/` to start fresh.
8
+ * Use a database-backed adapter when several hosts share one runtime.
9
+ */
10
+ export const data = new FileFoundryDataAdapter({
11
+ file: fileURLToPath(new URL("./.data/foundry.json", import.meta.url)),
12
+ });
5
13
 
6
14
  export default defineApplication({
7
15
  name: "{{projectName}}",
@@ -1,3 +1,4 @@
1
1
  node_modules
2
2
  .env.local
3
3
  .foundry/manifest.json
4
+ .data
@@ -0,0 +1,95 @@
1
+ import { createHash } from "node:crypto";
2
+ import { mkdir, readFile, rename, writeFile } from "node:fs/promises";
3
+ import { dirname, join } from "node:path";
4
+ import { fileURLToPath } from "node:url";
5
+ import {
6
+ MemoryStore,
7
+ type InboxItem,
8
+ type Message,
9
+ type Task,
10
+ type TokenConsumptionCounter,
11
+ } from "glove-core";
12
+
13
+ /** Transcripts live in `.data/transcripts`, beside this project's `lib` folder. */
14
+ const TRANSCRIPTS = fileURLToPath(new URL("../.data/transcripts/", import.meta.url));
15
+
16
+ interface SavedConversation {
17
+ readonly messages: Message[];
18
+ readonly turns: number;
19
+ readonly tokens: TokenConsumptionCounter;
20
+ readonly tasks: Task[];
21
+ readonly inbox: InboxItem[];
22
+ }
23
+
24
+ /**
25
+ * Foundry runs every message in a fresh process, so a plain `MemoryStore`
26
+ * would start each turn with no history. This one loads the conversation from
27
+ * a JSON file and rewrites it after every change.
28
+ *
29
+ * One host, one active run per conversation. Replace it with a database-backed
30
+ * StoreAdapter when several hosts share conversations.
31
+ */
32
+ export class FileStore extends MemoryStore {
33
+ private restoring = false;
34
+
35
+ private constructor(conversationId: string, private readonly file: string) {
36
+ super(conversationId);
37
+ }
38
+
39
+ static async open(conversationId: string, directory = TRANSCRIPTS): Promise<FileStore> {
40
+ const name = createHash("sha256").update(conversationId).digest("hex").slice(0, 32);
41
+ const store = new FileStore(conversationId, join(directory, `${name}.json`));
42
+ await store.restore();
43
+ return store;
44
+ }
45
+
46
+ private async restore(): Promise<void> {
47
+ let saved: SavedConversation;
48
+ try {
49
+ saved = JSON.parse(await readFile(this.file, "utf8")) as SavedConversation;
50
+ } catch (error) {
51
+ if ((error as NodeJS.ErrnoException).code === "ENOENT") return;
52
+ throw error;
53
+ }
54
+ this.restoring = true;
55
+ try {
56
+ await this.appendMessages(saved.messages);
57
+ await this.addTokens(saved.tokens);
58
+ for (let turn = 0; turn < saved.turns; turn++) await this.incrementTurn();
59
+ await this.addTasks(saved.tasks);
60
+ for (const item of saved.inbox) await this.addInboxItem(item);
61
+ } finally {
62
+ this.restoring = false;
63
+ }
64
+ }
65
+
66
+ private async save(): Promise<void> {
67
+ if (this.restoring) return;
68
+ const saved: SavedConversation = {
69
+ messages: await this.getMessages(),
70
+ turns: await this.getTurnCount(),
71
+ tokens: await this.getTokenConsumption(),
72
+ tasks: await this.getTasks(),
73
+ inbox: await this.getInboxItems(),
74
+ };
75
+ await mkdir(dirname(this.file), { recursive: true });
76
+ const temporary = `${this.file}.${process.pid}.tmp`;
77
+ await writeFile(temporary, JSON.stringify(saved));
78
+ await rename(temporary, this.file);
79
+ }
80
+
81
+ override async appendMessages(messages: Message[]) { await super.appendMessages(messages); await this.save(); }
82
+ override async addTokens(usage: TokenConsumptionCounter) { await super.addTokens(usage); await this.save(); }
83
+ override async incrementTurn() { await super.incrementTurn(); await this.save(); }
84
+ override async resetCounters() { await super.resetCounters(); await this.save(); }
85
+ override async addTasks(tasks: Task[]) { await super.addTasks(tasks); await this.save(); }
86
+ override async updateTask(id: string, updates: Partial<Pick<Task, "status" | "content" | "activeForm">>) {
87
+ await super.updateTask(id, updates);
88
+ await this.save();
89
+ }
90
+ override async addInboxItem(item: InboxItem) { await super.addInboxItem(item); await this.save(); }
91
+ override async updateInboxItem(id: string, updates: Partial<Pick<InboxItem, "status" | "response" | "resolved_at">>) {
92
+ await super.updateInboxItem(id, updates);
93
+ await this.save();
94
+ }
95
+ }
@@ -19,9 +19,15 @@ cp .env.example .env.local # optional: add OPENROUTER_API_KEY for real answe
19
19
  Then open **http://127.0.0.1:4141** and press **Start a run**.
20
20
 
21
21
  Choose **concierge** and send “Find a flight to Nairobi.” Open the resulting run
22
- to follow its model calls, tool calls and result. This is a deterministic demo:
23
- flights, calendar and messaging are examples, not live provider integrations.
24
- Change `agents/concierge/agent.ts`, save, and try another run to see the reload.
22
+ to follow its model calls, the `find_flights` tool call and the result. Send a
23
+ follow-up in the same conversation (the **Chat** page is easiest): the concierge
24
+ remembers the earlier turn. This is a deterministic demo: flights, calendar and
25
+ messaging are examples, not live provider integrations. Change
26
+ `agents/concierge/agent.ts`, save, and try another run to see the reload.
27
+
28
+ The run drawer creates a new instance by default. Pick **concierge-demo** instead
29
+ to use the seeded instance that has the calendar app and currency tool installed
30
+ and may reply over chat — see [Send it a chat message](#send-it-a-chat-message).
25
31
 
26
32
  To get live model answers, put your own `OPENROUTER_API_KEY` in `.env.local`, then
27
33
  restart the dev server. Never commit that file. The wizard does not collect keys.
@@ -33,7 +39,7 @@ Setting a model key does not connect a real calendar or messenger by itself.
33
39
  - Run `{{installCommand}}` again if installation was interrupted; project files are retained.
34
40
  - If port 4141 is occupied, run the local `glove foundry dev --port 4142` command and open that address.
35
41
  - If a run fails, open its event trace; a provider rate limit is different from a typecheck failure.
36
- - In-memory demo state resets across workers/restarts. Read **Going to production** before storing real user work.
42
+ - State lives in `.data/` and survives restarts. Delete `.data/` to start fresh (for example after renaming an installed tool). Read **Going to production** before storing real user work.
37
43
 
38
44
  ---
39
45
 
@@ -57,23 +63,28 @@ One definition serves many instances. Two travellers can run the same concierge
57
63
  ```
58
64
  agents/concierge/
59
65
  agent.ts the agent. start here
60
- composition.ts composeAgent(...) — what it is built from
61
- tools/find-flights.tool.ts a shared tool
66
+ composition.ts composeAgent(...) — the installable catalogue
67
+ flights.ts find_flights: always on, every instance
68
+ tools/convert-currency.tool.ts a shared tool an instance installs
62
69
  apps/calendar.app.ts an application an instance installs
70
+ instances.ts the seeded concierge-demo instance + its binding
63
71
  transmissions/messaging.transmission.ts Telegram/WhatsApp-shaped transport
64
72
  events/message-received.event.ts an inbound event
65
73
  events/message-sent.event.ts an outbound event
66
74
  predicates/mentions-trip.predicate.ts routing logic, kept out of the agent
67
- memory/traveller.memory.ts ambient context across conversations
75
+ memory/traveller.memory.ts ambient context, saved per instance
68
76
  schedules/trip-countdown.ts recurring work
69
77
  layers/trip-context.layer.ts direct access to the native Glove runtime
70
78
  subscribers/usage.subscriber.ts observation without behaviour change
71
- workbench.ts the agent's VFS + JavaScript REPL
79
+ workbench.ts the agent's VFS (persisted) + JavaScript REPL
72
80
  topology.ts accounts and routes (runtime data)
73
81
 
74
- foundry.application.ts data adapter, accounts, routes
82
+ foundry.application.ts data adapter, accounts, routes, bindings
75
83
  foundry.config.ts port, execution policy
76
84
  lib/demo-model.ts keyless model — delete once you have a key
85
+ lib/file-store.ts durable conversation transcripts
86
+ lib/file-context.ts durable traveller memory
87
+ .data/ runtime state (git-ignored). delete to reset
77
88
  src/client.ts a typed client for these agents
78
89
  .foundry/routes.d.ts generated. do not edit
79
90
  ```
@@ -105,7 +116,10 @@ Assembly fields such as tools, memory, and schedules accept **a value or a funct
105
116
 
106
117
  ### Add a tool
107
118
 
108
- Create `agents/concierge/tools/weather.tool.ts`, default-export `defineSharedTool({...})`, then add it to `composition.ts`. That is the whole loop — the dev server picks it up and regenerates types.
119
+ Two ways, depending on who should have it:
120
+
121
+ - **Every instance:** export a plain tool object and add it to the agent's `tools` field, like `find_flights` in `flights.ts`.
122
+ - **Instances that opt in:** create `agents/concierge/tools/weather.tool.ts`, default-export `defineSharedTool({...})`, add it to `composition.ts`, and install it on an instance (below), like `convert-currency`. Composing makes it available; installing mounts it.
109
123
 
110
124
  ### Add a second agent
111
125
 
@@ -113,7 +127,7 @@ Create `agents/<name>/agent.ts`. It is immediately routable, appears in the insp
113
127
 
114
128
  ### Give an instance a capability
115
129
 
116
- Applications and MCP servers stay inert until an instance installs one. From the inspector, open the instance and install `calendar`; or over the API:
130
+ Shared tools, applications and MCP servers stay inert until an instance installs them. `instances.ts` seeds `concierge-demo` with `convert-currency` and `calendar` installed. To install on another instance, use the API (the inspector shows installations but does not change them):
117
131
 
118
132
  ```bash
119
133
  curl -X PUT http://127.0.0.1:4141/api/installations \
@@ -121,6 +135,26 @@ curl -X PUT http://127.0.0.1:4141/api/installations \
121
135
  -d '{"agentId":"<instance-id>","kind":"application","id":"calendar","config":{"calendarId":"primary"}}'
122
136
  ```
123
137
 
138
+ ### Send it a chat message
139
+
140
+ The calendar app owns the messaging transmission, and `concierge-demo` has both the
141
+ app installed and a **binding** (in `instances.ts`) that lets it reply on the
142
+ outbound route. Its `traveller-chat` playbook is written onto the instance during
143
+ its first run, so send it one message first (Chat page, or **Start a run** with
144
+ `concierge-demo` selected). Then deliver an inbound chat message:
145
+
146
+ ```bash
147
+ curl -X POST http://127.0.0.1:4141/api/transmissions/traveller-inbound/fire \
148
+ -H 'content-type: application/json' \
149
+ -d '{"eventId":"evt-1","threadKey":"thread-42","raw":{"threadId":"thread-42","text":"Any flight to Nairobi in April?"}}'
150
+ ```
151
+
152
+ The message mentions a flight, so the playbook matches and starts a run. The agent
153
+ searches flights and replies through the generated `glove_app_calendar__messaging_send`
154
+ tool; the demo transport prints `[telegram] -> thread-42: …` in the terminal running
155
+ `{{devCommand}}`. An instance without the binding cannot send: delivery fails with
156
+ "agent has no enabled bindings".
157
+
124
158
  ### Connect a real chat app
125
159
 
126
160
  `transmissions/messaging.transmission.ts` has the shape; only `deliver` needs a real call.
@@ -190,7 +224,7 @@ Filters live in the URL, so `/runs?status=failed` is a link you can send. Press
190
224
 
191
225
  ## Going to production
192
226
 
193
- 1. **Persist each store.** `MemoryFoundryDataAdapter` in `foundry.application.ts` is disposable. Use `FileFoundryDataAdapter` for single-host runtime data or a transactional database adapter for multiple hosts. Also replace the agent's `MemoryStore` with a durable conversation store, provide durable native memory adapters (such as `glove-memory/sqlite` on Node 22.13+), and persist the working-environment VFS. Persisting one does not persist the others.
227
+ 1. **Choose where state lives.** Each run executes in its own process, so everything the next message needs is on disk under `.data/`: runtime data (`FileFoundryDataAdapter`), transcripts (`lib/file-store.ts`), traveller memory (`lib/file-context.ts`) and the VFS (`foundryDataEnvironmentPersistence`). These are single-host. For several hosts, replace each with a database-backed adapter — persisting one does not persist the others. See [Persistence](https://glove.dterminal.net/foundry/docs/persistence).
194
228
  2. **Delete `lib/demo-model.ts`** and the fallback in `agent.ts` once `OPENROUTER_API_KEY` is set.
195
229
  3. **Own your credentials.** Foundry stores account *references*, never secrets. Keep tokens in your own adapter or secret manager.
196
230
  4. **Run `{{startCommand}}`** rather than `dev` — no file watching, no restart-on-change.
@@ -1,12 +1,13 @@
1
- import { MemoryStore } from "glove-core";
2
1
  import { createAdapter } from "glove-core/models/providers";
3
2
  import { composePlaybook, defineAgent } from "glove-foundry";
4
3
  import { DemoModel } from "../../lib/demo-model.js";
4
+ import { FileStore } from "../../lib/file-store.js";
5
5
  import reply from "./actions/reply.action.js";
6
6
  import calendar from "./apps/calendar.app.js";
7
7
  import { conciergeComponents } from "./composition.js";
8
8
  import messageReceived from "./events/message-received.event.js";
9
9
  import messageSent from "./events/message-sent.event.js";
10
+ import { findFlights } from "./flights.js";
10
11
  import tripContext from "./layers/trip-context.layer.js";
11
12
  import travellerMemory from "./memory/traveller.memory.js";
12
13
  import mentionsTrip from "./predicates/mentions-trip.predicate.js";
@@ -67,15 +68,20 @@ export default defineAgent({
67
68
  tags: ["travel", "example"],
68
69
  components: conciergeComponents,
69
70
 
70
- // Persisted context, per conversation.
71
+ // Each run executes in its own process, so anything that must outlive one
72
+ // message lives on disk: the transcript here, traveller memory in memory/.
71
73
  memory: [travellerMemory],
72
- store: ({ conversationId }) => new MemoryStore(`concierge:${conversationId}`),
74
+ store: ({ conversationId }) => FileStore.open(conversationId),
73
75
  model,
74
76
 
77
+ // Always on: every instance can search flights. Installable capabilities
78
+ // (calendar, convert-currency) mount only where an instance installed them.
79
+ tools: [findFlights],
80
+
75
81
  // The prompt is built per run, so it can name what is actually mounted.
76
82
  systemPrompt: (_agent, { message, history, installations }) => [
77
83
  "You are a travel concierge. You are practical and you never invent bookings.",
78
- "Use find_flights for availability, and the calendar tools before proposing dates.",
84
+ "Use find_flights for availability, and the calendar tools (when installed) before proposing dates.",
79
85
  `Traveller asked: ${message.text}`,
80
86
  `Prior messages: ${history.length}.`,
81
87
  `Installed for this instance: ${installations.map((item) => `${item.kind}:${item.id}`).join(", ") || "nothing yet"}.`,