@dxos/compute 0.9.0 → 0.9.1-staging.ee54ba693a
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -4
- package/dist/lib/neutral/AgentService.mjs +12 -0
- package/dist/lib/neutral/StorageService.mjs +3 -3
- package/dist/lib/neutral/{chunk-AFBNVFAY.mjs → chunk-2ZN64ZS7.mjs} +3 -3
- package/dist/lib/neutral/{chunk-JAU4E4EK.mjs → chunk-5VAXF6AH.mjs} +2 -2
- package/dist/lib/neutral/{chunk-QZS4G6PE.mjs → chunk-EVROJER7.mjs} +70 -25
- package/dist/lib/neutral/chunk-EVROJER7.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-XEVFBI6S.mjs → chunk-PF7XP7XP.mjs} +13 -13
- package/dist/lib/neutral/{chunk-XEVFBI6S.mjs.map → chunk-PF7XP7XP.mjs.map} +3 -3
- package/dist/lib/neutral/{chunk-MEPE4HHX.mjs → chunk-SJ37RWHU.mjs} +3 -3
- package/dist/lib/neutral/chunk-VSAZPWSJ.mjs +25 -0
- package/dist/lib/neutral/chunk-VSAZPWSJ.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-2B2KSJT6.mjs → chunk-WEO4FCQY.mjs} +3 -3
- package/dist/lib/neutral/fib-5XIYECL5.mjs +10 -0
- package/dist/lib/neutral/index.mjs +448 -399
- package/dist/lib/neutral/index.mjs.map +4 -4
- package/dist/lib/neutral/meta.json +1 -1
- package/dist/lib/neutral/reply-GCBRCUVM.mjs +10 -0
- package/dist/lib/neutral/sleep-XR6CL6W3.mjs +10 -0
- package/dist/lib/neutral/sleep-XR6CL6W3.mjs.map +7 -0
- package/dist/lib/neutral/testing/index.mjs +6 -6
- package/dist/types/src/AgentService.d.ts +71 -0
- package/dist/types/src/AgentService.d.ts.map +1 -0
- package/dist/types/src/Credential.d.ts +2 -0
- package/dist/types/src/Credential.d.ts.map +1 -1
- package/dist/types/src/Instructions.d.ts +33 -0
- package/dist/types/src/Instructions.d.ts.map +1 -0
- package/dist/types/src/McpServer.d.ts +1 -1
- package/dist/types/src/Operation.d.ts +92 -27
- package/dist/types/src/Operation.d.ts.map +1 -1
- package/dist/types/src/Operation.test.d.ts +2 -0
- package/dist/types/src/Operation.test.d.ts.map +1 -0
- package/dist/types/src/Process.d.ts +55 -21
- package/dist/types/src/Process.d.ts.map +1 -1
- package/dist/types/src/Runnable.d.ts +4 -0
- package/dist/types/src/Runnable.d.ts.map +1 -0
- package/dist/types/src/Script.d.ts +9 -11
- package/dist/types/src/Script.d.ts.map +1 -1
- package/dist/types/src/ServiceResolver.d.ts +1 -1
- package/dist/types/src/Skill.d.ts +157 -0
- package/dist/types/src/Skill.d.ts.map +1 -0
- package/dist/types/src/StorageService.d.ts +8 -8
- package/dist/types/src/StorageService.d.ts.map +1 -1
- package/dist/types/src/Template.d.ts +2 -4
- package/dist/types/src/Template.d.ts.map +1 -1
- package/dist/types/src/Trace.d.ts +16 -14
- package/dist/types/src/Trace.d.ts.map +1 -1
- package/dist/types/src/Trigger.d.ts +26 -61
- package/dist/types/src/Trigger.d.ts.map +1 -1
- package/dist/types/src/TriggerEvent.d.ts +3 -11
- package/dist/types/src/TriggerEvent.d.ts.map +1 -1
- package/dist/types/src/index.d.ts +5 -3
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +22 -16
- package/src/AgentService.ts +90 -0
- package/src/Credential.ts +3 -0
- package/src/Instructions.ts +73 -0
- package/src/McpServer.ts +1 -1
- package/src/Operation.test.ts +39 -0
- package/src/Operation.ts +130 -54
- package/src/Process.ts +96 -26
- package/src/Runnable.ts +12 -0
- package/src/Script.ts +14 -14
- package/src/ServiceResolver.ts +1 -1
- package/src/Skill.ts +218 -0
- package/src/StorageService.ts +15 -12
- package/src/Template.ts +2 -1
- package/src/Trace.ts +13 -11
- package/src/Trigger.ts +57 -52
- package/src/index.ts +5 -3
- package/src/umbrella.test.ts +8 -6
- package/dist/lib/neutral/chunk-QZS4G6PE.mjs.map +0 -7
- package/dist/lib/neutral/fib-HBDUGQW7.mjs +0 -10
- package/dist/lib/neutral/reply-RJIAJ6FV.mjs +0 -10
- package/dist/lib/neutral/sleep-3T2CZ7RE.mjs +0 -10
- package/dist/types/src/Blueprint.d.ts +0 -182
- package/dist/types/src/Blueprint.d.ts.map +0 -1
- package/dist/types/src/Routine.d.ts +0 -54
- package/dist/types/src/Routine.d.ts.map +0 -1
- package/src/Blueprint.ts +0 -224
- package/src/Routine.ts +0 -68
- /package/dist/lib/neutral/{fib-HBDUGQW7.mjs.map → AgentService.mjs.map} +0 -0
- /package/dist/lib/neutral/{chunk-AFBNVFAY.mjs.map → chunk-2ZN64ZS7.mjs.map} +0 -0
- /package/dist/lib/neutral/{chunk-JAU4E4EK.mjs.map → chunk-5VAXF6AH.mjs.map} +0 -0
- /package/dist/lib/neutral/{chunk-MEPE4HHX.mjs.map → chunk-SJ37RWHU.mjs.map} +0 -0
- /package/dist/lib/neutral/{chunk-2B2KSJT6.mjs.map → chunk-WEO4FCQY.mjs.map} +0 -0
- /package/dist/lib/neutral/{reply-RJIAJ6FV.mjs.map → fib-5XIYECL5.mjs.map} +0 -0
- /package/dist/lib/neutral/{sleep-3T2CZ7RE.mjs.map → reply-GCBRCUVM.mjs.map} +0 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dxos/compute",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.1-staging.ee54ba693a",
|
|
4
4
|
"description": "Umbrella package for AI-aware DXOS compute primitives.",
|
|
5
5
|
"homepage": "https://dxos.org",
|
|
6
6
|
"bugs": "https://github.com/dxos/dxos/issues",
|
|
@@ -18,6 +18,11 @@
|
|
|
18
18
|
"types": "./dist/types/src/index.d.ts",
|
|
19
19
|
"default": "./dist/lib/neutral/index.mjs"
|
|
20
20
|
},
|
|
21
|
+
"./AgentService": {
|
|
22
|
+
"source": "./src/AgentService.ts",
|
|
23
|
+
"types": "./dist/types/src/AgentService.d.ts",
|
|
24
|
+
"default": "./dist/lib/neutral/AgentService.mjs"
|
|
25
|
+
},
|
|
21
26
|
"./StorageService": {
|
|
22
27
|
"source": "./src/StorageService.ts",
|
|
23
28
|
"types": "./dist/types/src/StorageService.d.ts",
|
|
@@ -36,25 +41,26 @@
|
|
|
36
41
|
],
|
|
37
42
|
"dependencies": {
|
|
38
43
|
"@effect-atom/atom": "^0.5.3",
|
|
39
|
-
"@effect/platform": "0.96.
|
|
40
|
-
"@
|
|
41
|
-
"@dxos/
|
|
42
|
-
"@dxos/
|
|
43
|
-
"@dxos/effect": "0.9.
|
|
44
|
-
"@dxos/invariant": "0.9.
|
|
45
|
-
"@dxos/keys": "0.9.
|
|
46
|
-
"@dxos/
|
|
47
|
-
"@dxos/
|
|
48
|
-
"@dxos/
|
|
49
|
-
"@dxos/
|
|
44
|
+
"@effect/platform": "0.96.2",
|
|
45
|
+
"@effect/rpc": "0.75.1",
|
|
46
|
+
"@dxos/ai": "0.9.1-staging.ee54ba693a",
|
|
47
|
+
"@dxos/echo": "0.9.1-staging.ee54ba693a",
|
|
48
|
+
"@dxos/effect": "0.9.1-staging.ee54ba693a",
|
|
49
|
+
"@dxos/invariant": "0.9.1-staging.ee54ba693a",
|
|
50
|
+
"@dxos/keys": "0.9.1-staging.ee54ba693a",
|
|
51
|
+
"@dxos/errors": "0.9.1-staging.ee54ba693a",
|
|
52
|
+
"@dxos/log": "0.9.1-staging.ee54ba693a",
|
|
53
|
+
"@dxos/vendor-kbn-handlebars": "0.9.1-staging.ee54ba693a",
|
|
54
|
+
"@dxos/schema": "0.9.1-staging.ee54ba693a",
|
|
55
|
+
"@dxos/protocols": "0.9.1-staging.ee54ba693a"
|
|
50
56
|
},
|
|
51
57
|
"devDependencies": {
|
|
52
|
-
"effect": "3.21.
|
|
53
|
-
"vitest": "4.1.
|
|
54
|
-
"@dxos/echo-client": "0.9.
|
|
58
|
+
"effect": "3.21.4",
|
|
59
|
+
"vitest": "4.1.8",
|
|
60
|
+
"@dxos/echo-client": "0.9.1-staging.ee54ba693a"
|
|
55
61
|
},
|
|
56
62
|
"peerDependencies": {
|
|
57
|
-
"effect": "3.21.
|
|
63
|
+
"effect": "3.21.4"
|
|
58
64
|
},
|
|
59
65
|
"publishConfig": {
|
|
60
66
|
"access": "public"
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2026 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
// @import-as-namespace
|
|
6
|
+
|
|
7
|
+
import * as Context from 'effect/Context';
|
|
8
|
+
import * as Effect from 'effect/Effect';
|
|
9
|
+
import type * as Stream from 'effect/Stream';
|
|
10
|
+
|
|
11
|
+
import type { Database, Feed, Obj, Ref } from '@dxos/echo';
|
|
12
|
+
import { DXN } from '@dxos/keys';
|
|
13
|
+
|
|
14
|
+
import type * as Trace from './Trace';
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Service interface for the agent session manager.
|
|
18
|
+
* Implementation lives in @dxos/functions-runtime.
|
|
19
|
+
*/
|
|
20
|
+
export interface Service {
|
|
21
|
+
/**
|
|
22
|
+
* Gets or creates a session for a feed.
|
|
23
|
+
*/
|
|
24
|
+
getSession: (feed: Feed.Feed, options?: GetSessionOptions) => Effect.Effect<Session>;
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Hydrates agent processes persisted by a previous session.
|
|
28
|
+
* Each record is rehydrated with a fresh process built from the layer options.
|
|
29
|
+
*/
|
|
30
|
+
hydrate: () => Effect.Effect<void>;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export class AgentService extends Context.Tag('@dxos/functions-runtime/AgentService')<AgentService, Service>() {}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Handle to an agent session.
|
|
37
|
+
*/
|
|
38
|
+
export interface Session {
|
|
39
|
+
/**
|
|
40
|
+
* The feed that the session is associated with.
|
|
41
|
+
*/
|
|
42
|
+
readonly feed: Feed.Feed;
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Gets the context objects from the agent.
|
|
46
|
+
*/
|
|
47
|
+
getContext: () => Effect.Effect<Ref.Ref<Obj.Unknown>[], never, Database.Service>;
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Adds context objects to the agent.
|
|
51
|
+
*/
|
|
52
|
+
addContext: (context: Ref.Ref<Obj.Unknown>[]) => Effect.Effect<void, never, Database.Service>;
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Submits a prompt to the agent.
|
|
56
|
+
*/
|
|
57
|
+
submitPrompt: (prompt: string) => Effect.Effect<void>;
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Wait until agent has completed its work.
|
|
61
|
+
*/
|
|
62
|
+
waitForCompletion: () => Effect.Effect<void>;
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Terminates the agent process and clears its durable storage.
|
|
66
|
+
*/
|
|
67
|
+
terminate: () => Effect.Effect<void>;
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Subscribe to ephemeral trace events (e.g., streaming partial messages).
|
|
71
|
+
* Replays buffered events, then streams new ones until the process ends.
|
|
72
|
+
*
|
|
73
|
+
* When forking a collector from a short-lived parent (e.g. `useEffect` +
|
|
74
|
+
* `runPromise(Effect.forEach(subscribe))`), use {@link Effect.forkDaemon} so the
|
|
75
|
+
* stream survives after the parent scope closes; interrupt it on dispose.
|
|
76
|
+
*/
|
|
77
|
+
subscribeEphemeral: () => Stream.Stream<Trace.Message>;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export const getSession = Effect.serviceFunctionEffect(AgentService, (service) => service.getSession);
|
|
81
|
+
|
|
82
|
+
export const hydrate = Effect.serviceFunctionEffect(AgentService, (service) => service.hydrate);
|
|
83
|
+
|
|
84
|
+
export interface GetSessionOptions {
|
|
85
|
+
readonly model?: DXN.DXN;
|
|
86
|
+
// The catalog's shared model ids are served by several providers, so the provider must accompany
|
|
87
|
+
// the model into the agent process — the id alone does not identify a resolver.
|
|
88
|
+
readonly provider?: DXN.DXN;
|
|
89
|
+
readonly systemPrompt?: string;
|
|
90
|
+
}
|
package/src/Credential.ts
CHANGED
|
@@ -19,6 +19,9 @@ export type ServiceCredential = {
|
|
|
19
19
|
|
|
20
20
|
// TODO(dmaretskyi): Build out.
|
|
21
21
|
apiKey?: string;
|
|
22
|
+
|
|
23
|
+
/** Non-secret secondary identifier carried alongside the credential (e.g. an account id or report id). */
|
|
24
|
+
account?: string;
|
|
22
25
|
};
|
|
23
26
|
|
|
24
27
|
export class CredentialsService extends Context.Tag('@dxos/functions/CredentialsService')<
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2025 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
// @import-as-namespace
|
|
6
|
+
|
|
7
|
+
import * as Schema from 'effect/Schema';
|
|
8
|
+
|
|
9
|
+
import { Annotation, DXN, Format, JsonSchema, Obj, Ref, Type } from '@dxos/echo';
|
|
10
|
+
import { Text } from '@dxos/schema';
|
|
11
|
+
|
|
12
|
+
import * as Skill from './Skill';
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Prompt-based operation.
|
|
16
|
+
* May reference skills and additional context.
|
|
17
|
+
* Hidden from the navtree and object picker — accessed only through Routines.
|
|
18
|
+
*/
|
|
19
|
+
export class Instructions extends Type.makeObject<Instructions>(DXN.make('org.dxos.type.instructions', '0.1.0'))(
|
|
20
|
+
Schema.Struct({
|
|
21
|
+
name: Schema.optional(Schema.String),
|
|
22
|
+
description: Schema.optional(Schema.String),
|
|
23
|
+
input: JsonSchema.JsonSchema.pipe(Annotation.FormInputAnnotation.set(false)).annotations({
|
|
24
|
+
description: 'Input schema',
|
|
25
|
+
}),
|
|
26
|
+
output: JsonSchema.JsonSchema.pipe(Annotation.FormInputAnnotation.set(false)).annotations({
|
|
27
|
+
description: 'Output schema',
|
|
28
|
+
}),
|
|
29
|
+
text: Ref.Ref(Text.Text).pipe(
|
|
30
|
+
Format.FormatAnnotation.set(Format.TypeFormat.Markdown),
|
|
31
|
+
Schema.annotations({ title: 'Instructions', description: 'Describe what the agent should do in each session.' }),
|
|
32
|
+
),
|
|
33
|
+
skills: Schema.Array(Ref.Ref(Skill.Skill)),
|
|
34
|
+
/**
|
|
35
|
+
* Context objects bound to the agent's session when this routine runs (sibling of `skills`).
|
|
36
|
+
* Generic `Ref.Ref(Obj.Unknown)` so any space object qualifies. Honored on every run path that
|
|
37
|
+
* executes a routine through the agent prompt, not only triggered automations.
|
|
38
|
+
*/
|
|
39
|
+
objects: Schema.Array(Ref.Ref(Obj.Unknown)).pipe(Schema.annotations({ title: 'Objects' }), Schema.optional),
|
|
40
|
+
}).pipe(
|
|
41
|
+
Annotation.LabelAnnotation.set(['name']),
|
|
42
|
+
Annotation.IconAnnotation.set({ icon: 'ph--scroll--regular', hue: 'sky' }),
|
|
43
|
+
Annotation.HiddenAnnotation.set(true),
|
|
44
|
+
),
|
|
45
|
+
) {}
|
|
46
|
+
|
|
47
|
+
export type MakeProps = {
|
|
48
|
+
name?: string;
|
|
49
|
+
description?: string;
|
|
50
|
+
input?: Schema.Schema.AnyNoContext;
|
|
51
|
+
output?: Schema.Schema.AnyNoContext;
|
|
52
|
+
text?: string;
|
|
53
|
+
skills?: Ref.Ref<Skill.Skill>[];
|
|
54
|
+
objects?: Ref.Ref<Obj.Unknown>[];
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
/** Creates an Instructions object with an owned Markdown `text` body (parented so it cascades and deep-clones). */
|
|
58
|
+
export const make = ({ name, description, input, output, text, skills = [], objects }: MakeProps): Instructions => {
|
|
59
|
+
const body = Text.make({ content: text ?? '' });
|
|
60
|
+
const instructions = Obj.make(Instructions, {
|
|
61
|
+
name,
|
|
62
|
+
description,
|
|
63
|
+
input: JsonSchema.toJsonSchema(input ?? Schema.Void),
|
|
64
|
+
output: JsonSchema.toJsonSchema(output ?? Schema.Void),
|
|
65
|
+
text: Ref.make(body),
|
|
66
|
+
skills,
|
|
67
|
+
objects,
|
|
68
|
+
});
|
|
69
|
+
// The body is owned by the instructions: it cascade-deletes with it and is cloned alongside it under
|
|
70
|
+
// `Obj.clone(..., { deep: 'parent' })`.
|
|
71
|
+
Obj.setParent(body, instructions);
|
|
72
|
+
return instructions;
|
|
73
|
+
};
|
package/src/McpServer.ts
CHANGED
|
@@ -9,7 +9,7 @@ import * as Schema from 'effect/Schema';
|
|
|
9
9
|
/**
|
|
10
10
|
* MCP server connection spec — the minimal fields needed to dial an MCP server.
|
|
11
11
|
*
|
|
12
|
-
* Used as a value type embedded in
|
|
12
|
+
* Used as a value type embedded in skills and passed to runtime session connect logic.
|
|
13
13
|
* The user-facing ECHO object (`@dxos/assistant-toolkit` `McpServer`) composes this struct
|
|
14
14
|
* and adds instance-level fields (`name`, `enabled`) and ECHO annotations.
|
|
15
15
|
*/
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2026 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import * as Effect from 'effect/Effect';
|
|
6
|
+
import * as Schema from 'effect/Schema';
|
|
7
|
+
import { describe, test } from 'vitest';
|
|
8
|
+
|
|
9
|
+
import { DXN } from '@dxos/keys';
|
|
10
|
+
|
|
11
|
+
import * as Operation from './Operation';
|
|
12
|
+
|
|
13
|
+
const KEY = DXN.make('org.example.test.op');
|
|
14
|
+
|
|
15
|
+
const makeOp = () => Operation.make({ input: Schema.Void, output: Schema.String, meta: { key: KEY, name: 'Test Op' } });
|
|
16
|
+
|
|
17
|
+
describe('Operation visibility', () => {
|
|
18
|
+
test('operations are hidden by default', ({ expect }) => {
|
|
19
|
+
expect(Operation.isVisible(Operation.serialize(makeOp()))).toBe(false);
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
test('visible combinator marks an operation visible', ({ expect }) => {
|
|
23
|
+
expect(Operation.isVisible(Operation.serialize(makeOp().pipe(Operation.visible)))).toBe(true);
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
test('annotate does not mutate the input definition', ({ expect }) => {
|
|
27
|
+
const op = makeOp();
|
|
28
|
+
const annotated = op.pipe(Operation.visible);
|
|
29
|
+
expect(Operation.isVisible(Operation.serialize(annotated))).toBe(true);
|
|
30
|
+
// The original definition is untouched — combinators return a fresh value.
|
|
31
|
+
expect(Operation.isVisible(Operation.serialize(op))).toBe(false);
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
test('visible preserves the definition type so a handler still attaches', ({ expect }) => {
|
|
35
|
+
// Type-preservation is a compile-time guarantee; this asserts the value path also works.
|
|
36
|
+
const op = makeOp().pipe(Operation.visible, (op) => Operation.withHandler(op, () => Effect.succeed('ok')));
|
|
37
|
+
expect(Operation.isOperationWithHandler(op)).toBe(true);
|
|
38
|
+
});
|
|
39
|
+
});
|
package/src/Operation.ts
CHANGED
|
@@ -9,10 +9,11 @@ import * as Effect from 'effect/Effect';
|
|
|
9
9
|
import * as Layer from 'effect/Layer';
|
|
10
10
|
import * as Option from 'effect/Option';
|
|
11
11
|
import * as Pipeable from 'effect/Pipeable';
|
|
12
|
+
import * as Schema from 'effect/Schema';
|
|
12
13
|
import * as Schema$ from 'effect/Schema';
|
|
13
14
|
import type * as Types from 'effect/Types';
|
|
14
15
|
|
|
15
|
-
import {
|
|
16
|
+
import { Annotation, DXN, JsonSchema, type Key, Migration, Obj, Ref, Type } from '@dxos/echo';
|
|
16
17
|
import type { URI } from '@dxos/keys';
|
|
17
18
|
|
|
18
19
|
import type { NoHandlerError } from './errors';
|
|
@@ -299,46 +300,48 @@ export type InvokeRemote = <I, O, E>(
|
|
|
299
300
|
* The registry `key` and `version` live in the object meta — access via
|
|
300
301
|
* `Obj.getMeta(record).key` and `Obj.getMeta(record).version`.
|
|
301
302
|
*/
|
|
302
|
-
|
|
303
|
-
|
|
303
|
+
// TODO(dmaretskyi): Keep typename as 'org.dxos.type.function' (not 'operation') to maintain
|
|
304
|
+
// backward compatibility with existing data and avoid requiring data migration.
|
|
305
|
+
export class PersistentOperation extends Type.makeObject<PersistentOperation>(
|
|
306
|
+
DXN.make('org.dxos.type.function', '0.2.0'),
|
|
307
|
+
)(
|
|
308
|
+
Schema$.Struct({
|
|
309
|
+
name: Schema$.NonEmptyString,
|
|
304
310
|
|
|
305
|
-
|
|
311
|
+
description: Schema$.optional(Schema$.String),
|
|
306
312
|
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
313
|
+
/**
|
|
314
|
+
* ISO date string of the last deployment.
|
|
315
|
+
*/
|
|
316
|
+
updated: Schema$.optional(Schema$.String),
|
|
311
317
|
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
318
|
+
// Reference to a source script if it exists within ECHO.
|
|
319
|
+
// TODO(burdon): Don't ref ScriptType directly (core).
|
|
320
|
+
source: Schema$.optional(Ref.Ref(Obj.Unknown)),
|
|
315
321
|
|
|
316
|
-
|
|
317
|
-
|
|
322
|
+
inputSchema: Schema$.optional(JsonSchema.JsonSchema),
|
|
323
|
+
outputSchema: Schema$.optional(JsonSchema.JsonSchema),
|
|
318
324
|
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
325
|
+
/**
|
|
326
|
+
* List of required services.
|
|
327
|
+
* Match the Context.Tag keys of the FunctionServices variants.
|
|
328
|
+
*/
|
|
329
|
+
services: Schema$.optional(Schema$.Array(Schema$.String)),
|
|
324
330
|
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
331
|
+
// Local binding to a function name.
|
|
332
|
+
// TODO(dmaretskyi): Add this field to Operation.Definition.
|
|
333
|
+
binding: Schema$.optional(Schema$.String),
|
|
328
334
|
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
}).pipe(
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
Type.makeObject(DXN.make('org.dxos.type.function', '0.2.0')),
|
|
340
|
-
);
|
|
341
|
-
export type PersistentOperation = Type.InstanceType<typeof PersistentOperation>;
|
|
335
|
+
/**
|
|
336
|
+
* Phosphor icon identifier in `ph--<name>--<variant>` format (e.g. `ph--file-text--regular`).
|
|
337
|
+
*/
|
|
338
|
+
icon: Schema$.optional(Schema$.String),
|
|
339
|
+
}).pipe(
|
|
340
|
+
Annotation.LabelAnnotation.set(['name']),
|
|
341
|
+
Annotation.IconAnnotation.set({ icon: 'ph--function--regular', hue: 'blue' }),
|
|
342
|
+
Annotation.HiddenAnnotation.set(true),
|
|
343
|
+
),
|
|
344
|
+
) {}
|
|
342
345
|
|
|
343
346
|
const FUNCTION_META_KEY = 'org.dxos.service.function';
|
|
344
347
|
|
|
@@ -429,20 +432,46 @@ export const setFrom = (target: PersistentOperation, source: PersistentOperation
|
|
|
429
432
|
* Defined locally to avoid a core dependency on UI translation packages; structurally compatible with
|
|
430
433
|
* the app-level `Label` type so values flow into UI toasts unchanged.
|
|
431
434
|
*/
|
|
432
|
-
export
|
|
435
|
+
export const Label = Schema.Union(
|
|
436
|
+
Schema.String,
|
|
437
|
+
// `Schema.mutable` mirrors the app-level `Label` (whose tuple is mutable), so decoded values are
|
|
438
|
+
// assignable to UI toast `title`/`label` slots without a readonly-vs-mutable tuple mismatch.
|
|
439
|
+
Schema.mutable(
|
|
440
|
+
Schema.Tuple(
|
|
441
|
+
Schema.String,
|
|
442
|
+
Schema.mutable(
|
|
443
|
+
Schema.Struct({
|
|
444
|
+
ns: Schema.String,
|
|
445
|
+
count: Schema.optional(Schema.Number),
|
|
446
|
+
defaultValue: Schema.optional(Schema.String),
|
|
447
|
+
}),
|
|
448
|
+
),
|
|
449
|
+
),
|
|
450
|
+
),
|
|
451
|
+
);
|
|
452
|
+
export type Label = Schema.Schema.Type<typeof Label>;
|
|
433
453
|
|
|
434
454
|
/**
|
|
435
455
|
* Per-phase user notification messages for an invocation.
|
|
436
456
|
* A phase is notified to the user iff its message is provided; messages are translatable {@link Label}s.
|
|
437
457
|
*/
|
|
438
|
-
export
|
|
458
|
+
export const NotifyOptions = Schema.Struct({
|
|
439
459
|
/** Shown when the invocation starts. */
|
|
440
|
-
start
|
|
460
|
+
start: Schema.optional(Label),
|
|
441
461
|
/** Shown when the invocation succeeds. */
|
|
442
|
-
success
|
|
462
|
+
success: Schema.optional(Label),
|
|
443
463
|
/** Shown when the invocation fails. */
|
|
444
|
-
error
|
|
445
|
-
}
|
|
464
|
+
error: Schema.optional(Label),
|
|
465
|
+
});
|
|
466
|
+
export type NotifyOptions = Schema.Schema.Type<typeof NotifyOptions>;
|
|
467
|
+
|
|
468
|
+
/**
|
|
469
|
+
* Annotation that configures the process to notify the user at the given invocation phases.
|
|
470
|
+
*/
|
|
471
|
+
export const NotifyOptionsAnnotation = Annotation.make({
|
|
472
|
+
id: 'org.dxos.operation.notify-options',
|
|
473
|
+
schema: NotifyOptions,
|
|
474
|
+
});
|
|
446
475
|
|
|
447
476
|
/**
|
|
448
477
|
* Options for operation invocation.
|
|
@@ -460,7 +489,7 @@ export interface InvokeOptions {
|
|
|
460
489
|
* URI of the conversation feed (queue) — today always an EID, but typed as
|
|
461
490
|
* `URI.URI` to accommodate future entity-kind extensions. Narrow with `EID.parse`
|
|
462
491
|
* at the point of use.
|
|
463
|
-
* Passed to the process environment so nested operations can resolve
|
|
492
|
+
* Passed to the process environment so nested operations can resolve HarnessService and related services.
|
|
464
493
|
*/
|
|
465
494
|
conversation?: URI.URI;
|
|
466
495
|
/**
|
|
@@ -487,6 +516,50 @@ export const isIdempotent = (op: Definition.Any): boolean =>
|
|
|
487
516
|
? Option.getOrElse(Annotation.getDictionary(op.meta.annotations, IdempotentAnnotation), () => false)
|
|
488
517
|
: false;
|
|
489
518
|
|
|
519
|
+
/**
|
|
520
|
+
* Attaches an annotation to an operation definition, returning a new definition.
|
|
521
|
+
* Combinators never mutate their input — operation definitions are module-level singletons
|
|
522
|
+
* shared across handler sets, skills, and the registry, so a fresh value keeps the
|
|
523
|
+
* annotated definition distinct from any other reference to the original.
|
|
524
|
+
*
|
|
525
|
+
* Type-preserving: an annotation does not change the operation's input/output/service types, so the
|
|
526
|
+
* returned definition keeps `Def` (preserving `withHandler` inference and downstream usage).
|
|
527
|
+
*/
|
|
528
|
+
export const annotate =
|
|
529
|
+
<T>(annotation: Annotation.Annotation<T>, value: T) =>
|
|
530
|
+
<Def extends Definition.Any>(op: Def): Def => {
|
|
531
|
+
const annotations = { ...(op.meta.annotations ?? {}) };
|
|
532
|
+
Annotation.setDictionary(annotations, annotation, value);
|
|
533
|
+
// The spread reconstructs the same shape with only `meta.annotations` changed; the checker can't
|
|
534
|
+
// track the branded variance symbol through the untyped dictionary mutation, so reassert `Def`.
|
|
535
|
+
return { ...op, meta: { ...op.meta, annotations } } as Def;
|
|
536
|
+
};
|
|
537
|
+
|
|
538
|
+
/**
|
|
539
|
+
* Marks an operation as visible on user-facing operation surfaces (trigger/automation pickers,
|
|
540
|
+
* manual invocation). Absent ⇒ internal: invoked programmatically by plugins and hidden from pickers.
|
|
541
|
+
*
|
|
542
|
+
* Polarity is inverted from the schema-level `HiddenAnnotation` (default visible): operations are
|
|
543
|
+
* hidden by default, since most are internal plugin machinery and only a minority are user-facing.
|
|
544
|
+
*/
|
|
545
|
+
export const VisibleAnnotation = Annotation.make({
|
|
546
|
+
id: 'org.dxos.operation.visible',
|
|
547
|
+
schema: Schema$.Boolean,
|
|
548
|
+
});
|
|
549
|
+
|
|
550
|
+
/**
|
|
551
|
+
* Pipeable combinator that marks an operation visible. Apply at the definition site:
|
|
552
|
+
* `Operation.make({ ... }).pipe(Operation.visible)`.
|
|
553
|
+
*/
|
|
554
|
+
export const visible = annotate(VisibleAnnotation, true);
|
|
555
|
+
|
|
556
|
+
/**
|
|
557
|
+
* Returns true when an operation is annotated as visible on user-facing surfaces (trigger/automation
|
|
558
|
+
* pickers, manual invocation). Reads from the persisted operation — the form every consumer holds.
|
|
559
|
+
*/
|
|
560
|
+
export const isVisible = (op: PersistentOperation): boolean =>
|
|
561
|
+
Option.getOrElse(Annotation.get(op, VisibleAnnotation), () => false);
|
|
562
|
+
|
|
490
563
|
/**
|
|
491
564
|
* Operation service interface - provides unified access to operation invocation and scheduling.
|
|
492
565
|
* This service is automatically provided to operation handlers.
|
|
@@ -605,19 +678,22 @@ export const withInvocationOptions = (options: InvokeOptions): Layer.Layer<Servi
|
|
|
605
678
|
* Persistent operation schema v0.1.0 — `key` and `version` are stored as data properties.
|
|
606
679
|
* @deprecated Use {@link PersistentOperation} (v0.2.0) instead; the `key` and `version` now live in the object meta.
|
|
607
680
|
*/
|
|
608
|
-
export
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
681
|
+
export class PersistentOperation_v0_1_0 extends Type.makeObject<PersistentOperation_v0_1_0>(
|
|
682
|
+
DXN.make('org.dxos.type.function', '0.1.0'),
|
|
683
|
+
)(
|
|
684
|
+
Schema$.Struct({
|
|
685
|
+
key: Schema$.optional(Schema$.String),
|
|
686
|
+
name: Schema$.NonEmptyString,
|
|
687
|
+
version: Schema$.String,
|
|
688
|
+
description: Schema$.optional(Schema$.String),
|
|
689
|
+
updated: Schema$.optional(Schema$.String),
|
|
690
|
+
source: Schema$.optional(Ref.Ref(Obj.Unknown)),
|
|
691
|
+
inputSchema: Schema$.optional(JsonSchema.JsonSchema),
|
|
692
|
+
outputSchema: Schema$.optional(JsonSchema.JsonSchema),
|
|
693
|
+
services: Schema$.optional(Schema$.Array(Schema$.String)),
|
|
694
|
+
binding: Schema$.optional(Schema$.String),
|
|
695
|
+
}),
|
|
696
|
+
) {}
|
|
621
697
|
|
|
622
698
|
/**
|
|
623
699
|
* Migration from {@link PersistentOperation_v0_1_0} (v0.1.0) to {@link PersistentOperation} (v0.2.0).
|