@spendgraph/tools 0.2.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 +283 -0
- package/dist/builtin/calculate/calculate.d.ts +13 -0
- package/dist/builtin/calculate/calculate.js +27 -0
- package/dist/builtin/calculate/index.d.ts +2 -0
- package/dist/builtin/calculate/index.js +2 -0
- package/dist/builtin/calculate/parse.d.ts +8 -0
- package/dist/builtin/calculate/parse.js +144 -0
- package/dist/builtin/clock/clock.d.ts +27 -0
- package/dist/builtin/clock/clock.js +76 -0
- package/dist/builtin/clock/index.d.ts +1 -0
- package/dist/builtin/clock/index.js +1 -0
- package/dist/builtin/date/date.d.ts +32 -0
- package/dist/builtin/date/date.js +47 -0
- package/dist/builtin/date/index.d.ts +2 -0
- package/dist/builtin/date/index.js +2 -0
- package/dist/builtin/date/shift.d.ts +12 -0
- package/dist/builtin/date/shift.js +62 -0
- package/dist/builtin/deep-recall/deep-recall.d.ts +27 -0
- package/dist/builtin/deep-recall/deep-recall.js +51 -0
- package/dist/builtin/deep-recall/index.d.ts +1 -0
- package/dist/builtin/deep-recall/index.js +1 -0
- package/dist/builtin/escalate/escalate.d.ts +46 -0
- package/dist/builtin/escalate/escalate.js +29 -0
- package/dist/builtin/escalate/index.d.ts +1 -0
- package/dist/builtin/escalate/index.js +1 -0
- package/dist/builtin/finish/finish.d.ts +27 -0
- package/dist/builtin/finish/finish.js +39 -0
- package/dist/builtin/finish/index.d.ts +1 -0
- package/dist/builtin/finish/index.js +1 -0
- package/dist/builtin/http/allow.d.ts +8 -0
- package/dist/builtin/http/allow.js +45 -0
- package/dist/builtin/http/http.d.ts +43 -0
- package/dist/builtin/http/http.js +51 -0
- package/dist/builtin/http/index.d.ts +2 -0
- package/dist/builtin/http/index.js +2 -0
- package/dist/builtin/index.d.ts +11 -0
- package/dist/builtin/index.js +11 -0
- package/dist/builtin/json/index.d.ts +2 -0
- package/dist/builtin/json/index.js +2 -0
- package/dist/builtin/json/json.d.ts +22 -0
- package/dist/builtin/json/json.js +44 -0
- package/dist/builtin/json/path.d.ts +8 -0
- package/dist/builtin/json/path.js +63 -0
- package/dist/builtin/think/index.d.ts +1 -0
- package/dist/builtin/think/index.js +1 -0
- package/dist/builtin/think/think.d.ts +13 -0
- package/dist/builtin/think/think.js +19 -0
- package/dist/builtin/web-search/index.d.ts +1 -0
- package/dist/builtin/web-search/index.js +1 -0
- package/dist/builtin/web-search/reply.d.ts +23 -0
- package/dist/builtin/web-search/reply.js +35 -0
- package/dist/builtin/web-search/web-search.d.ts +50 -0
- package/dist/builtin/web-search/web-search.js +93 -0
- package/dist/builtin/write-document/commission.d.ts +56 -0
- package/dist/builtin/write-document/commission.js +163 -0
- package/dist/builtin/write-document/design.d.ts +49 -0
- package/dist/builtin/write-document/design.js +99 -0
- package/dist/builtin/write-document/http.d.ts +34 -0
- package/dist/builtin/write-document/http.js +74 -0
- package/dist/builtin/write-document/index.d.ts +6 -0
- package/dist/builtin/write-document/index.js +4 -0
- package/dist/builtin/write-document/types.d.ts +33 -0
- package/dist/builtin/write-document/types.js +1 -0
- package/dist/builtin/write-document/write-document.d.ts +69 -0
- package/dist/builtin/write-document/write-document.js +150 -0
- package/dist/bus/bus.d.ts +76 -0
- package/dist/bus/bus.js +103 -0
- package/dist/bus/index.d.ts +3 -0
- package/dist/bus/index.js +2 -0
- package/dist/bus/invoke.d.ts +9 -0
- package/dist/bus/invoke.js +50 -0
- package/dist/bus/options.d.ts +22 -0
- package/dist/bus/options.js +1 -0
- package/dist/bus/overlap.d.ts +12 -0
- package/dist/bus/overlap.js +43 -0
- package/dist/bus/score.d.ts +9 -0
- package/dist/bus/score.js +19 -0
- package/dist/bus/select.d.ts +18 -0
- package/dist/bus/select.js +71 -0
- package/dist/bus/step.d.ts +4 -0
- package/dist/bus/step.js +12 -0
- package/dist/bus/trace.d.ts +42 -0
- package/dist/bus/trace.js +34 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +3 -0
- package/dist/internals.d.ts +16 -0
- package/dist/internals.js +16 -0
- package/dist/tool/bind.d.ts +42 -0
- package/dist/tool/bind.js +89 -0
- package/dist/tool/index.d.ts +4 -0
- package/dist/tool/index.js +2 -0
- package/dist/tool/tool.d.ts +20 -0
- package/dist/tool/tool.js +62 -0
- package/dist/types/index.d.ts +2 -0
- package/dist/types/index.js +1 -0
- package/dist/types/result.d.ts +10 -0
- package/dist/types/result.js +1 -0
- package/dist/types/tool.d.ts +105 -0
- package/dist/types/tool.js +1 -0
- package/dist/wire/index.d.ts +3 -0
- package/dist/wire/index.js +3 -0
- package/dist/wire/json-schema.d.ts +26 -0
- package/dist/wire/json-schema.js +81 -0
- package/dist/wire/markdown.d.ts +9 -0
- package/dist/wire/markdown.js +42 -0
- package/dist/wire/providers.d.ts +26 -0
- package/dist/wire/providers.js +20 -0
- package/package.json +64 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { FieldSpec } from "@spendgraph/sdk";
|
|
2
|
+
export interface JsonSchema {
|
|
3
|
+
type: "object";
|
|
4
|
+
properties: Record<string, JsonSchemaProperty>;
|
|
5
|
+
required: string[];
|
|
6
|
+
}
|
|
7
|
+
export interface JsonSchemaProperty {
|
|
8
|
+
type: "string" | "number" | "boolean" | "array" | "object";
|
|
9
|
+
description?: string;
|
|
10
|
+
enum?: string[];
|
|
11
|
+
default?: string | number | boolean;
|
|
12
|
+
minimum?: number;
|
|
13
|
+
maximum?: number;
|
|
14
|
+
maxLength?: number;
|
|
15
|
+
items?: {
|
|
16
|
+
type: "string";
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
export declare const JSON_TYPE: Record<FieldSpec["type"], JsonSchemaProperty["type"]>;
|
|
20
|
+
/**
|
|
21
|
+
* `FieldSpec[]` as a JSON Schema object.
|
|
22
|
+
*
|
|
23
|
+
* `separator`, `trueText` and `falseText` are dropped: they interpolate a value
|
|
24
|
+
* into a string, which a tool call does not do. So is `datasetKey`.
|
|
25
|
+
*/
|
|
26
|
+
export declare function toJsonSchema(args: FieldSpec[]): JsonSchema;
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
export const JSON_TYPE = {
|
|
2
|
+
string: "string",
|
|
3
|
+
text: "string",
|
|
4
|
+
number: "number",
|
|
5
|
+
boolean: "boolean",
|
|
6
|
+
enum: "string",
|
|
7
|
+
list: "array",
|
|
8
|
+
json: "object",
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* A field's default as a value of its own type.
|
|
12
|
+
*
|
|
13
|
+
* `FieldSpec.default` is already-rendered text, so `"5"` on a number field has
|
|
14
|
+
* to come back as `5` — a schema saying `number` and defaulting to `"5"` is
|
|
15
|
+
* something providers accept and models then copy.
|
|
16
|
+
*
|
|
17
|
+
* `list` and `json` defaults are joined and printed forms that cannot be parsed
|
|
18
|
+
* back, so they are dropped rather than guessed at.
|
|
19
|
+
*/
|
|
20
|
+
function coerceDefault(field) {
|
|
21
|
+
const raw = field.default;
|
|
22
|
+
if (raw === undefined)
|
|
23
|
+
return undefined;
|
|
24
|
+
switch (field.type) {
|
|
25
|
+
case "number": {
|
|
26
|
+
const n = Number(raw);
|
|
27
|
+
return Number.isFinite(n) ? n : undefined;
|
|
28
|
+
}
|
|
29
|
+
case "boolean": {
|
|
30
|
+
const t = raw.trim().toLowerCase();
|
|
31
|
+
if (t === "true" || t === field.trueText?.trim().toLowerCase())
|
|
32
|
+
return true;
|
|
33
|
+
if (t === "false" || t === field.falseText?.trim().toLowerCase())
|
|
34
|
+
return false;
|
|
35
|
+
return undefined;
|
|
36
|
+
}
|
|
37
|
+
case "enum":
|
|
38
|
+
return field.options?.includes(raw) ? raw : undefined;
|
|
39
|
+
case "list":
|
|
40
|
+
case "json":
|
|
41
|
+
return undefined;
|
|
42
|
+
default:
|
|
43
|
+
return raw;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* `FieldSpec[]` as a JSON Schema object.
|
|
48
|
+
*
|
|
49
|
+
* `separator`, `trueText` and `falseText` are dropped: they interpolate a value
|
|
50
|
+
* into a string, which a tool call does not do. So is `datasetKey`.
|
|
51
|
+
*/
|
|
52
|
+
export function toJsonSchema(args) {
|
|
53
|
+
const properties = {};
|
|
54
|
+
for (const field of args) {
|
|
55
|
+
const property = { type: JSON_TYPE[field.type] };
|
|
56
|
+
if (field.description)
|
|
57
|
+
property.description = field.description;
|
|
58
|
+
if (field.type === "enum" && field.options?.length)
|
|
59
|
+
property.enum = [...field.options];
|
|
60
|
+
if (field.type === "list")
|
|
61
|
+
property.items = { type: "string" };
|
|
62
|
+
if (field.type === "number") {
|
|
63
|
+
if (field.min !== undefined)
|
|
64
|
+
property.minimum = field.min;
|
|
65
|
+
if (field.max !== undefined)
|
|
66
|
+
property.maximum = field.max;
|
|
67
|
+
}
|
|
68
|
+
if ((field.type === "string" || field.type === "text") && field.maxLength !== undefined) {
|
|
69
|
+
property.maxLength = field.maxLength;
|
|
70
|
+
}
|
|
71
|
+
const fallback = coerceDefault(field);
|
|
72
|
+
if (fallback !== undefined)
|
|
73
|
+
property.default = fallback;
|
|
74
|
+
properties[field.name] = property;
|
|
75
|
+
}
|
|
76
|
+
return {
|
|
77
|
+
type: "object",
|
|
78
|
+
properties,
|
|
79
|
+
required: args.filter((a) => a.required).map((a) => a.name),
|
|
80
|
+
};
|
|
81
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { ToolDeclaration } from "../types/index.js";
|
|
2
|
+
/**
|
|
3
|
+
* Declarations as markdown, for a model with no tools API.
|
|
4
|
+
*
|
|
5
|
+
* About a quarter cheaper than the JSON, since JSON Schema is mostly
|
|
6
|
+
* scaffolding — but you give up structured tool calls and parse intent out of
|
|
7
|
+
* prose instead. Only worth it where there is no native `tools` array.
|
|
8
|
+
*/
|
|
9
|
+
export declare function toMarkdown(decls: ToolDeclaration[], heading?: string): string;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { JSON_TYPE } from "./json-schema.js";
|
|
2
|
+
/**
|
|
3
|
+
* Neutralises headings inside text about to become markdown.
|
|
4
|
+
*
|
|
5
|
+
* A `###` at the start of a line would close the tool's own section and open one
|
|
6
|
+
* the prompt author never wrote.
|
|
7
|
+
*/
|
|
8
|
+
function escapeHeadings(text) {
|
|
9
|
+
return text.replace(/^(\s*)(#{1,6})(\s|$)/gm, "$1\\$2$3");
|
|
10
|
+
}
|
|
11
|
+
function argLine(field) {
|
|
12
|
+
const type = JSON_TYPE[field.type];
|
|
13
|
+
const notes = [];
|
|
14
|
+
if (field.description)
|
|
15
|
+
notes.push(escapeHeadings(field.description.trim()).replace(/\.$/, ""));
|
|
16
|
+
if (field.type === "enum" && field.options?.length) {
|
|
17
|
+
notes.push(`one of ${field.options.join(", ")}`);
|
|
18
|
+
}
|
|
19
|
+
if (field.type === "number" && (field.min !== undefined || field.max !== undefined)) {
|
|
20
|
+
notes.push(`between ${field.min ?? "any"} and ${field.max ?? "any"}`);
|
|
21
|
+
}
|
|
22
|
+
if (field.default !== undefined)
|
|
23
|
+
notes.push(`defaults to ${field.default}`);
|
|
24
|
+
const head = `- \`${field.name}\` (${type}${field.required ? ", required" : ""})`;
|
|
25
|
+
return notes.length ? `${head} ${notes.join(". ")}.` : `${head}`;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Declarations as markdown, for a model with no tools API.
|
|
29
|
+
*
|
|
30
|
+
* About a quarter cheaper than the JSON, since JSON Schema is mostly
|
|
31
|
+
* scaffolding — but you give up structured tool calls and parse intent out of
|
|
32
|
+
* prose instead. Only worth it where there is no native `tools` array.
|
|
33
|
+
*/
|
|
34
|
+
export function toMarkdown(decls, heading = "## Tools") {
|
|
35
|
+
if (decls.length === 0)
|
|
36
|
+
return "";
|
|
37
|
+
const sections = decls.map((d) => {
|
|
38
|
+
const args = d.args.length ? d.args.map(argLine).join("\n") : "_Takes no arguments._";
|
|
39
|
+
return `### ${d.name}\n${escapeHeadings(d.description)}\n\n${args}`;
|
|
40
|
+
});
|
|
41
|
+
return `${heading}\n\n${sections.join("\n\n")}`;
|
|
42
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { ToolDeclaration } from "../types/index.js";
|
|
2
|
+
import { type JsonSchema } from "./json-schema.js";
|
|
3
|
+
/**
|
|
4
|
+
* A tool as one provider wants it.
|
|
5
|
+
*
|
|
6
|
+
* Envelope work: every provider asks for the same three things differently. It
|
|
7
|
+
* lives here because the easy mistakes — which `FieldSpec` keys map, and which
|
|
8
|
+
* lie about their type — are the same for everyone.
|
|
9
|
+
*/
|
|
10
|
+
export interface AnthropicTool {
|
|
11
|
+
name: string;
|
|
12
|
+
description: string;
|
|
13
|
+
input_schema: JsonSchema;
|
|
14
|
+
}
|
|
15
|
+
export interface OpenAITool {
|
|
16
|
+
type: "function";
|
|
17
|
+
function: {
|
|
18
|
+
name: string;
|
|
19
|
+
description: string;
|
|
20
|
+
parameters: JsonSchema;
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
/** Declarations in the shape the Anthropic Messages API takes. */
|
|
24
|
+
export declare function toAnthropic(decls: ToolDeclaration[]): AnthropicTool[];
|
|
25
|
+
/** Declarations in the shape the OpenAI chat completions API takes. */
|
|
26
|
+
export declare function toOpenAI(decls: ToolDeclaration[]): OpenAITool[];
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { toJsonSchema } from "./json-schema.js";
|
|
2
|
+
/** Declarations in the shape the Anthropic Messages API takes. */
|
|
3
|
+
export function toAnthropic(decls) {
|
|
4
|
+
return decls.map((d) => ({
|
|
5
|
+
name: d.name,
|
|
6
|
+
description: d.description,
|
|
7
|
+
input_schema: toJsonSchema(d.args),
|
|
8
|
+
}));
|
|
9
|
+
}
|
|
10
|
+
/** Declarations in the shape the OpenAI chat completions API takes. */
|
|
11
|
+
export function toOpenAI(decls) {
|
|
12
|
+
return decls.map((d) => ({
|
|
13
|
+
type: "function",
|
|
14
|
+
function: {
|
|
15
|
+
name: d.name,
|
|
16
|
+
description: d.description,
|
|
17
|
+
parameters: toJsonSchema(d.args),
|
|
18
|
+
},
|
|
19
|
+
}));
|
|
20
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@spendgraph/tools",
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "Declare a tool once, offer the right few, and record what was called.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "git+https://github.com/fnLog0/spendgraph.git",
|
|
9
|
+
"directory": "packages/tools"
|
|
10
|
+
},
|
|
11
|
+
"homepage": "https://github.com/fnLog0/spendgraph#readme",
|
|
12
|
+
"bugs": {
|
|
13
|
+
"url": "https://github.com/fnLog0/spendgraph/issues"
|
|
14
|
+
},
|
|
15
|
+
"keywords": [
|
|
16
|
+
"llm",
|
|
17
|
+
"tools",
|
|
18
|
+
"function-calling",
|
|
19
|
+
"agent",
|
|
20
|
+
"anthropic",
|
|
21
|
+
"openai"
|
|
22
|
+
],
|
|
23
|
+
"type": "module",
|
|
24
|
+
"main": "./dist/index.js",
|
|
25
|
+
"types": "./dist/index.d.ts",
|
|
26
|
+
"exports": {
|
|
27
|
+
".": {
|
|
28
|
+
"types": "./dist/index.d.ts",
|
|
29
|
+
"import": "./dist/index.js"
|
|
30
|
+
},
|
|
31
|
+
"./wire": {
|
|
32
|
+
"types": "./dist/wire/index.d.ts",
|
|
33
|
+
"import": "./dist/wire/index.js"
|
|
34
|
+
},
|
|
35
|
+
"./internals": {
|
|
36
|
+
"types": "./dist/internals.d.ts",
|
|
37
|
+
"import": "./dist/internals.js"
|
|
38
|
+
},
|
|
39
|
+
"./package.json": "./package.json"
|
|
40
|
+
},
|
|
41
|
+
"files": [
|
|
42
|
+
"dist",
|
|
43
|
+
"README.md"
|
|
44
|
+
],
|
|
45
|
+
"scripts": {
|
|
46
|
+
"build": "tsc -p tsconfig.json",
|
|
47
|
+
"test": "vitest run",
|
|
48
|
+
"examples": "npm run build && node examples/02-select/01-shortlist.mjs"
|
|
49
|
+
},
|
|
50
|
+
"dependencies": {
|
|
51
|
+
"@locusgraph/client": "^0.8.1",
|
|
52
|
+
"@spendgraph/sdk": "^0.2.0"
|
|
53
|
+
},
|
|
54
|
+
"devDependencies": {
|
|
55
|
+
"@spendgraph/prompt": "^0.2.0",
|
|
56
|
+
"typescript": "^5"
|
|
57
|
+
},
|
|
58
|
+
"engines": {
|
|
59
|
+
"node": ">=18"
|
|
60
|
+
},
|
|
61
|
+
"publishConfig": {
|
|
62
|
+
"access": "public"
|
|
63
|
+
}
|
|
64
|
+
}
|