@jskit-ai/assistant-core 0.1.200 → 0.1.202

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 (164) hide show
  1. package/examples/conversation/README.md +8 -1
  2. package/examples/conversation/package.json +5 -5
  3. package/fixtures/responsive-assistant/App.vue +4 -1
  4. package/package.json +99 -36
  5. package/src/client/conversation/AssistantConversationElement.vue +27 -4
  6. package/src/client/conversation/AssistantConversationStatus.vue +24 -0
  7. package/src/client/conversation/AssistantGoalControl.vue +8 -5
  8. package/src/client/conversation/AssistantTranscript.vue +10 -3
  9. package/src/client/conversation/index.js +2 -0
  10. package/src/client/conversation/messageDelivery.js +115 -32
  11. package/src/client/conversation/retainedConversation.js +32 -0
  12. package/src/client/conversation/useAssistantQuestions.js +76 -0
  13. package/src/client/lib/assistantApi.js +72 -2
  14. package/src/server/conversation/agentRun.js +222 -0
  15. package/src/server/conversation/attachments.js +93 -0
  16. package/src/server/conversation/claudeClient.js +221 -0
  17. package/src/server/conversation/claudeHistory.js +256 -0
  18. package/src/server/conversation/claudeProcess.js +327 -0
  19. package/src/server/conversation/claudeTools.js +42 -0
  20. package/src/server/conversation/claudeTurn.js +1082 -0
  21. package/src/server/conversation/codexConfiguration.js +1183 -0
  22. package/src/server/conversation/codexConversations.js +1082 -0
  23. package/src/server/conversation/codexDetachedTurn.js +332 -0
  24. package/src/server/conversation/codexEvents.js +194 -1
  25. package/src/server/conversation/codexGoalCommands.js +124 -0
  26. package/src/server/conversation/codexHelperExecution.js +306 -0
  27. package/src/server/conversation/codexHelperThreadLedger.js +804 -0
  28. package/src/server/conversation/codexHelperThreadRecovery.js +395 -0
  29. package/src/server/conversation/codexHelperThreads.js +638 -0
  30. package/src/server/conversation/codexHistoryAdapter.js +369 -0
  31. package/src/server/conversation/codexMessageCommands.js +663 -0
  32. package/src/server/conversation/codexMessageDelivery.js +211 -0
  33. package/src/server/conversation/codexNativeHistoryExport.js +95 -0
  34. package/src/server/conversation/codexNotificationObserver.js +482 -0
  35. package/src/server/conversation/codexNotificationQueue.js +103 -0
  36. package/src/server/conversation/codexObservationControl.js +174 -0
  37. package/src/server/conversation/codexOutput.js +931 -0
  38. package/src/server/conversation/codexProcess.js +1559 -0
  39. package/src/server/conversation/codexProcessLeader.js +14 -0
  40. package/src/server/conversation/codexProvider.js +2710 -0
  41. package/src/server/conversation/codexProviderOwner.js +1058 -0
  42. package/src/server/conversation/codexProviderSelection.js +218 -0
  43. package/src/server/conversation/codexReasoning.js +314 -0
  44. package/src/server/conversation/codexRenewalCommands.js +290 -0
  45. package/src/server/conversation/codexResultSettlement.js +409 -0
  46. package/src/server/conversation/codexRunJournal.js +658 -0
  47. package/src/server/conversation/codexRuntimeLifecycle.js +288 -0
  48. package/src/server/conversation/codexSessionCleanup.js +96 -0
  49. package/src/server/conversation/codexSessionReconciliation.js +284 -0
  50. package/src/server/conversation/codexThreadReadiness.js +397 -0
  51. package/src/server/conversation/codexThreadStatus.js +354 -0
  52. package/src/server/conversation/codexTurn.js +701 -255
  53. package/src/server/conversation/codexTurnControl.js +317 -0
  54. package/src/server/conversation/codexTurnRecovery.js +990 -0
  55. package/src/server/conversation/codexTurnState.js +549 -0
  56. package/src/server/conversation/commandHook.js +18 -0
  57. package/src/server/conversation/commandWrapper.js +37 -0
  58. package/src/server/conversation/configuration.js +43 -0
  59. package/src/server/conversation/continuity.js +289 -0
  60. package/src/server/conversation/fileStorage.js +55 -0
  61. package/src/server/conversation/hookBridge.js +19 -0
  62. package/src/server/conversation/index.js +13 -0
  63. package/src/server/conversation/localExecution.js +665 -0
  64. package/src/server/conversation/memoryStorage.js +7 -72
  65. package/src/server/conversation/nativeHistoryExport.js +90 -0
  66. package/src/server/conversation/nativeStorage.js +23 -0
  67. package/src/server/conversation/openCodeClient.js +209 -19
  68. package/src/server/conversation/openCodePlugin.js +84 -0
  69. package/src/server/conversation/openCodeProcess.js +476 -0
  70. package/src/server/conversation/openCodeRuntime.js +1578 -0
  71. package/src/server/conversation/openCodeTools.js +60 -0
  72. package/src/server/conversation/openCodeTurn.js +557 -0
  73. package/src/server/conversation/provider.js +30 -0
  74. package/src/server/conversation/providers/api.js +136 -0
  75. package/src/server/conversation/providers/claude.js +63 -0
  76. package/src/server/conversation/providers/claudeDriver.js +425 -0
  77. package/src/server/conversation/providers/codex.js +248 -0
  78. package/src/server/conversation/providers/codexDriver.js +1078 -0
  79. package/src/server/conversation/providers/opencode.js +49 -0
  80. package/src/server/conversation/providers/opencodeDriver.js +650 -0
  81. package/src/server/conversation/providers/scoped.js +312 -0
  82. package/src/server/conversation/runtime.js +2220 -0
  83. package/src/server/conversation/runtimeStateUpgrade.js +125 -0
  84. package/src/server/conversation/storage.js +184 -0
  85. package/src/server/conversation/streams.js +7 -2
  86. package/src/server/conversation/structuredOutput.js +240 -0
  87. package/src/server/conversation/systemPrompt.js +54 -0
  88. package/src/server/conversation/tools.js +84 -0
  89. package/src/server/conversation/transcript.js +5 -4
  90. package/src/server/hosts/claudeHistory.js +5 -0
  91. package/src/server/hosts/claudeProcess.js +11 -0
  92. package/src/server/hosts/claudeTurn.js +4 -0
  93. package/src/server/hosts/codexConfiguration.js +20 -0
  94. package/src/server/hosts/codexEvents.js +13 -0
  95. package/src/server/hosts/codexProcess.js +12 -0
  96. package/src/server/hosts/codexProvider.js +23 -0
  97. package/src/server/hosts/codexTurn.js +20 -0
  98. package/src/server/hosts/nativeHistory.js +3 -0
  99. package/src/server/hosts/openCodeClient.js +3 -0
  100. package/src/server/hosts/openCodeProcess.js +23 -0
  101. package/src/server/hosts/openCodeTurn.js +7 -0
  102. package/src/server/index.js +2 -0
  103. package/src/server/lib/aiConnectionClient.js +13 -6
  104. package/src/server/lib/assistantCompletion.js +190 -0
  105. package/src/server/lib/assistantToolLoop.js +314 -0
  106. package/src/server/lib/serviceToolCatalog.js +25 -10
  107. package/src/shared/assistantResponseText.js +29 -0
  108. package/src/shared/conversation/attachments.js +19 -0
  109. package/src/shared/conversation/index.js +3 -0
  110. package/src/shared/conversation/pagination.js +78 -0
  111. package/src/shared/conversation/patches.js +150 -0
  112. package/src/shared/conversation/questions.js +48 -0
  113. package/src/shared/conversation/streaming.js +7 -4
  114. package/src/shared/index.js +2 -0
  115. package/src/shared/nativeProviders.js +45 -0
  116. package/src/testing/conversationStorageContract.js +31 -1
  117. package/src/testing/nativeCodex.js +11 -0
  118. package/src/testing/nativeOpenCode.js +3 -0
  119. package/test/aiConnectionClient.test.js +2 -0
  120. package/test/apiConversationDriver.test.js +73 -0
  121. package/test/assistantApiSurfaceHeader.test.js +85 -0
  122. package/test/assistantBoundedToolLoop.test.js +285 -0
  123. package/test/assistantScroll.browser.test.js +16 -0
  124. package/test/claudeClient.test.js +189 -0
  125. package/test/claudeConversationSession.test.js +1173 -0
  126. package/test/claudeInstructionResume.test.js +82 -0
  127. package/test/claudeProcess.test.js +204 -0
  128. package/test/claudeTurn.test.js +253 -0
  129. package/test/codexConversationSession.test.js +2122 -0
  130. package/test/codexGoal.test.js +37 -0
  131. package/test/codexHelperDeletion.test.js +163 -0
  132. package/test/codexHelperThreadLedger.test.js +494 -0
  133. package/test/codexHistoryAdapter.test.js +541 -0
  134. package/test/codexInteractiveArguments.test.js +30 -0
  135. package/test/codexIsolation.test.js +756 -0
  136. package/test/codexModelCatalog.test.js +362 -0
  137. package/test/codexNativeHistoryExport.test.js +81 -0
  138. package/test/codexThreadSelection.test.js +136 -0
  139. package/test/codexTurn.test.js +2158 -0
  140. package/test/conversation.test.js +110 -0
  141. package/test/conversationAgentRun.test.js +326 -0
  142. package/test/conversationApiFacilities.test.js +90 -0
  143. package/test/conversationAttachments.test.js +238 -0
  144. package/test/conversationCommandWrapper.test.js +48 -0
  145. package/test/conversationConfiguration.test.js +174 -0
  146. package/test/conversationNativeStorage.test.js +25 -0
  147. package/test/conversationReplacement.test.js +172 -0
  148. package/test/conversationRuntime.test.js +241 -0
  149. package/test/conversationRuntimeStateUpgrade.test.js +144 -0
  150. package/test/conversationSession.test.js +1080 -0
  151. package/test/conversationStreaming.test.js +68 -0
  152. package/test/conversationSystemPrompt.test.js +84 -0
  153. package/test/conversationTools.test.js +416 -0
  154. package/test/fileConversationStorage.test.js +73 -0
  155. package/test/fixtures/codexHelperThreadLedger.js +39 -0
  156. package/test/localConversationExecution.test.js +90 -0
  157. package/test/messageDelivery.test.js +234 -1
  158. package/test/nativeConversationRetirement.test.js +215 -0
  159. package/test/openCodeClient.test.js +515 -0
  160. package/test/openCodeProcess.test.js +177 -0
  161. package/test/openCodeRuntime.test.js +322 -0
  162. package/test/openCodeTools.test.js +287 -0
  163. package/test/opencodeConversationSession.test.js +789 -0
  164. package/test/serviceToolCatalog.test.js +24 -0
