@code-yeongyu/senpi-ai 2026.9.12-3 → 2026.9.13-2

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 (35) hide show
  1. package/dist/api/devin-agent.lazy.d.ts +2 -0
  2. package/dist/api/devin-agent.lazy.d.ts.map +1 -1
  3. package/dist/api/devin-agent.lazy.js +6 -1
  4. package/dist/api/devin-agent.lazy.js.map +1 -1
  5. package/dist/api/openai-codex-responses.d.ts.map +1 -1
  6. package/dist/api/openai-codex-responses.js +55 -17
  7. package/dist/api/openai-codex-responses.js.map +1 -1
  8. package/dist/api/openai-responses-shared.d.ts.map +1 -1
  9. package/dist/api/openai-responses-shared.js +2 -1
  10. package/dist/api/openai-responses-shared.js.map +1 -1
  11. package/dist/api/openai-responses.d.ts +2 -1
  12. package/dist/api/openai-responses.d.ts.map +1 -1
  13. package/dist/api/openai-responses.js +9 -0
  14. package/dist/api/openai-responses.js.map +1 -1
  15. package/dist/api/responses-completion-grace.d.ts +30 -0
  16. package/dist/api/responses-completion-grace.d.ts.map +1 -0
  17. package/dist/api/responses-completion-grace.js +94 -0
  18. package/dist/api/responses-completion-grace.js.map +1 -0
  19. package/dist/api/websocket-liveness.d.ts +48 -0
  20. package/dist/api/websocket-liveness.d.ts.map +1 -0
  21. package/dist/api/websocket-liveness.js +104 -0
  22. package/dist/api/websocket-liveness.js.map +1 -0
  23. package/dist/devin-provider.d.ts +6 -0
  24. package/dist/devin-provider.d.ts.map +1 -0
  25. package/dist/devin-provider.js +4 -0
  26. package/dist/devin-provider.js.map +1 -0
  27. package/dist/providers/data/.manifest.json +1 -1
  28. package/dist/providers/data/nvidia.json +1 -1
  29. package/dist/providers/data/openrouter.json +1 -1
  30. package/dist/providers/data/together.json +1 -1
  31. package/dist/providers/data/vercel-ai-gateway.json +1 -1
  32. package/dist/utils/retry.d.ts.map +1 -1
  33. package/dist/utils/retry.js +7 -3
  34. package/dist/utils/retry.js.map +1 -1
  35. package/package.json +10 -2
@@ -1,4 +1,6 @@
1
1
  import type { ProviderStreams } from "../types.ts";
2
+ /** Installs the statically bundled implementation in a standalone Bun isolate. */
3
+ export declare function setDevinAgentProviderModule(module: ProviderStreams): void;
2
4
  declare const loadDevinAgentModule: () => Promise<ProviderStreams>;
3
5
  export declare const devinAgentApi: () => ProviderStreams;
4
6
  export { loadDevinAgentModule };
