@graview/tools 0.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/LICENSE +96 -0
- package/README.md +47 -0
- package/dist/agent/adapters.d.ts +43 -0
- package/dist/agent/adapters.d.ts.map +1 -0
- package/dist/agent/adapters.js +52 -0
- package/dist/agent/adapters.js.map +1 -0
- package/dist/agent/tools.d.ts +105 -0
- package/dist/agent/tools.d.ts.map +1 -0
- package/dist/agent/tools.js +311 -0
- package/dist/agent/tools.js.map +1 -0
- package/dist/cli.d.ts +37 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +306 -0
- package/dist/cli.js.map +1 -0
- package/dist/conversation.d.ts +108 -0
- package/dist/conversation.d.ts.map +1 -0
- package/dist/conversation.js +698 -0
- package/dist/conversation.js.map +1 -0
- package/dist/decide.d.ts +43 -0
- package/dist/decide.d.ts.map +1 -0
- package/dist/decide.js +125 -0
- package/dist/decide.js.map +1 -0
- package/dist/derive.d.ts +84 -0
- package/dist/derive.d.ts.map +1 -0
- package/dist/derive.js +302 -0
- package/dist/derive.js.map +1 -0
- package/dist/edit.d.ts +70 -0
- package/dist/edit.d.ts.map +1 -0
- package/dist/edit.js +97 -0
- package/dist/edit.js.map +1 -0
- package/dist/figure.d.ts +53 -0
- package/dist/figure.d.ts.map +1 -0
- package/dist/figure.js +86 -0
- package/dist/figure.js.map +1 -0
- package/dist/index.d.ts +44 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +31 -0
- package/dist/index.js.map +1 -0
- package/dist/intelligence.d.ts +132 -0
- package/dist/intelligence.d.ts.map +1 -0
- package/dist/intelligence.js +463 -0
- package/dist/intelligence.js.map +1 -0
- package/dist/local.d.ts +192 -0
- package/dist/local.d.ts.map +1 -0
- package/dist/local.js +365 -0
- package/dist/local.js.map +1 -0
- package/dist/loop.d.ts +84 -0
- package/dist/loop.d.ts.map +1 -0
- package/dist/loop.js +173 -0
- package/dist/loop.js.map +1 -0
- package/dist/mcp-stdio.d.ts +38 -0
- package/dist/mcp-stdio.d.ts.map +1 -0
- package/dist/mcp-stdio.js +83 -0
- package/dist/mcp-stdio.js.map +1 -0
- package/dist/pins.d.ts +29 -0
- package/dist/pins.d.ts.map +1 -0
- package/dist/pins.js +60 -0
- package/dist/pins.js.map +1 -0
- package/dist/plan.d.ts +150 -0
- package/dist/plan.d.ts.map +1 -0
- package/dist/plan.js +303 -0
- package/dist/plan.js.map +1 -0
- package/dist/providers/insight.d.ts +14 -0
- package/dist/providers/insight.d.ts.map +1 -0
- package/dist/providers/insight.js +81 -0
- package/dist/providers/insight.js.map +1 -0
- package/dist/providers/invariant.d.ts +14 -0
- package/dist/providers/invariant.d.ts.map +1 -0
- package/dist/providers/invariant.js +123 -0
- package/dist/providers/invariant.js.map +1 -0
- package/dist/providers/jev.d.ts +115 -0
- package/dist/providers/jev.d.ts.map +1 -0
- package/dist/providers/jev.js +148 -0
- package/dist/providers/jev.js.map +1 -0
- package/dist/providers/lens.d.ts +24 -0
- package/dist/providers/lens.d.ts.map +1 -0
- package/dist/providers/lens.js +36 -0
- package/dist/providers/lens.js.map +1 -0
- package/dist/providers/llm.d.ts +25 -0
- package/dist/providers/llm.d.ts.map +1 -0
- package/dist/providers/llm.js +44 -0
- package/dist/providers/llm.js.map +1 -0
- package/dist/providers/schema.d.ts +12 -0
- package/dist/providers/schema.d.ts.map +1 -0
- package/dist/providers/schema.js +508 -0
- package/dist/providers/schema.js.map +1 -0
- package/dist/providers/structure.d.ts +14 -0
- package/dist/providers/structure.d.ts.map +1 -0
- package/dist/providers/structure.js +211 -0
- package/dist/providers/structure.js.map +1 -0
- package/dist/questions.d.ts +162 -0
- package/dist/questions.d.ts.map +1 -0
- package/dist/questions.js +316 -0
- package/dist/questions.js.map +1 -0
- package/dist/run.d.ts +202 -0
- package/dist/run.d.ts.map +1 -0
- package/dist/run.js +453 -0
- package/dist/run.js.map +1 -0
- package/dist/space.d.ts +50 -0
- package/dist/space.d.ts.map +1 -0
- package/dist/space.js +55 -0
- package/dist/space.js.map +1 -0
- package/dist/types.d.ts +122 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/usage.d.ts +10 -0
- package/dist/usage.d.ts.map +1 -0
- package/dist/usage.js +59 -0
- package/dist/usage.js.map +1 -0
- package/package.json +61 -0
|
@@ -0,0 +1,463 @@
|
|
|
1
|
+
import { argShape, formFields, labelOf, nodeRefArgs, } from "@graview/core";
|
|
2
|
+
/**
|
|
3
|
+
* THE FIRST WHOLE JSON OBJECT IN AN ANSWER, or nothing.
|
|
4
|
+
*
|
|
5
|
+
* Models fence code, apologise first, explain afterwards and — often
|
|
6
|
+
* enough to matter — close one brace too many. Taking everything between
|
|
7
|
+
* the first `{` and the last `}` swallowed the extra, `JSON.parse` threw,
|
|
8
|
+
* and the caller fell back to showing the person the raw answer: a chat
|
|
9
|
+
* bubble containing `{"say": "Yes", "proposals": [...]}}`, which is the
|
|
10
|
+
* seat handing over its own plumbing.
|
|
11
|
+
*
|
|
12
|
+
* Scanning for the BALANCED close instead reads the object the model meant
|
|
13
|
+
* and ignores whatever it typed after it. Strings and their escapes are
|
|
14
|
+
* respected, or a brace inside a description ends the object early.
|
|
15
|
+
*/
|
|
16
|
+
export function firstJsonObject(answer) {
|
|
17
|
+
/*
|
|
18
|
+
* EITHER SHAPE THE MODEL ACTUALLY USES.
|
|
19
|
+
*
|
|
20
|
+
* Asked for `{"say", "proposals"}`, a model answers with the bare ARRAY
|
|
21
|
+
* of proposals often enough to matter — the sibling seam on this very
|
|
22
|
+
* contract asks for exactly that — and reading from the first `{` found
|
|
23
|
+
* the first PROPOSAL inside the array, returned it as the whole answer,
|
|
24
|
+
* and left the person looking at "…" with a perfectly good list thrown
|
|
25
|
+
* away. Whichever bracket opens first is the value the model meant.
|
|
26
|
+
*/
|
|
27
|
+
const object = answer.indexOf("{");
|
|
28
|
+
const array = answer.indexOf("[");
|
|
29
|
+
const start = array !== -1 && (object === -1 || array < object) ? array : object;
|
|
30
|
+
if (start === -1)
|
|
31
|
+
return undefined;
|
|
32
|
+
const opener = answer[start];
|
|
33
|
+
const closer = opener === "[" ? "]" : "}";
|
|
34
|
+
let depth = 0;
|
|
35
|
+
let inString = false;
|
|
36
|
+
let escaped = false;
|
|
37
|
+
for (let at = start; at < answer.length; at++) {
|
|
38
|
+
const char = answer[at];
|
|
39
|
+
if (inString) {
|
|
40
|
+
if (escaped)
|
|
41
|
+
escaped = false;
|
|
42
|
+
else if (char === "\\")
|
|
43
|
+
escaped = true;
|
|
44
|
+
else if (char === '"')
|
|
45
|
+
inString = false;
|
|
46
|
+
continue;
|
|
47
|
+
}
|
|
48
|
+
if (char === '"')
|
|
49
|
+
inString = true;
|
|
50
|
+
else if (char === opener)
|
|
51
|
+
depth += 1;
|
|
52
|
+
else if (char === closer) {
|
|
53
|
+
depth -= 1;
|
|
54
|
+
if (depth === 0) {
|
|
55
|
+
try {
|
|
56
|
+
return JSON.parse(answer.slice(start, at + 1));
|
|
57
|
+
}
|
|
58
|
+
catch {
|
|
59
|
+
return undefined;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
return undefined;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* A NAME IS NOT AN ID, and a model will hand you a name.
|
|
68
|
+
*
|
|
69
|
+
* Asked to add a field to Meal, a model answers `{"kind": "Meal"}` — the
|
|
70
|
+
* word on the screen rather than the node's id — and the store refuses it
|
|
71
|
+
* for the arguments, in zod's words, under a struck-through line. That is
|
|
72
|
+
* a lookup, not a guess: where EXACTLY ONE node of a kind the argument
|
|
73
|
+
* accepts carries that label, the label means that node. Where two do, or
|
|
74
|
+
* none, the value is left exactly as it came and the form asks.
|
|
75
|
+
*/
|
|
76
|
+
export function resolveProposal(store, proposal) {
|
|
77
|
+
let mutation;
|
|
78
|
+
try {
|
|
79
|
+
mutation = store.mutation(proposal.mutation);
|
|
80
|
+
}
|
|
81
|
+
catch {
|
|
82
|
+
return proposal;
|
|
83
|
+
}
|
|
84
|
+
const args = { ...proposal.args };
|
|
85
|
+
let moved = false;
|
|
86
|
+
for (const field of formFields(mutation.input)) {
|
|
87
|
+
if (field.control !== "node")
|
|
88
|
+
continue;
|
|
89
|
+
const said = args[field.name];
|
|
90
|
+
if (typeof said !== "string" || said.length === 0)
|
|
91
|
+
continue;
|
|
92
|
+
if (store.graph.getNode(said))
|
|
93
|
+
continue;
|
|
94
|
+
const wanted = said.trim().toLowerCase();
|
|
95
|
+
const found = [...store.graph.allNodes()].filter((node) => (field.kinds.includes("*") || field.kinds.includes(node.kind)) &&
|
|
96
|
+
labelOf(store.schema.tryDefinition(node.kind), node).trim().toLowerCase() === wanted);
|
|
97
|
+
if (found.length === 1) {
|
|
98
|
+
args[field.name] = found[0].id;
|
|
99
|
+
moved = true;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
return moved ? { ...proposal, args } : proposal;
|
|
103
|
+
}
|
|
104
|
+
/** A proposal as the store's own call shape, ready for apply/preview. */
|
|
105
|
+
export function toCall(proposal) {
|
|
106
|
+
return { name: proposal.mutation, args: { ...proposal.args } };
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* WHAT THE GATE TOOK OUT, AND WHY — so a seat can say so.
|
|
110
|
+
*
|
|
111
|
+
* `validateProposals` drops silently, which is right for a provider filling
|
|
112
|
+
* the inspector and wrong for a conversation: a model that answers "Sure"
|
|
113
|
+
* and names `add_field` on an app whose act is `add-field` left a person
|
|
114
|
+
* looking at a sentence with nothing under it and no way to know why. The
|
|
115
|
+
* seat can only say what it is told.
|
|
116
|
+
*/
|
|
117
|
+
export function droppedProposals(store, proposals, may) {
|
|
118
|
+
const allowed = may === undefined ? null : new Set(may);
|
|
119
|
+
const out = [];
|
|
120
|
+
for (const proposal of proposals) {
|
|
121
|
+
if (typeof proposal.mutation !== "string")
|
|
122
|
+
continue;
|
|
123
|
+
let known = true;
|
|
124
|
+
try {
|
|
125
|
+
store.mutation(proposal.mutation);
|
|
126
|
+
}
|
|
127
|
+
catch {
|
|
128
|
+
known = false;
|
|
129
|
+
}
|
|
130
|
+
if (!known)
|
|
131
|
+
out.push({ proposal, why: "unknown" });
|
|
132
|
+
else if (allowed && !allowed.has(proposal.mutation))
|
|
133
|
+
out.push({ proposal, why: "not-allowed" });
|
|
134
|
+
}
|
|
135
|
+
return out;
|
|
136
|
+
}
|
|
137
|
+
/** Drops proposals naming unknown or disallowed mutations, with no guessing. */
|
|
138
|
+
export function validateProposals(store, proposals, may) {
|
|
139
|
+
const allowed = may === undefined ? null : new Set(may);
|
|
140
|
+
return proposals.filter((proposal) => {
|
|
141
|
+
if (typeof proposal.mutation !== "string")
|
|
142
|
+
return false;
|
|
143
|
+
if (allowed && !allowed.has(proposal.mutation))
|
|
144
|
+
return false;
|
|
145
|
+
try {
|
|
146
|
+
store.mutation(proposal.mutation);
|
|
147
|
+
}
|
|
148
|
+
catch {
|
|
149
|
+
return false;
|
|
150
|
+
}
|
|
151
|
+
return proposal.args !== null && typeof proposal.args === "object";
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* An LLM as a provider: the model reads a compact statement of the
|
|
156
|
+
* declaration and the current trouble, and answers with calls to declared
|
|
157
|
+
* mutations. Vendor-neutral by construction — the adapter is one async
|
|
158
|
+
* function, so claude/openai/local are one line each in the host.
|
|
159
|
+
*/
|
|
160
|
+
export function llmIntelligence(options) {
|
|
161
|
+
return {
|
|
162
|
+
name: options.name,
|
|
163
|
+
...(options.may ? { may: options.may } : {}),
|
|
164
|
+
async propose(store) {
|
|
165
|
+
const kinds = store.schema.kinds
|
|
166
|
+
.map((kind) => {
|
|
167
|
+
const definition = store.schema.tryDefinition(kind);
|
|
168
|
+
const count = store.graph.nodesOfKind(kind).length;
|
|
169
|
+
return `- ${kind} (${definition?.plural ?? `${kind}s`}, ${count} present): ${definition?.description ?? ""}`;
|
|
170
|
+
})
|
|
171
|
+
.join("\n");
|
|
172
|
+
const mutations = store
|
|
173
|
+
.allMutations()
|
|
174
|
+
.map((mutation) => `- ${mutation.name}: ${mutation.description ?? mutation.title ?? ""}`)
|
|
175
|
+
.join("\n");
|
|
176
|
+
const trouble = store
|
|
177
|
+
.violations()
|
|
178
|
+
.map((violation) => `- ${violation.message}`)
|
|
179
|
+
.join("\n");
|
|
180
|
+
const prompt = [
|
|
181
|
+
"You are proposing changes to a typed context graph.",
|
|
182
|
+
"Kinds:",
|
|
183
|
+
kinds,
|
|
184
|
+
"Mutations you may call:",
|
|
185
|
+
mutations,
|
|
186
|
+
trouble ? `Currently broken:\n${trouble}` : "Nothing is currently broken.",
|
|
187
|
+
'Answer ONLY a JSON array of {"mutation": string, "args": object, "why": string}.',
|
|
188
|
+
].join("\n\n");
|
|
189
|
+
const answer = await options.complete(prompt);
|
|
190
|
+
const match = answer.match(/\[[\s\S]*\]/);
|
|
191
|
+
if (!match)
|
|
192
|
+
return [];
|
|
193
|
+
let parsed;
|
|
194
|
+
try {
|
|
195
|
+
parsed = JSON.parse(match[0]);
|
|
196
|
+
}
|
|
197
|
+
catch {
|
|
198
|
+
return [];
|
|
199
|
+
}
|
|
200
|
+
if (!Array.isArray(parsed))
|
|
201
|
+
return [];
|
|
202
|
+
return validateProposals(store, parsed, options.may);
|
|
203
|
+
},
|
|
204
|
+
};
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* Starter data FROM THE DECLARATION ALONE — the intelligence an empty app
|
|
208
|
+
* has before any key exists. For each mutation that creates a kind with no
|
|
209
|
+
* members yet, synthesise honest arguments off the derived form: sample
|
|
210
|
+
* text, today's date, a bounded number, the first choice. Anything needing
|
|
211
|
+
* a node that does not exist is left for the next round rather than faked.
|
|
212
|
+
*/
|
|
213
|
+
export function templateIntelligence(options = {}) {
|
|
214
|
+
return {
|
|
215
|
+
name: options.name ?? "starter",
|
|
216
|
+
async propose(store) {
|
|
217
|
+
const today = options.today ?? new Date().toISOString().slice(0, 10);
|
|
218
|
+
const proposals = [];
|
|
219
|
+
const fill = (field, hint) => {
|
|
220
|
+
switch (field.control) {
|
|
221
|
+
case "text":
|
|
222
|
+
// "First gardener", not "First label": the field is almost
|
|
223
|
+
// always the thing's name, and the hint is what it names.
|
|
224
|
+
return { ok: true, value: `First ${hint ?? field.name}` };
|
|
225
|
+
case "date":
|
|
226
|
+
return { ok: true, value: field.time ? `${today}T09:00` : today };
|
|
227
|
+
case "number":
|
|
228
|
+
return { ok: true, value: field.min ?? 1 };
|
|
229
|
+
case "boolean":
|
|
230
|
+
return { ok: true, value: false };
|
|
231
|
+
case "choice":
|
|
232
|
+
return field.options?.length
|
|
233
|
+
? { ok: true, value: field.options[0] }
|
|
234
|
+
: { ok: false };
|
|
235
|
+
case "variant": {
|
|
236
|
+
const arm = field.options[0];
|
|
237
|
+
if (!arm)
|
|
238
|
+
return { ok: false };
|
|
239
|
+
const held = { [field.tag]: arm.value };
|
|
240
|
+
for (const child of arm.fields) {
|
|
241
|
+
const answer = fill(child);
|
|
242
|
+
if (!answer.ok && !child.optional)
|
|
243
|
+
return { ok: false };
|
|
244
|
+
if (answer.ok)
|
|
245
|
+
held[child.name] = answer.value;
|
|
246
|
+
}
|
|
247
|
+
return { ok: true, value: held };
|
|
248
|
+
}
|
|
249
|
+
case "group": {
|
|
250
|
+
const held = {};
|
|
251
|
+
for (const child of field.fields) {
|
|
252
|
+
const answer = fill(child);
|
|
253
|
+
if (!answer.ok && !child.optional)
|
|
254
|
+
return { ok: false };
|
|
255
|
+
if (answer.ok)
|
|
256
|
+
held[child.name] = answer.value;
|
|
257
|
+
}
|
|
258
|
+
return { ok: true, value: held };
|
|
259
|
+
}
|
|
260
|
+
default:
|
|
261
|
+
return { ok: false };
|
|
262
|
+
}
|
|
263
|
+
};
|
|
264
|
+
for (const mutation of store.allMutations()) {
|
|
265
|
+
const creates = mutation.creates ?? [];
|
|
266
|
+
const empty = creates.filter((kind) => store.graph.nodesOfKind(kind).length === 0);
|
|
267
|
+
if (empty.length === 0)
|
|
268
|
+
continue;
|
|
269
|
+
const args = {};
|
|
270
|
+
let possible = true;
|
|
271
|
+
for (const field of formFields(mutation.input)) {
|
|
272
|
+
const answer = fill(field, empty[0]);
|
|
273
|
+
if (!answer.ok) {
|
|
274
|
+
if (!field.optional)
|
|
275
|
+
possible = false;
|
|
276
|
+
continue;
|
|
277
|
+
}
|
|
278
|
+
args[field.name] = answer.value;
|
|
279
|
+
}
|
|
280
|
+
if (!possible)
|
|
281
|
+
continue;
|
|
282
|
+
proposals.push({
|
|
283
|
+
mutation: mutation.name,
|
|
284
|
+
args,
|
|
285
|
+
why: `nothing of kind ${empty.join(", ")} exists yet`,
|
|
286
|
+
});
|
|
287
|
+
}
|
|
288
|
+
// Repairs whose arguments the violation already decided.
|
|
289
|
+
for (const violation of store.violations()) {
|
|
290
|
+
const repair = violation.repairs.find((candidate) => !candidate.missing?.length);
|
|
291
|
+
if (!repair)
|
|
292
|
+
continue;
|
|
293
|
+
proposals.push({
|
|
294
|
+
mutation: repair.mutation,
|
|
295
|
+
args: { ...repair.args },
|
|
296
|
+
why: violation.message,
|
|
297
|
+
});
|
|
298
|
+
}
|
|
299
|
+
return validateProposals(store, proposals);
|
|
300
|
+
},
|
|
301
|
+
};
|
|
302
|
+
}
|
|
303
|
+
/**
|
|
304
|
+
* An Intelligence as an affordance provider, for the suggestion surfaces.
|
|
305
|
+
*
|
|
306
|
+
* `deriveAffordances` is synchronous and a model is not, so the wrapper
|
|
307
|
+
* answers from a cache keyed to the log length and refreshes in the
|
|
308
|
+
* background; `notify` tells the host a fresh answer landed (a re-render
|
|
309
|
+
* re-derives). Every suggestion says which provider and why, and applies
|
|
310
|
+
* through the ordinary path — previewable, attributed, undoable.
|
|
311
|
+
*/
|
|
312
|
+
export function intelligenceProvider(intelligence, hooks = {}) {
|
|
313
|
+
let version = -1;
|
|
314
|
+
let pending = false;
|
|
315
|
+
let cached = [];
|
|
316
|
+
return {
|
|
317
|
+
name: "llm",
|
|
318
|
+
derive({ store }) {
|
|
319
|
+
const now = store.log.all().length;
|
|
320
|
+
if (now !== version && !pending) {
|
|
321
|
+
pending = true;
|
|
322
|
+
void intelligence
|
|
323
|
+
.propose(store)
|
|
324
|
+
.then((proposals) => {
|
|
325
|
+
cached = proposals;
|
|
326
|
+
version = now;
|
|
327
|
+
hooks.notify?.();
|
|
328
|
+
})
|
|
329
|
+
.catch(() => {
|
|
330
|
+
cached = [];
|
|
331
|
+
version = now;
|
|
332
|
+
})
|
|
333
|
+
.finally(() => {
|
|
334
|
+
pending = false;
|
|
335
|
+
});
|
|
336
|
+
}
|
|
337
|
+
const affordances = cached.map((proposal, index) => {
|
|
338
|
+
const mutation = store.allMutations().find((m) => m.name === proposal.mutation);
|
|
339
|
+
return {
|
|
340
|
+
id: `llm:${intelligence.name}:${index}`,
|
|
341
|
+
label: mutation?.title ?? proposal.mutation,
|
|
342
|
+
provider: "llm",
|
|
343
|
+
mutation: proposal.mutation,
|
|
344
|
+
args: proposal.args,
|
|
345
|
+
open: [],
|
|
346
|
+
score: 25,
|
|
347
|
+
why: `${intelligence.name}: ${proposal.why ?? "suggested"}`,
|
|
348
|
+
nodeIds: [],
|
|
349
|
+
};
|
|
350
|
+
});
|
|
351
|
+
return { affordances };
|
|
352
|
+
},
|
|
353
|
+
};
|
|
354
|
+
}
|
|
355
|
+
/** Something readable for logs and seats: the provider's own sentence. */
|
|
356
|
+
export function describeProposal(store, proposal) {
|
|
357
|
+
const mutation = store.allMutations().find((m) => m.name === proposal.mutation);
|
|
358
|
+
/*
|
|
359
|
+
* IN THE ACT'S OWN WORDS, when it can say them. "Sow something" under a
|
|
360
|
+
* proposal that already says sunflower and the back bed is the title of
|
|
361
|
+
* the menu entry, not the change on offer — and the act's `describe` is
|
|
362
|
+
* the sentence the activity rail will use once it lands, so the offer
|
|
363
|
+
* and the record read alike. Only for arguments that would actually
|
|
364
|
+
* validate: a describe handed half an answer names "undefined". A name
|
|
365
|
+
* nothing answers to yet — the plot staked out in the same reply — is
|
|
366
|
+
* still a name, and reads as one.
|
|
367
|
+
*/
|
|
368
|
+
if (mutation?.describe) {
|
|
369
|
+
const resolved = resolveProposal(store, proposal);
|
|
370
|
+
const parsed = mutation.input
|
|
371
|
+
.safeParse?.(resolved.args);
|
|
372
|
+
if (parsed?.success) {
|
|
373
|
+
try {
|
|
374
|
+
return mutation.describe(parsed.data, store.graph);
|
|
375
|
+
}
|
|
376
|
+
catch {
|
|
377
|
+
// A describe that cannot read this graph falls back to the title.
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
const subject = mutation?.subject?.arg;
|
|
382
|
+
const id = subject ? proposal.args[subject] : undefined;
|
|
383
|
+
const node = typeof id === "string" ? store.graph.getNode(id) : undefined;
|
|
384
|
+
const title = mutation?.title ?? proposal.mutation;
|
|
385
|
+
return node
|
|
386
|
+
? `${title} — ${labelOf(store.schema.tryDefinition(node.kind), node)}`
|
|
387
|
+
: title;
|
|
388
|
+
}
|
|
389
|
+
/**
|
|
390
|
+
* WHAT A PROPOSAL HAS NOT SAID YET.
|
|
391
|
+
*
|
|
392
|
+
* A responder proposes from the graph and knows nothing of the policy, so
|
|
393
|
+
* the seat asks the store whether the person may do a thing before offering
|
|
394
|
+
* it. It knows just as little about the ACT'S OWN ARGUMENTS — a model told
|
|
395
|
+
* "add a shift called soup kitchen" will happily answer `add-shift` with no
|
|
396
|
+
* arguments at all, or with the label and none of the day, the place and
|
|
397
|
+
* the hours. Applied, the store refuses, and what reaches the person is the
|
|
398
|
+
* validator talking to itself:
|
|
399
|
+
*
|
|
400
|
+
* Refused: Invalid arguments for mutation "add-shift" label: Invalid
|
|
401
|
+
* input: expected string, received undefined; on: Invalid input: …
|
|
402
|
+
*
|
|
403
|
+
* That is not a refusal, it is a stack trace. The act was never impossible;
|
|
404
|
+
* it was under-specified, and the framework already knows what to do with
|
|
405
|
+
* an under-specified act — it asks. A person pressing "Add a shift" from
|
|
406
|
+
* the menu gets the same questions one at a time, with the graph's own
|
|
407
|
+
* candidates offered for anything that names a node.
|
|
408
|
+
*
|
|
409
|
+
* So: the arguments this proposal still owes, in the shape the ask already
|
|
410
|
+
* takes. Empty means it is ready to apply.
|
|
411
|
+
*/
|
|
412
|
+
export function stillNeeded(store, proposal) {
|
|
413
|
+
const mutation = store.allMutations().find((one) => one.name === proposal.mutation);
|
|
414
|
+
if (!mutation)
|
|
415
|
+
return [];
|
|
416
|
+
/*
|
|
417
|
+
* A NAME IS AN ANSWER ONLY WHEN SOMETHING ANSWERS TO IT. A model names
|
|
418
|
+
* things the way a person does, and a proposal to sow into "back bed"
|
|
419
|
+
* made in the same breath as staking it out names a plot that does not
|
|
420
|
+
* exist yet. Resolved now, it may; unresolved, it is still owed — asked
|
|
421
|
+
* for with the graph's candidates rather than refused by the store.
|
|
422
|
+
*/
|
|
423
|
+
proposal = resolveProposal(store, proposal);
|
|
424
|
+
const shape = mutation.input.shape ?? {};
|
|
425
|
+
const refs = nodeRefArgs(mutation.input);
|
|
426
|
+
const owed = [];
|
|
427
|
+
for (const name of Object.keys(shape)) {
|
|
428
|
+
if (optionalArg(shape[name]))
|
|
429
|
+
continue;
|
|
430
|
+
const given = proposal.args[name];
|
|
431
|
+
/*
|
|
432
|
+
* Given means given. A model that answers `""` or `null` for a required
|
|
433
|
+
* field has not answered it — and the empty string is the common one,
|
|
434
|
+
* because a model asked for JSON fills every key it was shown.
|
|
435
|
+
*/
|
|
436
|
+
const ref = refs.find((candidate) => candidate.name === name);
|
|
437
|
+
const answered = given !== undefined &&
|
|
438
|
+
given !== null &&
|
|
439
|
+
given !== "" &&
|
|
440
|
+
(!ref || typeof given !== "string" || store.graph.getNode(given) !== undefined);
|
|
441
|
+
if (answered)
|
|
442
|
+
continue;
|
|
443
|
+
owed.push({
|
|
444
|
+
name,
|
|
445
|
+
...(ref ? { kinds: ref.kinds } : {}),
|
|
446
|
+
...(ref
|
|
447
|
+
? {
|
|
448
|
+
candidates: ref.kinds.includes("*")
|
|
449
|
+
? store.graph.allNodes().map((node) => node.id)
|
|
450
|
+
: ref.kinds.flatMap((kind) => store.graph.nodesOfKind(kind).map((node) => node.id)),
|
|
451
|
+
}
|
|
452
|
+
: {}),
|
|
453
|
+
shape: argShape(mutation.input, name),
|
|
454
|
+
});
|
|
455
|
+
}
|
|
456
|
+
return owed;
|
|
457
|
+
}
|
|
458
|
+
/** Whether an argument may be left out, so it does not count as unanswered. */
|
|
459
|
+
function optionalArg(schema) {
|
|
460
|
+
const type = schema?._def?.type;
|
|
461
|
+
return type === "optional" || type === "default" || type === "nullable";
|
|
462
|
+
}
|
|
463
|
+
//# sourceMappingURL=intelligence.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"intelligence.js","sourceRoot":"","sources":["../src/intelligence.ts"],"names":[],"mappings":"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"}
|
package/dist/local.d.ts
ADDED
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
import { type AnySchema, type IntelligenceCapability } from "@graview/core";
|
|
2
|
+
import { type Responder } from "./conversation.js";
|
|
3
|
+
import type { Completion } from "./intelligence.js";
|
|
4
|
+
import { type Decide } from "./providers/jev.js";
|
|
5
|
+
/**
|
|
6
|
+
* THE INTELLIGENCE LADDER, as configuration a person can climb.
|
|
7
|
+
*
|
|
8
|
+
* Four rungs: the graph answers for itself (keyless, always there); a
|
|
9
|
+
* model runs in the person's own browser (free after the download, and
|
|
10
|
+
* nothing leaves the machine); a decision provider answers typed questions
|
|
11
|
+
* exactly and has no prose; a frontier model answers over the network with
|
|
12
|
+
* the person's own key. The three that talk are the same Responder
|
|
13
|
+
* contract, and the one that does not says so in its answers — so choosing
|
|
14
|
+
* a rung is choosing a config value, and whatever answers, its proposals
|
|
15
|
+
* still travel the one validated path.
|
|
16
|
+
*
|
|
17
|
+
* The config is plain serialisable data in the BROWSER's storage, because
|
|
18
|
+
* an API key belongs to the person at the keyboard: it must never sit in a
|
|
19
|
+
* repo, a bundle, or a declaration that ships.
|
|
20
|
+
*/
|
|
21
|
+
export type IntelligenceSource = "graph" | "local" | "decision" | "remote";
|
|
22
|
+
export interface IntelligenceConfig {
|
|
23
|
+
readonly source: IntelligenceSource;
|
|
24
|
+
readonly local?: {
|
|
25
|
+
/** A WebLLM model id. The default is small enough to be honest about. */
|
|
26
|
+
readonly model?: string;
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
* THE DECISION RUNG: a provider that answers typed questions exactly
|
|
30
|
+
* and has no prose. Reached with the person's own key straight from
|
|
31
|
+
* this browser, or through the dev server's decision door — which holds
|
|
32
|
+
* the key on its side, so a browser never does. With neither, the
|
|
33
|
+
* default is the door at its default path.
|
|
34
|
+
*/
|
|
35
|
+
readonly decision?: {
|
|
36
|
+
readonly apiKey?: string;
|
|
37
|
+
/** The door's path when the key is on the server side. */
|
|
38
|
+
readonly bridge?: string;
|
|
39
|
+
readonly model?: string;
|
|
40
|
+
};
|
|
41
|
+
readonly remote?: {
|
|
42
|
+
readonly preset?: "xai" | "custom";
|
|
43
|
+
/** For `custom`: any OpenAI-compatible /chat/completions endpoint. */
|
|
44
|
+
readonly baseUrl?: string;
|
|
45
|
+
readonly apiKey: string;
|
|
46
|
+
readonly model?: string;
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
export declare const DEFAULT_INTELLIGENCE: IntelligenceConfig;
|
|
50
|
+
/**
|
|
51
|
+
* FOUR RUNGS, TWO AXES. Each rung says which capabilities it serves; a
|
|
52
|
+
* surface asks for a capability, never for a rung; and what the chosen
|
|
53
|
+
* rung cannot serve falls DOWN to the graph, which is keyless and always
|
|
54
|
+
* there. Pretending the ladder has one axis is how a switch starts lying:
|
|
55
|
+
* a decision provider is the best rung for a decision and no rung at all
|
|
56
|
+
* for prose.
|
|
57
|
+
*/
|
|
58
|
+
export declare const RUNGS: Readonly<Record<IntelligenceSource, {
|
|
59
|
+
readonly label: string;
|
|
60
|
+
readonly serves: readonly IntelligenceCapability[];
|
|
61
|
+
}>>;
|
|
62
|
+
/**
|
|
63
|
+
* Which rung answers a capability under this config: the chosen one when
|
|
64
|
+
* it serves the capability, the graph otherwise — with `fell` saying so,
|
|
65
|
+
* which is what a seat's honesty sentence is made of.
|
|
66
|
+
*/
|
|
67
|
+
export declare function rungFor(config: IntelligenceConfig, capability: IntelligenceCapability): {
|
|
68
|
+
readonly rung: IntelligenceSource;
|
|
69
|
+
readonly fell: boolean;
|
|
70
|
+
};
|
|
71
|
+
/** The sentence a seat says on a rung that cannot talk. Part of the answer, not chrome. */
|
|
72
|
+
export declare function rungHonesty(config: IntelligenceConfig, capability: IntelligenceCapability): string | undefined;
|
|
73
|
+
/** The saved rung, or the keyless default — never a throw. */
|
|
74
|
+
export declare function loadIntelligenceConfig(): IntelligenceConfig;
|
|
75
|
+
export declare function saveIntelligenceConfig(config: IntelligenceConfig): void;
|
|
76
|
+
type FetchLike = (input: string, init: {
|
|
77
|
+
method: string;
|
|
78
|
+
headers: Record<string, string>;
|
|
79
|
+
body: string;
|
|
80
|
+
signal?: AbortSignal;
|
|
81
|
+
}) => Promise<{
|
|
82
|
+
ok: boolean;
|
|
83
|
+
status: number;
|
|
84
|
+
json(): Promise<unknown>;
|
|
85
|
+
text(): Promise<string>;
|
|
86
|
+
}>;
|
|
87
|
+
/**
|
|
88
|
+
* Any OpenAI-compatible /chat/completions endpoint as one Completion.
|
|
89
|
+
* The call goes STRAIGHT from the browser to the provider — the key is
|
|
90
|
+
* sent nowhere else, and there is no relay to trust.
|
|
91
|
+
*/
|
|
92
|
+
export declare function openAiCompatibleCompletion(options: {
|
|
93
|
+
readonly baseUrl: string;
|
|
94
|
+
readonly apiKey: string;
|
|
95
|
+
readonly model: string;
|
|
96
|
+
/** Injectable for tests. */
|
|
97
|
+
readonly fetch?: FetchLike;
|
|
98
|
+
}): Completion;
|
|
99
|
+
/** xAI's Grok, as a preset of the same shape. */
|
|
100
|
+
export declare function xaiCompletion(options: {
|
|
101
|
+
readonly apiKey: string;
|
|
102
|
+
readonly model?: string;
|
|
103
|
+
readonly fetch?: FetchLike;
|
|
104
|
+
}): Completion;
|
|
105
|
+
/** What the local rung is doing, for a UI that wants to say so. */
|
|
106
|
+
export interface LocalStatus {
|
|
107
|
+
readonly state: "cold" | "warming" | "ready" | "failed";
|
|
108
|
+
/** 0–1 while warming, when the engine reports progress. */
|
|
109
|
+
readonly progress?: number;
|
|
110
|
+
readonly detail?: string;
|
|
111
|
+
}
|
|
112
|
+
interface EngineLike {
|
|
113
|
+
chat: {
|
|
114
|
+
completions: {
|
|
115
|
+
create(options: {
|
|
116
|
+
messages: {
|
|
117
|
+
role: string;
|
|
118
|
+
content: string;
|
|
119
|
+
}[];
|
|
120
|
+
}): Promise<{
|
|
121
|
+
choices?: {
|
|
122
|
+
message?: {
|
|
123
|
+
content?: string;
|
|
124
|
+
};
|
|
125
|
+
}[];
|
|
126
|
+
}>;
|
|
127
|
+
};
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
export declare function localCompletion(options?: {
|
|
131
|
+
readonly model?: string;
|
|
132
|
+
readonly onStatus?: (status: LocalStatus) => void;
|
|
133
|
+
/** Injectable for tests: replaces the whole engine bring-up. */
|
|
134
|
+
readonly load?: () => Promise<EngineLike>;
|
|
135
|
+
}): {
|
|
136
|
+
complete: Completion;
|
|
137
|
+
ready: () => boolean;
|
|
138
|
+
warm: () => void;
|
|
139
|
+
};
|
|
140
|
+
/**
|
|
141
|
+
* THE MODEL BEHIND A RUNG, when the person has chosen one.
|
|
142
|
+
*
|
|
143
|
+
* A conversation is not the only thing a model is good for: drawing a
|
|
144
|
+
* kind's figure is one prompt and one answer, judged by the checker's own
|
|
145
|
+
* function. Both reach the same configured provider through this, so there
|
|
146
|
+
* is one place a key is read and one place a rung is honoured — and a
|
|
147
|
+
* keyless config answers `undefined` rather than a completion that throws,
|
|
148
|
+
* so a caller can say what it will do INSTEAD of drawing.
|
|
149
|
+
*/
|
|
150
|
+
export declare function completionFor(config: IntelligenceConfig, hooks?: {
|
|
151
|
+
readonly onStatus?: (status: LocalStatus) => void;
|
|
152
|
+
}): Completion | undefined;
|
|
153
|
+
/**
|
|
154
|
+
* One Responder from one config. The graph is always the floor: a remote
|
|
155
|
+
* failure or a cold local model answers from the graph WITH A NOTE rather
|
|
156
|
+
* than failing the conversation — a chat that errors where it could have
|
|
157
|
+
* answered is worse than either rung alone.
|
|
158
|
+
*/
|
|
159
|
+
export declare function configuredResponder<S extends AnySchema>(config: IntelligenceConfig, hooks?: {
|
|
160
|
+
readonly onStatus?: (status: LocalStatus) => void;
|
|
161
|
+
/**
|
|
162
|
+
* The rung below every model, when a surface has one of its own. The
|
|
163
|
+
* studio's floor answers about the DECLARATION — what kinds there are,
|
|
164
|
+
* what an act writes — which the ordinary graph responder cannot know
|
|
165
|
+
* to say; passing it here means the studio climbs the same ladder
|
|
166
|
+
* rather than growing a second one beside it.
|
|
167
|
+
*/
|
|
168
|
+
readonly floor?: Responder<S>;
|
|
169
|
+
/**
|
|
170
|
+
* WHAT THE SETTING IS NOW, asked after the answer lands. A person who
|
|
171
|
+
* switches rungs while a turn is in flight gets the answer the old
|
|
172
|
+
* rung was making — and is told so, in the answer, rather than
|
|
173
|
+
* watching a turn quietly finish on a rung they left.
|
|
174
|
+
*/
|
|
175
|
+
readonly current?: () => IntelligenceConfig;
|
|
176
|
+
}): Responder<S>;
|
|
177
|
+
/**
|
|
178
|
+
* THE DECISION BEHIND A RUNG, for a surface that asks for one — a field
|
|
179
|
+
* that wants filling, a matrix that wants judging. On the decision rung
|
|
180
|
+
* it is the provider exactly, by the person's key or through the dev
|
|
181
|
+
* server's door; on a model rung it is the model with the parse-and-refuse
|
|
182
|
+
* layer behind it; on the graph rung it is nothing here, because the
|
|
183
|
+
* graph decides by its own rules and needs the store to do it
|
|
184
|
+
* (`graphDecide`). A surface holding `undefined` falls down to that.
|
|
185
|
+
*/
|
|
186
|
+
export declare function decideFor(config: IntelligenceConfig, hooks?: {
|
|
187
|
+
readonly onStatus?: (status: LocalStatus) => void;
|
|
188
|
+
}): Decide | undefined;
|
|
189
|
+
/** A word for the header: where answers are coming from right now. */
|
|
190
|
+
export declare function describeIntelligence(config: IntelligenceConfig): string;
|
|
191
|
+
export {};
|
|
192
|
+
//# sourceMappingURL=local.d.ts.map
|