@code-yeongyu/senpi 2026.10.11 → 2026.10.12
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/CHANGELOG.md +46 -0
- package/dist/bundle/chunks/anthropic-messages-GYG6YZY5.js +10 -0
- package/dist/bundle/chunks/{app-server-command-NHDOL4HQ.js → app-server-command-OL6PPUOA.js} +1 -1
- package/dist/bundle/chunks/{azure-openai-responses-EJF2XJ7Q.js → azure-openai-responses-GU6FOSJR.js} +1 -1
- package/dist/bundle/chunks/{chunk-ZABLYCHT.js → chunk-46JEQXD7.js} +1 -1
- package/dist/bundle/chunks/{chunk-VE3D74HN.js → chunk-55VKYA5V.js} +1 -1
- package/dist/bundle/chunks/{chunk-7UNN3YHW.js → chunk-5AVFHHDF.js} +230 -221
- package/dist/bundle/chunks/{chunk-2JE2DOIF.js → chunk-5DPTM5E2.js} +1 -1
- package/dist/bundle/chunks/chunk-5UPUSGP5.js +2 -0
- package/dist/bundle/chunks/chunk-5VMRMY6N.js +16 -0
- package/dist/bundle/chunks/{chunk-7X3VRAM3.js → chunk-7P3QPVTF.js} +1 -1
- package/dist/bundle/chunks/{chunk-T6IYKWIH.js → chunk-BUGZZVQW.js} +1 -1
- package/dist/bundle/chunks/chunk-DL7EFVT2.js +12 -0
- package/dist/bundle/chunks/chunk-E5YUVGLQ.js +11 -0
- package/dist/bundle/chunks/{chunk-RLFQICEY.js → chunk-EQJY2B5F.js} +1 -1
- package/dist/bundle/chunks/{chunk-VYKBN4MR.js → chunk-GC2RU5TS.js} +1 -1
- package/dist/bundle/chunks/chunk-GPKEJOTQ.js +202 -0
- package/dist/bundle/chunks/{chunk-KCVSSFOV.js → chunk-GQ5PWY6P.js} +4 -3
- package/dist/bundle/chunks/{chunk-4GPJOGXZ.js → chunk-I4AEC6MH.js} +1 -1
- package/dist/bundle/chunks/chunk-JXSFGRBE.js +8 -0
- package/dist/bundle/chunks/{chunk-YGCMN2CX.js → chunk-NAY5LB53.js} +1 -1
- package/dist/bundle/chunks/{chunk-EBOD66AS.js → chunk-PBN2CATL.js} +2 -2
- package/dist/bundle/chunks/chunk-PFNBY43W.js +2 -0
- package/dist/bundle/chunks/{chunk-CY2B4QRR.js → chunk-PUWEQK2W.js} +1 -1
- package/dist/bundle/chunks/{chunk-5DBPUQSX.js → chunk-SF6AUNQZ.js} +1 -1
- package/dist/bundle/chunks/{chunk-G2XAU4BX.js → chunk-TMTT5CLA.js} +1 -1
- package/dist/bundle/chunks/{chunk-2JKDZXIY.js → chunk-VWFKLW73.js} +2 -2
- package/dist/bundle/chunks/chunk-WZMSBRTW.js +2 -0
- package/dist/bundle/chunks/{chunk-55HLKZSB.js → chunk-XVJRRLGN.js} +1 -1
- package/dist/bundle/chunks/chunk-Z2PWWBBD.js +31 -0
- package/dist/bundle/chunks/cli-main-RSIYAR4J.js +3 -0
- package/dist/bundle/chunks/{cloudflare-workers-ai-system-one-SWVU2AXJ.js → cloudflare-workers-ai-system-one-LVWRKOUD.js} +1 -1
- package/dist/bundle/chunks/{google-generative-ai-XG4YX6FQ.js → google-generative-ai-JMGYPTXL.js} +1 -1
- package/dist/bundle/chunks/{google-vertex-BBOZ6OUB.js → google-vertex-CI4FPIU7.js} +1 -1
- package/dist/bundle/chunks/{help-fast-path-EZ3KEW6V.js → help-fast-path-M7KMBM6K.js} +1 -1
- package/dist/bundle/chunks/host-command-6UR3DSFR.js +2 -0
- package/dist/bundle/chunks/host-lifecycle-2BKCCK5X.js +3 -0
- package/dist/bundle/chunks/host-lifecycle.js +10 -7
- package/dist/bundle/chunks/host-session-command-A2MZHEBP.js +19 -0
- package/dist/bundle/chunks/interactive-mode-EJBMTJOH.js +2 -0
- package/dist/bundle/chunks/{list-tips-WE2YGQM6.js → list-tips-BEQAOA4N.js} +1 -1
- package/dist/bundle/chunks/{mistral-conversations-RB3ZBCGE.js → mistral-conversations-5OD7662T.js} +1 -1
- package/dist/bundle/chunks/{multi-session-host-V4CUQLV7.js → multi-session-host-YYMLHCUA.js} +4 -4
- package/dist/bundle/chunks/{openai-codex-responses-DBTPUXRW.js → openai-codex-responses-FN3UPAFI.js} +1 -1
- package/dist/bundle/chunks/{openai-completions-QAJQC4BY.js → openai-completions-KMUQ3T4M.js} +1 -1
- package/dist/bundle/chunks/{openai-responses-UBJWCEHG.js → openai-responses-V4Q5GVLO.js} +1 -1
- package/dist/bundle/chunks/{package-manager-cli-WTRDT4ZH.js → package-manager-cli-6A5ZP26E.js} +1 -1
- package/dist/bundle/chunks/rotation-stream-PT6LLBMJ.js +2 -0
- package/dist/bundle/chunks/rpc-mode-XNYJPYUM.js +2 -0
- package/dist/bundle/chunks/runtime-session-ZBHFMT65.js +2 -0
- package/dist/bundle/chunks/{schedule-command-PJVRKAKD.js → schedule-command-FYQG2MFX.js} +1 -1
- package/dist/bundle/chunks/session-control-endpoint-7TX4XHN4.js +3 -0
- package/dist/bundle/chunks/session-picker-4RNB27SM.js +2 -0
- package/dist/bundle/chunks/session-worker.js +418 -412
- package/dist/bundle/chunks/{typesafe-system-one-B5TW3FHM.js → typesafe-system-one-WUHW7HR4.js} +1 -1
- package/dist/bundle/cli.js +1 -1
- package/dist/bundle/index.js +1 -1
- package/dist/bundle/rpc-entry.js +1 -1
- package/dist/bundle/runtime-manifest.json +1 -1
- package/dist/core/agent-session.d.ts +11 -2
- package/dist/core/agent-session.js +152 -43
- package/dist/core/compaction/compaction.js +2 -0
- package/dist/core/extensions/builtin/anthropic-web-search/index.js +22 -14
- package/dist/core/extensions/builtin/cache-keepalive/index.js +8 -4
- package/dist/core/extensions/builtin/cache-keepalive/session-prewarm.d.ts +2 -1
- package/dist/core/extensions/builtin/cache-keepalive/session-prewarm.js +55 -7
- package/dist/core/extensions/builtin/cache-keepalive/startup-activity-gate.d.ts +8 -0
- package/dist/core/extensions/builtin/cache-keepalive/startup-activity-gate.js +25 -0
- package/dist/core/extensions/builtin/compaction/index.js +13 -5
- package/dist/core/extensions/builtin/compaction/speculative.d.ts +1 -0
- package/dist/core/extensions/builtin/compaction/speculative.js +8 -4
- package/dist/core/extensions/builtin/moved-path-guard/tool-classes.js +1 -0
- package/dist/core/extensions/builtin/openai-web-search/index.d.ts +4 -1
- package/dist/core/extensions/builtin/openai-web-search/index.js +54 -17
- package/dist/core/extensions/builtin/server-search-fallback.d.ts +12 -0
- package/dist/core/extensions/builtin/server-search-fallback.js +50 -0
- package/dist/core/extensions/builtin/terminal/runtime-session.d.ts +10 -1
- package/dist/core/extensions/builtin/terminal/runtime-session.js +48 -4
- package/dist/core/extensions/builtin/websearch/index.d.ts +1 -1
- package/dist/core/extensions/builtin/websearch/index.js +119 -18
- package/dist/core/extensions/builtin/websearch/server-search.d.ts +11 -0
- package/dist/core/extensions/builtin/websearch/server-search.js +230 -0
- package/dist/core/extensions/builtin/websearch/websearch/native.d.ts +2 -0
- package/dist/core/extensions/builtin/websearch/websearch/search-model.js +15 -0
- package/dist/core/extensions/runner.d.ts +8 -1
- package/dist/core/extensions/runner.js +56 -7
- package/dist/core/extensions/types.d.ts +12 -2
- package/dist/core/extensions/user-activity.d.ts +10 -0
- package/dist/core/extensions/user-activity.js +20 -0
- package/dist/core/model-config-schema.d.ts +34 -0
- package/dist/core/model-config-schema.js +2 -0
- package/dist/core/model-config.js +1 -0
- package/dist/core/reserved-keywords.d.ts +28 -0
- package/dist/core/reserved-keywords.js +81 -0
- package/dist/core/retry-fallback/candidates.d.ts +1 -1
- package/dist/core/retry-fallback/candidates.js +1 -12
- package/dist/core/retry-fallback/controller.d.ts +3 -1
- package/dist/core/retry-fallback/controller.js +11 -5
- package/dist/core/retry-fallback/cooldown.d.ts +2 -1
- package/dist/core/retry-fallback/cooldown.js +21 -12
- package/dist/core/retry-fallback/unusable.d.ts +2 -0
- package/dist/core/retry-fallback/unusable.js +14 -2
- package/dist/core/retry-fallback/usage-limit.d.ts +10 -1
- package/dist/core/retry-fallback/usage-limit.js +39 -2
- package/dist/core/session-title-generator.js +2 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.js +1 -0
- package/dist/modes/index.d.ts +1 -1
- package/dist/modes/interactive/components/assistant-render-descriptors.js +7 -1
- package/dist/modes/interactive/composer-user-activity.d.ts +6 -0
- package/dist/modes/interactive/composer-user-activity.js +30 -0
- package/dist/modes/interactive/grok/chrome.js +2 -1
- package/dist/modes/interactive/interactive-mode.js +15 -6
- package/dist/modes/interactive/session-control-registry.js +8 -1
- package/dist/modes/interactive/theme/reserved-keyword-rainbow.d.ts +11 -0
- package/dist/modes/interactive/theme/reserved-keyword-rainbow.js +50 -0
- package/dist/modes/interactive/theme/theme.d.ts +3 -1
- package/dist/modes/interactive/theme/theme.js +9 -0
- package/dist/modes/print-mode.js +7 -2
- package/dist/modes/rpc/connection-handler.js +43 -11
- package/dist/modes/rpc/custom-capability.d.ts +2 -0
- package/dist/modes/rpc/custom-capability.js +2 -0
- package/dist/modes/rpc/host-admission-proxy.d.ts +9 -0
- package/dist/modes/rpc/host-admission-proxy.js +211 -0
- package/dist/modes/rpc/host-admission.d.ts +21 -0
- package/dist/modes/rpc/host-admission.js +59 -0
- package/dist/modes/rpc/host-capabilities.js +2 -1
- package/dist/modes/rpc/host-client-occupancy.d.ts +2 -1
- package/dist/modes/rpc/host-client-occupancy.js +7 -0
- package/dist/modes/rpc/host-decision.d.ts +2 -2
- package/dist/modes/rpc/host-decision.js +4 -0
- package/dist/modes/rpc/host-ensure-types.d.ts +2 -0
- package/dist/modes/rpc/host-ensure.js +31 -3
- package/dist/modes/rpc/host-lifecycle-drain.d.ts +2 -1
- package/dist/modes/rpc/host-lifecycle-drain.js +3 -1
- package/dist/modes/rpc/host-lifecycle-proxy.d.ts +3 -2
- package/dist/modes/rpc/host-lifecycle-proxy.js +10 -19
- package/dist/modes/rpc/host-lifecycle-shutdown.d.ts +2 -0
- package/dist/modes/rpc/host-lifecycle-shutdown.js +3 -1
- package/dist/modes/rpc/host-lifecycle-ticker.d.ts +11 -0
- package/dist/modes/rpc/host-lifecycle-ticker.js +27 -0
- package/dist/modes/rpc/host-lifecycle.js +15 -23
- package/dist/modes/rpc/host-outcome.js +1 -0
- package/dist/modes/rpc/host-protocol-info.d.ts +2 -0
- package/dist/modes/rpc/host-protocol-info.js +1 -0
- package/dist/modes/rpc/host-session-runner.js +22 -1
- package/dist/modes/rpc/host-status-all.js +1 -0
- package/dist/modes/rpc/host-status.d.ts +1 -0
- package/dist/modes/rpc/host-status.js +5 -1
- package/dist/modes/rpc/rpc-client.d.ts +7 -1
- package/dist/modes/rpc/rpc-client.js +12 -0
- package/dist/modes/rpc/rpc-types.d.ts +49 -1
- package/dist/modes/rpc/rpc-types.js +5 -0
- package/dist/modes/rpc/session-command-activity.js +2 -0
- package/dist/modes/rpc/session-held.js +3 -0
- package/docs/extensions.md +13 -1
- package/docs/providers.md +88 -0
- package/docs/rpc.md +150 -5
- package/docs/web-search.md +3 -1
- package/package.json +7 -7
- package/dist/bundle/chunks/anthropic-messages-5QQJVQPZ.js +0 -9
- package/dist/bundle/chunks/chunk-2A3MS2Z7.js +0 -8
- package/dist/bundle/chunks/chunk-6SBY4ZWC.js +0 -2
- package/dist/bundle/chunks/chunk-6WCOSBI7.js +0 -2
- package/dist/bundle/chunks/chunk-E75RO54O.js +0 -14
- package/dist/bundle/chunks/chunk-JMYO34RK.js +0 -2
- package/dist/bundle/chunks/chunk-KRNXUTZJ.js +0 -2
- package/dist/bundle/chunks/chunk-L4HVJWIF.js +0 -11
- package/dist/bundle/chunks/chunk-N5WLLHUE.js +0 -2
- package/dist/bundle/chunks/chunk-NEFNNQSV.js +0 -9
- package/dist/bundle/chunks/chunk-PWIYVLIA.js +0 -9
- package/dist/bundle/chunks/chunk-Q3R44CGT.js +0 -5
- package/dist/bundle/chunks/chunk-QIARZN7G.js +0 -31
- package/dist/bundle/chunks/chunk-QKU6JOA4.js +0 -2
- package/dist/bundle/chunks/chunk-QYWXDE47.js +0 -2
- package/dist/bundle/chunks/chunk-XHELSLN3.js +0 -188
- package/dist/bundle/chunks/chunk-YDJ4HGWO.js +0 -16
- package/dist/bundle/chunks/chunk-ZJHRDQCH.js +0 -2
- package/dist/bundle/chunks/cli-main-TUBNBZNK.js +0 -3
- package/dist/bundle/chunks/host-command-WO7VKJBJ.js +0 -2
- package/dist/bundle/chunks/host-lifecycle-X2J5FTJL.js +0 -3
- package/dist/bundle/chunks/host-session-command-ICBOH5RP.js +0 -19
- package/dist/bundle/chunks/interactive-mode-UGDNCGQ5.js +0 -2
- package/dist/bundle/chunks/rotation-stream-OODURUGZ.js +0 -2
- package/dist/bundle/chunks/rpc-mode-22MCT32O.js +0 -2
- package/dist/bundle/chunks/runtime-session-I4NDNGC5.js +0 -2
- package/dist/bundle/chunks/session-control-endpoint-SFPRQBDO.js +0 -3
- package/dist/bundle/chunks/session-picker-3ZQPV7Z3.js +0 -2
|
@@ -78,6 +78,7 @@ declare const ModelDefinitionSchema: Type.TObject<{
|
|
|
78
78
|
extraBody: Type.TOptional<Type.TRecord<"^.*$", Type.TUnknown>>;
|
|
79
79
|
cacheRetention: Type.TOptional<Type.TUnion<[Type.TLiteral<"none">, Type.TLiteral<"short">, Type.TLiteral<"long">]>>;
|
|
80
80
|
compat: Type.TOptional<Type.TUnion<[Type.TObject<{
|
|
81
|
+
supportsWebSearch: Type.TOptional<Type.TBoolean>;
|
|
81
82
|
supportsStore: Type.TOptional<Type.TBoolean>;
|
|
82
83
|
supportsDeveloperRole: Type.TOptional<Type.TBoolean>;
|
|
83
84
|
supportsReasoningEffort: Type.TOptional<Type.TBoolean>;
|
|
@@ -142,6 +143,7 @@ declare const ModelDefinitionSchema: Type.TObject<{
|
|
|
142
143
|
supportsLongCacheRetention: Type.TOptional<Type.TBoolean>;
|
|
143
144
|
supportsForcedToolChoice: Type.TOptional<Type.TBoolean>;
|
|
144
145
|
}>, Type.TObject<{
|
|
146
|
+
webSearchToolType: Type.TOptional<Type.TUnion<[Type.TLiteral<"web_search">, Type.TLiteral<"web_search_preview">]>>;
|
|
145
147
|
supportsDeveloperRole: Type.TOptional<Type.TBoolean>;
|
|
146
148
|
sessionAffinityFormat: Type.TOptional<Type.TUnion<[Type.TLiteral<"openai">, Type.TLiteral<"openai-nosession">, Type.TLiteral<"openrouter">]>>;
|
|
147
149
|
supportsLongCacheRetention: Type.TOptional<Type.TBoolean>;
|
|
@@ -234,6 +236,7 @@ declare const ModelOverrideSchema: Type.TObject<{
|
|
|
234
236
|
extraBody: Type.TOptional<Type.TRecord<"^.*$", Type.TUnknown>>;
|
|
235
237
|
cacheRetention: Type.TOptional<Type.TUnion<[Type.TLiteral<"none">, Type.TLiteral<"short">, Type.TLiteral<"long">]>>;
|
|
236
238
|
compat: Type.TOptional<Type.TUnion<[Type.TObject<{
|
|
239
|
+
supportsWebSearch: Type.TOptional<Type.TBoolean>;
|
|
237
240
|
supportsStore: Type.TOptional<Type.TBoolean>;
|
|
238
241
|
supportsDeveloperRole: Type.TOptional<Type.TBoolean>;
|
|
239
242
|
supportsReasoningEffort: Type.TOptional<Type.TBoolean>;
|
|
@@ -298,6 +301,7 @@ declare const ModelOverrideSchema: Type.TObject<{
|
|
|
298
301
|
supportsLongCacheRetention: Type.TOptional<Type.TBoolean>;
|
|
299
302
|
supportsForcedToolChoice: Type.TOptional<Type.TBoolean>;
|
|
300
303
|
}>, Type.TObject<{
|
|
304
|
+
webSearchToolType: Type.TOptional<Type.TUnion<[Type.TLiteral<"web_search">, Type.TLiteral<"web_search_preview">]>>;
|
|
301
305
|
supportsDeveloperRole: Type.TOptional<Type.TBoolean>;
|
|
302
306
|
sessionAffinityFormat: Type.TOptional<Type.TUnion<[Type.TLiteral<"openai">, Type.TLiteral<"openai-nosession">, Type.TLiteral<"openrouter">]>>;
|
|
303
307
|
supportsLongCacheRetention: Type.TOptional<Type.TBoolean>;
|
|
@@ -348,6 +352,7 @@ declare const ProviderConfigSchema: Type.TObject<{
|
|
|
348
352
|
extraBody: Type.TOptional<Type.TRecord<"^.*$", Type.TUnknown>>;
|
|
349
353
|
cacheRetention: Type.TOptional<Type.TUnion<[Type.TLiteral<"none">, Type.TLiteral<"short">, Type.TLiteral<"long">]>>;
|
|
350
354
|
compat: Type.TOptional<Type.TUnion<[Type.TObject<{
|
|
355
|
+
supportsWebSearch: Type.TOptional<Type.TBoolean>;
|
|
351
356
|
supportsStore: Type.TOptional<Type.TBoolean>;
|
|
352
357
|
supportsDeveloperRole: Type.TOptional<Type.TBoolean>;
|
|
353
358
|
supportsReasoningEffort: Type.TOptional<Type.TBoolean>;
|
|
@@ -412,6 +417,7 @@ declare const ProviderConfigSchema: Type.TObject<{
|
|
|
412
417
|
supportsLongCacheRetention: Type.TOptional<Type.TBoolean>;
|
|
413
418
|
supportsForcedToolChoice: Type.TOptional<Type.TBoolean>;
|
|
414
419
|
}>, Type.TObject<{
|
|
420
|
+
webSearchToolType: Type.TOptional<Type.TUnion<[Type.TLiteral<"web_search">, Type.TLiteral<"web_search_preview">]>>;
|
|
415
421
|
supportsDeveloperRole: Type.TOptional<Type.TBoolean>;
|
|
416
422
|
sessionAffinityFormat: Type.TOptional<Type.TUnion<[Type.TLiteral<"openai">, Type.TLiteral<"openai-nosession">, Type.TLiteral<"openrouter">]>>;
|
|
417
423
|
supportsLongCacheRetention: Type.TOptional<Type.TBoolean>;
|
|
@@ -512,6 +518,7 @@ declare const ProviderConfigSchema: Type.TObject<{
|
|
|
512
518
|
extraBody: Type.TOptional<Type.TRecord<"^.*$", Type.TUnknown>>;
|
|
513
519
|
cacheRetention: Type.TOptional<Type.TUnion<[Type.TLiteral<"none">, Type.TLiteral<"short">, Type.TLiteral<"long">]>>;
|
|
514
520
|
compat: Type.TOptional<Type.TUnion<[Type.TObject<{
|
|
521
|
+
supportsWebSearch: Type.TOptional<Type.TBoolean>;
|
|
515
522
|
supportsStore: Type.TOptional<Type.TBoolean>;
|
|
516
523
|
supportsDeveloperRole: Type.TOptional<Type.TBoolean>;
|
|
517
524
|
supportsReasoningEffort: Type.TOptional<Type.TBoolean>;
|
|
@@ -576,6 +583,7 @@ declare const ProviderConfigSchema: Type.TObject<{
|
|
|
576
583
|
supportsLongCacheRetention: Type.TOptional<Type.TBoolean>;
|
|
577
584
|
supportsForcedToolChoice: Type.TOptional<Type.TBoolean>;
|
|
578
585
|
}>, Type.TObject<{
|
|
586
|
+
webSearchToolType: Type.TOptional<Type.TUnion<[Type.TLiteral<"web_search">, Type.TLiteral<"web_search_preview">]>>;
|
|
579
587
|
supportsDeveloperRole: Type.TOptional<Type.TBoolean>;
|
|
580
588
|
sessionAffinityFormat: Type.TOptional<Type.TUnion<[Type.TLiteral<"openai">, Type.TLiteral<"openai-nosession">, Type.TLiteral<"openrouter">]>>;
|
|
581
589
|
supportsLongCacheRetention: Type.TOptional<Type.TBoolean>;
|
|
@@ -668,6 +676,7 @@ declare const ProviderConfigSchema: Type.TObject<{
|
|
|
668
676
|
extraBody: Type.TOptional<Type.TRecord<"^.*$", Type.TUnknown>>;
|
|
669
677
|
cacheRetention: Type.TOptional<Type.TUnion<[Type.TLiteral<"none">, Type.TLiteral<"short">, Type.TLiteral<"long">]>>;
|
|
670
678
|
compat: Type.TOptional<Type.TUnion<[Type.TObject<{
|
|
679
|
+
supportsWebSearch: Type.TOptional<Type.TBoolean>;
|
|
671
680
|
supportsStore: Type.TOptional<Type.TBoolean>;
|
|
672
681
|
supportsDeveloperRole: Type.TOptional<Type.TBoolean>;
|
|
673
682
|
supportsReasoningEffort: Type.TOptional<Type.TBoolean>;
|
|
@@ -732,6 +741,7 @@ declare const ProviderConfigSchema: Type.TObject<{
|
|
|
732
741
|
supportsLongCacheRetention: Type.TOptional<Type.TBoolean>;
|
|
733
742
|
supportsForcedToolChoice: Type.TOptional<Type.TBoolean>;
|
|
734
743
|
}>, Type.TObject<{
|
|
744
|
+
webSearchToolType: Type.TOptional<Type.TUnion<[Type.TLiteral<"web_search">, Type.TLiteral<"web_search_preview">]>>;
|
|
735
745
|
supportsDeveloperRole: Type.TOptional<Type.TBoolean>;
|
|
736
746
|
sessionAffinityFormat: Type.TOptional<Type.TUnion<[Type.TLiteral<"openai">, Type.TLiteral<"openai-nosession">, Type.TLiteral<"openrouter">]>>;
|
|
737
747
|
supportsLongCacheRetention: Type.TOptional<Type.TBoolean>;
|
|
@@ -795,6 +805,7 @@ declare const ModelsConfigSchema: Type.TObject<{
|
|
|
795
805
|
extraBody: Type.TOptional<Type.TRecord<"^.*$", Type.TUnknown>>;
|
|
796
806
|
cacheRetention: Type.TOptional<Type.TUnion<[Type.TLiteral<"none">, Type.TLiteral<"short">, Type.TLiteral<"long">]>>;
|
|
797
807
|
compat: Type.TOptional<Type.TUnion<[Type.TObject<{
|
|
808
|
+
supportsWebSearch: Type.TOptional<Type.TBoolean>;
|
|
798
809
|
supportsStore: Type.TOptional<Type.TBoolean>;
|
|
799
810
|
supportsDeveloperRole: Type.TOptional<Type.TBoolean>;
|
|
800
811
|
supportsReasoningEffort: Type.TOptional<Type.TBoolean>;
|
|
@@ -859,6 +870,7 @@ declare const ModelsConfigSchema: Type.TObject<{
|
|
|
859
870
|
supportsLongCacheRetention: Type.TOptional<Type.TBoolean>;
|
|
860
871
|
supportsForcedToolChoice: Type.TOptional<Type.TBoolean>;
|
|
861
872
|
}>, Type.TObject<{
|
|
873
|
+
webSearchToolType: Type.TOptional<Type.TUnion<[Type.TLiteral<"web_search">, Type.TLiteral<"web_search_preview">]>>;
|
|
862
874
|
supportsDeveloperRole: Type.TOptional<Type.TBoolean>;
|
|
863
875
|
sessionAffinityFormat: Type.TOptional<Type.TUnion<[Type.TLiteral<"openai">, Type.TLiteral<"openai-nosession">, Type.TLiteral<"openrouter">]>>;
|
|
864
876
|
supportsLongCacheRetention: Type.TOptional<Type.TBoolean>;
|
|
@@ -959,6 +971,7 @@ declare const ModelsConfigSchema: Type.TObject<{
|
|
|
959
971
|
extraBody: Type.TOptional<Type.TRecord<"^.*$", Type.TUnknown>>;
|
|
960
972
|
cacheRetention: Type.TOptional<Type.TUnion<[Type.TLiteral<"none">, Type.TLiteral<"short">, Type.TLiteral<"long">]>>;
|
|
961
973
|
compat: Type.TOptional<Type.TUnion<[Type.TObject<{
|
|
974
|
+
supportsWebSearch: Type.TOptional<Type.TBoolean>;
|
|
962
975
|
supportsStore: Type.TOptional<Type.TBoolean>;
|
|
963
976
|
supportsDeveloperRole: Type.TOptional<Type.TBoolean>;
|
|
964
977
|
supportsReasoningEffort: Type.TOptional<Type.TBoolean>;
|
|
@@ -1023,6 +1036,7 @@ declare const ModelsConfigSchema: Type.TObject<{
|
|
|
1023
1036
|
supportsLongCacheRetention: Type.TOptional<Type.TBoolean>;
|
|
1024
1037
|
supportsForcedToolChoice: Type.TOptional<Type.TBoolean>;
|
|
1025
1038
|
}>, Type.TObject<{
|
|
1039
|
+
webSearchToolType: Type.TOptional<Type.TUnion<[Type.TLiteral<"web_search">, Type.TLiteral<"web_search_preview">]>>;
|
|
1026
1040
|
supportsDeveloperRole: Type.TOptional<Type.TBoolean>;
|
|
1027
1041
|
sessionAffinityFormat: Type.TOptional<Type.TUnion<[Type.TLiteral<"openai">, Type.TLiteral<"openai-nosession">, Type.TLiteral<"openrouter">]>>;
|
|
1028
1042
|
supportsLongCacheRetention: Type.TOptional<Type.TBoolean>;
|
|
@@ -1115,6 +1129,7 @@ declare const ModelsConfigSchema: Type.TObject<{
|
|
|
1115
1129
|
extraBody: Type.TOptional<Type.TRecord<"^.*$", Type.TUnknown>>;
|
|
1116
1130
|
cacheRetention: Type.TOptional<Type.TUnion<[Type.TLiteral<"none">, Type.TLiteral<"short">, Type.TLiteral<"long">]>>;
|
|
1117
1131
|
compat: Type.TOptional<Type.TUnion<[Type.TObject<{
|
|
1132
|
+
supportsWebSearch: Type.TOptional<Type.TBoolean>;
|
|
1118
1133
|
supportsStore: Type.TOptional<Type.TBoolean>;
|
|
1119
1134
|
supportsDeveloperRole: Type.TOptional<Type.TBoolean>;
|
|
1120
1135
|
supportsReasoningEffort: Type.TOptional<Type.TBoolean>;
|
|
@@ -1179,6 +1194,7 @@ declare const ModelsConfigSchema: Type.TObject<{
|
|
|
1179
1194
|
supportsLongCacheRetention: Type.TOptional<Type.TBoolean>;
|
|
1180
1195
|
supportsForcedToolChoice: Type.TOptional<Type.TBoolean>;
|
|
1181
1196
|
}>, Type.TObject<{
|
|
1197
|
+
webSearchToolType: Type.TOptional<Type.TUnion<[Type.TLiteral<"web_search">, Type.TLiteral<"web_search_preview">]>>;
|
|
1182
1198
|
supportsDeveloperRole: Type.TOptional<Type.TBoolean>;
|
|
1183
1199
|
sessionAffinityFormat: Type.TOptional<Type.TUnion<[Type.TLiteral<"openai">, Type.TLiteral<"openai-nosession">, Type.TLiteral<"openrouter">]>>;
|
|
1184
1200
|
supportsLongCacheRetention: Type.TOptional<Type.TBoolean>;
|
|
@@ -1243,6 +1259,7 @@ export declare const validateModelsConfig: import("typebox/compile").Validator<{
|
|
|
1243
1259
|
extraBody: Type.TOptional<Type.TRecord<"^.*$", Type.TUnknown>>;
|
|
1244
1260
|
cacheRetention: Type.TOptional<Type.TUnion<[Type.TLiteral<"none">, Type.TLiteral<"short">, Type.TLiteral<"long">]>>;
|
|
1245
1261
|
compat: Type.TOptional<Type.TUnion<[Type.TObject<{
|
|
1262
|
+
supportsWebSearch: Type.TOptional<Type.TBoolean>;
|
|
1246
1263
|
supportsStore: Type.TOptional<Type.TBoolean>;
|
|
1247
1264
|
supportsDeveloperRole: Type.TOptional<Type.TBoolean>;
|
|
1248
1265
|
supportsReasoningEffort: Type.TOptional<Type.TBoolean>;
|
|
@@ -1307,6 +1324,7 @@ export declare const validateModelsConfig: import("typebox/compile").Validator<{
|
|
|
1307
1324
|
supportsLongCacheRetention: Type.TOptional<Type.TBoolean>;
|
|
1308
1325
|
supportsForcedToolChoice: Type.TOptional<Type.TBoolean>;
|
|
1309
1326
|
}>, Type.TObject<{
|
|
1327
|
+
webSearchToolType: Type.TOptional<Type.TUnion<[Type.TLiteral<"web_search">, Type.TLiteral<"web_search_preview">]>>;
|
|
1310
1328
|
supportsDeveloperRole: Type.TOptional<Type.TBoolean>;
|
|
1311
1329
|
sessionAffinityFormat: Type.TOptional<Type.TUnion<[Type.TLiteral<"openai">, Type.TLiteral<"openai-nosession">, Type.TLiteral<"openrouter">]>>;
|
|
1312
1330
|
supportsLongCacheRetention: Type.TOptional<Type.TBoolean>;
|
|
@@ -1407,6 +1425,7 @@ export declare const validateModelsConfig: import("typebox/compile").Validator<{
|
|
|
1407
1425
|
extraBody: Type.TOptional<Type.TRecord<"^.*$", Type.TUnknown>>;
|
|
1408
1426
|
cacheRetention: Type.TOptional<Type.TUnion<[Type.TLiteral<"none">, Type.TLiteral<"short">, Type.TLiteral<"long">]>>;
|
|
1409
1427
|
compat: Type.TOptional<Type.TUnion<[Type.TObject<{
|
|
1428
|
+
supportsWebSearch: Type.TOptional<Type.TBoolean>;
|
|
1410
1429
|
supportsStore: Type.TOptional<Type.TBoolean>;
|
|
1411
1430
|
supportsDeveloperRole: Type.TOptional<Type.TBoolean>;
|
|
1412
1431
|
supportsReasoningEffort: Type.TOptional<Type.TBoolean>;
|
|
@@ -1471,6 +1490,7 @@ export declare const validateModelsConfig: import("typebox/compile").Validator<{
|
|
|
1471
1490
|
supportsLongCacheRetention: Type.TOptional<Type.TBoolean>;
|
|
1472
1491
|
supportsForcedToolChoice: Type.TOptional<Type.TBoolean>;
|
|
1473
1492
|
}>, Type.TObject<{
|
|
1493
|
+
webSearchToolType: Type.TOptional<Type.TUnion<[Type.TLiteral<"web_search">, Type.TLiteral<"web_search_preview">]>>;
|
|
1474
1494
|
supportsDeveloperRole: Type.TOptional<Type.TBoolean>;
|
|
1475
1495
|
sessionAffinityFormat: Type.TOptional<Type.TUnion<[Type.TLiteral<"openai">, Type.TLiteral<"openai-nosession">, Type.TLiteral<"openrouter">]>>;
|
|
1476
1496
|
supportsLongCacheRetention: Type.TOptional<Type.TBoolean>;
|
|
@@ -1563,6 +1583,7 @@ export declare const validateModelsConfig: import("typebox/compile").Validator<{
|
|
|
1563
1583
|
extraBody: Type.TOptional<Type.TRecord<"^.*$", Type.TUnknown>>;
|
|
1564
1584
|
cacheRetention: Type.TOptional<Type.TUnion<[Type.TLiteral<"none">, Type.TLiteral<"short">, Type.TLiteral<"long">]>>;
|
|
1565
1585
|
compat: Type.TOptional<Type.TUnion<[Type.TObject<{
|
|
1586
|
+
supportsWebSearch: Type.TOptional<Type.TBoolean>;
|
|
1566
1587
|
supportsStore: Type.TOptional<Type.TBoolean>;
|
|
1567
1588
|
supportsDeveloperRole: Type.TOptional<Type.TBoolean>;
|
|
1568
1589
|
supportsReasoningEffort: Type.TOptional<Type.TBoolean>;
|
|
@@ -1627,6 +1648,7 @@ export declare const validateModelsConfig: import("typebox/compile").Validator<{
|
|
|
1627
1648
|
supportsLongCacheRetention: Type.TOptional<Type.TBoolean>;
|
|
1628
1649
|
supportsForcedToolChoice: Type.TOptional<Type.TBoolean>;
|
|
1629
1650
|
}>, Type.TObject<{
|
|
1651
|
+
webSearchToolType: Type.TOptional<Type.TUnion<[Type.TLiteral<"web_search">, Type.TLiteral<"web_search_preview">]>>;
|
|
1630
1652
|
supportsDeveloperRole: Type.TOptional<Type.TBoolean>;
|
|
1631
1653
|
sessionAffinityFormat: Type.TOptional<Type.TUnion<[Type.TLiteral<"openai">, Type.TLiteral<"openai-nosession">, Type.TLiteral<"openrouter">]>>;
|
|
1632
1654
|
supportsLongCacheRetention: Type.TOptional<Type.TBoolean>;
|
|
@@ -1690,6 +1712,7 @@ export declare const validateModelsConfig: import("typebox/compile").Validator<{
|
|
|
1690
1712
|
extraBody?: Record<string, unknown> | undefined;
|
|
1691
1713
|
cacheRetention?: "long" | "none" | "short" | undefined;
|
|
1692
1714
|
compat?: {
|
|
1715
|
+
supportsWebSearch?: boolean | undefined;
|
|
1693
1716
|
supportsStore?: boolean | undefined;
|
|
1694
1717
|
supportsDeveloperRole?: boolean | undefined;
|
|
1695
1718
|
supportsReasoningEffort?: boolean | undefined;
|
|
@@ -1754,6 +1777,7 @@ export declare const validateModelsConfig: import("typebox/compile").Validator<{
|
|
|
1754
1777
|
supportsLongCacheRetention?: boolean | undefined;
|
|
1755
1778
|
supportsForcedToolChoice?: boolean | undefined;
|
|
1756
1779
|
} | {
|
|
1780
|
+
webSearchToolType?: "web_search" | "web_search_preview" | undefined;
|
|
1757
1781
|
supportsDeveloperRole?: boolean | undefined;
|
|
1758
1782
|
sessionAffinityFormat?: "openai" | "openai-nosession" | "openrouter" | undefined;
|
|
1759
1783
|
supportsLongCacheRetention?: boolean | undefined;
|
|
@@ -1854,6 +1878,7 @@ export declare const validateModelsConfig: import("typebox/compile").Validator<{
|
|
|
1854
1878
|
extraBody?: Record<string, unknown> | undefined;
|
|
1855
1879
|
cacheRetention?: "long" | "none" | "short" | undefined;
|
|
1856
1880
|
compat?: {
|
|
1881
|
+
supportsWebSearch?: boolean | undefined;
|
|
1857
1882
|
supportsStore?: boolean | undefined;
|
|
1858
1883
|
supportsDeveloperRole?: boolean | undefined;
|
|
1859
1884
|
supportsReasoningEffort?: boolean | undefined;
|
|
@@ -1918,6 +1943,7 @@ export declare const validateModelsConfig: import("typebox/compile").Validator<{
|
|
|
1918
1943
|
supportsLongCacheRetention?: boolean | undefined;
|
|
1919
1944
|
supportsForcedToolChoice?: boolean | undefined;
|
|
1920
1945
|
} | {
|
|
1946
|
+
webSearchToolType?: "web_search" | "web_search_preview" | undefined;
|
|
1921
1947
|
supportsDeveloperRole?: boolean | undefined;
|
|
1922
1948
|
sessionAffinityFormat?: "openai" | "openai-nosession" | "openrouter" | undefined;
|
|
1923
1949
|
supportsLongCacheRetention?: boolean | undefined;
|
|
@@ -2010,6 +2036,7 @@ export declare const validateModelsConfig: import("typebox/compile").Validator<{
|
|
|
2010
2036
|
extraBody?: Record<string, unknown> | undefined;
|
|
2011
2037
|
cacheRetention?: "long" | "none" | "short" | undefined;
|
|
2012
2038
|
compat?: {
|
|
2039
|
+
supportsWebSearch?: boolean | undefined;
|
|
2013
2040
|
supportsStore?: boolean | undefined;
|
|
2014
2041
|
supportsDeveloperRole?: boolean | undefined;
|
|
2015
2042
|
supportsReasoningEffort?: boolean | undefined;
|
|
@@ -2074,6 +2101,7 @@ export declare const validateModelsConfig: import("typebox/compile").Validator<{
|
|
|
2074
2101
|
supportsLongCacheRetention?: boolean | undefined;
|
|
2075
2102
|
supportsForcedToolChoice?: boolean | undefined;
|
|
2076
2103
|
} | {
|
|
2104
|
+
webSearchToolType?: "web_search" | "web_search_preview" | undefined;
|
|
2077
2105
|
supportsDeveloperRole?: boolean | undefined;
|
|
2078
2106
|
sessionAffinityFormat?: "openai" | "openai-nosession" | "openrouter" | undefined;
|
|
2079
2107
|
supportsLongCacheRetention?: boolean | undefined;
|
|
@@ -2137,6 +2165,7 @@ export declare const validateModelsConfig: import("typebox/compile").Validator<{
|
|
|
2137
2165
|
extraBody?: Record<string, unknown> | undefined;
|
|
2138
2166
|
cacheRetention?: "long" | "none" | "short" | undefined;
|
|
2139
2167
|
compat?: {
|
|
2168
|
+
supportsWebSearch?: boolean | undefined;
|
|
2140
2169
|
supportsStore?: boolean | undefined;
|
|
2141
2170
|
supportsDeveloperRole?: boolean | undefined;
|
|
2142
2171
|
supportsReasoningEffort?: boolean | undefined;
|
|
@@ -2201,6 +2230,7 @@ export declare const validateModelsConfig: import("typebox/compile").Validator<{
|
|
|
2201
2230
|
supportsLongCacheRetention?: boolean | undefined;
|
|
2202
2231
|
supportsForcedToolChoice?: boolean | undefined;
|
|
2203
2232
|
} | {
|
|
2233
|
+
webSearchToolType?: "web_search" | "web_search_preview" | undefined;
|
|
2204
2234
|
supportsDeveloperRole?: boolean | undefined;
|
|
2205
2235
|
sessionAffinityFormat?: "openai" | "openai-nosession" | "openrouter" | undefined;
|
|
2206
2236
|
supportsLongCacheRetention?: boolean | undefined;
|
|
@@ -2301,6 +2331,7 @@ export declare const validateModelsConfig: import("typebox/compile").Validator<{
|
|
|
2301
2331
|
extraBody?: Record<string, unknown> | undefined;
|
|
2302
2332
|
cacheRetention?: "long" | "none" | "short" | undefined;
|
|
2303
2333
|
compat?: {
|
|
2334
|
+
supportsWebSearch?: boolean | undefined;
|
|
2304
2335
|
supportsStore?: boolean | undefined;
|
|
2305
2336
|
supportsDeveloperRole?: boolean | undefined;
|
|
2306
2337
|
supportsReasoningEffort?: boolean | undefined;
|
|
@@ -2365,6 +2396,7 @@ export declare const validateModelsConfig: import("typebox/compile").Validator<{
|
|
|
2365
2396
|
supportsLongCacheRetention?: boolean | undefined;
|
|
2366
2397
|
supportsForcedToolChoice?: boolean | undefined;
|
|
2367
2398
|
} | {
|
|
2399
|
+
webSearchToolType?: "web_search" | "web_search_preview" | undefined;
|
|
2368
2400
|
supportsDeveloperRole?: boolean | undefined;
|
|
2369
2401
|
sessionAffinityFormat?: "openai" | "openai-nosession" | "openrouter" | undefined;
|
|
2370
2402
|
supportsLongCacheRetention?: boolean | undefined;
|
|
@@ -2457,6 +2489,7 @@ export declare const validateModelsConfig: import("typebox/compile").Validator<{
|
|
|
2457
2489
|
extraBody?: Record<string, unknown> | undefined;
|
|
2458
2490
|
cacheRetention?: "long" | "none" | "short" | undefined;
|
|
2459
2491
|
compat?: {
|
|
2492
|
+
supportsWebSearch?: boolean | undefined;
|
|
2460
2493
|
supportsStore?: boolean | undefined;
|
|
2461
2494
|
supportsDeveloperRole?: boolean | undefined;
|
|
2462
2495
|
supportsReasoningEffort?: boolean | undefined;
|
|
@@ -2521,6 +2554,7 @@ export declare const validateModelsConfig: import("typebox/compile").Validator<{
|
|
|
2521
2554
|
supportsLongCacheRetention?: boolean | undefined;
|
|
2522
2555
|
supportsForcedToolChoice?: boolean | undefined;
|
|
2523
2556
|
} | {
|
|
2557
|
+
webSearchToolType?: "web_search" | "web_search_preview" | undefined;
|
|
2524
2558
|
supportsDeveloperRole?: boolean | undefined;
|
|
2525
2559
|
sessionAffinityFormat?: "openai" | "openai-nosession" | "openrouter" | undefined;
|
|
2526
2560
|
supportsLongCacheRetention?: boolean | undefined;
|
|
@@ -101,6 +101,7 @@ const ModelInputLimitsSchema = Type.Object({
|
|
|
101
101
|
})),
|
|
102
102
|
});
|
|
103
103
|
const OpenAICompletionsCompatSchema = Type.Object({
|
|
104
|
+
supportsWebSearch: Type.Optional(Type.Boolean()),
|
|
104
105
|
supportsStore: Type.Optional(Type.Boolean()),
|
|
105
106
|
supportsDeveloperRole: Type.Optional(Type.Boolean()),
|
|
106
107
|
supportsReasoningEffort: Type.Optional(Type.Boolean()),
|
|
@@ -138,6 +139,7 @@ const OpenAICompletionsCompatSchema = Type.Object({
|
|
|
138
139
|
supportsForcedToolChoice: Type.Optional(Type.Boolean()),
|
|
139
140
|
});
|
|
140
141
|
const OpenAIResponsesCompatSchema = Type.Object({
|
|
142
|
+
webSearchToolType: Type.Optional(Type.Union([Type.Literal("web_search"), Type.Literal("web_search_preview")])),
|
|
141
143
|
supportsDeveloperRole: Type.Optional(Type.Boolean()),
|
|
142
144
|
sessionAffinityFormat: Type.Optional(Type.Union([Type.Literal("openai"), Type.Literal("openai-nosession"), Type.Literal("openrouter")])),
|
|
143
145
|
supportsLongCacheRetention: Type.Optional(Type.Boolean()),
|
|
@@ -109,6 +109,7 @@ const OpenAICompletionsCompatSchema = Type.Object({
|
|
|
109
109
|
});
|
|
110
110
|
|
|
111
111
|
const OpenAIResponsesCompatSchema = Type.Object({
|
|
112
|
+
webSearchToolType: Type.Optional(Type.Union([Type.Literal("web_search"), Type.Literal("web_search_preview")])),
|
|
112
113
|
supportsDeveloperRole: Type.Optional(Type.Boolean()),
|
|
113
114
|
sessionAffinityFormat: Type.Optional(
|
|
114
115
|
Type.Union([Type.Literal("openai"), Type.Literal("openai-nosession"), Type.Literal("openrouter")]),
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OmO's reserved prompt keywords (`ulw`, `mass ulw`, `ulw plan`, `ulw loop`, `ulw research`).
|
|
3
|
+
*
|
|
4
|
+
* Mirrors the omo-senpi engine's arming rules (omo `packages/omo-senpi/src/components/
|
|
5
|
+
* {ultrawork/index.ts, skill-pointers/index.ts, skill-pointers/strip-quoted-regions.ts}`),
|
|
6
|
+
* so the editor paints a keyword only where the engine would arm it: case-insensitive,
|
|
7
|
+
* spaces or hyphens between words, the mass aliases (`mulw`, `meth`, `ulw mass`), and
|
|
8
|
+
* each name only as a word of its own (not inside an identifier, path, file name or URL).
|
|
9
|
+
* Overlapping mentions all match ("ulw research" is both `ultrawork` and `ulw-research`).
|
|
10
|
+
* Injected blocks, fenced/inline code, relay headers, block quotes, double quotes, URLs
|
|
11
|
+
* and negated invocations ("do not load mass-ulw") are quoted material, never a request.
|
|
12
|
+
*/
|
|
13
|
+
export type ReservedKeyword = "ultrawork" | "mass-ulw" | "ulw-plan" | "ulw-loop" | "ulw-research";
|
|
14
|
+
export interface ReservedKeywordSpan {
|
|
15
|
+
readonly keyword: ReservedKeyword;
|
|
16
|
+
/** UTF-16 offsets into the searched text, end exclusive. */
|
|
17
|
+
readonly start: number;
|
|
18
|
+
readonly end: number;
|
|
19
|
+
}
|
|
20
|
+
export interface ReservedKeywordRun {
|
|
21
|
+
readonly start: number;
|
|
22
|
+
readonly end: number;
|
|
23
|
+
}
|
|
24
|
+
/** Every reserved-keyword mention outside quoted regions, in text order. */
|
|
25
|
+
export declare function findReservedKeywordSpans(text: string): ReservedKeywordSpan[];
|
|
26
|
+
/** Overlapping mentions ("mass ulw research" is three) merge into one painted run, as on the desktop. */
|
|
27
|
+
export declare function findReservedKeywordRuns(text: string): ReservedKeywordRun[];
|
|
28
|
+
//# sourceMappingURL=reserved-keywords.d.ts.map
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
const MASS_ULW_ALIAS = String.raw `(?:mass[\s-]*ulw|ulw[\s-]*mass|mulw|meth)`;
|
|
2
|
+
// A keyword glued to a preceding identifier segment (`mass-ulw`, `senpi-ulw-loop`, `.omo/ulw/`, `v1.ulw`)
|
|
3
|
+
// names something else; so does one that opens a path (`ulw-execute/ledger.jsonl`).
|
|
4
|
+
const NOT_AFTER_IDENTIFIER = String.raw `(?<![A-Za-z0-9][-_.]|[/\\])`;
|
|
5
|
+
const NOT_BEFORE_PATH = String.raw `(?![-_.]?[A-Za-z0-9]*[/\\])`;
|
|
6
|
+
// The name must end its own word (`ulw-plan-refactor`, `ulw-plan.md` do not count); a chained
|
|
7
|
+
// skill word may follow if it, too, ends there (`mass ulw-loop`).
|
|
8
|
+
const SEGMENT_END = String.raw `(?![-_.]?[A-Za-z0-9])`;
|
|
9
|
+
const NOT_INTO_IDENTIFIER = String.raw `(?${SEGMENT_END})[A-Za-z0-9]|\.[A-Za-z0-9])`;
|
|
10
|
+
const keywordPattern = (body) => new RegExp(String.raw `${NOT_AFTER_IDENTIFIER}\b${body}\b${NOT_INTO_IDENTIFIER}${NOT_BEFORE_PATH}`, "gi");
|
|
11
|
+
const RESERVED_KEYWORD_PATTERNS = [
|
|
12
|
+
["ultrawork", keywordPattern("(?:ultrawork|ulw)")],
|
|
13
|
+
["mass-ulw", keywordPattern(MASS_ULW_ALIAS)],
|
|
14
|
+
["ulw-plan", keywordPattern(String.raw `ulw[\s-]*plan`)],
|
|
15
|
+
["ulw-loop", keywordPattern(String.raw `ulw[\s-]*loop`)],
|
|
16
|
+
["ulw-research", keywordPattern(String.raw `(?:ulw|${MASS_ULW_ALIAS})[\s-]*research`)],
|
|
17
|
+
];
|
|
18
|
+
/** Cheap pre-check: every reserved keyword contains one of these stems. */
|
|
19
|
+
const RESERVED_KEYWORD_STEM = /ulw|ultrawork|mulw|meth/i;
|
|
20
|
+
const INJECTED_BLOCK = /<(omo-[a-z0-9-]+-pointer|ultrawork-mode|omo-ultrawork-reminder)>[\s\S]*?<\/\1>/gi;
|
|
21
|
+
const INLINE_CODE = /(?<!`)(`+)(?!`)[\s\S]*?(?<!`)\1(?!`)/g;
|
|
22
|
+
// A relayed message opens with a sender header (`[REPORT]`, `[a -> b]`, `Name (id), recipient:`): all of it is someone else's text.
|
|
23
|
+
const RELAY_HEADER = /^\s*(?:\[(?:[A-Z][A-Z0-9_-]{2,}|[\w.-]+ -> [\w.-]+)\]|[A-Z][\w.-]{0,30} \([^()\s]{1,40}\)(?:, | to )[\w.-]{1,40}:)/;
|
|
24
|
+
const BLOCK_QUOTE_LINE = /^ {0,3}>[^\n]*/gm;
|
|
25
|
+
const DOUBLE_QUOTED = /"[^"\n]*"|\u201C[^\u201D\n]*\u201D/g;
|
|
26
|
+
const URL_SPAN = /(?<![a-z0-9+.-])[a-z][a-z0-9+.-]*:\/\/[^\s<>"'`]+/gi;
|
|
27
|
+
// A keyword named only to forbid it ("Do not load mass-ulw or ulw-research") is masked up to the next clause break.
|
|
28
|
+
const NEGATED_INVOCATION = /\b(?:do\s+not|don['\u2019]t|dont|never)\s+(?:load|use|run|invoke|start|trigger|arm|enable)\b[^.;:!?\n]*?(?=[.;:!?\n]|\s(?:but|then|instead|however)\b|\s[\u2014\u2013-]\s|$)/gi;
|
|
29
|
+
function maskRegion(region) {
|
|
30
|
+
return region.replace(/[^\r\n]/g, "\0");
|
|
31
|
+
}
|
|
32
|
+
/** Quoted, injected, relayed and negated regions are masked (offsets kept) before matching. */
|
|
33
|
+
function maskQuotedRegions(text) {
|
|
34
|
+
if (RELAY_HEADER.test(text))
|
|
35
|
+
return maskRegion(text);
|
|
36
|
+
let visible = text.replace(INJECTED_BLOCK, maskRegion);
|
|
37
|
+
const fenceStart = /^ {0,3}(`{3,}|~{3,})[^\n]*(?:\n|$)/gm;
|
|
38
|
+
for (let opening = fenceStart.exec(visible); opening !== null; opening = fenceStart.exec(visible)) {
|
|
39
|
+
const fence = opening[1] ?? "```";
|
|
40
|
+
const fenceEnd = new RegExp(`^ {0,3}${fence[0]}{${fence.length},}[ \\t]*\\r?$`, "gm");
|
|
41
|
+
fenceEnd.lastIndex = fenceStart.lastIndex;
|
|
42
|
+
const closing = fenceEnd.exec(visible);
|
|
43
|
+
const end = closing === null ? visible.length : fenceEnd.lastIndex;
|
|
44
|
+
visible = visible.slice(0, opening.index) + maskRegion(visible.slice(opening.index, end)) + visible.slice(end);
|
|
45
|
+
fenceStart.lastIndex = end;
|
|
46
|
+
}
|
|
47
|
+
return visible
|
|
48
|
+
.replace(INLINE_CODE, maskRegion)
|
|
49
|
+
.replace(BLOCK_QUOTE_LINE, maskRegion)
|
|
50
|
+
.replace(DOUBLE_QUOTED, maskRegion)
|
|
51
|
+
.replace(URL_SPAN, maskRegion)
|
|
52
|
+
.replace(NEGATED_INVOCATION, maskRegion);
|
|
53
|
+
}
|
|
54
|
+
/** Every reserved-keyword mention outside quoted regions, in text order. */
|
|
55
|
+
export function findReservedKeywordSpans(text) {
|
|
56
|
+
if (!RESERVED_KEYWORD_STEM.test(text))
|
|
57
|
+
return [];
|
|
58
|
+
const visible = maskQuotedRegions(text);
|
|
59
|
+
const spans = [];
|
|
60
|
+
for (const [keyword, pattern] of RESERVED_KEYWORD_PATTERNS) {
|
|
61
|
+
for (const match of visible.matchAll(pattern)) {
|
|
62
|
+
spans.push({ keyword, start: match.index, end: match.index + match[0].length });
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
return spans.sort((left, right) => left.start - right.start || right.end - left.end);
|
|
66
|
+
}
|
|
67
|
+
/** Overlapping mentions ("mass ulw research" is three) merge into one painted run, as on the desktop. */
|
|
68
|
+
export function findReservedKeywordRuns(text) {
|
|
69
|
+
const runs = [];
|
|
70
|
+
for (const span of findReservedKeywordSpans(text)) {
|
|
71
|
+
const previous = runs.at(-1);
|
|
72
|
+
if (previous !== undefined && span.start <= previous.end) {
|
|
73
|
+
previous.end = Math.max(previous.end, span.end);
|
|
74
|
+
}
|
|
75
|
+
else {
|
|
76
|
+
runs.push({ start: span.start, end: span.end });
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
return runs;
|
|
80
|
+
}
|
|
81
|
+
//# sourceMappingURL=reserved-keywords.js.map
|
|
@@ -11,7 +11,7 @@ export interface CandidateFilters {
|
|
|
11
11
|
isSuppressed(base: string): boolean;
|
|
12
12
|
isAuthAvailable(provider: string): boolean;
|
|
13
13
|
isCircuitOpen(base: string): boolean;
|
|
14
|
-
/** Providers whose account-wide usage limit or billing failure this session saw: their entries are
|
|
14
|
+
/** Providers whose account-wide usage limit or billing failure this session saw: their entries are skipped. */
|
|
15
15
|
isProviderSpent?(provider: string): boolean;
|
|
16
16
|
skip(candidate: string, skipReason: string): void;
|
|
17
17
|
}
|
|
@@ -1,17 +1,6 @@
|
|
|
1
1
|
import { baseSelector, candidatesAfter, formatSelector, parseFallbackSelector, } from "./chains.js";
|
|
2
2
|
export function firstUsableCandidate(entries, current, filters) {
|
|
3
|
-
|
|
4
|
-
if (!isSpent)
|
|
5
|
-
return scanCandidates(entries, current, filters, () => false);
|
|
6
|
-
let avoided = false;
|
|
7
|
-
const elsewhere = scanCandidates(entries, current, filters, (provider) => {
|
|
8
|
-
const spent = isSpent(provider);
|
|
9
|
-
avoided ||= spent;
|
|
10
|
-
return spent;
|
|
11
|
-
});
|
|
12
|
-
if (elsewhere || !avoided)
|
|
13
|
-
return elsewhere;
|
|
14
|
-
return scanCandidates(entries, current, filters, () => false);
|
|
3
|
+
return scanCandidates(entries, current, filters, (provider) => filters.isProviderSpent?.(provider) ?? false);
|
|
15
4
|
}
|
|
16
5
|
function scanCandidates(entries, current, filters, avoidProvider) {
|
|
17
6
|
let probe;
|
|
@@ -14,6 +14,8 @@ export declare class RetryFallbackController {
|
|
|
14
14
|
constructor(deps: RetryFallbackControllerDeps);
|
|
15
15
|
get activeState(): Readonly<ActiveFallbackState> | undefined;
|
|
16
16
|
get exhaustedChainKey(): string | undefined;
|
|
17
|
+
isProviderSpent(provider: string): boolean;
|
|
18
|
+
accountError(provider: string): string | undefined;
|
|
17
19
|
resetTurn(): void;
|
|
18
20
|
clear(): void;
|
|
19
21
|
private canonicalChains;
|
|
@@ -68,7 +70,7 @@ export declare class RetryFallbackController {
|
|
|
68
70
|
tryFallback(reason: FallbackReason, failure: {
|
|
69
71
|
errorMessage?: string;
|
|
70
72
|
retryAfterMs?: number;
|
|
71
|
-
}): Promise<boolean>;
|
|
73
|
+
}, failureObserved?: boolean): Promise<boolean>;
|
|
72
74
|
private applyCandidate;
|
|
73
75
|
/** The chain governing `current`, when fallback is enabled; a model's own chain wins over an active one. */
|
|
74
76
|
private managedChainKey;
|
|
@@ -18,6 +18,12 @@ export class RetryFallbackController {
|
|
|
18
18
|
get exhaustedChainKey() {
|
|
19
19
|
return this.lastExhaustedChainKey;
|
|
20
20
|
}
|
|
21
|
+
isProviderSpent(provider) {
|
|
22
|
+
return this.unusable.isProviderSpent(provider);
|
|
23
|
+
}
|
|
24
|
+
accountError(provider) {
|
|
25
|
+
return this.unusable.accountError(provider);
|
|
26
|
+
}
|
|
21
27
|
resetTurn() {
|
|
22
28
|
this.triedSelectors.clear();
|
|
23
29
|
this.lastExhaustedChainKey = undefined;
|
|
@@ -149,9 +155,9 @@ export class RetryFallbackController {
|
|
|
149
155
|
* half-open probe - independent of whether a fallback candidate remains.
|
|
150
156
|
*/
|
|
151
157
|
noteHealthFailure(model, thinkingLevel, failure) {
|
|
158
|
+
this.unusable.note(model, failure);
|
|
152
159
|
if (!this.managedChainKey({ model, thinkingLevel }))
|
|
153
160
|
return;
|
|
154
|
-
this.unusable.note(model, failure);
|
|
155
161
|
this.probes.noteFailure(formatSelector(model), failure);
|
|
156
162
|
}
|
|
157
163
|
/**
|
|
@@ -174,21 +180,21 @@ export class RetryFallbackController {
|
|
|
174
180
|
await this.applyCandidate(current, candidate, "transient");
|
|
175
181
|
return true;
|
|
176
182
|
}
|
|
177
|
-
async tryFallback(reason, failure) {
|
|
183
|
+
async tryFallback(reason, failure, failureObserved = true) {
|
|
178
184
|
const current = this.deps.getCurrentSelector();
|
|
179
185
|
// Only a transient failure that spent its budget opens the shared circuit
|
|
180
186
|
// here; billing/quota exhaustion is recorded at the failure itself (see
|
|
181
187
|
// noteHealthFailure) so the final chain entry opens too.
|
|
182
|
-
if (current && reason === "transient")
|
|
188
|
+
if (failureObserved && current && reason === "transient")
|
|
183
189
|
this.noteHealthFailure(current.model, current.thinkingLevel, failure);
|
|
184
190
|
const limit = usageLimitScope(failure.errorMessage);
|
|
185
|
-
if (current)
|
|
191
|
+
if (failureObserved && current)
|
|
186
192
|
this.unusable.note(current.model, failure);
|
|
187
193
|
let candidate = this.nextCandidate(false, true);
|
|
188
194
|
if (!current || !candidate)
|
|
189
195
|
return false;
|
|
190
196
|
const currentBase = formatSelector(current.model);
|
|
191
|
-
if (reason === "transient" || reason === "hard-error" || reason === "billing") {
|
|
197
|
+
if (failureObserved && (reason === "transient" || reason === "hard-error" || reason === "billing")) {
|
|
192
198
|
this.deps.cooldowns.note(currentBase, failure);
|
|
193
199
|
this.deps.logger.info("cooldown_noted", { selector: currentBase, errorMessage: failure.errorMessage });
|
|
194
200
|
}
|
|
@@ -7,7 +7,8 @@ export declare class SelectorCooldowns {
|
|
|
7
7
|
private readonly expiresAtBySelector;
|
|
8
8
|
private readonly now;
|
|
9
9
|
private readonly random;
|
|
10
|
-
|
|
10
|
+
private readonly wallNow;
|
|
11
|
+
constructor(now: () => number, random?: () => number, wallNow?: () => number);
|
|
11
12
|
note(baseSelector: string, failure: {
|
|
12
13
|
retryAfterMs?: number;
|
|
13
14
|
errorMessage?: string;
|
|
@@ -1,14 +1,17 @@
|
|
|
1
|
+
import { MAX_SLOT_BLOCK_MS } from "@earendil-works/pi-ai/auth/pool/failover";
|
|
1
2
|
import { stripProviderRequestIds } from "@earendil-works/pi-ai/utils/retry";
|
|
3
|
+
import { usageLimitResetMs } from "../credential-pool/reset-time.js";
|
|
2
4
|
/**
|
|
3
5
|
* Runtime-only selector suppression. A SelectorCooldowns instance belongs to one
|
|
4
6
|
* AgentSession and is deliberately never persisted to settings or session files.
|
|
5
7
|
* Callers provide canonical base selectors without a thinking suffix.
|
|
6
8
|
*/
|
|
7
9
|
export class SelectorCooldowns {
|
|
8
|
-
constructor(now, random = Math.random) {
|
|
10
|
+
constructor(now, random = Math.random, wallNow = now) {
|
|
9
11
|
this.expiresAtBySelector = new Map();
|
|
10
12
|
this.now = now;
|
|
11
13
|
this.random = random;
|
|
14
|
+
this.wallNow = wallNow;
|
|
12
15
|
}
|
|
13
16
|
note(baseSelector, failure) {
|
|
14
17
|
this.expiresAtBySelector.set(baseSelector, this.now() + this.durationFor(failure));
|
|
@@ -29,18 +32,24 @@ export class SelectorCooldowns {
|
|
|
29
32
|
this.expiresAtBySelector.clear();
|
|
30
33
|
}
|
|
31
34
|
durationFor({ retryAfterMs, errorMessage }) {
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
}
|
|
35
|
+
// Reset hints are wall-clock times; the stored deadline remains monotonic.
|
|
36
|
+
const resetMs = errorMessage === undefined ? undefined : usageLimitResetMs(errorMessage, this.wallNow());
|
|
35
37
|
const message = stripProviderRequestIds(errorMessage ?? "").toLowerCase();
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
38
|
+
const defaultMs = /usage[- ]limit|quota|insufficient_quota|billing|credits[-_ ]required|credits are required/.test(message)
|
|
39
|
+
? 30 * 60_000
|
|
40
|
+
: /rate[ -]?limit|429|too many requests/.test(message)
|
|
41
|
+
? 30_000
|
|
42
|
+
: /overloaded|capacity/.test(message)
|
|
43
|
+
? 45_000 + this.capacityJitterMs()
|
|
44
|
+
: /5xx|\b5\d\d\b|server|internal error/.test(message)
|
|
45
|
+
? 20_000
|
|
46
|
+
: undefined;
|
|
47
|
+
const retryMs = retryAfterMs !== undefined && Number.isFinite(retryAfterMs) && retryAfterMs > 0 ? retryAfterMs : undefined;
|
|
48
|
+
const hintedMs = Math.max(resetMs ?? 0, retryMs ?? 0);
|
|
49
|
+
if (hintedMs > 0)
|
|
50
|
+
return Math.min(MAX_SLOT_BLOCK_MS, hintedMs);
|
|
51
|
+
if (defaultMs !== undefined)
|
|
52
|
+
return defaultMs;
|
|
44
53
|
// A reason-less forbidden rejection is a per-request blip on a healthy credential (senpi#2376).
|
|
45
54
|
if (/"type"\s*:\s*"forbidden"[^}]*request not allowed|request not allowed[^}]*"type"\s*:\s*"forbidden"/.test(message)) {
|
|
46
55
|
return 60_000;
|
|
@@ -10,9 +10,11 @@ import type { SelectorCooldowns } from "./cooldown.ts";
|
|
|
10
10
|
*/
|
|
11
11
|
export declare class UnusableEntries {
|
|
12
12
|
private readonly cooldowns;
|
|
13
|
+
private readonly accountErrors;
|
|
13
14
|
constructor(cooldowns: SelectorCooldowns);
|
|
14
15
|
note(model: Model<Api>, failure: CircuitFailure): void;
|
|
15
16
|
isProviderSpent(provider: string): boolean;
|
|
17
|
+
accountError(provider: string): string | undefined;
|
|
16
18
|
isUnusable(model: Model<Api>): boolean;
|
|
17
19
|
clear(model: Model<Api>): void;
|
|
18
20
|
}
|
|
@@ -10,12 +10,16 @@ import { usageLimitScope } from "./usage-limit.js";
|
|
|
10
10
|
*/
|
|
11
11
|
export class UnusableEntries {
|
|
12
12
|
constructor(cooldowns) {
|
|
13
|
+
this.accountErrors = new Map();
|
|
13
14
|
this.cooldowns = cooldowns;
|
|
14
15
|
}
|
|
15
16
|
note(model, failure) {
|
|
16
17
|
const scope = usageLimitScope(failure.errorMessage);
|
|
17
|
-
if (scope === "account")
|
|
18
|
+
if (scope === "account") {
|
|
18
19
|
this.cooldowns.note(accountKey(model.provider), failure);
|
|
20
|
+
if (failure.errorMessage)
|
|
21
|
+
this.accountErrors.set(model.provider, failure.errorMessage);
|
|
22
|
+
}
|
|
19
23
|
else if (scope === "model" || isHealthExhaustionFailure(failure.errorMessage)) {
|
|
20
24
|
this.cooldowns.note(entryKey(model), failure);
|
|
21
25
|
}
|
|
@@ -23,15 +27,23 @@ export class UnusableEntries {
|
|
|
23
27
|
isProviderSpent(provider) {
|
|
24
28
|
return this.cooldowns.isSuppressed(accountKey(provider));
|
|
25
29
|
}
|
|
30
|
+
accountError(provider) {
|
|
31
|
+
return this.isProviderSpent(provider) ? this.accountErrors.get(provider) : undefined;
|
|
32
|
+
}
|
|
26
33
|
isUnusable(model) {
|
|
27
34
|
return this.isProviderSpent(model.provider) || this.cooldowns.isSuppressed(entryKey(model));
|
|
28
35
|
}
|
|
29
36
|
clear(model) {
|
|
30
|
-
|
|
37
|
+
// A deliberate model selection allows the user to probe after reauth/reset.
|
|
31
38
|
this.cooldowns.clear(entryKey(model));
|
|
39
|
+
this.cooldowns.clear(accountKey(model.provider));
|
|
40
|
+
this.accountErrors.delete(model.provider);
|
|
32
41
|
}
|
|
33
42
|
}
|
|
34
43
|
function accountKey(provider) {
|
|
44
|
+
// This is a provider-name approximation, not resolved credential/account identity.
|
|
45
|
+
// Gateways with distinct model accounts share a key; pooled slots can reset earlier
|
|
46
|
+
// than the last surfaced account error. Explicit /model selection permits a probe.
|
|
35
47
|
return `account:${provider}`;
|
|
36
48
|
}
|
|
37
49
|
function entryKey(model) {
|