@@ -0,0 +1,174 @@
1
+ import {
2
+ codexAppServerTurnStatusIsSuccessfulComplete,
3
+ codexAppServerThreadStatus,
4
+ codexAppServerAgentRun,
5
+ codexAppServerTurnOwnsActiveGoal,
6
+ codexAppServerConversationTurnIsActive,
7
+ CODEX_APP_SERVER_AGENT_RUN_ID,
8
+ CODEX_APP_SERVER_RUN_STATE
9
+ } from "./codexTurnState.js";
10
+
11
+ // Original observation-loss barriers, stop settlement and saved-stop inspection.
12
+ // The shared conversation registry and journal remain their existing owners.
13
+ export function createCodexObservationControl({
14
+ conversations,
15
+ output,
16
+ journal,
17
+ namespace,
18
+ createRuntime,
19
+ publish,
20
+ runInContext,
21
+ turnState,
22
+ errorPrefix
23
+ }) {
24
+ const { codexAppServerConversations } = conversations;
25
+ const { readAgentRunForSession: readCodexAppServerAgentRunForSession } = output;
26
+ const {
27
+ agentRunRealtimePayload: codexAppServerAgentRunRealtimePayload,
28
+ clearActiveTimer: clearCodexAppServerActiveTimer
29
+ } = journal;
30
+
31
+ function assertCodexAppServerThreadCanResume(run, threadId) {
32
+ if (run?.providerThreadId === threadId && run.providerStatus === "observation_lost") {
33
+ throw Object.assign(new Error(run.error || "Codex is stopped. Use Resume or Send to continue."), {
34
+ code: `${errorPrefix}codex_observation_lost`
35
+ });
36
+ }
37
+ }
38
+
39
+ function createCodexAppServerObservation(sessionId, context = {}) {
40
+ const { projectContext, target, retireProvider } = context;
41
+ return {
42
+ prepare({ provider, error }) {
43
+ return runInContext(projectContext, async () => {
44
+ const managed = target(error);
45
+ const threads = new Map();
46
+ for (const entry of codexAppServerConversations.get(namespace(sessionId))?.values() || []) {
47
+ if (entry.provider !== provider) continue;
48
+ threads.set(entry.conversationId, entry.runId);
49
+ if (codexAppServerConversationTurnIsActive(entry.status) || entry.goal?.status === "active") {
50
+ entry.error = managed.pendingMessage;
51
+ }
52
+ }
53
+ // A helper owns only its own threads. Main chat belongs to its managed provider.
54
+ if (managed.threadId) {
55
+ const runtime = await createRuntime();
56
+ const turn = turnState(await runtime.getSession(sessionId));
57
+ threads.set(managed.threadId, turn.turnId);
58
+ if (turn.active || codexAppServerTurnOwnsActiveGoal(turn, managed.threadId)) {
59
+ await runtime.store.writeAgentRunEvent(sessionId, CODEX_APP_SERVER_AGENT_RUN_ID, {
60
+ event: { kind: "observation-lost", message: error.message },
61
+ patch: { providerStatus: "observation_lost", error: managed.pendingMessage }
62
+ });
63
+ await publish(sessionId, { reason: "codex-observation-lost" });
64
+ }
65
+ }
66
+ return threads;
67
+ });
68
+ },
69
+ barrier({ error }) {
70
+ return runInContext(projectContext, async () => {
71
+ const managed = target(error);
72
+ if (!managed.threadId) return;
73
+ const runtime = await createRuntime();
74
+ const turn = turnState(await runtime.getSession(sessionId));
75
+ if (!turn.active && !codexAppServerTurnOwnsActiveGoal(turn, managed.threadId)) return;
76
+ await runtime.store.writeAgentRunEvent(sessionId, CODEX_APP_SERVER_AGENT_RUN_ID, {
77
+ event: { kind: "observation-lost", message: error.message },
78
+ patch: { providerStatus: "observation_lost", error: managed.pendingMessage }
79
+ });
80
+ });
81
+ },
82
+ complete({ provider, error, sharedStop }) {
83
+ return runInContext(projectContext, async () => {
84
+ const managed = target(error);
85
+ let stoppedRun = null;
86
+ let conversationStream = null;
87
+ if (managed.threadId) {
88
+ const runtime = await createRuntime();
89
+ stoppedRun = await runtime.store.mutateSession(sessionId, async () => {
90
+ const run = await readCodexAppServerAgentRunForSession(runtime.store, sessionId);
91
+ if (run?.providerThreadId !== managed.threadId || run.providerStatus !== "observation_lost") return null;
92
+ const stopped = await runtime.store.writeAgentRunEvent(sessionId, CODEX_APP_SERVER_AGENT_RUN_ID, {
93
+ event: { kind: "codex-observation-stopped", state: CODEX_APP_SERVER_RUN_STATE.INTERRUPTED },
94
+ patch: {
95
+ error: sharedStop ? `${managed.message} Its shared service was stopped, affecting other sessions using it.` : managed.message,
96
+ providerStatus: "observation_lost", state: CODEX_APP_SERVER_RUN_STATE.INTERRUPTED
97
+ }
98
+ });
99
+ conversationStream = runtime.store.clearConversationStream(sessionId);
100
+ return stopped;
101
+ });
102
+ }
103
+ // Retain the stop owner until the stopped state is durable. Make the
104
+ // provider ready for explicit control before publishing that state.
105
+ if (sharedStop) await retireProvider(provider);
106
+ else provider.observationFailure = null;
107
+ for (const entry of codexAppServerConversations.get(namespace(sessionId))?.values() || []) {
108
+ if (entry.provider === provider && (
109
+ codexAppServerConversationTurnIsActive(entry.status) || entry.goal?.status === "active"
110
+ )) {
111
+ entry.status = "interrupted";
112
+ entry.error = managed.message;
113
+ entry.watcher?.failNow(error);
114
+ }
115
+ }
116
+ if (stoppedRun) {
117
+ await publish(sessionId, {
118
+ payload: { ...codexAppServerAgentRunRealtimePayload(stoppedRun), conversationStream },
119
+ reason: "codex-observation-stopped"
120
+ });
121
+ }
122
+ });
123
+ }
124
+ };
125
+ }
126
+
127
+ async function recoverCodexAppServerObservationLoss(runtime, session, context = {}) {
128
+ const sessionId = session.sessionId;
129
+ const current = await runtime.getSession(sessionId);
130
+ const turn = turnState(current);
131
+ if (turn.status !== "observation_lost" || !turn.active) return current;
132
+ const threadId = context.threadId(current);
133
+ if (!threadId || (turn.threadId && turn.threadId !== threadId)) return current;
134
+
135
+ // Reconnect only to inspect. Resuming a thread could restart its goal.
136
+ const provider = await context.acquireProvider(current);
137
+ const { goal } = await provider.readGoal(threadId);
138
+ if (goal !== null && !["paused", "complete"].includes(goal?.status)) return current;
139
+ const status = codexAppServerThreadStatus(await provider.readThreadStatus(threadId));
140
+ if (!codexAppServerTurnStatusIsSuccessfulComplete(status)) return current;
141
+
142
+ const stoppedRun = await runtime.store.mutateSession(sessionId, async () => {
143
+ const latest = await readCodexAppServerAgentRunForSession(runtime.store, sessionId);
144
+ if (JSON.stringify(latest) !== JSON.stringify(codexAppServerAgentRun(current))) return null;
145
+ return runtime.store.writeAgentRunEvent(sessionId, CODEX_APP_SERVER_AGENT_RUN_ID, {
146
+ event: { kind: "codex-observation-stop-recovered", message: "Codex confirmed that the conversation is stopped." },
147
+ patch: {
148
+ error: "",
149
+ providerThreadId: threadId,
150
+ providerGoalThreadId: threadId,
151
+ providerGoalStatus: goal?.status || "",
152
+ state: CODEX_APP_SERVER_RUN_STATE.INTERRUPTED
153
+ }
154
+ });
155
+ });
156
+ if (stoppedRun) {
157
+ clearCodexAppServerActiveTimer(sessionId);
158
+ await publish(sessionId, {
159
+ payload: {
160
+ ...codexAppServerAgentRunRealtimePayload(stoppedRun),
161
+ conversationStream: runtime.store.clearConversationStream(sessionId)
162
+ },
163
+ reason: "codex-observation-stop-recovered"
164
+ });
165
+ }
166
+ return runtime.getSession(sessionId);
167
+ }
168
+
169
+ return {
170
+ assertThreadCanResume: assertCodexAppServerThreadCanResume,
171
+ createObservation: createCodexAppServerObservation,
172
+ recoverObservationLoss: recoverCodexAppServerObservationLoss
173
+ };
174
+ }