robotrock 0.8.1 → 0.8.4
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/dist/ai/index.js +485 -36
- package/dist/ai/index.js.map +1 -1
- package/dist/ai/trigger.js +485 -36
- package/dist/ai/trigger.js.map +1 -1
- package/dist/ai/workflow.js +485 -36
- package/dist/ai/workflow.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +528 -39
- package/dist/index.js.map +1 -1
- package/dist/otel/index.d.ts +49 -0
- package/dist/otel/index.js +633 -0
- package/dist/otel/index.js.map +1 -0
- package/dist/schemas/index.d.ts +60 -1
- package/dist/schemas/index.js +407 -28
- package/dist/schemas/index.js.map +1 -1
- package/dist/trigger/index.js +382 -8
- package/dist/trigger/index.js.map +1 -1
- package/dist/workflow/index.js +382 -8
- package/dist/workflow/index.js.map +1 -1
- package/package.json +10 -4
package/dist/ai/index.js
CHANGED
|
@@ -53,13 +53,237 @@ var __callDispose = (stack, error, hasError) => {
|
|
|
53
53
|
return next();
|
|
54
54
|
};
|
|
55
55
|
|
|
56
|
-
//
|
|
56
|
+
// ../../node_modules/.bun/clsx@2.1.1/node_modules/clsx/dist/clsx.mjs
|
|
57
|
+
var init_clsx = __esm({
|
|
58
|
+
"../../node_modules/.bun/clsx@2.1.1/node_modules/clsx/dist/clsx.mjs"() {
|
|
59
|
+
"use strict";
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
// ../core/src/utils/cn.ts
|
|
64
|
+
var init_cn = __esm({
|
|
65
|
+
"../core/src/utils/cn.ts"() {
|
|
66
|
+
"use strict";
|
|
67
|
+
init_clsx();
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
// ../core/src/utils/convex-sanitize.ts
|
|
72
|
+
var init_convex_sanitize = __esm({
|
|
73
|
+
"../core/src/utils/convex-sanitize.ts"() {
|
|
74
|
+
"use strict";
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
// ../core/src/utils/safe-url.ts
|
|
79
|
+
function normalizeHostname(hostname) {
|
|
80
|
+
return hostname.toLowerCase().replace(/^\[|\]$/g, "");
|
|
81
|
+
}
|
|
82
|
+
function isBlockedIpv4(host) {
|
|
83
|
+
const match = /^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/.exec(host);
|
|
84
|
+
if (!match) {
|
|
85
|
+
return false;
|
|
86
|
+
}
|
|
87
|
+
const octets = match.slice(1, 5).map((part) => Number(part));
|
|
88
|
+
if (octets.some((octet) => Number.isNaN(octet) || octet < 0 || octet > 255)) {
|
|
89
|
+
return true;
|
|
90
|
+
}
|
|
91
|
+
const [a, b, _c, _d] = octets;
|
|
92
|
+
if (a === void 0 || b === void 0) {
|
|
93
|
+
return true;
|
|
94
|
+
}
|
|
95
|
+
if (a === 127 || a === 0) return true;
|
|
96
|
+
if (a === 10) return true;
|
|
97
|
+
if (a === 169 && b === 254) return true;
|
|
98
|
+
if (a === 192 && b === 168) return true;
|
|
99
|
+
if (a === 172 && b >= 16 && b <= 31) return true;
|
|
100
|
+
if (a === 100 && b >= 64 && b <= 127) return true;
|
|
101
|
+
return false;
|
|
102
|
+
}
|
|
103
|
+
function ipv4FromNumericHost(host) {
|
|
104
|
+
if (/^\d+$/.test(host)) {
|
|
105
|
+
const num = Number(host);
|
|
106
|
+
if (!Number.isFinite(num) || num < 0 || num > 4294967295) {
|
|
107
|
+
return null;
|
|
108
|
+
}
|
|
109
|
+
const a = num >>> 24 & 255;
|
|
110
|
+
const b = num >>> 16 & 255;
|
|
111
|
+
const c = num >>> 8 & 255;
|
|
112
|
+
const d = num & 255;
|
|
113
|
+
return `${a}.${b}.${c}.${d}`;
|
|
114
|
+
}
|
|
115
|
+
const hexMatch = /^0x([0-9a-f]{1,8})$/i.exec(host);
|
|
116
|
+
if (hexMatch) {
|
|
117
|
+
const num = Number.parseInt(hexMatch[1], 16);
|
|
118
|
+
if (!Number.isFinite(num) || num < 0 || num > 4294967295) {
|
|
119
|
+
return null;
|
|
120
|
+
}
|
|
121
|
+
const a = num >>> 24 & 255;
|
|
122
|
+
const b = num >>> 16 & 255;
|
|
123
|
+
const c = num >>> 8 & 255;
|
|
124
|
+
const d = num & 255;
|
|
125
|
+
return `${a}.${b}.${c}.${d}`;
|
|
126
|
+
}
|
|
127
|
+
return null;
|
|
128
|
+
}
|
|
129
|
+
function isBlockedIpv4Mapped(host) {
|
|
130
|
+
const mappedDotted = /^::ffff:(\d{1,3}(?:\.\d{1,3}){3})$/i.exec(host);
|
|
131
|
+
if (mappedDotted) {
|
|
132
|
+
return isBlockedIpv4(mappedDotted[1]);
|
|
133
|
+
}
|
|
134
|
+
const mappedHex = /^::ffff:([0-9a-f]{1,4}):([0-9a-f]{1,4})$/i.exec(host);
|
|
135
|
+
if (mappedHex) {
|
|
136
|
+
const high = Number.parseInt(mappedHex[1], 16);
|
|
137
|
+
const low = Number.parseInt(mappedHex[2], 16);
|
|
138
|
+
if (Number.isFinite(high) && Number.isFinite(low)) {
|
|
139
|
+
const a = high >> 8 & 255;
|
|
140
|
+
const b = high & 255;
|
|
141
|
+
const c = low >> 8 & 255;
|
|
142
|
+
const d = low & 255;
|
|
143
|
+
return isBlockedIpv4(`${a}.${b}.${c}.${d}`);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
return false;
|
|
147
|
+
}
|
|
148
|
+
function isBlockedIpv6(host) {
|
|
149
|
+
if (host === "::1" || host === "0:0:0:0:0:0:0:1") {
|
|
150
|
+
return true;
|
|
151
|
+
}
|
|
152
|
+
if (host.startsWith("fc") || host.startsWith("fd")) {
|
|
153
|
+
return true;
|
|
154
|
+
}
|
|
155
|
+
if (host.startsWith("fe80:")) {
|
|
156
|
+
return true;
|
|
157
|
+
}
|
|
158
|
+
if (isBlockedIpv4Mapped(host)) {
|
|
159
|
+
return true;
|
|
160
|
+
}
|
|
161
|
+
return false;
|
|
162
|
+
}
|
|
163
|
+
function isBlockedHostname(hostname) {
|
|
164
|
+
const host = normalizeHostname(hostname);
|
|
165
|
+
if (!host) {
|
|
166
|
+
return true;
|
|
167
|
+
}
|
|
168
|
+
if (BLOCKED_HOSTNAMES.has(host)) {
|
|
169
|
+
return true;
|
|
170
|
+
}
|
|
171
|
+
if (host.endsWith(".localhost") || host.endsWith(".local")) {
|
|
172
|
+
return true;
|
|
173
|
+
}
|
|
174
|
+
const numericIpv4 = ipv4FromNumericHost(host);
|
|
175
|
+
if (numericIpv4 && isBlockedIpv4(numericIpv4)) {
|
|
176
|
+
return true;
|
|
177
|
+
}
|
|
178
|
+
return isBlockedIpv4(host) || isBlockedIpv6(host);
|
|
179
|
+
}
|
|
180
|
+
function isPublicHttpUrl(urlString) {
|
|
181
|
+
let url;
|
|
182
|
+
try {
|
|
183
|
+
url = new URL(urlString);
|
|
184
|
+
} catch {
|
|
185
|
+
return false;
|
|
186
|
+
}
|
|
187
|
+
if (url.protocol !== "http:" && url.protocol !== "https:") {
|
|
188
|
+
return false;
|
|
189
|
+
}
|
|
190
|
+
if (url.username || url.password) {
|
|
191
|
+
return false;
|
|
192
|
+
}
|
|
193
|
+
return !isBlockedHostname(url.hostname);
|
|
194
|
+
}
|
|
195
|
+
var BLOCKED_HOSTNAMES, PUBLIC_HTTP_URL_ERROR;
|
|
196
|
+
var init_safe_url = __esm({
|
|
197
|
+
"../core/src/utils/safe-url.ts"() {
|
|
198
|
+
"use strict";
|
|
199
|
+
BLOCKED_HOSTNAMES = /* @__PURE__ */ new Set([
|
|
200
|
+
"localhost",
|
|
201
|
+
"metadata.google.internal",
|
|
202
|
+
"metadata.goog"
|
|
203
|
+
]);
|
|
204
|
+
PUBLIC_HTTP_URL_ERROR = "URL must be a public http:// or https:// address";
|
|
205
|
+
}
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
// ../core/src/utils/task-app.ts
|
|
209
|
+
var init_task_app = __esm({
|
|
210
|
+
"../core/src/utils/task-app.ts"() {
|
|
211
|
+
"use strict";
|
|
212
|
+
}
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
// ../core/src/utils/index.ts
|
|
216
|
+
var init_utils = __esm({
|
|
217
|
+
"../core/src/utils/index.ts"() {
|
|
218
|
+
"use strict";
|
|
219
|
+
init_cn();
|
|
220
|
+
init_convex_sanitize();
|
|
221
|
+
init_safe_url();
|
|
222
|
+
init_task_app();
|
|
223
|
+
}
|
|
224
|
+
});
|
|
225
|
+
|
|
226
|
+
// ../core/src/schemas/context-urls.ts
|
|
227
|
+
function resolveLinkUrl(value) {
|
|
228
|
+
return value.startsWith("http://") || value.startsWith("https://") ? value : `https://${value}`;
|
|
229
|
+
}
|
|
230
|
+
function widgetType(ui, field) {
|
|
231
|
+
const fieldUi = ui?.[field];
|
|
232
|
+
if (typeof fieldUi !== "object" || fieldUi === null) {
|
|
233
|
+
return void 0;
|
|
234
|
+
}
|
|
235
|
+
const widget = fieldUi["ui:widget"];
|
|
236
|
+
return typeof widget === "string" ? widget : void 0;
|
|
237
|
+
}
|
|
238
|
+
function validateUrlValue(value, widget) {
|
|
239
|
+
if (widget === "image" || widget === "link") {
|
|
240
|
+
if (typeof value !== "string") {
|
|
241
|
+
return PUBLIC_HTTP_URL_ERROR;
|
|
242
|
+
}
|
|
243
|
+
const url = widget === "link" ? resolveLinkUrl(value) : value;
|
|
244
|
+
if (!isPublicHttpUrl(url)) {
|
|
245
|
+
return PUBLIC_HTTP_URL_ERROR;
|
|
246
|
+
}
|
|
247
|
+
return null;
|
|
248
|
+
}
|
|
249
|
+
if (widget === "attachments" && Array.isArray(value)) {
|
|
250
|
+
for (const item of value) {
|
|
251
|
+
if (typeof item !== "object" || item === null) {
|
|
252
|
+
continue;
|
|
253
|
+
}
|
|
254
|
+
const url = item.url;
|
|
255
|
+
if (typeof url === "string" && !isPublicHttpUrl(resolveLinkUrl(url))) {
|
|
256
|
+
return PUBLIC_HTTP_URL_ERROR;
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
return null;
|
|
261
|
+
}
|
|
262
|
+
function validateContextPublicUrls(context) {
|
|
263
|
+
if (!context?.data) {
|
|
264
|
+
return null;
|
|
265
|
+
}
|
|
266
|
+
for (const [field, value] of Object.entries(context.data)) {
|
|
267
|
+
const widget = widgetType(context.ui, field);
|
|
268
|
+
if (!widget) {
|
|
269
|
+
continue;
|
|
270
|
+
}
|
|
271
|
+
const error = validateUrlValue(value, widget);
|
|
272
|
+
if (error) {
|
|
273
|
+
return `context.data.${field}: ${error}`;
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
return null;
|
|
277
|
+
}
|
|
278
|
+
var init_context_urls = __esm({
|
|
279
|
+
"../core/src/schemas/context-urls.ts"() {
|
|
280
|
+
"use strict";
|
|
281
|
+
init_safe_url();
|
|
282
|
+
}
|
|
283
|
+
});
|
|
284
|
+
|
|
285
|
+
// ../core/src/schemas/task.ts
|
|
57
286
|
import { z } from "zod";
|
|
58
|
-
import {
|
|
59
|
-
isPublicHttpUrl,
|
|
60
|
-
PUBLIC_HTTP_URL_ERROR
|
|
61
|
-
} from "@robotrock/core/utils";
|
|
62
|
-
import { validateContextPublicUrls } from "@robotrock/core/schemas";
|
|
63
287
|
function refineContextPublicUrls(data, ctx) {
|
|
64
288
|
const error = validateContextPublicUrls(data.context);
|
|
65
289
|
if (error) {
|
|
@@ -70,10 +294,12 @@ function refineContextPublicUrls(data, ctx) {
|
|
|
70
294
|
});
|
|
71
295
|
}
|
|
72
296
|
}
|
|
73
|
-
var safeUrlSchema, jsonSchema7Schema, uiSchemaSchema, webhookHandlerSchema, triggerHandlerSchema, handlerSchema, taskActionSchema, uiFieldSchemaSchema, contextUiSchema, contextDataSchema, taskContextObjectSchema, taskContextSchema, assignToSchema, threadUpdateMessageSchema, threadUpdateStatuses, threadUpdateStatusSchema, threadUpdateInputSchema, taskPriorities, taskPrioritySchema, nonNegativeInt, agentCostTokensSchema, agentCostSchema, AGENT_INFO_MAX_KEYS, agentTelemetrySchema, createTaskBodySchema
|
|
74
|
-
var
|
|
75
|
-
"src/schemas/
|
|
297
|
+
var safeUrlSchema, jsonSchema7Schema, uiSchemaSchema, webhookHandlerSchema, triggerHandlerSchema, handlerSchema, taskActionSchema, uiFieldSchemaSchema, contextUiSchema, contextDataSchema, taskContextObjectSchema, taskContextSchema, assignToSchema, threadUpdateMessageSchema, threadUpdateStatuses, threadUpdateStatusSchema, threadUpdateInputSchema, taskPriorities, taskPrioritySchema, nonNegativeInt, agentCostTokensSchema, agentCostSchema, AGENT_INFO_MAX_KEYS, AGENT_TOOL_CALLS_MAX_KEYS, AGENT_OTEL_SPANS_MAX, agentToolCallsSchema, agentOtelSpanStatusSchema, agentOtelSpanSummarySchema, agentOtelSchema, agentTelemetrySchema, createTaskBodySchema;
|
|
298
|
+
var init_task = __esm({
|
|
299
|
+
"../core/src/schemas/task.ts"() {
|
|
76
300
|
"use strict";
|
|
301
|
+
init_safe_url();
|
|
302
|
+
init_context_urls();
|
|
77
303
|
safeUrlSchema = z.string().refine((url) => isPublicHttpUrl(url), {
|
|
78
304
|
message: PUBLIC_HTTP_URL_ERROR
|
|
79
305
|
});
|
|
@@ -101,6 +327,7 @@ var init_schemas = __esm({
|
|
|
101
327
|
schema: jsonSchema7Schema.optional(),
|
|
102
328
|
ui: uiSchemaSchema.optional(),
|
|
103
329
|
data: z.record(z.string(), z.unknown()).optional(),
|
|
330
|
+
// Optional handlers for this action - if present, must have at least 1
|
|
104
331
|
handlers: z.array(handlerSchema).min(1).optional()
|
|
105
332
|
});
|
|
106
333
|
uiFieldSchemaSchema = z.object({
|
|
@@ -116,6 +343,7 @@ var init_schemas = __esm({
|
|
|
116
343
|
ui: contextUiSchema
|
|
117
344
|
}).optional();
|
|
118
345
|
taskContextObjectSchema = z.object({
|
|
346
|
+
/** Source application id; omitted tasks are grouped in the default inbox. */
|
|
119
347
|
app: z.string().min(1).optional(),
|
|
120
348
|
type: z.string().min(1),
|
|
121
349
|
name: z.string().min(1),
|
|
@@ -170,17 +398,47 @@ var init_schemas = __esm({
|
|
|
170
398
|
usd: z.number().nonnegative().optional()
|
|
171
399
|
});
|
|
172
400
|
AGENT_INFO_MAX_KEYS = 32;
|
|
401
|
+
AGENT_TOOL_CALLS_MAX_KEYS = 64;
|
|
402
|
+
AGENT_OTEL_SPANS_MAX = 32;
|
|
403
|
+
agentToolCallsSchema = z.record(z.string().min(1), nonNegativeInt);
|
|
404
|
+
agentOtelSpanStatusSchema = z.enum(["ok", "error"]);
|
|
405
|
+
agentOtelSpanSummarySchema = z.object({
|
|
406
|
+
name: z.string().min(1),
|
|
407
|
+
durationMs: z.number().nonnegative(),
|
|
408
|
+
status: agentOtelSpanStatusSchema
|
|
409
|
+
});
|
|
410
|
+
agentOtelSchema = z.object({
|
|
411
|
+
traceId: z.string().min(1),
|
|
412
|
+
spanId: z.string().min(1).optional(),
|
|
413
|
+
rootDurationMs: z.number().nonnegative().optional(),
|
|
414
|
+
spans: z.array(agentOtelSpanSummarySchema).max(AGENT_OTEL_SPANS_MAX).optional()
|
|
415
|
+
});
|
|
173
416
|
agentTelemetrySchema = z.object({
|
|
417
|
+
/** Agent or app version (semver, git SHA, deploy tag — caller-defined). */
|
|
174
418
|
version: z.string().min(1).optional(),
|
|
419
|
+
/** Total tool invocations. When omitted but `toolCalls` is set, the sum of counts is used. */
|
|
175
420
|
toolCallCount: nonNegativeInt.optional(),
|
|
421
|
+
/** Per-tool invocation counts keyed by tool name. */
|
|
422
|
+
toolCalls: agentToolCallsSchema.optional(),
|
|
176
423
|
cost: agentCostSchema.optional(),
|
|
177
|
-
|
|
424
|
+
/** Free-form metadata for experiments (model, prompt variant, etc.). */
|
|
425
|
+
info: z.record(z.string(), z.unknown()).optional(),
|
|
426
|
+
/** Structured OpenTelemetry span snapshot for feedback analysis. */
|
|
427
|
+
otel: agentOtelSchema.optional()
|
|
178
428
|
}).refine(
|
|
179
429
|
(data) => {
|
|
180
430
|
const keys = data.info ? Object.keys(data.info) : [];
|
|
181
431
|
return keys.length <= AGENT_INFO_MAX_KEYS;
|
|
182
432
|
},
|
|
183
433
|
{ message: `agent.info may contain at most ${AGENT_INFO_MAX_KEYS} keys` }
|
|
434
|
+
).refine(
|
|
435
|
+
(data) => {
|
|
436
|
+
const keys = data.toolCalls ? Object.keys(data.toolCalls) : [];
|
|
437
|
+
return keys.length <= AGENT_TOOL_CALLS_MAX_KEYS;
|
|
438
|
+
},
|
|
439
|
+
{
|
|
440
|
+
message: `agent.toolCalls may contain at most ${AGENT_TOOL_CALLS_MAX_KEYS} tool names`
|
|
441
|
+
}
|
|
184
442
|
);
|
|
185
443
|
createTaskBodySchema = taskContextObjectSchema.extend({
|
|
186
444
|
assignTo: assignToSchema.optional(),
|
|
@@ -199,9 +457,200 @@ var init_schemas = __esm({
|
|
|
199
457
|
* the inbox status bar and the thread update log.
|
|
200
458
|
*/
|
|
201
459
|
update: threadUpdateInputSchema.optional(),
|
|
460
|
+
/** Agent telemetry (version, cost, tool calls) — not shown in inbox UI. */
|
|
202
461
|
agent: agentTelemetrySchema.optional()
|
|
203
462
|
}).superRefine(refineContextPublicUrls);
|
|
204
|
-
|
|
463
|
+
}
|
|
464
|
+
});
|
|
465
|
+
|
|
466
|
+
// ../core/src/schemas/json-schema.ts
|
|
467
|
+
var init_json_schema = __esm({
|
|
468
|
+
"../core/src/schemas/json-schema.ts"() {
|
|
469
|
+
"use strict";
|
|
470
|
+
}
|
|
471
|
+
});
|
|
472
|
+
|
|
473
|
+
// ../core/src/schemas/index.ts
|
|
474
|
+
var init_schemas = __esm({
|
|
475
|
+
"../core/src/schemas/index.ts"() {
|
|
476
|
+
"use strict";
|
|
477
|
+
init_task();
|
|
478
|
+
init_json_schema();
|
|
479
|
+
init_context_urls();
|
|
480
|
+
}
|
|
481
|
+
});
|
|
482
|
+
|
|
483
|
+
// src/schemas/index.ts
|
|
484
|
+
import { z as z2 } from "zod";
|
|
485
|
+
function refineContextPublicUrls2(data, ctx) {
|
|
486
|
+
const error = validateContextPublicUrls(data.context);
|
|
487
|
+
if (error) {
|
|
488
|
+
ctx.addIssue({
|
|
489
|
+
code: z2.ZodIssueCode.custom,
|
|
490
|
+
message: error,
|
|
491
|
+
path: ["context"]
|
|
492
|
+
});
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
var safeUrlSchema2, jsonSchema7Schema2, uiSchemaSchema2, webhookHandlerSchema2, triggerHandlerSchema2, handlerSchema2, taskActionSchema2, uiFieldSchemaSchema2, contextUiSchema2, contextDataSchema2, taskContextObjectSchema2, taskContextSchema2, assignToSchema2, threadUpdateMessageSchema2, threadUpdateStatuses2, threadUpdateStatusSchema2, threadUpdateInputSchema2, taskPriorities2, taskPrioritySchema2, nonNegativeInt2, agentCostTokensSchema2, agentCostSchema2, AGENT_INFO_MAX_KEYS2, AGENT_TOOL_CALLS_MAX_KEYS2, AGENT_OTEL_SPANS_MAX2, agentToolCallsSchema2, agentOtelSpanStatusSchema2, agentOtelSpanSummarySchema2, agentOtelSchema2, agentTelemetrySchema2, createTaskBodySchema2, threadUpdateBodySchema;
|
|
496
|
+
var init_schemas2 = __esm({
|
|
497
|
+
"src/schemas/index.ts"() {
|
|
498
|
+
"use strict";
|
|
499
|
+
init_utils();
|
|
500
|
+
init_schemas();
|
|
501
|
+
safeUrlSchema2 = z2.string().refine((url) => isPublicHttpUrl(url), {
|
|
502
|
+
message: PUBLIC_HTTP_URL_ERROR
|
|
503
|
+
});
|
|
504
|
+
jsonSchema7Schema2 = z2.custom(
|
|
505
|
+
(val) => typeof val === "object" && val !== null,
|
|
506
|
+
{ message: "Must be a valid JSON Schema object" }
|
|
507
|
+
);
|
|
508
|
+
uiSchemaSchema2 = z2.custom((val) => typeof val === "object" && val !== null, {
|
|
509
|
+
message: "Must be a valid UiSchema object"
|
|
510
|
+
});
|
|
511
|
+
webhookHandlerSchema2 = z2.object({
|
|
512
|
+
type: z2.literal("webhook"),
|
|
513
|
+
url: safeUrlSchema2,
|
|
514
|
+
headers: z2.record(z2.string(), z2.string())
|
|
515
|
+
});
|
|
516
|
+
triggerHandlerSchema2 = webhookHandlerSchema2.extend({
|
|
517
|
+
type: z2.literal("trigger"),
|
|
518
|
+
tokenId: z2.string().min(1)
|
|
519
|
+
});
|
|
520
|
+
handlerSchema2 = z2.discriminatedUnion("type", [webhookHandlerSchema2, triggerHandlerSchema2]);
|
|
521
|
+
taskActionSchema2 = z2.object({
|
|
522
|
+
id: z2.string().min(1),
|
|
523
|
+
title: z2.string().min(1),
|
|
524
|
+
description: z2.string().optional(),
|
|
525
|
+
schema: jsonSchema7Schema2.optional(),
|
|
526
|
+
ui: uiSchemaSchema2.optional(),
|
|
527
|
+
data: z2.record(z2.string(), z2.unknown()).optional(),
|
|
528
|
+
handlers: z2.array(handlerSchema2).min(1).optional()
|
|
529
|
+
});
|
|
530
|
+
uiFieldSchemaSchema2 = z2.object({
|
|
531
|
+
"ui:widget": z2.string().optional(),
|
|
532
|
+
"ui:title": z2.string().optional(),
|
|
533
|
+
"ui:description": z2.string().optional(),
|
|
534
|
+
"ui:options": z2.record(z2.string(), z2.unknown()).optional(),
|
|
535
|
+
items: z2.lazy(() => z2.record(z2.string(), uiFieldSchemaSchema2)).optional()
|
|
536
|
+
}).passthrough();
|
|
537
|
+
contextUiSchema2 = z2.record(z2.string(), uiFieldSchemaSchema2).optional();
|
|
538
|
+
contextDataSchema2 = z2.object({
|
|
539
|
+
data: z2.record(z2.string(), z2.unknown()),
|
|
540
|
+
ui: contextUiSchema2
|
|
541
|
+
}).optional();
|
|
542
|
+
taskContextObjectSchema2 = z2.object({
|
|
543
|
+
app: z2.string().min(1).optional(),
|
|
544
|
+
type: z2.string().min(1),
|
|
545
|
+
name: z2.string().min(1),
|
|
546
|
+
description: z2.string().optional(),
|
|
547
|
+
validUntil: z2.string().optional(),
|
|
548
|
+
context: contextDataSchema2,
|
|
549
|
+
version: z2.literal(2).optional(),
|
|
550
|
+
actions: z2.array(taskActionSchema2).min(1, "At least one action is required")
|
|
551
|
+
});
|
|
552
|
+
taskContextSchema2 = taskContextObjectSchema2.superRefine(
|
|
553
|
+
refineContextPublicUrls2
|
|
554
|
+
);
|
|
555
|
+
assignToSchema2 = z2.object({
|
|
556
|
+
users: z2.array(z2.string().email()).optional(),
|
|
557
|
+
groups: z2.array(z2.string().min(1)).optional()
|
|
558
|
+
}).refine(
|
|
559
|
+
(data) => {
|
|
560
|
+
const groups = data.groups ?? [];
|
|
561
|
+
if (groups.includes("all") && groups.length > 1) {
|
|
562
|
+
return false;
|
|
563
|
+
}
|
|
564
|
+
return true;
|
|
565
|
+
},
|
|
566
|
+
{ message: 'Cannot combine "all" with other group slugs' }
|
|
567
|
+
);
|
|
568
|
+
threadUpdateMessageSchema2 = z2.string().min(1).max(500);
|
|
569
|
+
threadUpdateStatuses2 = [
|
|
570
|
+
"info",
|
|
571
|
+
"queued",
|
|
572
|
+
"running",
|
|
573
|
+
"waiting",
|
|
574
|
+
"succeeded",
|
|
575
|
+
"failed",
|
|
576
|
+
"cancelled"
|
|
577
|
+
];
|
|
578
|
+
threadUpdateStatusSchema2 = z2.enum(threadUpdateStatuses2);
|
|
579
|
+
threadUpdateInputSchema2 = z2.object({
|
|
580
|
+
message: threadUpdateMessageSchema2,
|
|
581
|
+
status: threadUpdateStatusSchema2.optional()
|
|
582
|
+
});
|
|
583
|
+
taskPriorities2 = ["low", "normal", "high", "urgent"];
|
|
584
|
+
taskPrioritySchema2 = z2.enum(taskPriorities2);
|
|
585
|
+
nonNegativeInt2 = z2.number().int().nonnegative();
|
|
586
|
+
agentCostTokensSchema2 = z2.object({
|
|
587
|
+
input: nonNegativeInt2.optional(),
|
|
588
|
+
output: nonNegativeInt2.optional(),
|
|
589
|
+
total: nonNegativeInt2.optional()
|
|
590
|
+
});
|
|
591
|
+
agentCostSchema2 = z2.object({
|
|
592
|
+
tokens: agentCostTokensSchema2.optional(),
|
|
593
|
+
eur: z2.number().nonnegative().optional(),
|
|
594
|
+
usd: z2.number().nonnegative().optional()
|
|
595
|
+
});
|
|
596
|
+
AGENT_INFO_MAX_KEYS2 = 32;
|
|
597
|
+
AGENT_TOOL_CALLS_MAX_KEYS2 = 64;
|
|
598
|
+
AGENT_OTEL_SPANS_MAX2 = 32;
|
|
599
|
+
agentToolCallsSchema2 = z2.record(z2.string().min(1), nonNegativeInt2);
|
|
600
|
+
agentOtelSpanStatusSchema2 = z2.enum(["ok", "error"]);
|
|
601
|
+
agentOtelSpanSummarySchema2 = z2.object({
|
|
602
|
+
name: z2.string().min(1),
|
|
603
|
+
durationMs: z2.number().nonnegative(),
|
|
604
|
+
status: agentOtelSpanStatusSchema2
|
|
605
|
+
});
|
|
606
|
+
agentOtelSchema2 = z2.object({
|
|
607
|
+
traceId: z2.string().min(1),
|
|
608
|
+
spanId: z2.string().min(1).optional(),
|
|
609
|
+
rootDurationMs: z2.number().nonnegative().optional(),
|
|
610
|
+
spans: z2.array(agentOtelSpanSummarySchema2).max(AGENT_OTEL_SPANS_MAX2).optional()
|
|
611
|
+
});
|
|
612
|
+
agentTelemetrySchema2 = z2.object({
|
|
613
|
+
version: z2.string().min(1).optional(),
|
|
614
|
+
toolCallCount: nonNegativeInt2.optional(),
|
|
615
|
+
toolCalls: agentToolCallsSchema2.optional(),
|
|
616
|
+
cost: agentCostSchema2.optional(),
|
|
617
|
+
info: z2.record(z2.string(), z2.unknown()).optional(),
|
|
618
|
+
otel: agentOtelSchema2.optional()
|
|
619
|
+
}).refine(
|
|
620
|
+
(data) => {
|
|
621
|
+
const keys = data.info ? Object.keys(data.info) : [];
|
|
622
|
+
return keys.length <= AGENT_INFO_MAX_KEYS2;
|
|
623
|
+
},
|
|
624
|
+
{ message: `agent.info may contain at most ${AGENT_INFO_MAX_KEYS2} keys` }
|
|
625
|
+
).refine(
|
|
626
|
+
(data) => {
|
|
627
|
+
const keys = data.toolCalls ? Object.keys(data.toolCalls) : [];
|
|
628
|
+
return keys.length <= AGENT_TOOL_CALLS_MAX_KEYS2;
|
|
629
|
+
},
|
|
630
|
+
{
|
|
631
|
+
message: `agent.toolCalls may contain at most ${AGENT_TOOL_CALLS_MAX_KEYS2} tool names`
|
|
632
|
+
}
|
|
633
|
+
);
|
|
634
|
+
createTaskBodySchema2 = taskContextObjectSchema2.extend({
|
|
635
|
+
assignTo: assignToSchema2.optional(),
|
|
636
|
+
/**
|
|
637
|
+
* Groups related tasks together. When omitted, the server generates one and
|
|
638
|
+
* returns it so the caller can reuse it on later tasks in the same thread.
|
|
639
|
+
*/
|
|
640
|
+
threadId: z2.string().min(1).optional(),
|
|
641
|
+
/**
|
|
642
|
+
* Optional thread priority. When set, applies to the whole thread and
|
|
643
|
+
* overwrites any previous priority. Omit on later tasks to leave unchanged.
|
|
644
|
+
*/
|
|
645
|
+
priority: taskPrioritySchema2.optional(),
|
|
646
|
+
/**
|
|
647
|
+
* Optional initial status update logged against the task's thread. Shows in
|
|
648
|
+
* the inbox status bar and the thread update log.
|
|
649
|
+
*/
|
|
650
|
+
update: threadUpdateInputSchema2.optional(),
|
|
651
|
+
agent: agentTelemetrySchema2.optional()
|
|
652
|
+
}).superRefine(refineContextPublicUrls2);
|
|
653
|
+
threadUpdateBodySchema = threadUpdateInputSchema2;
|
|
205
654
|
}
|
|
206
655
|
});
|
|
207
656
|
|
|
@@ -346,7 +795,7 @@ var DEFAULT_POLL_INTERVAL_MS, DEFAULT_TIMEOUT_MS, RobotRockError, RobotRock;
|
|
|
346
795
|
var init_client = __esm({
|
|
347
796
|
"src/client.ts"() {
|
|
348
797
|
"use strict";
|
|
349
|
-
|
|
798
|
+
init_schemas2();
|
|
350
799
|
init_approval_result();
|
|
351
800
|
DEFAULT_POLL_INTERVAL_MS = 2e3;
|
|
352
801
|
DEFAULT_TIMEOUT_MS = 24 * 60 * 60 * 1e3;
|
|
@@ -402,7 +851,7 @@ var init_client = __esm({
|
|
|
402
851
|
...task2.update !== void 0 ? { update: task2.update } : {},
|
|
403
852
|
...task2.agent !== void 0 ? { agent: task2.agent } : {}
|
|
404
853
|
};
|
|
405
|
-
const validation =
|
|
854
|
+
const validation = createTaskBodySchema2.safeParse(bodyPayload);
|
|
406
855
|
if (!validation.success) {
|
|
407
856
|
throw new RobotRockError(
|
|
408
857
|
`Invalid task: ${validation.error.issues[0]?.message}`,
|
|
@@ -845,7 +1294,7 @@ var init_workflow = __esm({
|
|
|
845
1294
|
import { tool } from "ai";
|
|
846
1295
|
|
|
847
1296
|
// src/ai/approve-by-human-tool-core.ts
|
|
848
|
-
import { z as
|
|
1297
|
+
import { z as z3 } from "zod";
|
|
849
1298
|
|
|
850
1299
|
// src/ai/context.ts
|
|
851
1300
|
init_client();
|
|
@@ -989,11 +1438,11 @@ var APPROVE_BY_HUMAN_ACTIONS4 = [
|
|
|
989
1438
|
{ id: "approve", title: "Approve" },
|
|
990
1439
|
{ id: "decline", title: "Decline" }
|
|
991
1440
|
];
|
|
992
|
-
var approveByHumanInputSchema =
|
|
993
|
-
type:
|
|
994
|
-
name:
|
|
995
|
-
description:
|
|
996
|
-
contextSummary:
|
|
1441
|
+
var approveByHumanInputSchema = z3.object({
|
|
1442
|
+
type: z3.string().optional().describe("Task type slug; defaults to ai-approval"),
|
|
1443
|
+
name: z3.string().describe("Short title for the approval request"),
|
|
1444
|
+
description: z3.string().describe("What needs approval and the consequences of approving or declining"),
|
|
1445
|
+
contextSummary: z3.string().optional().describe("Optional markdown summary shown to the reviewer")
|
|
997
1446
|
});
|
|
998
1447
|
function resolveApproveByHumanToolConfig(clientOrContext, maybeOptions = {}) {
|
|
999
1448
|
const isDurable = typeof clientOrContext === "object" && clientOrContext !== null && "mode" in clientOrContext && (clientOrContext.mode === "trigger" || clientOrContext.mode === "workflow");
|
|
@@ -1042,18 +1491,18 @@ function approveByHumanTool(clientOrContext, maybeOptions = {}) {
|
|
|
1042
1491
|
import { tool as tool2 } from "ai";
|
|
1043
1492
|
|
|
1044
1493
|
// src/ai/create-send-to-human-tool-core.ts
|
|
1045
|
-
|
|
1046
|
-
import { z as
|
|
1047
|
-
var sendToHumanToolInputSchema =
|
|
1048
|
-
type:
|
|
1049
|
-
name:
|
|
1050
|
-
description:
|
|
1051
|
-
context:
|
|
1052
|
-
data:
|
|
1053
|
-
ui:
|
|
1494
|
+
init_schemas2();
|
|
1495
|
+
import { z as z4 } from "zod";
|
|
1496
|
+
var sendToHumanToolInputSchema = z4.object({
|
|
1497
|
+
type: z4.string().describe("Task type slug shown in the RobotRock inbox"),
|
|
1498
|
+
name: z4.string().describe("Short title for the human reviewer"),
|
|
1499
|
+
description: z4.string().optional().describe("What you need from the human and why you cannot proceed alone"),
|
|
1500
|
+
context: z4.object({
|
|
1501
|
+
data: z4.record(z4.string(), z4.unknown()).optional(),
|
|
1502
|
+
ui: z4.record(z4.string(), z4.unknown()).optional()
|
|
1054
1503
|
}).optional().describe("Optional structured context for the inbox UI"),
|
|
1055
|
-
validUntil:
|
|
1056
|
-
assignTo:
|
|
1504
|
+
validUntil: z4.string().datetime().optional().describe("Optional ISO deadline for the task"),
|
|
1505
|
+
assignTo: assignToSchema2.optional().describe(
|
|
1057
1506
|
"Assign to tenant member emails and/or group slugs; narrows who sees the task in the inbox"
|
|
1058
1507
|
)
|
|
1059
1508
|
});
|
|
@@ -1104,15 +1553,15 @@ function createSendToHumanTool(clientOrOptions, maybeOptions) {
|
|
|
1104
1553
|
import { tool as tool3 } from "ai";
|
|
1105
1554
|
|
|
1106
1555
|
// src/ai/create-send-update-tool-core.ts
|
|
1107
|
-
|
|
1556
|
+
init_schemas2();
|
|
1108
1557
|
init_client();
|
|
1109
|
-
import { z as
|
|
1110
|
-
var sendUpdateToolInputSchema =
|
|
1111
|
-
threadId:
|
|
1558
|
+
import { z as z5 } from "zod";
|
|
1559
|
+
var sendUpdateToolInputSchema = z5.object({
|
|
1560
|
+
threadId: z5.string().optional().describe(
|
|
1112
1561
|
"Thread to post the update to. Use the `threadId` returned by a prior send-to-human task. Omit only when a session threadId is configured on the tool."
|
|
1113
1562
|
),
|
|
1114
|
-
message:
|
|
1115
|
-
status:
|
|
1563
|
+
message: z5.string().describe("Short progress update (1-2 sentences) shown in the inbox status bar"),
|
|
1564
|
+
status: threadUpdateStatusSchema2.optional().describe(
|
|
1116
1565
|
"Lifecycle status driving the status-bar icon/color: info, queued, running, waiting, succeeded, failed, cancelled"
|
|
1117
1566
|
)
|
|
1118
1567
|
});
|