@fungi.computer/agar 0.6.0 → 0.7.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 +1 -1
- package/dist/agents.d.ts +28 -4
- package/dist/agents.js +31 -2
- package/dist/computer.d.ts +2 -2
- package/dist/computer.js +2 -1
- package/dist/inbox.d.ts +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/dist/media.d.ts +33 -0
- package/dist/media.js +27 -0
- package/dist/query.d.ts +1 -1
- package/dist/test-kit/git.js +63 -37
- package/docs/api/backend-definition.md +3 -3
- package/docs/api/index.md +138 -2
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -9,7 +9,7 @@ methods, connects its frontend to a host through typed capabilities, and gives
|
|
|
9
9
|
App builders selected context, host-rendered permission requests and explicit
|
|
10
10
|
cleanup. The host and resource owners authorize the work; the same App runs on
|
|
11
11
|
Fungi's hosted Teams or on any host that composes
|
|
12
|
-
[Oyster](https://oyster
|
|
12
|
+
[Oyster](https://github.com/fungi-computer/oyster).
|
|
13
13
|
|
|
14
14
|
## Install or set up
|
|
15
15
|
|
package/dist/agents.d.ts
CHANGED
|
@@ -56,14 +56,31 @@ export declare const appAgentListResultSchema: z.ZodLazy<z.ZodObject<{
|
|
|
56
56
|
name: z.ZodString;
|
|
57
57
|
}, z.core.$strict>>;
|
|
58
58
|
}, z.core.$strict>>;
|
|
59
|
-
/**
|
|
60
|
-
|
|
59
|
+
/**
|
|
60
|
+
* Computer provisioning is a Team creation choice, separate from Home policy:
|
|
61
|
+
* a new Computer, none, or one of the Team's existing Computers.
|
|
62
|
+
*/
|
|
63
|
+
export declare const appAgentComputerSchema: Schema.Union<readonly [Schema.Literals<readonly ["new", "none"]>, Schema.Struct<{
|
|
64
|
+
readonly computerId: Schema.String;
|
|
65
|
+
}>]>;
|
|
66
|
+
/** The creation-time Computer choice for a new Agent. */
|
|
67
|
+
export type AppAgentComputer = Schema.Schema.Type<typeof appAgentComputerSchema>;
|
|
68
|
+
/** One existing Team Computer a new Agent may start on. */
|
|
69
|
+
export declare const appAgentComputerChoiceSchema: Schema.Struct<{
|
|
70
|
+
readonly computerId: Schema.String;
|
|
71
|
+
readonly name: Schema.String;
|
|
72
|
+
readonly createdAt: Schema.Number;
|
|
73
|
+
}>;
|
|
74
|
+
/** An existing Team Computer offered when creating an Agent. */
|
|
75
|
+
export type AppAgentComputerChoice = Schema.Schema.Type<typeof appAgentComputerChoiceSchema>;
|
|
61
76
|
/** Validates Agent creation input: a name, a caller-chosen request id, an
|
|
62
77
|
* optional Computer provisioning choice and an optional chosen avatar. */
|
|
63
78
|
export declare const appAgentCreateInputSchema: Schema.Struct<{
|
|
64
79
|
readonly name: Schema.String;
|
|
65
80
|
readonly requestId: Schema.String;
|
|
66
|
-
readonly computer: Schema.optionalKey<Schema.Literals<readonly ["new", "none"]
|
|
81
|
+
readonly computer: Schema.optionalKey<Schema.Union<readonly [Schema.Literals<readonly ["new", "none"]>, Schema.Struct<{
|
|
82
|
+
readonly computerId: Schema.String;
|
|
83
|
+
}>]>>;
|
|
67
84
|
readonly avatar: Schema.optionalKey<Schema.declare<{
|
|
68
85
|
v: 1;
|
|
69
86
|
character: "mushroom" | "cat" | "burger";
|
|
@@ -102,6 +119,8 @@ export type AppAgentListHandle = {
|
|
|
102
119
|
export type AppAgentCreateHandle = {
|
|
103
120
|
/** Create a new Agent with the given name and request id. */
|
|
104
121
|
create(input: AppAgentCreateInput): Promise<AppAgent>;
|
|
122
|
+
/** The Team Computers a new Agent may use; null when the host offers no choice. */
|
|
123
|
+
computers(): Promise<readonly AppAgentComputerChoice[] | null>;
|
|
105
124
|
};
|
|
106
125
|
/**
|
|
107
126
|
* Live capability handle for listing and creating Agents in a Team or
|
|
@@ -118,7 +137,7 @@ export type AppAgentDirectoryHandle = AppAgentListHandle & AppAgentCreateHandle
|
|
|
118
137
|
/** Capability to list the Agents visible to this App in read-only form. */
|
|
119
138
|
export declare const agentList: CapabilityContract<AppAgentListHandle>;
|
|
120
139
|
/** Capability to create new Agents and open transports to them. */
|
|
121
|
-
export declare const agentManage: CapabilityContract<Pick<AppAgentDirectoryHandle, "create" | "open">>;
|
|
140
|
+
export declare const agentManage: CapabilityContract<Pick<AppAgentDirectoryHandle, "create" | "computers" | "open">>;
|
|
122
141
|
/** Validates Agent rename input: the target Agent and its new display name. */
|
|
123
142
|
export declare const appAgentRenameInputSchema: Schema.Struct<{
|
|
124
143
|
readonly agentId: Schema.String;
|
|
@@ -217,6 +236,11 @@ export declare const agentSessionWrite: CapabilityContract<Pick<AppAgentDirector
|
|
|
217
236
|
export declare function listAppAgents(capabilities: CapabilityDirectory): Promise<readonly AppAgent[]>;
|
|
218
237
|
/** Create an Agent through the Team directory selected by the host. */
|
|
219
238
|
export declare function createAppAgent(capabilities: CapabilityDirectory, input: AppAgentCreateInput): Promise<AppAgent>;
|
|
239
|
+
/**
|
|
240
|
+
* The Team Computers a new Agent may use, newest first, or null when the host
|
|
241
|
+
* makes no creation-time Computer choice.
|
|
242
|
+
*/
|
|
243
|
+
export declare function listAppAgentComputers(capabilities: CapabilityDirectory): Promise<readonly AppAgentComputerChoice[] | null>;
|
|
220
244
|
/**
|
|
221
245
|
* A Fetch-based transport to one Agent's session endpoint, scoped to
|
|
222
246
|
* this App and safe to hand to an HTTP client adapter.
|
package/dist/agents.js
CHANGED
|
@@ -28,8 +28,26 @@ export const appAgentSchema = Schema.Struct({
|
|
|
28
28
|
export const appAgentListResultSchema = z.lazy(() => z.strictObject({
|
|
29
29
|
agents: z.array(z.strictObject({ agentId: z.string(), name: z.string() })),
|
|
30
30
|
}));
|
|
31
|
-
/**
|
|
32
|
-
|
|
31
|
+
/**
|
|
32
|
+
* Computer provisioning is a Team creation choice, separate from Home policy:
|
|
33
|
+
* a new Computer, none, or one of the Team's existing Computers.
|
|
34
|
+
*/
|
|
35
|
+
export const appAgentComputerSchema = Schema.Union([
|
|
36
|
+
Schema.Literals(["new", "none"]),
|
|
37
|
+
Schema.Struct({ computerId: boundedIdentity }),
|
|
38
|
+
]);
|
|
39
|
+
/** One existing Team Computer a new Agent may start on. */
|
|
40
|
+
export const appAgentComputerChoiceSchema = Schema.Struct({
|
|
41
|
+
computerId: boundedIdentity,
|
|
42
|
+
name: boundedIdentity,
|
|
43
|
+
createdAt: Schema.Number.pipe(Schema.check(Schema.isInt())),
|
|
44
|
+
});
|
|
45
|
+
/**
|
|
46
|
+
* The host's existing Computers for a new Agent, or null when the host makes
|
|
47
|
+
* no creation-time Computer choice at all.
|
|
48
|
+
*/
|
|
49
|
+
const appAgentComputerChoicesSchema = Schema.NullOr(Schema.Array(appAgentComputerChoiceSchema));
|
|
50
|
+
const decodeComputerChoices = Schema.decodeUnknownSync(appAgentComputerChoicesSchema, { onExcessProperty: "error" });
|
|
33
51
|
/** Validates Agent creation input: a name, a caller-chosen request id, an
|
|
34
52
|
* optional Computer provisioning choice and an optional chosen avatar. */
|
|
35
53
|
export const appAgentCreateInputSchema = Schema.Struct({
|
|
@@ -51,6 +69,7 @@ export const agentList = defineCapability("agent.list", 1, z.lazy(() => rpcHandl
|
|
|
51
69
|
/** Capability to create new Agents and open transports to them. */
|
|
52
70
|
export const agentManage = defineCapability("agent.manage", 1, z.lazy(() => rpcHandleSchema({
|
|
53
71
|
open: rpcMethod(rpcFetchHandleSchema),
|
|
72
|
+
computers: rpcMethod(rpcDataSchema(z.unknown().transform((value) => decodeComputerChoices(value)))),
|
|
54
73
|
create: rpcMethod(rpcDataSchema(z
|
|
55
74
|
.unknown()
|
|
56
75
|
.transform((value) => Schema.decodeUnknownSync(appAgentSchema)(value)))),
|
|
@@ -127,6 +146,16 @@ export async function createAppAgent(capabilities, input) {
|
|
|
127
146
|
const agent = await capabilities.require(agentManage).create(request);
|
|
128
147
|
return Schema.decodeUnknownSync(appAgentSchema)(agent);
|
|
129
148
|
}
|
|
149
|
+
/**
|
|
150
|
+
* The Team Computers a new Agent may use, newest first, or null when the host
|
|
151
|
+
* makes no creation-time Computer choice.
|
|
152
|
+
*/
|
|
153
|
+
export async function listAppAgentComputers(capabilities) {
|
|
154
|
+
const choices = decodeComputerChoices(await capabilities.require(agentManage).computers());
|
|
155
|
+
return choices === null
|
|
156
|
+
? null
|
|
157
|
+
: [...choices].sort((a, b) => b.createdAt - a.createdAt);
|
|
158
|
+
}
|
|
130
159
|
/** Keep read and write handles separate while owning their shared connection lifetime. */
|
|
131
160
|
async function openOperationHandles(openRead, openWrite) {
|
|
132
161
|
const read = await openRead();
|
package/dist/computer.d.ts
CHANGED
|
@@ -20,7 +20,7 @@ export declare const computerList: CapabilityContract<{
|
|
|
20
20
|
}): Promise<ComputerListing>;
|
|
21
21
|
}>;
|
|
22
22
|
export declare const computerRuntimeStateSchema: Schema.Union<readonly [Schema.Struct<{
|
|
23
|
-
readonly state: Schema.Literals<readonly ["running", "sleeping", "starting"]>;
|
|
23
|
+
readonly state: Schema.Literals<readonly ["running", "sleeping", "starting", "start_failed"]>;
|
|
24
24
|
}>, Schema.Struct<{
|
|
25
25
|
readonly state: Schema.Literal<"queued">;
|
|
26
26
|
readonly position: Schema.Number;
|
|
@@ -36,7 +36,7 @@ export declare const computerInstrumentSnapshotSchema: Schema.Struct<{
|
|
|
36
36
|
readonly computerId: Schema.NonEmptyString;
|
|
37
37
|
readonly name: Schema.NonEmptyString;
|
|
38
38
|
readonly runtime: Schema.Union<readonly [Schema.Struct<{
|
|
39
|
-
readonly state: Schema.Literals<readonly ["running", "sleeping", "starting"]>;
|
|
39
|
+
readonly state: Schema.Literals<readonly ["running", "sleeping", "starting", "start_failed"]>;
|
|
40
40
|
}>, Schema.Struct<{
|
|
41
41
|
readonly state: Schema.Literal<"queued">;
|
|
42
42
|
readonly position: Schema.Number;
|
package/dist/computer.js
CHANGED
|
@@ -22,7 +22,8 @@ export const computerList = defineCapability("computer.list", 1, z.lazy(() => rp
|
|
|
22
22
|
})));
|
|
23
23
|
export const computerRuntimeStateSchema = Schema.Union([
|
|
24
24
|
Schema.Struct({
|
|
25
|
-
|
|
25
|
+
// start_failed: a queued start ended without running; start again.
|
|
26
|
+
state: Schema.Literals(["running", "sleeping", "starting", "start_failed"]),
|
|
26
27
|
}),
|
|
27
28
|
Schema.Struct({
|
|
28
29
|
state: Schema.Literal("queued"),
|
package/dist/inbox.d.ts
CHANGED
|
@@ -78,8 +78,8 @@ export declare function watchMemberInbox(options: Readonly<{
|
|
|
78
78
|
export declare function readTeamInboxNoticePage(transport: Pick<AppAgentTransport, "baseUrl" | "fetch">, after?: string | null): Promise<{
|
|
79
79
|
readonly items: readonly ({
|
|
80
80
|
readonly appId: import("@fungi.computer/puffball").AppId;
|
|
81
|
-
readonly displayName: string;
|
|
82
81
|
readonly createdAt: number;
|
|
82
|
+
readonly displayName: string;
|
|
83
83
|
readonly dispositionId: string;
|
|
84
84
|
readonly releaseIds: readonly import("@fungi.computer/puffball").ReleaseId[];
|
|
85
85
|
readonly reason?: string | undefined;
|
package/dist/index.d.ts
CHANGED
|
@@ -6,8 +6,8 @@ export type { Pending } from "./pending.js";
|
|
|
6
6
|
export type { CapabilityContract, CapabilityDirectory, CapabilityRegistry, } from "./capabilities.js";
|
|
7
7
|
export { agentAvatar, agentList, agentManage, agentRename, agentSessionRead, agentSessionWrite, agentToolPolicy, createAppAgent, renameAppAgent, setAppAgentAvatar, appAgentAvatarInputSchema, appAgentAvatarSchema, appAgentCreateInputSchema, appAgentRenameInputSchema, appAgentSchema, appAgentToolPolicyResultSchema, appAgentToolPolicyStatusSchema, listAppAgents, openAppAgent, } from "./agents.js";
|
|
8
8
|
export type { AppAgent, AppAgentAvatarHandle, AppAgentAvatarInput, AppAgentCreateHandle, AppAgentCreateInput, AppAgentDirectoryHandle, AppAgentListHandle, AppAgentRenameHandle, AppAgentRenameInput, AppAgentToolPolicyHandle, AppAgentToolPolicyResult, AppAgentToolPolicyStatus, AppAgentTransport, AppAgentTransportHandle, } from "./agents.js";
|
|
9
|
-
export { mediaGeneration, mediaGenerationFailureSchema, mediaGenerationReferenceSchema, mediaGenerationSelectionSchema, mediaModelSchema, openMediaGeneration, } from "./media.js";
|
|
10
|
-
export type { MediaGenerationHandle, MediaGenerationAttempt, MediaGenerationAttemptHandle, MediaGenerationFailure, MediaGenerationInput, MediaGenerationOutcome, MediaGenerationReference, MediaGenerationResult, MediaGenerationSelection, MediaModel, MediaOutputFormat, MediaGenerationSession, } from "./media.js";
|
|
9
|
+
export { mediaGeneration, mediaGenerationFailureSchema, mediaGenerationReferenceSchema, mediaGenerationSelectionSchema, mediaModelSchema, mediaShare, mediaShareInputSchema, mediaShareStatusSchema, openMediaGeneration, } from "./media.js";
|
|
10
|
+
export type { MediaShareHandle, MediaShareInput, MediaShareStatus, MediaGenerationHandle, MediaGenerationAttempt, MediaGenerationAttemptHandle, MediaGenerationFailure, MediaGenerationInput, MediaGenerationOutcome, MediaGenerationReference, MediaGenerationResult, MediaGenerationSelection, MediaModel, MediaOutputFormat, MediaGenerationSession, } from "./media.js";
|
|
11
11
|
export type { AppCommand, AppCommandHandler, AppCommandInvocation, AppCommands, } from "./commands.js";
|
|
12
12
|
export { registerCatalog } from "./commands.js";
|
|
13
13
|
export { connectApp } from "./connect.js";
|
package/dist/index.js
CHANGED
|
@@ -2,7 +2,7 @@ export { FungiAuthorSchema, FungiDelegationReplySchema, FungiMessageMetaSchema,
|
|
|
2
2
|
export { createCapabilityRegistry, defineCapability } from "./capabilities.js";
|
|
3
3
|
export { pending, pendingSchema } from "./pending.js";
|
|
4
4
|
export { agentAvatar, agentList, agentManage, agentRename, agentSessionRead, agentSessionWrite, agentToolPolicy, createAppAgent, renameAppAgent, setAppAgentAvatar, appAgentAvatarInputSchema, appAgentAvatarSchema, appAgentCreateInputSchema, appAgentRenameInputSchema, appAgentSchema, appAgentToolPolicyResultSchema, appAgentToolPolicyStatusSchema, listAppAgents, openAppAgent, } from "./agents.js";
|
|
5
|
-
export { mediaGeneration, mediaGenerationFailureSchema, mediaGenerationReferenceSchema, mediaGenerationSelectionSchema, mediaModelSchema, openMediaGeneration, } from "./media.js";
|
|
5
|
+
export { mediaGeneration, mediaGenerationFailureSchema, mediaGenerationReferenceSchema, mediaGenerationSelectionSchema, mediaModelSchema, mediaShare, mediaShareInputSchema, mediaShareStatusSchema, openMediaGeneration, } from "./media.js";
|
|
6
6
|
export { registerCatalog } from "./commands.js";
|
|
7
7
|
export { connectApp } from "./connect.js";
|
|
8
8
|
/** Data exchanged by iframe and host before the RPC MessagePort takes over. */
|
package/dist/media.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import * as z from "zod";
|
|
1
2
|
import * as Schema from "effect/Schema";
|
|
2
3
|
import type { MediaProviderDiagnostic } from "./errors.js";
|
|
3
4
|
export { mediaLibraryRequestSchema, mediaLibraryPathSchema, mediaLibraryResponseSchema, } from "./media-library.js";
|
|
@@ -371,6 +372,38 @@ export declare const mediaGenerationFailureSchema: Schema.Struct<{
|
|
|
371
372
|
* declare it to request access; openMediaGeneration uses it to obtain
|
|
372
373
|
* the host's handle. */
|
|
373
374
|
export declare const mediaGeneration: CapabilityContract<MediaGenerationHandle>;
|
|
375
|
+
/** Whether one generated Print has a public link, and what that link shows. */
|
|
376
|
+
export declare const mediaShareStatusSchema: z.ZodUnion<readonly [z.ZodObject<{
|
|
377
|
+
shared: z.ZodLiteral<false>;
|
|
378
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
379
|
+
shared: z.ZodLiteral<true>;
|
|
380
|
+
url: z.ZodURL;
|
|
381
|
+
showPrompt: z.ZodBoolean;
|
|
382
|
+
}, z.core.$strict>]>;
|
|
383
|
+
/** A Print's share state as the host reports it. */
|
|
384
|
+
export type MediaShareStatus = z.output<typeof mediaShareStatusSchema>;
|
|
385
|
+
/** Turn a public link on for one generated Print. */
|
|
386
|
+
export declare const mediaShareInputSchema: z.ZodObject<{
|
|
387
|
+
requestId: z.ZodString;
|
|
388
|
+
showPrompt: z.ZodBoolean;
|
|
389
|
+
}, z.core.$strict>;
|
|
390
|
+
/** What to share and whether to show its prompt. */
|
|
391
|
+
export type MediaShareInput = z.output<typeof mediaShareInputSchema>;
|
|
392
|
+
/** Host handle behind the `media.share` capability. */
|
|
393
|
+
export type MediaShareHandle = Readonly<{
|
|
394
|
+
/** Read whether this Print has a live public link. */
|
|
395
|
+
status(requestId: string): Promise<MediaShareStatus>;
|
|
396
|
+
/** Turn a public link on; repeating it returns the live link unchanged. */
|
|
397
|
+
share(input: MediaShareInput): Promise<MediaShareStatus>;
|
|
398
|
+
/** Stop sharing; the link stops working at once. */
|
|
399
|
+
stop(requestId: string): Promise<MediaShareStatus>;
|
|
400
|
+
}>;
|
|
401
|
+
/**
|
|
402
|
+
* Capability contract for public links to generated Media. Off by default
|
|
403
|
+
* per output; the host keeps the link, the bytes it serves and who may change
|
|
404
|
+
* it.
|
|
405
|
+
*/
|
|
406
|
+
export declare const mediaShare: CapabilityContract<MediaShareHandle>;
|
|
374
407
|
/** Decode and normalize a typed input envelope; storage parses the envelope first. */
|
|
375
408
|
export declare function parseMediaGenerationInput(input: Schema.Schema.Type<typeof mediaGenerationInputWireSchema>): MediaGenerationInput;
|
|
376
409
|
/** Discover the exact retained model catalog surfaced by the owner. */
|
package/dist/media.js
CHANGED
|
@@ -357,6 +357,33 @@ export const mediaGeneration = defineCapability("media.generation", 5, z.lazy(()
|
|
|
357
357
|
restoreAttempt: rpcMethod(mediaAttemptHandleSchema),
|
|
358
358
|
cancelAttempt: rpcVoid,
|
|
359
359
|
})));
|
|
360
|
+
/** Whether one generated Print has a public link, and what that link shows. */
|
|
361
|
+
export const mediaShareStatusSchema = z.union([
|
|
362
|
+
z.strictObject({ shared: z.literal(false) }),
|
|
363
|
+
z.strictObject({
|
|
364
|
+
shared: z.literal(true),
|
|
365
|
+
/** The public, read-only page; anyone with it can see this one Print. */
|
|
366
|
+
url: z.url(),
|
|
367
|
+
/** The page shows the prompt only when its owner chose to. */
|
|
368
|
+
showPrompt: z.boolean(),
|
|
369
|
+
}),
|
|
370
|
+
]);
|
|
371
|
+
/** Turn a public link on for one generated Print. */
|
|
372
|
+
export const mediaShareInputSchema = z.strictObject({
|
|
373
|
+
/** The generation's request identity (a Print's `printId`). */
|
|
374
|
+
requestId: z.string().min(1).max(256),
|
|
375
|
+
showPrompt: z.boolean(),
|
|
376
|
+
});
|
|
377
|
+
/**
|
|
378
|
+
* Capability contract for public links to generated Media. Off by default
|
|
379
|
+
* per output; the host keeps the link, the bytes it serves and who may change
|
|
380
|
+
* it.
|
|
381
|
+
*/
|
|
382
|
+
export const mediaShare = defineCapability("media.share", 1, z.lazy(() => rpcHandleSchema({
|
|
383
|
+
status: rpcMethod(rpcDataSchema(mediaShareStatusSchema)),
|
|
384
|
+
share: rpcMethod(rpcDataSchema(mediaShareStatusSchema)),
|
|
385
|
+
stop: rpcMethod(rpcDataSchema(mediaShareStatusSchema)),
|
|
386
|
+
})));
|
|
360
387
|
/** Parse a value received from the host and turn schema failures into the
|
|
361
388
|
* transport-safe Agar error used by the other capability helpers. */
|
|
362
389
|
function decode(schema, value) {
|
package/dist/query.d.ts
CHANGED
|
@@ -37,8 +37,8 @@ export declare function useMemberInbox(app: QueryApp | null): {
|
|
|
37
37
|
readonly agentId: string;
|
|
38
38
|
readonly sessionId: string;
|
|
39
39
|
readonly title: string;
|
|
40
|
-
readonly state: "running" | "done" | "needs_you" | "errored";
|
|
41
40
|
readonly createdAt: number;
|
|
41
|
+
readonly state: "running" | "done" | "needs_you" | "errored";
|
|
42
42
|
readonly lastActivityAt: number;
|
|
43
43
|
readonly triggerId?: string | undefined;
|
|
44
44
|
readonly settledAt?: number | undefined;
|
package/dist/test-kit/git.js
CHANGED
|
@@ -13,50 +13,41 @@ export function realGit() {
|
|
|
13
13
|
const info = (name) => existsSync(join(root, `${name}.git`))
|
|
14
14
|
? { name, defaultBranch: "main", lastPushAt: null, source: null }
|
|
15
15
|
: null;
|
|
16
|
+
const gitOutput = (name, ...args) => execFileSync("git", [`--git-dir=${join(root, `${name}.git`)}`, ...args], {
|
|
17
|
+
encoding: "utf8",
|
|
18
|
+
// A thousand-commit log page is over execFileSync's 1 MiB default.
|
|
19
|
+
maxBuffer: 256 * 1024 * 1024,
|
|
20
|
+
});
|
|
16
21
|
// A full object id names an immutable commit, so one read serves every
|
|
17
22
|
// later ask; refs and abbreviations move and are never cached.
|
|
18
23
|
const commits = new Map();
|
|
19
24
|
const immutable = (hash) => /^[0-9a-f]{40,64}$/u.test(hash);
|
|
20
|
-
const
|
|
25
|
+
const cacheKey = (name, hash) => {
|
|
21
26
|
// The repository's directory identity keeps a deleted-and-recreated name
|
|
22
27
|
// from serving the old repository's commits, however it was removed.
|
|
23
28
|
const dir = statSync(join(root, `${name}.git`), {
|
|
24
29
|
bigint: true,
|
|
25
30
|
throwIfNoEntry: false,
|
|
26
31
|
});
|
|
27
|
-
|
|
28
|
-
|
|
32
|
+
return `${name}\0${String(dir?.ino)}\0${String(dir?.birthtimeNs)}\0${hash}`;
|
|
33
|
+
};
|
|
34
|
+
const remember = (name, commit) => {
|
|
35
|
+
commits.set(cacheKey(name, commit.hash), structuredClone(commit));
|
|
36
|
+
};
|
|
37
|
+
const readCommit = (name, hash) => {
|
|
38
|
+
const cached = immutable(hash)
|
|
39
|
+
? commits.get(cacheKey(name, hash))
|
|
40
|
+
: undefined;
|
|
29
41
|
if (cached !== undefined)
|
|
30
42
|
return structuredClone(cached);
|
|
31
43
|
const found = spawnSync("git", [`--git-dir=${join(root, `${name}.git`)}`, "cat-file", "-t", hash], { encoding: "utf8" });
|
|
32
44
|
if (found.status !== 0 || found.stdout.trim() !== "commit")
|
|
33
45
|
return null;
|
|
34
|
-
const
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
z.string(),
|
|
38
|
-
z.string(),
|
|
39
|
-
z.string(),
|
|
40
|
-
z.string(),
|
|
41
|
-
z.string(),
|
|
42
|
-
z.string(),
|
|
43
|
-
z.string(),
|
|
44
|
-
z.string(),
|
|
45
|
-
z.string(),
|
|
46
|
-
])
|
|
47
|
-
.parse(run(name, "show", "-s", "--format=%H%x00%T%x00%P%x00%an%x00%ae%x00%cn%x00%ce%x00%at%x00%ct%x00%B", hash).split("\0"));
|
|
48
|
-
const commit = {
|
|
49
|
-
hash: oid,
|
|
50
|
-
treeHash,
|
|
51
|
-
parents: parents ? parents.split(" ") : [],
|
|
52
|
-
author: { name: authorName, email: authorEmail },
|
|
53
|
-
committer: { name: committerName, email: committerEmail },
|
|
54
|
-
authoredAt: Number(authoredAt),
|
|
55
|
-
committedAt: Number(committedAt),
|
|
56
|
-
message,
|
|
57
|
-
};
|
|
46
|
+
const commit = parseCommits(gitOutput(name, "show", "-s", "-z", `--format=${COMMIT_FORMAT}`, hash)).at(0);
|
|
47
|
+
if (!commit)
|
|
48
|
+
throw new Error("Commit unreadable");
|
|
58
49
|
if (immutable(hash))
|
|
59
|
-
|
|
50
|
+
remember(name, commit);
|
|
60
51
|
return commit;
|
|
61
52
|
};
|
|
62
53
|
const git = {
|
|
@@ -93,15 +84,11 @@ export function realGit() {
|
|
|
93
84
|
log: (name, { ref, limit = 50, offset = 0 }) => {
|
|
94
85
|
if (!readCommit(name, ref))
|
|
95
86
|
return Promise.resolve([]);
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
if (!commit)
|
|
102
|
-
throw new Error("Commit disappeared");
|
|
103
|
-
return commit;
|
|
104
|
-
}));
|
|
87
|
+
// One walk with the same rev-list flags reads every page commit.
|
|
88
|
+
const page = parseCommits(gitOutput(name, "log", "-z", `--format=${COMMIT_FORMAT}`, "--first-parent", `--max-count=${String(limit)}`, `--skip=${String(offset)}`, ref));
|
|
89
|
+
for (const commit of page)
|
|
90
|
+
remember(name, commit);
|
|
91
|
+
return Promise.resolve(page);
|
|
105
92
|
},
|
|
106
93
|
readTree: (name, hash) => Promise.resolve(run(name, "ls-tree", "-z", hash)
|
|
107
94
|
.split("\0")
|
|
@@ -189,3 +176,42 @@ export function realGit() {
|
|
|
189
176
|
},
|
|
190
177
|
};
|
|
191
178
|
}
|
|
179
|
+
// Ten NUL-separated fields per commit; `-z` ends each commit with NUL too.
|
|
180
|
+
const COMMIT_FORMAT = "%H%x00%T%x00%P%x00%an%x00%ae%x00%cn%x00%ce%x00%at%x00%ct%x00%B";
|
|
181
|
+
const COMMIT_FIELDS = 10;
|
|
182
|
+
const commitFields = z.tuple([
|
|
183
|
+
z.string(),
|
|
184
|
+
z.string(),
|
|
185
|
+
z.string(),
|
|
186
|
+
z.string(),
|
|
187
|
+
z.string(),
|
|
188
|
+
z.string(),
|
|
189
|
+
z.string(),
|
|
190
|
+
z.string(),
|
|
191
|
+
z.string(),
|
|
192
|
+
z.string(),
|
|
193
|
+
]);
|
|
194
|
+
function parseCommits(output) {
|
|
195
|
+
const fields = output.split("\0");
|
|
196
|
+
// The final commit's NUL terminator leaves one empty trailing field.
|
|
197
|
+
if (fields.at(-1) === "")
|
|
198
|
+
fields.pop();
|
|
199
|
+
if (fields.length % COMMIT_FIELDS !== 0)
|
|
200
|
+
throw new Error("Unexpected git commit format");
|
|
201
|
+
const parsed = [];
|
|
202
|
+
for (let start = 0; start < fields.length; start += COMMIT_FIELDS) {
|
|
203
|
+
const [oid, treeHash, parents, authorName, authorEmail, committerName, committerEmail, authoredAt, committedAt, message,] = commitFields.parse(fields.slice(start, start + COMMIT_FIELDS));
|
|
204
|
+
parsed.push({
|
|
205
|
+
hash: oid,
|
|
206
|
+
treeHash,
|
|
207
|
+
parents: parents ? parents.split(" ") : [],
|
|
208
|
+
author: { name: authorName, email: authorEmail },
|
|
209
|
+
committer: { name: committerName, email: committerEmail },
|
|
210
|
+
authoredAt: Number(authoredAt),
|
|
211
|
+
committedAt: Number(committedAt),
|
|
212
|
+
// %B keeps the raw message's trailing newline; readers see it trimmed.
|
|
213
|
+
message: message.trimEnd(),
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
return parsed;
|
|
217
|
+
}
|
|
@@ -228,9 +228,9 @@ Define a typed method once; neither discovery nor builds execute its handler.
|
|
|
228
228
|
|
|
229
229
|
#### Parameters
|
|
230
230
|
|
|
231
|
-
| Parameter | Type
|
|
232
|
-
| --------- |
|
|
233
|
-
| `method` | `Omit`\<`Readonly`\<\{ `description`: `string`; `effect`: `"external"` \| `"read"` \| `"write"`; `requires`: readonly ( \| `"agent.list"` \| `"agent.manage"` \| `"agent.read"` \| `"agent.send"` \| `"computer.list"` \| `"computer.readFile"` \| `"computer.writeFile"` \| `"computer.execute"` \| `"agent.rename"` \| `"agent.avatar"` \| `"agent.toolPolicy"` \| `"approvals"` \| `"apps.open"` \| `"apps.call"` \| `"llm.generation"` \| `"media.generation"` \| `"games:servers"` \| `"git.repository"` \| `"app.storage"` \| `"app.events.emit"` \| `"team.workbenchHost"` \| `"marketplace.browse"` \| `"marketplace.purchase"` \| `"workflow.run"` \| `"workflow.publish"` \| `"workflow.arm"` \| `"world"` \| `"channels.read"` \| `"channels.personal.manage"`)[]; `hidden?`: `true`; `pending?`: `true`; `present?`: `Readonly`\<\{ `verb`: `string`; \}\>; \}\>, `"present"`\> & \{ input: I; output: O; present?: Readonly\<\{ verb: string; row: (call: Readonly\<\{ input: output\<I\>; output: output\<O\>; \}\>) =\> \{ readonly id: string; readonly title: string; ... 4 more ...; readonly media?: \{ ...; \} \| undefined; \}; rows: Readonly\<...\>; \}\> \| undefined; \} & (\{ ...; \} \| \{ ...; \}) |
|
|
231
|
+
| Parameter | Type |
|
|
232
|
+
| --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
233
|
+
| `method` | `Omit`\<`Readonly`\<\{ `description`: `string`; `effect`: `"external"` \| `"read"` \| `"write"`; `requires`: readonly ( \| `"agent.list"` \| `"agent.manage"` \| `"agent.read"` \| `"agent.send"` \| `"computer.list"` \| `"computer.readFile"` \| `"computer.writeFile"` \| `"computer.execute"` \| `"agent.rename"` \| `"agent.avatar"` \| `"agent.toolPolicy"` \| `"approvals"` \| `"apps.open"` \| `"apps.call"` \| `"llm.generation"` \| `"media.generation"` \| `"media.share"` \| `"games:servers"` \| `"git.repository"` \| `"app.storage"` \| `"app.events.emit"` \| `"team.workbenchHost"` \| `"marketplace.browse"` \| `"marketplace.purchase"` \| `"workflow.run"` \| `"workflow.publish"` \| `"workflow.arm"` \| `"world"` \| `"channels.read"` \| `"channels.personal.manage"`)[]; `hidden?`: `true`; `pending?`: `true`; `present?`: `Readonly`\<\{ `verb`: `string`; \}\>; \}\>, `"present"`\> & \{ input: I; output: O; present?: Readonly\<\{ verb: string; row: (call: Readonly\<\{ input: output\<I\>; output: output\<O\>; \}\>) =\> \{ readonly id: string; readonly title: string; ... 4 more ...; readonly media?: \{ ...; \} \| undefined; \}; rows: Readonly\<...\>; \}\> \| undefined; \} & (\{ ...; \} \| \{ ...; \}) |
|
|
234
234
|
|
|
235
235
|
#### Returns
|
|
236
236
|
|
package/docs/api/index.md
CHANGED
|
@@ -235,6 +235,18 @@ Create a new Agent with the given name and request id.
|
|
|
235
235
|
`"crt"`; `watercolor`: `"watercolor"`; \}\>; \}; `sessionOperations`: readonly
|
|
236
236
|
(`"agent.manage"` \| `"agent.read"` \| `"agent.send"`)[]; \}\>
|
|
237
237
|
|
|
238
|
+
##### computers()
|
|
239
|
+
|
|
240
|
+
```ts
|
|
241
|
+
computers(): Promise<readonly object[] | null>;
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
The Team Computers a new Agent may use; null when the host offers no choice.
|
|
245
|
+
|
|
246
|
+
###### Returns
|
|
247
|
+
|
|
248
|
+
`Promise`\<readonly `object`[] \| `null`\>
|
|
249
|
+
|
|
238
250
|
---
|
|
239
251
|
|
|
240
252
|
### AppAgentDirectoryHandle
|
|
@@ -1243,6 +1255,67 @@ and Computer-relative reference paths.
|
|
|
1243
1255
|
|
|
1244
1256
|
---
|
|
1245
1257
|
|
|
1258
|
+
### MediaShareStatus
|
|
1259
|
+
|
|
1260
|
+
```ts
|
|
1261
|
+
type MediaShareStatus = z.output<typeof mediaShareStatusSchema>;
|
|
1262
|
+
```
|
|
1263
|
+
|
|
1264
|
+
A Print's share state as the host reports it.
|
|
1265
|
+
|
|
1266
|
+
---
|
|
1267
|
+
|
|
1268
|
+
### MediaShareInput
|
|
1269
|
+
|
|
1270
|
+
```ts
|
|
1271
|
+
type MediaShareInput = z.output<typeof mediaShareInputSchema>;
|
|
1272
|
+
```
|
|
1273
|
+
|
|
1274
|
+
What to share and whether to show its prompt.
|
|
1275
|
+
|
|
1276
|
+
---
|
|
1277
|
+
|
|
1278
|
+
### MediaShareHandle
|
|
1279
|
+
|
|
1280
|
+
```ts
|
|
1281
|
+
type MediaShareHandle = Readonly<{
|
|
1282
|
+
status: Promise<
|
|
1283
|
+
| {
|
|
1284
|
+
shared: false;
|
|
1285
|
+
}
|
|
1286
|
+
| {
|
|
1287
|
+
shared: true;
|
|
1288
|
+
url: string;
|
|
1289
|
+
showPrompt: boolean;
|
|
1290
|
+
}
|
|
1291
|
+
>;
|
|
1292
|
+
share: Promise<
|
|
1293
|
+
| {
|
|
1294
|
+
shared: false;
|
|
1295
|
+
}
|
|
1296
|
+
| {
|
|
1297
|
+
shared: true;
|
|
1298
|
+
url: string;
|
|
1299
|
+
showPrompt: boolean;
|
|
1300
|
+
}
|
|
1301
|
+
>;
|
|
1302
|
+
stop: Promise<
|
|
1303
|
+
| {
|
|
1304
|
+
shared: false;
|
|
1305
|
+
}
|
|
1306
|
+
| {
|
|
1307
|
+
shared: true;
|
|
1308
|
+
url: string;
|
|
1309
|
+
showPrompt: boolean;
|
|
1310
|
+
}
|
|
1311
|
+
>;
|
|
1312
|
+
}>;
|
|
1313
|
+
```
|
|
1314
|
+
|
|
1315
|
+
Host handle behind the `media.share` capability.
|
|
1316
|
+
|
|
1317
|
+
---
|
|
1318
|
+
|
|
1246
1319
|
### Pending
|
|
1247
1320
|
|
|
1248
1321
|
```ts
|
|
@@ -2246,7 +2319,16 @@ Agent has an avatar: the one its owner chose, else Sprite's
|
|
|
2246
2319
|
const appAgentCreateInputSchema: Struct<{
|
|
2247
2320
|
name: String;
|
|
2248
2321
|
requestId: String;
|
|
2249
|
-
computer: optionalKey<
|
|
2322
|
+
computer: optionalKey<
|
|
2323
|
+
Union<
|
|
2324
|
+
readonly [
|
|
2325
|
+
Literals<readonly ["new", "none"]>,
|
|
2326
|
+
Struct<{
|
|
2327
|
+
computerId: String;
|
|
2328
|
+
}>,
|
|
2329
|
+
]
|
|
2330
|
+
>
|
|
2331
|
+
>;
|
|
2250
2332
|
avatar: optionalKey<
|
|
2251
2333
|
declare<
|
|
2252
2334
|
{
|
|
@@ -2309,7 +2391,7 @@ Capability to list the Agents visible to this App in read-only form.
|
|
|
2309
2391
|
|
|
2310
2392
|
```ts
|
|
2311
2393
|
const agentManage: CapabilityContract<
|
|
2312
|
-
Pick<AppAgentDirectoryHandle, "create" | "open">
|
|
2394
|
+
Pick<AppAgentDirectoryHandle, "create" | "computers" | "open">
|
|
2313
2395
|
>;
|
|
2314
2396
|
```
|
|
2315
2397
|
|
|
@@ -2808,6 +2890,60 @@ request access; openMediaGeneration uses it to obtain the host's handle.
|
|
|
2808
2890
|
|
|
2809
2891
|
---
|
|
2810
2892
|
|
|
2893
|
+
### mediaShareStatusSchema
|
|
2894
|
+
|
|
2895
|
+
```ts
|
|
2896
|
+
const mediaShareStatusSchema: ZodUnion<
|
|
2897
|
+
readonly [
|
|
2898
|
+
ZodObject<
|
|
2899
|
+
{
|
|
2900
|
+
shared: ZodLiteral<false>;
|
|
2901
|
+
},
|
|
2902
|
+
$strict
|
|
2903
|
+
>,
|
|
2904
|
+
ZodObject<
|
|
2905
|
+
{
|
|
2906
|
+
shared: ZodLiteral<true>;
|
|
2907
|
+
url: ZodURL;
|
|
2908
|
+
showPrompt: ZodBoolean;
|
|
2909
|
+
},
|
|
2910
|
+
$strict
|
|
2911
|
+
>,
|
|
2912
|
+
]
|
|
2913
|
+
>;
|
|
2914
|
+
```
|
|
2915
|
+
|
|
2916
|
+
Whether one generated Print has a public link, and what that link shows.
|
|
2917
|
+
|
|
2918
|
+
---
|
|
2919
|
+
|
|
2920
|
+
### mediaShareInputSchema
|
|
2921
|
+
|
|
2922
|
+
```ts
|
|
2923
|
+
const mediaShareInputSchema: ZodObject<
|
|
2924
|
+
{
|
|
2925
|
+
requestId: ZodString;
|
|
2926
|
+
showPrompt: ZodBoolean;
|
|
2927
|
+
},
|
|
2928
|
+
$strict
|
|
2929
|
+
>;
|
|
2930
|
+
```
|
|
2931
|
+
|
|
2932
|
+
Turn a public link on for one generated Print.
|
|
2933
|
+
|
|
2934
|
+
---
|
|
2935
|
+
|
|
2936
|
+
### mediaShare
|
|
2937
|
+
|
|
2938
|
+
```ts
|
|
2939
|
+
const mediaShare: CapabilityContract<MediaShareHandle>;
|
|
2940
|
+
```
|
|
2941
|
+
|
|
2942
|
+
Capability contract for public links to generated Media. Off by default per
|
|
2943
|
+
output; the host keeps the link, the bytes it serves and who may change it.
|
|
2944
|
+
|
|
2945
|
+
---
|
|
2946
|
+
|
|
2811
2947
|
### pendingSchema
|
|
2812
2948
|
|
|
2813
2949
|
```ts
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fungi.computer/agar",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0",
|
|
4
4
|
"author": "Levi <levi@technomancy.dev>",
|
|
5
5
|
"description": "App contract for fungi.computer: typed backend methods, host capabilities and the App frontend connection",
|
|
6
6
|
"type": "module",
|
|
@@ -168,7 +168,7 @@
|
|
|
168
168
|
}
|
|
169
169
|
},
|
|
170
170
|
"dependencies": {
|
|
171
|
-
"@fungi.computer/puffball": "0.
|
|
171
|
+
"@fungi.computer/puffball": "0.5.0",
|
|
172
172
|
"@fungi.computer/whistle": "0.3.0",
|
|
173
173
|
"@opentui/keymap": "0.5.10",
|
|
174
174
|
"@fungi.computer/capnweb": "0.12.0",
|