logisheets-logician 1.11.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.
Files changed (49) hide show
  1. package/README.md +89 -0
  2. package/dist/agent/loop.d.ts +101 -0
  3. package/dist/agent/loop.js +260 -0
  4. package/dist/conversation.d.ts +105 -0
  5. package/dist/conversation.js +10 -0
  6. package/dist/craft-interactions-api.d.ts +81 -0
  7. package/dist/craft-interactions-api.js +25 -0
  8. package/dist/craft-interactions-core.d.ts +14 -0
  9. package/dist/craft-interactions-core.js +33 -0
  10. package/dist/crafts/manifest.d.ts +39 -0
  11. package/dist/crafts/manifest.js +10 -0
  12. package/dist/crafts/skill-tools.d.ts +33 -0
  13. package/dist/crafts/skill-tools.js +146 -0
  14. package/dist/crafts/store.d.ts +47 -0
  15. package/dist/crafts/store.js +69 -0
  16. package/dist/index.d.ts +22 -0
  17. package/dist/index.js +22 -0
  18. package/dist/index.node.js +5065 -0
  19. package/dist/projection.d.ts +129 -0
  20. package/dist/projection.js +249 -0
  21. package/dist/storage.d.ts +99 -0
  22. package/dist/storage.js +223 -0
  23. package/dist/tool.d.ts +137 -0
  24. package/dist/tool.js +57 -0
  25. package/dist/tools/block-ops.d.ts +30 -0
  26. package/dist/tools/block-ops.js +97 -0
  27. package/dist/tools/builder.d.ts +206 -0
  28. package/dist/tools/builder.js +1502 -0
  29. package/dist/tools/cells.d.ts +58 -0
  30. package/dist/tools/cells.js +263 -0
  31. package/dist/tools/comments.d.ts +54 -0
  32. package/dist/tools/comments.js +234 -0
  33. package/dist/tools/craft-interactions.d.ts +22 -0
  34. package/dist/tools/craft-interactions.js +454 -0
  35. package/dist/tools/edit.d.ts +55 -0
  36. package/dist/tools/edit.js +356 -0
  37. package/dist/tools/format.d.ts +58 -0
  38. package/dist/tools/format.js +208 -0
  39. package/dist/tools/history.d.ts +13 -0
  40. package/dist/tools/history.js +39 -0
  41. package/dist/tools/inspect.d.ts +93 -0
  42. package/dist/tools/inspect.js +488 -0
  43. package/dist/tools/links.d.ts +30 -0
  44. package/dist/tools/links.js +122 -0
  45. package/dist/tools/structure.d.ts +62 -0
  46. package/dist/tools/structure.js +174 -0
  47. package/dist/tools/taxonomy.d.ts +32 -0
  48. package/dist/tools/taxonomy.js +93 -0
  49. package/package.json +53 -0
