@fungi.computer/shiitake-extensions 0.0.2 → 0.1.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/README.md +43 -13
- package/dist/almanac/contract.d.ts +94 -0
- package/dist/almanac/contract.js +71 -5
- package/dist/goal/client.d.ts +5 -2
- package/dist/goal/client.js +66 -72
- package/dist/goal/contract.d.ts +181 -64
- package/dist/goal/contract.js +102 -12
- package/dist/goal/host.js +206 -124
- package/dist/home/contract.d.ts +18 -0
- package/dist/home/contract.js +24 -3
- package/dist/home/host.d.ts +3 -0
- package/dist/home/host.js +1 -2
- package/dist/home/routing.js +13 -24
- package/dist/internal/history.d.ts +16 -0
- package/dist/internal/history.js +8 -0
- package/dist/loop/client.d.ts +1 -1
- package/dist/loop/client.js +28 -34
- package/dist/loop/contract.d.ts +129 -84
- package/dist/loop/contract.js +79 -9
- package/dist/loop/host.d.ts +1 -0
- package/dist/loop/host.js +89 -48
- package/dist/plan/client.d.ts +1 -1
- package/dist/plan/contract.d.ts +33 -0
- package/dist/plan/contract.js +28 -3
- package/dist/plan/host.js +12 -7
- package/dist/question/client.d.ts +1 -1
- package/dist/question/contract.d.ts +158 -0
- package/dist/question/contract.js +92 -7
- package/dist/question/host.js +34 -20
- package/dist/roster/conversation-agents.d.ts +31 -0
- package/dist/roster/conversation-agents.js +114 -0
- package/dist/roster.js +1 -0
- package/dist/skills/host.d.ts +1 -0
- package/dist/skills/host.js +22 -17
- package/dist/skills/source.d.ts +34 -0
- package/dist/subagents/client.d.ts +1 -1
- package/dist/subagents/client.js +43 -12
- package/dist/subagents/contract.d.ts +46 -8
- package/dist/subagents/contract.js +38 -8
- package/dist/subagents/host.d.ts +20 -8
- package/dist/subagents/host.js +58 -12
- package/docs/api/README.md +35 -0
- package/docs/api/almanac/contract.md +90 -0
- package/docs/api/almanac/host.md +19 -0
- package/docs/api/goal/client.md +26 -0
- package/docs/api/goal/contract.md +247 -0
- package/docs/api/goal/host.md +29 -0
- package/docs/api/home/contract.md +58 -0
- package/docs/api/home/host.md +55 -0
- package/docs/api/loop/client.md +25 -0
- package/docs/api/loop/contract.md +161 -0
- package/docs/api/loop/host.md +30 -0
- package/docs/api/plan/client.md +26 -0
- package/docs/api/plan/contract.md +163 -0
- package/docs/api/plan/host.md +19 -0
- package/docs/api/question/client.md +25 -0
- package/docs/api/question/contract.md +377 -0
- package/docs/api/question/host.md +19 -0
- package/docs/api/roster/conversation-agents.md +80 -0
- package/docs/api/roster.md +40 -0
- package/docs/api/skills/host.md +39 -0
- package/docs/api/skills/source.md +104 -0
- package/docs/api/subagents/client.md +26 -0
- package/docs/api/subagents/contract.md +131 -0
- package/docs/api/subagents/host.md +115 -0
- package/package.json +14 -8
package/dist/home/contract.js
CHANGED
|
@@ -4,22 +4,43 @@ import { CatalogStep } from "../internal/catalog.js";
|
|
|
4
4
|
const attachmentId = Schema.String.pipe(Schema.check(Schema.isMinLength(1)));
|
|
5
5
|
/** The Agent's recorded choice survives the chosen attachment being detached. */
|
|
6
6
|
export const Home = Schema.Struct({
|
|
7
|
+
/** Chosen Computer attachment, or null when no Home is selected. */
|
|
7
8
|
attachmentId: Schema.NullOr(attachmentId),
|
|
8
9
|
});
|
|
9
10
|
/** Human selection changes Agent state; no model operation exposes this command. */
|
|
10
11
|
export const homeContract = {
|
|
12
|
+
/** Stable extension identity. */
|
|
11
13
|
id: ExtensionId.make("botanical-home"),
|
|
14
|
+
/** Human selection and initial seeding operations. */
|
|
12
15
|
commands: {
|
|
16
|
+
/** Open Home controls or select an attachment by name. */
|
|
13
17
|
home: {
|
|
18
|
+
/** Human controls are opened from a Session. */
|
|
14
19
|
scope: "session",
|
|
15
|
-
|
|
20
|
+
/** Decode an optional attachment name. */
|
|
21
|
+
input: Schema.Struct({
|
|
22
|
+
/** Attachment name selected by the person. */
|
|
23
|
+
name: Schema.optionalKey(Schema.String),
|
|
24
|
+
}),
|
|
25
|
+
/** Return the server-owned conversation step. */
|
|
16
26
|
output: CatalogStep,
|
|
17
27
|
},
|
|
28
|
+
/** Seed the Agent's initial recorded Home choice. */
|
|
18
29
|
seed: {
|
|
30
|
+
/** Home selection belongs to the Agent. */
|
|
19
31
|
scope: "agent",
|
|
32
|
+
/** Decode the initial selection. */
|
|
20
33
|
input: Home,
|
|
21
|
-
|
|
34
|
+
/** Report whether seeding changed the recorded choice. */
|
|
35
|
+
output: Schema.Struct({
|
|
36
|
+
/** Whether the initial choice was seeded. */
|
|
37
|
+
seeded: Schema.Boolean,
|
|
38
|
+
}),
|
|
22
39
|
},
|
|
23
40
|
},
|
|
24
|
-
|
|
41
|
+
/** Recorded selection visible to clients, or no seeded state. */
|
|
42
|
+
projection: {
|
|
43
|
+
/** Decoder for the optional Home state. */
|
|
44
|
+
schema: Schema.NullOr(Home),
|
|
45
|
+
},
|
|
25
46
|
};
|
package/dist/home/host.d.ts
CHANGED
|
@@ -2,8 +2,11 @@ import { type FilesPort } from "@fungi.computer/knapsack";
|
|
|
2
2
|
import { type ExtensionGrantV0, type RosteredExtensionV0 } from "@fungi.computer/shiitake/extensions";
|
|
3
3
|
/** Already-scoped authority supplied by the host, never constructed by Home. */
|
|
4
4
|
export type HomeComputer = Readonly<{
|
|
5
|
+
/** Attachment name offered to the person choosing Home. */
|
|
5
6
|
name: string;
|
|
7
|
+
/** Stable identity stored by the Home selection. */
|
|
6
8
|
attachmentId: string;
|
|
9
|
+
/** Already-scoped Files authority captured for this attachment. */
|
|
7
10
|
port: FilesPort;
|
|
8
11
|
}>;
|
|
9
12
|
/** Hosts admit Home explicitly; no other extension receives the Files slot. */
|
package/dist/home/host.js
CHANGED
|
@@ -13,7 +13,7 @@ export const homeGrant = {
|
|
|
13
13
|
};
|
|
14
14
|
const config = {
|
|
15
15
|
promptLimit: 4_000,
|
|
16
|
-
guide: "Home supplies read, list, glob and grep over your default Computer. Bare paths and computer://home/ use Home; computer://<name>/ uses that captured attachment. apply_patch, when offered,
|
|
16
|
+
guide: "Home supplies read, list, glob and grep over your default Computer. Bare paths and computer://home/ use Home; computer://<name>/ uses that captured attachment. apply_patch, when offered, also works on Home. Only a person changes Home with /home <name>; ask them when no Home is available.",
|
|
17
17
|
};
|
|
18
18
|
const collections = {
|
|
19
19
|
choice: defineCollection(Home, { key: () => "default" }),
|
|
@@ -79,7 +79,6 @@ export function homeExtension(options) {
|
|
|
79
79
|
return null;
|
|
80
80
|
return Knapsack.files({
|
|
81
81
|
port: homeFilesRouting(new Map(computers.map(({ name, port }) => [name, port])), selected.port),
|
|
82
|
-
pathInstructions: "Bare paths and computer://home/ select Home. computer://<name>/ selects another captured attachment. apply_patch uses Home only.",
|
|
83
82
|
}).tools;
|
|
84
83
|
},
|
|
85
84
|
prompt: (_ctx, run) => [
|
package/dist/home/routing.js
CHANGED
|
@@ -36,36 +36,15 @@ export function homeFilesRouting(connections, home) {
|
|
|
36
36
|
},
|
|
37
37
|
list: async (input, context) => {
|
|
38
38
|
const { port, path, locate } = resolve(input.path);
|
|
39
|
-
|
|
40
|
-
return {
|
|
41
|
-
...result,
|
|
42
|
-
path: input.path,
|
|
43
|
-
entries: result.entries.map((entry) => ({
|
|
44
|
-
...entry,
|
|
45
|
-
path: locate(entry.path),
|
|
46
|
-
})),
|
|
47
|
-
};
|
|
39
|
+
return locateSearch(await port.list({ ...input, path }, context), input.path, locate);
|
|
48
40
|
},
|
|
49
41
|
glob: async (input, context) => {
|
|
50
42
|
const { port, path, locate } = resolve(input.path);
|
|
51
|
-
|
|
52
|
-
return {
|
|
53
|
-
...result,
|
|
54
|
-
path: input.path,
|
|
55
|
-
matches: result.matches.map(locate),
|
|
56
|
-
};
|
|
43
|
+
return locateSearch(await port.glob({ ...input, path }, context), input.path, locate);
|
|
57
44
|
},
|
|
58
45
|
grep: async (input, context) => {
|
|
59
46
|
const { port, path, locate } = resolve(input.path);
|
|
60
|
-
|
|
61
|
-
return {
|
|
62
|
-
...result,
|
|
63
|
-
path: input.path,
|
|
64
|
-
matches: result.matches.map((match) => ({
|
|
65
|
-
...match,
|
|
66
|
-
path: locate(match.path),
|
|
67
|
-
})),
|
|
68
|
-
};
|
|
47
|
+
return locateSearch(await port.grep({ ...input, path }, context), input.path, locate);
|
|
69
48
|
},
|
|
70
49
|
replace: async (input, context) => {
|
|
71
50
|
const { port, path } = resolve(input.path);
|
|
@@ -78,3 +57,13 @@ export function homeFilesRouting(connections, home) {
|
|
|
78
57
|
const patch = home.patch?.bind(home);
|
|
79
58
|
return patch === undefined ? routing : { ...routing, patch };
|
|
80
59
|
}
|
|
60
|
+
function locateSearch(result, path, locate) {
|
|
61
|
+
return {
|
|
62
|
+
...result,
|
|
63
|
+
path,
|
|
64
|
+
results: result.results.map((found) => ({
|
|
65
|
+
...found,
|
|
66
|
+
path: locate(found.path),
|
|
67
|
+
})),
|
|
68
|
+
};
|
|
69
|
+
}
|
|
@@ -1,25 +1,41 @@
|
|
|
1
1
|
import * as Schema from "effect/Schema";
|
|
2
2
|
/** Producer state: committed event identity survives reconnection and trimming. */
|
|
3
3
|
export declare function historySchema<E, EI>(event: Schema.Codec<E, EI>): Schema.Struct<{
|
|
4
|
+
/** Sequence to assign to the next committed event. */
|
|
4
5
|
readonly nextSequence: Schema.Int;
|
|
6
|
+
/** Number of older events removed by retention. */
|
|
5
7
|
readonly omitted: Schema.Int;
|
|
8
|
+
/** Retained committed events in sequence order. */
|
|
6
9
|
readonly events: Schema.$Array<Schema.Struct<{
|
|
10
|
+
/** Stable event identity within this producer's history. */
|
|
7
11
|
readonly id: Schema.String;
|
|
12
|
+
/** Producer-assigned event order. */
|
|
8
13
|
readonly sequence: Schema.Int;
|
|
14
|
+
/** Event timestamp supplied by the owner. */
|
|
9
15
|
readonly at: Schema.Int;
|
|
16
|
+
/** Associated accepted command, or null when none applies. */
|
|
10
17
|
readonly commandId: Schema.NullOr<Schema.String>;
|
|
18
|
+
/** Extension-specific event payload. */
|
|
11
19
|
readonly event: Schema.Codec<E, EI, never, never>;
|
|
12
20
|
}>>;
|
|
13
21
|
}>;
|
|
14
22
|
/** The extension's own persisted history, not a core cursor. */
|
|
15
23
|
export type History<E> = Readonly<{
|
|
24
|
+
/** Sequence to assign to the next committed event. */
|
|
16
25
|
nextSequence: number;
|
|
26
|
+
/** Number of older events removed by retention. */
|
|
17
27
|
omitted: number;
|
|
28
|
+
/** Retained committed events in sequence order. */
|
|
18
29
|
events: readonly Readonly<{
|
|
30
|
+
/** Stable event identity within this producer's history. */
|
|
19
31
|
id: string;
|
|
32
|
+
/** Producer-assigned event order. */
|
|
20
33
|
sequence: number;
|
|
34
|
+
/** Event timestamp supplied by the owner. */
|
|
21
35
|
at: number;
|
|
36
|
+
/** Associated accepted command, or null when none applies. */
|
|
22
37
|
commandId: string | null;
|
|
38
|
+
/** Extension-specific event payload. */
|
|
23
39
|
event: E;
|
|
24
40
|
}>[];
|
|
25
41
|
}>;
|
package/dist/internal/history.js
CHANGED
|
@@ -2,13 +2,21 @@ import * as Schema from "effect/Schema";
|
|
|
2
2
|
/** Producer state: committed event identity survives reconnection and trimming. */
|
|
3
3
|
export function historySchema(event) {
|
|
4
4
|
return Schema.Struct({
|
|
5
|
+
/** Sequence to assign to the next committed event. */
|
|
5
6
|
nextSequence: Schema.Int.check(Schema.isGreaterThan(0)),
|
|
7
|
+
/** Number of older events removed by retention. */
|
|
6
8
|
omitted: Schema.Int.check(Schema.isGreaterThanOrEqualTo(0)),
|
|
9
|
+
/** Retained committed events in sequence order. */
|
|
7
10
|
events: Schema.Array(Schema.Struct({
|
|
11
|
+
/** Stable event identity within this producer's history. */
|
|
8
12
|
id: Schema.String,
|
|
13
|
+
/** Producer-assigned event order. */
|
|
9
14
|
sequence: Schema.Int,
|
|
15
|
+
/** Event timestamp supplied by the owner. */
|
|
10
16
|
at: Schema.Int,
|
|
17
|
+
/** Associated accepted command, or null when none applies. */
|
|
11
18
|
commandId: Schema.NullOr(Schema.String),
|
|
19
|
+
/** Extension-specific event payload. */
|
|
12
20
|
event,
|
|
13
21
|
})),
|
|
14
22
|
});
|
package/dist/loop/client.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ import { type ClientContributionV1 } from "@fungi.computer/shiitake/client-entry
|
|
|
3
3
|
declare const _default: Readonly<{
|
|
4
4
|
protocol: "shiitake.client/v1";
|
|
5
5
|
id: import("@fungi.computer/shiitake/extensions").ExtensionId;
|
|
6
|
-
|
|
6
|
+
promptPresentation?: "footer";
|
|
7
7
|
attach?: (context: import("@fungi.computer/shiitake/client-entry").ClientExtensionContextV1) => import("effect/Effect").Effect<void, Error, import("effect/Scope").Scope>;
|
|
8
8
|
contribute?: (slot: import("@fungi.computer/shiitake").ExtensionSlotV0 | undefined) => ClientContributionV1;
|
|
9
9
|
}>;
|
package/dist/loop/client.js
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
import { defineClientEntry, } from "@fungi.computer/shiitake/client-entry";
|
|
2
2
|
import { loopContract } from "./contract.js";
|
|
3
|
+
/** One footer line: the full prompt stays in the row's detail. */
|
|
4
|
+
const summary = (text) => {
|
|
5
|
+
const line = text.replace(/\s+/gu, " ").trim();
|
|
6
|
+
return line.length <= 60 ? line : `${line.slice(0, 59)}…`;
|
|
7
|
+
};
|
|
3
8
|
const tone = (loop) => loop.state === "failed"
|
|
4
9
|
? "error"
|
|
5
10
|
: loop.state === "active"
|
|
@@ -17,6 +22,7 @@ const due = (at) => new Intl.DateTimeFormat(undefined, {
|
|
|
17
22
|
}).format(at);
|
|
18
23
|
/** Loop supplies its own absolute due copy and advertised stop intent. */
|
|
19
24
|
export default defineClientEntry(loopContract, {
|
|
25
|
+
promptPresentation: "footer",
|
|
20
26
|
contribute: (view) => {
|
|
21
27
|
if (view.status !== "running" || view.value === null)
|
|
22
28
|
return {
|
|
@@ -25,10 +31,10 @@ export default defineClientEntry(loopContract, {
|
|
|
25
31
|
timeline: { cells: [], omitted: 0 },
|
|
26
32
|
waiting: null,
|
|
27
33
|
};
|
|
28
|
-
const { loop
|
|
29
|
-
const waiting = loop
|
|
34
|
+
const { loop } = view.value;
|
|
35
|
+
const waiting = loop.state === "active" && loop.nextDueAt !== null;
|
|
30
36
|
return {
|
|
31
|
-
chips: loop
|
|
37
|
+
chips: loop.state !== "active" && loop.state !== "paused"
|
|
32
38
|
? []
|
|
33
39
|
: [
|
|
34
40
|
{
|
|
@@ -41,39 +47,27 @@ export default defineClientEntry(loopContract, {
|
|
|
41
47
|
},
|
|
42
48
|
},
|
|
43
49
|
],
|
|
44
|
-
panel:
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
{
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
id: "error",
|
|
58
|
-
title: loop.lastError.slice(0, 4096),
|
|
59
|
-
tone: "error",
|
|
60
|
-
},
|
|
61
|
-
]),
|
|
62
|
-
],
|
|
63
|
-
timeline: {
|
|
64
|
-
omitted: history.omitted,
|
|
65
|
-
cells: history.events.map(({ event, ...cell }) => ({
|
|
66
|
-
...cell,
|
|
67
|
-
rows: [
|
|
50
|
+
panel: [
|
|
51
|
+
{
|
|
52
|
+
id: "loop",
|
|
53
|
+
title: `Loop · ${loop.state} · ${loop.mode === "self_paced" ? "self-paced" : `${loop.cron?.expression ?? "fixed"} ${loop.cron?.timeZone ?? ""}`}${loop.nextDueAt === null ? "" : ` · Next ${due(loop.nextDueAt)}`} · ${summary(loop.prompt)}`,
|
|
54
|
+
detail: [loop.reason, loop.prompt]
|
|
55
|
+
.filter((part) => part !== null)
|
|
56
|
+
.join("\n")
|
|
57
|
+
.slice(0, 1024),
|
|
58
|
+
tone: tone(loop),
|
|
59
|
+
},
|
|
60
|
+
...(loop.lastError === null
|
|
61
|
+
? []
|
|
62
|
+
: [
|
|
68
63
|
{
|
|
69
|
-
id: "
|
|
70
|
-
title:
|
|
71
|
-
|
|
72
|
-
tone: tone(event),
|
|
64
|
+
id: "error",
|
|
65
|
+
title: loop.lastError.slice(0, 4096),
|
|
66
|
+
tone: "error",
|
|
73
67
|
},
|
|
74
|
-
],
|
|
75
|
-
|
|
76
|
-
},
|
|
68
|
+
]),
|
|
69
|
+
],
|
|
70
|
+
timeline: { cells: [], omitted: 0 },
|
|
77
71
|
waiting: waiting
|
|
78
72
|
? {
|
|
79
73
|
summary: `Waiting until ${due(loop.nextDueAt)}`,
|