@cadraos/sdk 0.1.2 → 0.1.3

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 CHANGED
@@ -398,4 +398,4 @@ const stream = await client.agents.stream(uuid, { task: '...' });
398
398
 
399
399
  ## License
400
400
 
401
- MIT
401
+ Apache-2.0
package/dist/index.cjs CHANGED
@@ -405,6 +405,9 @@ var SSEClient = class {
405
405
  */
406
406
  async connect() {
407
407
  this.abortController = new AbortController();
408
+ console.log("[SDK:SSE] Connecting to:", this.config.url);
409
+ console.log("[SDK:SSE] Auth header:", this.config.authHeader ? `${this.config.authHeader.substring(0, 30)}...` : "MISSING");
410
+ console.log("[SDK:SSE] Org ID:", this.config.orgId);
408
411
  try {
409
412
  const response = await fetch(this.config.url, {
410
413
  method: "GET",
@@ -416,23 +419,39 @@ var SSEClient = class {
416
419
  },
417
420
  signal: this.abortController.signal
418
421
  });
422
+ console.log("[SDK:SSE] Response status:", response.status, response.statusText);
423
+ console.log("[SDK:SSE] Response headers:", {
424
+ contentType: response.headers.get("content-type"),
425
+ cacheControl: response.headers.get("cache-control")
426
+ });
419
427
  if (!response.ok) {
420
- throw new Error(`SSE connection failed: ${response.status} ${response.statusText}`);
428
+ let errorBody = "";
429
+ try {
430
+ errorBody = await response.text();
431
+ console.error("[SDK:SSE] Error response body:", errorBody);
432
+ } catch (e) {
433
+ console.error("[SDK:SSE] Could not read error body");
434
+ }
435
+ throw new Error(`SSE connection failed: ${response.status} ${response.statusText} - ${errorBody}`);
421
436
  }
422
437
  if (!response.body) {
423
438
  throw new Error("Response body not available");
424
439
  }
440
+ console.log("[SDK:SSE] Connection successful, starting stream parsing");
425
441
  this.connected = true;
426
442
  this.config.onConnectionChange(true);
427
443
  await this.parseStream(response.body);
428
444
  } catch (error) {
429
445
  if (error instanceof Error && error.name === "AbortError") {
446
+ console.log("[SDK:SSE] Connection aborted (intentional)");
430
447
  return;
431
448
  }
449
+ console.error("[SDK:SSE] Connection error:", error);
432
450
  this.config.onError(error instanceof Error ? error : new Error(String(error)));
433
451
  } finally {
434
452
  this.connected = false;
435
453
  this.config.onConnectionChange(false);
454
+ console.log("[SDK:SSE] Connection closed");
436
455
  }
437
456
  }
438
457
  /**
@@ -459,18 +478,29 @@ var SSEClient = class {
459
478
  const decoder = new TextDecoder();
460
479
  let buffer = "";
461
480
  let currentEvent = {};
481
+ let chunkCount = 0;
482
+ let eventCount = 0;
483
+ console.log("[SDK:SSE] Starting to parse stream");
462
484
  try {
463
485
  while (true) {
464
486
  const { done, value } = await reader.read();
465
487
  if (done) {
488
+ console.log("[SDK:SSE] Stream reading complete. Total chunks:", chunkCount, "events:", eventCount);
466
489
  break;
467
490
  }
468
- buffer += decoder.decode(value, { stream: true });
491
+ chunkCount++;
492
+ const chunk = decoder.decode(value, { stream: true });
493
+ buffer += chunk;
494
+ if (chunkCount <= 5) {
495
+ console.log(`[SDK:SSE] Chunk ${chunkCount} (${value.length} bytes):`, chunk.substring(0, 200));
496
+ }
469
497
  const lines = buffer.split("\n");
470
498
  buffer = lines.pop() ?? "";
471
499
  for (const line of lines) {
472
500
  if (line === "") {
473
501
  if (currentEvent.type && currentEvent.data !== void 0) {
502
+ eventCount++;
503
+ console.log(`[SDK:SSE] Event ${eventCount}:`, currentEvent.type, "- data length:", currentEvent.data.length);
474
504
  this.dispatchEvent(currentEvent);
475
505
  }
476
506
  currentEvent = {};
@@ -502,6 +532,7 @@ var SSEClient = class {
502
532
  }
503
533
  }
504
534
  } finally {
535
+ console.log("[SDK:SSE] parseStream finished. Releasing reader lock.");
505
536
  reader.releaseLock();
506
537
  }
507
538
  }
@@ -509,10 +540,12 @@ var SSEClient = class {
509
540
  * Dispatch parsed event
510
541
  */
511
542
  dispatchEvent(event) {
543
+ console.log("[SDK:SSE] dispatchEvent called:", event.type, "id:", event.id);
512
544
  try {
513
545
  let data;
514
546
  try {
515
547
  data = JSON.parse(event.data);
548
+ console.log("[SDK:SSE] Parsed event data:", typeof data, data && typeof data === "object" ? Object.keys(data) : "");
516
549
  } catch {
517
550
  data = event.data;
518
551
  }
@@ -556,6 +589,13 @@ var ExecutionStreamControllerImpl = class {
556
589
  toolCall: [],
557
590
  toolResult: [],
558
591
  plan: [],
592
+ paused: [],
593
+ started: [],
594
+ progress: [],
595
+ taskListUpdate: [],
596
+ delegationStarted: [],
597
+ delegationCompleted: [],
598
+ textDelta: [],
559
599
  complete: [],
560
600
  error: [],
561
601
  connectionChange: []
@@ -574,6 +614,18 @@ var ExecutionStreamControllerImpl = class {
574
614
  get lastEventId() {
575
615
  return this._lastEventId;
576
616
  }
617
+ /**
618
+ * Get the execution ID
619
+ */
620
+ get executionId() {
621
+ return this.options.executionId;
622
+ }
623
+ /**
624
+ * Get the session ID (if available)
625
+ */
626
+ get sessionId() {
627
+ return this.options.sessionId;
628
+ }
577
629
  /**
578
630
  * Connect to the execution stream
579
631
  */
@@ -635,13 +687,23 @@ var ExecutionStreamControllerImpl = class {
635
687
  */
636
688
  async connectSSE() {
637
689
  const url = `${this.options.baseUrl}/agents/runs/${this.options.executionId}/stream`;
690
+ console.log("[SDK:StreamController] Connecting to SSE");
691
+ console.log("[SDK:StreamController] URL:", url);
692
+ console.log("[SDK:StreamController] baseUrl:", this.options.baseUrl);
693
+ console.log("[SDK:StreamController] executionId:", this.options.executionId);
694
+ console.log("[SDK:StreamController] orgId:", this.options.orgId);
695
+ console.log("[SDK:StreamController] apiKey:", this.options.apiKey ? `${this.options.apiKey.substring(0, 20)}...` : "MISSING");
638
696
  this.sseClient = new SSEClient({
639
697
  url,
640
698
  authHeader: `Bearer ${this.options.apiKey}`,
641
699
  orgId: this.options.orgId,
642
700
  onEvent: (event) => this.handleEvent(event),
643
- onError: (error) => this.handleConnectionError(error),
701
+ onError: (error) => {
702
+ console.error("[SDK:StreamController] SSE error:", error);
703
+ this.handleConnectionError(error);
704
+ },
644
705
  onConnectionChange: (connected) => {
706
+ console.log("[SDK:StreamController] SSE connection change:", connected);
645
707
  if (connected) {
646
708
  this.status = "connected";
647
709
  this.reconnectAttempts = 0;
@@ -650,15 +712,23 @@ var ExecutionStreamControllerImpl = class {
650
712
  this.emit("connectionChange", { connected, usingFallback: false });
651
713
  }
652
714
  });
653
- await this.sseClient.connect();
715
+ try {
716
+ await this.sseClient.connect();
717
+ console.log("[SDK:StreamController] SSE connect() completed");
718
+ } catch (error) {
719
+ console.error("[SDK:StreamController] SSE connect() threw:", error);
720
+ throw error;
721
+ }
654
722
  }
655
723
  /**
656
724
  * Handle incoming SSE event
657
725
  */
658
726
  handleEvent(event) {
727
+ console.log("[SDK:StreamController] handleEvent called:", event.type, "id:", event.id);
659
728
  this.resetActivityTimeout();
660
729
  if (event.id) {
661
730
  if (this.seenEventIds.has(event.id)) {
731
+ console.log("[SDK:StreamController] Skipping duplicate event:", event.id);
662
732
  return;
663
733
  }
664
734
  this.seenEventIds.add(event.id);
@@ -669,24 +739,52 @@ var ExecutionStreamControllerImpl = class {
669
739
  }
670
740
  }
671
741
  const data = event.data;
742
+ console.log("[SDK:StreamController] Event data keys:", Object.keys(data));
672
743
  switch (event.type) {
673
- case "log":
674
- this.emit("log", data.log);
744
+ case "log": {
745
+ const rawLog = data.log;
746
+ if (!rawLog) {
747
+ console.warn("[StreamController] Received log event without log data");
748
+ break;
749
+ }
750
+ const logTypeValue = rawLog.logType || rawLog.type || "info";
751
+ const transformedLog = {
752
+ uuid: rawLog.uuid || `log-${rawLog.stepIndex || Date.now()}`,
753
+ type: logTypeValue,
754
+ title: rawLog.message || rawLog.title || "",
755
+ content: rawLog.content,
756
+ metadata: {
757
+ ...rawLog.metadata || {},
758
+ // Include stepIndex in metadata for deduplication
759
+ stepIndex: rawLog.stepIndex ?? 0
760
+ },
761
+ timestamp: rawLog.timestamp || (/* @__PURE__ */ new Date()).toISOString(),
762
+ durationMs: rawLog.durationMs
763
+ };
764
+ this.emit("log", transformedLog);
675
765
  break;
766
+ }
676
767
  case "tool_call":
677
768
  this.emit("toolCall", {
678
- toolCallId: data.toolCallId,
679
- toolName: data.toolName,
680
- inputs: data.args,
769
+ toolCallId: data.toolCallId || `tool-call-${Date.now()}`,
770
+ toolName: data.toolName || "Unknown Tool",
771
+ inputs: data.args || {},
681
772
  stepIndex: data.stepIndex ?? 0
682
773
  });
683
774
  break;
684
775
  case "tool_result":
685
776
  this.emit("toolResult", {
686
- toolCallId: data.toolCallId,
687
- toolName: data.toolName,
777
+ toolCallId: data.toolCallId || `tool-result-${Date.now()}`,
778
+ toolName: data.toolName || "Unknown Tool",
688
779
  result: data.result,
689
- durationMs: data.durationMs
780
+ durationMs: data.durationMs ?? 0
781
+ });
782
+ break;
783
+ case "execution_paused":
784
+ this.emit("paused", {
785
+ question: data.question || data.output || "",
786
+ options: data.options,
787
+ reason: "waiting_user_input"
690
788
  });
691
789
  break;
692
790
  case "complete":
@@ -698,6 +796,12 @@ var ExecutionStreamControllerImpl = class {
698
796
  errorCode: data.errorCode
699
797
  });
700
798
  break;
799
+ case "failed":
800
+ this.handleError({
801
+ error: data.error || data.message || "Execution failed",
802
+ errorCode: data.errorCode || "execution_failed"
803
+ });
804
+ break;
701
805
  case "timeout":
702
806
  if (data.retryable) {
703
807
  this.handleConnectionError(new Error("Stream timeout"));
@@ -708,6 +812,74 @@ var ExecutionStreamControllerImpl = class {
708
812
  });
709
813
  }
710
814
  break;
815
+ // Handle started event - immediate feedback that execution began
816
+ case "started":
817
+ this.emit("started", {
818
+ executionId: data.executionId,
819
+ agentUuid: data.agentUuid,
820
+ status: "initializing",
821
+ currentStep: data.currentStep
822
+ });
823
+ break;
824
+ // Handle progress event - status updates during execution
825
+ case "progress":
826
+ this.emit("progress", {
827
+ status: data.status,
828
+ iteration: data.iteration ?? 0,
829
+ currentStep: data.currentStep,
830
+ tokenUsage: data.tokenUsage,
831
+ cost: data.cost,
832
+ toolCalls: data.toolCalls
833
+ });
834
+ break;
835
+ // Handle task list update event from TaskTracker
836
+ case "task_list_update":
837
+ this.emit("taskListUpdate", {
838
+ executionId: data.executionId,
839
+ tasks: data.tasks,
840
+ timestamp: data.timestamp
841
+ });
842
+ break;
843
+ // Handle delegation started event (handoff_to_agent initiated)
844
+ case "delegation_started":
845
+ this.emit("delegationStarted", {
846
+ type: "delegation_started",
847
+ handoffId: data.handoffId,
848
+ targetAgentUuid: data.targetAgentUuid,
849
+ targetAgentName: data.targetAgentName,
850
+ taskPreview: data.taskPreview,
851
+ timestamp: data.timestamp || (/* @__PURE__ */ new Date()).toISOString()
852
+ });
853
+ break;
854
+ // Handle delegation completed event (handoff_to_agent finished)
855
+ case "delegation_completed":
856
+ this.emit("delegationCompleted", {
857
+ type: "delegation_completed",
858
+ handoffId: data.handoffId,
859
+ status: data.status,
860
+ resultPreview: data.resultPreview,
861
+ error: data.error,
862
+ durationMs: data.durationMs,
863
+ timestamp: data.timestamp || (/* @__PURE__ */ new Date()).toISOString()
864
+ });
865
+ break;
866
+ // Handle status_update event - immediate feedback (e.g., "thinking")
867
+ // Map to progress event for consistency
868
+ case "status_update":
869
+ this.emit("progress", {
870
+ status: data.status || "thinking",
871
+ iteration: 0,
872
+ currentStep: data.message
873
+ });
874
+ break;
875
+ // Handle text_delta event - token-by-token streaming
876
+ case "text_delta":
877
+ this.emit("textDelta", {
878
+ delta: data.delta,
879
+ executionId: data.executionId,
880
+ timestamp: data.timestamp || (/* @__PURE__ */ new Date()).toISOString()
881
+ });
882
+ break;
711
883
  }
712
884
  }
713
885
  /**
@@ -716,9 +888,11 @@ var ExecutionStreamControllerImpl = class {
716
888
  handleComplete(data) {
717
889
  this.status = "closed";
718
890
  this.stopActivityTimeout();
891
+ const sessionId = data.sessionId ?? this.options.sessionId;
719
892
  const execution = {
720
893
  uuid: this.options.executionId,
721
894
  agentUuid: "",
895
+ sessionId,
722
896
  status: "completed",
723
897
  input: { task: "" },
724
898
  output: data.output,
@@ -842,6 +1016,7 @@ var ExecutionStreamControllerImpl = class {
842
1016
  */
843
1017
  emit(event, data) {
844
1018
  const listeners = this.listeners[event];
1019
+ console.log(`[SDK:StreamController] Emitting '${event}' to ${listeners?.length || 0} listeners`);
845
1020
  if (listeners) {
846
1021
  for (const listener of listeners) {
847
1022
  try {
@@ -921,8 +1096,12 @@ var AgentsAPI = class extends BaseResourceAPI {
921
1096
  return this.httpPost(
922
1097
  `/${uuid}/execute`,
923
1098
  {
924
- task: input.task,
925
- context: input.context,
1099
+ input: {
1100
+ task: input.task,
1101
+ context: input.context ?? {},
1102
+ // Pass attachment IDs for multi-modal messages (images, documents, etc.)
1103
+ attachmentIds: input.attachmentIds
1104
+ },
926
1105
  options: input.options
927
1106
  },
928
1107
  { idempotencyKey }
@@ -973,16 +1152,69 @@ var AgentsAPI = class extends BaseResourceAPI {
973
1152
  * ```
974
1153
  */
975
1154
  async stream(uuid, input) {
976
- const { executionId } = await this.execute(uuid, input);
1155
+ console.log("[SDK:Agents] stream() called for agent:", uuid);
1156
+ const { executionId, sessionId } = await this.execute(uuid, input);
1157
+ console.log("[SDK:Agents] Execution started:", { executionId, sessionId });
977
1158
  const config = this.getStreamConfig();
1159
+ console.log("[SDK:Agents] Stream config:", {
1160
+ baseUrl: config.baseUrl,
1161
+ apiKey: config.apiKey ? `${config.apiKey.substring(0, 20)}...` : "MISSING",
1162
+ orgId: config.orgId
1163
+ });
978
1164
  const controller = createExecutionStreamController({
979
1165
  executionId,
1166
+ sessionId,
980
1167
  baseUrl: config.baseUrl,
981
1168
  apiKey: config.apiKey,
982
1169
  orgId: config.orgId,
983
1170
  getExecution: (id) => this.getExecution(id)
984
1171
  });
985
- await controller.connect();
1172
+ console.log("[SDK:Agents] Stream controller created - caller must call connect() after registering listeners");
1173
+ return controller;
1174
+ }
1175
+ /**
1176
+ * Connect to an existing execution's stream
1177
+ *
1178
+ * Use this when the execution was started externally (e.g., via tRPC for team executions)
1179
+ * and you need to connect to its SSE stream for real-time updates.
1180
+ *
1181
+ * @param executionId - Execution UUID (already running)
1182
+ * @param sessionId - Optional session ID for conversation continuity
1183
+ * @returns Stream controller for the execution
1184
+ *
1185
+ * @example
1186
+ * ```typescript
1187
+ * // Execution started via tRPC
1188
+ * const executionId = await trpc.executions.start.mutate({ teamUuid, task });
1189
+ *
1190
+ * // Connect to SSE stream for real-time updates
1191
+ * const stream = client.agents.streamExecution(executionId);
1192
+ *
1193
+ * stream.on('log', (log) => console.log(log.title));
1194
+ * stream.on('delegationStarted', (data) => console.log('Subagent:', data.targetAgentName));
1195
+ * stream.on('complete', ({ execution }) => console.log(execution.output));
1196
+ *
1197
+ * await stream.connect();
1198
+ * const result = await stream.wait();
1199
+ * ```
1200
+ */
1201
+ streamExecution(executionId, sessionId) {
1202
+ console.log("[SDK:Agents] streamExecution() called for execution:", executionId);
1203
+ const config = this.getStreamConfig();
1204
+ console.log("[SDK:Agents] Stream config:", {
1205
+ baseUrl: config.baseUrl,
1206
+ apiKey: config.apiKey ? `${config.apiKey.substring(0, 20)}...` : "MISSING",
1207
+ orgId: config.orgId
1208
+ });
1209
+ const controller = createExecutionStreamController({
1210
+ executionId,
1211
+ sessionId,
1212
+ baseUrl: config.baseUrl,
1213
+ apiKey: config.apiKey,
1214
+ orgId: config.orgId,
1215
+ getExecution: (id) => this.getExecution(id)
1216
+ });
1217
+ console.log("[SDK:Agents] Stream controller created for existing execution - caller must call connect() after registering listeners");
986
1218
  return controller;
987
1219
  }
988
1220
  // ===== RECEIVE Operations =====
@@ -1514,13 +1746,16 @@ var ArtifactsAPI = class extends BaseResourceAPI {
1514
1746
  while (true) {
1515
1747
  const { done, value } = await reader.read();
1516
1748
  if (done) break;
1517
- const arrayBuffer = value.buffer.slice(
1518
- value.byteOffset,
1519
- value.byteOffset + value.byteLength
1520
- );
1521
- chunks.push(arrayBuffer);
1749
+ chunks.push(new Uint8Array(value));
1750
+ }
1751
+ const totalLength = chunks.reduce((acc, chunk) => acc + chunk.length, 0);
1752
+ const combined = new Uint8Array(totalLength);
1753
+ let offset = 0;
1754
+ for (const chunk of chunks) {
1755
+ combined.set(chunk, offset);
1756
+ offset += chunk.length;
1522
1757
  }
1523
- const blob = new Blob(chunks, { type: input.mimeType ?? "application/octet-stream" });
1758
+ const blob = new Blob([combined.buffer], { type: input.mimeType ?? "application/octet-stream" });
1524
1759
  formData.append("file", blob, input.name);
1525
1760
  }
1526
1761
  if (input.type) {
@@ -1620,7 +1855,9 @@ var SessionsAPI = class extends BaseResourceAPI {
1620
1855
  `/${sessionId}/messages`,
1621
1856
  {
1622
1857
  message: input.message,
1623
- context: input.context
1858
+ context: input.context,
1859
+ // Pass attachment IDs for multi-modal messages (images, documents, etc.)
1860
+ attachmentIds: input.attachmentIds
1624
1861
  },
1625
1862
  { idempotencyKey }
1626
1863
  );
@@ -1671,6 +1908,7 @@ var SessionsAPI = class extends BaseResourceAPI {
1671
1908
  const config = this.getStreamConfig();
1672
1909
  const controller = createExecutionStreamController({
1673
1910
  executionId,
1911
+ sessionId,
1674
1912
  baseUrl: config.baseUrl,
1675
1913
  apiKey: config.apiKey,
1676
1914
  orgId: config.orgId,