@fungi.computer/agar 0.1.0 → 0.3.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/README.md +34 -18
- package/dist/agent-message-meta.d.ts +21 -16
- package/dist/agent-message-meta.js +17 -6
- package/dist/agents.d.ts +86 -13
- package/dist/agents.js +48 -25
- package/dist/approvals.d.ts +5 -0
- package/dist/approvals.js +36 -0
- package/dist/apps.js +4 -4
- package/dist/backend-definition.d.ts +41 -4
- package/dist/backend-definition.js +70 -10
- package/dist/backend-refusal.d.ts +1 -0
- package/dist/backend-refusal.js +1 -0
- package/dist/backend.js +4 -4
- package/dist/channels.js +4 -4
- package/dist/computer-contracts.d.ts +11 -28
- package/dist/computer-contracts.js +10 -29
- package/dist/computer.js +16 -16
- package/dist/connect.d.ts +3 -3
- package/dist/connect.js +7 -17
- package/dist/errors.d.ts +39 -1
- package/dist/errors.js +62 -5
- package/dist/game-servers.js +2 -2
- package/dist/git-rpc.d.ts +23 -23
- package/dist/git-rpc.js +14 -16
- package/dist/git.d.ts +9 -9
- package/dist/git.js +8 -8
- package/dist/host.d.ts +3 -1
- package/dist/host.js +5 -1
- package/dist/index.d.ts +8 -4
- package/dist/index.js +5 -2
- package/dist/inference.js +2 -1
- package/dist/internal/app-session.js +37 -1
- package/dist/internal/media-diagnostic.d.ts +11 -0
- package/dist/internal/media-diagnostic.js +21 -0
- package/dist/internal/protocol.d.ts +4 -4
- package/dist/internal/schemas.d.ts +40 -7
- package/dist/internal/schemas.js +122 -35
- package/dist/marketplace.js +7 -5
- package/dist/media-json.d.ts +14 -0
- package/dist/media-json.js +1 -0
- package/dist/media-request-id.d.ts +1 -1
- package/dist/media-request-id.js +2 -2
- package/dist/media.d.ts +11 -0
- package/dist/media.js +8 -2
- package/dist/method-presentation.d.ts +7 -0
- package/dist/method-presentation.js +14 -0
- package/dist/method-refusal.d.ts +5 -5
- package/dist/method-refusal.js +4 -4
- package/dist/query.d.ts +2 -2
- package/dist/react-mount.d.ts +7 -1
- package/dist/react-mount.js +28 -8
- package/dist/react.d.ts +14 -2
- package/dist/react.js +40 -4
- package/dist/read-copy.d.ts +1 -1
- package/dist/read-copy.js +3 -6
- package/dist/storage.js +1 -1
- package/dist/test-kit/git.js +19 -2
- package/dist/window.d.ts +68 -0
- package/dist/window.js +31 -0
- package/docs/api/README.md +15 -15
- package/docs/api/backend-definition.md +83 -9
- package/docs/api/backend.md +45 -38
- package/docs/api/errors.md +104 -0
- package/docs/api/git-rpc.md +35 -35
- package/docs/api/git.md +66 -80
- package/docs/api/index.md +851 -143
- package/docs/api/media-json.md +32 -59
- package/docs/api/media-request-id.md +1 -1
- package/docs/api/method-presentation.md +21 -0
- package/docs/api/modules.md +1 -0
- package/docs/api/query.md +1 -1
- package/docs/api/react.md +23 -10
- package/package.json +16 -6
package/README.md
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
# Agar (`@fungi.computer/agar`)
|
|
2
2
|
|
|
3
3
|
Agar defines typed App backends and host capabilities. Most people want
|
|
4
|
-
[Oyster](https://docs.fungi.computer/
|
|
5
|
-
[Shiitake](https://docs.fungi.computer/
|
|
6
|
-
Agents.
|
|
4
|
+
[Oyster](https://docs.fungi.computer/oyster/) to run Apps or
|
|
5
|
+
[Shiitake](https://docs.fungi.computer/shiitake/) to run Agents.
|
|
7
6
|
|
|
8
7
|
Agar is the App contract for fungi.computer. It defines an App's typed backend
|
|
9
8
|
methods, connects its frontend to a host through typed capabilities, and gives
|
|
@@ -336,10 +335,15 @@ the declared methods separately.
|
|
|
336
335
|
|
|
337
336
|
## Connect and release
|
|
338
337
|
|
|
339
|
-
connectApp
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
338
|
+
`connectApp({ host: "parent", signal })` discovers the host through the existing
|
|
339
|
+
parent handshake, without reading a referrer or accepting an origin parameter.
|
|
340
|
+
Serve the App document with CSP `frame-ancestors` pinned to its allowed host.
|
|
341
|
+
The browser checks the entire ancestor chain; without that policy an unrelated
|
|
342
|
+
site embedding the App could become its host. Hub and Oyster supply this policy
|
|
343
|
+
on their App document routes. Only the public, secret-free ready announcement
|
|
344
|
+
uses `"*"`; connection acceptance checks the actual parent Window, its
|
|
345
|
+
non-opaque origin, protocol and single transferred port before returning an
|
|
346
|
+
AppRoot. It permits one live connection per frontend page.
|
|
343
347
|
|
|
344
348
|
The root supplies:
|
|
345
349
|
|
|
@@ -557,14 +561,18 @@ const dispose = mountApp(root, { name: "Bazaar" }, ({ app }) => (
|
|
|
557
561
|
import.meta.hot?.dispose(dispose);
|
|
558
562
|
```
|
|
559
563
|
|
|
560
|
-
`mountApp`
|
|
561
|
-
|
|
564
|
+
`mountApp` discovers its actual parent through Agar's existing handshake,
|
|
565
|
+
independently of referrer policy. The parent must have a non-opaque origin and
|
|
566
|
+
transfer exactly one port for the validated epoch. Top-level launches remain
|
|
567
|
+
standalone; embedded pages without a valid handshake report `not-hosted` with an
|
|
568
|
+
`AppError` and a visible alert rather than silently becoming standalone. It
|
|
569
|
+
applies and subscribes to the host's theme, and restores the original theme on
|
|
562
570
|
disconnect or unmount. Its render callback receives `connecting`, `live`,
|
|
563
|
-
`standalone` (
|
|
564
|
-
connection). Only `live` carries an AppRoot. The
|
|
565
|
-
pending handshake, releases subscriptions, disposes
|
|
566
|
-
React. A late connection is disposed too. Existing
|
|
567
|
-
marks are emitted at root render and commits.
|
|
571
|
+
`standalone` (a top-level launch), `not-hosted` (an initial connection failure),
|
|
572
|
+
or `ended` (a closed live connection). Only `live` carries an AppRoot. The
|
|
573
|
+
returned disposer aborts a pending handshake, releases subscriptions, disposes
|
|
574
|
+
the connection and unmounts React. A late connection is disposed too. Existing
|
|
575
|
+
App-open React performance marks are emitted at root render and commits.
|
|
568
576
|
|
|
569
577
|
Supply `queryClient` to wrap the App in `QueryClientProvider`. The caller owns
|
|
570
578
|
that client, its cache policy and grant invalidation; mounting does not clear
|
|
@@ -751,6 +759,13 @@ The exported `mediaGenerationDescriptionSchema`,
|
|
|
751
759
|
`mediaGenerationJsonReplySchema` and `mediaGenerationReferenceSchema` decode
|
|
752
760
|
these boundaries with the existing Agar Media grammar.
|
|
753
761
|
|
|
762
|
+
Failures may include safe `provider` facts: an allowlisted category and bounded
|
|
763
|
+
code, or `result_download` and an HTTP status. JSON, RPC and
|
|
764
|
+
`MediaGenerationError.provider` preserve the same facts and retry truth.
|
|
765
|
+
`./errors` exposes declaration-safe diagnostic types and decoder helpers; one
|
|
766
|
+
internal Effect schema owns validation. Private provider messages, bodies, URLs
|
|
767
|
+
and causes are not diagnostic fields and are rejected at this boundary.
|
|
768
|
+
|
|
754
769
|
Attempts retain their canonical request ID when restored or when polling
|
|
755
770
|
Pending. The shared Agar Pending validator requires an integer `retryAfterMs`
|
|
756
771
|
from 1000 to 60000. Cancellation aborts the attempt's active local requests;
|
|
@@ -761,7 +776,8 @@ the platform DOM types and `ESNext.Disposable`.
|
|
|
761
776
|
See the [generated API](docs/api/README.md) for signatures and host ports.
|
|
762
777
|
|
|
763
778
|
`@fungi.computer/agar/computer-contracts` is the runtime-neutral public home for
|
|
764
|
-
|
|
765
|
-
definitions can validate
|
|
766
|
-
|
|
767
|
-
|
|
779
|
+
Computer admission, input, dispatch, timeout and attachment-budget outcomes. App
|
|
780
|
+
backend definitions can validate these outcomes without importing the Computer
|
|
781
|
+
RPC client. Apps request ordinary Computer execution; Workflow Git credential
|
|
782
|
+
issuance, carriage, renewal and revocation stay inside the trusted host and
|
|
783
|
+
native execution boundary, not the App contract.
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import * as z from "zod";
|
|
2
2
|
/** Who a Session line came from, as the admitting host authenticated them. */
|
|
3
|
-
export declare const FungiAuthorSchema: z.ZodObject<{
|
|
3
|
+
export declare const FungiAuthorSchema: z.ZodLazy<z.ZodObject<{
|
|
4
4
|
id: z.ZodString;
|
|
5
5
|
name: z.ZodString;
|
|
6
|
-
|
|
6
|
+
kind: z.ZodOptional<z.ZodLiteral<"agent">>;
|
|
7
|
+
}, z.core.$strict>>;
|
|
7
8
|
/** Who a Session line came from, as the admitting host authenticated them. */
|
|
8
9
|
export type FungiAuthor = z.infer<typeof FungiAuthorSchema>;
|
|
9
10
|
/**
|
|
@@ -11,10 +12,10 @@ export type FungiAuthor = z.infer<typeof FungiAuthorSchema>;
|
|
|
11
12
|
* mail it sent. `commandId` is the replying Session's accepted command, the
|
|
12
13
|
* same id as the sender's `agents.send` receipt.
|
|
13
14
|
*/
|
|
14
|
-
export declare const FungiDelegationReplySchema: z.ZodObject<{
|
|
15
|
-
agentId: z.ZodString
|
|
16
|
-
sessionId: z.ZodString
|
|
17
|
-
commandId: z.ZodString
|
|
15
|
+
export declare const FungiDelegationReplySchema: z.ZodLazy<z.ZodObject<{
|
|
16
|
+
agentId: z.ZodLazy<z.ZodString>;
|
|
17
|
+
sessionId: z.ZodLazy<z.ZodString>;
|
|
18
|
+
commandId: z.ZodLazy<z.ZodString>;
|
|
18
19
|
outcome: z.ZodEnum<{
|
|
19
20
|
completed: "completed";
|
|
20
21
|
failed: "failed";
|
|
@@ -23,7 +24,7 @@ export declare const FungiDelegationReplySchema: z.ZodObject<{
|
|
|
23
24
|
outcome_unknown: "outcome_unknown";
|
|
24
25
|
}>;
|
|
25
26
|
diagnostic: z.ZodOptional<z.ZodString>;
|
|
26
|
-
}, z.core.$strict
|
|
27
|
+
}, z.core.$strict>>;
|
|
27
28
|
/** A delegated Agent's reply as the admitting host authenticated it. */
|
|
28
29
|
export type FungiDelegationReply = z.infer<typeof FungiDelegationReplySchema>;
|
|
29
30
|
/**
|
|
@@ -31,17 +32,19 @@ export type FungiDelegationReply = z.infer<typeof FungiDelegationReplySchema>;
|
|
|
31
32
|
* Shiitake stores it opaquely; the host writes it and Apps read it.
|
|
32
33
|
*/
|
|
33
34
|
export declare const FungiMessageMetaSchema: z.ZodObject<{
|
|
34
|
-
author: z.ZodOptional<z.ZodObject<{
|
|
35
|
+
author: z.ZodOptional<z.ZodLazy<z.ZodObject<{
|
|
35
36
|
id: z.ZodString;
|
|
36
37
|
name: z.ZodString;
|
|
37
|
-
|
|
38
|
+
kind: z.ZodOptional<z.ZodLiteral<"agent">>;
|
|
39
|
+
}, z.core.$strict>>>;
|
|
40
|
+
sourceRequestId: z.ZodOptional<z.ZodLazy<z.ZodString>>;
|
|
38
41
|
delegation: z.ZodOptional<z.ZodObject<{
|
|
39
|
-
ancestors: z.ZodArray<z.ZodString
|
|
42
|
+
ancestors: z.ZodArray<z.ZodLazy<z.ZodString>>;
|
|
40
43
|
maxDepth: z.ZodNumber;
|
|
41
|
-
reply: z.ZodOptional<z.ZodObject<{
|
|
42
|
-
agentId: z.ZodString
|
|
43
|
-
sessionId: z.ZodString
|
|
44
|
-
commandId: z.ZodString
|
|
44
|
+
reply: z.ZodOptional<z.ZodLazy<z.ZodObject<{
|
|
45
|
+
agentId: z.ZodLazy<z.ZodString>;
|
|
46
|
+
sessionId: z.ZodLazy<z.ZodString>;
|
|
47
|
+
commandId: z.ZodLazy<z.ZodString>;
|
|
45
48
|
outcome: z.ZodEnum<{
|
|
46
49
|
completed: "completed";
|
|
47
50
|
failed: "failed";
|
|
@@ -50,7 +53,7 @@ export declare const FungiMessageMetaSchema: z.ZodObject<{
|
|
|
50
53
|
outcome_unknown: "outcome_unknown";
|
|
51
54
|
}>;
|
|
52
55
|
diagnostic: z.ZodOptional<z.ZodString>;
|
|
53
|
-
}, z.core.$strict
|
|
56
|
+
}, z.core.$strict>>>;
|
|
54
57
|
}, z.core.$strict>>;
|
|
55
58
|
}, z.core.$strict>;
|
|
56
59
|
/** The metadata the host attaches to every prompt and operator line it admits. */
|
|
@@ -68,7 +71,9 @@ export declare function messageAuthor(meta: MessageMetaValue | undefined): Fungi
|
|
|
68
71
|
export declare function messageDelegationReply(meta: MessageMetaValue | undefined): FungiDelegationReply | undefined;
|
|
69
72
|
/** The metadata the host attaches for one authenticated author, as JSON. */
|
|
70
73
|
export type AuthorMeta = Readonly<{
|
|
71
|
-
author: Readonly<
|
|
74
|
+
author: Readonly<{
|
|
75
|
+
[K in keyof FungiAuthor]: Exclude<FungiAuthor[K], undefined>;
|
|
76
|
+
}>;
|
|
72
77
|
}>;
|
|
73
78
|
/** The metadata the host attaches for one authenticated author. */
|
|
74
79
|
export declare function authorMeta(author: FungiAuthor): AuthorMeta;
|
|
@@ -1,16 +1,22 @@
|
|
|
1
1
|
import * as z from "zod";
|
|
2
2
|
/** Who a Session line came from, as the admitting host authenticated them. */
|
|
3
|
-
export const FungiAuthorSchema = z.strictObject({
|
|
3
|
+
export const FungiAuthorSchema = z.lazy(() => z.strictObject({
|
|
4
4
|
id: z.string().min(1).max(256),
|
|
5
5
|
name: z.string().min(1).max(128),
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
/**
|
|
7
|
+
* Present only when the author is another Agent the host admitted a
|
|
8
|
+
* delegated send or reply from; a line's text never sets it. Human
|
|
9
|
+
* authors carry no kind.
|
|
10
|
+
*/
|
|
11
|
+
kind: z.literal("agent").optional(),
|
|
12
|
+
}));
|
|
13
|
+
const identifier = z.lazy(() => z.string().min(1).max(256));
|
|
8
14
|
/**
|
|
9
15
|
* A delegated Agent's reply as the admitting host authenticated it against the
|
|
10
16
|
* mail it sent. `commandId` is the replying Session's accepted command, the
|
|
11
17
|
* same id as the sender's `agents.send` receipt.
|
|
12
18
|
*/
|
|
13
|
-
export const FungiDelegationReplySchema = z.strictObject({
|
|
19
|
+
export const FungiDelegationReplySchema = z.lazy(() => z.strictObject({
|
|
14
20
|
agentId: identifier,
|
|
15
21
|
sessionId: identifier,
|
|
16
22
|
commandId: identifier,
|
|
@@ -24,13 +30,15 @@ export const FungiDelegationReplySchema = z.strictObject({
|
|
|
24
30
|
]),
|
|
25
31
|
/** Bounded, single-line terminal diagnostic for work that did not complete. */
|
|
26
32
|
diagnostic: z.string().min(1).max(200).optional(),
|
|
27
|
-
});
|
|
33
|
+
}));
|
|
28
34
|
/**
|
|
29
35
|
* The metadata the host attaches to every prompt and operator line it admits.
|
|
30
36
|
* Shiitake stores it opaquely; the host writes it and Apps read it.
|
|
31
37
|
*/
|
|
32
38
|
export const FungiMessageMetaSchema = z.strictObject({
|
|
33
39
|
author: FungiAuthorSchema.optional(),
|
|
40
|
+
/** Original caller identity when the host translates its request into an owner key. */
|
|
41
|
+
sourceRequestId: identifier.optional(),
|
|
34
42
|
/** Host-admitted delegation path and its inherited abuse bound. */
|
|
35
43
|
delegation: z
|
|
36
44
|
.strictObject({
|
|
@@ -59,5 +67,8 @@ export function messageDelegationReply(meta) {
|
|
|
59
67
|
}
|
|
60
68
|
/** The metadata the host attaches for one authenticated author. */
|
|
61
69
|
export function authorMeta(author) {
|
|
62
|
-
|
|
70
|
+
const { id, name, kind } = author;
|
|
71
|
+
return kind === undefined
|
|
72
|
+
? { author: { id, name } }
|
|
73
|
+
: { author: { id, name, kind } };
|
|
63
74
|
}
|
package/dist/agents.d.ts
CHANGED
|
@@ -4,13 +4,44 @@ import * as z from "zod";
|
|
|
4
4
|
import * as Schema from "effect/Schema";
|
|
5
5
|
import type { CapabilityContract, CapabilityDirectory } from "./capabilities.js";
|
|
6
6
|
/**
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
|
|
7
|
+
* An Agent's avatar: Sprite's Avatar v1 envelope. Apps check its shape; the
|
|
8
|
+
* host owns the character-catalog refinement when it stores one.
|
|
9
|
+
*/
|
|
10
|
+
export declare const appAgentAvatarSchema: Schema.declare<{
|
|
11
|
+
v: 1;
|
|
12
|
+
character: "mushroom" | "cat" | "burger";
|
|
13
|
+
appearance: Record<string, string | number | boolean>;
|
|
14
|
+
expression: string;
|
|
15
|
+
renderStyle: "plain" | "pencil" | "manga" | "riso" | "halftone" | "blueprint" | "crt" | "watercolor";
|
|
16
|
+
}, {
|
|
17
|
+
v: 1;
|
|
18
|
+
character: "mushroom" | "cat" | "burger";
|
|
19
|
+
appearance: Record<string, string | number | boolean>;
|
|
20
|
+
expression: string;
|
|
21
|
+
renderStyle: "plain" | "pencil" | "manga" | "riso" | "halftone" | "blueprint" | "crt" | "watercolor";
|
|
22
|
+
}>;
|
|
23
|
+
/**
|
|
24
|
+
* Validates the wire shape of an Agent record: its id, display name, avatar,
|
|
25
|
+
* and which session operations (read, send, manage) this App may perform on
|
|
26
|
+
* it. Every Agent has an avatar: the one its owner chose, else Sprite's
|
|
27
|
+
* `seededAvatar(agentId)`. Conversations carry none of their own.
|
|
10
28
|
*/
|
|
11
29
|
export declare const appAgentSchema: Schema.Struct<{
|
|
12
30
|
readonly agentId: Schema.String;
|
|
13
31
|
readonly name: Schema.String;
|
|
32
|
+
readonly avatar: Schema.declare<{
|
|
33
|
+
v: 1;
|
|
34
|
+
character: "mushroom" | "cat" | "burger";
|
|
35
|
+
appearance: Record<string, string | number | boolean>;
|
|
36
|
+
expression: string;
|
|
37
|
+
renderStyle: "plain" | "pencil" | "manga" | "riso" | "halftone" | "blueprint" | "crt" | "watercolor";
|
|
38
|
+
}, {
|
|
39
|
+
v: 1;
|
|
40
|
+
character: "mushroom" | "cat" | "burger";
|
|
41
|
+
appearance: Record<string, string | number | boolean>;
|
|
42
|
+
expression: string;
|
|
43
|
+
renderStyle: "plain" | "pencil" | "manga" | "riso" | "halftone" | "blueprint" | "crt" | "watercolor";
|
|
44
|
+
}>;
|
|
14
45
|
readonly sessionOperations: Schema.$Array<Schema.Literals<readonly ["agent.read", "agent.send", "agent.manage"]>>;
|
|
15
46
|
}>;
|
|
16
47
|
/**
|
|
@@ -19,24 +50,38 @@ export declare const appAgentSchema: Schema.Struct<{
|
|
|
19
50
|
*/
|
|
20
51
|
export type AppAgent = Schema.Schema.Type<typeof appAgentSchema>;
|
|
21
52
|
/** The admitted AGENTS.list projection, containing only ids and display names. */
|
|
22
|
-
export declare const appAgentListResultSchema: z.ZodObject<{
|
|
53
|
+
export declare const appAgentListResultSchema: z.ZodLazy<z.ZodObject<{
|
|
23
54
|
agents: z.ZodArray<z.ZodObject<{
|
|
24
55
|
agentId: z.ZodString;
|
|
25
56
|
name: z.ZodString;
|
|
26
57
|
}, z.core.$strict>>;
|
|
27
|
-
}, z.core.$strict
|
|
58
|
+
}, z.core.$strict>>;
|
|
28
59
|
/** Computer provisioning is a Team creation choice, separate from Home policy. */
|
|
29
60
|
export declare const appAgentComputerSchema: Schema.Literals<readonly ["new", "none"]>;
|
|
30
|
-
/** Validates Agent creation input: a name, a caller-chosen request id
|
|
31
|
-
* optional Computer provisioning choice. */
|
|
61
|
+
/** Validates Agent creation input: a name, a caller-chosen request id, an
|
|
62
|
+
* optional Computer provisioning choice and an optional chosen avatar. */
|
|
32
63
|
export declare const appAgentCreateInputSchema: Schema.Struct<{
|
|
33
64
|
readonly name: Schema.String;
|
|
34
65
|
readonly requestId: Schema.String;
|
|
35
66
|
readonly computer: Schema.optionalKey<Schema.Literals<readonly ["new", "none"]>>;
|
|
67
|
+
readonly avatar: Schema.optionalKey<Schema.declare<{
|
|
68
|
+
v: 1;
|
|
69
|
+
character: "mushroom" | "cat" | "burger";
|
|
70
|
+
appearance: Record<string, string | number | boolean>;
|
|
71
|
+
expression: string;
|
|
72
|
+
renderStyle: "plain" | "pencil" | "manga" | "riso" | "halftone" | "blueprint" | "crt" | "watercolor";
|
|
73
|
+
}, {
|
|
74
|
+
v: 1;
|
|
75
|
+
character: "mushroom" | "cat" | "burger";
|
|
76
|
+
appearance: Record<string, string | number | boolean>;
|
|
77
|
+
expression: string;
|
|
78
|
+
renderStyle: "plain" | "pencil" | "manga" | "riso" | "halftone" | "blueprint" | "crt" | "watercolor";
|
|
79
|
+
}>>;
|
|
36
80
|
}>;
|
|
37
81
|
/**
|
|
38
82
|
* Input for creating a new Agent: its name, a caller-chosen request id
|
|
39
|
-
* for idempotency,
|
|
83
|
+
* for idempotency, whether to provision a new Computer for it, and the
|
|
84
|
+
* avatar it wears (omitted, it wears its seeded avatar).
|
|
40
85
|
*/
|
|
41
86
|
export type AppAgentCreateInput = Readonly<Schema.Schema.Type<typeof appAgentCreateInputSchema>>;
|
|
42
87
|
/** Live object-capability shape received from Cap'n Web. */
|
|
@@ -93,26 +138,54 @@ export type AppAgentRenameHandle = {
|
|
|
93
138
|
export declare const agentRename: CapabilityContract<AppAgentRenameHandle>;
|
|
94
139
|
/** Rename an Agent through the host-granted owner-only capability. */
|
|
95
140
|
export declare function renameAppAgent(capabilities: CapabilityDirectory, input: AppAgentRenameInput): Promise<AppAgent>;
|
|
141
|
+
/** Validates avatar input: the target Agent and the avatar it now wears. */
|
|
142
|
+
export declare const appAgentAvatarInputSchema: Schema.Struct<{
|
|
143
|
+
readonly agentId: Schema.String;
|
|
144
|
+
readonly avatar: Schema.declare<{
|
|
145
|
+
v: 1;
|
|
146
|
+
character: "mushroom" | "cat" | "burger";
|
|
147
|
+
appearance: Record<string, string | number | boolean>;
|
|
148
|
+
expression: string;
|
|
149
|
+
renderStyle: "plain" | "pencil" | "manga" | "riso" | "halftone" | "blueprint" | "crt" | "watercolor";
|
|
150
|
+
}, {
|
|
151
|
+
v: 1;
|
|
152
|
+
character: "mushroom" | "cat" | "burger";
|
|
153
|
+
appearance: Record<string, string | number | boolean>;
|
|
154
|
+
expression: string;
|
|
155
|
+
renderStyle: "plain" | "pencil" | "manga" | "riso" | "halftone" | "blueprint" | "crt" | "watercolor";
|
|
156
|
+
}>;
|
|
157
|
+
}>;
|
|
158
|
+
/** Input for changing an existing Agent's avatar. */
|
|
159
|
+
export type AppAgentAvatarInput = Readonly<Schema.Schema.Type<typeof appAgentAvatarInputSchema>>;
|
|
160
|
+
/** Capability handle for changing an Agent's avatar. */
|
|
161
|
+
export type AppAgentAvatarHandle = {
|
|
162
|
+
/** Set an existing Agent's avatar and return its updated record. */
|
|
163
|
+
setAvatar(input: AppAgentAvatarInput): Promise<AppAgent>;
|
|
164
|
+
};
|
|
165
|
+
/** Owner-only capability to change an existing Agent's avatar; not every host grants it. */
|
|
166
|
+
export declare const agentAvatar: CapabilityContract<AppAgentAvatarHandle>;
|
|
167
|
+
/** Change an Agent's avatar through the host-granted owner-only capability. */
|
|
168
|
+
export declare function setAppAgentAvatar(capabilities: CapabilityDirectory, input: AppAgentAvatarInput): Promise<AppAgent>;
|
|
96
169
|
/** One Agent's App-tool policy, as the owner-only policy capability reports it. */
|
|
97
|
-
export declare const appAgentToolPolicyStatusSchema: z.ZodUnion<readonly [z.ZodObject<{
|
|
170
|
+
export declare const appAgentToolPolicyStatusSchema: z.ZodLazy<z.ZodUnion<readonly [z.ZodObject<{
|
|
98
171
|
status: z.ZodLiteral<"pending">;
|
|
99
172
|
revision: z.ZodString;
|
|
100
173
|
}, z.core.$strip>, z.ZodObject<{
|
|
101
174
|
status: z.ZodLiteral<"approved">;
|
|
102
175
|
revision: z.ZodString;
|
|
103
|
-
}, z.core.$strip>]
|
|
176
|
+
}, z.core.$strip>]>>;
|
|
104
177
|
/** Whether an Agent's App tools are still pending the owner's approval. */
|
|
105
178
|
export type AppAgentToolPolicyStatus = z.infer<typeof appAgentToolPolicyStatusSchema>;
|
|
106
179
|
/** The outcome of an owner's direct App-tool approval. */
|
|
107
|
-
export declare const appAgentToolPolicyResultSchema: z.ZodUnion<readonly [z.ZodUnion<readonly [z.ZodObject<{
|
|
180
|
+
export declare const appAgentToolPolicyResultSchema: z.ZodLazy<z.ZodUnion<readonly [z.ZodLazy<z.ZodUnion<readonly [z.ZodObject<{
|
|
108
181
|
status: z.ZodLiteral<"pending">;
|
|
109
182
|
revision: z.ZodString;
|
|
110
183
|
}, z.core.$strip>, z.ZodObject<{
|
|
111
184
|
status: z.ZodLiteral<"approved">;
|
|
112
185
|
revision: z.ZodString;
|
|
113
|
-
}, z.core.$strip>]
|
|
186
|
+
}, z.core.$strip>]>>, z.ZodObject<{
|
|
114
187
|
error: z.ZodString;
|
|
115
|
-
}, z.core.$strip>]
|
|
188
|
+
}, z.core.$strip>]>>;
|
|
116
189
|
/** The outcome of an owner's direct App-tool approval. */
|
|
117
190
|
export type AppAgentToolPolicyResult = z.infer<typeof appAgentToolPolicyResultSchema>;
|
|
118
191
|
/** Capability handle for reading and approving an Agent's App-tool policy. */
|
package/dist/agents.js
CHANGED
|
@@ -3,31 +3,40 @@ import * as z from "zod";
|
|
|
3
3
|
import { defineCapability } from "./capabilities.js";
|
|
4
4
|
import { rpcDataSchema, rpcHandleSchema, rpcMethod, rpcFetchHandleSchema, } from "./internal/rpc-contract.js";
|
|
5
5
|
import * as Schema from "effect/Schema";
|
|
6
|
+
import { avatarEnvelopeSchema, } from "@fungi.computer/sprite/avatar";
|
|
6
7
|
import { AppError } from "./errors.js";
|
|
7
8
|
import { reportCatchFailure } from "./failure.js";
|
|
8
9
|
const boundedIdentity = Schema.String.pipe(Schema.check(Schema.isMinLength(1)), Schema.check(Schema.isMaxLength(256)));
|
|
9
10
|
/**
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
|
|
11
|
+
* An Agent's avatar: Sprite's Avatar v1 envelope. Apps check its shape; the
|
|
12
|
+
* host owns the character-catalog refinement when it stores one.
|
|
13
|
+
*/
|
|
14
|
+
export const appAgentAvatarSchema = Schema.declare((value) => avatarEnvelopeSchema.safeParse(value).success, { expected: "an Avatar v1 descriptor" });
|
|
15
|
+
/**
|
|
16
|
+
* Validates the wire shape of an Agent record: its id, display name, avatar,
|
|
17
|
+
* and which session operations (read, send, manage) this App may perform on
|
|
18
|
+
* it. Every Agent has an avatar: the one its owner chose, else Sprite's
|
|
19
|
+
* `seededAvatar(agentId)`. Conversations carry none of their own.
|
|
13
20
|
*/
|
|
14
21
|
export const appAgentSchema = Schema.Struct({
|
|
15
22
|
agentId: boundedIdentity,
|
|
16
23
|
name: boundedIdentity,
|
|
24
|
+
avatar: appAgentAvatarSchema,
|
|
17
25
|
sessionOperations: Schema.Array(Schema.Literals(["agent.read", "agent.send", "agent.manage"])),
|
|
18
26
|
});
|
|
19
27
|
/** The admitted AGENTS.list projection, containing only ids and display names. */
|
|
20
|
-
export const appAgentListResultSchema = z.strictObject({
|
|
28
|
+
export const appAgentListResultSchema = z.lazy(() => z.strictObject({
|
|
21
29
|
agents: z.array(z.strictObject({ agentId: z.string(), name: z.string() })),
|
|
22
|
-
});
|
|
30
|
+
}));
|
|
23
31
|
/** Computer provisioning is a Team creation choice, separate from Home policy. */
|
|
24
32
|
export const appAgentComputerSchema = Schema.Literals(["new", "none"]);
|
|
25
|
-
/** Validates Agent creation input: a name, a caller-chosen request id
|
|
26
|
-
* optional Computer provisioning choice. */
|
|
33
|
+
/** Validates Agent creation input: a name, a caller-chosen request id, an
|
|
34
|
+
* optional Computer provisioning choice and an optional chosen avatar. */
|
|
27
35
|
export const appAgentCreateInputSchema = Schema.Struct({
|
|
28
36
|
name: boundedIdentity,
|
|
29
37
|
requestId: boundedIdentity,
|
|
30
38
|
computer: Schema.optionalKey(appAgentComputerSchema),
|
|
39
|
+
avatar: Schema.optionalKey(appAgentAvatarSchema),
|
|
31
40
|
});
|
|
32
41
|
const appAgentDirectorySchema = Schema.Array(appAgentSchema);
|
|
33
42
|
const decodeAgents = Schema.decodeUnknownSync(appAgentDirectorySchema, {
|
|
@@ -36,64 +45,78 @@ const decodeAgents = Schema.decodeUnknownSync(appAgentDirectorySchema, {
|
|
|
36
45
|
const decodeAgentId = Schema.decodeUnknownSync(boundedIdentity);
|
|
37
46
|
const decodeResponse = Schema.decodeUnknownSync(Schema.instanceOf(Response));
|
|
38
47
|
/** Capability to list the Agents visible to this App in read-only form. */
|
|
39
|
-
export const agentList = defineCapability("agent.list", 1, rpcHandleSchema({
|
|
48
|
+
export const agentList = defineCapability("agent.list", 1, z.lazy(() => rpcHandleSchema({
|
|
40
49
|
list: rpcMethod(rpcDataSchema(z.unknown().transform((value) => decodeAgents(value)))),
|
|
41
|
-
}));
|
|
50
|
+
})));
|
|
42
51
|
/** Capability to create new Agents and open transports to them. */
|
|
43
|
-
export const agentManage = defineCapability("agent.manage", 1, rpcHandleSchema({
|
|
52
|
+
export const agentManage = defineCapability("agent.manage", 1, z.lazy(() => rpcHandleSchema({
|
|
44
53
|
open: rpcMethod(rpcFetchHandleSchema),
|
|
45
54
|
create: rpcMethod(rpcDataSchema(z
|
|
46
55
|
.unknown()
|
|
47
56
|
.transform((value) => Schema.decodeUnknownSync(appAgentSchema)(value)))),
|
|
48
|
-
}));
|
|
57
|
+
})));
|
|
49
58
|
/** Validates Agent rename input: the target Agent and its new display name. */
|
|
50
59
|
export const appAgentRenameInputSchema = Schema.Struct({
|
|
51
60
|
agentId: boundedIdentity,
|
|
52
61
|
name: boundedIdentity,
|
|
53
62
|
});
|
|
54
63
|
/** Owner-only capability to rename an existing Agent; not every host grants it. */
|
|
55
|
-
export const agentRename = defineCapability("agent.rename", 1, rpcHandleSchema({
|
|
64
|
+
export const agentRename = defineCapability("agent.rename", 1, z.lazy(() => rpcHandleSchema({
|
|
56
65
|
rename: rpcMethod(rpcDataSchema(z
|
|
57
66
|
.unknown()
|
|
58
67
|
.transform((value) => Schema.decodeUnknownSync(appAgentSchema)(value)))),
|
|
59
|
-
}));
|
|
68
|
+
})));
|
|
60
69
|
/** Rename an Agent through the host-granted owner-only capability. */
|
|
61
70
|
export async function renameAppAgent(capabilities, input) {
|
|
62
71
|
const request = Schema.decodeUnknownSync(appAgentRenameInputSchema)(input);
|
|
63
72
|
const agent = await capabilities.require(agentRename).rename(request);
|
|
64
73
|
return Schema.decodeUnknownSync(appAgentSchema)(agent);
|
|
65
74
|
}
|
|
75
|
+
/** Validates avatar input: the target Agent and the avatar it now wears. */
|
|
76
|
+
export const appAgentAvatarInputSchema = Schema.Struct({
|
|
77
|
+
agentId: boundedIdentity,
|
|
78
|
+
avatar: appAgentAvatarSchema,
|
|
79
|
+
});
|
|
80
|
+
/** Owner-only capability to change an existing Agent's avatar; not every host grants it. */
|
|
81
|
+
export const agentAvatar = defineCapability("agent.avatar", 1, z.lazy(() => rpcHandleSchema({
|
|
82
|
+
setAvatar: rpcMethod(rpcDataSchema(z
|
|
83
|
+
.unknown()
|
|
84
|
+
.transform((value) => Schema.decodeUnknownSync(appAgentSchema)(value)))),
|
|
85
|
+
})));
|
|
86
|
+
/** Change an Agent's avatar through the host-granted owner-only capability. */
|
|
87
|
+
export async function setAppAgentAvatar(capabilities, input) {
|
|
88
|
+
const request = Schema.decodeUnknownSync(appAgentAvatarInputSchema)(input);
|
|
89
|
+
const agent = await capabilities.require(agentAvatar).setAvatar(request);
|
|
90
|
+
return Schema.decodeUnknownSync(appAgentSchema)(agent);
|
|
91
|
+
}
|
|
66
92
|
/** One Agent's App-tool policy, as the owner-only policy capability reports it. */
|
|
67
|
-
export const appAgentToolPolicyStatusSchema = z.union([
|
|
93
|
+
export const appAgentToolPolicyStatusSchema = z.lazy(() => z.union([
|
|
68
94
|
z.object({ status: z.literal("pending"), revision: z.string() }),
|
|
69
95
|
z.object({ status: z.literal("approved"), revision: z.string() }),
|
|
70
|
-
]);
|
|
96
|
+
]));
|
|
71
97
|
/** The outcome of an owner's direct App-tool approval. */
|
|
72
|
-
export const appAgentToolPolicyResultSchema = z.union([
|
|
73
|
-
appAgentToolPolicyStatusSchema,
|
|
74
|
-
z.object({ error: z.string() }),
|
|
75
|
-
]);
|
|
98
|
+
export const appAgentToolPolicyResultSchema = z.lazy(() => z.union([appAgentToolPolicyStatusSchema, z.object({ error: z.string() })]));
|
|
76
99
|
/** Owner-only capability to read and approve an Agent's App-tool policy. */
|
|
77
|
-
export const agentToolPolicy = defineCapability("agent.toolPolicy", 1, rpcHandleSchema({
|
|
100
|
+
export const agentToolPolicy = defineCapability("agent.toolPolicy", 1, z.lazy(() => rpcHandleSchema({
|
|
78
101
|
status: rpcMethod(rpcDataSchema(z.union([appAgentToolPolicyStatusSchema, z.null()]))),
|
|
79
102
|
approve: rpcMethod(rpcDataSchema(appAgentToolPolicyResultSchema)),
|
|
80
|
-
}));
|
|
103
|
+
})));
|
|
81
104
|
/**
|
|
82
105
|
* Capability for read-only Agent sessions: open a transport to an
|
|
83
106
|
* existing Agent, or read the member's inbox feed.
|
|
84
107
|
*/
|
|
85
|
-
export const agentSessionRead = defineCapability("agent.read", 1, rpcHandleSchema({
|
|
108
|
+
export const agentSessionRead = defineCapability("agent.read", 1, z.lazy(() => rpcHandleSchema({
|
|
86
109
|
open: rpcMethod(rpcFetchHandleSchema),
|
|
87
110
|
openInbox: rpcMethod(rpcFetchHandleSchema),
|
|
88
|
-
}));
|
|
111
|
+
})));
|
|
89
112
|
/**
|
|
90
113
|
* Capability for read-write Agent sessions: open a transport to an
|
|
91
114
|
* existing Agent and send to it, including the member's inbox feed.
|
|
92
115
|
*/
|
|
93
|
-
export const agentSessionWrite = defineCapability("agent.send", 1, rpcHandleSchema({
|
|
116
|
+
export const agentSessionWrite = defineCapability("agent.send", 1, z.lazy(() => rpcHandleSchema({
|
|
94
117
|
open: rpcMethod(rpcFetchHandleSchema),
|
|
95
118
|
openInbox: rpcMethod(rpcFetchHandleSchema),
|
|
96
|
-
}));
|
|
119
|
+
})));
|
|
97
120
|
/** List the Agents in the host-granted Team or local-project scope. */
|
|
98
121
|
export async function listAppAgents(capabilities) {
|
|
99
122
|
return decodeAgents(await capabilities.require(agentList).list());
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { type Approvals } from "@fungi.computer/approvals";
|
|
2
|
+
import { type CapabilityContract } from "./capabilities.js";
|
|
3
|
+
export type { Approvals } from "@fungi.computer/approvals";
|
|
4
|
+
/** Member-bound approval view. Authentication and current rights belong to the host. */
|
|
5
|
+
export declare const approvals: CapabilityContract<Approvals>;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import * as Schema from "effect/Schema";
|
|
2
|
+
import * as z from "zod";
|
|
3
|
+
import { ApprovalViewSchema, ApprovalRefusalReasonSchema, AutoApproveInputSchema, } from "@fungi.computer/approvals";
|
|
4
|
+
import { defineCapability } from "./capabilities.js";
|
|
5
|
+
import { rpcDataSchema, rpcHandleSchema, rpcMethod, } from "./internal/rpc-contract.js";
|
|
6
|
+
const refusal = Schema.Struct({
|
|
7
|
+
kind: Schema.Literal("refused"),
|
|
8
|
+
reason: ApprovalRefusalReasonSchema,
|
|
9
|
+
});
|
|
10
|
+
const page = Schema.Struct({
|
|
11
|
+
items: Schema.Array(ApprovalViewSchema),
|
|
12
|
+
nextCursor: Schema.NullOr(Schema.String),
|
|
13
|
+
});
|
|
14
|
+
const answer = Schema.Union([
|
|
15
|
+
Schema.Struct({ kind: Schema.Literal("answered"), view: ApprovalViewSchema }),
|
|
16
|
+
refusal,
|
|
17
|
+
]);
|
|
18
|
+
const policy = Schema.Union([
|
|
19
|
+
Schema.Struct({
|
|
20
|
+
kind: Schema.Literal("updated"),
|
|
21
|
+
rule: AutoApproveInputSchema,
|
|
22
|
+
}),
|
|
23
|
+
refusal,
|
|
24
|
+
]);
|
|
25
|
+
// Match the existing storage/Agent capability adapters: the maintained RPC
|
|
26
|
+
// helpers bind native stub receivers, decode data and release result envelopes.
|
|
27
|
+
const data = (schema) => rpcDataSchema(z
|
|
28
|
+
.unknown()
|
|
29
|
+
.transform((value) => Schema.decodeUnknownSync(schema, { onExcessProperty: "error" })(value)));
|
|
30
|
+
/** Member-bound approval view. Authentication and current rights belong to the host. */
|
|
31
|
+
export const approvals = defineCapability("approvals", 1, z.lazy(() => rpcHandleSchema({
|
|
32
|
+
list: rpcMethod(data(page)),
|
|
33
|
+
get: rpcMethod(data(Schema.NullOr(ApprovalViewSchema))),
|
|
34
|
+
answer: rpcMethod(data(answer)),
|
|
35
|
+
setAutoApprove: rpcMethod(data(policy)),
|
|
36
|
+
})));
|
package/dist/apps.js
CHANGED
|
@@ -36,12 +36,12 @@ export const appRoleChoiceSchema = z
|
|
|
36
36
|
* `role` answers which App that open would reach (null when none fills it),
|
|
37
37
|
* so a caller can name or hide its entry without hard-coding another App.
|
|
38
38
|
*/
|
|
39
|
-
export const appsOpen = defineCapability("apps.open", 1, rpcHandleSchema({
|
|
39
|
+
export const appsOpen = defineCapability("apps.open", 1, z.lazy(() => rpcHandleSchema({
|
|
40
40
|
open: rpcVoid,
|
|
41
41
|
role: rpcMethod(rpcDataSchema(appRoleChoiceSchema)),
|
|
42
|
-
}));
|
|
42
|
+
})));
|
|
43
43
|
export const openApp = (directory, input) => directory.require(appsOpen).open(input);
|
|
44
44
|
/** Call a declared method of another App as the signed-in member. Caller grants never travel. */
|
|
45
|
-
export const appsCall = defineCapability("apps.call", 1, rpcHandleSchema({
|
|
45
|
+
export const appsCall = defineCapability("apps.call", 1, z.lazy(() => rpcHandleSchema({
|
|
46
46
|
call: rpcMethod(rpcDataSchema(z.unknown().transform((value) => parseJsonValue(value)))),
|
|
47
|
-
}));
|
|
47
|
+
})));
|