@@ -1 +1 @@
1
- {"version":3,"file":"devin-agent.lazy.d.ts","sourceRoot":"","sources":["../../src/api/devin-agent.lazy.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAcnD,QAAA,MAAM,oBAAoB,QAAO,OAAO,CAAC,eAAe,CACU,CAAC;AAEnE,eAAO,MAAM,aAAa,uBAAsC,CAAC;AACjE,OAAO,EAAE,oBAAoB,EAAE,CAAC"}
1
+ {"version":3,"file":"devin-agent.lazy.d.ts","sourceRoot":"","sources":["../../src/api/devin-agent.lazy.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAgBnD,kFAAkF;AAClF,wBAAgB,2BAA2B,CAAC,MAAM,EAAE,eAAe,GAAG,IAAI,CAEzE;AAED,QAAA,MAAM,oBAAoB,QAAa,OAAO,CAAC,eAAe,CACI,CAAC;AAEnE,eAAO,MAAM,aAAa,uBAAsC,CAAC;AACjE,OAAO,EAAE,oBAAoB,EAAE,CAAC"}
@@ -17,7 +17,12 @@ const importNodeOnlyApi = (specifier) => {
17
17
  const runtimeSpecifier = import.meta.url.endsWith(".js") ? specifier.replace(/\.ts$/, ".js") : specifier;
18
18
  return import(__rewriteRelativeImportExtension(runtimeSpecifier));
19
19
  };
20
- const loadDevinAgentModule = () => importNodeOnlyApi("./devin-agent.ts");
20
+ let devinAgentModuleOverride;
21
+ /** Installs the statically bundled implementation in a standalone Bun isolate. */
22
+ export function setDevinAgentProviderModule(module) {
23
+ devinAgentModuleOverride = module;
24
+ }
25
+ const loadDevinAgentModule = async () => devinAgentModuleOverride ?? importNodeOnlyApi("./devin-agent.ts");
21
26
  export const devinAgentApi = () => lazyApi(loadDevinAgentModule);
22
27
  export { loadDevinAgentModule };
23
28
  //# sourceMappingURL=devin-agent.lazy.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"devin-agent.lazy.js","sourceRoot":"","sources":["../../src/api/devin-agent.lazy.ts"],"names":[],"mappings":";;;;;;;;AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC;;;;;GAKG;AACH,MAAM,iBAAiB,GAAG,CAAC,SAAiB,EAAoB,EAAE;IACjE,MAAM,gBAAgB,GAAG,OAAO,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,OAAO,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IACzG,OAAO,MAAM,kCAAC,gBAAgB,EAAC,CAAC;AACjC,CAAC,CAAC;AAEF,MAAM,oBAAoB,GAAG,GAA6B,EAAE,CAC3D,iBAAiB,CAAC,kBAAkB,CAA6B,CAAC;AAEnE,MAAM,CAAC,MAAM,aAAa,GAAG,GAAG,EAAE,CAAC,OAAO,CAAC,oBAAoB,CAAC,CAAC;AACjE,OAAO,EAAE,oBAAoB,EAAE,CAAC","sourcesContent":["import type { ProviderStreams } from \"../types.ts\";\nimport { lazyApi } from \"./lazy.ts\";\n\n/**\n * Loads the devin-agent implementation through a variable specifier so bundlers\n * (browser smoke, Bun compile) cannot follow the import into the Node-only\n * Connect transport. The `.ts`/`.js` rewrite keeps the trick working from both\n * source and built output.\n */\nconst importNodeOnlyApi = (specifier: string): Promise<unknown> => {\n\tconst runtimeSpecifier = import.meta.url.endsWith(\".js\") ? specifier.replace(/\\.ts$/, \".js\") : specifier;\n\treturn import(runtimeSpecifier);\n};\n\nconst loadDevinAgentModule = (): Promise<ProviderStreams> =>\n\timportNodeOnlyApi(\"./devin-agent.ts\") as Promise<ProviderStreams>;\n\nexport const devinAgentApi = () => lazyApi(loadDevinAgentModule);\nexport { loadDevinAgentModule };\n"]}
1
+ {"version":3,"file":"devin-agent.lazy.js","sourceRoot":"","sources":["../../src/api/devin-agent.lazy.ts"],"names":[],"mappings":";;;;;;;;AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC;;;;;GAKG;AACH,MAAM,iBAAiB,GAAG,CAAC,SAAiB,EAA4B,EAAE;IACzE,MAAM,gBAAgB,GAAG,OAAO,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,OAAO,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IACzG,OAAO,MAAM,kCAAC,gBAAgB,EAAC,CAAC;AACjC,CAAC,CAAC;AAEF,IAAI,wBAAqD,CAAC;AAE1D,kFAAkF;AAClF,MAAM,UAAU,2BAA2B,CAAC,MAAuB;IAClE,wBAAwB,GAAG,MAAM,CAAC;AACnC,CAAC;AAED,MAAM,oBAAoB,GAAG,KAAK,IAA8B,EAAE,CACjE,wBAAwB,IAAI,iBAAiB,CAAC,kBAAkB,CAAC,CAAC;AAEnE,MAAM,CAAC,MAAM,aAAa,GAAG,GAAG,EAAE,CAAC,OAAO,CAAC,oBAAoB,CAAC,CAAC;AACjE,OAAO,EAAE,oBAAoB,EAAE,CAAC","sourcesContent":["import type { ProviderStreams } from \"../types.ts\";\nimport { lazyApi } from \"./lazy.ts\";\n\n/**\n * Loads the devin-agent implementation through a variable specifier so bundlers\n * (browser smoke, Bun compile) cannot follow the import into the Node-only\n * Connect transport. The `.ts`/`.js` rewrite keeps the trick working from both\n * source and built output.\n */\nconst importNodeOnlyApi = (specifier: string): Promise<ProviderStreams> => {\n\tconst runtimeSpecifier = import.meta.url.endsWith(\".js\") ? specifier.replace(/\\.ts$/, \".js\") : specifier;\n\treturn import(runtimeSpecifier);\n};\n\nlet devinAgentModuleOverride: ProviderStreams | undefined;\n\n/** Installs the statically bundled implementation in a standalone Bun isolate. */\nexport function setDevinAgentProviderModule(module: ProviderStreams): void {\n\tdevinAgentModuleOverride = module;\n}\n\nconst loadDevinAgentModule = async (): Promise<ProviderStreams> =>\n\tdevinAgentModuleOverride ?? importNodeOnlyApi(\"./devin-agent.ts\");\n\nexport const devinAgentApi = () => lazyApi(loadDevinAgentModule);\nexport { loadDevinAgentModule };\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"openai-codex-responses.d.ts","sourceRoot":"","sources":["../../src/api/openai-codex-responses.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAEX,6BAA6B,EAG7B,MAAM,yCAAyC,CAAC;AAmBjD,OAAO,KAAK,EAOX,mBAAmB,EACnB,cAAc,EACd,aAAa,EAEb,MAAM,aAAa,CAAC;AAgBrB,OAAO,EAKN,KAAK,8BAA8B,EAGnC,MAAM,4CAA4C,CAAC;AACpD,OAAO,EAAuB,KAAK,0BAA0B,EAAE,MAAM,uCAAuC,CAAC;AAyC7G,MAAM,WAAW,2BAA4B,SAAQ,aAAa;IACjE,eAAe,CAAC,EAAE,MAAM,GAAG,SAAS,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,OAAO,GAAG,KAAK,CAAC;IACnF,gBAAgB,CAAC,EAAE,0BAA0B,CAAC;IAC9C,WAAW,CAAC,EAAE,6BAA6B,CAAC,cAAc,CAAC,GAAG,MAAM,CAAC;IACrE,aAAa,CAAC,EAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAC;IAC1C,UAAU,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,UAAU,CAAC;CAC1C;AAmID,eAAO,MAAM,MAAM,EAAE,cAAc,CAAC,wBAAwB,EAAE,2BAA2B,CAsRxF,CAAC;AAEF,eAAO,MAAM,YAAY,EAAE,cAAc,CAAC,wBAAwB,EAAE,mBAAmB,CA2BtF,CAAC;AAuYF,YAAY,EAAE,8BAA8B,EAAE,MAAM,4CAA4C,CAAC;AAIjG,wBAAgB,iCAAiC,CAAC,SAAS,EAAE,MAAM,GAAG,8BAA8B,GAAG,SAAS,CAE/G;AAED,wBAAgB,mCAAmC,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAE5E;AAED,wBAAgB,iCAAiC,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAgB1E"}
1
+ {"version":3,"file":"openai-codex-responses.d.ts","sourceRoot":"","sources":["../../src/api/openai-codex-responses.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAEX,6BAA6B,EAG7B,MAAM,yCAAyC,CAAC;AAmBjD,OAAO,KAAK,EAOX,mBAAmB,EACnB,cAAc,EACd,aAAa,EAEb,MAAM,aAAa,CAAC;AAgBrB,OAAO,EAKN,KAAK,8BAA8B,EAGnC,MAAM,4CAA4C,CAAC;AACpD,OAAO,EAAuB,KAAK,0BAA0B,EAAE,MAAM,uCAAuC,CAAC;AA0C7G,MAAM,WAAW,2BAA4B,SAAQ,aAAa;IACjE,eAAe,CAAC,EAAE,MAAM,GAAG,SAAS,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,OAAO,GAAG,KAAK,CAAC;IACnF,gBAAgB,CAAC,EAAE,0BAA0B,CAAC;IAC9C,WAAW,CAAC,EAAE,6BAA6B,CAAC,cAAc,CAAC,GAAG,MAAM,CAAC;IACrE,aAAa,CAAC,EAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAC;IAC1C,UAAU,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,UAAU,CAAC;CAC1C;AAmID,eAAO,MAAM,MAAM,EAAE,cAAc,CAAC,wBAAwB,EAAE,2BAA2B,CAsRxF,CAAC;AAEF,eAAO,MAAM,YAAY,EAAE,cAAc,CAAC,wBAAwB,EAAE,mBAAmB,CA2BtF,CAAC;AA0YF,YAAY,EAAE,8BAA8B,EAAE,MAAM,4CAA4C,CAAC;AAIjG,wBAAgB,iCAAiC,CAAC,SAAS,EAAE,MAAM,GAAG,8BAA8B,GAAG,SAAS,CAE/G;AAED,wBAAgB,mCAAmC,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAE5E;AAED,wBAAgB,iCAAiC,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAgB1E"}
@@ -25,6 +25,7 @@ import { buildCodexReasoning } from "./openai-codex-responses/reasoning.js";
25
25
  import { applyOpenAICodexCacheAffinityHeaders, clampOpenAIPromptCacheKey } from "./openai-prompt-cache.js";
26
26
  import { convertResponsesMessages, convertResponsesTools, processResponsesStream } from "./openai-responses-shared.js";
27
27
  import { applyExtraBody, buildBaseOptions, clampMaxForOpenAI, OPENAI_RESPONSES_RESERVED_BODY_KEYS, } from "./simple-options.js";
28
+ import { startWebSocketLiveness } from "./websocket-liveness.js";
28
29
  // ============================================================================
29
30
  // Configuration
30
31
  // ============================================================================
@@ -682,8 +683,7 @@ export function resetOpenAICodexWebSocketDebugStats(sessionId) {
682
683
  }
683
684
  export function closeOpenAICodexWebSocketSessions(sessionId) {
684
685
  const closeEntry = (entry) => {
685
- if (entry.idleTimer)
686
- clearTimeout(entry.idleTimer);
686
+ unparkSessionWebSocket(entry);
687
687
  closeWebSocketSilently(entry.socket, 1000, "debug_close");
688
688
  };
689
689
  if (sessionId) {
@@ -722,6 +722,13 @@ async function getWebSocketConstructor(env) {
722
722
  url,
723
723
  { ..._opts, ...(proxyUrl ? { proxy: proxyUrl.toString() } : {}) },
724
724
  ]);
725
+ const innerPing = this.socket.ping;
726
+ if (typeof innerPing === "function") {
727
+ this.ping = (data) => innerPing.call(this.socket, data);
728
+ }
729
+ }
730
+ get readyState() {
731
+ return getWebSocketReadyState(this.socket);
725
732
  }
726
733
  close(code, reason) {
727
734
  this.socket.close(code, reason);
@@ -776,20 +783,48 @@ function closeWebSocketSilently(socket, code = 1000, reason = "done") {
776
783
  }
777
784
  catch { }
778
785
  }
779
- function scheduleSessionWebSocketExpiry(sessionId, accountId, entry) {
786
+ function evictSessionWebSocket(sessionId, accountId, entry, reason) {
787
+ unparkSessionWebSocket(entry);
788
+ closeWebSocketSilently(entry.socket, 1000, reason);
789
+ const accountEntries = websocketSessionCache.get(sessionId);
790
+ if (accountEntries?.get(accountId) === entry)
791
+ accountEntries.delete(accountId);
792
+ if (accountEntries?.size === 0)
793
+ websocketSessionCache.delete(sessionId);
794
+ }
795
+ function unparkSessionWebSocket(entry) {
780
796
  if (entry.idleTimer) {
781
797
  clearTimeout(entry.idleTimer);
798
+ entry.idleTimer = undefined;
782
799
  }
800
+ if (entry.parkedCloseListener) {
801
+ entry.socket.removeEventListener("close", entry.parkedCloseListener);
802
+ entry.socket.removeEventListener("error", entry.parkedCloseListener);
803
+ entry.parkedCloseListener = undefined;
804
+ }
805
+ }
806
+ /**
807
+ * Parks a connection between requests. The idle TTL is the only eviction the
808
+ * cache had; a server or network close while parked must evict immediately,
809
+ * because a WHATWG `send()` on a closed socket discards the frame silently and
810
+ * the next request would then wait out the whole stream-start watchdog.
811
+ */
812
+ function parkSessionWebSocket(sessionId, accountId, entry) {
813
+ unparkSessionWebSocket(entry);
814
+ entry.busy = false;
783
815
  entry.idleTimer = setTimeout(() => {
784
816
  if (entry.busy)
785
817
  return;
786
- closeWebSocketSilently(entry.socket, 1000, "idle_timeout");
787
- const accountEntries = websocketSessionCache.get(sessionId);
788
- if (accountEntries?.get(accountId) === entry)
789
- accountEntries.delete(accountId);
790
- if (accountEntries?.size === 0)
791
- websocketSessionCache.delete(sessionId);
818
+ evictSessionWebSocket(sessionId, accountId, entry, "idle_timeout");
792
819
  }, SESSION_WEBSOCKET_CACHE_TTL_MS);
820
+ const onParkedClose = () => {
821
+ if (entry.busy)
822
+ return;
823
+ evictSessionWebSocket(sessionId, accountId, entry, "parked_close");
824
+ };
825
+ entry.parkedCloseListener = onParkedClose;
826
+ entry.socket.addEventListener("close", onParkedClose);
827
+ entry.socket.addEventListener("error", onParkedClose);
793
828
  }
794
829
  async function connectWebSocket(url, headers, signal, connectTimeoutMs = DEFAULT_WEBSOCKET_CONNECT_TIMEOUT_MS, env) {
795
830
  const WebSocketCtor = await getWebSocketConstructor(env);
@@ -871,10 +906,7 @@ async function acquireWebSocket(url, headers, sessionId, accountId, signal, conn
871
906
  let accountEntries = websocketSessionCache.get(sessionId);
872
907
  const cached = accountEntries?.get(accountId);
873
908
  if (cached) {
874
- if (cached.idleTimer) {
875
- clearTimeout(cached.idleTimer);
876
- cached.idleTimer = undefined;
877
- }
909
+ unparkSessionWebSocket(cached);
878
910
  if (!cached.busy && isWebSocketSessionExpired(cached)) {
879
911
  closeWebSocketSilently(cached.socket, 1000, "connection_age_limit");
880
912
  accountEntries?.delete(accountId);
@@ -897,8 +929,7 @@ async function acquireWebSocket(url, headers, sessionId, accountId, signal, conn
897
929
  websocketSessionCache.delete(sessionId);
898
930
  return;
899
931
  }
900
- cached.busy = false;
901
- scheduleSessionWebSocketExpiry(sessionId, accountId, cached);
932
+ parkSessionWebSocket(sessionId, accountId, cached);
902
933
  },
903
934
  };
904
935
  }
@@ -943,8 +974,7 @@ async function acquireWebSocket(url, headers, sessionId, accountId, signal, conn
943
974
  websocketSessionCache.delete(sessionId);
944
975
  return;
945
976
  }
946
- entry.busy = false;
947
- scheduleSessionWebSocketExpiry(sessionId, accountId, entry);
977
+ parkSessionWebSocket(sessionId, accountId, entry);
948
978
  },
949
979
  };
950
980
  }
@@ -1015,7 +1045,14 @@ async function* parseWebSocket(socket, signal, idleTimeoutMs) {
1015
1045
  pending = null;
1016
1046
  resolve();
1017
1047
  };
1048
+ const liveness = startWebSocketLiveness(socket, (error) => {
1049
+ failed = error;
1050
+ done = true;
1051
+ closeWebSocketSilently(socket, 1000, "liveness_timeout");
1052
+ wake();
1053
+ });
1018
1054
  const onMessage = (event) => {
1055
+ liveness.noteActivity();
1019
1056
  void (async () => {
1020
1057
  let text = null;
1021
1058
  try {
@@ -1107,6 +1144,7 @@ async function* parseWebSocket(socket, signal, idleTimeoutMs) {
1107
1144
  }
1108
1145
  }
1109
1146
  finally {
1147
+ liveness.stop();
1110
1148
  socket.removeEventListener("message", onMessage);
1111
1149
  socket.removeEventListener("error", onError);
1112
1150
  socket.removeEventListener("close", onClose);