@fungi.computer/shiitake-extensions 0.1.1 → 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 +25 -18
- package/dist/goal/contract.d.ts +21 -8
- package/dist/goal/contract.js +14 -3
- package/dist/goal/host.d.ts +4 -1
- package/dist/goal/host.js +203 -106
- package/dist/goal/prompts.d.ts +73 -0
- package/dist/goal/prompts.js +98 -0
- package/dist/home/host.d.ts +5 -0
- package/dist/home/host.js +11 -4
- package/dist/internal/headline.d.ts +7 -0
- package/dist/internal/headline.js +18 -0
- package/dist/loop/client.js +1 -1
- package/dist/loop/contract.d.ts +6 -2
- package/dist/loop/contract.js +10 -1
- package/dist/loop/host.js +10 -12
- package/dist/loop/prompts.d.ts +56 -0
- package/dist/loop/prompts.js +54 -0
- package/dist/question/host.js +37 -2
- package/dist/roster/conversation-agents.d.ts +10 -14
- package/dist/roster/conversation-agents.js +128 -39
- package/dist/roster.d.ts +3 -0
- package/dist/roster.js +17 -1
- package/dist/skills/host.js +20 -2
- package/dist/subagents/host.d.ts +4 -2
- package/docs/api/goal/contract.md +5 -2
- package/docs/api/home/host.md +6 -5
- package/docs/api/loop/contract.md +5 -2
- package/package.json +5 -5
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { AgentCreateRefused, createAgentControlSource, } from "@fungi.computer/shiitake/agent-control";
|
|
2
|
+
import * as Effect from "effect/Effect";
|
|
2
3
|
import * as Schema from "effect/Schema";
|
|
3
|
-
import { botanicalAgentExtensions } from "../roster.js";
|
|
4
|
-
import { subagentsExtension, subagentsGrant, } from "../subagents/host.js";
|
|
4
|
+
import { botanicalAgentExtensions, botanicalExtensionsWithSubagents, } from "../roster.js";
|
|
5
5
|
/** Host-pack creation admission; attachments/model selection retain their own owners. */
|
|
6
6
|
export function assertOrdinaryAgentCreation(input) {
|
|
7
7
|
if (input.model !== undefined)
|
|
@@ -14,11 +14,24 @@ const conversationAgentRow = Schema.Struct({
|
|
|
14
14
|
agent_id: Schema.String,
|
|
15
15
|
session_id: Schema.NullOr(Schema.String),
|
|
16
16
|
});
|
|
17
|
+
const delegatedCommandRow = Schema.Struct({
|
|
18
|
+
parent_session_id: Schema.String,
|
|
19
|
+
agent_id: Schema.String,
|
|
20
|
+
session_id: Schema.String,
|
|
21
|
+
command_id: Schema.String,
|
|
22
|
+
at: Schema.Number,
|
|
23
|
+
});
|
|
24
|
+
/** Private safety ceilings for command-status polling; not a delegation policy. */
|
|
25
|
+
const maxWatchedCommands = 64;
|
|
26
|
+
const pollMs = 2_000;
|
|
27
|
+
const maxWatchMs = 30 * 60_000;
|
|
17
28
|
/**
|
|
18
29
|
* This host's own record of the Agents each conversation created or sent
|
|
19
30
|
* accepted work to, written as its Agent-control directory accepts them
|
|
20
|
-
* (Wiki: agent-runtime-tools-and-clients, read-only sub-agent view).
|
|
21
|
-
*
|
|
31
|
+
* (Wiki: agent-runtime-tools-and-clients, read-only sub-agent view). Accepted
|
|
32
|
+
* child command receipts are separately reconciled against their owner's
|
|
33
|
+
* settlement records for the parent's goal guard. Neither record grants
|
|
34
|
+
* authority over a child.
|
|
22
35
|
*/
|
|
23
36
|
export function createConversationAgents(storage) {
|
|
24
37
|
// Composing a host does no storage I/O; the first record or read prepares it.
|
|
@@ -27,6 +40,7 @@ export function createConversationAgents(storage) {
|
|
|
27
40
|
if (!prepared) {
|
|
28
41
|
storage.sql.exec("CREATE TABLE IF NOT EXISTS oyster_conversation_agents (parent_session_id TEXT NOT NULL, agent_id TEXT NOT NULL, session_id TEXT, at INTEGER NOT NULL, PRIMARY KEY (parent_session_id, agent_id)) STRICT");
|
|
29
42
|
storage.sql.exec("CREATE INDEX IF NOT EXISTS idx_oyster_conversation_agents_parent ON oyster_conversation_agents(parent_session_id, at)");
|
|
43
|
+
storage.sql.exec("CREATE TABLE IF NOT EXISTS oyster_delegated_commands (parent_session_id TEXT NOT NULL, agent_id TEXT NOT NULL, session_id TEXT NOT NULL, command_id TEXT NOT NULL PRIMARY KEY, at INTEGER NOT NULL) STRICT");
|
|
30
44
|
prepared = true;
|
|
31
45
|
}
|
|
32
46
|
return storage.sql;
|
|
@@ -35,9 +49,13 @@ export function createConversationAgents(storage) {
|
|
|
35
49
|
function created(parentSessionId, agentId) {
|
|
36
50
|
sql().exec("INSERT OR IGNORE INTO oyster_conversation_agents(parent_session_id, agent_id, session_id, at) VALUES (?, ?, NULL, ?)", parentSessionId, agentId, Date.now());
|
|
37
51
|
}
|
|
38
|
-
/** A send
|
|
39
|
-
function sent(parentSessionId, agentId, sessionId) {
|
|
40
|
-
sql().exec("INSERT INTO oyster_conversation_agents(parent_session_id, agent_id, session_id, at) VALUES (?, ?, ?, ?) ON CONFLICT(parent_session_id, agent_id) DO UPDATE SET session_id = excluded.session_id, at = excluded.at", parentSessionId, agentId, sessionId, Date.now());
|
|
52
|
+
/** A send may not know its Session until the recipient accepts it. */
|
|
53
|
+
function sent(parentSessionId, agentId, sessionId, commandId) {
|
|
54
|
+
sql().exec("INSERT INTO oyster_conversation_agents(parent_session_id, agent_id, session_id, at) VALUES (?, ?, ?, ?) ON CONFLICT(parent_session_id, agent_id) DO UPDATE SET session_id = excluded.session_id, at = excluded.at", parentSessionId, agentId, sessionId ?? null, Date.now());
|
|
55
|
+
if (sessionId !== undefined) {
|
|
56
|
+
sql().exec("INSERT OR REPLACE INTO oyster_delegated_commands(parent_session_id, agent_id, session_id, command_id, at) VALUES (?, ?, ?, ?, ?)", parentSessionId, agentId, sessionId, commandId, Date.now());
|
|
57
|
+
sql().exec("DELETE FROM oyster_delegated_commands WHERE command_id NOT IN (SELECT command_id FROM oyster_delegated_commands ORDER BY at DESC LIMIT ?)", maxWatchedCommands);
|
|
58
|
+
}
|
|
41
59
|
}
|
|
42
60
|
/** One conversation's directory: its accepted creates and sends are recorded. */
|
|
43
61
|
function recording(parentSessionId, directory) {
|
|
@@ -57,7 +75,8 @@ export function createConversationAgents(storage) {
|
|
|
57
75
|
...recorded,
|
|
58
76
|
send: async (task, sourceSessionId, signal, invocation) => {
|
|
59
77
|
const accepted = await send(task, sourceSessionId, signal, invocation);
|
|
60
|
-
|
|
78
|
+
if (accepted.status === "accepted")
|
|
79
|
+
sent(sourceSessionId, task.agentId, accepted.sessionId ?? task.sessionId, accepted.commandId);
|
|
61
80
|
return accepted;
|
|
62
81
|
},
|
|
63
82
|
};
|
|
@@ -75,40 +94,110 @@ export function createConversationAgents(storage) {
|
|
|
75
94
|
},
|
|
76
95
|
}),
|
|
77
96
|
/** The footer rows for one conversation; archived and unknown Agents leave it. */
|
|
78
|
-
source: (directory) =>
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
+
source: (directory) => {
|
|
98
|
+
const polling = new Set();
|
|
99
|
+
const signal = new AbortController().signal;
|
|
100
|
+
function poll(commandId) {
|
|
101
|
+
if (polling.has(commandId) || polling.size >= maxWatchedCommands)
|
|
102
|
+
return;
|
|
103
|
+
polling.add(commandId);
|
|
104
|
+
const check = async () => {
|
|
105
|
+
let raw;
|
|
106
|
+
try {
|
|
107
|
+
raw = sql()
|
|
108
|
+
.exec("SELECT parent_session_id, agent_id, session_id, command_id, at FROM oyster_delegated_commands WHERE command_id = ?", commandId)
|
|
109
|
+
.toArray()[0];
|
|
110
|
+
}
|
|
111
|
+
catch (cause) {
|
|
112
|
+
// The host's store was closed; no orphan poller may keep using it.
|
|
113
|
+
Effect.runFork(Effect.logError("subagents.command-store-read", cause));
|
|
114
|
+
polling.delete(commandId);
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
if (raw === undefined) {
|
|
118
|
+
polling.delete(commandId);
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
const row = Schema.decodeUnknownSync(delegatedCommandRow)(raw);
|
|
122
|
+
// An unobservable command cannot justify an indefinite live wait.
|
|
123
|
+
if (Date.now() - row.at >= maxWatchMs) {
|
|
124
|
+
sql().exec("DELETE FROM oyster_delegated_commands WHERE command_id = ?", commandId);
|
|
125
|
+
polling.delete(commandId);
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
try {
|
|
129
|
+
const opened = await directory.open(row.agent_id, signal);
|
|
130
|
+
let settled;
|
|
131
|
+
try {
|
|
132
|
+
settled = await opened.agent
|
|
133
|
+
.session(row.session_id)
|
|
134
|
+
.readSettlement(commandId, {
|
|
135
|
+
timeoutMs: 0,
|
|
136
|
+
signal,
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
finally {
|
|
140
|
+
await opened.release();
|
|
141
|
+
}
|
|
142
|
+
if (settled !== undefined) {
|
|
143
|
+
sql().exec("DELETE FROM oyster_delegated_commands WHERE command_id = ?", commandId);
|
|
144
|
+
polling.delete(commandId);
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
catch (cause) {
|
|
149
|
+
// An unreadable child is not proof of live work; do not hold the guard.
|
|
150
|
+
Effect.runFork(Effect.logError("subagents.command-status", cause));
|
|
151
|
+
try {
|
|
152
|
+
sql().exec("DELETE FROM oyster_delegated_commands WHERE command_id = ?", commandId);
|
|
153
|
+
}
|
|
154
|
+
catch (closed) {
|
|
155
|
+
// Host teardown closed storage while the remote read was pending.
|
|
156
|
+
Effect.runFork(Effect.logError("subagents.command-store-closed", closed));
|
|
157
|
+
}
|
|
158
|
+
polling.delete(commandId);
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
setTimeout(() => void check(), pollMs);
|
|
97
162
|
};
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
163
|
+
void check();
|
|
164
|
+
}
|
|
165
|
+
return {
|
|
166
|
+
// Polling is demand-driven: only a parent whose goal asks about its
|
|
167
|
+
// live children watches their receipts, including ones recorded
|
|
168
|
+
// before a restart. Composing a host or sending mail does no polling.
|
|
169
|
+
hasLiveChildCommand: (sessionId) => {
|
|
170
|
+
const live = sql()
|
|
171
|
+
.exec("SELECT command_id FROM oyster_delegated_commands WHERE parent_session_id = ? AND at > ? ORDER BY at DESC LIMIT ?", sessionId, Date.now() - maxWatchMs, maxWatchedCommands)
|
|
172
|
+
.toArray()
|
|
173
|
+
.map((row) => Schema.decodeUnknownSync(Schema.Struct({ command_id: Schema.String }))(row).command_id);
|
|
174
|
+
for (const commandId of live)
|
|
175
|
+
poll(commandId);
|
|
176
|
+
return live.length > 0;
|
|
177
|
+
},
|
|
178
|
+
read: async (sessionId, limit) => {
|
|
179
|
+
const rows = sql()
|
|
180
|
+
.exec("SELECT agent_id, session_id FROM oyster_conversation_agents WHERE parent_session_id = ? ORDER BY at DESC, agent_id", sessionId)
|
|
181
|
+
.toArray()
|
|
182
|
+
.map((row) => Schema.decodeUnknownSync(conversationAgentRow)(row));
|
|
183
|
+
const known = new Map((await directory.list(new AbortController().signal)).map((agent) => [agent.agentId, agent.name]));
|
|
184
|
+
const agents = rows.flatMap((row) => {
|
|
185
|
+
const name = known.get(row.agent_id);
|
|
186
|
+
return name === undefined
|
|
187
|
+
? []
|
|
188
|
+
: [{ agentId: row.agent_id, name, sessionId: row.session_id }];
|
|
189
|
+
});
|
|
190
|
+
return {
|
|
191
|
+
agents: agents.slice(0, limit),
|
|
192
|
+
more: Math.max(0, agents.length - limit),
|
|
193
|
+
};
|
|
194
|
+
},
|
|
195
|
+
open: directory.open,
|
|
196
|
+
};
|
|
197
|
+
},
|
|
101
198
|
};
|
|
102
199
|
}
|
|
103
200
|
/** Both hosts compose the ordinary roster and its read-only created-Agent footer. */
|
|
104
201
|
export function oysterAgentExtensions(source) {
|
|
105
|
-
return
|
|
106
|
-
/** Ordinary extensions plus the read-only created-Agent footer. */
|
|
107
|
-
roster: [
|
|
108
|
-
...botanicalAgentExtensions.roster,
|
|
109
|
-
subagentsExtension({ source }),
|
|
110
|
-
],
|
|
111
|
-
/** Host grants corresponding to the composed extension roster. */
|
|
112
|
-
grants: [...botanicalAgentExtensions.grants, subagentsGrant],
|
|
113
|
-
};
|
|
202
|
+
return botanicalExtensionsWithSubagents(botanicalAgentExtensions, source);
|
|
114
203
|
}
|
package/dist/roster.d.ts
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
import type { ExtensionRosterV0 } from "@fungi.computer/shiitake/extensions";
|
|
2
2
|
import type { SkillSource } from "./skills/source.js";
|
|
3
|
+
import { type SubagentSource } from "./subagents/host.js";
|
|
3
4
|
/**
|
|
4
5
|
* Botanical's product roster with explicit grants. Hub and Local pass this
|
|
5
6
|
* same value; a stranger host passes its own (or an empty) roster.
|
|
6
7
|
*/
|
|
7
8
|
export declare const botanicalAgentExtensions: ExtensionRosterV0;
|
|
9
|
+
/** Compose the goal and footer over one source; an absent goal is a wiring error. */
|
|
10
|
+
export declare function botanicalExtensionsWithSubagents(base: ExtensionRosterV0, source: SubagentSource): ExtensionRosterV0;
|
|
8
11
|
/** A host with a SkillSource grants read-only skill discovery for its own runs. */
|
|
9
12
|
export declare function botanicalExtensionsWithSkills(source: SkillSource): ExtensionRosterV0;
|
package/dist/roster.js
CHANGED
|
@@ -3,12 +3,13 @@ import { almanacExtension } from "./almanac/host.js";
|
|
|
3
3
|
import { questionContract } from "./question/contract.js";
|
|
4
4
|
import { questionExtension } from "./question/host.js";
|
|
5
5
|
import { goalContract } from "./goal/contract.js";
|
|
6
|
-
import { goalExtension } from "./goal/host.js";
|
|
6
|
+
import { goalExtension, goalExtensionFor } from "./goal/host.js";
|
|
7
7
|
import { loopContract } from "./loop/contract.js";
|
|
8
8
|
import { loopExtension } from "./loop/host.js";
|
|
9
9
|
import { planContract } from "./plan/contract.js";
|
|
10
10
|
import { planExtension } from "./plan/host.js";
|
|
11
11
|
import { skillsExtension, skillsGrant } from "./skills/host.js";
|
|
12
|
+
import { subagentsExtension, subagentsGrant, } from "./subagents/host.js";
|
|
12
13
|
/**
|
|
13
14
|
* Botanical's product roster with explicit grants. Hub and Local pass this
|
|
14
15
|
* same value; a stranger host passes its own (or an empty) roster.
|
|
@@ -42,6 +43,7 @@ export const botanicalAgentExtensions = Object.freeze({
|
|
|
42
43
|
"state",
|
|
43
44
|
"settled",
|
|
44
45
|
"send",
|
|
46
|
+
"timers",
|
|
45
47
|
"commands",
|
|
46
48
|
"projection",
|
|
47
49
|
"run_tools",
|
|
@@ -72,6 +74,20 @@ export const botanicalAgentExtensions = Object.freeze({
|
|
|
72
74
|
},
|
|
73
75
|
]),
|
|
74
76
|
});
|
|
77
|
+
/** Compose the goal and footer over one source; an absent goal is a wiring error. */
|
|
78
|
+
export function botanicalExtensionsWithSubagents(base, source) {
|
|
79
|
+
if (!base.roster.some((extension) => extension.manifest.id === goalContract.id))
|
|
80
|
+
throw new Error("Cannot attach sub-agents without the goal extension");
|
|
81
|
+
return {
|
|
82
|
+
roster: [
|
|
83
|
+
...base.roster.map((extension) => extension.manifest.id === goalContract.id
|
|
84
|
+
? goalExtensionFor(source)
|
|
85
|
+
: extension),
|
|
86
|
+
subagentsExtension({ source }),
|
|
87
|
+
],
|
|
88
|
+
grants: [...base.grants, subagentsGrant],
|
|
89
|
+
};
|
|
90
|
+
}
|
|
75
91
|
/** A host with a SkillSource grants read-only skill discovery for its own runs. */
|
|
76
92
|
export function botanicalExtensionsWithSkills(source) {
|
|
77
93
|
return {
|
package/dist/skills/host.js
CHANGED
|
@@ -130,11 +130,29 @@ function skillsStep(found, name) {
|
|
|
130
130
|
});
|
|
131
131
|
return ask({
|
|
132
132
|
type: "choice",
|
|
133
|
-
message:
|
|
133
|
+
message: `Skills (${String(found.skills.length)})`,
|
|
134
|
+
summary: reasons.length === 0
|
|
135
|
+
? undefined
|
|
136
|
+
: `${String(reasons.length)} ${reasons.length === 1 ? "skill was" : "skills were"} not loaded. Details shows why.`,
|
|
137
|
+
details: [
|
|
138
|
+
...reasons
|
|
139
|
+
.slice(0, config.maximumListedDiagnostics)
|
|
140
|
+
.map((diagnostic) => ({
|
|
141
|
+
label: diagnostic.reason,
|
|
142
|
+
value: `${diagnostic.message} (${diagnostic.path})`,
|
|
143
|
+
})),
|
|
144
|
+
...found.skills.map((skill) => ({
|
|
145
|
+
label: skill.name,
|
|
146
|
+
value: skill.location,
|
|
147
|
+
})),
|
|
148
|
+
].slice(0, 24),
|
|
134
149
|
options: found.skills.map((skill) => ({
|
|
135
150
|
value: skill.name,
|
|
136
151
|
label: skill.name,
|
|
137
|
-
description: skill.
|
|
152
|
+
description: skill.description
|
|
153
|
+
.replace(/\s+/gu, " ")
|
|
154
|
+
.trim()
|
|
155
|
+
.slice(0, 100),
|
|
138
156
|
})),
|
|
139
157
|
}, {}, "name");
|
|
140
158
|
}
|
package/dist/subagents/host.d.ts
CHANGED
|
@@ -9,12 +9,12 @@ export type SubagentRecord = Readonly<{
|
|
|
9
9
|
/** A host-selected conversation; null asks the view to read its latest one. */
|
|
10
10
|
sessionId: string | null;
|
|
11
11
|
}>;
|
|
12
|
-
/**
|
|
12
|
+
/** Owner reads used for status and exact delegated command settlement. */
|
|
13
13
|
export type SubagentAgent = Readonly<{
|
|
14
14
|
/** Read the child's owner-ordered conversation summaries. */
|
|
15
15
|
listSessions: ShiitakeAgent["listSessions"];
|
|
16
16
|
/** Open the read-only view of a selected child conversation. */
|
|
17
|
-
session: (sessionId: string) => Pick<ShiitakeSession, "read">;
|
|
17
|
+
session: (sessionId: string) => Pick<ShiitakeSession, "read" | "readSettlement">;
|
|
18
18
|
}>;
|
|
19
19
|
/**
|
|
20
20
|
* The host's read-only facts. `read` returns ordinary created Agents,
|
|
@@ -23,6 +23,8 @@ export type SubagentAgent = Readonly<{
|
|
|
23
23
|
* `open` fits), and releasing it never stops the Agent's work.
|
|
24
24
|
*/
|
|
25
25
|
export type SubagentSource = Readonly<{
|
|
26
|
+
/** A recorded accepted child command is still pending or running. Synchronous for settlement. */
|
|
27
|
+
hasLiveChildCommand: (sessionId: string) => boolean;
|
|
26
28
|
/** Read a bounded list of this conversation's created Agents. */
|
|
27
29
|
read: (sessionId: string, limit: number) => Promise<Readonly<{
|
|
28
30
|
/** Created Agents included in this page. */
|
|
@@ -152,7 +152,10 @@ const GoalCommandInput: Union<
|
|
|
152
152
|
confirmed: optional<Boolean>;
|
|
153
153
|
}>,
|
|
154
154
|
Struct<{
|
|
155
|
-
action: Literals<
|
|
155
|
+
action: Literals<
|
|
156
|
+
readonly ["pause", "resume", "replace", "clear", "clear-ask"]
|
|
157
|
+
>;
|
|
158
|
+
confirmed: optional<Boolean>;
|
|
156
159
|
}>,
|
|
157
160
|
Struct<{}>,
|
|
158
161
|
]
|
|
@@ -225,7 +228,7 @@ Session-owned goal controls and their visible projection.
|
|
|
225
228
|
| <a id="property-commands"></a> `commands` | `object` | - | Goal commands admitted by the Session owner. |
|
|
226
229
|
| `commands.goal` | `object` | - | Open or answer the human goal controls. |
|
|
227
230
|
| `commands.goal.scope` | `"session"` | `"session"` | The Session owns this goal. |
|
|
228
|
-
| `commands.goal.input` | `Union`\<readonly \[`Struct`\<\{ `action`: `Literal`\<`"set"`\>; `objective`: `String`; `requestId`: `String`; `expectedRevision`: `optional`\<`NullOr`\<`String`\>\>; `confirmed`: `optional`\<`Boolean`\>; \}\>, `Struct`\<\{ `action`: `Literals`\<readonly \[`"pause"`, `"resume"`, `"replace"`, `"clear"`\]\>; \}\>, `Struct`\<\{ \}\>\]\>
|
|
231
|
+
| `commands.goal.input` | `Union`\<readonly \[`Struct`\<\{ `action`: `Literal`\<`"set"`\>; `objective`: `String`; `requestId`: `String`; `expectedRevision`: `optional`\<`NullOr`\<`String`\>\>; `confirmed`: `optional`\<`Boolean`\>; \}\>, `Struct`\<\{ `action`: `Literals`\<readonly \[`"pause"`, `"resume"`, `"replace"`, `"clear"`, `"clear-ask"`\]\>; `confirmed`: `optional`\<`Boolean`\>; \}\>, `Struct`\<\{ \}\>\]\> | `GoalCommandInput` | Decode the control action. |
|
|
229
232
|
| `commands.goal.output` | `declare`\<`WhistleCatalogStepV1`, `WhistleCatalogStepV1`\> | `CatalogStep` | Return the server-owned conversation step. |
|
|
230
233
|
| `commands.pause` | `object` | - | Pause work on the current goal. |
|
|
231
234
|
| `commands.pause.scope` | `"session"` | `"session"` | The Session owns this goal. |
|
package/docs/api/home/host.md
CHANGED
|
@@ -44,11 +44,12 @@ Agent-scope choice with per-run tools and prompt over one captured table.
|
|
|
44
44
|
|
|
45
45
|
#### Parameters
|
|
46
46
|
|
|
47
|
-
| Parameter
|
|
48
|
-
|
|
|
49
|
-
| `options`
|
|
50
|
-
| `options.computers`
|
|
51
|
-
| `options.computers.read`
|
|
47
|
+
| Parameter | Type | Description |
|
|
48
|
+
| ---------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------- |
|
|
49
|
+
| `options` | \{ `computers`: \{ `read`: (`context`) => readonly `Readonly`\<\{ `name`: `string`; `attachmentId`: `string`; `port`: `FilesPort`; \}\>[]; `prepare?`: (`context`) => `Promise`\<`void`\>; \}; \} | - |
|
|
50
|
+
| `options.computers` | \{ `read`: (`context`) => readonly `Readonly`\<\{ `name`: `string`; `attachmentId`: `string`; `port`: `FilesPort`; \}\>[]; `prepare?`: (`context`) => `Promise`\<`void`\>; \} | - |
|
|
51
|
+
| `options.computers.read` | (`context`) => readonly `Readonly`\<\{ `name`: `string`; `attachmentId`: `string`; `port`: `FilesPort`; \}\>[] | Read the table inside the synchronous Home choice transaction. |
|
|
52
|
+
| `options.computers.prepare?` | (`context`) => `Promise`\<`void`\> | Optional host preparation before run-scoped Files capture. |
|
|
52
53
|
|
|
53
54
|
#### Returns
|
|
54
55
|
|
|
@@ -74,7 +74,10 @@ const LoopCommandInput: Union<
|
|
|
74
74
|
requestId: String;
|
|
75
75
|
}>,
|
|
76
76
|
Struct<{
|
|
77
|
-
action: Literals<
|
|
77
|
+
action: Literals<
|
|
78
|
+
readonly ["status", "pause", "resume", "stop", "stop-ask", "new"]
|
|
79
|
+
>;
|
|
80
|
+
confirmed: optional<Boolean>;
|
|
78
81
|
}>,
|
|
79
82
|
Struct<{}>,
|
|
80
83
|
]
|
|
@@ -135,7 +138,7 @@ Session-owned loop controls and their visible state.
|
|
|
135
138
|
| <a id="property-commands"></a> `commands` | `object` | - | Loop operations admitted by the Session owner. |
|
|
136
139
|
| `commands.loop` | `object` | - | Open or answer the human loop controls. |
|
|
137
140
|
| `commands.loop.scope` | `"session"` | `"session"` | The Session owns this loop. |
|
|
138
|
-
| `commands.loop.input` | `Union`\<readonly \[`Struct`\<\{ `action`: `Literal`\<`"start"`\>; `text`: `String`; `requestId`: `String`; \}\>, `Struct`\<\{ `action`: `Literals`\<readonly \[`"status"`, `"pause"`, `"resume"`, `"stop"`, `"new"`\]\>; \}\>, `Struct`\<\{ \}\>\]\>
|
|
141
|
+
| `commands.loop.input` | `Union`\<readonly \[`Struct`\<\{ `action`: `Literal`\<`"start"`\>; `text`: `String`; `requestId`: `String`; \}\>, `Struct`\<\{ `action`: `Literals`\<readonly \[`"status"`, `"pause"`, `"resume"`, `"stop"`, `"stop-ask"`, `"new"`\]\>; `confirmed`: `optional`\<`Boolean`\>; \}\>, `Struct`\<\{ \}\>\]\> | `LoopCommandInput` | Decode the selected human action. |
|
|
139
142
|
| `commands.loop.output` | `declare`\<`WhistleCatalogStepV1`, `WhistleCatalogStepV1`\> | `CatalogStep` | Return the server-owned conversation step. |
|
|
140
143
|
| `commands.startSelfPaced` | `object` | - | Start a loop whose next occurrence is chosen by the model. |
|
|
141
144
|
| `commands.startSelfPaced.scope` | `"session"` | `"session"` | The Session owns this loop. |
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fungi.computer/shiitake-extensions",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"author": "Levi <levi@technomancy.dev>",
|
|
5
5
|
"private": false,
|
|
6
6
|
"description": "Botanical's product Shiitake extensions: goal, loop and Almanac on the generic extension surface",
|
|
@@ -108,11 +108,11 @@
|
|
|
108
108
|
"dependencies": {
|
|
109
109
|
"@fungi.computer/almanac": "0.2.0",
|
|
110
110
|
"@fungi.computer/cairn": "0.1.0",
|
|
111
|
-
"@fungi.computer/knapsack": "0.
|
|
112
|
-
"@fungi.computer/mycelium": "0.2.
|
|
113
|
-
"@fungi.computer/shiitake": "0.
|
|
111
|
+
"@fungi.computer/knapsack": "0.3.1",
|
|
112
|
+
"@fungi.computer/mycelium": "0.2.2",
|
|
113
|
+
"@fungi.computer/shiitake": "0.5.0",
|
|
114
114
|
"@fungi.computer/watchdog": "0.1.0",
|
|
115
|
-
"@fungi.computer/whistle": "0.
|
|
115
|
+
"@fungi.computer/whistle": "0.2.0",
|
|
116
116
|
"effect": "4.0.2",
|
|
117
117
|
"papaparse": "5.7.0",
|
|
118
118
|
"zod": "4.4.3",
|