@ai-ecoverse/slicc-agent 5.0.2 → 5.1.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 +15 -1
- package/dist/approvals/index.js +172 -0
- package/dist/approvals/index.js.map +7 -0
- package/dist/approvals/record.js +89 -0
- package/dist/approvals/record.js.map +7 -0
- package/dist/client.js +2 -0
- package/dist/client.js.map +2 -2
- package/dist/control.js +14 -3
- package/dist/control.js.map +2 -2
- package/dist/host.js +18 -3
- package/dist/host.js.map +2 -2
- package/dist/index.js +10 -0
- package/dist/index.js.map +2 -2
- package/dist/services.js +4 -2
- package/dist/services.js.map +2 -2
- package/dist/spectrum/approvals-port.js +135 -0
- package/dist/spectrum/approvals-port.js.map +7 -0
- package/dist/spectrum/index.js +10 -0
- package/dist/spectrum/index.js.map +3 -3
- package/dist/types/approvals/index.d.ts +28 -0
- package/dist/types/approvals/record.d.ts +108 -0
- package/dist/types/client.d.ts +3 -0
- package/dist/types/host.d.ts +4 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/types/services.d.ts +5 -2
- package/dist/types/spectrum/approvals-port.d.ts +13 -0
- package/dist/types/spectrum/index.d.ts +4 -0
- package/package.json +4 -4
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import { BACKGROUND_CONTEXT } from "@earendil-works/chord/context";
|
|
2
|
+
import { Emitter } from "./emitter.js";
|
|
3
|
+
const ENDS = {
|
|
4
|
+
approved: "answered",
|
|
5
|
+
rejected: "answered",
|
|
6
|
+
unanswered: "expired",
|
|
7
|
+
withdrawn: "withdrawn"
|
|
8
|
+
};
|
|
9
|
+
function requesterOf(item) {
|
|
10
|
+
const { kind, name, agentId, where } = item.requester;
|
|
11
|
+
return {
|
|
12
|
+
kind,
|
|
13
|
+
name,
|
|
14
|
+
...agentId ? { agentId } : {},
|
|
15
|
+
...where ? { where } : {}
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
function shown(item, agentName) {
|
|
19
|
+
const base = {
|
|
20
|
+
id: item.id,
|
|
21
|
+
requester: requesterOf(item),
|
|
22
|
+
createdAt: item.createdAt,
|
|
23
|
+
expiresAt: item.expiresAt
|
|
24
|
+
};
|
|
25
|
+
if (item.kind === "sudo") {
|
|
26
|
+
const { command, target, cwd, alwaysScope } = item.detail;
|
|
27
|
+
return {
|
|
28
|
+
...base,
|
|
29
|
+
kind: "sudo",
|
|
30
|
+
command,
|
|
31
|
+
...target ? { target } : {},
|
|
32
|
+
...cwd ? { cwd } : {},
|
|
33
|
+
always: item.always,
|
|
34
|
+
...alwaysScope ? { alwaysScope } : {}
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
const guest = {
|
|
38
|
+
...base,
|
|
39
|
+
agentId: item.agentId,
|
|
40
|
+
...agentName ? { agentName } : {},
|
|
41
|
+
always: false,
|
|
42
|
+
...item.verdict ? { verdict: { ...item.verdict } } : {}
|
|
43
|
+
};
|
|
44
|
+
if (item.kind === "guest-tool")
|
|
45
|
+
return { ...guest, kind: "guest-tool", tool: item.detail.tool, summary: item.detail.summary };
|
|
46
|
+
return {
|
|
47
|
+
...guest,
|
|
48
|
+
kind: "guest-message",
|
|
49
|
+
text: item.detail.text,
|
|
50
|
+
...item.detail.attachments.length ? { attachments: item.detail.attachments.map((file) => ({ ...file })) } : {}
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
const NOT_HERE = "This request can't be answered in this tab.";
|
|
54
|
+
const asked = (item) => item.state === "pending" && item.tier === "user";
|
|
55
|
+
class ApprovalsAdapter extends Emitter {
|
|
56
|
+
#connection;
|
|
57
|
+
#host;
|
|
58
|
+
#ours;
|
|
59
|
+
#mine = /* @__PURE__ */ new Set();
|
|
60
|
+
#deciding = /* @__PURE__ */ new Set();
|
|
61
|
+
#listed = /* @__PURE__ */ new Set();
|
|
62
|
+
decide;
|
|
63
|
+
constructor(connection, host) {
|
|
64
|
+
super();
|
|
65
|
+
this.#connection = connection;
|
|
66
|
+
this.#host = host;
|
|
67
|
+
this.#ours = !connection.readOnly && !connection.mismatch;
|
|
68
|
+
if (this.#ours || host?.decide) this.decide = (...args) => this.#route(...args);
|
|
69
|
+
this.#listed = new Set(this.#agent().map((approval) => approval.id));
|
|
70
|
+
connection.approvals?.subscribe(() => this.#changed());
|
|
71
|
+
host?.on("approvals", () => this.emit("approvals", this.list()));
|
|
72
|
+
host?.on("ended", (detail) => this.emit("ended", detail));
|
|
73
|
+
}
|
|
74
|
+
#items() {
|
|
75
|
+
return this.#connection.approvals?.value ?? [];
|
|
76
|
+
}
|
|
77
|
+
list() {
|
|
78
|
+
return [...this.#host?.list() ?? [], ...this.#agent()].sort(
|
|
79
|
+
(a, b) => a.createdAt - b.createdAt
|
|
80
|
+
);
|
|
81
|
+
}
|
|
82
|
+
#agent() {
|
|
83
|
+
const names = new Map(
|
|
84
|
+
(this.#connection.agents?.value?.agents ?? []).map((agent) => [agent.id, agent.name])
|
|
85
|
+
);
|
|
86
|
+
return this.#items().filter((item) => asked(item) && !this.#mine.has(item.id)).sort((a, b) => a.createdAt - b.createdAt).map((item) => shown(item, names.get(item.agentId)));
|
|
87
|
+
}
|
|
88
|
+
#changed() {
|
|
89
|
+
const items = new Map(this.#items().map((item) => [item.id, item]));
|
|
90
|
+
const listed = this.#agent();
|
|
91
|
+
const now = new Set(listed.map((approval) => approval.id));
|
|
92
|
+
for (const id of this.#listed) {
|
|
93
|
+
if (now.has(id) || this.#mine.has(id) || this.#deciding.has(id)) continue;
|
|
94
|
+
const state = items.get(id)?.state;
|
|
95
|
+
this.emit("ended", { id, reason: state && ENDS[state] || "answered" });
|
|
96
|
+
}
|
|
97
|
+
for (const id of this.#mine) {
|
|
98
|
+
const item = items.get(id);
|
|
99
|
+
if (!item || !asked(item)) this.#mine.delete(id);
|
|
100
|
+
}
|
|
101
|
+
this.#listed = now;
|
|
102
|
+
this.emit("approvals", this.list());
|
|
103
|
+
}
|
|
104
|
+
#route(id, decision, reason) {
|
|
105
|
+
const host = this.#host;
|
|
106
|
+
if (host?.list().some((approval) => approval.id === id)) {
|
|
107
|
+
if (!host.decide) return Promise.reject(new Error(NOT_HERE));
|
|
108
|
+
return host.decide(id, decision, reason);
|
|
109
|
+
}
|
|
110
|
+
if (!this.#ours) return Promise.reject(new Error(NOT_HERE));
|
|
111
|
+
return this.#decide(id, decision, reason);
|
|
112
|
+
}
|
|
113
|
+
async #decide(id, decision, reason) {
|
|
114
|
+
this.#deciding.add(id);
|
|
115
|
+
try {
|
|
116
|
+
const answer = await this.#connection.control.decide(
|
|
117
|
+
id,
|
|
118
|
+
decision,
|
|
119
|
+
reason ?? null,
|
|
120
|
+
BACKGROUND_CONTEXT
|
|
121
|
+
);
|
|
122
|
+
if (!answer.done) throw new Error(answer.error);
|
|
123
|
+
this.#mine.add(id);
|
|
124
|
+
} finally {
|
|
125
|
+
this.#deciding.delete(id);
|
|
126
|
+
}
|
|
127
|
+
this.#changed();
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
export {
|
|
131
|
+
ApprovalsAdapter,
|
|
132
|
+
NOT_HERE,
|
|
133
|
+
shown
|
|
134
|
+
};
|
|
135
|
+
//# sourceMappingURL=approvals-port.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/spectrum/approvals-port.ts"],
|
|
4
|
+
"sourcesContent": ["import type {\n Approval,\n ApprovalDecision,\n ApprovalEnd,\n ApprovalRequester,\n ApprovalsEvents,\n ApprovalsPort,\n} from '@ai-ecoverse/slicc-spectrum/ui';\nimport { BACKGROUND_CONTEXT } from '@earendil-works/chord/context';\nimport type { Approval as Item } from '../approvals/record.ts';\nimport type { AgentConnection } from '../client.ts';\nimport { Emitter } from './emitter.ts';\n\nconst ENDS: Record<string, ApprovalEnd> = {\n approved: 'answered',\n rejected: 'answered',\n unanswered: 'expired',\n withdrawn: 'withdrawn',\n};\n\nfunction requesterOf(item: Item): ApprovalRequester {\n const { kind, name, agentId, where } = item.requester;\n return {\n kind,\n name,\n ...(agentId ? { agentId } : {}),\n ...(where ? { where } : {}),\n };\n}\n\nexport function shown(item: Item, agentName: string | undefined): Approval {\n const base = {\n id: item.id,\n requester: requesterOf(item),\n createdAt: item.createdAt,\n expiresAt: item.expiresAt,\n };\n if (item.kind === 'sudo') {\n const { command, target, cwd, alwaysScope } = item.detail;\n return {\n ...base,\n kind: 'sudo',\n command,\n ...(target ? { target } : {}),\n ...(cwd ? { cwd } : {}),\n always: item.always,\n ...(alwaysScope ? { alwaysScope } : {}),\n };\n }\n const guest = {\n ...base,\n agentId: item.agentId,\n ...(agentName ? { agentName } : {}),\n always: false as const,\n ...(item.verdict ? { verdict: { ...item.verdict } } : {}),\n };\n if (item.kind === 'guest-tool')\n return { ...guest, kind: 'guest-tool', tool: item.detail.tool, summary: item.detail.summary };\n return {\n ...guest,\n kind: 'guest-message',\n text: item.detail.text,\n ...(item.detail.attachments.length\n ? { attachments: item.detail.attachments.map((file) => ({ ...file })) }\n : {}),\n };\n}\n\nexport type HostApprovals = ApprovalsPort;\n\nexport const NOT_HERE = \"This request can't be answered in this tab.\";\n\nconst asked = (item: Item) => item.state === 'pending' && item.tier === 'user';\n\nexport class ApprovalsAdapter extends Emitter<ApprovalsEvents> implements ApprovalsPort {\n readonly #connection: AgentConnection;\n readonly #host: HostApprovals | undefined;\n readonly #ours: boolean;\n readonly #mine = new Set<string>();\n readonly #deciding = new Set<string>();\n #listed = new Set<string>();\n readonly decide?: (id: string, decision: ApprovalDecision, reason?: string) => Promise<void>;\n\n constructor(connection: AgentConnection, host?: HostApprovals) {\n super();\n this.#connection = connection;\n this.#host = host;\n this.#ours = !connection.readOnly && !connection.mismatch;\n if (this.#ours || host?.decide) this.decide = (...args) => this.#route(...args);\n this.#listed = new Set(this.#agent().map((approval) => approval.id));\n connection.approvals?.subscribe(() => this.#changed());\n host?.on('approvals', () => this.emit('approvals', this.list()));\n host?.on('ended', (detail) => this.emit('ended', detail));\n }\n\n #items(): readonly Item[] {\n return this.#connection.approvals?.value ?? [];\n }\n\n list(): readonly Approval[] {\n return [...(this.#host?.list() ?? []), ...this.#agent()].sort(\n (a, b) => a.createdAt - b.createdAt\n );\n }\n\n #agent(): readonly Approval[] {\n const names = new Map(\n (this.#connection.agents?.value?.agents ?? []).map((agent) => [agent.id, agent.name])\n );\n return this.#items()\n .filter((item) => asked(item) && !this.#mine.has(item.id))\n .sort((a, b) => a.createdAt - b.createdAt)\n .map((item) => shown(item, names.get(item.agentId)));\n }\n\n #changed(): void {\n const items = new Map(this.#items().map((item) => [item.id, item]));\n const listed = this.#agent();\n const now = new Set(listed.map((approval) => approval.id));\n for (const id of this.#listed) {\n if (now.has(id) || this.#mine.has(id) || this.#deciding.has(id)) continue;\n const state = items.get(id)?.state;\n this.emit('ended', { id, reason: (state && ENDS[state]) || 'answered' });\n }\n for (const id of this.#mine) {\n const item = items.get(id);\n if (!item || !asked(item)) this.#mine.delete(id);\n }\n this.#listed = now;\n this.emit('approvals', this.list());\n }\n\n #route(id: string, decision: ApprovalDecision, reason?: string): Promise<void> {\n const host = this.#host;\n if (host?.list().some((approval) => approval.id === id)) {\n if (!host.decide) return Promise.reject(new Error(NOT_HERE));\n return host.decide(id, decision, reason);\n }\n if (!this.#ours) return Promise.reject(new Error(NOT_HERE));\n return this.#decide(id, decision, reason);\n }\n\n async #decide(id: string, decision: ApprovalDecision, reason?: string): Promise<void> {\n this.#deciding.add(id);\n try {\n const answer = await this.#connection.control.decide(\n id,\n decision,\n reason ?? null,\n BACKGROUND_CONTEXT\n );\n if (!answer.done) throw new Error(answer.error);\n this.#mine.add(id);\n } finally {\n this.#deciding.delete(id);\n }\n this.#changed();\n }\n}\n"],
|
|
5
|
+
"mappings": "AAQA,SAAS,0BAA0B;AAGnC,SAAS,eAAe;AAExB,MAAM,OAAoC;AAAA,EACxC,UAAU;AAAA,EACV,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,WAAW;AACb;AAEA,SAAS,YAAY,MAA+B;AAClD,QAAM,EAAE,MAAM,MAAM,SAAS,MAAM,IAAI,KAAK;AAC5C,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,GAAI,UAAU,EAAE,QAAQ,IAAI,CAAC;AAAA,IAC7B,GAAI,QAAQ,EAAE,MAAM,IAAI,CAAC;AAAA,EAC3B;AACF;AAEO,SAAS,MAAM,MAAY,WAAyC;AACzE,QAAM,OAAO;AAAA,IACX,IAAI,KAAK;AAAA,IACT,WAAW,YAAY,IAAI;AAAA,IAC3B,WAAW,KAAK;AAAA,IAChB,WAAW,KAAK;AAAA,EAClB;AACA,MAAI,KAAK,SAAS,QAAQ;AACxB,UAAM,EAAE,SAAS,QAAQ,KAAK,YAAY,IAAI,KAAK;AACnD,WAAO;AAAA,MACL,GAAG;AAAA,MACH,MAAM;AAAA,MACN;AAAA,MACA,GAAI,SAAS,EAAE,OAAO,IAAI,CAAC;AAAA,MAC3B,GAAI,MAAM,EAAE,IAAI,IAAI,CAAC;AAAA,MACrB,QAAQ,KAAK;AAAA,MACb,GAAI,cAAc,EAAE,YAAY,IAAI,CAAC;AAAA,IACvC;AAAA,EACF;AACA,QAAM,QAAQ;AAAA,IACZ,GAAG;AAAA,IACH,SAAS,KAAK;AAAA,IACd,GAAI,YAAY,EAAE,UAAU,IAAI,CAAC;AAAA,IACjC,QAAQ;AAAA,IACR,GAAI,KAAK,UAAU,EAAE,SAAS,EAAE,GAAG,KAAK,QAAQ,EAAE,IAAI,CAAC;AAAA,EACzD;AACA,MAAI,KAAK,SAAS;AAChB,WAAO,EAAE,GAAG,OAAO,MAAM,cAAc,MAAM,KAAK,OAAO,MAAM,SAAS,KAAK,OAAO,QAAQ;AAC9F,SAAO;AAAA,IACL,GAAG;AAAA,IACH,MAAM;AAAA,IACN,MAAM,KAAK,OAAO;AAAA,IAClB,GAAI,KAAK,OAAO,YAAY,SACxB,EAAE,aAAa,KAAK,OAAO,YAAY,IAAI,CAAC,UAAU,EAAE,GAAG,KAAK,EAAE,EAAE,IACpE,CAAC;AAAA,EACP;AACF;AAIO,MAAM,WAAW;AAExB,MAAM,QAAQ,CAAC,SAAe,KAAK,UAAU,aAAa,KAAK,SAAS;AAEjE,MAAM,yBAAyB,QAAkD;AAAA,EAC7E;AAAA,EACA;AAAA,EACA;AAAA,EACA,QAAQ,oBAAI,IAAY;AAAA,EACxB,YAAY,oBAAI,IAAY;AAAA,EACrC,UAAU,oBAAI,IAAY;AAAA,EACjB;AAAA,EAET,YAAY,YAA6B,MAAsB;AAC7D,UAAM;AACN,SAAK,cAAc;AACnB,SAAK,QAAQ;AACb,SAAK,QAAQ,CAAC,WAAW,YAAY,CAAC,WAAW;AACjD,QAAI,KAAK,SAAS,MAAM,OAAQ,MAAK,SAAS,IAAI,SAAS,KAAK,OAAO,GAAG,IAAI;AAC9E,SAAK,UAAU,IAAI,IAAI,KAAK,OAAO,EAAE,IAAI,CAAC,aAAa,SAAS,EAAE,CAAC;AACnE,eAAW,WAAW,UAAU,MAAM,KAAK,SAAS,CAAC;AACrD,UAAM,GAAG,aAAa,MAAM,KAAK,KAAK,aAAa,KAAK,KAAK,CAAC,CAAC;AAC/D,UAAM,GAAG,SAAS,CAAC,WAAW,KAAK,KAAK,SAAS,MAAM,CAAC;AAAA,EAC1D;AAAA,EAEA,SAA0B;AACxB,WAAO,KAAK,YAAY,WAAW,SAAS,CAAC;AAAA,EAC/C;AAAA,EAEA,OAA4B;AAC1B,WAAO,CAAC,GAAI,KAAK,OAAO,KAAK,KAAK,CAAC,GAAI,GAAG,KAAK,OAAO,CAAC,EAAE;AAAA,MACvD,CAAC,GAAG,MAAM,EAAE,YAAY,EAAE;AAAA,IAC5B;AAAA,EACF;AAAA,EAEA,SAA8B;AAC5B,UAAM,QAAQ,IAAI;AAAA,OACf,KAAK,YAAY,QAAQ,OAAO,UAAU,CAAC,GAAG,IAAI,CAAC,UAAU,CAAC,MAAM,IAAI,MAAM,IAAI,CAAC;AAAA,IACtF;AACA,WAAO,KAAK,OAAO,EAChB,OAAO,CAAC,SAAS,MAAM,IAAI,KAAK,CAAC,KAAK,MAAM,IAAI,KAAK,EAAE,CAAC,EACxD,KAAK,CAAC,GAAG,MAAM,EAAE,YAAY,EAAE,SAAS,EACxC,IAAI,CAAC,SAAS,MAAM,MAAM,MAAM,IAAI,KAAK,OAAO,CAAC,CAAC;AAAA,EACvD;AAAA,EAEA,WAAiB;AACf,UAAM,QAAQ,IAAI,IAAI,KAAK,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,IAAI,IAAI,CAAC,CAAC;AAClE,UAAM,SAAS,KAAK,OAAO;AAC3B,UAAM,MAAM,IAAI,IAAI,OAAO,IAAI,CAAC,aAAa,SAAS,EAAE,CAAC;AACzD,eAAW,MAAM,KAAK,SAAS;AAC7B,UAAI,IAAI,IAAI,EAAE,KAAK,KAAK,MAAM,IAAI,EAAE,KAAK,KAAK,UAAU,IAAI,EAAE,EAAG;AACjE,YAAM,QAAQ,MAAM,IAAI,EAAE,GAAG;AAC7B,WAAK,KAAK,SAAS,EAAE,IAAI,QAAS,SAAS,KAAK,KAAK,KAAM,WAAW,CAAC;AAAA,IACzE;AACA,eAAW,MAAM,KAAK,OAAO;AAC3B,YAAM,OAAO,MAAM,IAAI,EAAE;AACzB,UAAI,CAAC,QAAQ,CAAC,MAAM,IAAI,EAAG,MAAK,MAAM,OAAO,EAAE;AAAA,IACjD;AACA,SAAK,UAAU;AACf,SAAK,KAAK,aAAa,KAAK,KAAK,CAAC;AAAA,EACpC;AAAA,EAEA,OAAO,IAAY,UAA4B,QAAgC;AAC7E,UAAM,OAAO,KAAK;AAClB,QAAI,MAAM,KAAK,EAAE,KAAK,CAAC,aAAa,SAAS,OAAO,EAAE,GAAG;AACvD,UAAI,CAAC,KAAK,OAAQ,QAAO,QAAQ,OAAO,IAAI,MAAM,QAAQ,CAAC;AAC3D,aAAO,KAAK,OAAO,IAAI,UAAU,MAAM;AAAA,IACzC;AACA,QAAI,CAAC,KAAK,MAAO,QAAO,QAAQ,OAAO,IAAI,MAAM,QAAQ,CAAC;AAC1D,WAAO,KAAK,QAAQ,IAAI,UAAU,MAAM;AAAA,EAC1C;AAAA,EAEA,MAAM,QAAQ,IAAY,UAA4B,QAAgC;AACpF,SAAK,UAAU,IAAI,EAAE;AACrB,QAAI;AACF,YAAM,SAAS,MAAM,KAAK,YAAY,QAAQ;AAAA,QAC5C;AAAA,QACA;AAAA,QACA,UAAU;AAAA,QACV;AAAA,MACF;AACA,UAAI,CAAC,OAAO,KAAM,OAAM,IAAI,MAAM,OAAO,KAAK;AAC9C,WAAK,MAAM,IAAI,EAAE;AAAA,IACnB,UAAE;AACA,WAAK,UAAU,OAAO,EAAE;AAAA,IAC1B;AACA,SAAK,SAAS;AAAA,EAChB;AACF;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
package/dist/spectrum/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { AgentAdapter } from "./agent-port.js";
|
|
2
|
+
import { ApprovalsAdapter } from "./approvals-port.js";
|
|
2
3
|
import { ChangesAdapter } from "./changes-port.js";
|
|
3
4
|
import { MemoryAdapter } from "./memory-port.js";
|
|
4
5
|
import { MonitorAdapter } from "./monitor-port.js";
|
|
@@ -8,6 +9,11 @@ import { SettingsAdapter } from "./settings-port.js";
|
|
|
8
9
|
import { SprinkleAdapter } from "./sprinkle-port.js";
|
|
9
10
|
import { TrayAdapter } from "./tray-port.js";
|
|
10
11
|
import { AgentAdapter as AgentAdapter2, CONE } from "./agent-port.js";
|
|
12
|
+
import {
|
|
13
|
+
ApprovalsAdapter as ApprovalsAdapter2,
|
|
14
|
+
NOT_HERE,
|
|
15
|
+
shown
|
|
16
|
+
} from "./approvals-port.js";
|
|
11
17
|
import { ChangesAdapter as ChangesAdapter2 } from "./changes-port.js";
|
|
12
18
|
import { MemoryAdapter as MemoryAdapter2 } from "./memory-port.js";
|
|
13
19
|
import {
|
|
@@ -43,6 +49,7 @@ function createAgentModel(connection, options = {}) {
|
|
|
43
49
|
const run = options.page?.run;
|
|
44
50
|
return {
|
|
45
51
|
agent,
|
|
52
|
+
approvals: new ApprovalsAdapter(connection, options.approvals),
|
|
46
53
|
page: options.page && run ? new PageAdapter(connection, agent, { ...options.page, run }) : null,
|
|
47
54
|
settings: new SettingsAdapter(
|
|
48
55
|
connection.settings,
|
|
@@ -63,12 +70,14 @@ function createAgentModel(connection, options = {}) {
|
|
|
63
70
|
}
|
|
64
71
|
export {
|
|
65
72
|
AgentAdapter2 as AgentAdapter,
|
|
73
|
+
ApprovalsAdapter2 as ApprovalsAdapter,
|
|
66
74
|
CONE,
|
|
67
75
|
ChangesAdapter2 as ChangesAdapter,
|
|
68
76
|
KEYS_MOVED,
|
|
69
77
|
MISMATCH,
|
|
70
78
|
MemoryAdapter2 as MemoryAdapter,
|
|
71
79
|
MonitorAdapter2 as MonitorAdapter,
|
|
80
|
+
NOT_HERE,
|
|
72
81
|
NoticesAdapter2 as NoticesAdapter,
|
|
73
82
|
PageAdapter2 as PageAdapter,
|
|
74
83
|
SETTINGS_KEY,
|
|
@@ -85,6 +94,7 @@ export {
|
|
|
85
94
|
movedList,
|
|
86
95
|
movedNotice,
|
|
87
96
|
queued,
|
|
97
|
+
shown as shownApproval,
|
|
88
98
|
textOf,
|
|
89
99
|
toMessages
|
|
90
100
|
};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/spectrum/index.ts"],
|
|
4
|
-
"sourcesContent": ["import type { MonitorSection } from '@ai-ecoverse/slicc-spectrum/ui';\nimport type { AgentConnection } from '../client.ts';\nimport { AgentAdapter } from './agent-port.ts';\nimport { ChangesAdapter } from './changes-port.ts';\nimport { MemoryAdapter } from './memory-port.ts';\nimport { MonitorAdapter } from './monitor-port.ts';\nimport { type HostNotices, NoticesAdapter } from './notices-port.ts';\nimport { PageAdapter, type PageOptions } from './page-port.ts';\nimport { type Login, SettingsAdapter } from './settings-port.ts';\nimport { SprinkleAdapter } from './sprinkle-port.ts';\nimport { TrayAdapter } from './tray-port.ts';\n\nexport { AgentAdapter, CONE } from './agent-port.ts';\nexport { ChangesAdapter, type ChangesEvents } from './changes-port.ts';\nexport { MemoryAdapter } from './memory-port.ts';\nexport {\n assistant,\n errorAction,\n errorPart,\n isBusy,\n queued,\n textOf,\n toMessages,\n} from './messages.ts';\nexport {\n MonitorAdapter,\n type MonitorAdapterOptions,\n type MonitorInput,\n monitorSnapshot,\n} from './monitor-port.ts';\nexport {\n type HostNotices,\n KEYS_MOVED,\n MISMATCH,\n mismatchBanner,\n movedList,\n movedNotice,\n NoticesAdapter,\n} from './notices-port.ts';\nexport {\n PageAdapter,\n type PageDocument,\n type PageOptions,\n type PageRun,\n type PageTarget,\n} from './page-port.ts';\nexport { type Login, SETTINGS_KEY, SettingsAdapter } from './settings-port.ts';\nexport { SprinkleAdapter } from './sprinkle-port.ts';\nexport { TrayAdapter } from './tray-port.ts';\n\nexport function createAgentModel(\n connection: AgentConnection,\n options: {\n storage?: Pick<Storage, 'getItem' | 'setItem'> | null;\n login?: Login;\n monitor?: { extra?: () => readonly MonitorSection[] };\n page?: PageOptions;\n notices?: HostNotices;\n } = {}\n): {\n agent: AgentAdapter;\n settings: SettingsAdapter;\n tray: TrayAdapter;\n sprinkles: SprinkleAdapter;\n memory: MemoryAdapter;\n changes: ChangesAdapter;\n monitor: MonitorAdapter;\n notices: NoticesAdapter;\n page: PageAdapter | null;\n} {\n const agent = new AgentAdapter(connection);\n const report = (text: string) => agent.notify(text);\n const run = options.page?.run;\n return {\n agent,\n page: options.page && run ? new PageAdapter(connection, agent, { ...options.page, run }) : null,\n settings: new SettingsAdapter(\n connection.settings,\n agent,\n options.storage ?? null,\n options.login ?? null\n ),\n tray: new TrayAdapter(connection.settings),\n sprinkles: new SprinkleAdapter(connection, report),\n memory: new MemoryAdapter(connection, report),\n changes: new ChangesAdapter(connection, report),\n notices: new NoticesAdapter(connection.settings, report, connection.mismatch, options.notices),\n monitor: new MonitorAdapter(\n connection,\n options.monitor?.extra ? { extra: options.monitor.extra } : {}\n ),\n };\n}\n"],
|
|
5
|
-
"mappings": "AAEA,SAAS,oBAAoB;AAC7B,SAAS,sBAAsB;AAC/B,SAAS,qBAAqB;AAC9B,SAAS,sBAAsB;AAC/B,SAA2B,sBAAsB;AACjD,SAAS,mBAAqC;AAC9C,SAAqB,uBAAuB;AAC5C,SAAS,uBAAuB;AAChC,SAAS,mBAAmB;AAE5B,SAAS,gBAAAA,eAAc,YAAY;AACnC,SAAS,kBAAAC,uBAA0C;AACnD,SAAS,iBAAAC,sBAAqB;AAC9B;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP;AAAA,EACE,kBAAAC;AAAA,EAGA;AAAA,OACK;AACP;AAAA,EAEE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,kBAAAC;AAAA,OACK;AACP;AAAA,EACE,eAAAC;AAAA,OAKK;AACP,SAAqB,cAAc,mBAAAC,wBAAuB;AAC1D,SAAS,mBAAAC,wBAAuB;AAChC,SAAS,eAAAC,oBAAmB;AAErB,SAAS,iBACd,YACA,
|
|
6
|
-
"names": ["AgentAdapter", "ChangesAdapter", "MemoryAdapter", "MonitorAdapter", "NoticesAdapter", "PageAdapter", "SettingsAdapter", "SprinkleAdapter", "TrayAdapter"]
|
|
4
|
+
"sourcesContent": ["import type { MonitorSection } from '@ai-ecoverse/slicc-spectrum/ui';\nimport type { AgentConnection } from '../client.ts';\nimport { AgentAdapter } from './agent-port.ts';\nimport { ApprovalsAdapter, type HostApprovals } from './approvals-port.ts';\nimport { ChangesAdapter } from './changes-port.ts';\nimport { MemoryAdapter } from './memory-port.ts';\nimport { MonitorAdapter } from './monitor-port.ts';\nimport { type HostNotices, NoticesAdapter } from './notices-port.ts';\nimport { PageAdapter, type PageOptions } from './page-port.ts';\nimport { type Login, SettingsAdapter } from './settings-port.ts';\nimport { SprinkleAdapter } from './sprinkle-port.ts';\nimport { TrayAdapter } from './tray-port.ts';\n\nexport { AgentAdapter, CONE } from './agent-port.ts';\nexport {\n ApprovalsAdapter,\n type HostApprovals,\n NOT_HERE,\n shown as shownApproval,\n} from './approvals-port.ts';\nexport { ChangesAdapter, type ChangesEvents } from './changes-port.ts';\nexport { MemoryAdapter } from './memory-port.ts';\nexport {\n assistant,\n errorAction,\n errorPart,\n isBusy,\n queued,\n textOf,\n toMessages,\n} from './messages.ts';\nexport {\n MonitorAdapter,\n type MonitorAdapterOptions,\n type MonitorInput,\n monitorSnapshot,\n} from './monitor-port.ts';\nexport {\n type HostNotices,\n KEYS_MOVED,\n MISMATCH,\n mismatchBanner,\n movedList,\n movedNotice,\n NoticesAdapter,\n} from './notices-port.ts';\nexport {\n PageAdapter,\n type PageDocument,\n type PageOptions,\n type PageRun,\n type PageTarget,\n} from './page-port.ts';\nexport { type Login, SETTINGS_KEY, SettingsAdapter } from './settings-port.ts';\nexport { SprinkleAdapter } from './sprinkle-port.ts';\nexport { TrayAdapter } from './tray-port.ts';\n\nexport function createAgentModel(\n connection: AgentConnection,\n options: {\n storage?: Pick<Storage, 'getItem' | 'setItem'> | null;\n login?: Login;\n monitor?: { extra?: () => readonly MonitorSection[] };\n page?: PageOptions;\n approvals?: HostApprovals;\n notices?: HostNotices;\n } = {}\n): {\n agent: AgentAdapter;\n approvals: ApprovalsAdapter;\n settings: SettingsAdapter;\n tray: TrayAdapter;\n sprinkles: SprinkleAdapter;\n memory: MemoryAdapter;\n changes: ChangesAdapter;\n monitor: MonitorAdapter;\n notices: NoticesAdapter;\n page: PageAdapter | null;\n} {\n const agent = new AgentAdapter(connection);\n const report = (text: string) => agent.notify(text);\n const run = options.page?.run;\n return {\n agent,\n approvals: new ApprovalsAdapter(connection, options.approvals),\n page: options.page && run ? new PageAdapter(connection, agent, { ...options.page, run }) : null,\n settings: new SettingsAdapter(\n connection.settings,\n agent,\n options.storage ?? null,\n options.login ?? null\n ),\n tray: new TrayAdapter(connection.settings),\n sprinkles: new SprinkleAdapter(connection, report),\n memory: new MemoryAdapter(connection, report),\n changes: new ChangesAdapter(connection, report),\n notices: new NoticesAdapter(connection.settings, report, connection.mismatch, options.notices),\n monitor: new MonitorAdapter(\n connection,\n options.monitor?.extra ? { extra: options.monitor.extra } : {}\n ),\n };\n}\n"],
|
|
5
|
+
"mappings": "AAEA,SAAS,oBAAoB;AAC7B,SAAS,wBAA4C;AACrD,SAAS,sBAAsB;AAC/B,SAAS,qBAAqB;AAC9B,SAAS,sBAAsB;AAC/B,SAA2B,sBAAsB;AACjD,SAAS,mBAAqC;AAC9C,SAAqB,uBAAuB;AAC5C,SAAS,uBAAuB;AAChC,SAAS,mBAAmB;AAE5B,SAAS,gBAAAA,eAAc,YAAY;AACnC;AAAA,EACE,oBAAAC;AAAA,EAEA;AAAA,EACS;AAAA,OACJ;AACP,SAAS,kBAAAC,uBAA0C;AACnD,SAAS,iBAAAC,sBAAqB;AAC9B;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP;AAAA,EACE,kBAAAC;AAAA,EAGA;AAAA,OACK;AACP;AAAA,EAEE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,kBAAAC;AAAA,OACK;AACP;AAAA,EACE,eAAAC;AAAA,OAKK;AACP,SAAqB,cAAc,mBAAAC,wBAAuB;AAC1D,SAAS,mBAAAC,wBAAuB;AAChC,SAAS,eAAAC,oBAAmB;AAErB,SAAS,iBACd,YACA,UAOI,CAAC,GAYL;AACA,QAAM,QAAQ,IAAI,aAAa,UAAU;AACzC,QAAM,SAAS,CAAC,SAAiB,MAAM,OAAO,IAAI;AAClD,QAAM,MAAM,QAAQ,MAAM;AAC1B,SAAO;AAAA,IACL;AAAA,IACA,WAAW,IAAI,iBAAiB,YAAY,QAAQ,SAAS;AAAA,IAC7D,MAAM,QAAQ,QAAQ,MAAM,IAAI,YAAY,YAAY,OAAO,EAAE,GAAG,QAAQ,MAAM,IAAI,CAAC,IAAI;AAAA,IAC3F,UAAU,IAAI;AAAA,MACZ,WAAW;AAAA,MACX;AAAA,MACA,QAAQ,WAAW;AAAA,MACnB,QAAQ,SAAS;AAAA,IACnB;AAAA,IACA,MAAM,IAAI,YAAY,WAAW,QAAQ;AAAA,IACzC,WAAW,IAAI,gBAAgB,YAAY,MAAM;AAAA,IACjD,QAAQ,IAAI,cAAc,YAAY,MAAM;AAAA,IAC5C,SAAS,IAAI,eAAe,YAAY,MAAM;AAAA,IAC9C,SAAS,IAAI,eAAe,WAAW,UAAU,QAAQ,WAAW,UAAU,QAAQ,OAAO;AAAA,IAC7F,SAAS,IAAI;AAAA,MACX;AAAA,MACA,QAAQ,SAAS,QAAQ,EAAE,OAAO,QAAQ,QAAQ,MAAM,IAAI,CAAC;AAAA,IAC/D;AAAA,EACF;AACF;",
|
|
6
|
+
"names": ["AgentAdapter", "ApprovalsAdapter", "ChangesAdapter", "MemoryAdapter", "MonitorAdapter", "NoticesAdapter", "PageAdapter", "SettingsAdapter", "SprinkleAdapter", "TrayAdapter"]
|
|
7
7
|
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { type Context, type ReplicatedState } from '@earendil-works/chord';
|
|
2
|
+
import type { Harness } from '@earendil-works/pi-durable';
|
|
3
|
+
import { type Approval, type ApprovalDraft, type ApprovalState, type DecidedBy } from './record.ts';
|
|
4
|
+
export * from './record.ts';
|
|
5
|
+
export type ApprovalDecided = {
|
|
6
|
+
done: true;
|
|
7
|
+
state: ApprovalState;
|
|
8
|
+
error: null;
|
|
9
|
+
} | {
|
|
10
|
+
done: false;
|
|
11
|
+
state: null;
|
|
12
|
+
error: string;
|
|
13
|
+
};
|
|
14
|
+
export interface Approvals {
|
|
15
|
+
readonly state: ReplicatedState<Approval[]>;
|
|
16
|
+
request(draft: ApprovalDraft, context: Context): Promise<Approval>;
|
|
17
|
+
decide(id: string, answer: unknown, reason: string | null, by: DecidedBy, context: Context): Promise<ApprovalDecided>;
|
|
18
|
+
settled(id: string, context: Context): Promise<Approval>;
|
|
19
|
+
withdraw(id: string, reason: string | null, context: Context): Promise<Approval | undefined>;
|
|
20
|
+
withdrawSeat(seat: string, context: Context): Promise<number>;
|
|
21
|
+
close(): void;
|
|
22
|
+
}
|
|
23
|
+
export interface ApprovalsAttach {
|
|
24
|
+
harness: Pick<Harness, 'commit'>;
|
|
25
|
+
now?: () => number;
|
|
26
|
+
ttlMs?: number;
|
|
27
|
+
}
|
|
28
|
+
export declare function attachApprovals(options: ApprovalsAttach, context?: Context): Promise<Approvals>;
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
export type ApprovalKind = 'guest-message' | 'guest-tool' | 'sudo';
|
|
2
|
+
export type ApprovalState = 'pending' | 'approved' | 'rejected' | 'unanswered' | 'withdrawn';
|
|
3
|
+
export type ApprovalTier = 'user' | 'agent' | 'cone' | `scoop:${string}`;
|
|
4
|
+
export type ApprovalAnswer = 'once' | 'always' | 'deny';
|
|
5
|
+
export type DecidedBy = 'owner' | 'follower' | 'judge' | 'host';
|
|
6
|
+
export type ApprovalRequester = {
|
|
7
|
+
kind: 'guest' | 'agent' | 'user';
|
|
8
|
+
name: string;
|
|
9
|
+
seat?: string;
|
|
10
|
+
agentId?: string;
|
|
11
|
+
where?: string;
|
|
12
|
+
};
|
|
13
|
+
export type ApprovalVerdict = {
|
|
14
|
+
decision: 'allow' | 'deny';
|
|
15
|
+
reason: string;
|
|
16
|
+
};
|
|
17
|
+
export type ApprovalAttachment = {
|
|
18
|
+
name: string;
|
|
19
|
+
mimeType: string;
|
|
20
|
+
size: number;
|
|
21
|
+
};
|
|
22
|
+
export type GuestMessageDetail = {
|
|
23
|
+
text: string;
|
|
24
|
+
attachments: ApprovalAttachment[];
|
|
25
|
+
};
|
|
26
|
+
export type GuestToolDetail = {
|
|
27
|
+
tool: string;
|
|
28
|
+
summary: string;
|
|
29
|
+
};
|
|
30
|
+
export type SudoDetail = {
|
|
31
|
+
command: string;
|
|
32
|
+
target?: string;
|
|
33
|
+
cwd?: string;
|
|
34
|
+
alwaysScope?: 'cwd';
|
|
35
|
+
};
|
|
36
|
+
type Base = {
|
|
37
|
+
id: string;
|
|
38
|
+
seat?: string;
|
|
39
|
+
agentId: string;
|
|
40
|
+
requester: ApprovalRequester;
|
|
41
|
+
tier: string;
|
|
42
|
+
state: ApprovalState;
|
|
43
|
+
decidedBy: DecidedBy | null;
|
|
44
|
+
answer?: 'once' | 'always';
|
|
45
|
+
reason?: string;
|
|
46
|
+
verdict?: ApprovalVerdict;
|
|
47
|
+
always: boolean;
|
|
48
|
+
createdAt: number;
|
|
49
|
+
expiresAt: number;
|
|
50
|
+
decidedAt?: number;
|
|
51
|
+
};
|
|
52
|
+
export type GuestMessageApproval = Base & {
|
|
53
|
+
kind: 'guest-message';
|
|
54
|
+
detail: GuestMessageDetail;
|
|
55
|
+
};
|
|
56
|
+
export type GuestToolApproval = Base & {
|
|
57
|
+
kind: 'guest-tool';
|
|
58
|
+
detail: GuestToolDetail;
|
|
59
|
+
};
|
|
60
|
+
export type SudoApproval = Base & {
|
|
61
|
+
kind: 'sudo';
|
|
62
|
+
detail: SudoDetail;
|
|
63
|
+
};
|
|
64
|
+
export type Approval = GuestMessageApproval | GuestToolApproval | SudoApproval;
|
|
65
|
+
type DraftOf<T extends Approval> = Pick<T, 'kind' | 'detail' | 'agentId' | 'requester'> & {
|
|
66
|
+
seat?: string;
|
|
67
|
+
tier: string;
|
|
68
|
+
always?: boolean;
|
|
69
|
+
expiresAt?: number;
|
|
70
|
+
};
|
|
71
|
+
export type ApprovalDraft = DraftOf<GuestMessageApproval> | DraftOf<GuestToolApproval> | DraftOf<SudoApproval>;
|
|
72
|
+
export type ApprovalsState = {
|
|
73
|
+
items: Approval[];
|
|
74
|
+
};
|
|
75
|
+
export declare const ApprovalsDoc: import("@earendil-works/pi-durable").SessionDocToken<ApprovalsState>;
|
|
76
|
+
export declare const APPROVAL_MS = 300000;
|
|
77
|
+
export declare const APPROVALS_KEPT = 100;
|
|
78
|
+
export declare const MAX_DELAY = 2147483647;
|
|
79
|
+
export declare const REASON_LENGTH = 500;
|
|
80
|
+
export declare const REASONS: {
|
|
81
|
+
readonly timeout: 'timeout';
|
|
82
|
+
readonly unknownTier: 'unknown-tier';
|
|
83
|
+
readonly unroutable: 'unroutable';
|
|
84
|
+
readonly unknownAnswer: 'unknown-answer';
|
|
85
|
+
readonly restart: 'restart';
|
|
86
|
+
readonly revoked: 'revoked';
|
|
87
|
+
};
|
|
88
|
+
export declare const guestKind: (kind: ApprovalKind) => boolean;
|
|
89
|
+
export declare function knownTier(tier: unknown): tier is ApprovalTier;
|
|
90
|
+
export declare function routable(kind: ApprovalKind, tier: ApprovalTier): boolean;
|
|
91
|
+
export declare function answerOf(value: unknown): ApprovalAnswer | null;
|
|
92
|
+
export declare const personal: (by: DecidedBy) => boolean;
|
|
93
|
+
export declare function answerer(by: DecidedBy, tier: string): boolean;
|
|
94
|
+
export declare function gone(state: ApprovalState): string;
|
|
95
|
+
export declare function cleanReason(reason: unknown): string | undefined;
|
|
96
|
+
export declare function prune(items: Approval[], kept?: number): Approval[];
|
|
97
|
+
export type Settle = {
|
|
98
|
+
state: Exclude<ApprovalState, 'pending'>;
|
|
99
|
+
by: DecidedBy;
|
|
100
|
+
reason?: string;
|
|
101
|
+
};
|
|
102
|
+
export type Ruling = {
|
|
103
|
+
error?: string;
|
|
104
|
+
settle?: Settle;
|
|
105
|
+
answer?: 'once' | 'always';
|
|
106
|
+
};
|
|
107
|
+
export declare function ruled(item: Approval, answer: unknown, reason: unknown, by: DecidedBy, at: number): Ruling;
|
|
108
|
+
export {};
|
package/dist/types/client.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { type Context, type ReplicatedState } from '@earendil-works/chord';
|
|
2
2
|
import type { ConversationView } from '@earendil-works/pi-durable';
|
|
3
|
+
import type { Approval } from './approvals/record.ts';
|
|
3
4
|
import type { ChangesView } from './changes/git.ts';
|
|
4
5
|
import type { FrozenCone } from './freezer/index.ts';
|
|
5
6
|
import type { MemoryEntry, MemoryScope } from './memory/format.ts';
|
|
@@ -26,11 +27,13 @@ export interface AgentConnection {
|
|
|
26
27
|
readonly monitor?: ReplicatedState<MonitorFeed>;
|
|
27
28
|
readonly vault?: ReplicatedState<VaultState>;
|
|
28
29
|
readonly labels?: ReplicatedState<Record<string, string>>;
|
|
30
|
+
readonly approvals?: ReplicatedState<Approval[]>;
|
|
29
31
|
readonly settings: AgentSettings;
|
|
30
32
|
readonly remote?: AgentRemote;
|
|
31
33
|
readonly pages?: AgentPages;
|
|
32
34
|
readonly closed: Promise<Error | undefined>;
|
|
33
35
|
readonly mismatch?: string;
|
|
36
|
+
readonly readOnly?: boolean;
|
|
34
37
|
prompt(text: string, whenBusy?: SendMode): Promise<string>;
|
|
35
38
|
webhook(name: string, delivery: {
|
|
36
39
|
id?: string | null;
|
package/dist/types/host.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { type Context, type Host, type ReplicatedState } from '@earendil-works/chord';
|
|
2
2
|
import type { Agent } from './agent.ts';
|
|
3
|
+
import { type Approvals, type DecidedBy } from './approvals/index.ts';
|
|
3
4
|
import type { ChangesRuntime } from './changes/index.ts';
|
|
4
5
|
import { type HostLicks, type HostScoops } from './control.ts';
|
|
5
6
|
import type { FreezerRuntime } from './freezer/index.ts';
|
|
@@ -27,6 +28,7 @@ export interface AgentHost {
|
|
|
27
28
|
readonly agent: Agent;
|
|
28
29
|
readonly users?: UserClients;
|
|
29
30
|
readonly pages: Pages;
|
|
31
|
+
readonly approvals: Approvals;
|
|
30
32
|
connect(endpoint: PortEndpoint, options?: ConnectOptions): void;
|
|
31
33
|
close(): Promise<void>;
|
|
32
34
|
}
|
|
@@ -54,6 +56,7 @@ export declare function hostAgent(agent: Agent, options?: {
|
|
|
54
56
|
uploads?: Uploads;
|
|
55
57
|
thumbnail?: Thumbnail;
|
|
56
58
|
labels?: LabelsRuntime;
|
|
59
|
+
approvals?: Approvals;
|
|
57
60
|
}): Promise<AgentHost>;
|
|
58
61
|
interface Served {
|
|
59
62
|
trusted: AgentControl;
|
|
@@ -63,6 +66,7 @@ interface Served {
|
|
|
63
66
|
settings: AgentSettings;
|
|
64
67
|
remote: AgentRemote;
|
|
65
68
|
pages: Pages;
|
|
69
|
+
decide: (by: DecidedBy) => AgentControl['decide'];
|
|
66
70
|
}
|
|
67
71
|
export declare function serveAgent(serving: Served): Host;
|
|
68
72
|
export {};
|
package/dist/types/index.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export { ADOBE, ADOBE_PROXY, type AdobeConfig, type AdobeModelInfo, adobeClassifiers, adobeConfig, adobeIdentity, adobeModel, adobeProvider, adobeUsage, type Budget, SESSION_HEADER, VERSION_HEADER, withAdobeIdentity, } from './adobe.ts';
|
|
2
2
|
export { type Agent, type AgentOptions, answerText, openAgent } from './agent.ts';
|
|
3
|
+
export { APPROVAL_MS, type Approval, type ApprovalAnswer, type ApprovalDecided, type ApprovalDraft, type ApprovalKind, type ApprovalRequester, type ApprovalState, type Approvals, ApprovalsDoc, type ApprovalTier, type ApprovalVerdict, attachApprovals, type DecidedBy, REASONS, } from './approvals/index.ts';
|
|
3
4
|
export { FILE_LIMIT, IMAGE_LIMIT, type SendAttachment, type ShownAttachment, splitUser, TOTAL_LIMIT, userParts, } from './attachments.ts';
|
|
4
5
|
export { type AgentConnection, connectAgent } from './client.ts';
|
|
5
6
|
export { createAgentControl } from './control.ts';
|
package/dist/types/services.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { Context, JsonValue, RemoteContract, ReplicatedState } from '@earendil-works/chord';
|
|
2
2
|
import type { ConversationView } from '@earendil-works/pi-durable';
|
|
3
|
+
import type { Approval, ApprovalAnswer, ApprovalDecided } from './approvals/index.ts';
|
|
3
4
|
import type { SendAttachment, ShownAttachment } from './attachments.ts';
|
|
4
5
|
import type { ChangesView } from './changes/git.ts';
|
|
5
6
|
import type { FrozenCone } from './freezer/index.ts';
|
|
@@ -87,6 +88,7 @@ export interface AgentControl {
|
|
|
87
88
|
image(ref: ImageRef, context: Context): Promise<StoredImage>;
|
|
88
89
|
agentCommands(agentId: string, context: Context): Promise<Command[]>;
|
|
89
90
|
toolLabel(agentId: string, callIds: string[], context: Context): Promise<string | null>;
|
|
91
|
+
decide(id: string, decision: ApprovalAnswer, reason: string | null, context: Context): Promise<ApprovalDecided>;
|
|
90
92
|
}
|
|
91
93
|
export interface ImageRef {
|
|
92
94
|
entry: number;
|
|
@@ -231,7 +233,7 @@ export interface AgentSettingsChange {
|
|
|
231
233
|
thinkingLevel: 'off' | 'minimal' | 'low' | 'medium' | 'high' | 'xhigh' | 'max' | null;
|
|
232
234
|
agentId?: string | null;
|
|
233
235
|
}
|
|
234
|
-
export declare const CONTROL_METHODS: ("abort" | "agentCommands" | "changeAccept" | "changeRevert" | "changesOpen" | "compact" | "compactAgent" | "configure" | "createCone" | "createScoop" | "discard" | "drop" | "freeze" | "image" | "memoryRemove" | "memorySave" | "monitorClose" | "monitorOpen" | "newChat" | "reset" | "resolveAgentLick" | "resolveLick" | "rewind" | "rewindAgent" | "selectCone" | "send" | "sprinkleCall" | "sprinkleSend" | "stopAgent" | "thaw" | "toolLabel" | "unqueue" | "wait" | "webhook" | "withdraw")[];
|
|
236
|
+
export declare const CONTROL_METHODS: ("abort" | "agentCommands" | "changeAccept" | "changeRevert" | "changesOpen" | "compact" | "compactAgent" | "configure" | "createCone" | "createScoop" | "decide" | "discard" | "drop" | "freeze" | "image" | "memoryRemove" | "memorySave" | "monitorClose" | "monitorOpen" | "newChat" | "reset" | "resolveAgentLick" | "resolveLick" | "rewind" | "rewindAgent" | "selectCone" | "send" | "sprinkleCall" | "sprinkleSend" | "stopAgent" | "thaw" | "toolLabel" | "unqueue" | "wait" | "webhook" | "withdraw")[];
|
|
235
237
|
export declare const CONTROL_READS: readonly (keyof AgentControl & string)[];
|
|
236
238
|
export declare const AgentControl: RemoteContract;
|
|
237
239
|
export type Delivered = 'run' | 'steer' | 'follow-up';
|
|
@@ -250,6 +252,7 @@ export interface AgentTranscript {
|
|
|
250
252
|
readonly monitor: ReplicatedState<MonitorFeed>;
|
|
251
253
|
readonly vault: ReplicatedState<VaultState>;
|
|
252
254
|
readonly labels: ReplicatedState<Record<string, string>>;
|
|
255
|
+
readonly approvals: ReplicatedState<Approval[]>;
|
|
253
256
|
}
|
|
254
257
|
export interface PrivateRevision {
|
|
255
258
|
revision: number;
|
|
@@ -259,7 +262,7 @@ export interface Command {
|
|
|
259
262
|
description: string;
|
|
260
263
|
kind: 'prompt' | 'skill' | 'action';
|
|
261
264
|
}
|
|
262
|
-
export declare const TRANSCRIPT_STATES: ("agents" | "changes" | "commands" | "deliveries" | "frozen" | "labels" | "memories" | "memoryScopes" | "monitor" | "privateRevision" | "sprinkles" | "state" | "vault" | "views")[];
|
|
265
|
+
export declare const TRANSCRIPT_STATES: ("agents" | "approvals" | "changes" | "commands" | "deliveries" | "frozen" | "labels" | "memories" | "memoryScopes" | "monitor" | "privateRevision" | "sprinkles" | "state" | "vault" | "views")[];
|
|
263
266
|
export declare const AgentTranscript: RemoteContract;
|
|
264
267
|
export declare const REMOTE_METHODS: ("abort" | "close" | "next" | "prompt" | "watch")[];
|
|
265
268
|
export declare const REMOTE_READS: readonly (keyof AgentRemote & string)[];
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { Approval, ApprovalDecision, ApprovalsEvents, ApprovalsPort } from '@ai-ecoverse/slicc-spectrum/ui';
|
|
2
|
+
import type { Approval as Item } from '../approvals/record.ts';
|
|
3
|
+
import type { AgentConnection } from '../client.ts';
|
|
4
|
+
import { Emitter } from './emitter.ts';
|
|
5
|
+
export declare function shown(item: Item, agentName: string | undefined): Approval;
|
|
6
|
+
export type HostApprovals = ApprovalsPort;
|
|
7
|
+
export declare const NOT_HERE = "This request can't be answered in this tab.";
|
|
8
|
+
export declare class ApprovalsAdapter extends Emitter<ApprovalsEvents> implements ApprovalsPort {
|
|
9
|
+
#private;
|
|
10
|
+
readonly decide?: (id: string, decision: ApprovalDecision, reason?: string) => Promise<void>;
|
|
11
|
+
constructor(connection: AgentConnection, host?: HostApprovals);
|
|
12
|
+
list(): readonly Approval[];
|
|
13
|
+
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { MonitorSection } from '@ai-ecoverse/slicc-spectrum/ui';
|
|
2
2
|
import type { AgentConnection } from '../client.ts';
|
|
3
3
|
import { AgentAdapter } from './agent-port.ts';
|
|
4
|
+
import { ApprovalsAdapter, type HostApprovals } from './approvals-port.ts';
|
|
4
5
|
import { ChangesAdapter } from './changes-port.ts';
|
|
5
6
|
import { MemoryAdapter } from './memory-port.ts';
|
|
6
7
|
import { MonitorAdapter } from './monitor-port.ts';
|
|
@@ -10,6 +11,7 @@ import { type Login, SettingsAdapter } from './settings-port.ts';
|
|
|
10
11
|
import { SprinkleAdapter } from './sprinkle-port.ts';
|
|
11
12
|
import { TrayAdapter } from './tray-port.ts';
|
|
12
13
|
export { AgentAdapter, CONE } from './agent-port.ts';
|
|
14
|
+
export { ApprovalsAdapter, type HostApprovals, NOT_HERE, shown as shownApproval, } from './approvals-port.ts';
|
|
13
15
|
export { ChangesAdapter, type ChangesEvents } from './changes-port.ts';
|
|
14
16
|
export { MemoryAdapter } from './memory-port.ts';
|
|
15
17
|
export { assistant, errorAction, errorPart, isBusy, queued, textOf, toMessages, } from './messages.ts';
|
|
@@ -26,9 +28,11 @@ export declare function createAgentModel(connection: AgentConnection, options?:
|
|
|
26
28
|
extra?: () => readonly MonitorSection[];
|
|
27
29
|
};
|
|
28
30
|
page?: PageOptions;
|
|
31
|
+
approvals?: HostApprovals;
|
|
29
32
|
notices?: HostNotices;
|
|
30
33
|
}): {
|
|
31
34
|
agent: AgentAdapter;
|
|
35
|
+
approvals: ApprovalsAdapter;
|
|
32
36
|
settings: SettingsAdapter;
|
|
33
37
|
tray: TrayAdapter;
|
|
34
38
|
sprinkles: SprinkleAdapter;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ai-ecoverse/slicc-agent",
|
|
3
|
-
"version": "5.0
|
|
3
|
+
"version": "5.1.0",
|
|
4
4
|
"description": "SLICC's agent core on pi durable: an agent worker, session storage, remoting and pi extensions",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -64,7 +64,7 @@
|
|
|
64
64
|
"@ai-ecoverse/slicc-kernel": "1.94.0",
|
|
65
65
|
"@ai-ecoverse/slicc-scrub": "1.0.0",
|
|
66
66
|
"@ai-ecoverse/slicc-shared-web": "1.20.0",
|
|
67
|
-
"@ai-ecoverse/slicc-spectrum": "1.
|
|
67
|
+
"@ai-ecoverse/slicc-spectrum": "1.79.0",
|
|
68
68
|
"@ai-ecoverse/wasm-bash": "5.3.0-18",
|
|
69
69
|
"@ai-ecoverse/wasm-coreutils": "9.12.0-6",
|
|
70
70
|
"@ai-ecoverse/wasm-git": "2.55.0-15",
|
|
@@ -91,8 +91,8 @@
|
|
|
91
91
|
"typebox": "1.3.36"
|
|
92
92
|
},
|
|
93
93
|
"peerDependencies": {
|
|
94
|
-
"@ai-ecoverse/slicc-kernel": ">=1.
|
|
95
|
-
"@ai-ecoverse/slicc-spectrum": "^1.
|
|
94
|
+
"@ai-ecoverse/slicc-kernel": ">=1.90.0 <2",
|
|
95
|
+
"@ai-ecoverse/slicc-spectrum": "^1.78.0"
|
|
96
96
|
},
|
|
97
97
|
"peerDependenciesMeta": {
|
|
98
98
|
"@ai-ecoverse/slicc-spectrum": {
|