@oneshot-agent/mcp-server 0.49.0 → 0.51.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 +7 -6
- package/dist/index.js +1 -1
- package/dist/tools/annotations.d.ts +4 -2
- package/dist/tools/annotations.js +28 -19
- package/dist/tools/compute.d.ts +0 -5
- package/dist/tools/compute.js +197 -8
- package/dist/tools/connections.d.ts +1 -1
- package/dist/tools/connections.js +1 -1
- package/dist/tools/discover.js +1 -1
- package/dist/tools/domains.js +1 -1
- package/dist/tools/email.js +3 -15
- package/dist/tools/index.js +12 -1
- package/dist/tools/linkedin.js +1 -1
- package/dist/tools/local.js +1 -3
- package/dist/tools/lookup-call.d.ts +13 -0
- package/dist/tools/lookup-call.js +45 -0
- package/dist/tools/lookup-manifest.generated.d.ts +2 -0
- package/dist/tools/lookup-manifest.generated.js +2349 -33
- package/dist/tools/lookup.js +6 -1
- package/dist/tools/predict-schema.generated.d.ts +37 -2
- package/dist/tools/predict-schema.generated.js +52 -3
- package/dist/tools/predict.d.ts +1 -1
- package/dist/tools/predict.js +1 -1
- package/dist/tools/search.js +6 -0
- package/dist/tools/solve-schema.generated.d.ts +2 -8
- package/dist/tools/solve-schema.generated.js +6 -15
- package/dist/tools/untrusted-tools.generated.js +128 -0
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -79,12 +79,12 @@ Every tool is named `oneshot_<name>`. Below are the names.
|
|
|
79
79
|
| [Talk](https://docs.oneshotagent.com/api-reference/email/send) | `email` `voice` `sms` `inbox_list` `inbox_get` `sms_inbox_list` `sms_inbox_get` `notifications` `mark_notification_read` |
|
|
80
80
|
| [Inbound calls](https://docs.oneshotagent.com/api-reference/voice/inbound) | `voice_number_provision` `voice_numbers` `voice_inbound_set` `voice_inbound_disable` `voice_inbound_calls` |
|
|
81
81
|
| [Send from your domains](https://docs.oneshotagent.com/api-reference/email/domains) | `list_domains` `pause_domain` `resume_domain` |
|
|
82
|
-
| [Find people and companies](https://docs.oneshotagent.com/api-reference/research/person-find) | `person_find` `person_profile` `person_email` `person_email_status` `person_dossier` `person_social_accounts` `person_articles` `person_posts` `person_interests` `person_followers` `company_find` `company_profile` `business_find` `business_resolve` `record_solicitations_find` |
|
|
82
|
+
| [Find people and companies](https://docs.oneshotagent.com/api-reference/research/person-find) | `person_find` `person_profile` `person_email` `person_email_status` `person_dossier` `person_social_accounts` `person_articles` `person_posts` `person_interests` `person_followers` `company_find` `company_profile` `company_dossier` `business_find` `business_resolve` `record_solicitations_find` |
|
|
83
83
|
| [Lookups](https://docs.oneshotagent.com/tools-and-goals#lookups) | public records, places, products, vehicles, genes, proteins and more, one tool each |
|
|
84
84
|
| [Think](https://docs.oneshotagent.com/api-reference/research) | `research` `predict` `solve` |
|
|
85
85
|
| [Web and buying](https://docs.oneshotagent.com/api-reference/web-search) | `web_search` `web_read` `browser` `product_find` `commerce_buy` |
|
|
86
86
|
| [Physical mail](https://docs.oneshotagent.com/api-reference/physical-mail/overview) | `physical_mail_upload` `physical_mail_validate_address` `physical_mail_preview` `physical_mail_quote` `physical_mail_approve` `physical_mail_send` `physical_mail_recover` `physical_mail_order` `physical_mail_cancel` |
|
|
87
|
-
| [Connected systems](https://docs.oneshotagent.com/api-reference/connections/overview) | `connections_list` `ledger_invoices` `ledger_bills` `ledger_reports` `crm_accounts` `crm_contacts` `crm_opportunities` `tax_rates` `tax_calculate` `shipping_shipments` `shipping_tracking` `shipping_rates` `procurement_transactions` `procurement_bills` `procurement_suppliers` |
|
|
87
|
+
| [Connected systems](https://docs.oneshotagent.com/api-reference/connections/overview) | `connections_list` `ledger_invoices` `ledger_invoice_lines` `ledger_bills` `ledger_reports` `ledger_bank_transactions` `crm_accounts` `crm_contacts` `crm_opportunities` `crm_tickets` `crm_activity` `tax_rates` `tax_calculate` `shipping_shipments` `shipping_tracking` `shipping_rates` `procurement_transactions` `procurement_bills` `procurement_suppliers` `meetings_list` `meetings_get` `field_service_clients` `field_service_jobs` `field_service_quotes` `field_service_invoices` |
|
|
88
88
|
| [LinkedIn](https://docs.oneshotagent.com/api-reference/linkedin/overview) | `linkedin_connect` `linkedin_accounts` `linkedin_invite` `linkedin_message` `linkedin_reply` and more |
|
|
89
89
|
| [Build](https://docs.oneshotagent.com/api-reference/build/create) | `build` `update_build` |
|
|
90
90
|
| [Goals](https://docs.oneshotagent.com/api-reference/compute/create) | `compute` `compute_status` `compute_tasks` `compute_respond` `compute_pause` `compute_resume` `compute_fund` `compute_cancel` |
|
|
@@ -110,9 +110,10 @@ wallet. The server signs it for you. A read with no proof and no valid token is
|
|
|
110
110
|
## Tool notes
|
|
111
111
|
|
|
112
112
|
- **Email.** Omit `from_domain` and `from_mailbox` and the send rotates across
|
|
113
|
-
your
|
|
114
|
-
|
|
115
|
-
|
|
113
|
+
your domains, each from its main address. `from_mailbox` needs `from_domain`
|
|
114
|
+
and must be one of the domain's addresses. A new `from_domain` or address only
|
|
115
|
+
quotes its setup; nothing is charged or sent. The owner picks the domain's mode
|
|
116
|
+
and addresses when buying it. [Details](https://docs.oneshotagent.com/api-reference/email/send).
|
|
116
117
|
- **Phone lookup** is off by default on `person_find`, `person_profile` and
|
|
117
118
|
`person_dossier`. `include_phone: true` is charged for each person you ask for
|
|
118
119
|
(the search limit, default 100), or once for a profile or dossier, found or not.
|
|
@@ -149,7 +150,7 @@ wallet. The server signs it for you. A read with no proof and no valid token is
|
|
|
149
150
|
|
|
150
151
|
## Tool discovery
|
|
151
152
|
|
|
152
|
-
The MCP catalog contains
|
|
153
|
+
The MCP catalog contains 243 tools. `oneshot_discover_tools` is a free, read-only
|
|
153
154
|
search over the tools your token can call. Call it with no arguments for category
|
|
154
155
|
counts, `{ "query": "send a printed letter" }` to search, or `{ "category": "email" }`
|
|
155
156
|
to browse. Results contain public tool names, purposes and required inputs.
|
package/dist/index.js
CHANGED
|
@@ -50,7 +50,7 @@ async function main() {
|
|
|
50
50
|
const agent = await initAgent();
|
|
51
51
|
const server = new Server({
|
|
52
52
|
name: "oneshot-mcp",
|
|
53
|
-
version: "0.
|
|
53
|
+
version: "0.51.0", // keep in sync with package.json; guarded by version.test.ts
|
|
54
54
|
}, {
|
|
55
55
|
capabilities: {
|
|
56
56
|
tools: {},
|
|
@@ -6,8 +6,10 @@ import type { ToolAnnotations } from "@modelcontextprotocol/sdk/types.js";
|
|
|
6
6
|
*
|
|
7
7
|
* readOnlyHint true = retrieval only (paid lookups included — the only
|
|
8
8
|
* side effect is our own billing)
|
|
9
|
-
* destructiveHint true = deletes, overwrites or revokes something
|
|
10
|
-
*
|
|
9
|
+
* destructiveHint true = deletes, overwrites or revokes something, or is an
|
|
10
|
+
* irreversible send or transaction (a message, call, letter
|
|
11
|
+
* or purchase cannot be taken back). OpenAI's plugin
|
|
12
|
+
* guidelines ask for true on those.
|
|
11
13
|
* openWorldHint true = reaches the public web or third parties;
|
|
12
14
|
* false = only the caller's own OneShot account data.
|
|
13
15
|
*/
|
|
@@ -1,38 +1,47 @@
|
|
|
1
1
|
import { LOOKUP_MANIFEST, ROUTE_MANIFEST } from "./lookup-manifest.generated.js";
|
|
2
2
|
/** Retrieval only. */
|
|
3
3
|
const read = (title, openWorld) => ({ title, readOnlyHint: true, destructiveHint: false, openWorldHint: openWorld });
|
|
4
|
-
/** Changes something. `destructive`
|
|
4
|
+
/** Changes something. `destructive` for delete / overwrite / revoke and for irreversible sends and transactions. */
|
|
5
5
|
const write = (title, openWorld, destructive = false) => ({ title, readOnlyHint: false, destructiveHint: destructive, openWorldHint: openWorld });
|
|
6
|
+
/** Declared routes that cannot be taken back or overwrite settings (a watch's cap and webhook), so destructive. */
|
|
7
|
+
const IRREVERSIBLE_ROUTES = new Set(["physical_mail_approve", "physical_mail_cancel", "identity_start", "watch_update"]);
|
|
8
|
+
/**
|
|
9
|
+
* Free declared routes that still reach outside the account, so open-world: approving a mail quote posts a
|
|
10
|
+
* letter, an identity check sends a person a link, a watch follows third-party data and may call a webhook,
|
|
11
|
+
* and a browser account connection signs in to another site.
|
|
12
|
+
*/
|
|
13
|
+
const OUTBOUND_ROUTES = new Set(["physical_mail_approve", "identity_start", "watch", "watch_update", "browser_connect_account"]);
|
|
6
14
|
/** The connected-system reads (#2403): paid, but each reads the caller's own connected business system, so closed-world. */
|
|
7
|
-
const CONNECTED_SYSTEM_READ = /^\/v1\/tools\/(ledger|crm|shipping|tax|procurement)\//;
|
|
15
|
+
const CONNECTED_SYSTEM_READ = /^\/v1\/tools\/(ledger|crm|shipping|tax|procurement|meetings|mailbox|files|field_service)\//;
|
|
8
16
|
const OPEN = true;
|
|
9
17
|
const OWN = false;
|
|
10
18
|
const DESTRUCTIVE = true;
|
|
11
19
|
export const TOOL_ANNOTATIONS = {
|
|
12
20
|
oneshot_discover_tools: read("Discover tools", OWN),
|
|
21
|
+
oneshot_lookup: read("Run a lookup", OPEN),
|
|
13
22
|
oneshot_solve: read("Solve", OWN),
|
|
14
23
|
oneshot_predict: read("Predict", OWN),
|
|
15
24
|
oneshot_hunt_list: read("List Soul Hunts", OPEN),
|
|
16
25
|
oneshot_hunt_status: read("Get Soul Hunt Status", OPEN),
|
|
17
|
-
oneshot_hunt_predict: write("Predict Soul Hunt", OPEN),
|
|
26
|
+
oneshot_hunt_predict: write("Predict Soul Hunt", OPEN, DESTRUCTIVE), // a submitted prediction cannot be withdrawn
|
|
18
27
|
oneshot_hunt_collection: read("List Collected Souls", OWN),
|
|
19
28
|
oneshot_hunt_leaderboard: read("Soul Hunt Leaderboard", OPEN),
|
|
20
|
-
oneshot_email: write("Send email", OPEN),
|
|
21
|
-
oneshot_voice: write("Place a phone call", OPEN),
|
|
22
|
-
oneshot_sms: write("Send a text message", OPEN),
|
|
29
|
+
oneshot_email: write("Send email", OPEN, DESTRUCTIVE),
|
|
30
|
+
oneshot_voice: write("Place a phone call", OPEN, DESTRUCTIVE),
|
|
31
|
+
oneshot_sms: write("Send a text message", OPEN, DESTRUCTIVE),
|
|
23
32
|
oneshot_inbox_list: read("List received emails", OWN),
|
|
24
33
|
oneshot_inbox_get: read("Read a received email", OWN),
|
|
25
34
|
oneshot_sms_inbox_list: read("List received texts", OWN),
|
|
26
35
|
oneshot_sms_inbox_get: read("Read a received text", OWN),
|
|
27
|
-
oneshot_voice_number_provision: write("Get a phone number", OPEN),
|
|
36
|
+
oneshot_voice_number_provision: write("Get a phone number", OPEN, DESTRUCTIVE),
|
|
28
37
|
oneshot_voice_numbers: read("List phone numbers", OWN),
|
|
29
38
|
oneshot_voice_inbound_set: write("Set up call answering", OPEN, DESTRUCTIVE), // replaces the number's answering settings; outside callers reach it via the carrier
|
|
30
|
-
oneshot_voice_inbound_disable: write("Stop answering calls", OPEN),
|
|
39
|
+
oneshot_voice_inbound_disable: write("Stop answering calls", OPEN, DESTRUCTIVE),
|
|
31
40
|
oneshot_voice_inbound_calls: read("List answered calls", OWN),
|
|
32
41
|
// Physical Mail (#1883): the upload stores artwork in the agent's own account; the send puts a letter in the post.
|
|
33
42
|
// The generated route tools (validate, preview, quote, approve, recover, order, cancel) get their hints from the manifest below.
|
|
34
43
|
oneshot_physical_mail_upload: write("Upload mail artwork", OWN),
|
|
35
|
-
oneshot_physical_mail_send: write("Send approved physical mail", OPEN),
|
|
44
|
+
oneshot_physical_mail_send: write("Send approved physical mail", OPEN, DESTRUCTIVE),
|
|
36
45
|
oneshot_research: read("Deep research", OPEN),
|
|
37
46
|
oneshot_person_find: read("Find people", OPEN),
|
|
38
47
|
oneshot_person_profile: read("Look up a person's profile", OPEN),
|
|
@@ -51,7 +60,7 @@ export const TOOL_ANNOTATIONS = {
|
|
|
51
60
|
oneshot_business_resolve: read("Look up a local business", OPEN),
|
|
52
61
|
oneshot_record_solicitations_find: read("Find government contracts", OPEN),
|
|
53
62
|
oneshot_product_find: read("Search products", OPEN),
|
|
54
|
-
oneshot_commerce_buy: write("Buy a product", OPEN),
|
|
63
|
+
oneshot_commerce_buy: write("Buy a product", OPEN, DESTRUCTIVE),
|
|
55
64
|
oneshot_compute: write("Start a goal", OPEN),
|
|
56
65
|
oneshot_compute_status: read("Check a goal", OWN),
|
|
57
66
|
oneshot_compute_tasks: read("List a goal's tasks", OWN),
|
|
@@ -59,8 +68,8 @@ export const TOOL_ANNOTATIONS = {
|
|
|
59
68
|
oneshot_compute_respond: write("Answer a goal's question", OWN),
|
|
60
69
|
oneshot_compute_pause: write("Pause a goal", OWN),
|
|
61
70
|
oneshot_compute_resume: write("Resume a goal", OWN),
|
|
62
|
-
oneshot_compute_fund: write("Add budget to a goal", OWN),
|
|
63
|
-
oneshot_build: write("Build a website", OPEN),
|
|
71
|
+
oneshot_compute_fund: write("Add budget to a goal", OWN, DESTRUCTIVE),
|
|
72
|
+
oneshot_build: write("Build a website", OPEN, DESTRUCTIVE), // publishes a live site and is paid
|
|
64
73
|
oneshot_update_build: write("Update a website", OPEN, DESTRUCTIVE), // overwrites the live site
|
|
65
74
|
oneshot_browser: write("Browse and act on a website", OPEN),
|
|
66
75
|
oneshot_browser_create_profile: write("Create a browser profile", OWN),
|
|
@@ -72,14 +81,14 @@ export const TOOL_ANNOTATIONS = {
|
|
|
72
81
|
oneshot_linkedin_sync: write("Sync LinkedIn messages", OPEN), // paid; imports history into the account
|
|
73
82
|
oneshot_linkedin_conversations: read("List LinkedIn conversations", OWN),
|
|
74
83
|
oneshot_linkedin_messages: read("Read LinkedIn messages", OWN),
|
|
75
|
-
oneshot_linkedin_reply: write("Reply in a LinkedIn conversation", OPEN),
|
|
76
|
-
oneshot_linkedin_message: write("Message a LinkedIn connection", OPEN),
|
|
84
|
+
oneshot_linkedin_reply: write("Reply in a LinkedIn conversation", OPEN, DESTRUCTIVE),
|
|
85
|
+
oneshot_linkedin_message: write("Message a LinkedIn connection", OPEN, DESTRUCTIVE),
|
|
77
86
|
oneshot_linkedin_invitation: read("Check a LinkedIn invitation", OWN),
|
|
78
87
|
oneshot_linkedin_invitations: read("List LinkedIn invitations", OWN),
|
|
79
|
-
oneshot_linkedin_invite: write("Send a LinkedIn invitation", OPEN),
|
|
88
|
+
oneshot_linkedin_invite: write("Send a LinkedIn invitation", OPEN, DESTRUCTIVE),
|
|
80
89
|
oneshot_linkedin_withdraw_invitation: write("Withdraw a LinkedIn invitation", OPEN, DESTRUCTIVE),
|
|
81
90
|
oneshot_linkedin_view_profile: write("View a LinkedIn profile", OPEN), // notify=true is visible to the person
|
|
82
|
-
oneshot_linkedin_react: write("React to a LinkedIn post", OPEN),
|
|
91
|
+
oneshot_linkedin_react: write("React to a LinkedIn post", OPEN, DESTRUCTIVE),
|
|
83
92
|
oneshot_list_domains: read("List sending domains", OWN),
|
|
84
93
|
oneshot_pause_domain: write("Pause a sending domain", OWN),
|
|
85
94
|
oneshot_resume_domain: write("Resume a sending domain", OWN),
|
|
@@ -92,7 +101,7 @@ export const TOOL_ANNOTATIONS = {
|
|
|
92
101
|
oneshot_mark_notification_read: write("Mark a notification read", OWN),
|
|
93
102
|
oneshot_get_balance: read("Check balance", OWN),
|
|
94
103
|
oneshot_budget_status: read("Check budget", OWN),
|
|
95
|
-
oneshot_approval_create: write("Ask a person to approve", OPEN),
|
|
104
|
+
oneshot_approval_create: write("Ask a person to approve", OPEN, DESTRUCTIVE),
|
|
96
105
|
oneshot_approval_get: read("Check an approval", OWN),
|
|
97
106
|
oneshot_approval_list: read("List approvals", OWN),
|
|
98
107
|
oneshot_approval_cancel: write("Cancel an approval", OWN, DESTRUCTIVE),
|
|
@@ -105,10 +114,10 @@ export const TOOL_ANNOTATIONS = {
|
|
|
105
114
|
// read (Changes, Benchmark) reaches recorded third-party data, a connected-system read the caller's own system; a
|
|
106
115
|
// write changes something, and a DELETE removes it.
|
|
107
116
|
...Object.fromEntries(ROUTE_MANIFEST.map((entry) => {
|
|
108
|
-
const own = !entry.paid || CONNECTED_SYSTEM_READ.test(entry.path);
|
|
117
|
+
const own = (!entry.paid || CONNECTED_SYSTEM_READ.test(entry.path)) && !OUTBOUND_ROUTES.has(entry.name);
|
|
109
118
|
return [
|
|
110
119
|
`oneshot_${entry.name}`,
|
|
111
|
-
entry.readOnly ? read(entry.title, own ? OWN : OPEN) : write(entry.title, own ? OWN : OPEN, entry.method === "DELETE"),
|
|
120
|
+
entry.readOnly ? read(entry.title, own ? OWN : OPEN) : write(entry.title, own ? OWN : OPEN, entry.method === "DELETE" || IRREVERSIBLE_ROUTES.has(entry.name)),
|
|
112
121
|
];
|
|
113
122
|
})),
|
|
114
123
|
};
|
package/dist/tools/compute.d.ts
CHANGED
|
@@ -20,11 +20,6 @@ export declare function handleComputeCancel(agent: OneShot, args: Record<string,
|
|
|
20
20
|
export declare function handleComputeRespond(agent: OneShot, args: Record<string, unknown>): Promise<{
|
|
21
21
|
goal_id: string;
|
|
22
22
|
status: string;
|
|
23
|
-
end_reason: string | null;
|
|
24
|
-
dispute: {
|
|
25
|
-
at: string;
|
|
26
|
-
reason: string;
|
|
27
|
-
};
|
|
28
23
|
} | {
|
|
29
24
|
task_id: string;
|
|
30
25
|
goal_id: string;
|
package/dist/tools/compute.js
CHANGED
|
@@ -1,6 +1,30 @@
|
|
|
1
|
+
const KNOWN_GOAL_TOOL = { type: "string", description: 'A OneShot tool name, e.g. "email", "voice", "commerce_buy"' };
|
|
2
|
+
const SCOPE_DRIVERS = { type: "object", additionalProperties: { anyOf: [{ type: "number" }, { type: "boolean" }, { type: "string" }] }, description: 'Request sizes, never prices: recipients, segments, max_duration_minutes, max_steps (e.g. {"max_steps":25}), include_phone and limit, or letter kind/pages/color/double_sided; Predict/Solve size and time_limit_s. Omitted fields use tool defaults.' };
|
|
3
|
+
const SCOPE_USE = {
|
|
4
|
+
type: "object",
|
|
5
|
+
properties: {
|
|
6
|
+
tool: KNOWN_GOAL_TOOL,
|
|
7
|
+
qty: { type: "integer", minimum: 1, description: "How many times inside one unit" },
|
|
8
|
+
max_attempts: { type: "integer", minimum: 1, description: "Attempts each use may take" },
|
|
9
|
+
drivers: SCOPE_DRIVERS,
|
|
10
|
+
target: { type: "string", description: 'Whom or what the use is pointed at, e.g. "the carrier\'s billing desk"' },
|
|
11
|
+
persistence: {
|
|
12
|
+
type: "object",
|
|
13
|
+
description: "How long a use keeps trying to reach the world, and what happens when it cannot",
|
|
14
|
+
properties: {
|
|
15
|
+
max_attempts: { type: "integer", minimum: 1 },
|
|
16
|
+
spacing_seconds: { type: "integer", minimum: 0, description: "Seconds between two attempts at the same target" },
|
|
17
|
+
escalate_to: KNOWN_GOAL_TOOL,
|
|
18
|
+
then: { type: "string", enum: ["owner", "give_up"], description: "After the last attempt: back to you, or given up as unreached" },
|
|
19
|
+
},
|
|
20
|
+
required: ["max_attempts", "spacing_seconds", "then"],
|
|
21
|
+
},
|
|
22
|
+
},
|
|
23
|
+
required: ["tool", "qty", "max_attempts"],
|
|
24
|
+
};
|
|
1
25
|
export const computeTool = {
|
|
2
26
|
name: "oneshot_compute",
|
|
3
|
-
description: "Create an autonomous compute goal: give OneShot an objective and a budget; it plans and runs the steps across OneShot tools. Returns a goal id to poll. Paid tool (quote-to-pay against the budget).",
|
|
27
|
+
description: "Create an autonomous compute goal: give OneShot an objective and a budget; it plans and runs the steps across OneShot tools. Name the unit of work, how work starts (a given list, an event, a schedule, or once) and what each unit needs, or pass `scope`. The quote returns `scope`, `price` (per unit expected and ceiling, overhead, total or units covered, unpriced, unmeasured) and the `done_check` the goal is held to. Returns a goal id to poll. Paid tool (quote-to-pay against the budget).",
|
|
4
28
|
inputSchema: {
|
|
5
29
|
type: "object",
|
|
6
30
|
properties: {
|
|
@@ -43,6 +67,159 @@ export const computeTool = {
|
|
|
43
67
|
},
|
|
44
68
|
additionalProperties: false,
|
|
45
69
|
},
|
|
70
|
+
done_check: {
|
|
71
|
+
description: "What done means, written before the goal runs and evaluated in code: the goal completes on its own when the check is met. Without one the goal waits in awaiting_confirmation for its owner to confirm. Give one shape.",
|
|
72
|
+
oneOf: [
|
|
73
|
+
{
|
|
74
|
+
type: "object",
|
|
75
|
+
description: "At least at_least tasks of a tool (of: tasks, needs tool), events of one type (of: events, needs event_type) or emails that reached a status (of: emails).",
|
|
76
|
+
properties: {
|
|
77
|
+
kind: { const: "count" },
|
|
78
|
+
of: { type: "string", enum: ["tasks", "events", "emails"] },
|
|
79
|
+
tool: KNOWN_GOAL_TOOL,
|
|
80
|
+
status: { type: "string", description: 'For tasks: "completed" or "failed"; for emails: "sent", "delivered" or "opened"' },
|
|
81
|
+
event_type: { type: "string", enum: ["email_reply", "sms_reply", "voice_completed", "task_completed", "task_failed"] },
|
|
82
|
+
at_least: { type: "integer", minimum: 1 },
|
|
83
|
+
},
|
|
84
|
+
required: ["kind", "of", "at_least"],
|
|
85
|
+
additionalProperties: false,
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
type: "object",
|
|
89
|
+
description: "The latest completed result of a tool, at a dot path (omit for the whole result), equals a value or is at least a number. Give exactly one of equals or at_least.",
|
|
90
|
+
properties: {
|
|
91
|
+
kind: { const: "tool_result" },
|
|
92
|
+
tool: KNOWN_GOAL_TOOL,
|
|
93
|
+
path: { type: "string", description: 'Dot path into the result, e.g. "result.status" (up to 8 keys)' },
|
|
94
|
+
equals: { type: ["string", "number", "boolean"] },
|
|
95
|
+
at_least: { type: "number" },
|
|
96
|
+
},
|
|
97
|
+
required: ["kind", "tool"],
|
|
98
|
+
// The API rejects a tool_result check with neither or both criteria; say so in the schema so a client fails before the quote.
|
|
99
|
+
oneOf: [{ required: ["equals"] }, { required: ["at_least"] }],
|
|
100
|
+
additionalProperties: false,
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
type: "object",
|
|
104
|
+
description: "No check can be written: the owner confirms completion.",
|
|
105
|
+
properties: { kind: { const: "owner" } },
|
|
106
|
+
required: ["kind"],
|
|
107
|
+
additionalProperties: false,
|
|
108
|
+
},
|
|
109
|
+
{
|
|
110
|
+
type: "object",
|
|
111
|
+
description: "Every case of the goal is in one of finished_states (a state in owner_required_for also needs an owner on the record); at least min_cases (default 1) must exist.",
|
|
112
|
+
properties: {
|
|
113
|
+
kind: { const: "cases" },
|
|
114
|
+
finished_states: { type: "array", items: { type: "string" }, minItems: 1, maxItems: 20, description: 'Lowercase state tokens such as "merged"' },
|
|
115
|
+
owner_required_for: { type: "array", items: { type: "string" }, maxItems: 20, description: "States from finished_states that only count when the case record names an owner" },
|
|
116
|
+
min_cases: { type: "integer", minimum: 1 },
|
|
117
|
+
},
|
|
118
|
+
required: ["kind", "finished_states"],
|
|
119
|
+
additionalProperties: false,
|
|
120
|
+
},
|
|
121
|
+
{
|
|
122
|
+
type: "object",
|
|
123
|
+
description: "A named verifier accepts proof the agent submits (a document, photo, link or fields read from a document). The verifier needs an email or a phone number. With fields, a field the proof does not show, or one outside its bounds, is reported back without asking the verifier. One-off goals only.",
|
|
124
|
+
properties: {
|
|
125
|
+
kind: { const: "evidence" },
|
|
126
|
+
verifier: {
|
|
127
|
+
type: "object",
|
|
128
|
+
properties: {
|
|
129
|
+
name: { type: "string" },
|
|
130
|
+
email: { type: "string" },
|
|
131
|
+
phone: { type: "string", description: "E.164, such as +14155550100" },
|
|
132
|
+
timezone: { type: "string", description: 'IANA zone, e.g. "America/Chicago", for texts' },
|
|
133
|
+
},
|
|
134
|
+
required: ["name"],
|
|
135
|
+
additionalProperties: false,
|
|
136
|
+
},
|
|
137
|
+
accepts: { type: "string", description: "What proof is acceptable, in plain words; the verifier is shown it" },
|
|
138
|
+
fields: {
|
|
139
|
+
type: "array",
|
|
140
|
+
maxItems: 20,
|
|
141
|
+
items: {
|
|
142
|
+
type: "object",
|
|
143
|
+
properties: {
|
|
144
|
+
name: { type: "string" },
|
|
145
|
+
description: { type: "string" },
|
|
146
|
+
type: { type: "string", enum: ["string", "number", "boolean"] },
|
|
147
|
+
equals: { type: ["string", "number", "boolean"] },
|
|
148
|
+
one_of: { type: "array", items: { type: "string" } },
|
|
149
|
+
at_least: { type: "number" },
|
|
150
|
+
at_most: { type: "number" },
|
|
151
|
+
},
|
|
152
|
+
required: ["name", "description", "type"],
|
|
153
|
+
additionalProperties: false,
|
|
154
|
+
},
|
|
155
|
+
},
|
|
156
|
+
},
|
|
157
|
+
required: ["kind", "verifier", "accepts"],
|
|
158
|
+
additionalProperties: false,
|
|
159
|
+
},
|
|
160
|
+
],
|
|
161
|
+
},
|
|
162
|
+
egress_allowlist: {
|
|
163
|
+
type: "array",
|
|
164
|
+
items: { type: "string" },
|
|
165
|
+
maxItems: 50,
|
|
166
|
+
description: "Hosts the goal's sandboxes may reach besides OneShot's API: hostnames, IPv4 addresses or IPv4 ranges. Setting it (even to []) limits every sandbox of the goal to OneShot's API and these hosts.",
|
|
167
|
+
},
|
|
168
|
+
scope: {
|
|
169
|
+
type: "object",
|
|
170
|
+
description: "Your reading of the goal, replacing the quote's and priced again in code. Omit it and the quote proposes one. A tool the goal cannot call is refused.",
|
|
171
|
+
properties: {
|
|
172
|
+
unit: {
|
|
173
|
+
type: "object",
|
|
174
|
+
description: "What one unit is and what starts it",
|
|
175
|
+
properties: {
|
|
176
|
+
name: { type: "string", description: 'One unit in your words, e.g. "a carrier invoice"' },
|
|
177
|
+
starts_on: { type: "string", enum: ["list", "event", "schedule", "once"], description: "A given list, an event in the world, a schedule, or the goal itself once" },
|
|
178
|
+
},
|
|
179
|
+
required: ["name", "starts_on"],
|
|
180
|
+
},
|
|
181
|
+
per_unit: {
|
|
182
|
+
type: "object",
|
|
183
|
+
description: "What one unit takes",
|
|
184
|
+
properties: {
|
|
185
|
+
uses: { type: "array", maxItems: 50, items: SCOPE_USE, description: "Tool uses inside one unit" },
|
|
186
|
+
step_allowance: { type: "integer", minimum: 0, description: "Model steps one unit may take beyond its tool uses" },
|
|
187
|
+
done: { type: "array", items: { type: "string" }, minItems: 1, description: 'Case states that finish a unit, e.g. ["paid"]; "unreached" is always among them' },
|
|
188
|
+
},
|
|
189
|
+
required: ["uses", "step_allowance", "done"],
|
|
190
|
+
},
|
|
191
|
+
overhead: {
|
|
192
|
+
type: "object",
|
|
193
|
+
description: "Tool uses outside any unit: setting up, reporting",
|
|
194
|
+
properties: {
|
|
195
|
+
uses: { type: "array", maxItems: 50, items: { type: "object", properties: { tool: KNOWN_GOAL_TOOL, qty: { type: "integer", minimum: 1 }, max_attempts: { type: "integer", minimum: 1 }, drivers: SCOPE_DRIVERS }, required: ["tool", "qty", "max_attempts"] } },
|
|
196
|
+
step_allowance: { type: "integer", minimum: 0 },
|
|
197
|
+
},
|
|
198
|
+
required: ["uses", "step_allowance"],
|
|
199
|
+
},
|
|
200
|
+
volume: {
|
|
201
|
+
type: "object",
|
|
202
|
+
description: 'How many units: {"kind": "list", "count": N} for a given list, {"kind": "open"} otherwise',
|
|
203
|
+
properties: { kind: { type: "string", enum: ["list", "open"] }, count: { type: "integer", minimum: 1 } },
|
|
204
|
+
required: ["kind"],
|
|
205
|
+
},
|
|
206
|
+
unpriced: {
|
|
207
|
+
type: "array",
|
|
208
|
+
maxItems: 50,
|
|
209
|
+
description: "What the price list cannot price: a connected system you pay for, or a tool quoted per call",
|
|
210
|
+
items: {
|
|
211
|
+
type: "object",
|
|
212
|
+
properties: {
|
|
213
|
+
name: { type: "string" },
|
|
214
|
+
reason: { type: "string", enum: ["connection", "quoted_tool"] },
|
|
215
|
+
assumption: { type: "string", description: "What remains unknown until a live quote, capped by the remaining goal budget" },
|
|
216
|
+
},
|
|
217
|
+
required: ["name", "reason"],
|
|
218
|
+
},
|
|
219
|
+
},
|
|
220
|
+
},
|
|
221
|
+
required: ["unit", "per_unit", "overhead", "volume", "unpriced"],
|
|
222
|
+
},
|
|
46
223
|
},
|
|
47
224
|
required: ["objective"],
|
|
48
225
|
},
|
|
@@ -84,14 +261,15 @@ export const computeCancelTool = {
|
|
|
84
261
|
};
|
|
85
262
|
export const computeRespondTool = {
|
|
86
263
|
name: "oneshot_compute_respond",
|
|
87
|
-
description: "Respond to a human-in-the-loop task that a compute goal is waiting on (approve/reject or provide input), or send `dispute: true` without task_id to dispute a goal that ended impossible_unverified, with `response` as the reason; nothing is refunded. Free.",
|
|
264
|
+
description: "Respond to a human-in-the-loop task that a compute goal is waiting on (approve/reject or provide input), send `continue_without_tool: true` without task_id to release a goal awaiting a requested tool (with `response` as the message it resumes with), or send `dispute: true` without task_id to dispute a goal that ended impossible_unverified, with `response` as the reason; nothing is refunded. Free.",
|
|
88
265
|
inputSchema: {
|
|
89
266
|
type: "object",
|
|
90
267
|
properties: {
|
|
91
268
|
goal_id: { type: "string", description: "Compute goal id" },
|
|
92
|
-
task_id: { type: "string", description: "Id of the task awaiting a response (not with dispute)" },
|
|
93
|
-
response: { type: "string", description: "Free-text response for the task, or the reason for a dispute" },
|
|
269
|
+
task_id: { type: "string", description: "Id of the task awaiting a response (not with continue_without_tool or dispute)" },
|
|
270
|
+
response: { type: "string", description: "Free-text response for the task, the message an awaiting_tool goal resumes with, or the reason for a dispute" },
|
|
94
271
|
approved: { type: "boolean", description: "Approve (true) or reject (false) an approval task" },
|
|
272
|
+
continue_without_tool: { type: "boolean", description: "Continue an awaiting_tool goal without the requested tool; must be true, without task_id" },
|
|
95
273
|
dispute: { type: "boolean", description: "Dispute an impossible_unverified ending; must be true, without task_id" },
|
|
96
274
|
},
|
|
97
275
|
required: ["goal_id"],
|
|
@@ -99,7 +277,7 @@ export const computeRespondTool = {
|
|
|
99
277
|
};
|
|
100
278
|
export const computePauseTool = {
|
|
101
279
|
name: "oneshot_compute_pause",
|
|
102
|
-
description: "Pause a
|
|
280
|
+
description: "Pause a compute goal. A recurring goal stops taking scheduled runs until resumed; any other goal keeps its sessions, cases and reserved budget and continues where it was when resumed. Free.",
|
|
103
281
|
inputSchema: {
|
|
104
282
|
type: "object",
|
|
105
283
|
properties: {
|
|
@@ -111,7 +289,7 @@ export const computePauseTool = {
|
|
|
111
289
|
};
|
|
112
290
|
export const computeResumeTool = {
|
|
113
291
|
name: "oneshot_compute_resume",
|
|
114
|
-
description: "Resume a paused
|
|
292
|
+
description: "Resume a paused compute goal. A recurring goal picks up at its next scheduled run; any other goal continues now where it was. Nothing is lost. Free.",
|
|
115
293
|
inputSchema: {
|
|
116
294
|
type: "object",
|
|
117
295
|
properties: {
|
|
@@ -133,7 +311,7 @@ export const computeFundTool = {
|
|
|
133
311
|
},
|
|
134
312
|
};
|
|
135
313
|
export async function handleCompute(agent, args) {
|
|
136
|
-
|
|
314
|
+
const options = {
|
|
137
315
|
objective: args.objective,
|
|
138
316
|
budget_usdc: args.budget_usdc,
|
|
139
317
|
params: args.params,
|
|
@@ -142,7 +320,12 @@ export async function handleCompute(agent, args) {
|
|
|
142
320
|
soul_service_slug: args.soul_service_slug,
|
|
143
321
|
schedule: args.schedule,
|
|
144
322
|
approvals: args.approvals,
|
|
145
|
-
|
|
323
|
+
done_check: args.done_check,
|
|
324
|
+
egress_allowlist: args.egress_allowlist,
|
|
325
|
+
};
|
|
326
|
+
if (args.scope !== undefined)
|
|
327
|
+
options.scope = args.scope;
|
|
328
|
+
return agent.compute(options);
|
|
146
329
|
}
|
|
147
330
|
export async function handleComputeStatus(agent, args) {
|
|
148
331
|
return agent.getComputeGoal(args.goal_id);
|
|
@@ -163,6 +346,12 @@ export async function handleComputeRespond(agent, args) {
|
|
|
163
346
|
throw new Error("Send dispute: true, with an optional response, and without task_id");
|
|
164
347
|
return agent.disputeComputeGoal(args.goal_id, { reason: args.response });
|
|
165
348
|
}
|
|
349
|
+
// The owner continues a goal held for a requested tool without it (#3173); no task answers it either.
|
|
350
|
+
if (args.continue_without_tool !== undefined) {
|
|
351
|
+
if (args.continue_without_tool !== true || args.task_id !== undefined)
|
|
352
|
+
throw new Error("Send continue_without_tool: true, with an optional response, and without task_id");
|
|
353
|
+
return agent.continueComputeGoalWithoutTool(args.goal_id, { message: args.response });
|
|
354
|
+
}
|
|
166
355
|
return agent.respondToComputeTask(args.goal_id, {
|
|
167
356
|
task_id: args.task_id,
|
|
168
357
|
response: args.response,
|
|
@@ -3,7 +3,7 @@ import type { OneShot } from "@oneshot-agent/sdk";
|
|
|
3
3
|
/**
|
|
4
4
|
* The agent's connections (#2403). Hand-written because `GET /v1/connections` is not a declared route: the
|
|
5
5
|
* connected-system read tools (`oneshot_ledger_*`, `oneshot_crm_*`, `oneshot_shipping_*`, `oneshot_tax_*`,
|
|
6
|
-
* `oneshot_procurement_*`) are generated from their routes and each tells the model to call this one first.
|
|
6
|
+
* `oneshot_procurement_*`, `oneshot_meetings_*`, `oneshot_field_service_*`) are generated from their routes and each tells the model to call this one first.
|
|
7
7
|
* Connecting and revoking stay in the console.
|
|
8
8
|
*/
|
|
9
9
|
export declare const connectionsListTool: Tool;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* The agent's connections (#2403). Hand-written because `GET /v1/connections` is not a declared route: the
|
|
3
3
|
* connected-system read tools (`oneshot_ledger_*`, `oneshot_crm_*`, `oneshot_shipping_*`, `oneshot_tax_*`,
|
|
4
|
-
* `oneshot_procurement_*`) are generated from their routes and each tells the model to call this one first.
|
|
4
|
+
* `oneshot_procurement_*`, `oneshot_meetings_*`, `oneshot_field_service_*`) are generated from their routes and each tells the model to call this one first.
|
|
5
5
|
* Connecting and revoking stay in the console.
|
|
6
6
|
*/
|
|
7
7
|
export const connectionsListTool = {
|
package/dist/tools/discover.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export const discoverToolsTool = {
|
|
2
2
|
name: 'oneshot_discover_tools',
|
|
3
|
-
description: 'Find OneShot tools by task or category. Free. Returns public names, purposes and required inputs. With no query or category, lists categories. Category pages contain up to five tools; pass nextCursor with the same query and category.',
|
|
3
|
+
description: 'Find OneShot tools by task or category. Free. Returns public names, purposes and required inputs; a lookup that is not in your tool list runs with oneshot_lookup. With no query or category, lists categories. Category pages contain up to five tools; pass nextCursor with the same query and category.',
|
|
4
4
|
inputSchema: {
|
|
5
5
|
type: 'object',
|
|
6
6
|
properties: {
|
package/dist/tools/domains.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export const listDomainsTool = {
|
|
2
2
|
name: "oneshot_list_domains",
|
|
3
|
-
description: "List the agent's sending domains. Each has default_from (
|
|
3
|
+
description: "List the agent's sending domains. Each has default_from (the main address, e.g. agent@domain; rotation and goals send from it), mailbox_mode (relay|mailbox), addresses[] (the addresses the domain sends and receives at: {address, status, warmup_state}), pool_status (rotation eligibility: active|paused|removed), warmup_state (reputation health: warming|warmed|degraded|not_warmed), pause_reason (warming|low_reputation|manual|null), warmup_score, and daily send limits. mailbox_mode is fixed when the domain is bought. relay: addresses send and receive with no hosted inbox; never warmed (not_warmed), they rotate at once on a daily limit that rises with the domain's age. mailbox: each address is a hosted inbox, warmed before it rotates. The owner adds addresses with the domain purchase; a send never creates one. A domain can be paused AND warming: reputation pauses auto-recover once warmed; manual pauses need a resume. Free.",
|
|
4
4
|
inputSchema: { type: "object", properties: {} },
|
|
5
5
|
};
|
|
6
6
|
export const pauseDomainTool = {
|
package/dist/tools/email.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export const emailTool = {
|
|
2
2
|
name: "oneshot_email",
|
|
3
3
|
description: "Send an email. Supports HTML body, attachments, and threaded replies (set reply_to_email_id to an inbound email id from oneshot_inbox_list/oneshot_inbox_get, or one this agent sent). Paid tool — quote provided before payment.\n\n" +
|
|
4
|
-
"Sending requires
|
|
4
|
+
"Sending requires an owned, verified domain, and a domain sends only from its own addresses. Call oneshot_list_domains first. A send never sets up a domain or an address: a new from_domain, or a from_mailbox the domain does not have, returns status confirmation_required with a separate setup quote, and no agent domain at all returns setup_required with requirements. Nothing is charged or sent. Show setup.total_cost and setup.billing to the owner, who buys through POST /v1/domains/buy or the account console. Models and goals cannot buy setup. Send again once setup is done.",
|
|
5
5
|
inputSchema: {
|
|
6
6
|
type: "object",
|
|
7
7
|
properties: {
|
|
@@ -23,21 +23,16 @@ export const emailTool = {
|
|
|
23
23
|
},
|
|
24
24
|
from_domain: {
|
|
25
25
|
type: "string",
|
|
26
|
-
description: "
|
|
26
|
+
description: "Pin an owned sending domain, or choose a new name to quote separate account setup. The owner must buy setup and wait for verification before sending. Omit both from_domain and from_mailbox to rotate across eligible owned domains, each sending from its main address.",
|
|
27
27
|
},
|
|
28
28
|
from_mailbox: {
|
|
29
29
|
type: "string",
|
|
30
|
-
description: "Sender
|
|
30
|
+
description: "Sender local-part on from_domain (optional, defaults to the domain's main address, its default_from). Requires from_domain. Must be one of the domain's addresses (see oneshot_list_domains); another returns the setup quote that adds it, and no email is sent.",
|
|
31
31
|
},
|
|
32
32
|
from_name: {
|
|
33
33
|
type: "string",
|
|
34
34
|
description: "Display name shown to the recipient (optional), e.g. 'Jane Doe' renders as 'Jane Doe <jane@domain>'",
|
|
35
35
|
},
|
|
36
|
-
mailbox_mode: {
|
|
37
|
-
type: "string",
|
|
38
|
-
enum: ["relay", "mailbox"],
|
|
39
|
-
description: "How this domain sends (optional). 'relay' = no dedicated mailbox, no mailbox fee. 'mailbox' = a real dedicated mailbox per address (better deliverability + per-address warmup); each new address adds a one-time mailbox_provisioning_fee to the quote. Only honored while a domain is unprovisioned (brand new, or owned with provisioning_status 'unprovisioned') — an already-provisioned domain keeps the mode it was created with, which means OMITTING this does not make a send relay and does not avoid the fee. On a domain already in mailbox mode every address that isn't active yet bills the fee on its first send, the default agent@ included; from_mailbox does not change that. Use oneshot_list_domains to see each domain's mailbox_mode before quoting.",
|
|
40
|
-
},
|
|
41
36
|
attachments: {
|
|
42
37
|
type: "array",
|
|
43
38
|
items: {
|
|
@@ -55,10 +50,6 @@ export const emailTool = {
|
|
|
55
50
|
type: "string",
|
|
56
51
|
description: "Only when retrying a call the action policy held: the approval_id from the approval_required error, once a human approved it. The call then runs once.",
|
|
57
52
|
},
|
|
58
|
-
confirm_new_domain: {
|
|
59
|
-
type: "string",
|
|
60
|
-
description: "The quote_id from a 'confirmation_required' result, and nothing else. A call with a from_domain you don't own yet always stops before charging and returns that result with the exact total. Only after showing that total to the user and getting their go-ahead, call this again with the same arguments and confirm_new_domain set to the quote_id: the domain is registered, exactly that quote's total is charged, and the email is sent in that one call. Passing true never charges; it only quotes again. A wrong, expired or already-used quote id is rejected by the server without charge: drop it and call again without confirm_new_domain for a fresh quote.",
|
|
61
|
-
},
|
|
62
53
|
},
|
|
63
54
|
required: ["body"],
|
|
64
55
|
},
|
|
@@ -72,10 +63,7 @@ export async function handleEmail(agent, args) {
|
|
|
72
63
|
from_domain: args.from_domain,
|
|
73
64
|
from_mailbox: args.from_mailbox,
|
|
74
65
|
from_name: args.from_name,
|
|
75
|
-
mailbox_mode: args.mailbox_mode,
|
|
76
66
|
attachments: args.attachments,
|
|
77
67
|
approvalId: args.approval_id,
|
|
78
|
-
// Only the quote id confirms; `true` or anything else is not a confirmation.
|
|
79
|
-
confirmNewDomain: typeof args.confirm_new_domain === "string" ? args.confirm_new_domain : undefined,
|
|
80
68
|
});
|
|
81
69
|
}
|
package/dist/tools/index.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { UNTRUSTED_TOOLS } from './untrusted-tools.generated.js';
|
|
2
2
|
import { discoverToolsTool, handleDiscoverTools } from './discover.js';
|
|
3
|
+
import { handleLookupCall, lookupCallTool, lookupTarget } from './lookup-call.js';
|
|
3
4
|
import { emailTool, handleEmail } from "./email.js";
|
|
4
5
|
import { voiceTool, handleVoice } from "./voice.js";
|
|
5
6
|
import { voiceNumberProvisionTool, voiceNumbersTool, voiceInboundSetTool, voiceInboundDisableTool, voiceInboundCallsTool, handleVoiceNumberProvision, handleVoiceNumbers, handleVoiceInboundSet, handleVoiceInboundDisable, handleVoiceInboundCalls, } from "./voice-inbound.js";
|
|
@@ -34,6 +35,7 @@ import { connectionsListTool, handleConnectionsList } from "./connections.js";
|
|
|
34
35
|
import { spendBreakdownTool, rocsTool, rocsByGoalTool, receiptsListTool, tagReceiptValueTool, handleSpendBreakdown, handleRocs, handleRocsByGoal, handleReceiptsList, handleTagReceiptValue } from "./analytics.js";
|
|
35
36
|
const toolDefinitions = [
|
|
36
37
|
discoverToolsTool,
|
|
38
|
+
lookupCallTool,
|
|
37
39
|
emailTool,
|
|
38
40
|
voiceTool,
|
|
39
41
|
smsTool,
|
|
@@ -130,6 +132,7 @@ export const tools = toolDefinitions.map((tool) => {
|
|
|
130
132
|
});
|
|
131
133
|
const handlers = {
|
|
132
134
|
oneshot_discover_tools: handleDiscoverTools,
|
|
135
|
+
oneshot_lookup: handleLookupCall,
|
|
133
136
|
"oneshot_email": handleEmail,
|
|
134
137
|
"oneshot_voice": handleVoice,
|
|
135
138
|
"oneshot_sms": handleSms,
|
|
@@ -227,7 +230,9 @@ export async function handleToolCall(agent, toolName, args) {
|
|
|
227
230
|
isError: true,
|
|
228
231
|
};
|
|
229
232
|
}
|
|
230
|
-
|
|
233
|
+
// oneshot_lookup returns what the lookup it runs returns, so it is marked by that lookup.
|
|
234
|
+
const marked = toolName === "oneshot_lookup" && args.input !== undefined ? lookupTarget(args) ?? toolName : toolName;
|
|
235
|
+
const untrusted = UNTRUSTED_TOOLS.has(marked.replace(/^oneshot_/, ""));
|
|
231
236
|
try {
|
|
232
237
|
const data = await handler(agent, args);
|
|
233
238
|
const acknowledgement = data && typeof data === "object" && "request_id" in data && "status" in data
|
|
@@ -282,6 +287,12 @@ export function structuredToolError(error) {
|
|
|
282
287
|
};
|
|
283
288
|
case "PaymentError":
|
|
284
289
|
return { error: "payment_failed", message: e.message, reason: e.reason };
|
|
290
|
+
case "SettlementAmbiguousError":
|
|
291
|
+
return {
|
|
292
|
+
error: "settlement_ambiguous",
|
|
293
|
+
message: e.message,
|
|
294
|
+
...(typeof e.settlementId === "string" ? { settlement_id: e.settlementId } : {}),
|
|
295
|
+
};
|
|
285
296
|
case "ToolError": {
|
|
286
297
|
// Every 4xx the SDK doesn't recognize as one of the typed errors above
|
|
287
298
|
// (budget/credits/payment) lands here as a plain ToolError, and its
|