@superblocksteam/vite-plugin-file-sync 2.0.72-next.8 → 2.0.73-next.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.
Files changed (151) hide show
  1. package/dist/ai-service/agent/middleware.d.ts.map +1 -1
  2. package/dist/ai-service/agent/middleware.js +4 -1
  3. package/dist/ai-service/agent/middleware.js.map +1 -1
  4. package/dist/ai-service/agent/subagents/testing/prompt-builder.d.ts.map +1 -1
  5. package/dist/ai-service/agent/subagents/testing/prompt-builder.js +99 -4
  6. package/dist/ai-service/agent/subagents/testing/prompt-builder.js.map +1 -1
  7. package/dist/ai-service/agent/subagents/testing/types.d.ts +20 -0
  8. package/dist/ai-service/agent/subagents/testing/types.d.ts.map +1 -1
  9. package/dist/ai-service/agent/tools/apis/api-source.d.ts +1 -1
  10. package/dist/ai-service/agent/tools/apis/api-source.d.ts.map +1 -1
  11. package/dist/ai-service/agent/tools/apis/api-source.js +37 -9
  12. package/dist/ai-service/agent/tools/apis/api-source.js.map +1 -1
  13. package/dist/ai-service/agent/tools/build-reload-file.d.ts +5 -2
  14. package/dist/ai-service/agent/tools/build-reload-file.d.ts.map +1 -1
  15. package/dist/ai-service/agent/tools/build-reload-file.js +4 -3
  16. package/dist/ai-service/agent/tools/build-reload-file.js.map +1 -1
  17. package/dist/ai-service/agent/tools/index.d.ts +1 -0
  18. package/dist/ai-service/agent/tools/index.d.ts.map +1 -1
  19. package/dist/ai-service/agent/tools/index.js +1 -0
  20. package/dist/ai-service/agent/tools/index.js.map +1 -1
  21. package/dist/ai-service/agent/tools/integrations/execute-request.d.ts +1 -1
  22. package/dist/ai-service/agent/tools/integrations/internal.d.ts.map +1 -1
  23. package/dist/ai-service/agent/tools/integrations/internal.js +8 -1
  24. package/dist/ai-service/agent/tools/integrations/internal.js.map +1 -1
  25. package/dist/ai-service/agent/tools.d.ts.map +1 -1
  26. package/dist/ai-service/agent/tools.js +37 -4
  27. package/dist/ai-service/agent/tools.js.map +1 -1
  28. package/dist/ai-service/agent/tools2/tools/ask-multi-choice.d.ts +0 -1
  29. package/dist/ai-service/agent/tools2/tools/ask-multi-choice.d.ts.map +1 -1
  30. package/dist/ai-service/agent/tools2/tools/ask-multi-choice.js +1 -6
  31. package/dist/ai-service/agent/tools2/tools/ask-multi-choice.js.map +1 -1
  32. package/dist/ai-service/agent/tools2/tools/end-test-run.d.ts.map +1 -1
  33. package/dist/ai-service/agent/tools2/tools/end-test-run.js +2 -0
  34. package/dist/ai-service/agent/tools2/tools/end-test-run.js.map +1 -1
  35. package/dist/ai-service/agent/tools2/tools/exit-plan-mode.d.ts +2 -2
  36. package/dist/ai-service/agent/tools2/tools/exit-plan-mode.d.ts.map +1 -1
  37. package/dist/ai-service/agent/tools2/tools/exit-plan-mode.js +58 -195
  38. package/dist/ai-service/agent/tools2/tools/exit-plan-mode.js.map +1 -1
  39. package/dist/ai-service/agent/tools2/tools/list-attachments.d.ts +15 -0
  40. package/dist/ai-service/agent/tools2/tools/list-attachments.d.ts.map +1 -0
  41. package/dist/ai-service/agent/tools2/tools/list-attachments.js +47 -0
  42. package/dist/ai-service/agent/tools2/tools/list-attachments.js.map +1 -0
  43. package/dist/ai-service/agent/tools2/tools/start-test-run.d.ts.map +1 -1
  44. package/dist/ai-service/agent/tools2/tools/start-test-run.js +92 -10
  45. package/dist/ai-service/agent/tools2/tools/start-test-run.js.map +1 -1
  46. package/dist/ai-service/agent/tools2/tools/update-test-case-status.d.ts +2 -2
  47. package/dist/ai-service/agent/tools2/tools/update-test-case-status.d.ts.map +1 -1
  48. package/dist/ai-service/agent/tools2/tools/update-test-case-status.js +21 -2
  49. package/dist/ai-service/agent/tools2/tools/update-test-case-status.js.map +1 -1
  50. package/dist/ai-service/agent/utils.d.ts.map +1 -1
  51. package/dist/ai-service/agent/utils.js +46 -2
  52. package/dist/ai-service/agent/utils.js.map +1 -1
  53. package/dist/ai-service/attachments/index.d.ts +2 -0
  54. package/dist/ai-service/attachments/index.d.ts.map +1 -0
  55. package/dist/ai-service/attachments/index.js +2 -0
  56. package/dist/ai-service/attachments/index.js.map +1 -0
  57. package/dist/ai-service/attachments/store.d.ts +65 -0
  58. package/dist/ai-service/attachments/store.d.ts.map +1 -0
  59. package/dist/ai-service/attachments/store.js +158 -0
  60. package/dist/ai-service/attachments/store.js.map +1 -0
  61. package/dist/ai-service/chat/chat-session-store.d.ts.map +1 -1
  62. package/dist/ai-service/chat/chat-session-store.js +11 -0
  63. package/dist/ai-service/chat/chat-session-store.js.map +1 -1
  64. package/dist/ai-service/context-download.d.ts +24 -0
  65. package/dist/ai-service/context-download.d.ts.map +1 -0
  66. package/dist/ai-service/context-download.js +127 -0
  67. package/dist/ai-service/context-download.js.map +1 -0
  68. package/dist/ai-service/context-upload.d.ts +17 -0
  69. package/dist/ai-service/context-upload.d.ts.map +1 -0
  70. package/dist/ai-service/context-upload.js +100 -0
  71. package/dist/ai-service/context-upload.js.map +1 -0
  72. package/dist/ai-service/index.d.ts +27 -3
  73. package/dist/ai-service/index.d.ts.map +1 -1
  74. package/dist/ai-service/index.js +252 -12
  75. package/dist/ai-service/index.js.map +1 -1
  76. package/dist/ai-service/llm/context/context.d.ts +4 -0
  77. package/dist/ai-service/llm/context/context.d.ts.map +1 -1
  78. package/dist/ai-service/llm/context/context.js +10 -0
  79. package/dist/ai-service/llm/context/context.js.map +1 -1
  80. package/dist/ai-service/llm/context/manager.d.ts +5 -0
  81. package/dist/ai-service/llm/context/manager.d.ts.map +1 -1
  82. package/dist/ai-service/llm/context/manager.js +8 -0
  83. package/dist/ai-service/llm/context/manager.js.map +1 -1
  84. package/dist/ai-service/llm/context/serialization.d.ts +3 -0
  85. package/dist/ai-service/llm/context/serialization.d.ts.map +1 -1
  86. package/dist/ai-service/llm/interaction/adapters/vercel.d.ts.map +1 -1
  87. package/dist/ai-service/llm/interaction/adapters/vercel.js +5 -4
  88. package/dist/ai-service/llm/interaction/adapters/vercel.js.map +1 -1
  89. package/dist/ai-service/llm/stream/config.d.ts +2 -0
  90. package/dist/ai-service/llm/stream/config.d.ts.map +1 -1
  91. package/dist/ai-service/llm/stream/config.js +1 -0
  92. package/dist/ai-service/llm/stream/config.js.map +1 -1
  93. package/dist/ai-service/llm/stream/orchestrator.d.ts.map +1 -1
  94. package/dist/ai-service/llm/stream/orchestrator.js +1 -1
  95. package/dist/ai-service/llm/stream/orchestrator.js.map +1 -1
  96. package/dist/ai-service/llm/stream/retry-engine.d.ts +1 -0
  97. package/dist/ai-service/llm/stream/retry-engine.d.ts.map +1 -1
  98. package/dist/ai-service/llm/stream/retry-engine.js +20 -1
  99. package/dist/ai-service/llm/stream/retry-engine.js.map +1 -1
  100. package/dist/ai-service/llm/stream/session.d.ts +2 -0
  101. package/dist/ai-service/llm/stream/session.d.ts.map +1 -1
  102. package/dist/ai-service/llm/stream/session.js +6 -2
  103. package/dist/ai-service/llm/stream/session.js.map +1 -1
  104. package/dist/ai-service/llmobs/otel-exporter.d.ts +58 -0
  105. package/dist/ai-service/llmobs/otel-exporter.d.ts.map +1 -0
  106. package/dist/ai-service/llmobs/otel-exporter.js +182 -0
  107. package/dist/ai-service/llmobs/otel-exporter.js.map +1 -0
  108. package/dist/ai-service/llmobs/tracer.d.ts +9 -0
  109. package/dist/ai-service/llmobs/tracer.d.ts.map +1 -1
  110. package/dist/ai-service/llmobs/tracer.js +46 -2
  111. package/dist/ai-service/llmobs/tracer.js.map +1 -1
  112. package/dist/ai-service/mcp/embedded-playwright-mcp-server.d.ts +17 -0
  113. package/dist/ai-service/mcp/embedded-playwright-mcp-server.d.ts.map +1 -1
  114. package/dist/ai-service/mcp/embedded-playwright-mcp-server.js +329 -7
  115. package/dist/ai-service/mcp/embedded-playwright-mcp-server.js.map +1 -1
  116. package/dist/ai-service/mcp/playwright-server.d.ts +29 -0
  117. package/dist/ai-service/mcp/playwright-server.d.ts.map +1 -1
  118. package/dist/ai-service/mcp/playwright-server.js +53 -0
  119. package/dist/ai-service/mcp/playwright-server.js.map +1 -1
  120. package/dist/ai-service/state-machine/clark-fsm.d.ts +3 -1
  121. package/dist/ai-service/state-machine/clark-fsm.d.ts.map +1 -1
  122. package/dist/ai-service/state-machine/clark-fsm.js +1 -0
  123. package/dist/ai-service/state-machine/clark-fsm.js.map +1 -1
  124. package/dist/ai-service/state-machine/fsm.d.ts.map +1 -1
  125. package/dist/ai-service/state-machine/fsm.js +1 -0
  126. package/dist/ai-service/state-machine/fsm.js.map +1 -1
  127. package/dist/ai-service/state-machine/handlers/agent-planning.d.ts.map +1 -1
  128. package/dist/ai-service/state-machine/handlers/agent-planning.js +42 -1
  129. package/dist/ai-service/state-machine/handlers/agent-planning.js.map +1 -1
  130. package/dist/ai-service/state-machine/handlers/awaiting-user.d.ts.map +1 -1
  131. package/dist/ai-service/state-machine/handlers/awaiting-user.js +9 -0
  132. package/dist/ai-service/state-machine/handlers/awaiting-user.js.map +1 -1
  133. package/dist/ai-service/state-machine/handlers/llm-generating.d.ts.map +1 -1
  134. package/dist/ai-service/state-machine/handlers/llm-generating.js +43 -16
  135. package/dist/ai-service/state-machine/handlers/llm-generating.js.map +1 -1
  136. package/dist/ai-service/state-machine/helpers/peer.d.ts +1 -1
  137. package/dist/ai-service/state-machine/helpers/peer.d.ts.map +1 -1
  138. package/dist/ai-service/state-machine/helpers/peer.js +21 -4
  139. package/dist/ai-service/state-machine/helpers/peer.js.map +1 -1
  140. package/dist/ai-service/util/scoped-token-utils.d.ts +15 -0
  141. package/dist/ai-service/util/scoped-token-utils.d.ts.map +1 -0
  142. package/dist/ai-service/util/scoped-token-utils.js +131 -0
  143. package/dist/ai-service/util/scoped-token-utils.js.map +1 -0
  144. package/dist/file-sync-vite-plugin.js +3 -3
  145. package/dist/file-sync-vite-plugin.js.map +1 -1
  146. package/dist/server-rpc/index.js +1 -1
  147. package/dist/server-rpc/index.js.map +1 -1
  148. package/dist/socket-manager.d.ts.map +1 -1
  149. package/dist/socket-manager.js +61 -4
  150. package/dist/socket-manager.js.map +1 -1
  151. package/package.json +6 -6
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context-upload.js","sourceRoot":"","sources":["../../src/ai-service/context-upload.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,EAAE,iCAAiC,EAAE,MAAM,uBAAuB,CAAC;AAC1E,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAG9D;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,wBAAwB,CAAC,EAC7C,aAAa,EACb,QAAQ,EACR,UAAU,EACV,cAAc,EACd,MAAM,EACN,kBAAkB,EAClB,MAAM,EACN,GAAG,GAUJ;IACC,iDAAiD;IACjD,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAC1B,cAAc,EACd,cAAc,EACd,SAAS,EACT,MAAM,CACP,CAAC;IAEF,0CAA0C;IAC1C,IAAI,YAAsB,CAAC;IAC3B,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,UAAU,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;QACnE,iEAAiE;QACjE,YAAY,GAAG,OAAO;aACnB,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC;aACjC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAChC,CAAC;IAAC,OAAO,GAAQ,EAAE,CAAC;QAClB,IAAI,GAAG,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YAC1B,8DAA8D;YAC9D,MAAM,CAAC,IAAI,CACT,oEAAoE,MAAM,mBAAmB,CAC9F,CAAC;YACF,OAAO;QACT,CAAC;QACD,MAAM,GAAG,CAAC;IACZ,CAAC;IAED,IAAI,YAAY,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC9B,MAAM,CAAC,IAAI,CACT,gEAAgE,MAAM,mBAAmB,CAC1F,CAAC;QACF,OAAO;IACT,CAAC;IAED,wCAAwC;IACxC,IAAI,WAAmB,CAAC;IACxB,IAAI,CAAC;QACH,WAAW,GAAG,MAAM,cAAc,CAAC;YACjC,aAAa;YACb,kBAAkB;YAClB,GAAG;SACJ,CAAC,CAAC;IACL,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,CAAC,KAAK,CACV,uDAAuD,EACvD,YAAY,CAAC,KAAK,CAAC,CACpB,CAAC;QACF,MAAM,KAAK,CAAC;IACd,CAAC;IAED,+CAA+C;IAC/C,MAAM,QAAQ,GAAG,IAAI,QAAQ,EAAE,CAAC;IAChC,MAAM,aAAa,GAAa,EAAE,CAAC;IAEnC,KAAK,MAAM,QAAQ,IAAI,YAAY,EAAE,CAAC;QACpC,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;QACjD,IAAI,CAAC;YACH,iDAAiD;YACjD,MAAM,UAAU,GAAG,MAAM,QAAQ,CAAC,QAAQ,CAAC,CAAC;YAE5C,wCAAwC;YACxC,4DAA4D;YAC5D,MAAM,UAAU,GAAG,IAAI,UAAU,CAAC,UAAU,CAAC,CAAC;YAC9C,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC;YAEpC,sDAAsD;YACtD,QAAQ,CAAC,MAAM,CAAC,SAAS,EAAE,IAAI,EAAE,QAAQ,CAAC,CAAC;YAC3C,aAAa,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC/B,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,CAAC,IAAI,CACT,0DAA0D,QAAQ,YAAY,EAC9E,YAAY,CAAC,GAAG,CAAC,CAClB,CAAC;YACF,8CAA8C;QAChD,CAAC;IACH,CAAC;IAED,IAAI,aAAa,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC/B,MAAM,CAAC,IAAI,CACT,uEAAuE,CACxE,CAAC;QACF,OAAO;IACT,CAAC;IAED,8CAA8C;IAC9C,MAAM,YAAY,GAAG,iCAAiC,CAAC,kBAAkB,CAAC,CAAC;IAE3E,8DAA8D;IAC9D,MAAM,GAAG,GAAG,GAAG,YAAY,iBAAiB,aAAa,aAAa,kBAAkB,CAAC,UAAU,CAAC,YAAY,kBAAkB,CAAC,QAAQ,CAAC,UAAU,CAAC;IAEvJ,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;YAChC,MAAM,EAAE,MAAM;YACd,IAAI,EAAE,QAAQ;YACd,OAAO,EAAE;gBACP,aAAa,EAAE,UAAU,WAAW,EAAE;gBACtC,gEAAgE;aACjE;SACF,CAAC,CAAC;QAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,MAAM,SAAS,GAAG,MAAM,QAAQ;iBAC7B,IAAI,EAAE;iBACN,KAAK,CAAC,GAAG,EAAE,CAAC,+BAA+B,CAAC,CAAC;YAChD,MAAM,CAAC,KAAK,CACV,oDAAoD,QAAQ,CAAC,MAAM,gBAAgB,QAAQ,CAAC,UAAU,WAAW,SAAS,sBAAsB,aAAa,cAAc,QAAQ,EAAE,CACtL,CAAC;YACF,MAAM,IAAI,KAAK,CAAC,0BAA0B,QAAQ,CAAC,UAAU,EAAE,CAAC,CAAC;QACnE,CAAC;QAED,MAAM,CAAC,IAAI,CACT,oDAAoD,aAAa,CAAC,MAAM,qBAAqB,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,uBAAuB,aAAa,cAAc,QAAQ,EAAE,CAClL,CAAC;IACJ,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,CAAC,KAAK,CACV,qDAAqD,EACrD,YAAY,CAAC,KAAK,CAAC,CACpB,CAAC;QACF,MAAM,KAAK,CAAC;IACd,CAAC;AACH,CAAC"}
@@ -5,7 +5,8 @@ import type { FileSystemManager } from "../file-system-manager.js";
5
5
  import type { SourceTracker } from "../source-tracker.js";
