@dxos/compute 0.9.1-staging.ee54ba693a → 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/lib/AgentService.mjs +16 -0
- package/dist/lib/AgentService.mjs.map +1 -0
- package/dist/lib/StorageService.mjs +59 -0
- package/dist/lib/StorageService.mjs.map +1 -0
- package/dist/lib/chunk-OperationHandlerSet.mjs +660 -0
- package/dist/lib/chunk-OperationHandlerSet.mjs.map +1 -0
- package/dist/lib/chunk-definitions.mjs +41 -0
- package/dist/lib/chunk-definitions.mjs.map +1 -0
- package/dist/lib/chunk-rolldown-runtime.mjs +13 -0
- package/dist/lib/index.mjs +1576 -0
- package/dist/lib/index.mjs.map +1 -0
- package/dist/lib/testing.mjs +43 -0
- package/dist/lib/testing.mjs.map +1 -0
- package/dist/types/src/AgentIdentity.d.ts +27 -0
- package/dist/types/src/AgentIdentity.d.ts.map +1 -0
- package/dist/types/src/AgentService.d.ts +10 -2
- package/dist/types/src/AgentService.d.ts.map +1 -1
- package/dist/types/src/Cancellation.d.ts +19 -0
- package/dist/types/src/Cancellation.d.ts.map +1 -0
- package/dist/types/src/Credential.d.ts +41 -0
- package/dist/types/src/Credential.d.ts.map +1 -1
- package/dist/types/src/Operation.d.ts +79 -1
- package/dist/types/src/Operation.d.ts.map +1 -1
- package/dist/types/src/Process.d.ts +15 -3
- package/dist/types/src/Process.d.ts.map +1 -1
- package/dist/types/src/Trace.d.ts +55 -3
- package/dist/types/src/Trace.d.ts.map +1 -1
- package/dist/types/src/Trace.test.d.ts +2 -0
- package/dist/types/src/Trace.test.d.ts.map +1 -0
- package/dist/types/src/errors.d.ts +35 -1
- package/dist/types/src/errors.d.ts.map +1 -1
- package/dist/types/src/index.d.ts +3 -6
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/testing/index.d.ts +1 -0
- package/dist/types/src/testing/index.d.ts.map +1 -1
- package/dist/types/src/testing/operation.d.ts +5 -0
- package/dist/types/src/testing/operation.d.ts.map +1 -0
- package/dist/types/src/{Instructions.d.ts → types/Instructions.d.ts} +14 -1
- package/dist/types/src/types/Instructions.d.ts.map +1 -0
- package/dist/types/src/types/Instructions.test.d.ts +2 -0
- package/dist/types/src/types/Instructions.test.d.ts.map +1 -0
- package/dist/types/src/types/Project.d.ts +53 -0
- package/dist/types/src/types/Project.d.ts.map +1 -0
- package/dist/types/src/types/Project.test.d.ts +2 -0
- package/dist/types/src/types/Project.test.d.ts.map +1 -0
- package/dist/types/src/types/Routine.d.ts +42 -0
- package/dist/types/src/types/Routine.d.ts.map +1 -0
- package/dist/types/src/types/Routine.test.d.ts +2 -0
- package/dist/types/src/types/Routine.test.d.ts.map +1 -0
- package/dist/types/src/types/Script.d.ts.map +1 -0
- package/dist/types/src/{Skill.d.ts → types/Skill.d.ts} +1 -1
- package/dist/types/src/types/Skill.d.ts.map +1 -0
- package/dist/types/src/{Template.d.ts → types/Template.d.ts} +2 -2
- package/dist/types/src/types/Template.d.ts.map +1 -0
- package/dist/types/src/types/Template.test.d.ts.map +1 -0
- package/dist/types/src/types/Trigger.d.ts +249 -0
- package/dist/types/src/types/Trigger.d.ts.map +1 -0
- package/dist/types/src/{TriggerEvent.d.ts → types/TriggerEvent.d.ts} +19 -6
- package/dist/types/src/types/TriggerEvent.d.ts.map +1 -0
- package/dist/types/src/types/index.d.ts +9 -0
- package/dist/types/src/types/index.d.ts.map +1 -0
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +18 -17
- package/src/AgentIdentity.ts +35 -0
- package/src/AgentService.ts +10 -2
- package/src/Cancellation.ts +33 -0
- package/src/Credential.ts +52 -0
- package/src/Operation.ts +92 -2
- package/src/Process.ts +21 -4
- package/src/Trace.test.ts +155 -0
- package/src/Trace.ts +207 -6
- package/src/errors.ts +9 -5
- package/src/index.ts +3 -6
- package/src/testing/index.ts +1 -0
- package/src/testing/operation.ts +21 -0
- package/src/types/Instructions.test.ts +18 -0
- package/src/{Instructions.ts → types/Instructions.ts} +22 -1
- package/src/types/Project.test.ts +52 -0
- package/src/types/Project.ts +99 -0
- package/src/types/Routine.test.ts +18 -0
- package/src/types/Routine.ts +85 -0
- package/src/{Skill.ts → types/Skill.ts} +2 -2
- package/src/{Template.test.ts → types/Template.test.ts} +2 -2
- package/src/{Template.ts → types/Template.ts} +2 -2
- package/src/{Trigger.ts → types/Trigger.ts} +126 -8
- package/src/{TriggerEvent.ts → types/TriggerEvent.ts} +23 -5
- package/src/types/index.ts +12 -0
- package/dist/lib/neutral/AgentService.mjs +0 -12
- package/dist/lib/neutral/AgentService.mjs.map +0 -7
- package/dist/lib/neutral/StorageService.mjs +0 -22
- package/dist/lib/neutral/StorageService.mjs.map +0 -7
- package/dist/lib/neutral/chunk-2ZN64ZS7.mjs +0 -25
- package/dist/lib/neutral/chunk-2ZN64ZS7.mjs.map +0 -7
- package/dist/lib/neutral/chunk-5VAXF6AH.mjs +0 -53
- package/dist/lib/neutral/chunk-5VAXF6AH.mjs.map +0 -7
- package/dist/lib/neutral/chunk-EVROJER7.mjs +0 -285
- package/dist/lib/neutral/chunk-EVROJER7.mjs.map +0 -7
- package/dist/lib/neutral/chunk-J5LGTIGS.mjs +0 -10
- package/dist/lib/neutral/chunk-J5LGTIGS.mjs.map +0 -7
- package/dist/lib/neutral/chunk-PF7XP7XP.mjs +0 -62
- package/dist/lib/neutral/chunk-PF7XP7XP.mjs.map +0 -7
- package/dist/lib/neutral/chunk-SJ37RWHU.mjs +0 -21
- package/dist/lib/neutral/chunk-SJ37RWHU.mjs.map +0 -7
- package/dist/lib/neutral/chunk-VSAZPWSJ.mjs +0 -25
- package/dist/lib/neutral/chunk-VSAZPWSJ.mjs.map +0 -7
- package/dist/lib/neutral/chunk-WEO4FCQY.mjs +0 -17
- package/dist/lib/neutral/chunk-WEO4FCQY.mjs.map +0 -7
- package/dist/lib/neutral/chunk-Z3Y7FQGN.mjs +0 -174
- package/dist/lib/neutral/chunk-Z3Y7FQGN.mjs.map +0 -7
- package/dist/lib/neutral/fib-5XIYECL5.mjs +0 -10
- package/dist/lib/neutral/fib-5XIYECL5.mjs.map +0 -7
- package/dist/lib/neutral/index.mjs +0 -1232
- package/dist/lib/neutral/index.mjs.map +0 -7
- package/dist/lib/neutral/meta.json +0 -1
- package/dist/lib/neutral/reply-GCBRCUVM.mjs +0 -10
- package/dist/lib/neutral/reply-GCBRCUVM.mjs.map +0 -7
- package/dist/lib/neutral/sleep-XR6CL6W3.mjs +0 -10
- package/dist/lib/neutral/sleep-XR6CL6W3.mjs.map +0 -7
- package/dist/lib/neutral/testing/index.mjs +0 -32
- package/dist/lib/neutral/testing/index.mjs.map +0 -7
- package/dist/types/src/Instructions.d.ts.map +0 -1
- package/dist/types/src/Script.d.ts.map +0 -1
- package/dist/types/src/Skill.d.ts.map +0 -1
- package/dist/types/src/Template.d.ts.map +0 -1
- package/dist/types/src/Template.test.d.ts.map +0 -1
- package/dist/types/src/Trigger.d.ts +0 -157
- package/dist/types/src/Trigger.d.ts.map +0 -1
- package/dist/types/src/TriggerEvent.d.ts.map +0 -1
- /package/dist/types/src/{Script.d.ts → types/Script.d.ts} +0 -0
- /package/dist/types/src/{Template.test.d.ts → types/Template.test.d.ts} +0 -0
- /package/src/{Script.ts → types/Script.ts} +0 -0
|
@@ -0,0 +1,1576 @@
|
|
|
1
|
+
import { t as __exportAll } from "./chunk-rolldown-runtime.mjs";
|
|
2
|
+
import { C as RunAgainError, S as NoHandlerError, T as TriggerStateNotFoundError, _ as FunctionsAiMemoizationMissError, b as InvalidOperationOutputError, c as PersistentOperation, d as invoke, f as isIdempotent, g as FunctionNotFoundError, h as FunctionError, i as getHandlerByKey, n as OperationHandlerSet_exports, o as NotifyOptions, r as getHandler, s as Operation_exports, t as OperationHandlerProvider, u as deserialize, v as FunctionsAiUpstreamError, w as ServiceNotAvailableError, x as InvokerNotInitializedError, y as InvalidOperationInputError } from "./chunk-OperationHandlerSet.mjs";
|
|
3
|
+
import { t as AgentService_exports } from "./AgentService.mjs";
|
|
4
|
+
import { cell, t as StorageService_exports, withDefault } from "./StorageService.mjs";
|
|
5
|
+
import { BaseError } from "@dxos/errors";
|
|
6
|
+
import * as Schema from "effect/Schema";
|
|
7
|
+
import { Annotation, Collection, DXN, Database, Feed, Filter, Format, JsonSchema, Obj, Query, QueryAST, Ref, Registry, Type, URI } from "@dxos/echo";
|
|
8
|
+
import { Text } from "@dxos/schema";
|
|
9
|
+
import * as Effect from "effect/Effect";
|
|
10
|
+
import { ToolId } from "@dxos/ai";
|
|
11
|
+
import { assertArgument, invariant } from "@dxos/invariant";
|
|
12
|
+
import { log } from "@dxos/log";
|
|
13
|
+
import Handlebars from "@dxos/vendor-kbn-handlebars";
|
|
14
|
+
import * as Context from "effect/Context";
|
|
15
|
+
import * as Layer from "effect/Layer";
|
|
16
|
+
import * as Option from "effect/Option";
|
|
17
|
+
import * as SchemaAST from "effect/SchemaAST";
|
|
18
|
+
import { FormInlineAnnotation, FormInputAnnotation, HiddenAnnotation, LabelAnnotation } from "@dxos/echo/Annotation";
|
|
19
|
+
import { OptionsAnnotationId } from "@dxos/echo/Format";
|
|
20
|
+
import { Outline, TaskSet } from "@dxos/types";
|
|
21
|
+
import { LabelAnnotation as LabelAnnotation$1 } from "@dxos/echo/internal";
|
|
22
|
+
import * as Redacted from "effect/Redacted";
|
|
23
|
+
import * as HttpClient from "@effect/platform/HttpClient";
|
|
24
|
+
import * as HttpClientRequest from "@effect/platform/HttpClientRequest";
|
|
25
|
+
import { BYOK_HEADER } from "@dxos/protocols";
|
|
26
|
+
import { DXN as DXN$1, EID, URI as URI$1 } from "@dxos/keys";
|
|
27
|
+
import * as RpcGroup from "@effect/rpc/RpcGroup";
|
|
28
|
+
import * as Either from "effect/Either";
|
|
29
|
+
//#region src/McpServer.ts
|
|
30
|
+
var McpServer_exports = /* @__PURE__ */ __exportAll({ McpServer: () => McpServer });
|
|
31
|
+
/**
|
|
32
|
+
* MCP server connection spec — the minimal fields needed to dial an MCP server.
|
|
33
|
+
*
|
|
34
|
+
* Used as a value type embedded in skills and passed to runtime session connect logic.
|
|
35
|
+
* The user-facing ECHO object (`@dxos/assistant-toolkit` `McpServer`) composes this struct
|
|
36
|
+
* and adds instance-level fields (`name`, `enabled`) and ECHO annotations.
|
|
37
|
+
*/
|
|
38
|
+
var McpServer = Schema.Struct({
|
|
39
|
+
name: Schema.String.pipe(Schema.optional).annotations({ description: "Human-readable name of the MCP server" }),
|
|
40
|
+
url: Schema.String.annotations({ description: "URL of the MCP server" }),
|
|
41
|
+
/**
|
|
42
|
+
* Transport protocol. Prefer `'http'` (Streamable HTTP) for new servers; `'sse'` is
|
|
43
|
+
* kept for compatibility with servers that haven't migrated and is deprecated per
|
|
44
|
+
* the MCP SDK. Clients support both during the migration period.
|
|
45
|
+
*/
|
|
46
|
+
protocol: Schema.Union(Schema.Literal("http"), Schema.Literal("sse")).annotations({ description: "Transport protocol of the MCP server (prefer \"http\"; \"sse\" deprecated)" }),
|
|
47
|
+
/**
|
|
48
|
+
* Optional API key sent with requests.
|
|
49
|
+
* Persisted in plaintext when stored on a space-replicated ECHO object — see the
|
|
50
|
+
* `@dxos/assistant-toolkit` `McpServer` type for security implications.
|
|
51
|
+
*/
|
|
52
|
+
apiKey: Schema.optional(Schema.String).annotations({ description: "Optional API key sent with requests" })
|
|
53
|
+
});
|
|
54
|
+
//#endregion
|
|
55
|
+
//#region src/types/Template.ts
|
|
56
|
+
var Template_exports = /* @__PURE__ */ __exportAll({
|
|
57
|
+
Input: () => Input,
|
|
58
|
+
InputKind: () => InputKind,
|
|
59
|
+
Template: () => Template,
|
|
60
|
+
make: () => make$9,
|
|
61
|
+
process: () => process,
|
|
62
|
+
processTemplate: () => processTemplate
|
|
63
|
+
});
|
|
64
|
+
var __dxlog_file$2 = "/__w/dxos/dxos/packages/core/compute/compute/src/types/Template.ts";
|
|
65
|
+
/**
|
|
66
|
+
* Template input kind determines how template variables are resolved.
|
|
67
|
+
*/
|
|
68
|
+
var InputKind = Schema.Literal("value", "operation");
|
|
69
|
+
/**
|
|
70
|
+
* Template input variable.
|
|
71
|
+
* E.g., {{foo}}
|
|
72
|
+
*/
|
|
73
|
+
var Input = Schema.Struct({
|
|
74
|
+
name: Schema.String,
|
|
75
|
+
kind: InputKind,
|
|
76
|
+
default: Schema.optional(Schema.Any),
|
|
77
|
+
/**
|
|
78
|
+
* Operation key invoked when `kind === 'operation'`. The referenced operation must accept void input —
|
|
79
|
+
* template inputs have no mechanism for passing arguments.
|
|
80
|
+
*/
|
|
81
|
+
operation: Schema.optional(Schema.String)
|
|
82
|
+
});
|
|
83
|
+
/**
|
|
84
|
+
* Template type.
|
|
85
|
+
*/
|
|
86
|
+
var Template = Schema.Struct({
|
|
87
|
+
source: Ref.Ref(Text.Text).annotations({ description: "Markdown + Handlebars template." }),
|
|
88
|
+
/**
|
|
89
|
+
* NOTE: We use an array rather than map so that updating variable names in the template doesn't disconnect existing inputs.
|
|
90
|
+
*/
|
|
91
|
+
inputs: Schema.optional(Schema.Array(Input))
|
|
92
|
+
});
|
|
93
|
+
var make$9 = ({ id, source, inputs = [] } = {}) => ({
|
|
94
|
+
source: Ref.make(Text.make({
|
|
95
|
+
id,
|
|
96
|
+
content: source
|
|
97
|
+
})),
|
|
98
|
+
inputs
|
|
99
|
+
});
|
|
100
|
+
/**
|
|
101
|
+
* Process Handlebars template.
|
|
102
|
+
*/
|
|
103
|
+
var process = (source, variables = {}) => {
|
|
104
|
+
assertArgument(typeof source === "string", "source");
|
|
105
|
+
let section = 0;
|
|
106
|
+
const handlebars = Handlebars.create();
|
|
107
|
+
handlebars.registerHelper("section", () => String(++section));
|
|
108
|
+
return handlebars.compileAST(source.trim())(variables).trim().replace(/(\n\s*){3,}/g, "\n\n");
|
|
109
|
+
};
|
|
110
|
+
var processTemplate = (template) => Effect.gen(function* () {
|
|
111
|
+
const entries = yield* Effect.forEach(template.inputs ?? [], (input) => Effect.gen(function* () {
|
|
112
|
+
switch (input.kind) {
|
|
113
|
+
case "value": return [input.name, input.default];
|
|
114
|
+
case "operation": {
|
|
115
|
+
invariant(input.operation, void 0, {
|
|
116
|
+
"~LogMeta": "~LogMeta",
|
|
117
|
+
F: __dxlog_file$2,
|
|
118
|
+
L: 99,
|
|
119
|
+
S: this,
|
|
120
|
+
A: ["input.operation", ""]
|
|
121
|
+
});
|
|
122
|
+
const key = DXN.isDXN(input.operation) ? input.operation : `dxn:${input.operation}`;
|
|
123
|
+
const results = yield* Registry.runQuery(Filter.and(Filter.type(PersistentOperation), Filter.key(key)));
|
|
124
|
+
if (results.length === 0) return yield* Effect.fail(new FunctionNotFoundError(input.operation));
|
|
125
|
+
const result = yield* invoke(deserialize(results[0]), void 0).pipe(Effect.orDie);
|
|
126
|
+
return [input.name, result];
|
|
127
|
+
}
|
|
128
|
+
default: return yield* Effect.dieMessage(`Unsupported input kind: ${input.kind}`);
|
|
129
|
+
}
|
|
130
|
+
}));
|
|
131
|
+
const variables = Object.fromEntries(entries);
|
|
132
|
+
log("processTemplate", { variables }, {
|
|
133
|
+
"~LogMeta": "~LogMeta",
|
|
134
|
+
F: __dxlog_file$2,
|
|
135
|
+
L: 124,
|
|
136
|
+
S: this
|
|
137
|
+
});
|
|
138
|
+
return process((yield* Database.load(template.source)).content, variables);
|
|
139
|
+
});
|
|
140
|
+
//#endregion
|
|
141
|
+
//#region src/Runnable.ts
|
|
142
|
+
var Runnable_exports = /* @__PURE__ */ __exportAll({ Runnable: () => Runnable });
|
|
143
|
+
var Runnable = PersistentOperation;
|
|
144
|
+
//#endregion
|
|
145
|
+
//#region src/types/Trigger.ts
|
|
146
|
+
var Trigger_exports = /* @__PURE__ */ __exportAll({
|
|
147
|
+
DirectSpec: () => DirectSpec,
|
|
148
|
+
EmailSpec: () => EmailSpec,
|
|
149
|
+
FeedSpec: () => FeedSpec,
|
|
150
|
+
InputTemplate: () => InputTemplate,
|
|
151
|
+
Kinds: () => Kinds$1,
|
|
152
|
+
Spec: () => Spec,
|
|
153
|
+
SubscriptionSpec: () => SubscriptionSpec,
|
|
154
|
+
TimerSpec: () => TimerSpec,
|
|
155
|
+
Trigger: () => Trigger,
|
|
156
|
+
TriggerMonitorService: () => TriggerMonitorService,
|
|
157
|
+
WebhookSpec: () => WebhookSpec,
|
|
158
|
+
isManuallyInvokable: () => isManuallyInvokable,
|
|
159
|
+
make: () => make$8,
|
|
160
|
+
specDirect: () => specDirect,
|
|
161
|
+
specEmail: () => specEmail,
|
|
162
|
+
specFeed: () => specFeed,
|
|
163
|
+
specSubscription: () => specSubscription,
|
|
164
|
+
specTimer: () => specTimer,
|
|
165
|
+
specWebhook: () => specWebhook
|
|
166
|
+
});
|
|
167
|
+
/**
|
|
168
|
+
* Type discriminator for TriggerType.
|
|
169
|
+
* Every spec has a type field of type TriggerKind that we can use to understand which type we're working with.
|
|
170
|
+
* https://www.typescriptlang.org/docs/handbook/2/narrowing.html#discriminated-unions
|
|
171
|
+
*/
|
|
172
|
+
var Kinds$1 = [
|
|
173
|
+
"email",
|
|
174
|
+
"feed",
|
|
175
|
+
"direct",
|
|
176
|
+
"subscription",
|
|
177
|
+
"timer",
|
|
178
|
+
"webhook"
|
|
179
|
+
];
|
|
180
|
+
var kindLiteralAnnotations = { title: "Kind" };
|
|
181
|
+
var EmailSpec = Schema.Struct({ kind: Schema.Literal("email").annotations(kindLiteralAnnotations) });
|
|
182
|
+
/**
|
|
183
|
+
* Construct an Email trigger spec.
|
|
184
|
+
*/
|
|
185
|
+
var specEmail = () => ({ kind: "email" });
|
|
186
|
+
var FeedSpec = Schema.Struct({
|
|
187
|
+
kind: Schema.Literal("feed").annotations(kindLiteralAnnotations),
|
|
188
|
+
feed: Schema.optional(Ref.Ref(Feed.Feed).annotations({ title: "Feed" }))
|
|
189
|
+
});
|
|
190
|
+
/**
|
|
191
|
+
* Construct a Feed trigger spec from a Feed object.
|
|
192
|
+
*/
|
|
193
|
+
var specFeed = (feed) => ({
|
|
194
|
+
kind: "feed",
|
|
195
|
+
feed: Ref.make(feed)
|
|
196
|
+
});
|
|
197
|
+
/**
|
|
198
|
+
* Subscription.
|
|
199
|
+
*/
|
|
200
|
+
var SubscriptionSpec = Schema.Struct({
|
|
201
|
+
kind: Schema.Literal("subscription").annotations(kindLiteralAnnotations),
|
|
202
|
+
query: Schema.Struct({
|
|
203
|
+
raw: Schema.optional(Schema.String.annotations({ title: "Query" })),
|
|
204
|
+
ast: QueryAST.Query
|
|
205
|
+
}),
|
|
206
|
+
options: Schema.optional(Schema.Struct({
|
|
207
|
+
deep: Schema.optional(Schema.Boolean.annotations({ title: "Nested" })),
|
|
208
|
+
delay: Schema.optional(Schema.Number.annotations({ title: "Delay" }))
|
|
209
|
+
}).annotations({ title: "Options" }))
|
|
210
|
+
});
|
|
211
|
+
/**
|
|
212
|
+
* Construct a Subscription trigger spec from a Query object.
|
|
213
|
+
*/
|
|
214
|
+
var specSubscription = (query, options) => ({
|
|
215
|
+
kind: "subscription",
|
|
216
|
+
query: { ast: query.ast },
|
|
217
|
+
options: options ? {
|
|
218
|
+
deep: options.deep,
|
|
219
|
+
delay: options.delay
|
|
220
|
+
} : void 0
|
|
221
|
+
});
|
|
222
|
+
/**
|
|
223
|
+
* Direct invocation only; never scheduled by the dispatcher (invoked on demand by a caller).
|
|
224
|
+
*/
|
|
225
|
+
var DirectSpec = Schema.Struct({ kind: Schema.Literal("direct").annotations(kindLiteralAnnotations) });
|
|
226
|
+
/**
|
|
227
|
+
* Construct a Direct trigger spec.
|
|
228
|
+
*/
|
|
229
|
+
var specDirect = () => ({ kind: "direct" });
|
|
230
|
+
/**
|
|
231
|
+
* Cron timer.
|
|
232
|
+
*/
|
|
233
|
+
var TimerSpec = Schema.Struct({
|
|
234
|
+
kind: Schema.Literal("timer").annotations(kindLiteralAnnotations),
|
|
235
|
+
cron: Schema.String.annotations({
|
|
236
|
+
title: "Cron",
|
|
237
|
+
[SchemaAST.ExamplesAnnotationId]: ["0 0 * * *"]
|
|
238
|
+
})
|
|
239
|
+
});
|
|
240
|
+
/**
|
|
241
|
+
* Construct a Timer trigger spec from a cron string.
|
|
242
|
+
*/
|
|
243
|
+
var specTimer = (cron) => ({
|
|
244
|
+
kind: "timer",
|
|
245
|
+
cron
|
|
246
|
+
});
|
|
247
|
+
/**
|
|
248
|
+
* Webhook.
|
|
249
|
+
*/
|
|
250
|
+
var WebhookSpec = Schema.Struct({
|
|
251
|
+
kind: Schema.Literal("webhook").annotations(kindLiteralAnnotations),
|
|
252
|
+
method: Schema.optional(Schema.String.annotations({
|
|
253
|
+
title: "Method",
|
|
254
|
+
[OptionsAnnotationId]: ["GET", "POST"]
|
|
255
|
+
})),
|
|
256
|
+
port: Schema.optional(Schema.Number.annotations({ title: "Port" }))
|
|
257
|
+
});
|
|
258
|
+
/**
|
|
259
|
+
* Construct a Webhook trigger spec from a method and port.
|
|
260
|
+
*/
|
|
261
|
+
var specWebhook = (opts) => ({
|
|
262
|
+
kind: "webhook",
|
|
263
|
+
method: opts?.method,
|
|
264
|
+
port: opts?.port
|
|
265
|
+
});
|
|
266
|
+
/**
|
|
267
|
+
* Trigger schema.
|
|
268
|
+
*/
|
|
269
|
+
var Spec = Schema.Union(EmailSpec, FeedSpec, DirectSpec, SubscriptionSpec, TimerSpec, WebhookSpec).annotations({ title: "Trigger" });
|
|
270
|
+
/**
|
|
271
|
+
* Forms the input data passed to the function.
|
|
272
|
+
* Must match the function's input schema.
|
|
273
|
+
*
|
|
274
|
+
* @example
|
|
275
|
+
* {
|
|
276
|
+
* item: '{{event.item}}',
|
|
277
|
+
* instructions: 'Summarize and perform entity-extraction'
|
|
278
|
+
* mailbox: { '/': 'echo://AAA/ZZZ' }
|
|
279
|
+
* }
|
|
280
|
+
*/
|
|
281
|
+
var InputTemplate = Schema.Record({
|
|
282
|
+
key: Schema.String,
|
|
283
|
+
value: Schema.Any
|
|
284
|
+
});
|
|
285
|
+
/**
|
|
286
|
+
* Function trigger.
|
|
287
|
+
* Runnable is invoked with the `payload` passed as input data.
|
|
288
|
+
* The event that fires the trigger is available in the runnable context.
|
|
289
|
+
*/
|
|
290
|
+
var Trigger = class extends Type.makeObject(DXN.make("org.dxos.type.trigger", "0.1.0"))(Schema.Struct({
|
|
291
|
+
/**
|
|
292
|
+
* Runnable (operation or workflow) to invoke.
|
|
293
|
+
* Wired programmatically (see plugin-routine's `wireTriggers`); not user-editable, so hidden from forms.
|
|
294
|
+
*/
|
|
295
|
+
runnable: Ref.Ref(Runnable).pipe(Schema.annotations({ title: "Runnable" }), Annotation.FormInputAnnotation.set(false), Schema.optional),
|
|
296
|
+
spec: Spec.pipe(Schema.optional),
|
|
297
|
+
enabled: Schema.Boolean.pipe(Schema.optional),
|
|
298
|
+
/**
|
|
299
|
+
* Runs this trigger on the edge rather than locally.
|
|
300
|
+
* When unset, the trigger runs locally on the client.
|
|
301
|
+
*/
|
|
302
|
+
remote: Schema.Boolean.pipe(Schema.annotations({ title: "Remote" }), Schema.optional),
|
|
303
|
+
concurrency: Schema.Number.pipe(Schema.annotations({
|
|
304
|
+
title: "Concurrency",
|
|
305
|
+
default: 1,
|
|
306
|
+
description: "Maximum number of concurrent invocations of the trigger."
|
|
307
|
+
}), Annotation.FormInputAnnotation.set(false), Schema.optional),
|
|
308
|
+
/**
|
|
309
|
+
* Only used for workflowSchema.
|
|
310
|
+
* Specifies the input node in the circuit.
|
|
311
|
+
* @deprecated Remove and enforce a single input node in all compute graphSchema.
|
|
312
|
+
*/
|
|
313
|
+
inputNodeId: Schema.String.pipe(Schema.annotations({ title: "Input Node ID" }), Annotation.FormInputAnnotation.set(false), Schema.optional),
|
|
314
|
+
/**
|
|
315
|
+
* Passed as the input data to the runnable.
|
|
316
|
+
*/
|
|
317
|
+
input: InputTemplate.pipe(Annotation.FormInputAnnotation.set(false), Schema.optional)
|
|
318
|
+
}).pipe(Annotation.IconAnnotation.set({
|
|
319
|
+
icon: "ph--lightning--regular",
|
|
320
|
+
hue: "yellow"
|
|
321
|
+
}), HiddenAnnotation.set(true))) {};
|
|
322
|
+
var make$8 = (props) => Obj.make(Trigger, props);
|
|
323
|
+
/**
|
|
324
|
+
* Checks if a trigger having this spec can be manually invoked (a `direct` or `timer` trigger).
|
|
325
|
+
*/
|
|
326
|
+
var isManuallyInvokable = (spec) => spec?.kind === "direct" || spec?.kind === "timer";
|
|
327
|
+
/**
|
|
328
|
+
* Service for monitoring trigger executions.
|
|
329
|
+
*/
|
|
330
|
+
var TriggerMonitorService = class extends Context.Tag("@dxos/functions/TriggerMonitorService")() {};
|
|
331
|
+
//#endregion
|
|
332
|
+
//#region src/types/Skill.ts
|
|
333
|
+
var Skill_exports = /* @__PURE__ */ __exportAll({
|
|
334
|
+
Hook: () => Hook,
|
|
335
|
+
HookSpec: () => HookSpec,
|
|
336
|
+
NotFoundError: () => NotFoundError,
|
|
337
|
+
Skill: () => Skill,
|
|
338
|
+
getKey: () => getKey,
|
|
339
|
+
getVersion: () => getVersion,
|
|
340
|
+
make: () => make$7,
|
|
341
|
+
registryURI: () => registryURI,
|
|
342
|
+
resolve: () => resolve$2,
|
|
343
|
+
toolDefinitions: () => toolDefinitions,
|
|
344
|
+
upsert: () => upsert
|
|
345
|
+
});
|
|
346
|
+
/**
|
|
347
|
+
* Skill schema defines the structure for AI assistant skills.
|
|
348
|
+
* Skills contain instructions, tools, and artifacts that guide the AI's behavior.
|
|
349
|
+
* Skills may use tools to create and read artifacts, which are managed by the assistant.
|
|
350
|
+
*
|
|
351
|
+
* The registry `key` and `version` are stored in the object meta — access them via
|
|
352
|
+
* `Obj.getMeta(skill).key` and `Obj.getMeta(skill).version`.
|
|
353
|
+
*/
|
|
354
|
+
var Skill = class extends Type.makeObject(DXN.make("org.dxos.type.skill", "0.2.0"))(Schema.Struct({
|
|
355
|
+
/**
|
|
356
|
+
* Human-readable name of the skill.
|
|
357
|
+
*/
|
|
358
|
+
name: Schema.String.annotations({ description: "Human-readable name of the skill" }),
|
|
359
|
+
/**
|
|
360
|
+
* Description of the skill's purpose and functionality.
|
|
361
|
+
*/
|
|
362
|
+
description: Schema.optional(Schema.String).annotations({ description: "Description of the skill's purpose and functionality" }),
|
|
363
|
+
/**
|
|
364
|
+
* Instructions that guide the AI assistant's behavior and responses.
|
|
365
|
+
* These are system prompts or guidelines that the AI should follow.
|
|
366
|
+
*/
|
|
367
|
+
instructions: Template.annotations({ description: "Instructions that guide the AI assistant's behavior and responses" }),
|
|
368
|
+
/**
|
|
369
|
+
* Array of tools that the AI assistant can use when this skill is active.
|
|
370
|
+
*/
|
|
371
|
+
tools: Schema.Array(ToolId).annotations({ description: "Array of tools that the AI assistant can use when this skill is active" }),
|
|
372
|
+
/**
|
|
373
|
+
* Whether an agent is allowed to auto-enable this skill in a conversation.
|
|
374
|
+
*/
|
|
375
|
+
agentCanEnable: Schema.optional(Schema.Boolean).annotations({ description: "Whether an agent is allowed to auto-enable this skill in a conversation." }),
|
|
376
|
+
/**
|
|
377
|
+
* Array of MCP servers that the AI assistant can use when this skill is active.
|
|
378
|
+
*/
|
|
379
|
+
mcpServers: Schema.optional(Schema.Array(McpServer)),
|
|
380
|
+
/**
|
|
381
|
+
* Hooks triggered automatically at certain points in the agent's lifecycle.
|
|
382
|
+
*/
|
|
383
|
+
hooks: Schema.optional(Schema.Array(Schema.suspend(() => Hook)))
|
|
384
|
+
}).pipe(Annotation.LabelAnnotation.set(["name"]), Annotation.IconAnnotation.set({
|
|
385
|
+
icon: "ph--blueprint--regular",
|
|
386
|
+
hue: "sky"
|
|
387
|
+
}))) {};
|
|
388
|
+
/**
|
|
389
|
+
* Controls when the hook is triggered.
|
|
390
|
+
*/
|
|
391
|
+
var HookSpec = Schema.Union(
|
|
392
|
+
/**
|
|
393
|
+
* Triggered when the agent is about to start a request.
|
|
394
|
+
* A request is a series of agent/tool turns that the model drives.
|
|
395
|
+
*/
|
|
396
|
+
Schema.TaggedStruct("begin-request", {}),
|
|
397
|
+
/**
|
|
398
|
+
* Triggered when the agent has completed a request.
|
|
399
|
+
* A request is a series of agent/tool turns that the model drives.
|
|
400
|
+
*/
|
|
401
|
+
Schema.TaggedStruct("end-request", {})
|
|
402
|
+
);
|
|
403
|
+
/**
|
|
404
|
+
* Allows hooking into the agent's lifecycle.
|
|
405
|
+
* NOTE: Intentionally similar to Trigger, perhaps we should merge them.
|
|
406
|
+
*/
|
|
407
|
+
var Hook = Schema.Struct({
|
|
408
|
+
/**
|
|
409
|
+
* What to do when the hook is triggered.
|
|
410
|
+
*
|
|
411
|
+
* Can be a Ref to a PersistentOperation.
|
|
412
|
+
*/
|
|
413
|
+
function: Schema.optional(Ref.Ref(Obj.Unknown).annotations({ title: "Function" })),
|
|
414
|
+
/**
|
|
415
|
+
* Controls when the hook is triggered.
|
|
416
|
+
*/
|
|
417
|
+
spec: HookSpec,
|
|
418
|
+
/**
|
|
419
|
+
* Passed as the input data to the function.
|
|
420
|
+
* Must match the function's input schema.
|
|
421
|
+
*/
|
|
422
|
+
input: InputTemplate.pipe(Annotation.FormInputAnnotation.set(false), Schema.optional)
|
|
423
|
+
});
|
|
424
|
+
/**
|
|
425
|
+
* Create a new Skill.
|
|
426
|
+
* The `key` (and optional `version`) are stored in the object meta.
|
|
427
|
+
* `key` must be a valid DXN name (e.g. `org.dxos.skill.mySkill`).
|
|
428
|
+
*/
|
|
429
|
+
var make$7 = ({ key, version, tools = [], instructions = make$9(), ...props }) => Obj.make(Skill, {
|
|
430
|
+
[Obj.Meta]: {
|
|
431
|
+
key,
|
|
432
|
+
version
|
|
433
|
+
},
|
|
434
|
+
tools,
|
|
435
|
+
instructions,
|
|
436
|
+
...props
|
|
437
|
+
});
|
|
438
|
+
/**
|
|
439
|
+
* Get the registry key for a skill.
|
|
440
|
+
*/
|
|
441
|
+
var getKey = (skill) => {
|
|
442
|
+
const key = Obj.getMeta(skill).key;
|
|
443
|
+
if (key === void 0) throw new Error("Skill is missing the meta key.");
|
|
444
|
+
return key;
|
|
445
|
+
};
|
|
446
|
+
/**
|
|
447
|
+
* Get the registry version for a skill, if any.
|
|
448
|
+
*/
|
|
449
|
+
var getVersion = (skill) => Obj.getMeta(skill).version;
|
|
450
|
+
/**
|
|
451
|
+
* Util to create tool definitions for a skill.
|
|
452
|
+
*/
|
|
453
|
+
var toolDefinitions = ({ tools = [], operations = [] }) => [...operations.map((op) => ToolId.make(DXN.getName(op.meta.key))), ...tools.map((tool) => ToolId.make(tool))];
|
|
454
|
+
/**
|
|
455
|
+
* Returns the canonical URI used to reference this skill in the registry.
|
|
456
|
+
* Use this URI with `Ref.fromURI` to bind a skill without cloning it to the DB.
|
|
457
|
+
*
|
|
458
|
+
* TODO(wittjosiah): Should use Obj.getURI instead once it supports options to prefer meta key over EID.
|
|
459
|
+
*/
|
|
460
|
+
var registryURI = (key) => DXN.tryMake(`dxn:${key}`) ?? URI.make(key);
|
|
461
|
+
/**
|
|
462
|
+
* Resolves a skill from the registry by its meta key.
|
|
463
|
+
* Does not check the local database for the skill.
|
|
464
|
+
*/
|
|
465
|
+
var resolve$2 = (key) => Effect.gen(function* () {
|
|
466
|
+
const skill = (yield* Registry.runQuery(Filter.and(Filter.type(Skill), Filter.key(key))))[0];
|
|
467
|
+
if (!skill) return yield* Effect.fail(new NotFoundError({ context: { key } }));
|
|
468
|
+
return skill;
|
|
469
|
+
});
|
|
470
|
+
/**
|
|
471
|
+
* Upserts a skill into the database.
|
|
472
|
+
* If the skill already exists in the database, the local (possibly forked) copy is returned as-is.
|
|
473
|
+
* Otherwise, a fresh copy is cloned from the registry and added.
|
|
474
|
+
* @deprecated Since we're using a registry we no longer need to store skills in the database.
|
|
475
|
+
*/
|
|
476
|
+
var upsert = (key) => Effect.gen(function* () {
|
|
477
|
+
const local = yield* Database.query(Filter.and(Filter.type(Skill), Filter.key(key))).run;
|
|
478
|
+
if (local.length > 0) return local[0];
|
|
479
|
+
return yield* Database.add(Obj.clone(yield* resolve$2(key), { deep: "all" }));
|
|
480
|
+
});
|
|
481
|
+
var NotFoundError = class extends BaseError.extend("SkillNotFound", "Skill not found") {};
|
|
482
|
+
//#endregion
|
|
483
|
+
//#region src/types/Instructions.ts
|
|
484
|
+
var Instructions_exports = /* @__PURE__ */ __exportAll({
|
|
485
|
+
Command: () => Command,
|
|
486
|
+
Instructions: () => Instructions,
|
|
487
|
+
make: () => make$6
|
|
488
|
+
});
|
|
489
|
+
/** A sentinel command the model recognizes in chat (e.g. `$track <text>`). */
|
|
490
|
+
var Command = Schema.Struct({
|
|
491
|
+
sentinel: Schema.String.annotations({ description: "Token that invokes the command (e.g. \"$track\")." }),
|
|
492
|
+
description: Schema.optional(Schema.String),
|
|
493
|
+
prompt: Schema.String.annotations({ description: "What the model should do when the sentinel appears." })
|
|
494
|
+
});
|
|
495
|
+
/**
|
|
496
|
+
* Prompt-based operation.
|
|
497
|
+
* May reference skills and additional context.
|
|
498
|
+
* Hidden from the navtree and object picker — accessed only through Routines.
|
|
499
|
+
*/
|
|
500
|
+
var Instructions = class extends Type.makeObject(DXN.make("org.dxos.type.instructions", "0.1.0"))(Schema.Struct({
|
|
501
|
+
name: Schema.optional(Schema.String),
|
|
502
|
+
description: Schema.optional(Schema.String),
|
|
503
|
+
input: JsonSchema.JsonSchema.pipe(Annotation.FormInputAnnotation.set(false)).annotations({ description: "Input schema" }),
|
|
504
|
+
output: JsonSchema.JsonSchema.pipe(Annotation.FormInputAnnotation.set(false)).annotations({ description: "Output schema" }),
|
|
505
|
+
text: Ref.Ref(Text.Text).pipe(Format.FormatAnnotation.set(Format.TypeFormat.Markdown), Schema.annotations({
|
|
506
|
+
title: "Instructions",
|
|
507
|
+
description: "Describe what the agent should do in each session."
|
|
508
|
+
})),
|
|
509
|
+
skills: Schema.Array(Ref.Ref(Skill)),
|
|
510
|
+
/**
|
|
511
|
+
* Context objects bound to the agent's session when this routine runs (sibling of `skills`).
|
|
512
|
+
* Generic `Ref.Ref(Obj.Unknown)` so any space object qualifies. Honored on every run path that
|
|
513
|
+
* executes a routine through the agent prompt, not only triggered automations.
|
|
514
|
+
*/
|
|
515
|
+
objects: Schema.Array(Ref.Ref(Obj.Unknown)).pipe(Schema.annotations({ title: "Objects" }), Schema.optional),
|
|
516
|
+
/** Sentinel commands available to chat sessions running with these instructions. */
|
|
517
|
+
commands: Schema.Array(Command).pipe(Schema.annotations({ title: "Commands" }), Schema.optional)
|
|
518
|
+
}).pipe(Annotation.LabelAnnotation.set(["name"]), Annotation.IconAnnotation.set({
|
|
519
|
+
icon: "ph--scroll--regular",
|
|
520
|
+
hue: "sky"
|
|
521
|
+
}), Annotation.HiddenAnnotation.set(true))) {};
|
|
522
|
+
/** Creates an Instructions object with an owned Markdown `text` body (parented so it cascades and deep-clones). */
|
|
523
|
+
var make$6 = ({ name, description, input, output, text, skills = [], objects, commands }) => {
|
|
524
|
+
const body = Text.make({ content: text ?? "" });
|
|
525
|
+
const instructions = Obj.make(Instructions, {
|
|
526
|
+
name,
|
|
527
|
+
description,
|
|
528
|
+
input: JsonSchema.toJsonSchema(input ?? Schema.Void),
|
|
529
|
+
output: JsonSchema.toJsonSchema(output ?? Schema.Void),
|
|
530
|
+
text: Ref.make(body),
|
|
531
|
+
skills,
|
|
532
|
+
objects,
|
|
533
|
+
commands
|
|
534
|
+
});
|
|
535
|
+
Obj.setParent(body, instructions);
|
|
536
|
+
return instructions;
|
|
537
|
+
};
|
|
538
|
+
//#endregion
|
|
539
|
+
//#region src/types/Routine.ts
|
|
540
|
+
var Routine_exports = /* @__PURE__ */ __exportAll({
|
|
541
|
+
Kind: () => Kind,
|
|
542
|
+
Routine: () => Routine,
|
|
543
|
+
instanceOf: () => instanceOf,
|
|
544
|
+
instructionsRef: () => instructionsRef,
|
|
545
|
+
make: () => make$5,
|
|
546
|
+
runnableRef: () => runnableRef
|
|
547
|
+
});
|
|
548
|
+
var Kind = Schema.Literal(...["runnable", "instructions"]);
|
|
549
|
+
var RunnableSpec = Schema.Struct({
|
|
550
|
+
kind: Schema.Literal("runnable"),
|
|
551
|
+
runnable: Ref.Ref(Runnable)
|
|
552
|
+
});
|
|
553
|
+
var InstructionsSpec = Schema.Struct({
|
|
554
|
+
kind: Schema.Literal("instructions"),
|
|
555
|
+
instructions: Ref.Ref(Instructions)
|
|
556
|
+
});
|
|
557
|
+
var RoutineSpec = Schema.Union(RunnableSpec, InstructionsSpec);
|
|
558
|
+
/**
|
|
559
|
+
* User-facing routine: a thin aggregate of an action (`runnable`) and the triggers that fire it.
|
|
560
|
+
* App-level only — EDGE stays unaware of it (triggers point directly at the runnable).
|
|
561
|
+
*/
|
|
562
|
+
var Routine = class extends Type.makeObject(DXN.make("org.dxos.type.routine", "0.2.0"))(Schema.Struct({
|
|
563
|
+
name: Schema.String.pipe(Schema.optional),
|
|
564
|
+
description: Schema.String.pipe(Schema.optional),
|
|
565
|
+
/**
|
|
566
|
+
* The action to run: either an Operation (`spec.runnable`, bound directly) or the routine's own owned
|
|
567
|
+
* Instructions (`spec.instructions`). For an Operation action the trigger's `runnable` points at this
|
|
568
|
+
* Operation. For an Instructions action `spec.instructions` is the owned Instructions object (the operation
|
|
569
|
+
* is implicitly the static RunInstructions, so no separate operation ref is stored), and the trigger's
|
|
570
|
+
* `runnable` is RunInstructions with this instructions bound as its input.
|
|
571
|
+
*/
|
|
572
|
+
spec: RoutineSpec.pipe(Schema.optional),
|
|
573
|
+
/**
|
|
574
|
+
* Explicit membership, bi-directional with `trigger.runnable → runnable`. Required (not derived by query)
|
|
575
|
+
* because the runnable may be a shared registry operation referenced by multiple automations, which would
|
|
576
|
+
* conflate triggers. MVP enforces length <= 1.
|
|
577
|
+
*/
|
|
578
|
+
triggers: Schema.Array(Ref.Ref(Trigger))
|
|
579
|
+
}).pipe(LabelAnnotation$1.set(["name"]), Annotation.IconAnnotation.set({
|
|
580
|
+
icon: "ph--lightning--regular",
|
|
581
|
+
hue: "amber"
|
|
582
|
+
}))) {};
|
|
583
|
+
/** Returns true when value is a Routine object. */
|
|
584
|
+
var instanceOf = (value) => Obj.instanceOf(Routine, value);
|
|
585
|
+
/**
|
|
586
|
+
* The owned Instructions ref of an instructions-action routine, or undefined for an operation action.
|
|
587
|
+
* Classification is explicit in `spec.kind`, so this needs no `.target` dereference; callers resolve the ref
|
|
588
|
+
* reactively (`useObject`) or asynchronously (`Database.load`) as appropriate.
|
|
589
|
+
*/
|
|
590
|
+
var instructionsRef = (routine) => routine.spec?.kind === "instructions" ? routine.spec.instructions : void 0;
|
|
591
|
+
/** The Operation (runnable) ref of an operation-action routine, or undefined for an instructions action. */
|
|
592
|
+
var runnableRef = (routine) => routine.spec?.kind === "runnable" ? routine.spec.runnable : void 0;
|
|
593
|
+
/** Factory wrapper around `Obj.make` for {@link Routine}. Trigger wiring lives in plugin-routine (`makeRoutine`). */
|
|
594
|
+
var make$5 = (props) => Obj.make(Routine, {
|
|
595
|
+
...props,
|
|
596
|
+
triggers: props.triggers ?? []
|
|
597
|
+
});
|
|
598
|
+
//#endregion
|
|
599
|
+
//#region src/types/Project.ts
|
|
600
|
+
var Project_exports = /* @__PURE__ */ __exportAll({
|
|
601
|
+
Goal: () => Goal,
|
|
602
|
+
Project: () => Project,
|
|
603
|
+
contextBindings: () => contextBindings,
|
|
604
|
+
make: () => make$4
|
|
605
|
+
});
|
|
606
|
+
/** Lightweight inline goal: per-item status and addressability without document ceremony. */
|
|
607
|
+
var Goal = Schema.Struct({
|
|
608
|
+
id: Schema.String,
|
|
609
|
+
text: Schema.String,
|
|
610
|
+
status: Schema.optional(Schema.Literal("open", "met", "dropped"))
|
|
611
|
+
});
|
|
612
|
+
/**
|
|
613
|
+
* A user-facing container for interactive, long-running work: instructions (skills + commands),
|
|
614
|
+
* routines, artifacts, and AI chat sessions in project context. Successor to `Topic`.
|
|
615
|
+
* Chats and agents attach via relations/queries (assistant-toolkit depends on compute, so no typed refs here).
|
|
616
|
+
*/
|
|
617
|
+
var Project = class extends Type.makeObject(DXN.make("org.dxos.type.project", "0.3.0"))(Schema.Struct({
|
|
618
|
+
name: Schema.optional(Schema.String),
|
|
619
|
+
description: Schema.optional(Schema.String),
|
|
620
|
+
/** Owned agent instructions (created + parented at the plugin layer). */
|
|
621
|
+
instructions: Schema.optional(Ref.Ref(Instructions).pipe(FormInlineAnnotation.set(true))),
|
|
622
|
+
/** Routines created within the scope of this project. */
|
|
623
|
+
routines: Schema.Array(Ref.Ref(Routine)),
|
|
624
|
+
/** Owned collection of artifacts (documents, outliners, tables, ...) managed by the project. */
|
|
625
|
+
artifacts: Schema.optional(Ref.Ref(Collection.Collection)),
|
|
626
|
+
/** What done means for this project. */
|
|
627
|
+
goals: Schema.optional(Schema.Array(Goal)),
|
|
628
|
+
/** Ad hoc markdown checklist — the scratch surface; project chats write into it. */
|
|
629
|
+
outline: Schema.optional(Ref.Ref(Outline.Outline)),
|
|
630
|
+
/** Owned (or adopted synced) task container; membership is the ECHO parent edge. */
|
|
631
|
+
taskSet: Schema.optional(Ref.Ref(TaskSet.TaskSet))
|
|
632
|
+
}).pipe(Schema.annotations({ title: "Project" }), LabelAnnotation.set(["name"]), Annotation.IconAnnotation.set({
|
|
633
|
+
icon: "ph--stack--regular",
|
|
634
|
+
hue: "amber"
|
|
635
|
+
}))) {};
|
|
636
|
+
/** Factory wrapper around `Obj.make` for {@link Project}. */
|
|
637
|
+
var make$4 = (props = {}) => Obj.make(Project, {
|
|
638
|
+
...props,
|
|
639
|
+
routines: props.routines ?? []
|
|
640
|
+
});
|
|
641
|
+
/**
|
|
642
|
+
* Bindings a chat session should receive when running in this project's context: the instructions'
|
|
643
|
+
* skills and context objects. The instructions object itself is NOT bound — its text/commands reach
|
|
644
|
+
* the system prompt through the chat's `instructions` ref, and a bound Instructions object would
|
|
645
|
+
* render as an inert context stub. Requires the instructions ref to be resolved (`.target`);
|
|
646
|
+
* unresolved refs contribute nothing.
|
|
647
|
+
*/
|
|
648
|
+
var contextBindings = (project) => {
|
|
649
|
+
const instructionsRef = project.instructions;
|
|
650
|
+
if (!instructionsRef?.isAvailable) return {
|
|
651
|
+
skills: [],
|
|
652
|
+
objects: []
|
|
653
|
+
};
|
|
654
|
+
const instructions = instructionsRef.target;
|
|
655
|
+
if (!instructions) return {
|
|
656
|
+
skills: [],
|
|
657
|
+
objects: []
|
|
658
|
+
};
|
|
659
|
+
return {
|
|
660
|
+
skills: [...instructions.skills],
|
|
661
|
+
objects: [...instructions.objects ?? []]
|
|
662
|
+
};
|
|
663
|
+
};
|
|
664
|
+
//#endregion
|
|
665
|
+
//#region src/types/Script.ts
|
|
666
|
+
var Script_exports = /* @__PURE__ */ __exportAll({
|
|
667
|
+
Script: () => Script,
|
|
668
|
+
make: () => make$3
|
|
669
|
+
});
|
|
670
|
+
/**
|
|
671
|
+
* Source script.
|
|
672
|
+
*/
|
|
673
|
+
var Script = class extends Type.makeObject(DXN.make("org.dxos.type.script", "0.1.0"))(Schema.Struct({
|
|
674
|
+
name: Schema.String.pipe(Schema.optional),
|
|
675
|
+
description: Schema.String.pipe(Schema.optional),
|
|
676
|
+
changed: Schema.Boolean.pipe(FormInputAnnotation.set(false), Schema.optional),
|
|
677
|
+
source: Ref.Ref(Text.Text).pipe(FormInputAnnotation.set(false))
|
|
678
|
+
}).pipe(Annotation.LabelAnnotation.set(["name"]), Annotation.IconAnnotation.set({
|
|
679
|
+
icon: "ph--code--regular",
|
|
680
|
+
hue: "sky"
|
|
681
|
+
}))) {};
|
|
682
|
+
var make$3 = ({ source = "", ...props } = {}) => Obj.make(Script, {
|
|
683
|
+
...props,
|
|
684
|
+
source: Ref.make(Text.make({ content: source }))
|
|
685
|
+
});
|
|
686
|
+
//#endregion
|
|
687
|
+
//#region src/types/TriggerEvent.ts
|
|
688
|
+
var TriggerEvent_exports = /* @__PURE__ */ __exportAll({
|
|
689
|
+
DirectEvent: () => DirectEvent,
|
|
690
|
+
EmailEvent: () => EmailEvent,
|
|
691
|
+
FeedEvent: () => FeedEvent,
|
|
692
|
+
SubscriptionEvent: () => SubscriptionEvent,
|
|
693
|
+
SubscriptionMutationType: () => SubscriptionMutationType,
|
|
694
|
+
TimerEvent: () => TimerEvent,
|
|
695
|
+
TriggerEvent: () => TriggerEvent,
|
|
696
|
+
WebhookEvent: () => WebhookEvent
|
|
697
|
+
});
|
|
698
|
+
var EmailEvent = Schema.Struct({
|
|
699
|
+
from: Schema.String,
|
|
700
|
+
to: Schema.String,
|
|
701
|
+
subject: Schema.String,
|
|
702
|
+
created: Schema.String,
|
|
703
|
+
body: Schema.String
|
|
704
|
+
});
|
|
705
|
+
var FeedEvent = Schema.Struct({
|
|
706
|
+
feed: Ref.Ref(Feed.Feed),
|
|
707
|
+
item: Schema.Any,
|
|
708
|
+
cursor: Schema.String
|
|
709
|
+
});
|
|
710
|
+
/**
|
|
711
|
+
* Kind of mutation a subscription trigger observed for its subject.
|
|
712
|
+
*/
|
|
713
|
+
var SubscriptionMutationType = Schema.Literal("created", "updated", "deleted");
|
|
714
|
+
var SubscriptionEvent = Schema.Struct({
|
|
715
|
+
/**
|
|
716
|
+
* Type of the mutation.
|
|
717
|
+
*/
|
|
718
|
+
type: SubscriptionMutationType,
|
|
719
|
+
/**
|
|
720
|
+
* Reference to the object that was changed or created. For `deleted`, carries the object's URI;
|
|
721
|
+
* dereferencing may yield `undefined` since the object is gone.
|
|
722
|
+
*/
|
|
723
|
+
subject: Ref.Ref(Obj.Unknown),
|
|
724
|
+
/**
|
|
725
|
+
* @deprecated Use `subject`.
|
|
726
|
+
*/
|
|
727
|
+
changedObjectId: Schema.optional(Schema.String)
|
|
728
|
+
});
|
|
729
|
+
var TimerEvent = Schema.Struct({ tick: Schema.Number });
|
|
730
|
+
var DirectEvent = Schema.Struct({ data: Schema.optional(Schema.Record({
|
|
731
|
+
key: Schema.String,
|
|
732
|
+
value: Schema.Any
|
|
733
|
+
})) });
|
|
734
|
+
var WebhookEvent = Schema.Struct({
|
|
735
|
+
url: Schema.String,
|
|
736
|
+
method: Schema.Literal("GET", "POST"),
|
|
737
|
+
headers: Schema.Record({
|
|
738
|
+
key: Schema.String,
|
|
739
|
+
value: Schema.String
|
|
740
|
+
}),
|
|
741
|
+
bodyText: Schema.String
|
|
742
|
+
});
|
|
743
|
+
var TriggerEvent = Schema.Union(EmailEvent, FeedEvent, DirectEvent, SubscriptionEvent, TimerEvent, WebhookEvent);
|
|
744
|
+
//#endregion
|
|
745
|
+
//#region src/AgentIdentity.ts
|
|
746
|
+
var AgentIdentity_exports = /* @__PURE__ */ __exportAll({
|
|
747
|
+
AgentIdentity: () => AgentIdentity,
|
|
748
|
+
currentDid: () => currentDid
|
|
749
|
+
});
|
|
750
|
+
var AgentIdentity = class extends Context.Tag("@dxos/compute/AgentIdentity")() {};
|
|
751
|
+
/**
|
|
752
|
+
* The current author DID, or `undefined` when no {@link AgentIdentity} is in scope (e.g. a human-
|
|
753
|
+
* initiated invocation). Reads optionally, so an operation that defaults its author from the agent
|
|
754
|
+
* identity does not add a hard service requirement.
|
|
755
|
+
*/
|
|
756
|
+
var currentDid = Effect.serviceOption(AgentIdentity).pipe(Effect.map(Option.match({
|
|
757
|
+
onNone: () => void 0,
|
|
758
|
+
onSome: (identity) => identity.did
|
|
759
|
+
})));
|
|
760
|
+
//#endregion
|
|
761
|
+
//#region src/Cancellation.ts
|
|
762
|
+
var Cancellation_exports = /* @__PURE__ */ __exportAll({
|
|
763
|
+
Service: () => Service$1,
|
|
764
|
+
signal: () => signal
|
|
765
|
+
});
|
|
766
|
+
/**
|
|
767
|
+
* Cooperative cancellation of the current operation run. The runtime that owns execution provides
|
|
768
|
+
* the service and fires the signal when the run is cancelled — the EDGE worker on a client cancel
|
|
769
|
+
* request, the local process runtime on terminate. Operations observe it via {@link signal}.
|
|
770
|
+
*/
|
|
771
|
+
var Service$1 = class extends Context.Tag("@dxos/compute/Cancellation")() {};
|
|
772
|
+
/**
|
|
773
|
+
* The current run's cancellation signal — e.g. for `Pipeline.abortWith` or `fetch`. Never fires when
|
|
774
|
+
* the runtime provided no cancellation channel.
|
|
775
|
+
*/
|
|
776
|
+
var signal = Effect.serviceOption(Service$1).pipe(Effect.map(Option.match({
|
|
777
|
+
onNone: () => new AbortController().signal,
|
|
778
|
+
onSome: (service) => service.signal
|
|
779
|
+
})));
|
|
780
|
+
//#endregion
|
|
781
|
+
//#region src/Credential.ts
|
|
782
|
+
var Credential_exports = /* @__PURE__ */ __exportAll({
|
|
783
|
+
AccessTokenResolver: () => AccessTokenResolver,
|
|
784
|
+
CredentialsService: () => CredentialsService,
|
|
785
|
+
getApiKeyValue: () => getApiKeyValue
|
|
786
|
+
});
|
|
787
|
+
/**
|
|
788
|
+
* Source for credentials EDGE custodies rather than replicating into the space (those stored as
|
|
789
|
+
* `MANAGED_ACCESS_TOKEN`).
|
|
790
|
+
*
|
|
791
|
+
* An implementation detail of {@link CredentialsService}, not a consumer-facing service: it exists
|
|
792
|
+
* as a tag only because the two surfaces reach EDGE differently — clients over authenticated HTTP,
|
|
793
|
+
* functions over a space-bound service binding. Implementations cache; pass `refresh` to bypass that
|
|
794
|
+
* cache after an authorization failure.
|
|
795
|
+
*/
|
|
796
|
+
var AccessTokenResolver = class AccessTokenResolver extends Context.Tag("@dxos/functions/AccessTokenResolver")() {
|
|
797
|
+
static resolve = (request) => Effect.gen(function* () {
|
|
798
|
+
const resolver = yield* AccessTokenResolver;
|
|
799
|
+
return yield* Effect.promise(() => resolver.resolve(request));
|
|
800
|
+
});
|
|
801
|
+
/**
|
|
802
|
+
* Fails on every managed token. The default where EDGE is unreachable (tests, offline CLI runs):
|
|
803
|
+
* a managed credential genuinely cannot be resolved there, and failing says so.
|
|
804
|
+
*/
|
|
805
|
+
static notAvailable = Layer.succeed(AccessTokenResolver, { resolve: async ({ accessTokenId }) => {
|
|
806
|
+
throw new Error(`No access token resolver configured; cannot resolve managed token: ${accessTokenId}`);
|
|
807
|
+
} });
|
|
808
|
+
};
|
|
809
|
+
var CredentialsService = class CredentialsService extends Context.Tag("@dxos/functions/CredentialsService")() {
|
|
810
|
+
static getCredential = (query) => Effect.gen(function* () {
|
|
811
|
+
const credentials = yield* CredentialsService;
|
|
812
|
+
return yield* Effect.promise(() => credentials.getCredential(query));
|
|
813
|
+
});
|
|
814
|
+
static getApiKey = (query) => Effect.gen(function* () {
|
|
815
|
+
const credential = yield* CredentialsService.getCredential(query);
|
|
816
|
+
if (!credential.apiKey) throw new Error(`API key not found for service: ${query.service}`);
|
|
817
|
+
return Redacted.make(credential.apiKey);
|
|
818
|
+
});
|
|
819
|
+
};
|
|
820
|
+
/**
|
|
821
|
+
* The credential's API key as a plain string — what a caller passing it to an HTTP client needs.
|
|
822
|
+
* Resolves a server-custodied value transparently, so callers never branch on where it came from.
|
|
823
|
+
*/
|
|
824
|
+
var getApiKeyValue = (query) => Effect.map(CredentialsService.getApiKey(query), Redacted.value);
|
|
825
|
+
//#endregion
|
|
826
|
+
//#region src/Header.ts
|
|
827
|
+
var Header_exports = /* @__PURE__ */ __exportAll({ byokLayer: () => byokLayer });
|
|
828
|
+
/**
|
|
829
|
+
* Wraps an `HttpClient` so outbound requests carry `X-BYOK: <apiKey>` whenever the active space
|
|
830
|
+
* has an `AccessToken` for `providerHost`. Lookup failures pass the request through unchanged.
|
|
831
|
+
*/
|
|
832
|
+
var byokLayer = (providerHost) => Layer.effect(HttpClient.HttpClient, Effect.gen(function* () {
|
|
833
|
+
const client = yield* HttpClient.HttpClient;
|
|
834
|
+
const credentials = yield* CredentialsService;
|
|
835
|
+
return HttpClient.mapRequestEffect(client, (request) => Effect.gen(function* () {
|
|
836
|
+
const apiKey = (yield* Effect.tryPromise(() => credentials.queryCredentials({ service: providerHost })).pipe(Effect.orElseSucceed(() => []))).find((credential) => credential.apiKey)?.apiKey;
|
|
837
|
+
return apiKey ? HttpClientRequest.setHeader(request, BYOK_HEADER, apiKey) : request;
|
|
838
|
+
}));
|
|
839
|
+
}));
|
|
840
|
+
//#endregion
|
|
841
|
+
//#region src/LayerSpec.ts
|
|
842
|
+
var LayerSpec_exports = /* @__PURE__ */ __exportAll({
|
|
843
|
+
TypeId: () => TypeId,
|
|
844
|
+
make: () => make$2
|
|
845
|
+
});
|
|
846
|
+
var TypeId = "~@dxos/functions/LayerSpec";
|
|
847
|
+
/**
|
|
848
|
+
* Make a service.
|
|
849
|
+
*/
|
|
850
|
+
var make$2 = (opts, make) => {
|
|
851
|
+
return {
|
|
852
|
+
[TypeId]: TypeId,
|
|
853
|
+
affinity: opts.affinity,
|
|
854
|
+
requires: opts.requires,
|
|
855
|
+
provides: opts.provides,
|
|
856
|
+
make
|
|
857
|
+
};
|
|
858
|
+
};
|
|
859
|
+
//#endregion
|
|
860
|
+
//#region src/OperationRegistry.ts
|
|
861
|
+
var OperationRegistry_exports = /* @__PURE__ */ __exportAll({
|
|
862
|
+
Service: () => Service,
|
|
863
|
+
layer: () => layer,
|
|
864
|
+
resolve: () => resolve$1
|
|
865
|
+
});
|
|
866
|
+
var Service = class extends Context.Tag("@dxos/operation/OperationRegistry")() {};
|
|
867
|
+
/**
|
|
868
|
+
* Resolve an operation by key.
|
|
869
|
+
*/
|
|
870
|
+
var resolve$1 = Effect.serviceFunctionEffect(Service, (service) => service.resolve);
|
|
871
|
+
var layer = Layer.effect(Service, Effect.gen(function* () {
|
|
872
|
+
const database = yield* Database.Service;
|
|
873
|
+
const handlerSet = yield* OperationHandlerProvider;
|
|
874
|
+
return { resolve: (key) => Database.query(Query.select(Filter.and(Filter.type(PersistentOperation), Filter.key(key)))).first.pipe(Effect.flatten, Effect.map(deserialize), Effect.catchTag("NoSuchElementException", () => getHandlerByKey(handlerSet, key)), Effect.option).pipe(Effect.provideService(Database.Service, database)) };
|
|
875
|
+
}));
|
|
876
|
+
//#endregion
|
|
877
|
+
//#region src/Trace.ts
|
|
878
|
+
var Trace_exports = /* @__PURE__ */ __exportAll({
|
|
879
|
+
CommonRuntimeName: () => CommonRuntimeName,
|
|
880
|
+
Event: () => Event,
|
|
881
|
+
EventType: () => EventType,
|
|
882
|
+
Message: () => Message,
|
|
883
|
+
MessageData: () => MessageData,
|
|
884
|
+
Meta: () => Meta,
|
|
885
|
+
OperationEnd: () => OperationEnd,
|
|
886
|
+
OperationInput: () => OperationInput,
|
|
887
|
+
OperationOutput: () => OperationOutput,
|
|
888
|
+
OperationStart: () => OperationStart,
|
|
889
|
+
RuntimeName: () => RuntimeName,
|
|
890
|
+
StatusUpdate: () => StatusUpdate,
|
|
891
|
+
TRACE_MESSAGE_TYPE_URL: () => TRACE_MESSAGE_TYPE_URL,
|
|
892
|
+
TraceService: () => TraceService,
|
|
893
|
+
TraceSink: () => TraceSink,
|
|
894
|
+
decodeTraceMessage: () => decodeTraceMessage,
|
|
895
|
+
emitStatus: () => emitStatus,
|
|
896
|
+
encodeTraceMessage: () => encodeTraceMessage,
|
|
897
|
+
flatten: () => flatten,
|
|
898
|
+
isEdgeRuntime: () => isEdgeRuntime,
|
|
899
|
+
isOfType: () => isOfType,
|
|
900
|
+
layerConsole: () => layerConsole,
|
|
901
|
+
layerNoop: () => layerNoop,
|
|
902
|
+
matchesFilter: () => matchesFilter,
|
|
903
|
+
mergeSinks: () => mergeSinks,
|
|
904
|
+
messageToTags: () => messageToTags,
|
|
905
|
+
noopSink: () => noopSink,
|
|
906
|
+
noopWriter: () => noopWriter,
|
|
907
|
+
subscriptionTagForFilter: () => subscriptionTagForFilter,
|
|
908
|
+
testTraceService: () => testTraceService,
|
|
909
|
+
write: () => write,
|
|
910
|
+
writerLayerNoop: () => writerLayerNoop
|
|
911
|
+
});
|
|
912
|
+
var __dxlog_file$1 = "/__w/dxos/dxos/packages/core/compute/compute/src/Trace.ts";
|
|
913
|
+
/**
|
|
914
|
+
* Service that writes events to the trace.
|
|
915
|
+
* Exposed to processes and operations to record events to the trace.
|
|
916
|
+
*/
|
|
917
|
+
var TraceService = class extends Context.Tag("@dxos/functions/TraceService")() {};
|
|
918
|
+
/**
|
|
919
|
+
* Writes an event to the trace.
|
|
920
|
+
*/
|
|
921
|
+
function write(eventType, payload) {
|
|
922
|
+
return Effect.gen(function* () {
|
|
923
|
+
log("trace write", {
|
|
924
|
+
key: eventType.key,
|
|
925
|
+
isEphemeral: eventType.isEphemeral
|
|
926
|
+
}, {
|
|
927
|
+
"~LogMeta": "~LogMeta",
|
|
928
|
+
F: __dxlog_file$1,
|
|
929
|
+
L: 37,
|
|
930
|
+
S: this
|
|
931
|
+
});
|
|
932
|
+
(yield* TraceService).write(eventType, payload);
|
|
933
|
+
});
|
|
934
|
+
}
|
|
935
|
+
var EventType = (key, opts) => {
|
|
936
|
+
return {
|
|
937
|
+
key,
|
|
938
|
+
schema: opts.schema,
|
|
939
|
+
isEphemeral: opts.isEphemeral
|
|
940
|
+
};
|
|
941
|
+
};
|
|
942
|
+
var Event = Schema.Struct({
|
|
943
|
+
timestamp: Schema.Number,
|
|
944
|
+
type: Schema.String,
|
|
945
|
+
data: Schema.Unknown
|
|
946
|
+
});
|
|
947
|
+
/**
|
|
948
|
+
* Checks if an event is of a given type.
|
|
949
|
+
*/
|
|
950
|
+
var isOfType = (eventType, event) => {
|
|
951
|
+
return event.type === eventType.key;
|
|
952
|
+
};
|
|
953
|
+
/**
|
|
954
|
+
* Extensible name informing which runtime executed the code that produced the event.
|
|
955
|
+
*/
|
|
956
|
+
var RuntimeName = Schema.String.pipe(Schema.brand("@dxos/compute/Trace/RuntimeName"));
|
|
957
|
+
/**
|
|
958
|
+
* Common runtime names.
|
|
959
|
+
*/
|
|
960
|
+
var CommonRuntimeName = {
|
|
961
|
+
/**
|
|
962
|
+
* Web app / CLI / Desktop app / Mobile app.
|
|
963
|
+
*/
|
|
964
|
+
local: RuntimeName.make("local"),
|
|
965
|
+
edgeIntrinsic: RuntimeName.make("edge-intrinsic"),
|
|
966
|
+
edgeWorkerLoader: RuntimeName.make("edge-worker-loader"),
|
|
967
|
+
edgeWorkerForPlatforms: RuntimeName.make("edge-worker-for-platforms")
|
|
968
|
+
};
|
|
969
|
+
/**
|
|
970
|
+
* Metadata on the context of a trace message.
|
|
971
|
+
*/
|
|
972
|
+
var Meta = Schema.Struct({
|
|
973
|
+
pid: Schema.optional(Schema.String),
|
|
974
|
+
parentPid: Schema.optional(Schema.String),
|
|
975
|
+
processName: Schema.optional(Schema.String),
|
|
976
|
+
/**
|
|
977
|
+
* Space the message was produced in.
|
|
978
|
+
* Stored as a string to avoid circular dependency on `@dxos/keys`.
|
|
979
|
+
*/
|
|
980
|
+
space: Schema.optional(Schema.String),
|
|
981
|
+
/**
|
|
982
|
+
* Ref to the conversation feed object if present.
|
|
983
|
+
*/
|
|
984
|
+
conversation: Ref.Ref(Obj.Unknown).pipe(Schema.optional),
|
|
985
|
+
/**
|
|
986
|
+
* Ref to the trigger object if invocation resulted from a trigger.
|
|
987
|
+
*/
|
|
988
|
+
trigger: Ref.Ref(Trigger).pipe(Schema.optional),
|
|
989
|
+
/**
|
|
990
|
+
* ID of the tool call that created the current process.
|
|
991
|
+
*/
|
|
992
|
+
toolCallId: Schema.optional(Schema.String),
|
|
993
|
+
/**
|
|
994
|
+
* Extensible name informing which runtime executed the code that produced the event.
|
|
995
|
+
*/
|
|
996
|
+
runtimeName: Schema.optional(RuntimeName)
|
|
997
|
+
});
|
|
998
|
+
/**
|
|
999
|
+
* Checks if a runtime is an edge runtime.
|
|
1000
|
+
*/
|
|
1001
|
+
var isEdgeRuntime = (name) => name === CommonRuntimeName.edgeIntrinsic || name === CommonRuntimeName.edgeWorkerLoader || name === CommonRuntimeName.edgeWorkerForPlatforms;
|
|
1002
|
+
/**
|
|
1003
|
+
* Envelope for a set of events.
|
|
1004
|
+
*/
|
|
1005
|
+
var MessageData = Schema.Struct({
|
|
1006
|
+
meta: Meta,
|
|
1007
|
+
isEphemeral: Schema.Boolean,
|
|
1008
|
+
events: Schema.Array(Event)
|
|
1009
|
+
});
|
|
1010
|
+
var Message = class extends Type.makeObject(DXN.make("org.dxos.type.traceMessage", "0.1.0"))(MessageData.pipe(Annotation.IconAnnotation.set({
|
|
1011
|
+
icon: "ph--note--regular",
|
|
1012
|
+
hue: "rose"
|
|
1013
|
+
}), Annotation.HiddenAnnotation.set(true))) {};
|
|
1014
|
+
/**
|
|
1015
|
+
* Flattens a trace message into a list of flat events.
|
|
1016
|
+
*/
|
|
1017
|
+
var flatten = (message) => {
|
|
1018
|
+
return message.events.map((event) => ({
|
|
1019
|
+
...event,
|
|
1020
|
+
meta: message.meta,
|
|
1021
|
+
isEphemeral: message.isEphemeral
|
|
1022
|
+
}));
|
|
1023
|
+
};
|
|
1024
|
+
/**
|
|
1025
|
+
* `google.protobuf.Any` type URL for a trace message broadcast over the swarm.
|
|
1026
|
+
*/
|
|
1027
|
+
var TRACE_MESSAGE_TYPE_URL = "dxos.compute.TraceMessage";
|
|
1028
|
+
/**
|
|
1029
|
+
* Derive the flat broadcast tag list for a message (DX-1125). The publisher emits all applicable tags;
|
|
1030
|
+
* subscribers match a subset (logical OR).
|
|
1031
|
+
*/
|
|
1032
|
+
var messageToTags = (message) => {
|
|
1033
|
+
const { meta } = message;
|
|
1034
|
+
const tags = [];
|
|
1035
|
+
for (const event of message.events) tags.push(`type:${event.type}`);
|
|
1036
|
+
if (meta.pid) tags.push(`pid:${meta.pid}`);
|
|
1037
|
+
if (meta.parentPid) tags.push(`parentPid:${meta.parentPid}`);
|
|
1038
|
+
if (meta.conversation) tags.push(`conversation:${meta.conversation.uri.toString()}`);
|
|
1039
|
+
if (meta.trigger) tags.push(`trigger:${meta.trigger.uri.toString()}`);
|
|
1040
|
+
if (meta.space) tags.push(`space:${meta.space}`);
|
|
1041
|
+
if (meta.runtimeName) tags.push(`runtime:${meta.runtimeName}`);
|
|
1042
|
+
if (meta.toolCallId) tags.push(`toolCall:${meta.toolCallId}`);
|
|
1043
|
+
return tags;
|
|
1044
|
+
};
|
|
1045
|
+
/**
|
|
1046
|
+
* Pick the coarse subscription tag for a filter (DX-1125). The swarm cuts traffic to a superset of the
|
|
1047
|
+
* filter using its most selective present dimension; the client re-applies the exact filter.
|
|
1048
|
+
*/
|
|
1049
|
+
var subscriptionTagForFilter = (filter) => {
|
|
1050
|
+
if (filter.conversation !== void 0) return `conversation:${filter.conversation}`;
|
|
1051
|
+
if (filter.trigger !== void 0) return `trigger:${filter.trigger}`;
|
|
1052
|
+
if (filter.parentPid !== void 0) return `parentPid:${filter.parentPid}`;
|
|
1053
|
+
if (filter.pid !== void 0) return `pid:${filter.pid}`;
|
|
1054
|
+
if (filter.space !== void 0) return `space:${filter.space}`;
|
|
1055
|
+
if (filter.type !== void 0) return `type:${filter.type}`;
|
|
1056
|
+
};
|
|
1057
|
+
/**
|
|
1058
|
+
* Exact (AND) filter match applied client-side after the coarse swarm subscription.
|
|
1059
|
+
*/
|
|
1060
|
+
var matchesFilter = (message, filter) => {
|
|
1061
|
+
const { meta } = message;
|
|
1062
|
+
if (filter.type !== void 0 && !message.events.some((event) => event.type === filter.type)) return false;
|
|
1063
|
+
if (filter.pid !== void 0 && meta.pid !== filter.pid) return false;
|
|
1064
|
+
if (filter.parentPid !== void 0 && meta.parentPid !== filter.parentPid) return false;
|
|
1065
|
+
if (filter.conversation !== void 0 && meta.conversation?.uri.toString() !== filter.conversation) return false;
|
|
1066
|
+
if (filter.trigger !== void 0 && meta.trigger?.uri.toString() !== filter.trigger) return false;
|
|
1067
|
+
if (filter.space !== void 0 && meta.space !== filter.space) return false;
|
|
1068
|
+
if (filter.runtimeName !== void 0 && meta.runtimeName !== filter.runtimeName) return false;
|
|
1069
|
+
if (filter.toolCallId !== void 0 && meta.toolCallId !== filter.toolCallId) return false;
|
|
1070
|
+
return true;
|
|
1071
|
+
};
|
|
1072
|
+
/**
|
|
1073
|
+
* Wire-safe subset of {@link Meta} for broadcast. Ref fields (`conversation`, `trigger`) are not
|
|
1074
|
+
* carried in the payload — they are represented only as envelope tags — so the decoded message never
|
|
1075
|
+
* attempts ref resolution on the consumer.
|
|
1076
|
+
*/
|
|
1077
|
+
var encodeMetaForWire = (meta) => ({
|
|
1078
|
+
pid: meta.pid,
|
|
1079
|
+
parentPid: meta.parentPid,
|
|
1080
|
+
processName: meta.processName,
|
|
1081
|
+
space: meta.space,
|
|
1082
|
+
toolCallId: meta.toolCallId,
|
|
1083
|
+
runtimeName: meta.runtimeName
|
|
1084
|
+
});
|
|
1085
|
+
/**
|
|
1086
|
+
* Encode a trace message for the broadcast envelope's `google.protobuf.Any.value` (DX-1125).
|
|
1087
|
+
* The wire format is UTF-8 JSON of the message data (ref fields dropped — see {@link encodeMetaForWire}).
|
|
1088
|
+
*/
|
|
1089
|
+
var encodeTraceMessage = (message) => new TextEncoder().encode(JSON.stringify({
|
|
1090
|
+
meta: encodeMetaForWire(message.meta),
|
|
1091
|
+
isEphemeral: message.isEphemeral,
|
|
1092
|
+
events: message.events
|
|
1093
|
+
}));
|
|
1094
|
+
/**
|
|
1095
|
+
* Decode a broadcast trace message back into a {@link Message} object (DX-1125). The wire payload
|
|
1096
|
+
* drops both ref meta fields (see {@link encodeMetaForWire}), so `tags` — the broadcast envelope's
|
|
1097
|
+
* tag list — is required to restore them: `trigger` addresses work for cancellation, and
|
|
1098
|
+
* `conversation` is what {@link matchesFilter} compares, so a subscription filtered by it matches
|
|
1099
|
+
* nothing without this. Restored refs are address-only (`.uri`); they are never resolved.
|
|
1100
|
+
*/
|
|
1101
|
+
var decodeTraceMessage = (bytes, tags) => {
|
|
1102
|
+
const parsed = JSON.parse(new TextDecoder().decode(bytes));
|
|
1103
|
+
const meta = parsed.meta ?? {};
|
|
1104
|
+
const conversation = meta.conversation ?? refFromTags(tags, "conversation:");
|
|
1105
|
+
const trigger = meta.trigger ?? refFromTags(tags, "trigger:");
|
|
1106
|
+
return Obj.make(Message, {
|
|
1107
|
+
meta: {
|
|
1108
|
+
...meta,
|
|
1109
|
+
...conversation ? { conversation } : {},
|
|
1110
|
+
...trigger ? { trigger } : {}
|
|
1111
|
+
},
|
|
1112
|
+
isEphemeral: parsed.isEphemeral ?? true,
|
|
1113
|
+
events: parsed.events ?? []
|
|
1114
|
+
});
|
|
1115
|
+
};
|
|
1116
|
+
/** The ref carried on a broadcast envelope's `<prefix><uri>` tag, when present and parseable. */
|
|
1117
|
+
var refFromTags = (tags, prefix) => {
|
|
1118
|
+
const uri = tags?.find((tag) => tag.startsWith(prefix))?.slice(prefix.length);
|
|
1119
|
+
const eid = uri !== void 0 ? EID.tryParse(uri) : void 0;
|
|
1120
|
+
return eid !== void 0 ? Ref.fromURI(eid) : void 0;
|
|
1121
|
+
};
|
|
1122
|
+
/**
|
|
1123
|
+
* Sink for complete trace messages.
|
|
1124
|
+
* The Process Manager forwards trace messages to it.
|
|
1125
|
+
*/
|
|
1126
|
+
var TraceSink = class extends Context.Tag("@dxos/functions/TraceSink")() {};
|
|
1127
|
+
var noopWriter = { write: () => {} };
|
|
1128
|
+
var writerLayerNoop = Layer.succeed(TraceService, noopWriter);
|
|
1129
|
+
var noopSink = { write: () => {} };
|
|
1130
|
+
var layerNoop = Layer.succeed(TraceSink, noopSink);
|
|
1131
|
+
var layerConsole = Layer.succeed(TraceSink, { write: (message) => {
|
|
1132
|
+
console.log(message);
|
|
1133
|
+
} });
|
|
1134
|
+
/**
|
|
1135
|
+
* Merge a set of sinks into a single sink.
|
|
1136
|
+
*
|
|
1137
|
+
* Each message is forwarded to every sink in order. Failures in one sink do not
|
|
1138
|
+
* prevent downstream sinks from receiving the message.
|
|
1139
|
+
*/
|
|
1140
|
+
var mergeSinks = (sinks) => {
|
|
1141
|
+
if (sinks.length === 0) return noopSink;
|
|
1142
|
+
return { write: (message) => {
|
|
1143
|
+
for (const sink of sinks) try {
|
|
1144
|
+
sink.write(message);
|
|
1145
|
+
} catch (err) {
|
|
1146
|
+
console.error("[trace] sink.write threw", err);
|
|
1147
|
+
}
|
|
1148
|
+
} };
|
|
1149
|
+
};
|
|
1150
|
+
/**
|
|
1151
|
+
* Builds a {@link TraceService} layer that wraps each `write` into a fresh {@link Message}
|
|
1152
|
+
* and forwards it to the provided {@link TraceSink}. Intended for tests and lightweight
|
|
1153
|
+
* fixtures.
|
|
1154
|
+
*
|
|
1155
|
+
* Options:
|
|
1156
|
+
* - `meta`: stamped on every emitted message (defaults to `{}`).
|
|
1157
|
+
* - `clock`: timestamp source (defaults to {@link Date.now}). Pass a monotonic counter
|
|
1158
|
+
* in tests to make event ordering deterministic when many writes happen in the same
|
|
1159
|
+
* millisecond.
|
|
1160
|
+
*/
|
|
1161
|
+
var testTraceService = (opts = {}) => Layer.effect(TraceService, Effect.gen(function* () {
|
|
1162
|
+
const sink = yield* TraceSink;
|
|
1163
|
+
const clock = opts.clock ?? Date.now;
|
|
1164
|
+
return { write: (event, data) => {
|
|
1165
|
+
sink.write(Obj.make(Message, {
|
|
1166
|
+
meta: opts.meta ?? {},
|
|
1167
|
+
isEphemeral: event.isEphemeral,
|
|
1168
|
+
events: [{
|
|
1169
|
+
type: event.key,
|
|
1170
|
+
timestamp: clock(),
|
|
1171
|
+
data
|
|
1172
|
+
}]
|
|
1173
|
+
}));
|
|
1174
|
+
} };
|
|
1175
|
+
}));
|
|
1176
|
+
/**
|
|
1177
|
+
* Operation invocation started.
|
|
1178
|
+
*/
|
|
1179
|
+
var OperationStart = EventType("operation.start", {
|
|
1180
|
+
schema: Schema.Struct({
|
|
1181
|
+
/** Operation key. */
|
|
1182
|
+
key: Schema.String,
|
|
1183
|
+
/** Human-readable operation name. */
|
|
1184
|
+
name: Schema.optional(Schema.String),
|
|
1185
|
+
/** Phosphor icon identifier in `ph--<name>--<variant>` format. */
|
|
1186
|
+
icon: Schema.optional(Schema.String)
|
|
1187
|
+
}),
|
|
1188
|
+
isEphemeral: false
|
|
1189
|
+
});
|
|
1190
|
+
/**
|
|
1191
|
+
* Operation invocation ended.
|
|
1192
|
+
*/
|
|
1193
|
+
var OperationEnd = EventType("operation.end", {
|
|
1194
|
+
schema: Schema.Struct({
|
|
1195
|
+
/** Operation key. */
|
|
1196
|
+
key: Schema.String,
|
|
1197
|
+
/** Human-readable operation name. */
|
|
1198
|
+
name: Schema.optional(Schema.String),
|
|
1199
|
+
/** Phosphor icon identifier in `ph--<name>--<variant>` format. */
|
|
1200
|
+
icon: Schema.optional(Schema.String),
|
|
1201
|
+
/** Outcome of the operation. */
|
|
1202
|
+
outcome: Schema.Literal("success", "failure"),
|
|
1203
|
+
/** Error message if the operation failed. */
|
|
1204
|
+
error: Schema.optional(Schema.String)
|
|
1205
|
+
}),
|
|
1206
|
+
isEphemeral: false
|
|
1207
|
+
});
|
|
1208
|
+
/**
|
|
1209
|
+
* Operation input. Emitted as an ephemeral event alongside {@link OperationStart}
|
|
1210
|
+
* so subscribers (such as the undo/redo history tracker) can observe the raw
|
|
1211
|
+
* input payload without persisting it to long-lived sinks.
|
|
1212
|
+
*/
|
|
1213
|
+
var OperationInput = EventType("operation.input", {
|
|
1214
|
+
schema: Schema.Struct({
|
|
1215
|
+
/** Operation key. */
|
|
1216
|
+
key: Schema.String,
|
|
1217
|
+
/** Human-readable operation name. */
|
|
1218
|
+
name: Schema.optional(Schema.String),
|
|
1219
|
+
/** Raw operation input. Shape determined by the operation definition. */
|
|
1220
|
+
input: Schema.Unknown
|
|
1221
|
+
}),
|
|
1222
|
+
isEphemeral: true
|
|
1223
|
+
});
|
|
1224
|
+
/**
|
|
1225
|
+
* Operation output. Emitted as an ephemeral event just before
|
|
1226
|
+
* {@link OperationEnd} for successful invocations so subscribers (such as the
|
|
1227
|
+
* undo/redo history tracker) can observe the raw output payload without
|
|
1228
|
+
* persisting it to long-lived sinks.
|
|
1229
|
+
*/
|
|
1230
|
+
var OperationOutput = EventType("operation.output", {
|
|
1231
|
+
schema: Schema.Struct({
|
|
1232
|
+
/** Operation key. */
|
|
1233
|
+
key: Schema.String,
|
|
1234
|
+
/** Human-readable operation name. */
|
|
1235
|
+
name: Schema.optional(Schema.String),
|
|
1236
|
+
/** Raw operation output. Shape determined by the operation definition. */
|
|
1237
|
+
output: Schema.Unknown
|
|
1238
|
+
}),
|
|
1239
|
+
isEphemeral: true
|
|
1240
|
+
});
|
|
1241
|
+
/**
|
|
1242
|
+
* Human-readable status update emitted by an agent or operation.
|
|
1243
|
+
*/
|
|
1244
|
+
var StatusUpdate = EventType("status.update", {
|
|
1245
|
+
schema: Schema.Struct({
|
|
1246
|
+
/** Human-readable status message.. */
|
|
1247
|
+
message: Schema.optional(Schema.String),
|
|
1248
|
+
progress: Schema.optional(Schema.Struct({
|
|
1249
|
+
/** Progress key. See {@link ProgressRegistry.key}. */
|
|
1250
|
+
key: Schema.String,
|
|
1251
|
+
current: Schema.optional(Schema.Number),
|
|
1252
|
+
/** Progress total item count. */
|
|
1253
|
+
total: Schema.optional(Schema.Number),
|
|
1254
|
+
/** Progress estimate of remaining time (ms). */
|
|
1255
|
+
estimate: Schema.optional(Schema.Number)
|
|
1256
|
+
}))
|
|
1257
|
+
}),
|
|
1258
|
+
isEphemeral: true
|
|
1259
|
+
});
|
|
1260
|
+
/**
|
|
1261
|
+
* Emit the current human-readable execution status to the trace.
|
|
1262
|
+
*/
|
|
1263
|
+
var emitStatus = (message) => write(StatusUpdate, typeof message === "string" ? { message } : message);
|
|
1264
|
+
//#endregion
|
|
1265
|
+
//#region src/Process.ts
|
|
1266
|
+
var Process_exports = /* @__PURE__ */ __exportAll({
|
|
1267
|
+
ExitedEvent: () => ExitedEvent,
|
|
1268
|
+
HarnessHostAnnotation: () => HarnessHostAnnotation,
|
|
1269
|
+
ID: () => ID,
|
|
1270
|
+
InstructionsAnnotation: () => InstructionsAnnotation,
|
|
1271
|
+
NotifyAnnotation: () => NotifyAnnotation,
|
|
1272
|
+
ProcessMonitorService: () => ProcessMonitorService,
|
|
1273
|
+
ProcessTypeId: () => ProcessTypeId,
|
|
1274
|
+
SpawnedEvent: () => SpawnedEvent,
|
|
1275
|
+
State: () => State,
|
|
1276
|
+
TargetAnnotation: () => TargetAnnotation,
|
|
1277
|
+
fromOperation: () => fromOperation,
|
|
1278
|
+
isProcess: () => isProcess,
|
|
1279
|
+
make: () => make$1,
|
|
1280
|
+
prettyProcessTree: () => prettyProcessTree
|
|
1281
|
+
});
|
|
1282
|
+
var __dxlog_file = "/__w/dxos/dxos/packages/core/compute/compute/src/Process.ts";
|
|
1283
|
+
/** Opaque process id (arbitrary string). */
|
|
1284
|
+
var ID = Schema.String.pipe(Schema.brand("ProcessId"));
|
|
1285
|
+
/**
|
|
1286
|
+
* Attaches the process to a target object.
|
|
1287
|
+
*/
|
|
1288
|
+
var TargetAnnotation = Annotation.make({
|
|
1289
|
+
id: "org.dxos.process.target",
|
|
1290
|
+
schema: URI$1.Schema
|
|
1291
|
+
});
|
|
1292
|
+
/**
|
|
1293
|
+
* Notification descriptor for surfacing process lifecycle events to the user.
|
|
1294
|
+
*/
|
|
1295
|
+
var NotifyAnnotation = Annotation.make({
|
|
1296
|
+
id: "org.dxos.process.notify",
|
|
1297
|
+
schema: NotifyOptions
|
|
1298
|
+
});
|
|
1299
|
+
/**
|
|
1300
|
+
* URI of the Instructions object steering the process's conversation. Persisted at spawn (like
|
|
1301
|
+
* {@link TargetAnnotation}) so a re-hydrated process recovers its steering without reaching the Chat.
|
|
1302
|
+
*/
|
|
1303
|
+
var InstructionsAnnotation = Annotation.make({
|
|
1304
|
+
id: "org.dxos.process.instructions",
|
|
1305
|
+
schema: URI$1.Schema
|
|
1306
|
+
});
|
|
1307
|
+
/**
|
|
1308
|
+
* Marks a process as the harness host for its conversation (discovery substrate).
|
|
1309
|
+
*/
|
|
1310
|
+
var HarnessHostAnnotation = Annotation.make({
|
|
1311
|
+
id: "org.dxos.process.harnessHost",
|
|
1312
|
+
schema: Schema.Boolean
|
|
1313
|
+
});
|
|
1314
|
+
var ProcessTypeId = "~@dxos/functions/Process";
|
|
1315
|
+
var isProcess = (executable) => typeof executable === "object" && executable !== null && "~@dxos/functions/Process" in executable;
|
|
1316
|
+
var make$1 = (opts, create) => {
|
|
1317
|
+
assertArgument(/^[a-z0-9]([a-z0-9.\-/]*[a-z0-9])?$/i.test(opts.key), "key", "Invalid key");
|
|
1318
|
+
return {
|
|
1319
|
+
[ProcessTypeId]: {},
|
|
1320
|
+
...opts,
|
|
1321
|
+
rpcs: opts.rpcs ?? RpcGroup.make(),
|
|
1322
|
+
create: (ctx) => create(ctx).pipe(Effect.map((partial) => ({
|
|
1323
|
+
onSpawn: () => Effect.void,
|
|
1324
|
+
onInput: () => Effect.void,
|
|
1325
|
+
onAlarm: () => Effect.void,
|
|
1326
|
+
onChildEvent: () => Effect.void,
|
|
1327
|
+
...partial,
|
|
1328
|
+
rpcHandlers: sanitizeRpcs(opts.rpcs, partial.rpcHandlers)
|
|
1329
|
+
})))
|
|
1330
|
+
};
|
|
1331
|
+
};
|
|
1332
|
+
var sanitizeRpcs = (defined, provided) => {
|
|
1333
|
+
if (!(defined !== void 0 && defined.requests.size > 0)) return provided ?? Context.empty();
|
|
1334
|
+
if (!provided) throw new TypeError("Process declared RPCs but did not provide any handlers");
|
|
1335
|
+
return provided;
|
|
1336
|
+
};
|
|
1337
|
+
/**
|
|
1338
|
+
* Durable marker recording that an operation's input handler has begun executing.
|
|
1339
|
+
* Persisted before the handler runs so that, after an interruption (suspend/restart), a
|
|
1340
|
+
* re-delivered input can tell that the previous attempt was in-flight. Cleared automatically
|
|
1341
|
+
* when the process reaches a terminal state (the runtime clears the process's storage).
|
|
1342
|
+
*/
|
|
1343
|
+
var OperationStartedCell = cell(Schema.parseJson(Schema.Boolean), "operation/started").pipe(withDefault(() => false));
|
|
1344
|
+
var fromOperation = (op, handler) => make$1({
|
|
1345
|
+
key: DXN$1.getName(op.meta.key),
|
|
1346
|
+
input: op.input,
|
|
1347
|
+
output: op.output,
|
|
1348
|
+
services: op.services
|
|
1349
|
+
}, (ctx) => Effect.gen(function* () {
|
|
1350
|
+
const semaphore = yield* Effect.makeSemaphore(1);
|
|
1351
|
+
const idempotent = isIdempotent(op);
|
|
1352
|
+
return { onInput: (input) => Effect.gen(function* () {
|
|
1353
|
+
if (!idempotent) {
|
|
1354
|
+
if (yield* OperationStartedCell.get) return yield* Effect.die(/* @__PURE__ */ new Error(`non-idempotent operation "${op.meta.key}" was interrupted; cannot retry safely`));
|
|
1355
|
+
yield* OperationStartedCell.set(true);
|
|
1356
|
+
}
|
|
1357
|
+
log("operation process invoking", {
|
|
1358
|
+
key: op.meta.key,
|
|
1359
|
+
name: op.meta.name
|
|
1360
|
+
}, {
|
|
1361
|
+
"~LogMeta": "~LogMeta",
|
|
1362
|
+
F: __dxlog_file,
|
|
1363
|
+
L: 375,
|
|
1364
|
+
S: this
|
|
1365
|
+
});
|
|
1366
|
+
yield* write(OperationStart, {
|
|
1367
|
+
key: op.meta.key,
|
|
1368
|
+
name: op.meta.name,
|
|
1369
|
+
icon: op.meta.icon
|
|
1370
|
+
});
|
|
1371
|
+
yield* write(OperationInput, {
|
|
1372
|
+
key: op.meta.key,
|
|
1373
|
+
name: op.meta.name,
|
|
1374
|
+
input
|
|
1375
|
+
});
|
|
1376
|
+
const output = yield* (yield* getHandler(handler, op).pipe(Effect.orDie)).handler(input).pipe(Effect.orDie, Effect.withSpan(op.meta.key));
|
|
1377
|
+
ctx.submitOutput(output);
|
|
1378
|
+
ctx.succeed();
|
|
1379
|
+
yield* write(OperationOutput, {
|
|
1380
|
+
key: op.meta.key,
|
|
1381
|
+
name: op.meta.name,
|
|
1382
|
+
output
|
|
1383
|
+
});
|
|
1384
|
+
yield* write(OperationEnd, {
|
|
1385
|
+
key: op.meta.key,
|
|
1386
|
+
name: op.meta.name,
|
|
1387
|
+
icon: op.meta.icon,
|
|
1388
|
+
outcome: "success"
|
|
1389
|
+
});
|
|
1390
|
+
}).pipe(Effect.catchAllDefect((defect) => Effect.gen(function* () {
|
|
1391
|
+
const errorMessage = defect instanceof Error ? defect.message : String(defect);
|
|
1392
|
+
yield* write(OperationEnd, {
|
|
1393
|
+
key: op.meta.key,
|
|
1394
|
+
name: op.meta.name,
|
|
1395
|
+
icon: op.meta.icon,
|
|
1396
|
+
outcome: "failure",
|
|
1397
|
+
error: errorMessage
|
|
1398
|
+
});
|
|
1399
|
+
return yield* Effect.die(defect);
|
|
1400
|
+
})), semaphore.withPermits(1)) };
|
|
1401
|
+
}));
|
|
1402
|
+
/**
|
|
1403
|
+
* Runtime state of a process.
|
|
1404
|
+
*/
|
|
1405
|
+
var State = /* @__PURE__ */ function(State) {
|
|
1406
|
+
State["RUNNING"] = "RUNNING";
|
|
1407
|
+
State["HYBERNATING"] = "HYBERNATING";
|
|
1408
|
+
State["IDLE"] = "IDLE";
|
|
1409
|
+
State["TERMINATING"] = "TERMINATING";
|
|
1410
|
+
State["TERMINATED"] = "TERMINATED";
|
|
1411
|
+
State["SUCCEEDED"] = "SUCCEEDED";
|
|
1412
|
+
State["FAILED"] = "FAILED";
|
|
1413
|
+
return State;
|
|
1414
|
+
}({});
|
|
1415
|
+
var ProcessMonitorService = class extends Context.Tag("@dxos/functions/ProcessMonitorService")() {};
|
|
1416
|
+
/**
|
|
1417
|
+
* New process is spawned.
|
|
1418
|
+
*/
|
|
1419
|
+
var SpawnedEvent = EventType("process.spawned", {
|
|
1420
|
+
schema: Schema.Void,
|
|
1421
|
+
isEphemeral: false
|
|
1422
|
+
});
|
|
1423
|
+
/**
|
|
1424
|
+
* Process has reached a terminal state.
|
|
1425
|
+
*/
|
|
1426
|
+
var ExitedEvent = EventType("process.exited", {
|
|
1427
|
+
schema: Schema.Struct({ outcome: Schema.Literal("succeeded", "failed", "terminated") }),
|
|
1428
|
+
isEphemeral: false
|
|
1429
|
+
});
|
|
1430
|
+
/**
|
|
1431
|
+
* Renders spawned processes as a forest: top-level rows use "- ", nested rows use ├── / └── / │.
|
|
1432
|
+
*/
|
|
1433
|
+
var prettyProcessTree = (tree) => {
|
|
1434
|
+
if (tree.length === 0) return "";
|
|
1435
|
+
const pidSet = new Set(tree.map((node) => node.pid));
|
|
1436
|
+
const childrenByParent = /* @__PURE__ */ new Map();
|
|
1437
|
+
const roots = [];
|
|
1438
|
+
for (const node of tree) {
|
|
1439
|
+
const parent = node.parentPid;
|
|
1440
|
+
if (parent === null || !pidSet.has(parent)) {
|
|
1441
|
+
roots.push(node);
|
|
1442
|
+
continue;
|
|
1443
|
+
}
|
|
1444
|
+
const key = String(parent);
|
|
1445
|
+
const siblings = childrenByParent.get(key) ?? [];
|
|
1446
|
+
siblings.push(node);
|
|
1447
|
+
childrenByParent.set(key, siblings);
|
|
1448
|
+
}
|
|
1449
|
+
const byPid = (a, b) => String(a.pid).localeCompare(String(b.pid));
|
|
1450
|
+
roots.sort(byPid);
|
|
1451
|
+
for (const siblings of childrenByParent.values()) siblings.sort(byPid);
|
|
1452
|
+
const formatLabel = (node) => {
|
|
1453
|
+
const parts = [String(node.pid).slice(0, 6), node.state];
|
|
1454
|
+
if (node.params.name != null && node.params.name !== "") parts.push(node.params.name);
|
|
1455
|
+
if (node.error != null) parts.push(`(${node.error.message ?? node.error.name ?? "error"})`);
|
|
1456
|
+
const { inputCount, outputCount, wallTime } = node.metrics;
|
|
1457
|
+
parts.push(`[in:${inputCount} out:${outputCount} wall:${Math.round(wallTime)}ms]`);
|
|
1458
|
+
return parts.join(" ");
|
|
1459
|
+
};
|
|
1460
|
+
const lines = [];
|
|
1461
|
+
const walk = (node, prefix, isLast, isRoot) => {
|
|
1462
|
+
if (isRoot) lines.push(`- ${formatLabel(node)}`);
|
|
1463
|
+
else {
|
|
1464
|
+
const branch = isLast ? "└── " : "├── ";
|
|
1465
|
+
lines.push(`${prefix}${branch}${formatLabel(node)}`);
|
|
1466
|
+
}
|
|
1467
|
+
const children = childrenByParent.get(String(node.pid)) ?? [];
|
|
1468
|
+
const nextPrefix = isRoot ? " " : `${prefix}${isLast ? " " : "│ "}`;
|
|
1469
|
+
children.forEach((child, index) => {
|
|
1470
|
+
walk(child, nextPrefix, index === children.length - 1, false);
|
|
1471
|
+
});
|
|
1472
|
+
};
|
|
1473
|
+
for (const root of roots) walk(root, "", true, true);
|
|
1474
|
+
return lines.join("\n");
|
|
1475
|
+
};
|
|
1476
|
+
//#endregion
|
|
1477
|
+
//#region src/ServiceResolver.ts
|
|
1478
|
+
var ServiceResolver_exports = /* @__PURE__ */ __exportAll({
|
|
1479
|
+
ServiceResolver: () => ServiceResolver,
|
|
1480
|
+
compose: () => compose,
|
|
1481
|
+
empty: () => empty,
|
|
1482
|
+
fromContext: () => fromContext,
|
|
1483
|
+
fromRequirements: () => fromRequirements,
|
|
1484
|
+
layerRequirements: () => layerRequirements,
|
|
1485
|
+
make: () => make,
|
|
1486
|
+
provide: () => provide,
|
|
1487
|
+
resolve: () => resolve,
|
|
1488
|
+
resolveAll: () => resolveAll,
|
|
1489
|
+
succeed: () => succeed
|
|
1490
|
+
});
|
|
1491
|
+
var ServiceResolverTypeId = "~@dxos/functions/ServiceResolver";
|
|
1492
|
+
/**
|
|
1493
|
+
* Tag for the ServiceResolver service.
|
|
1494
|
+
*/
|
|
1495
|
+
var ServiceResolver = Context.GenericTag("@dxos/functions/ServiceResolver");
|
|
1496
|
+
var resolve = Effect.serviceFunctionEffect(ServiceResolver, (_) => _.resolve);
|
|
1497
|
+
var resolveAll = (tags, context) => Effect.gen(function* () {
|
|
1498
|
+
const services = yield* Effect.forEach(tags, (tag) => resolve(tag, context).pipe(Effect.map((service) => Context.make(tag, service))));
|
|
1499
|
+
return Context.mergeAll(...services);
|
|
1500
|
+
});
|
|
1501
|
+
var succeed = (tag, getService) => {
|
|
1502
|
+
return make((tag1, context) => {
|
|
1503
|
+
if (tag1.key !== tag.key) return Effect.fail(new ServiceNotAvailableError(`Service not available: ${String(tag.key ?? tag)}`));
|
|
1504
|
+
return getService(context);
|
|
1505
|
+
});
|
|
1506
|
+
};
|
|
1507
|
+
/**
|
|
1508
|
+
* Create a ServiceResolver from a custom resolution function.
|
|
1509
|
+
*/
|
|
1510
|
+
var make = (resolveFn) => ({
|
|
1511
|
+
[ServiceResolverTypeId]: ServiceResolverTypeId,
|
|
1512
|
+
resolve: resolveFn
|
|
1513
|
+
});
|
|
1514
|
+
/**
|
|
1515
|
+
* Create a ServiceResolver backed by a static Context.
|
|
1516
|
+
* Tags present in the context are resolved; missing tags fail with ServiceNotAvailableError.
|
|
1517
|
+
*/
|
|
1518
|
+
var fromContext = (ctx) => make((tag, context) => Effect.gen(function* () {
|
|
1519
|
+
const service = Context.getOption(ctx, tag);
|
|
1520
|
+
if (Option.isNone(service)) return yield* Effect.fail(new ServiceNotAvailableError(String(tag.key ?? tag)));
|
|
1521
|
+
return service.value;
|
|
1522
|
+
}));
|
|
1523
|
+
/**
|
|
1524
|
+
* Create a ServiceResolver that resolves tags from the current Effect context.
|
|
1525
|
+
* Only the specified tags are available; requests for other tags fail.
|
|
1526
|
+
*/
|
|
1527
|
+
var fromRequirements = (...tags) => Effect.contextWith((parentCtx) => {
|
|
1528
|
+
const available = new Set(tags.map((tag) => tag.key));
|
|
1529
|
+
return make((tag, context) => Effect.gen(function* () {
|
|
1530
|
+
Context.empty();
|
|
1531
|
+
if (!available.has(tag.key)) return yield* Effect.fail(new ServiceNotAvailableError(String(tag.key ?? tag)));
|
|
1532
|
+
const service = Context.getOption(parentCtx, tag);
|
|
1533
|
+
if (Option.isNone(service)) return yield* Effect.fail(new ServiceNotAvailableError(String(tag.key ?? tag)));
|
|
1534
|
+
return service.value;
|
|
1535
|
+
}));
|
|
1536
|
+
});
|
|
1537
|
+
/**
|
|
1538
|
+
* Like {@link fromRequirements} but returns a Layer that provides ServiceResolver.
|
|
1539
|
+
*/
|
|
1540
|
+
var layerRequirements = (...tags) => Layer.effect(ServiceResolver, fromRequirements(...tags));
|
|
1541
|
+
/**
|
|
1542
|
+
* Build a {@link Layer} that materialises the requested services by calling
|
|
1543
|
+
* {@link resolveAll} against the {@link ServiceResolver} currently in context.
|
|
1544
|
+
*
|
|
1545
|
+
* The returned layer manages its own {@link Scope.Scope} and requires only a
|
|
1546
|
+
* {@link ServiceResolver} (typically supplied by the process-manager runtime).
|
|
1547
|
+
*
|
|
1548
|
+
* @example
|
|
1549
|
+
* ```ts
|
|
1550
|
+
* processManagerRuntime.runPromise(
|
|
1551
|
+
* myEffect.pipe(Effect.provide(ServiceResolver.provide({ space }, Database.Service))),
|
|
1552
|
+
* );
|
|
1553
|
+
* ```
|
|
1554
|
+
*/
|
|
1555
|
+
var provide = (context, ...tags) => Layer.scopedContext(resolveAll(tags, context));
|
|
1556
|
+
/**
|
|
1557
|
+
* Compose multiple resolvers left to right. Earlier resolvers take precedence:
|
|
1558
|
+
* the first resolver that can satisfy a tag wins.
|
|
1559
|
+
*/
|
|
1560
|
+
var compose = (...resolvers) => make((tag, context) => Effect.gen(function* () {
|
|
1561
|
+
for (const resolver of resolvers) {
|
|
1562
|
+
const single = yield* resolver.resolve(tag, context).pipe(Effect.either);
|
|
1563
|
+
if (Either.isRight(single)) return single.right;
|
|
1564
|
+
}
|
|
1565
|
+
return yield* Effect.fail(new ServiceNotAvailableError(String(tag.key ?? tag)));
|
|
1566
|
+
}));
|
|
1567
|
+
/**
|
|
1568
|
+
* An empty resolver that fails for any requested service.
|
|
1569
|
+
*/
|
|
1570
|
+
var empty = make((tag, context) => {
|
|
1571
|
+
return Effect.fail(new ServiceNotAvailableError(String(tag.key ?? tag)));
|
|
1572
|
+
});
|
|
1573
|
+
//#endregion
|
|
1574
|
+
export { AgentIdentity_exports as AgentIdentity, AgentService_exports as AgentService, Cancellation_exports as Cancellation, Credential_exports as Credential, FunctionError, FunctionNotFoundError, FunctionsAiMemoizationMissError, FunctionsAiUpstreamError, Header_exports as Header, Instructions_exports as Instructions, InvalidOperationInputError, InvalidOperationOutputError, InvokerNotInitializedError, LayerSpec_exports as LayerSpec, McpServer_exports as McpServer, NoHandlerError, Operation_exports as Operation, OperationHandlerSet_exports as OperationHandlerSet, OperationRegistry_exports as OperationRegistry, Process_exports as Process, Project_exports as Project, Routine_exports as Routine, RunAgainError, Runnable_exports as Runnable, Script_exports as Script, ServiceNotAvailableError, ServiceResolver_exports as ServiceResolver, Skill_exports as Skill, StorageService_exports as StorageService, Template_exports as Template, Trace_exports as Trace, Trigger_exports as Trigger, TriggerEvent_exports as TriggerEvent, TriggerStateNotFoundError };
|
|
1575
|
+
|
|
1576
|
+
//# sourceMappingURL=index.mjs.map
|