robotrock 0.9.0 → 1.0.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/dist/ai/index.d.ts +18 -7
- package/dist/ai/index.js +581 -82
- package/dist/ai/index.js.map +1 -1
- package/dist/ai/trigger.d.ts +4 -3
- package/dist/ai/trigger.js +539 -82
- package/dist/ai/trigger.js.map +1 -1
- package/dist/ai/workflow.d.ts +15 -4
- package/dist/ai/workflow.js +458 -82
- package/dist/ai/workflow.js.map +1 -1
- package/dist/{client-Cy7YLxms.d.ts → client-CzVmjXpz.d.ts} +86 -12
- package/dist/index.d.ts +10 -3
- package/dist/index.js +263 -66
- package/dist/index.js.map +1 -1
- package/dist/schemas/index.d.ts +11 -1
- package/dist/schemas/index.js +59 -4
- package/dist/schemas/index.js.map +1 -1
- package/dist/{tool-approval-bridge-G765kMJR.d.ts → tool-approval-bridge-DbwUEBHv.d.ts} +93 -2
- package/dist/trigger/index.d.ts +2 -1
- package/dist/trigger/index.js +250 -56
- package/dist/trigger/index.js.map +1 -1
- package/dist/{trigger-D0shjqk0.d.ts → trigger-BCKBbAV7.d.ts} +64 -3
- package/dist/workflow/index.d.ts +2 -1
- package/dist/workflow/index.js +251 -57
- package/dist/workflow/index.js.map +1 -1
- package/package.json +1 -1
package/dist/trigger/index.js
CHANGED
|
@@ -399,13 +399,15 @@ var triggerHandlerSchema = webhookHandlerSchema.extend({
|
|
|
399
399
|
tokenId: z.string().min(1)
|
|
400
400
|
});
|
|
401
401
|
var handlerSchema = z.discriminatedUnion("type", [webhookHandlerSchema, triggerHandlerSchema]);
|
|
402
|
-
var
|
|
402
|
+
var taskActionInputSchema = z.object({
|
|
403
403
|
id: z.string().min(1),
|
|
404
404
|
title: z.string().min(1),
|
|
405
405
|
description: z.string().optional(),
|
|
406
406
|
schema: jsonSchema7Schema.optional(),
|
|
407
407
|
ui: uiSchemaSchema.optional(),
|
|
408
|
-
data: z.record(z.string(), z.unknown()).optional()
|
|
408
|
+
data: z.record(z.string(), z.unknown()).optional()
|
|
409
|
+
});
|
|
410
|
+
var taskActionSchema = taskActionInputSchema.extend({
|
|
409
411
|
// Optional handlers for this action - if present, must have at least 1
|
|
410
412
|
handlers: z.array(handlerSchema).min(1).optional()
|
|
411
413
|
});
|
|
@@ -513,6 +515,56 @@ var createTaskBodySchema = taskContextObjectBaseSchema.extend({
|
|
|
513
515
|
/** Agent release version — not shown in inbox UI. */
|
|
514
516
|
agent: agentTelemetrySchema.optional()
|
|
515
517
|
}).transform(normalizeTaskContextVersion).superRefine(refineContextPublicUrls);
|
|
518
|
+
var agentChatSeedActionSchema = z.object({
|
|
519
|
+
/** Stable action id echoed back on submit; auto-derived from title when omitted. */
|
|
520
|
+
id: z.string().min(1).optional(),
|
|
521
|
+
title: z.string().min(1),
|
|
522
|
+
description: z.string().optional(),
|
|
523
|
+
/** JSON Schema object for the form fields. */
|
|
524
|
+
schema: z.record(z.string(), z.unknown()).optional(),
|
|
525
|
+
/** RJSF ui schema overrides (ui:widget, ui:enumNames, etc.). */
|
|
526
|
+
ui: z.record(z.string(), z.unknown()).optional(),
|
|
527
|
+
/** Optional default field values. */
|
|
528
|
+
data: z.record(z.string(), z.unknown()).optional()
|
|
529
|
+
});
|
|
530
|
+
var agentChatSeedMessageSchema = z.object({
|
|
531
|
+
role: z.enum(["user", "assistant"]),
|
|
532
|
+
text: z.string().min(1),
|
|
533
|
+
/** Optional display-name override for the message sender. */
|
|
534
|
+
senderName: z.string().min(1).optional(),
|
|
535
|
+
/**
|
|
536
|
+
* Optional structured input request rendered as a styled RobotRock action
|
|
537
|
+
* widget below the message text. Use this instead of asking the user to reply
|
|
538
|
+
* in plain text so the request is always a proper action form.
|
|
539
|
+
*/
|
|
540
|
+
requestActionInput: z.object({
|
|
541
|
+
prompt: z.string().optional(),
|
|
542
|
+
action: agentChatSeedActionSchema
|
|
543
|
+
}).optional()
|
|
544
|
+
});
|
|
545
|
+
var createAgentChatBodySchema = z.object({
|
|
546
|
+
/** Trigger chat agent id (task slug). Required unless `parentChatId` is set. */
|
|
547
|
+
agentIdentifier: z.string().min(1).optional(),
|
|
548
|
+
/** Inherit tenant/connection/agent from an existing chat (agent-spawned chats). */
|
|
549
|
+
parentChatId: z.string().min(1).optional(),
|
|
550
|
+
/** Convex tenantTriggerConnections id; resolved from the tenant when omitted. */
|
|
551
|
+
connectionId: z.string().min(1).optional(),
|
|
552
|
+
/** Source application id; groups the chat under an inbox section. */
|
|
553
|
+
app: z.string().min(1).optional(),
|
|
554
|
+
assignTo: assignToSchema.optional(),
|
|
555
|
+
title: z.string().min(1),
|
|
556
|
+
messages: z.array(agentChatSeedMessageSchema).default([]),
|
|
557
|
+
/** Provenance label stored on the session ("cron" | "agent" | ...). */
|
|
558
|
+
source: z.string().min(1).optional()
|
|
559
|
+
}).refine((data) => Boolean(data.agentIdentifier || data.parentChatId), {
|
|
560
|
+
message: "Provide either agentIdentifier or parentChatId"
|
|
561
|
+
});
|
|
562
|
+
var agentChatTransportBodySchema = z.object({
|
|
563
|
+
chatId: z.string().min(1),
|
|
564
|
+
publicAccessToken: z.string().min(1),
|
|
565
|
+
lastEventId: z.string().optional(),
|
|
566
|
+
isStreaming: z.boolean().optional()
|
|
567
|
+
});
|
|
516
568
|
|
|
517
569
|
// src/schemas/index.ts
|
|
518
570
|
var safeUrlSchema2 = z2.string().refine((url) => isPublicHttpUrl(url), {
|
|
@@ -535,13 +587,15 @@ var triggerHandlerSchema2 = webhookHandlerSchema2.extend({
|
|
|
535
587
|
tokenId: z2.string().min(1)
|
|
536
588
|
});
|
|
537
589
|
var handlerSchema2 = z2.discriminatedUnion("type", [webhookHandlerSchema2, triggerHandlerSchema2]);
|
|
538
|
-
var
|
|
590
|
+
var taskActionInputSchema2 = z2.object({
|
|
539
591
|
id: z2.string().min(1),
|
|
540
592
|
title: z2.string().min(1),
|
|
541
593
|
description: z2.string().optional(),
|
|
542
594
|
schema: jsonSchema7Schema2.optional(),
|
|
543
595
|
ui: uiSchemaSchema2.optional(),
|
|
544
|
-
data: z2.record(z2.string(), z2.unknown()).optional()
|
|
596
|
+
data: z2.record(z2.string(), z2.unknown()).optional()
|
|
597
|
+
});
|
|
598
|
+
var taskActionSchema2 = taskActionInputSchema2.extend({
|
|
545
599
|
handlers: z2.array(handlerSchema2).min(1).optional()
|
|
546
600
|
});
|
|
547
601
|
var uiFieldSchemaSchema2 = z2.object({
|
|
@@ -673,6 +727,149 @@ function toDiscriminatedApprovalResult(actions, task2) {
|
|
|
673
727
|
};
|
|
674
728
|
}
|
|
675
729
|
|
|
730
|
+
// src/http.ts
|
|
731
|
+
var RobotRockError = class extends Error {
|
|
732
|
+
constructor(message, statusCode, response) {
|
|
733
|
+
super(message);
|
|
734
|
+
this.statusCode = statusCode;
|
|
735
|
+
this.response = response;
|
|
736
|
+
this.name = "RobotRockError";
|
|
737
|
+
}
|
|
738
|
+
};
|
|
739
|
+
async function parseResponseBody(response) {
|
|
740
|
+
const contentType = response.headers.get("content-type") ?? "";
|
|
741
|
+
const bodyText = await response.text();
|
|
742
|
+
if (!bodyText) {
|
|
743
|
+
return null;
|
|
744
|
+
}
|
|
745
|
+
if (contentType.toLowerCase().includes("application/json")) {
|
|
746
|
+
try {
|
|
747
|
+
return JSON.parse(bodyText);
|
|
748
|
+
} catch {
|
|
749
|
+
}
|
|
750
|
+
}
|
|
751
|
+
try {
|
|
752
|
+
return JSON.parse(bodyText);
|
|
753
|
+
} catch {
|
|
754
|
+
return bodyText;
|
|
755
|
+
}
|
|
756
|
+
}
|
|
757
|
+
function getErrorMessage(data, fallback) {
|
|
758
|
+
if (data && typeof data === "object" && !Array.isArray(data)) {
|
|
759
|
+
const maybeMessage = data.message;
|
|
760
|
+
if (typeof maybeMessage === "string" && maybeMessage.trim()) {
|
|
761
|
+
return maybeMessage;
|
|
762
|
+
}
|
|
763
|
+
}
|
|
764
|
+
if (typeof data === "string" && data.trim()) {
|
|
765
|
+
const compact = data.replace(/\s+/g, " ").trim();
|
|
766
|
+
const snippet = compact.length > 180 ? `${compact.slice(0, 180)}...` : compact;
|
|
767
|
+
return `${fallback}. Server returned non-JSON response: ${snippet}`;
|
|
768
|
+
}
|
|
769
|
+
return fallback;
|
|
770
|
+
}
|
|
771
|
+
|
|
772
|
+
// ../core/src/handler-retry.ts
|
|
773
|
+
var HANDLER_RETRY_DELAYS_MS = [
|
|
774
|
+
6e4,
|
|
775
|
+
// 1m
|
|
776
|
+
3e5,
|
|
777
|
+
// 5m
|
|
778
|
+
18e5,
|
|
779
|
+
// 30m
|
|
780
|
+
36e5,
|
|
781
|
+
// 1h
|
|
782
|
+
216e5,
|
|
783
|
+
// 6h
|
|
784
|
+
864e5,
|
|
785
|
+
// 24h
|
|
786
|
+
1728e5
|
|
787
|
+
// 48h
|
|
788
|
+
];
|
|
789
|
+
var HANDLER_MAX_ATTEMPTS = HANDLER_RETRY_DELAYS_MS.length + 1;
|
|
790
|
+
|
|
791
|
+
// ../core/src/attribution/index.ts
|
|
792
|
+
import { z as z3 } from "zod";
|
|
793
|
+
|
|
794
|
+
// ../core/src/app-url.ts
|
|
795
|
+
var PRODUCTION_APP_URL = "https://app.robotrock.io";
|
|
796
|
+
var APP_SIGNUP_URL = `${PRODUCTION_APP_URL}/sign-up`;
|
|
797
|
+
|
|
798
|
+
// ../core/src/attribution/index.ts
|
|
799
|
+
var ATTRIBUTION_COOKIE_MAX_AGE = 60 * 60 * 24 * 90;
|
|
800
|
+
var attributionSchema = z3.object({
|
|
801
|
+
utmSource: z3.string().optional(),
|
|
802
|
+
utmMedium: z3.string().optional(),
|
|
803
|
+
utmCampaign: z3.string().optional(),
|
|
804
|
+
utmContent: z3.string().optional(),
|
|
805
|
+
utmTerm: z3.string().optional(),
|
|
806
|
+
gclid: z3.string().optional(),
|
|
807
|
+
landingUrl: z3.string().optional(),
|
|
808
|
+
referrer: z3.string().optional(),
|
|
809
|
+
capturedAt: z3.number()
|
|
810
|
+
});
|
|
811
|
+
|
|
812
|
+
// src/chats.ts
|
|
813
|
+
function createChatsApi(config) {
|
|
814
|
+
const headers = () => ({
|
|
815
|
+
"Content-Type": "application/json",
|
|
816
|
+
"X-Api-Key": config.apiKey
|
|
817
|
+
});
|
|
818
|
+
return {
|
|
819
|
+
async create(input) {
|
|
820
|
+
const bodyPayload = {
|
|
821
|
+
...input,
|
|
822
|
+
app: input.app ?? config.app,
|
|
823
|
+
messages: input.messages ?? []
|
|
824
|
+
};
|
|
825
|
+
const validation = createAgentChatBodySchema.safeParse(bodyPayload);
|
|
826
|
+
if (!validation.success) {
|
|
827
|
+
throw new RobotRockError(
|
|
828
|
+
`Invalid chat: ${validation.error.issues[0]?.message}`,
|
|
829
|
+
400,
|
|
830
|
+
validation.error.issues
|
|
831
|
+
);
|
|
832
|
+
}
|
|
833
|
+
const response = await fetch(`${config.baseUrl}/agent-chats`, {
|
|
834
|
+
method: "POST",
|
|
835
|
+
headers: headers(),
|
|
836
|
+
body: JSON.stringify(validation.data)
|
|
837
|
+
});
|
|
838
|
+
const data = await parseResponseBody(response);
|
|
839
|
+
if (!response.ok) {
|
|
840
|
+
throw new RobotRockError(
|
|
841
|
+
getErrorMessage(data, "Failed to create chat"),
|
|
842
|
+
response.status,
|
|
843
|
+
data
|
|
844
|
+
);
|
|
845
|
+
}
|
|
846
|
+
const result = data;
|
|
847
|
+
return { tenantSlug: result.tenantSlug, chats: result.chats };
|
|
848
|
+
},
|
|
849
|
+
async close(chatId, options) {
|
|
850
|
+
if (!chatId) {
|
|
851
|
+
throw new RobotRockError("chatId is required to close a chat", 400);
|
|
852
|
+
}
|
|
853
|
+
const response = await fetch(
|
|
854
|
+
`${config.baseUrl}/agent-chats/${encodeURIComponent(chatId)}/close`,
|
|
855
|
+
{
|
|
856
|
+
method: "POST",
|
|
857
|
+
headers: headers(),
|
|
858
|
+
body: JSON.stringify({ reason: options?.reason })
|
|
859
|
+
}
|
|
860
|
+
);
|
|
861
|
+
if (!response.ok) {
|
|
862
|
+
const data = await parseResponseBody(response);
|
|
863
|
+
throw new RobotRockError(
|
|
864
|
+
getErrorMessage(data, "Failed to close chat"),
|
|
865
|
+
response.status,
|
|
866
|
+
data
|
|
867
|
+
);
|
|
868
|
+
}
|
|
869
|
+
}
|
|
870
|
+
};
|
|
871
|
+
}
|
|
872
|
+
|
|
676
873
|
// src/client.ts
|
|
677
874
|
var DEFAULT_POLL_INTERVAL_MS = 2e3;
|
|
678
875
|
var DEFAULT_TIMEOUT_MS = 24 * 60 * 60 * 1e3;
|
|
@@ -710,14 +907,6 @@ function serializeValidUntil(value) {
|
|
|
710
907
|
}
|
|
711
908
|
throw new RobotRockError("Invalid validUntil: expected a Date or parseable date string", 400);
|
|
712
909
|
}
|
|
713
|
-
var RobotRockError = class extends Error {
|
|
714
|
-
constructor(message, statusCode, response) {
|
|
715
|
-
super(message);
|
|
716
|
-
this.statusCode = statusCode;
|
|
717
|
-
this.response = response;
|
|
718
|
-
this.name = "RobotRockError";
|
|
719
|
-
}
|
|
720
|
-
};
|
|
721
910
|
var RobotRock = class {
|
|
722
911
|
apiKey;
|
|
723
912
|
baseUrl;
|
|
@@ -726,6 +915,10 @@ var RobotRock = class {
|
|
|
726
915
|
contextVersion;
|
|
727
916
|
webhook;
|
|
728
917
|
polling;
|
|
918
|
+
/** Task CRUD: `create`, `get`, `cancel`, `sendUpdate`. */
|
|
919
|
+
tasks;
|
|
920
|
+
/** Chat CRUD: `create`, `close`. */
|
|
921
|
+
chats;
|
|
729
922
|
constructor(config) {
|
|
730
923
|
if (config.webhook && config.polling) {
|
|
731
924
|
throw new Error(
|
|
@@ -746,11 +939,19 @@ var RobotRock = class {
|
|
|
746
939
|
this.contextVersion = config.advanced?.contextVersion ?? TASK_CONTEXT_FORMAT_VERSION2;
|
|
747
940
|
this.webhook = config.webhook;
|
|
748
941
|
this.polling = config.polling ?? {};
|
|
942
|
+
this.tasks = {
|
|
943
|
+
create: (task2) => this.createTaskRequest(task2),
|
|
944
|
+
get: (taskId) => this.getTaskById(taskId),
|
|
945
|
+
cancel: (taskId) => this.cancelTaskRequest(taskId),
|
|
946
|
+
sendUpdate: (input) => this.sendThreadUpdate(input)
|
|
947
|
+
};
|
|
948
|
+
this.chats = createChatsApi({
|
|
949
|
+
baseUrl: this.baseUrl,
|
|
950
|
+
apiKey: this.apiKey,
|
|
951
|
+
app: this.app
|
|
952
|
+
});
|
|
749
953
|
}
|
|
750
|
-
|
|
751
|
-
* Create a task via POST /v1 without waiting for a human response.
|
|
752
|
-
*/
|
|
753
|
-
async createTask(task2) {
|
|
954
|
+
async createTaskRequest(task2) {
|
|
754
955
|
const normalizedTask = normalizeSendToHumanInput(task2, {
|
|
755
956
|
webhook: this.webhook,
|
|
756
957
|
app: this.app,
|
|
@@ -803,7 +1004,7 @@ var RobotRock = class {
|
|
|
803
1004
|
contextVersion: this.contextVersion,
|
|
804
1005
|
agentVersion: this.agentVersion
|
|
805
1006
|
});
|
|
806
|
-
const createdTaskTask = await this.
|
|
1007
|
+
const createdTaskTask = await this.createTaskRequest(task2);
|
|
807
1008
|
const hasHandlers = normalizedTask.actions.some(
|
|
808
1009
|
(action) => Array.isArray(action.handlers) && action.handlers.length > 0
|
|
809
1010
|
);
|
|
@@ -820,7 +1021,7 @@ var RobotRock = class {
|
|
|
820
1021
|
const deadline = validUntilMs !== void 0 ? Math.min(pollingDeadline, validUntilMs) : pollingDeadline;
|
|
821
1022
|
const taskId = createdTaskTask.taskId;
|
|
822
1023
|
while (Date.now() < deadline) {
|
|
823
|
-
const existing = await this.
|
|
1024
|
+
const existing = await this.getTaskById(taskId);
|
|
824
1025
|
if (existing?.status === "handled" && existing.handled) {
|
|
825
1026
|
return {
|
|
826
1027
|
mode: "handled",
|
|
@@ -842,10 +1043,35 @@ var RobotRock = class {
|
|
|
842
1043
|
}
|
|
843
1044
|
throw new TaskTimeoutError(`No human response within ${timeoutMs}ms`);
|
|
844
1045
|
}
|
|
1046
|
+
/**
|
|
1047
|
+
* Create a task via POST /v1 without waiting for a human response.
|
|
1048
|
+
* @deprecated Use `client.tasks.create()` instead.
|
|
1049
|
+
*/
|
|
1050
|
+
async createTask(task2) {
|
|
1051
|
+
return this.tasks.create(task2);
|
|
1052
|
+
}
|
|
845
1053
|
/**
|
|
846
1054
|
* Get a task by public task id (returned as `task.taskId` from {@link sendToHuman}).
|
|
1055
|
+
* @deprecated Use `client.tasks.get()` instead.
|
|
847
1056
|
*/
|
|
848
1057
|
async getTask(taskId) {
|
|
1058
|
+
return this.tasks.get(taskId);
|
|
1059
|
+
}
|
|
1060
|
+
/**
|
|
1061
|
+
* Log a status update against a thread.
|
|
1062
|
+
* @deprecated Use `client.tasks.sendUpdate()` instead.
|
|
1063
|
+
*/
|
|
1064
|
+
async sendUpdate(input) {
|
|
1065
|
+
return this.tasks.sendUpdate(input);
|
|
1066
|
+
}
|
|
1067
|
+
/**
|
|
1068
|
+
* Cancel a task by public task id.
|
|
1069
|
+
* @deprecated Use `client.tasks.cancel()` instead.
|
|
1070
|
+
*/
|
|
1071
|
+
async cancelTask(taskId) {
|
|
1072
|
+
return this.tasks.cancel(taskId);
|
|
1073
|
+
}
|
|
1074
|
+
async getTaskById(taskId) {
|
|
849
1075
|
const response = await fetch(`${this.baseUrl}/tasks/${taskId}`, {
|
|
850
1076
|
method: "GET",
|
|
851
1077
|
headers: {
|
|
@@ -865,11 +1091,11 @@ var RobotRock = class {
|
|
|
865
1091
|
}
|
|
866
1092
|
return data;
|
|
867
1093
|
}
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
1094
|
+
async sendThreadUpdate({
|
|
1095
|
+
threadId,
|
|
1096
|
+
message,
|
|
1097
|
+
status
|
|
1098
|
+
}) {
|
|
873
1099
|
if (!threadId) {
|
|
874
1100
|
throw new RobotRockError("threadId is required to send an update", 400);
|
|
875
1101
|
}
|
|
@@ -902,7 +1128,7 @@ var RobotRock = class {
|
|
|
902
1128
|
}
|
|
903
1129
|
return data.update;
|
|
904
1130
|
}
|
|
905
|
-
async
|
|
1131
|
+
async cancelTaskRequest(taskId) {
|
|
906
1132
|
const response = await fetch(`${this.baseUrl}/tasks/${taskId}/cancel`, {
|
|
907
1133
|
method: "POST",
|
|
908
1134
|
headers: {
|
|
@@ -961,38 +1187,6 @@ function normalizeSendToHumanInput(task2, clientDefaults) {
|
|
|
961
1187
|
actions: normalizedActions
|
|
962
1188
|
};
|
|
963
1189
|
}
|
|
964
|
-
async function parseResponseBody(response) {
|
|
965
|
-
const contentType = response.headers.get("content-type") ?? "";
|
|
966
|
-
const bodyText = await response.text();
|
|
967
|
-
if (!bodyText) {
|
|
968
|
-
return null;
|
|
969
|
-
}
|
|
970
|
-
if (contentType.toLowerCase().includes("application/json")) {
|
|
971
|
-
try {
|
|
972
|
-
return JSON.parse(bodyText);
|
|
973
|
-
} catch {
|
|
974
|
-
}
|
|
975
|
-
}
|
|
976
|
-
try {
|
|
977
|
-
return JSON.parse(bodyText);
|
|
978
|
-
} catch {
|
|
979
|
-
return bodyText;
|
|
980
|
-
}
|
|
981
|
-
}
|
|
982
|
-
function getErrorMessage(data, fallback) {
|
|
983
|
-
if (data && typeof data === "object" && !Array.isArray(data)) {
|
|
984
|
-
const maybeMessage = data.message;
|
|
985
|
-
if (typeof maybeMessage === "string" && maybeMessage.trim()) {
|
|
986
|
-
return maybeMessage;
|
|
987
|
-
}
|
|
988
|
-
}
|
|
989
|
-
if (typeof data === "string" && data.trim()) {
|
|
990
|
-
const compact = data.replace(/\s+/g, " ").trim();
|
|
991
|
-
const snippet = compact.length > 180 ? `${compact.slice(0, 180)}...` : compact;
|
|
992
|
-
return `${fallback}. Server returned non-JSON response: ${snippet}`;
|
|
993
|
-
}
|
|
994
|
-
return fallback;
|
|
995
|
-
}
|
|
996
1190
|
|
|
997
1191
|
// src/env.ts
|
|
998
1192
|
var DEFAULT_BASE_URL = "https://api.robotrock.io/v1";
|