6
6
  import type { JudgeEvaluationOptions, JudgeEvaluationResult } from "./judge/judge-service.js";
7
7
  import type { AiServiceConfig, AiServiceEvents, EditorClient, UserChange, ApiUpdate } from "./types.ts";
8
- import type { AiGenerateRequest, AiExplainCodeRequest, LLMProviderConfig, PromptContext, RuntimeErrorData, ConsoleLogEntry } from "@superblocksteam/library-shared/types";
8
+ import type { ContextId } from "./llm/context/types.js";
9
+ import type { AiGenerateRequest, AiExplainCodeRequest, AiLabelAttachmentRequest, AiLabelAttachmentResponse, LLMProviderConfig, PromptContext, RuntimeErrorData, ConsoleLogEntry } from "@superblocksteam/library-shared/types";
9
10
  import type { ViteDevServer } from "vite";
10
11
  export { AiServiceFeatureFlags } from "./features.js";
11
12
  export declare class AiService extends TracedEventEmitter<AiServiceEvents> {
@@ -18,7 +19,7 @@ export declare class AiService extends TracedEventEmitter<AiServiceEvents> {
18
19
  private _appContext;
19
20
  private llmProviderSettings;
20
21
  private _logger;
21
- private clark;
22
+ private readonly clark;
22
23
  private clarkProfiler;
23
24
  readonly chatSessionStore: ChatSessionStore;
24
25
  private readonly contextManager;
@@ -31,6 +32,22 @@ export declare class AiService extends TracedEventEmitter<AiServiceEvents> {
31
32
  private readonly mcpServerManager;
32
33
  get appContext(): AppContextStore;
33
34
  get clarkState(): string;
35
+ get appRootDirPath(): string;
36
+ get organizationId(): string;
37
+ get superblocksBaseUrl(): string;
38
+ /**
39
+ * Gets the contextId for the current conversation context.
40
+ * Returns null if JWT is missing or has no userId.
41
+ */
42
+ getContextId(): ContextId | null;
43
+ /**
44
+ * Gets the JWT from Clark context
45
+ */
46
+ getClarkJwt(): string | undefined;
47
+ /**
48
+ * Updates the JWT in Clark context
49
+ */
50
+ updateClarkJwt(jwt: string): void;
34
51
  constructor(config: AiServiceConfig);
35
52
  /**
36
53
  * Initialize the AI service. Must be called after construction.
@@ -48,10 +65,16 @@ export declare class AiService extends TracedEventEmitter<AiServiceEvents> {
48
65
  private createClarkTagProviderFactory;
49
66
  handleAiGenerate(request: AiGenerateRequest, peer: EditorClient, peerId: string): Promise<void>;
50
67
  handleAiExplainCode(request: AiExplainCodeRequest, peer: EditorClient): Promise<void>;
68
+ handleAiLabelAttachment(request: AiLabelAttachmentRequest): Promise<AiLabelAttachmentResponse>;
69
+ /**
70
+ * Converts an attachment to the appropriate LLM content part.
71
+ */
72
+ private attachmentToContentPart;
51
73
  private submitAcceptanceEvaluation;
52
74
  handleUserAcceptedDraft(peer: EditorClient, silently?: boolean): Promise<void>;
53
75
  handleUserRejectedDraft(peer: EditorClient, silently?: boolean): Promise<void>;
54
76
  handleUserCanceled(): Promise<void>;
77
+ handleSkipTestCase(testRunId: string, testCaseId: string): Promise<void>;
55
78
  handleUserConnected(peer: EditorClient, peerId: string): void;
56
79
  handleUserDisconnected(peerId: string): void;
57
80
  private clearPeerConnection;
@@ -87,9 +110,10 @@ export declare class AiService extends TracedEventEmitter<AiServiceEvents> {
87
110
  }): Promise<JudgeEvaluationResult>;
88
111
  handleUserChange(change: UserChange): void;
89
112
  handleNewChat(): Promise<void>;
90
- handleTruncateChatAfterTimestamp(sinceTimestamp: number): Promise<void>;
113
+ handleRestoreToCommit(sinceTimestamp: number, commitId: string, applicationId: string, branchName: string): Promise<void>;
91
114
  handleApiUpdate(update: ApiUpdate): Promise<void>;
92
115
  isBusy(): boolean;
116
+ isAwaitingUser(): boolean;
93
117
  /**
94
118
  * Check if Clark is currently generating code.
95
119
  * Used by lock-service to determine if lock should be held during generation.
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ai-service/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ai-service/index.ts"],"names":[],"mappings":"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"}
@@ -1,7 +1,9 @@
1
1
  import os from "node:os";
2
2
  import path from "node:path";
3
+ import { isTextAttachment } from "@superblocksteam/library-shared/types";
3
4
  import { addTracingToMethods, TracedEventEmitter, } from "@superblocksteam/shared";
4
- import { hasToolCall } from "ai";
5
+ import { generateObject, hasToolCall } from "ai";
6
+ import { z } from "zod";
5
7
  import { getErrorMeta, getLogger, setDefaultLogger } from "../util/logger.js";
6
8
  import { OperationPassthrough } from "../util/operation-queue.js";
7
9
  import { readFile } from "./agent/tools/build-read-file.js";
@@ -15,6 +17,7 @@ import { AppShell } from "./app-interface/shell.js";
15
17
  import { BoltArtifactProcessor } from "./artifacts/bolt.js";
16
18
  import { ChatSessionStore } from "./chat/chat-session-store.js";
17
19
  import { AppContextStore } from "./context/app-context.js";
20
+ import { restoreContextFromCheckpoint } from "./context-download.js";
18
21
  import { IntegrationStore } from "./integrations/store.js";
19
22
  import { JudgeService } from "./judge/judge-service.js";
20
23
  import { CsvJudgeStorage } from "./judge/storage/csv-storage.js";
@@ -100,6 +103,7 @@ const mergePlanContexts = (existing, incoming) => {
100
103
  plan: incoming?.plan ?? existing?.plan,
101
104
  approved: incoming?.approved !== undefined ? incoming.approved : existing?.approved,
102
105
  integrations: incoming?.integrations ?? existing?.integrations,
106
+ entities: incoming?.entities ?? existing?.entities,
103
107
  title: incoming?.title ?? existing?.title,
104
108
  attachments: incoming?.attachments ?? existing?.attachments,
105
109
  enableTesting: incoming?.enableTesting ?? existing?.enableTesting,
@@ -132,11 +136,48 @@ export class AiService extends TracedEventEmitter {
132
136
  get clarkState() {
133
137
  return this.clark.state;
134
138
  }
139
+ get appRootDirPath() {
140
+ return this.config.appRootDirPath;
141
+ }
142
+ get organizationId() {
143
+ return this.config.organizationId;
144
+ }
145
+ get superblocksBaseUrl() {
146
+ return this.config.superblocksBaseUrl;
147
+ }
148
+ /**
149
+ * Gets the contextId for the current conversation context.
150
+ * Returns null if JWT is missing or has no userId.
151
+ */
152
+ getContextId() {
153
+ try {
154
+ return getContextId(this.clark, this.config);
155
+ }
156
+ catch {
157
+ return null;
158
+ }
159
+ }
160
+ /**
161
+ * Gets the JWT from Clark context
162
+ */
163
+ getClarkJwt() {
164
+ return this.clark?.context?.jwt;
165
+ }
166
+ /**
167
+ * Updates the JWT in Clark context
168
+ */
169
+ updateClarkJwt(jwt) {
170
+ if (jwt) {
171
+ this.clark.updateContext({ jwt });
172
+ }
173
+ }
135
174
  constructor(config) {
136
175
  super(config.tracer);
137
176
  this.config = config;
138
- this._logger = config.logger;
139
177
  setDefaultLogger(config.logger);
178
+ // Store the wrapped logger so getLogger() can return it
179
+ // The wrapped logger forwards logs to the browser console when Clark logs are enabled
180
+ this._logger = getLogger();
140
181
  // Prevent traced functions from creating traces when called outside of a Clark context
141
182
  llmobs.setDefaultRootPolicy("drop-if-no-parent");
142
183
  // todo: move to state handlers
@@ -234,6 +275,7 @@ export class AiService extends TracedEventEmitter {
234
275
  "handleUserAcceptedDraft",
235
276
  "handleUserRejectedDraft",
236
277
  "handleUserCanceled",
278
+ "handleSkipTestCase",
237
279
  "handleBuildSystemError",
238
280
  "handleRuntimeError",
239
281
  "handleClearRuntimeError",
@@ -261,6 +303,8 @@ export class AiService extends TracedEventEmitter {
261
303
  this.getLogger().info("[ai-service] Integration cache removed");
262
304
  }
263
305
  getLogger() {
306
+ // Return the wrapped logger that forwards logs to the browser console
307
+ // when Clark logs are enabled (via ?clark_logs=true or SUPERBLOCKS_CLI_ENV=local)
264
308
  return this._logger;
265
309
  }
266
310
  createClarkTransitionHandler() {
@@ -355,6 +399,7 @@ export class AiService extends TracedEventEmitter {
355
399
  };
356
400
  }
357
401
  async handleAiGenerate(request, peer, peerId) {
402
+ this.getLogger().info(`[ai-service] handleAiGenerate: peerId=${peerId}`);
358
403
  if (this.clark.state === ClarkStateNames.Dead) {
359
404
  throw new Error("Service is unavailable");
360
405
  }
@@ -364,6 +409,13 @@ export class AiService extends TracedEventEmitter {
364
409
  }
365
410
  this.clarkProfiler.startSession();
366
411
  getLogger().info("AI Service received request with llmConfig:", request.llmConfig || {});
412
+ getLogger().info("[ai-service] handleAiGenerate received request", {
413
+ requestMode: request.mode,
414
+ currentContextMode: this.clark.context.currentMode,
415
+ requestPlanContextApproved: request.planContext?.approved,
416
+ existingPlanContextApproved: this.clark.context.planContext?.approved,
417
+ responseMetadataType: request.responseMetadata?.type,
418
+ });
367
419
  this.clark.updateContext((context) => {
368
420
  return {
369
421
  ...context,
@@ -520,6 +572,110 @@ export class AiService extends TracedEventEmitter {
520
572
  });
521
573
  }
522
574
  }
575
+ async handleAiLabelAttachment(request) {
576
+ const logger = getLogger();
577
+ const startTime = Date.now();
578
+ const timeout = 30_000;
579
+ const attachment = request.attachment;
580
+ logger.debug("[ai-service] Labeling attachment", {
581
+ fileName: attachment.fileName ?? "unnamed",
582
+ type: attachment.type,
583
+ });
584
+ const llmConfig = request.llmConfig
585
+ ? {
586
+ ...request.llmConfig,
587
+ interleavedThinking: false,
588
+ thinkingEnabled: false,
589
+ }
590
+ : undefined;
591
+ const llmProviderSettings = this.getLLMProviderSettings(false, llmConfig);
592
+ const llmProvider = createLLMProvider(llmProviderSettings, () => request.jwt, llmConfig);
593
+ const model = llmProvider.modelForTask("fast");
594
+ const LabelAttachmentSchema = z.object({
595
+ label: z
596
+ .string()
597
+ .min(1)
598
+ .describe('A brief 2-3 word description (e.g., "sales dashboard", "user profile", "data table", "customer data")'),
599
+ insight: z
600
+ .string()
601
+ .min(1)
602
+ .describe('A key observation about the content (e.g., "chart displays monthly revenue", "CSV contains customer records", "JSON config for API settings")'),
603
+ });
604
+ const timeoutController = new AbortController();
605
+ const timeoutId = setTimeout(() => timeoutController.abort(), timeout);
606
+ try {
607
+ // Build the appropriate content part based on attachment type
608
+ const contentPart = this.attachmentToContentPart(attachment);
609
+ const { object: result } = await generateObject({
610
+ model,
611
+ schema: LabelAttachmentSchema,
612
+ messages: [
613
+ {
614
+ role: "user",
615
+ content: [
616
+ {
617
+ type: "text",
618
+ text: "Analyze this attachment and provide a brief label and key insight about its content.",
619
+ },
620
+ contentPart,
621
+ ],
622
+ },
623
+ ],
624
+ abortSignal: timeoutController.signal,
625
+ });
626
+ const durationMs = Date.now() - startTime;
627
+ logger.debug("[ai-service] Attachment labeling complete", {
628
+ fileName: attachment.fileName,
629
+ type: attachment.type,
630
+ label: result.label,
631
+ insight: result.insight,
632
+ durationMs,
633
+ });
634
+ return result;
635
+ }
636
+ finally {
637
+ clearTimeout(timeoutId);
638
+ }
639
+ }
640
+ /**
641
+ * Converts an attachment to the appropriate LLM content part.
642
+ */
643
+ attachmentToContentPart(attachment) {
644
+ if (attachment.type === "image") {
645
+ return {
646
+ type: "image",
647
+ image: attachment.image,
648
+ };
649
+ }
650
+ else if (attachment.type === "pdf") {
651
+ // Parse data URL to extract base64 data
652
+ const match = attachment.data.match(/^data:([^;]+);base64,(.+)$/);
653
+ const data = match?.[2] ?? attachment.data;
654
+ const mediaType = match?.[1] ?? "application/pdf";
655
+ return {
656
+ type: "file",
657
+ data,
658
+ mediaType,
659
+ filename: attachment.fileName,
660
+ };
661
+ }
662
+ else if (isTextAttachment(attachment)) {
663
+ // Wrap text content in XML tags for structured presentation
664
+ const sanitizedFileName = attachment.fileName
665
+ .replace(/&/g, "&amp;")
666
+ .replace(/"/g, "&quot;")
667
+ .replace(/'/g, "&apos;")
668
+ .replace(/</g, "&lt;")
669
+ .replace(/>/g, "&gt;");
670
+ return {
671
+ type: "text",
672
+ text: `<${attachment.type}_file name="${sanitizedFileName}">\n${attachment.content}\n</${attachment.type}_file>`,
673
+ };
674
+ }
675
+ else {
676
+ throw new Error(`Unsupported attachment type: ${attachment.type}`);
677
+ }
678
+ }
523
679
  submitAcceptanceEvaluation(wasAccepted) {
524
680
  if (!this.clark.rootSpan) {
525
681
  this.getLogger().warn("[ai-service] No root span available for submitting feedback");
@@ -537,12 +693,14 @@ export class AiService extends TracedEventEmitter {
537
693
  }
538
694
  }
539
695
  async handleUserAcceptedDraft(peer, silently) {
696
+ this.getLogger().info(`[ai-service] handleUserAcceptedDraft`);
540
697
  this.submitAcceptanceEvaluation(true);
541
698
  if (this.clark.state !== ClarkStateNames.AwaitingUser) {
542
699
  throw new Error("Service is not awaiting user input");
543
700
  }
544
701
  if (!this.clark.context.peer) {
545
- // this can happen if the service was started with a draft
702
+ // peer can be null if service was started with a draft
703
+ this.getLogger().info(`[ai-service] Setting peer from RPC caller`);
546
704
  this.clark.updateContext({
547
705
  peer,
548
706
  });
@@ -551,12 +709,14 @@ export class AiService extends TracedEventEmitter {
551
709
  void transitionTo({ type: USER_ACCEPTED_DRAFT, silently });
552
710
  }
553
711
  async handleUserRejectedDraft(peer, silently) {
712
+ this.getLogger().info(`[ai-service] handleUserRejectedDraft`);
554
713
  this.submitAcceptanceEvaluation(false);
555
714
  if (this.clark.state !== ClarkStateNames.AwaitingUser) {
556
715
  throw new Error("Service is not awaiting user input");
557
716
  }
558
717
  if (!this.clark.context.peer) {
559
- // this can happen if the service was started with a draft
718
+ // peer can be null if service was started with a draft
719
+ this.getLogger().info(`[ai-service] Setting peer from RPC caller`);
560
720
  this.clark.updateContext({
561
721
  peer,
562
722
  });
@@ -574,8 +734,42 @@ export class AiService extends TracedEventEmitter {
574
734
  this.clark.context.abortController?.abort();
575
735
  void this.clark.send({ type: USER_CANCELED });
576
736
  }
737
+ async handleSkipTestCase(testRunId, testCaseId) {
738
+ const logger = this.getLogger();
739
+ logger.info(`[ai-service] Skip test case requested: testRunId=${testRunId}, testCaseId=${testCaseId}`);
740
+ // Verify this is the active test run
741
+ if (this.clark.context.currentTestRunId !== testRunId) {
742
+ logger.warn(`[ai-service] Skip request for testRunId=${testRunId} but current is ${this.clark.context.currentTestRunId}`);
743
+ return;
744
+ }
745
+ // Update context with skip request
746
+ this.clark.updateContext({
747
+ skipRequestedForTestCase: testCaseId,
748
+ });
749
+ // Update the test case status to skipped
750
+ const testCaseStatuses = this.clark.context.testCaseStatuses ??
751
+ new Map();
752
+ testCaseStatuses.set(testCaseId, "skipped");
753
+ this.clark.updateContext({
754
+ testCaseStatuses,
755
+ });
756
+ // Send test_case_update message to UI
757
+ const peer = this.clark.context.peer;
758
+ if (peer) {
759
+ void peer.call.aiPushMessage({
760
+ type: "test_case_update",
761
+ testRunId,
762
+ testCaseId,
763
+ testCaseStatus: "skipped",
764
+ role: "assistant",
765
+ content: "",
766
+ });
767
+ }
768
+ logger.info(`[ai-service] Test case ${testCaseId} marked as skipped, flag set for subagent`);
769
+ }
577
770
  handleUserConnected(peer, peerId) {
578
771
  const existingPeerId = this.clark.context.peerId;
772
+ this.getLogger().info(`[ai-service] handleUserConnected: peerId=${peerId}`);
579
773
  if (this.clark.context.peer) {
580
774
  if (existingPeerId === peerId) {
581
775
  this.getLogger().info(`[ai-service] Existing peer ${peerId} reconnected; refreshing reference`);
@@ -592,6 +786,7 @@ export class AiService extends TracedEventEmitter {
592
786
  peer,
593
787
  peerId,
594
788
  }));
789
+ this.getLogger().info(`[ai-service] Peer set: ${peerId}`);
595
790
  // 1. Sync generation state if generation is in progress
596
791
  if (this.clark.context.lastGenerationState) {
597
792
  this.getLogger().info(`[ai-service] Syncing generation state on reconnect: ${this.clark.context.lastGenerationState.state}`);
@@ -627,18 +822,19 @@ export class AiService extends TracedEventEmitter {
627
822
  }
628
823
  handleUserDisconnected(peerId) {
629
824
  const currentPeerId = this.clark.context.peerId;
825
+ this.getLogger().info(`[ai-service] handleUserDisconnected: peerId=${peerId}`);
630
826
  if (!currentPeerId) {
631
827
  return;
632
828
  }
633
829
  if (currentPeerId !== peerId) {
634
- this.getLogger().warn(`[ai-service] Disconnect event for ${peerId} but current peer is ${currentPeerId}; clearing stale peer`);
635
- }
636
- else {
637
- this.getLogger().info(`[ai-service] peer disconnecting: ${peerId}`);
830
+ this.getLogger().info(`[ai-service] Stale disconnect ignored: peer ${peerId} disconnecting but current peer is ${currentPeerId}`);
831
+ return; // Don't clear the current peer on stale disconnect
638
832
  }
833
+ this.getLogger().info(`[ai-service] peer disconnecting: ${peerId}`);
639
834
  this.clearPeerConnection();
640
835
  }
641
836
  clearPeerConnection() {
837
+ this.getLogger().info(`[ai-service] Clearing peer connection`);
642
838
  this.clark.updateContext((context) => ({
643
839
  ...context,
644
840
  peer: undefined,
@@ -877,18 +1073,59 @@ export class AiService extends TracedEventEmitter {
877
1073
  this.getLogger().error("[ai-service] Failed to clear contexts on new chat", getErrorMeta(error));
878
1074
  }
879
1075
  }
880
- async handleTruncateChatAfterTimestamp(sinceTimestamp) {
881
- // Truncate chat messages on server
1076
+ async handleRestoreToCommit(sinceTimestamp, commitId, applicationId, branchName) {
1077
+ // TODO: change this to truncate after commit once commit info is supported here, so we can truncate messages accurately.
1078
+ // 1. Truncate chat messages on server (always do this first)
882
1079
  await this.chatSessionStore.truncateAfterTimestamp(sinceTimestamp);
883
- // Truncate LLM context
1080
+ // Check JWT once at the beginning - needed for both restoration and truncation
1081
+ // Note: clark.context.jwt should be set by the socket handler (socket-manager.ts) before
1082
+ // this method is called. The socket handler updates it from peerAuthorization if missing.
1083
+ const jwt = this.clark?.context?.jwt;
1084
+ if (!jwt) {
1085
+ this.getLogger().warn(`[handleRestoreToCommit] No JWT available, cannot restore or truncate context`);
1086
+ return;
1087
+ }
1088
+ // 2. Try to restore context from checkpoint
1089
+ try {
1090
+ const contextId = getContextId(this.clark, this.config);
1091
+ const result = await restoreContextFromCheckpoint({
1092
+ applicationId,
1093
+ commitId,
1094
+ branchName,
1095
+ contextId,
1096
+ appRootDirPath: this.config.appRootDirPath,
1097
+ superblocksBaseUrl: this.config.superblocksBaseUrl,
1098
+ logger: this.getLogger(),
1099
+ jwt,
1100
+ contextManager: this.contextManager,
1101
+ });
1102
+ if (result.success) {
1103
+ this.getLogger().info(`[handleRestoreToCommit] Successfully restored main.json from checkpoint commitId=${commitId}, skipping truncation`);
1104
+ return; // Success - no need to truncate
1105
+ }
1106
+ else {
1107
+ // main.json not found or failed - fall through to truncation
1108
+ const reason = result.savedFiles.length > 0
1109
+ ? "main.json not found in checkpoint"
1110
+ : "no file saved from checkpoint";
1111
+ this.getLogger().info(`[handleRestoreToCommit] Context restore failed: ${reason} for commitId=${commitId}, using truncation fallback`);
1112
+ }
1113
+ }
1114
+ catch (error) {
1115
+ // Error downloading - log and fall through to truncation
1116
+ this.getLogger().warn(`[handleRestoreToCommit] Error restoring context from checkpoint, using truncation fallback`, getErrorMeta(error));
1117
+ }
1118
+ // 3. Fallback: Truncate LLM context (restore failed)
884
1119
  const contextId = getContextId(this.clark, this.config);
885
- const ownerId = `truncation-handler-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`;
1120
+ const ownerId = `restore-handler-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`;
886
1121
  const contextHandle = await this.contextManager.acquireContext(contextId, ownerId);
887
1122
  try {
888
1123
  contextHandle.context.truncateAfterTimestamp(sinceTimestamp);
1124
+ this.getLogger().info(`[handleRestoreToCommit] Context truncated after timestamp ${sinceTimestamp}`);
889
1125
  }
890
1126
  catch (error) {
891
1127
  this.getLogger().error(`[ai-service] Failed to truncate context after timestamp ${sinceTimestamp}`, getErrorMeta(error));
1128
+ throw error;
892
1129
  }
893
1130
  finally {
894
1131
  contextHandle.release();
@@ -914,6 +1151,9 @@ export class AiService extends TracedEventEmitter {
914
1151
  this.clark.state !== ClarkStateNames.AwaitingUser &&
915
1152
  this.clark.state !== ClarkStateNames.Dead);
916
1153
  }
1154
+ isAwaitingUser() {
1155
+ return this.clark.state === ClarkStateNames.AwaitingUser;
1156
+ }
917
1157
  /**
918
1158
  * Check if Clark is currently generating code.
919
1159
  * Used by lock-service to determine if lock should be held during generation.