@fungi.computer/trellis 0.0.0-stage → 0.0.1
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/LICENSE +21 -0
- package/README.md +125 -2
- package/backend/catalog.ts +58 -0
- package/backend/gills.ts +56 -0
- package/backend/index.ts +40 -0
- package/backend/indexes.ts +419 -0
- package/backend/library-methods.ts +287 -0
- package/backend/library.ts +594 -0
- package/backend/methods.ts +221 -0
- package/backend/publication-job.ts +625 -0
- package/backend/push.ts +287 -0
- package/backend/schedule-methods.ts +120 -0
- package/backend/share.ts +221 -0
- package/backend/tool-family.ts +124 -0
- package/backend/tsconfig.build.json +11 -0
- package/backend/tsconfig.json +15 -0
- package/dist/backend/catalog.js +42 -0
- package/dist/backend/gills.js +49 -0
- package/dist/backend/indexes.js +294 -0
- package/dist/backend/library-methods.js +219 -0
- package/dist/backend/library.js +454 -0
- package/dist/backend/methods.js +141 -0
- package/dist/backend/publication-job.js +451 -0
- package/dist/backend/schedule-methods.js +90 -0
- package/dist/backend/share.js +140 -0
- package/dist/backend/tool-family.js +98 -0
- package/dist/shared/tool-contracts.js +32 -0
- package/package.json +166 -3
- package/shared/tool-contracts.ts +35 -0
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
import { workflowLibraryGill } from "./gills.js";
|
|
2
|
+
import * as z from "zod";
|
|
3
|
+
import type { GraphStartRequest } from "@fungi.computer/braid/runtime";
|
|
4
|
+
import { memberInboxItemSchema } from "@fungi.computer/agar/inbox";
|
|
5
|
+
import { catalogReplySchema as catalogReply } from "./catalog.js";
|
|
6
|
+
import type { BackgroundBinding } from "@fungi.computer/puffball/background-replay";
|
|
7
|
+
import type { GitBinding } from "@fungi.computer/agar/git";
|
|
8
|
+
import type { WorkflowIndexes } from "./indexes.js";
|
|
9
|
+
import { scheduleMethods } from "./schedule-methods.js";
|
|
10
|
+
import { toolFamilyMethods } from "./tool-family.js";
|
|
11
|
+
import { libraryMethods } from "./library-methods.js";
|
|
12
|
+
import * as Schema from "effect/Schema";
|
|
13
|
+
import { reviewAnswerSchema } from "@fungi.computer/braid";
|
|
14
|
+
import {
|
|
15
|
+
defineAppBackend,
|
|
16
|
+
defineAppMethod,
|
|
17
|
+
} from "@fungi.computer/agar/backend-definition";
|
|
18
|
+
import {
|
|
19
|
+
chatsReplySchema,
|
|
20
|
+
type WorkflowTriggerArmTarget,
|
|
21
|
+
answerReviewReply,
|
|
22
|
+
cancelReplySchema,
|
|
23
|
+
catalogInputSchema,
|
|
24
|
+
runListItemSchema,
|
|
25
|
+
runsReplySchema,
|
|
26
|
+
statusReply,
|
|
27
|
+
viewerReplySchema,
|
|
28
|
+
} from "@fungi.computer/workflows-wire";
|
|
29
|
+
import { workflowIdSchema } from "@fungi.computer/braid";
|
|
30
|
+
|
|
31
|
+
const identity = z.string().min(1).max(256);
|
|
32
|
+
const inboxPage = z.object({ items: z.array(z.json()).max(200) });
|
|
33
|
+
export type WorkflowMethodContext = Readonly<{
|
|
34
|
+
indexes?: WorkflowIndexes;
|
|
35
|
+
env: Readonly<{
|
|
36
|
+
GIT?: GitBinding;
|
|
37
|
+
/** The member's Inbox, read only to offer chats for run reports. */
|
|
38
|
+
INBOX?: Readonly<{
|
|
39
|
+
page(input: { after: string | null }): Promise<typeof Schema.Json.Type>;
|
|
40
|
+
}>;
|
|
41
|
+
BACKGROUND?: BackgroundBinding;
|
|
42
|
+
WORKFLOWS?: Readonly<{
|
|
43
|
+
armEventTrigger(
|
|
44
|
+
input: WorkflowTriggerArmTarget,
|
|
45
|
+
): Promise<typeof Schema.Json.Type>;
|
|
46
|
+
disarmEventTrigger(input: {
|
|
47
|
+
eventTriggerId: string;
|
|
48
|
+
}): Promise<typeof Schema.Json.Type>;
|
|
49
|
+
eventTriggers(
|
|
50
|
+
input: Record<string, never>,
|
|
51
|
+
): Promise<typeof Schema.Json.Type>;
|
|
52
|
+
armSchedule(
|
|
53
|
+
input: WorkflowTriggerArmTarget,
|
|
54
|
+
): Promise<typeof Schema.Json.Type>;
|
|
55
|
+
disarmSchedule(input: {
|
|
56
|
+
scheduleId: string;
|
|
57
|
+
}): Promise<typeof Schema.Json.Type>;
|
|
58
|
+
schedules(input: Record<string, never>): Promise<typeof Schema.Json.Type>;
|
|
59
|
+
catalog(input: {
|
|
60
|
+
installationId?: string | undefined;
|
|
61
|
+
}): Promise<typeof Schema.Json.Type>;
|
|
62
|
+
runGraph(input: GraphStartRequest): Promise<typeof Schema.Json.Type>;
|
|
63
|
+
cancel(input: { runId: string }): Promise<typeof Schema.Json.Type>;
|
|
64
|
+
graphStatus(input: { runId: string }): Promise<typeof Schema.Json.Type>;
|
|
65
|
+
answerReview(input: {
|
|
66
|
+
runId: string;
|
|
67
|
+
nodeId: string;
|
|
68
|
+
iteration: string;
|
|
69
|
+
answer: typeof reviewAnswerSchema.Type;
|
|
70
|
+
}): Promise<typeof Schema.Json.Type>;
|
|
71
|
+
runs(input: { workflowId?: string }): Promise<typeof Schema.Json.Type>;
|
|
72
|
+
}>;
|
|
73
|
+
}>;
|
|
74
|
+
}>;
|
|
75
|
+
|
|
76
|
+
const granted = (context: WorkflowMethodContext) => {
|
|
77
|
+
if (!context.env.WORKFLOWS) throw new Error("Workflow access is not granted");
|
|
78
|
+
return context.env.WORKFLOWS;
|
|
79
|
+
};
|
|
80
|
+
export const appBackend = defineAppBackend<WorkflowMethodContext>({
|
|
81
|
+
sync: { method: "continuePublication" },
|
|
82
|
+
gills: [workflowLibraryGill],
|
|
83
|
+
toolFamily: { name: "flows", list: "listWorkflowTools", call: "runWorkflow" },
|
|
84
|
+
methods: {
|
|
85
|
+
...libraryMethods,
|
|
86
|
+
...toolFamilyMethods,
|
|
87
|
+
listRuns: defineAppMethod({
|
|
88
|
+
description:
|
|
89
|
+
"List up to fifty runs from this installation, newest first.",
|
|
90
|
+
effect: "read",
|
|
91
|
+
requires: ["workflow.run"],
|
|
92
|
+
input: z.strictObject({ workflowId: workflowIdSchema.optional() }),
|
|
93
|
+
output: z.array(runListItemSchema).max(50),
|
|
94
|
+
handler: async (input, context) => {
|
|
95
|
+
const indexes = context.indexes;
|
|
96
|
+
if (!indexes) throw new Error("Workflow indexes unavailable");
|
|
97
|
+
const reply = runsReplySchema.parse(
|
|
98
|
+
await granted(context).runs(
|
|
99
|
+
input.workflowId === undefined
|
|
100
|
+
? {}
|
|
101
|
+
: { workflowId: input.workflowId },
|
|
102
|
+
),
|
|
103
|
+
);
|
|
104
|
+
if ("error" in reply) throw new Error("Workflow run list unavailable");
|
|
105
|
+
return reply.runs.map((row) => {
|
|
106
|
+
const copied = indexes.publications.read(
|
|
107
|
+
`${row.workflowId}:${row.commit}`,
|
|
108
|
+
);
|
|
109
|
+
const published =
|
|
110
|
+
copied.kind === "ready" &&
|
|
111
|
+
copied.head === row.commit &&
|
|
112
|
+
copied.value.commit === row.commit
|
|
113
|
+
? copied.value
|
|
114
|
+
: null;
|
|
115
|
+
return {
|
|
116
|
+
...row,
|
|
117
|
+
title: published?.definition.title ?? null,
|
|
118
|
+
version: published?.version ?? null,
|
|
119
|
+
};
|
|
120
|
+
});
|
|
121
|
+
},
|
|
122
|
+
}),
|
|
123
|
+
viewerId: defineAppMethod({
|
|
124
|
+
description:
|
|
125
|
+
"The calling member's own id, so the Runs UI can tell its own runs from a teammate's.",
|
|
126
|
+
effect: "read",
|
|
127
|
+
requires: [],
|
|
128
|
+
input: z.strictObject({}),
|
|
129
|
+
output: viewerReplySchema,
|
|
130
|
+
handler: (_input, _context, caller) =>
|
|
131
|
+
caller.actor.kind === "member"
|
|
132
|
+
? { memberId: caller.actor.memberId }
|
|
133
|
+
: { error: "not_granted" },
|
|
134
|
+
}),
|
|
135
|
+
...scheduleMethods,
|
|
136
|
+
listChats: defineAppMethod({
|
|
137
|
+
description:
|
|
138
|
+
"List your existing chats (Agent Sessions) that a run or trigger may report its result to.",
|
|
139
|
+
effect: "read",
|
|
140
|
+
requires: ["agent.read"],
|
|
141
|
+
input: z.strictObject({}),
|
|
142
|
+
output: chatsReplySchema,
|
|
143
|
+
handler: async (_input, context) => {
|
|
144
|
+
if (!context.env.INBOX) return { error: "not_granted" as const };
|
|
145
|
+
const page = inboxPage.parse(
|
|
146
|
+
await context.env.INBOX.page({ after: null }),
|
|
147
|
+
);
|
|
148
|
+
return {
|
|
149
|
+
chats: page.items.flatMap((raw) => {
|
|
150
|
+
const item = Schema.decodeUnknownSync(memberInboxItemSchema)(raw);
|
|
151
|
+
return "kind" in item || !("title" in item)
|
|
152
|
+
? []
|
|
153
|
+
: [
|
|
154
|
+
{
|
|
155
|
+
agentId: item.agentId,
|
|
156
|
+
sessionId: item.sessionId,
|
|
157
|
+
title: item.title,
|
|
158
|
+
},
|
|
159
|
+
];
|
|
160
|
+
}),
|
|
161
|
+
};
|
|
162
|
+
},
|
|
163
|
+
}),
|
|
164
|
+
catalog: defineAppMethod({
|
|
165
|
+
description:
|
|
166
|
+
"List your installed Apps' methods: a palette index with no port schemas, or one installation's full ports when `installationId` is given.",
|
|
167
|
+
effect: "read",
|
|
168
|
+
requires: ["workflow.run"],
|
|
169
|
+
input: catalogInputSchema,
|
|
170
|
+
output: catalogReply,
|
|
171
|
+
handler: async (input, context) =>
|
|
172
|
+
catalogReply.parse(await granted(context).catalog(input)),
|
|
173
|
+
}),
|
|
174
|
+
runStatus: defineAppMethod({
|
|
175
|
+
description:
|
|
176
|
+
"Read one of your Workflow runs: per-node events, open reviews and the engine's status.",
|
|
177
|
+
effect: "read",
|
|
178
|
+
requires: ["workflow.run"],
|
|
179
|
+
input: z.strictObject({ runId: identity }),
|
|
180
|
+
output: statusReply,
|
|
181
|
+
handler: async (input, context) =>
|
|
182
|
+
statusReply.parse(await granted(context).graphStatus(input)),
|
|
183
|
+
}),
|
|
184
|
+
cancel: defineAppMethod({
|
|
185
|
+
description:
|
|
186
|
+
"Cancel a run you started or administer as the current Team owner. Completed runs remain terminal.",
|
|
187
|
+
effect: "write",
|
|
188
|
+
requires: ["workflow.run"],
|
|
189
|
+
input: z.strictObject({ runId: identity }),
|
|
190
|
+
output: cancelReplySchema,
|
|
191
|
+
handler: async (input, context) =>
|
|
192
|
+
cancelReplySchema.parse(await granted(context).cancel(input)),
|
|
193
|
+
}),
|
|
194
|
+
answerReview: defineAppMethod({
|
|
195
|
+
description:
|
|
196
|
+
"Answer one of your Workflow runs' reviews: approve or reject, or pick one of the review's named choices. Only a person can answer; Agents cannot.",
|
|
197
|
+
effect: "write",
|
|
198
|
+
requires: ["workflow.run"],
|
|
199
|
+
input: z.strictObject({
|
|
200
|
+
runId: identity,
|
|
201
|
+
nodeId: identity,
|
|
202
|
+
iteration: identity,
|
|
203
|
+
answer: z.fromJSONSchema(
|
|
204
|
+
Schema.toJsonSchemaDocument(reviewAnswerSchema).schema,
|
|
205
|
+
),
|
|
206
|
+
}),
|
|
207
|
+
output: answerReviewReply,
|
|
208
|
+
handler: async (input, context, caller) => {
|
|
209
|
+
if (caller.actor.kind !== "member") return { error: "not_granted" };
|
|
210
|
+
return answerReviewReply.parse(
|
|
211
|
+
await granted(context).answerReview({
|
|
212
|
+
...input,
|
|
213
|
+
answer: Schema.decodeUnknownSync(reviewAnswerSchema)(input.answer, {
|
|
214
|
+
onExcessProperty: "error",
|
|
215
|
+
}),
|
|
216
|
+
}),
|
|
217
|
+
);
|
|
218
|
+
},
|
|
219
|
+
}),
|
|
220
|
+
},
|
|
221
|
+
});
|