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