@@ -0,0 +1,33 @@
1
+ /**
2
+ * A {@link CraftInteractionsApi} implementation backed directly by
3
+ * logisheets-core's craft-interactions singletons.
4
+ *
5
+ * Use this when logician runs IN-PROCESS with the engine logic — i.e. a Node
6
+ * runtime (logisheets-runtime), or any non-iframe host. The browser/Watson
7
+ * path still uses the window-global adapter, because a craft iframe has its
8
+ * own module instances and must bridge to the *host page's* singletons across
9
+ * the iframe boundary; importing core there would yield a fresh, isolated
10
+ * store. In-process (Node), there is no boundary, so delegating straight to
11
+ * core is correct and removes the window dependency entirely.
12
+ */
13
+ import { registerRadioBinding, clearRadioBindings, getRadioSelection, registerMultiSelectBinding, setMultiSelectMax, clearMultiSelectBindings, getMultiSelectSelections, registerPointAllocator, setPointPool, clearPointAllocators, getPointPool, getPointAllocations, registerPercentAllocator, clearPercentAllocators, registerNumberSlider, clearNumberSliders, } from 'logisheets-core';
14
+ export function createCoreCraftInteractions() {
15
+ return {
16
+ registerRadio: (b) => registerRadioBinding({ type: 'radio', ...b }),
17
+ registerMultiSelect: (b) => registerMultiSelectBinding({ type: 'multiSelect', ...b }),
18
+ setMultiSelectMax: (groupId, max) => setMultiSelectMax(groupId, max),
19
+ registerPointAllocator: (b) => registerPointAllocator({ type: 'pointAllocator', ...b }),
20
+ setPointPool: (groupId, total) => setPointPool(groupId, total),
21
+ registerPercentAllocator: (b) => registerPercentAllocator({ type: 'percentAllocator', ...b }),
22
+ registerNumberSlider: (b) => registerNumberSlider({ type: 'numberSlider', ...b }),
23
+ clearRadios: (groupId) => clearRadioBindings(groupId),
24
+ clearMultiSelects: (groupId) => clearMultiSelectBindings(groupId),
25
+ clearPointAllocators: (groupId) => clearPointAllocators(groupId),
26
+ clearPercentAllocators: (groupId) => clearPercentAllocators(groupId),
27
+ clearNumberSliders: (groupId) => clearNumberSliders(groupId),
28
+ getRadioSelection: (groupId) => getRadioSelection(groupId),
29
+ getMultiSelectSelections: (groupId) => getMultiSelectSelections(groupId),
30
+ getPointPool: (groupId) => getPointPool(groupId),
31
+ getPointAllocations: (groupId) => getPointAllocations(groupId),
32
+ };
33
+ }
@@ -0,0 +1,39 @@
1
+ /**
2
+ * The craft capability manifest — the wire contract Watson reads to discover a
3
+ * craft's skill and invoke its tools. Produced by the `craftsmith` CLI as
4
+ * `dist/manifest.json`. Mirrored here (rather than imported from `craftsmith`)
5
+ * so `logician` stays free of any build-tooling dependency — the same way the
6
+ * `Tool` / JSONSchema shapes are self-contained.
7
+ *
8
+ * Keep in sync with packages/craftsmith/src/manifest.ts.
9
+ */
10
+ import type { JSONSchema, ConfirmationPolicy } from '../tool.js';
11
+ export type MutatesPolicy = 'none' | 'temp' | true;
12
+ export interface ManifestTool {
13
+ name: string;
14
+ description: string;
15
+ inputSchema: JSONSchema;
16
+ outputSchema?: JSONSchema;
17
+ /** Parameter names in call order: fn(ctx, ...paramOrder.map(p => args[p])). */
18
+ paramOrder: string[];
19
+ /** Module the function lives in, relative to the craft package root. */
20
+ entry: string;
21
+ /** Exported binding name = the dispatch key. */
22
+ export: string;
23
+ mutates: MutatesPolicy;
24
+ confirmation: ConfirmationPolicy;
25
+ }
26
+ export interface ManifestSkill {
27
+ description: string;
28
+ guidance?: string;
29
+ }
30
+ export interface CraftManifest {
31
+ schemaVersion: 1;
32
+ craftId: string;
33
+ version: string;
34
+ label: string;
35
+ url?: string;
36
+ rtJs?: string;
37
+ skill?: ManifestSkill;
38
+ tools?: ManifestTool[];
39
+ }
@@ -0,0 +1,10 @@
1
+ /**
2
+ * The craft capability manifest — the wire contract Watson reads to discover a
3
+ * craft's skill and invoke its tools. Produced by the `craftsmith` CLI as
4
+ * `dist/manifest.json`. Mirrored here (rather than imported from `craftsmith`)
5
+ * so `logician` stays free of any build-tooling dependency — the same way the
6
+ * `Tool` / JSONSchema shapes are self-contained.
7
+ *
8
+ * Keep in sync with packages/craftsmith/src/manifest.ts.
9
+ */
10
+ export {};
@@ -0,0 +1,33 @@
1
+ /**
2
+ * The bridge between Watson and installed crafts.
3
+ *
4
+ * Two meta-tools implement progressive discovery (keeps the LLM tool list
5
+ * bounded as the plugin ecosystem grows):
6
+ *
7
+ * skills__discover → list installed crafts + their "when to use me" line
8
+ * skills__use → load one craft's tools into the live registry so the
9
+ * model can call them on the next turn
10
+ *
11
+ * A loaded craft tool dispatches straight to the craft module's named export,
12
+ * passing the same ToolContext the built-in tools receive — which is exactly the
13
+ * craft's `ctx` (workbook / signal / confirm / log). One function, three callers.
14
+ */
15
+ import type { CraftStateAccess, Tool, ToolRegistry } from '../tool.js';
16
+ import type { InstalledCraftStore } from './store.js';
17
+ import type { ManifestTool } from './manifest.js';
18
+ /** Host capability: build a craftState accessor scoped to one craft. */
19
+ export type CraftStateProvider = (craftId: string) => CraftStateAccess;
20
+ export interface CraftSkillToolsOptions {
21
+ /** Wires ctx.craftState for dispatched craft tools, scoped per craft. */
22
+ craftState?: CraftStateProvider;
23
+ }
24
+ /** Build a live Tool that dispatches to a craft module's exported function. */
25
+ export declare function craftToolFromManifest(craftId: string, mt: ManifestTool, store: InstalledCraftStore, craftState?: CraftStateProvider): Tool;
26
+ /**
27
+ * The two discovery/loading meta-tools. Register these into the same registry
28
+ * the Agent uses; `skills__use` registers craft tools into it on demand, and the
29
+ * agent loop re-lists tools every request so they surface immediately.
30
+ */
31
+ export declare function makeCraftSkillTools(store: InstalledCraftStore, registry: ToolRegistry, opts?: CraftSkillToolsOptions): Tool[];
32
+ /** Convenience: build and register the two meta-tools into `registry`. */
33
+ export declare function installCraftSkillTools(store: InstalledCraftStore, registry: ToolRegistry, opts?: CraftSkillToolsOptions): void;
@@ -0,0 +1,146 @@
1
+ /**
2
+ * The bridge between Watson and installed crafts.
3
+ *
4
+ * Two meta-tools implement progressive discovery (keeps the LLM tool list
5
+ * bounded as the plugin ecosystem grows):
6
+ *
7
+ * skills__discover → list installed crafts + their "when to use me" line
8
+ * skills__use → load one craft's tools into the live registry so the
9
+ * model can call them on the next turn
10
+ *
11
+ * A loaded craft tool dispatches straight to the craft module's named export,
12
+ * passing the same ToolContext the built-in tools receive — which is exactly the
13
+ * craft's `ctx` (workbook / signal / confirm / log). One function, three callers.
14
+ */
15
+ import { toolId } from '../tool.js';
16
+ /** Anthropic tool names allow [A-Za-z0-9_-] only — no dots. */
17
+ function sanitizeNamespace(craftId) {
18
+ return craftId.replace(/[^a-zA-Z0-9_-]/g, '_');
19
+ }
20
+ /** Build a live Tool that dispatches to a craft module's exported function. */
21
+ export function craftToolFromManifest(craftId, mt, store, craftState) {
22
+ return {
23
+ namespace: sanitizeNamespace(craftId),
24
+ name: mt.name,
25
+ description: mt.description,
26
+ inputSchema: mt.inputSchema,
27
+ mutates: mt.mutates !== 'none',
28
+ confirmation: mt.confirmation,
29
+ handler: async (input, ctx) => {
30
+ const mod = await store.load(craftId, mt.entry);
31
+ const fn = mod[mt.export];
32
+ if (typeof fn !== 'function')
33
+ throw new Error(`craft "${craftId}" has no exported function "${mt.export}" in ${mt.entry}`);
34
+ const args = mt.paramOrder.map((p) => input === null || input === void 0 ? void 0 : input[p]);
35
+ // Scope craftState to THIS craft before handing the ctx to it.
36
+ const craftCtx = craftState
37
+ ? { ...ctx, craftState: craftState(craftId) }
38
+ : ctx;
39
+ // ctx is the craft's first (host-injected) parameter.
40
+ const data = await fn(craftCtx, ...args);
41
+ return { data: data !== null && data !== void 0 ? data : null };
42
+ },
43
+ };
44
+ }
45
+ const DISCOVER_DESCRIPTION = 'List installed crafts and what each is good at. Call this FIRST when a task ' +
46
+ 'might be handled by a craft/plugin, then call skills__use to load the ' +
47
+ 'chosen craft\'s tools. Optional `query` filters by keyword.';
48
+ const USE_DESCRIPTION = "Load an installed craft's tools into this conversation so you can call them. " +
49
+ 'Pass the `craftId` from skills__discover. Returns the loaded tool names and ' +
50
+ "the craft's usage guidance; the tools become callable on your next step.";
51
+ /**
52
+ * The two discovery/loading meta-tools. Register these into the same registry
53
+ * the Agent uses; `skills__use` registers craft tools into it on demand, and the
54
+ * agent loop re-lists tools every request so they surface immediately.
55
+ */
56
+ export function makeCraftSkillTools(store, registry, opts = {}) {
57
+ const discover = {
58
+ namespace: 'skills',
59
+ name: 'discover',
60
+ description: DISCOVER_DESCRIPTION,
61
+ inputSchema: {
62
+ type: 'object',
63
+ properties: {
64
+ query: {
65
+ type: 'string',
66
+ description: 'Optional keyword to filter crafts by.',
67
+ },
68
+ },
69
+ },
70
+ mutates: false,
71
+ confirmation: 'never',
72
+ handler: async (input) => {
73
+ var _a;
74
+ const rows = await store.list();
75
+ const q = (_a = input === null || input === void 0 ? void 0 : input.query) === null || _a === void 0 ? void 0 : _a.toString().toLowerCase();
76
+ const filtered = q
77
+ ? rows.filter((s) => {
78
+ var _a;
79
+ return `${s.label} ${s.craftId} ${(_a = s.description) !== null && _a !== void 0 ? _a : ''}`
80
+ .toLowerCase()
81
+ .includes(q);
82
+ })
83
+ : rows;
84
+ return {
85
+ data: filtered.map((s) => {
86
+ var _a;
87
+ return ({
88
+ craftId: s.craftId,
89
+ label: s.label,
90
+ when: (_a = s.description) !== null && _a !== void 0 ? _a : null,
91
+ });
92
+ }),
93
+ display: `${filtered.length} craft(s) available`,
94
+ };
95
+ },
96
+ };
97
+ const use = {
98
+ namespace: 'skills',
99
+ name: 'use',
100
+ description: USE_DESCRIPTION,
101
+ inputSchema: {
102
+ type: 'object',
103
+ properties: {
104
+ craftId: {
105
+ type: 'string',
106
+ description: 'The craft to load, from skills__discover.',
107
+ },
108
+ },
109
+ required: ['craftId'],
110
+ },
111
+ mutates: false,
112
+ confirmation: 'never',
113
+ handler: async (input) => {
114
+ var _a, _b, _c, _d;
115
+ const craftId = input === null || input === void 0 ? void 0 : input.craftId;
116
+ if (!craftId)
117
+ throw new Error('craftId is required');
118
+ const manifest = await store.get(craftId);
119
+ if (!manifest)
120
+ throw new Error(`craft "${craftId}" is not installed`);
121
+ const tools = (_a = manifest.tools) !== null && _a !== void 0 ? _a : [];
122
+ const loaded = [];
123
+ for (const mt of tools) {
124
+ const tool = craftToolFromManifest(craftId, mt, store, opts.craftState);
125
+ if (!registry.get(toolId(tool)))
126
+ registry.register(tool);
127
+ loaded.push(toolId(tool));
128
+ }
129
+ return {
130
+ data: {
131
+ craftId,
132
+ label: manifest.label,
133
+ guidance: (_c = (_b = manifest.skill) === null || _b === void 0 ? void 0 : _b.guidance) !== null && _c !== void 0 ? _c : null,
134
+ tools: loaded,
135
+ },
136
+ display: `Loaded ${loaded.length} tool(s) from "${manifest.label}"` +
137
+ (((_d = manifest.skill) === null || _d === void 0 ? void 0 : _d.guidance) ? ' — see guidance' : ''),
138
+ };
139
+ },
140
+ };
141
+ return [discover, use];
142
+ }
143
+ /** Convenience: build and register the two meta-tools into `registry`. */
144
+ export function installCraftSkillTools(store, registry, opts = {}) {
145
+ registry.registerMany(makeCraftSkillTools(store, registry, opts));
146
+ }
@@ -0,0 +1,47 @@
1
+ /**
2
+ * InstalledCraftStore — the host capability that lets Watson enumerate and load
3
+ * installed crafts, VSCode-extension style. The store is platform-specific (web:
4
+ * a DB / IndexedDB + fetch of the built package; desktop: an app-data dir), but
5
+ * this interface is host-neutral so the discover/use tools work everywhere.
6
+ *
7
+ * See docs/craft/craftsmith.md → "Distribution, installation & enumeration".
8
+ */
9
+ import type { CraftManifest } from './manifest.js';
10
+ /** Lightweight row for the discovery list (no tool detail). */
11
+ export interface InstalledCraftSummary {
12
+ craftId: string;
13
+ label: string;
14
+ /** The skill's "when to use me" description, if the craft exposes tools. */
15
+ description?: string;
16
+ }
17
+ export interface InstalledCraftStore {
18
+ /** Enumerate installed crafts — what `discover_skills` iterates. */
19
+ list(): Promise<InstalledCraftSummary[]>;
20
+ /** Full manifest for one craft, or undefined if not installed. */
21
+ get(craftId: string): Promise<CraftManifest | undefined>;
22
+ /**
23
+ * Import a craft module by its manifest-relative entry (e.g. "tools.js") and
24
+ * return its exports. On web this is a dynamic `import()` of the installed
25
+ * package's URL; on desktop a file import. Implementations should cache.
26
+ */
27
+ load(craftId: string, entry: string): Promise<Record<string, unknown>>;
28
+ }
29
+ /**
30
+ * Merge several stores behind one InstalledCraftStore. This is how crafts from
31
+ * different sources coexist: today a single WebCraftStore over the crafts bundled
32
+ * into the app; once a marketplace/registry lands, add a DB-backed store for
33
+ * downloaded crafts — `new CompositeCraftStore([registryStore, bundledStore])` —
34
+ * and both show up in discovery, with no change to the discover/use tools.
35
+ *
36
+ * Precedence is by order: the FIRST store that knows a craftId owns it (so a
37
+ * downloaded craft can shadow a bundled one if its store is listed first). All
38
+ * of a craft's operations (get/load) route to its owning store.
39
+ */
40
+ export declare class CompositeCraftStore implements InstalledCraftStore {
41
+ private readonly stores;
42
+ private owner;
43
+ constructor(stores: readonly InstalledCraftStore[]);
44
+ list(): Promise<InstalledCraftSummary[]>;
45
+ get(craftId: string): Promise<CraftManifest | undefined>;
46
+ load(craftId: string, entry: string): Promise<Record<string, unknown>>;
47
+ }
@@ -0,0 +1,69 @@
1
+ /**
2
+ * InstalledCraftStore — the host capability that lets Watson enumerate and load
3
+ * installed crafts, VSCode-extension style. The store is platform-specific (web:
4
+ * a DB / IndexedDB + fetch of the built package; desktop: an app-data dir), but
5
+ * this interface is host-neutral so the discover/use tools work everywhere.
6
+ *
7
+ * See docs/craft/craftsmith.md → "Distribution, installation & enumeration".
8
+ */
9
+ /**
10
+ * Merge several stores behind one InstalledCraftStore. This is how crafts from
11
+ * different sources coexist: today a single WebCraftStore over the crafts bundled
12
+ * into the app; once a marketplace/registry lands, add a DB-backed store for
13
+ * downloaded crafts — `new CompositeCraftStore([registryStore, bundledStore])` —
14
+ * and both show up in discovery, with no change to the discover/use tools.
15
+ *
16
+ * Precedence is by order: the FIRST store that knows a craftId owns it (so a
17
+ * downloaded craft can shadow a bundled one if its store is listed first). All
18
+ * of a craft's operations (get/load) route to its owning store.
19
+ */
20
+ export class CompositeCraftStore {
21
+ constructor(stores) {
22
+ this.stores = stores;
23
+ this.owner = new Map();
24
+ }
25
+ async list() {
26
+ const seen = new Set();
27
+ const out = [];
28
+ for (const store of this.stores) {
29
+ let rows = [];
30
+ try {
31
+ rows = await store.list();
32
+ }
33
+ catch (_a) {
34
+ rows = []; // one source being down must not sink the rest
35
+ }
36
+ for (const row of rows) {
37
+ if (seen.has(row.craftId))
38
+ continue;
39
+ seen.add(row.craftId);
40
+ this.owner.set(row.craftId, store);
41
+ out.push(row);
42
+ }
43
+ }
44
+ return out;
45
+ }
46
+ async get(craftId) {
47
+ const known = this.owner.get(craftId);
48
+ if (known)
49
+ return known.get(craftId);
50
+ for (const store of this.stores) {
51
+ const m = await store.get(craftId);
52
+ if (m) {
53
+ this.owner.set(craftId, store);
54
+ return m;
55
+ }
56
+ }
57
+ return undefined;
58
+ }
59
+ async load(craftId, entry) {
60
+ let store = this.owner.get(craftId);
61
+ if (!store) {
62
+ await this.get(craftId); // resolve ownership
63
+ store = this.owner.get(craftId);
64
+ }
65
+ if (!store)
66
+ throw new Error(`craft "${craftId}" not found in any installed source`);
67
+ return store.load(craftId, entry);
68
+ }
69
+ }
@@ -0,0 +1,22 @@
1
+ export * from './tool.js';
2
+ export * from './craft-interactions-api.js';
3
+ export * from './craft-interactions-core.js';
4
+ export * from './tools/builder.js';
5
+ export * from './tools/inspect.js';
6
+ export * from './tools/edit.js';
7
+ export * from './tools/cells.js';
8
+ export * from './tools/format.js';
9
+ export * from './tools/structure.js';
10
+ export * from './tools/history.js';
11
+ export * from './tools/comments.js';
12
+ export * from './tools/block-ops.js';
13
+ export * from './tools/links.js';
14
+ export * from './tools/taxonomy.js';
15
+ export * from './tools/craft-interactions.js';
16
+ export * from './crafts/manifest.js';
17
+ export * from './crafts/store.js';
18
+ export * from './crafts/skill-tools.js';
19
+ export * from './conversation.js';
20
+ export * from './storage.js';
21
+ export * from './projection.js';
22
+ export * from './agent/loop.js';
package/dist/index.js ADDED
@@ -0,0 +1,22 @@
1
+ export * from './tool.js';
2
+ export * from './craft-interactions-api.js';
3
+ export * from './craft-interactions-core.js';
4
+ export * from './tools/builder.js';
5
+ export * from './tools/inspect.js';
6
+ export * from './tools/edit.js';
7
+ export * from './tools/cells.js';
8
+ export * from './tools/format.js';
9
+ export * from './tools/structure.js';
10
+ export * from './tools/history.js';
11
+ export * from './tools/comments.js';
12
+ export * from './tools/block-ops.js';
13
+ export * from './tools/links.js';
14
+ export * from './tools/taxonomy.js';
15
+ export * from './tools/craft-interactions.js';
16
+ export * from './crafts/manifest.js';
17
+ export * from './crafts/store.js';
18
+ export * from './crafts/skill-tools.js';
19
+ export * from './conversation.js';
20
+ export * from './storage.js';
21
+ export * from './projection.js';
22
+ export * from './agent/loop.js';