pi-harness-runtime 0.10.13 → 0.10.15
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/harness/notification-events.ts +2 -2
- package/package.json +4 -7
- package/packages/auth/src/minimax-browser-auth.js +889 -0
- package/packages/capability-registry/src/types.js +10 -0
- package/packages/checkpoint/src/checkpoint-manager.js +29 -0
- package/packages/clipboard/src/copy-sync.js +169 -0
- package/packages/clipboard/src/gist-relay.js +185 -0
- package/packages/clipboard/src/github-login.js +68 -0
- package/packages/config-capture/src/index.js +268 -0
- package/packages/cookie-sanitizer/src/atomic-write.js +66 -0
- package/packages/cookie-sanitizer/src/detect-format.js +87 -0
- package/packages/cookie-sanitizer/src/index.js +38 -0
- package/packages/cookie-sanitizer/src/infer-provider.js +95 -0
- package/packages/cookie-sanitizer/src/normalize.js +74 -0
- package/packages/cookie-sanitizer/src/parse-json.js +107 -0
- package/packages/cookie-sanitizer/src/parse-netscape.js +98 -0
- package/packages/cookie-sanitizer/src/sync.js +268 -0
- package/packages/cookie-sanitizer/src/types.js +12 -0
- package/packages/cookie-sanitizer/src/watcher.js +147 -0
- package/packages/evaluation-engine/src/engine.js +343 -0
- package/packages/evaluation-engine/src/index.js +7 -0
- package/packages/evaluation-engine/src/types.js +14 -0
- package/packages/event-store/src/types.js +5 -0
- package/packages/experience-replay/src/index.js +6 -0
- package/packages/experience-replay/src/replay.js +228 -0
- package/packages/experience-replay/src/types.js +6 -0
- package/packages/learning-engine/src/engine.js +294 -0
- package/packages/learning-engine/src/index.js +7 -0
- package/packages/learning-engine/src/types.js +63 -0
- package/packages/memory-engine/src/engine.js +507 -0
- package/packages/memory-engine/src/index.js +7 -0
- package/packages/memory-engine/src/types.js +39 -0
- package/packages/model-registry/src/types.js +5 -0
- package/packages/performance-optimizer/src/index.js +6 -0
- package/packages/performance-optimizer/src/optimizer.js +304 -0
- package/packages/performance-optimizer/src/types.js +6 -0
- package/packages/projection-engine/src/types.js +5 -0
- package/packages/providers/src/provider-id.js +112 -0
- package/packages/quota-manager/src/quota-manager.js +259 -0
- package/packages/quota-manager/src/tui-usage-monitor.js +267 -0
- package/packages/todo-bd-sync/src/detector.js +131 -0
- package/packages/todo-bd-sync/src/extension.js +104 -0
- package/packages/todo-bd-sync/src/sync.js +289 -0
- package/packages/todo-bd-sync/src/task-analyzer.js +239 -0
- package/packages/todo-bd-sync/src/types.js +66 -0
- package/packages/token-estimation/src/index.js +114 -0
- package/packages/types/src/agent-worker-types.js +41 -0
- package/packages/types/src/ai-providers.js +66 -0
- package/packages/types/src/runtime-types.js +3 -0
- package/packages/workflow-events/src/types.js +5 -0
- package/packages/write-review/src/blackboard.js +228 -0
- package/packages/write-review/src/gate.js +137 -0
- package/packages/write-review/src/index.js +17 -0
- package/packages/write-review/src/injection.js +141 -0
- package/packages/write-review/src/review.js +153 -0
- package/packages/write-review/src/trigger.js +106 -0
- package/packages/write-review/src/types.js +25 -0
- package/IMPLEMENTATION/RFC-0010/ACCEPTANCE_CRITERIA.md +0 -7
- package/IMPLEMENTATION/RFC-0010/AI_BRIEF.md +0 -20
- package/IMPLEMENTATION/RFC-0010/FILES.md +0 -11
- package/IMPLEMENTATION/RFC-0010/TASKS.md +0 -10
- package/IMPLEMENTATION/RFC-0010/TESTS.md +0 -6
- package/IMPLEMENTATION/RFC-0011/ACCEPTANCE_CRITERIA.md +0 -7
- package/IMPLEMENTATION/RFC-0011/AI_BRIEF.md +0 -19
- package/IMPLEMENTATION/RFC-0011/FILES.md +0 -11
- package/IMPLEMENTATION/RFC-0011/TASKS.md +0 -10
- package/IMPLEMENTATION/RFC-0011/TESTS.md +0 -6
- package/IMPLEMENTATION/RFC-0012/ACCEPTANCE_CRITERIA.md +0 -7
- package/IMPLEMENTATION/RFC-0012/AI_BRIEF.md +0 -18
- package/IMPLEMENTATION/RFC-0012/FILES.md +0 -11
- package/IMPLEMENTATION/RFC-0012/TASKS.md +0 -10
- package/IMPLEMENTATION/RFC-0012/TESTS.md +0 -6
- package/IMPLEMENTATION/RFC-0013/ACCEPTANCE_CRITERIA.md +0 -7
- package/IMPLEMENTATION/RFC-0013/AI_BRIEF.md +0 -19
- package/IMPLEMENTATION/RFC-0013/FILES.md +0 -11
- package/IMPLEMENTATION/RFC-0013/TASKS.md +0 -10
- package/IMPLEMENTATION/RFC-0013/TESTS.md +0 -6
- package/IMPLEMENTATION/RFC-0014/ACCEPTANCE_CRITERIA.md +0 -7
- package/IMPLEMENTATION/RFC-0014/AI_BRIEF.md +0 -20
- package/IMPLEMENTATION/RFC-0014/FILES.md +0 -11
- package/IMPLEMENTATION/RFC-0014/TASKS.md +0 -10
- package/IMPLEMENTATION/RFC-0014/TESTS.md +0 -6
- package/IMPLEMENTATION/RFC-0015/ACCEPTANCE_CRITERIA.md +0 -2
- package/IMPLEMENTATION/RFC-0015/AI_BRIEF.md +0 -2
- package/IMPLEMENTATION/RFC-0015/FILES.md +0 -2
- package/IMPLEMENTATION/RFC-0015/TASKS.md +0 -4
- package/IMPLEMENTATION/RFC-0015/TESTS.md +0 -3
- package/IMPLEMENTATION/RFC-0016/ACCEPTANCE_CRITERIA.md +0 -2
- package/IMPLEMENTATION/RFC-0016/AI_BRIEF.md +0 -2
- package/IMPLEMENTATION/RFC-0016/FILES.md +0 -2
- package/IMPLEMENTATION/RFC-0016/TASKS.md +0 -4
- package/IMPLEMENTATION/RFC-0016/TESTS.md +0 -3
- package/IMPLEMENTATION/RFC-0017/ACCEPTANCE_CRITERIA.md +0 -2
- package/IMPLEMENTATION/RFC-0017/AI_BRIEF.md +0 -2
- package/IMPLEMENTATION/RFC-0017/FILES.md +0 -2
- package/IMPLEMENTATION/RFC-0017/TASKS.md +0 -4
- package/IMPLEMENTATION/RFC-0017/TESTS.md +0 -3
- package/IMPLEMENTATION/RFC-0018/ACCEPTANCE_CRITERIA.md +0 -2
- package/IMPLEMENTATION/RFC-0018/AI_BRIEF.md +0 -2
- package/IMPLEMENTATION/RFC-0018/FILES.md +0 -2
- package/IMPLEMENTATION/RFC-0018/TASKS.md +0 -4
- package/IMPLEMENTATION/RFC-0018/TESTS.md +0 -3
- package/IMPLEMENTATION/RFC-0019/ACCEPTANCE_CRITERIA.md +0 -7
- package/IMPLEMENTATION/RFC-0019/AI_BRIEF.md +0 -18
- package/IMPLEMENTATION/RFC-0019/TASKS.md +0 -10
- package/IMPLEMENTATION/RFC-0020/ACCEPTANCE_CRITERIA.md +0 -7
- package/IMPLEMENTATION/RFC-0020/AI_BRIEF.md +0 -18
- package/IMPLEMENTATION/RFC-0020/TASKS.md +0 -10
- package/IMPLEMENTATION/RFC-0021/ACCEPTANCE_CRITERIA.md +0 -7
- package/IMPLEMENTATION/RFC-0021/AI_BRIEF.md +0 -18
- package/IMPLEMENTATION/RFC-0021/TASKS.md +0 -10
- package/IMPLEMENTATION/RFC-0022/ACCEPTANCE_CRITERIA.md +0 -7
- package/IMPLEMENTATION/RFC-0022/AI_BRIEF.md +0 -18
- package/IMPLEMENTATION/RFC-0022/TASKS.md +0 -10
- package/IMPLEMENTATION/RFC-0023/ACCEPTANCE_CRITERIA.md +0 -7
- package/IMPLEMENTATION/RFC-0023/AI_BRIEF.md +0 -18
- package/IMPLEMENTATION/RFC-0023/TASKS.md +0 -10
- package/IMPLEMENTATION/RFC-0024/AI_BRIEF.md +0 -1
- package/IMPLEMENTATION/RFC-0024/TASKS.md +0 -3
- package/IMPLEMENTATION/RFC-0025/AI_BRIEF.md +0 -1
- package/IMPLEMENTATION/RFC-0025/TASKS.md +0 -3
- package/IMPLEMENTATION/RFC-0026/AI_BRIEF.md +0 -1
- package/IMPLEMENTATION/RFC-0026/TASKS.md +0 -3
- package/IMPLEMENTATION/RFC-0027/AI_BRIEF.md +0 -1
- package/IMPLEMENTATION/RFC-0027/TASKS.md +0 -3
- package/IMPLEMENTATION/RFC-0028/AI_BRIEF.md +0 -1
- package/IMPLEMENTATION/RFC-0028/TASKS.md +0 -3
- package/IMPLEMENTATION/RFC-0029/AI_BRIEF.md +0 -1
- package/IMPLEMENTATION/RFC-0029/TASKS.md +0 -4
- package/IMPLEMENTATION/RFC-0030/AI_BRIEF.md +0 -1
- package/IMPLEMENTATION/RFC-0030/TASKS.md +0 -3
- package/IMPLEMENTATION/RFC-0031/AI_BRIEF.md +0 -45
- package/IMPLEMENTATION/RFC-0031/TASKS.md +0 -48
- package/IMPLEMENTATION/RFC-0032/AI_BRIEF.md +0 -45
- package/IMPLEMENTATION/RFC-0032/TASKS.md +0 -44
- package/IMPLEMENTATION/RFC-0033/AI_BRIEF.md +0 -46
- package/IMPLEMENTATION/RFC-0033/TASKS.md +0 -49
- package/IMPLEMENTATION/RFC-0034/AI_BRIEF.md +0 -54
- package/IMPLEMENTATION/RFC-0034/TASKS.md +0 -57
- package/IMPLEMENTATION/RFC-0035/AI_BRIEF.md +0 -55
- package/IMPLEMENTATION/RFC-0035/TASKS.md +0 -75
- package/IMPLEMENTATION/RFC-0036/AI_BRIEF.md +0 -62
- package/IMPLEMENTATION/RFC-0036/TASKS.md +0 -60
- package/IMPLEMENTATION/RFC-0037/AI_BRIEF.md +0 -59
- package/IMPLEMENTATION/RFC-0037/TASKS.md +0 -63
- package/IMPLEMENTATION/RFC-0038/AI_BRIEF.md +0 -67
- package/IMPLEMENTATION/RFC-0038/TASKS.md +0 -65
- package/IMPLEMENTATION/RFC-0039/AI_BRIEF.md +0 -68
- package/IMPLEMENTATION/RFC-0039/TASKS.md +0 -74
- package/IMPLEMENTATION/RFC-0040/AI_BRIEF.md +0 -79
- package/IMPLEMENTATION/RFC-0040/TASKS.md +0 -77
- package/IMPLEMENTATION/RFC-0041/ACCEPTANCE_CRITERIA.md +0 -8
- package/IMPLEMENTATION/RFC-0041/AI_BRIEF.md +0 -26
- package/IMPLEMENTATION/RFC-0041/FILES.md +0 -12
- package/IMPLEMENTATION/RFC-0041/TASKS.md +0 -12
- package/IMPLEMENTATION/RFC-0041/TESTS.md +0 -12
- package/IMPLEMENTATION/RFC-0042/ACCEPTANCE_CRITERIA.md +0 -7
- package/IMPLEMENTATION/RFC-0042/AI_BRIEF.md +0 -5
- package/IMPLEMENTATION/RFC-0042/FILES.md +0 -14
- package/IMPLEMENTATION/RFC-0042/TASKS.md +0 -12
- package/IMPLEMENTATION/RFC-0042/TESTS.md +0 -11
- package/IMPLEMENTATION/RFC-0043/ACCEPTANCE_CRITERIA.md +0 -7
- package/IMPLEMENTATION/RFC-0043/AI_BRIEF.md +0 -5
- package/IMPLEMENTATION/RFC-0043/FILES.md +0 -14
- package/IMPLEMENTATION/RFC-0043/TASKS.md +0 -12
- package/IMPLEMENTATION/RFC-0043/TESTS.md +0 -10
- package/IMPLEMENTATION/RFC-0044/ACCEPTANCE_CRITERIA.md +0 -7
- package/IMPLEMENTATION/RFC-0044/AI_BRIEF.md +0 -5
- package/IMPLEMENTATION/RFC-0044/FILES.md +0 -13
- package/IMPLEMENTATION/RFC-0044/TASKS.md +0 -12
- package/IMPLEMENTATION/RFC-0044/TESTS.md +0 -10
- package/IMPLEMENTATION/RFC-0045/ACCEPTANCE_CRITERIA.md +0 -30
- package/IMPLEMENTATION/RFC-0045/AI_BRIEF.md +0 -53
- package/IMPLEMENTATION/RFC-0045/FILES.md +0 -13
- package/IMPLEMENTATION/RFC-0045/TASKS.md +0 -31
- package/IMPLEMENTATION/RFC-0045/TESTS.md +0 -62
- package/IMPLEMENTATION/RFC-0046/ACCEPTANCE_CRITERIA.md +0 -1
- package/IMPLEMENTATION/RFC-0046/AI_BRIEF.md +0 -1
- package/IMPLEMENTATION/RFC-0046/FILES.md +0 -2
- package/IMPLEMENTATION/RFC-0046/TASKS.md +0 -3
- package/IMPLEMENTATION/RFC-0046/TESTS.md +0 -1
- package/IMPLEMENTATION/RFC-0047/ACCEPTANCE_CRITERIA.md +0 -1
- package/IMPLEMENTATION/RFC-0047/AI_BRIEF.md +0 -1
- package/IMPLEMENTATION/RFC-0047/FILES.md +0 -2
- package/IMPLEMENTATION/RFC-0047/TASKS.md +0 -3
- package/IMPLEMENTATION/RFC-0047/TESTS.md +0 -1
- package/IMPLEMENTATION/RFC-0048/ACCEPTANCE_CRITERIA.md +0 -1
- package/IMPLEMENTATION/RFC-0048/AI_BRIEF.md +0 -1
- package/IMPLEMENTATION/RFC-0048/FILES.md +0 -2
- package/IMPLEMENTATION/RFC-0048/TASKS.md +0 -3
- package/IMPLEMENTATION/RFC-0048/TESTS.md +0 -1
- package/IMPLEMENTATION/RFC-0049/ACCEPTANCE_CRITERIA.md +0 -1
- package/IMPLEMENTATION/RFC-0049/AI_BRIEF.md +0 -1
- package/IMPLEMENTATION/RFC-0049/FILES.md +0 -2
- package/IMPLEMENTATION/RFC-0049/TASKS.md +0 -3
- package/IMPLEMENTATION/RFC-0049/TESTS.md +0 -1
- package/IMPLEMENTATION/RFC-0050/ACCEPTANCE_CRITERIA.md +0 -1
- package/IMPLEMENTATION/RFC-0050/AI_BRIEF.md +0 -1
- package/IMPLEMENTATION/RFC-0050/FILES.md +0 -2
- package/IMPLEMENTATION/RFC-0050/TASKS.md +0 -3
- package/IMPLEMENTATION/RFC-0050/TESTS.md +0 -1
- package/IMPLEMENTATION/RFC-0051/ACCEPTANCE_CRITERIA.md +0 -6
- package/IMPLEMENTATION/RFC-0051/AI_BRIEF.md +0 -20
- package/IMPLEMENTATION/RFC-0051/FILES.md +0 -8
- package/IMPLEMENTATION/RFC-0051/TASKS.md +0 -3
- package/IMPLEMENTATION/RFC-0051/TESTS.md +0 -4
- package/IMPLEMENTATION/RFC-0052/ACCEPTANCE_CRITERIA.md +0 -7
- package/IMPLEMENTATION/RFC-0052/AI_BRIEF.md +0 -19
- package/IMPLEMENTATION/RFC-0052/FILES.md +0 -8
- package/IMPLEMENTATION/RFC-0052/TASKS.md +0 -3
- package/IMPLEMENTATION/RFC-0052/TESTS.md +0 -1
- package/IMPLEMENTATION/RFC-0053/ACCEPTANCE_CRITERIA.md +0 -8
- package/IMPLEMENTATION/RFC-0053/AI_BRIEF.md +0 -20
- package/IMPLEMENTATION/RFC-0053/FILES.md +0 -9
- package/IMPLEMENTATION/RFC-0053/TASKS.md +0 -3
- package/IMPLEMENTATION/RFC-0053/TESTS.md +0 -1
- package/IMPLEMENTATION/RFC-0054/ACCEPTANCE_CRITERIA.md +0 -8
- package/IMPLEMENTATION/RFC-0054/AI_BRIEF.md +0 -19
- package/IMPLEMENTATION/RFC-0054/FILES.md +0 -8
- package/IMPLEMENTATION/RFC-0054/TASKS.md +0 -3
- package/IMPLEMENTATION/RFC-0054/TESTS.md +0 -1
- package/IMPLEMENTATION/RFC-0055/ACCEPTANCE_CRITERIA.md +0 -8
- package/IMPLEMENTATION/RFC-0055/AI_BRIEF.md +0 -17
- package/IMPLEMENTATION/RFC-0055/FILES.md +0 -9
- package/IMPLEMENTATION/RFC-0055/TASKS.md +0 -3
- package/IMPLEMENTATION/RFC-0055/TESTS.md +0 -1
- package/IMPLEMENTATION/RFC-0056/ACCEPTANCE_CRITERIA.md +0 -6
- package/IMPLEMENTATION/RFC-0056/AI_BRIEF.md +0 -18
- package/IMPLEMENTATION/RFC-0056/FILES.md +0 -9
- package/IMPLEMENTATION/RFC-0056/TASKS.md +0 -9
- package/IMPLEMENTATION/RFC-0056/TESTS.md +0 -7
- package/IMPLEMENTATION/RFC-0057/ACCEPTANCE_CRITERIA.md +0 -5
- package/IMPLEMENTATION/RFC-0057/AI_BRIEF.md +0 -5
- package/IMPLEMENTATION/RFC-0057/FILES.md +0 -11
- package/IMPLEMENTATION/RFC-0057/TASKS.md +0 -9
- package/IMPLEMENTATION/RFC-0057/TESTS.md +0 -7
- package/IMPLEMENTATION/RFC-0058/ACCEPTANCE_CRITERIA.md +0 -6
- package/IMPLEMENTATION/RFC-0058/AI_BRIEF.md +0 -5
- package/IMPLEMENTATION/RFC-0058/FILES.md +0 -11
- package/IMPLEMENTATION/RFC-0058/TASKS.md +0 -9
- package/IMPLEMENTATION/RFC-0058/TESTS.md +0 -7
- package/IMPLEMENTATION/RFC-0059/ACCEPTANCE_CRITERIA.md +0 -6
- package/IMPLEMENTATION/RFC-0059/AI_BRIEF.md +0 -5
- package/IMPLEMENTATION/RFC-0059/FILES.md +0 -11
- package/IMPLEMENTATION/RFC-0059/TASKS.md +0 -9
- package/IMPLEMENTATION/RFC-0059/TESTS.md +0 -7
- package/IMPLEMENTATION/RFC-0060/ACCEPTANCE_CRITERIA.md +0 -7
- package/IMPLEMENTATION/RFC-0060/AI_BRIEF.md +0 -5
- package/IMPLEMENTATION/RFC-0060/FILES.md +0 -14
- package/IMPLEMENTATION/RFC-0060/TASKS.md +0 -12
- package/IMPLEMENTATION/RFC-0060/TESTS.md +0 -10
- package/IMPLEMENTATION/RFC-0061/ACCEPTANCE_CRITERIA.md +0 -1
- package/IMPLEMENTATION/RFC-0061/AI_BRIEF.md +0 -1
- package/IMPLEMENTATION/RFC-0061/FILES.md +0 -2
- package/IMPLEMENTATION/RFC-0061/TASKS.md +0 -4
- package/IMPLEMENTATION/RFC-0061/TESTS.md +0 -2
- package/IMPLEMENTATION/RFC-0062/ACCEPTANCE_CRITERIA.md +0 -1
- package/IMPLEMENTATION/RFC-0062/AI_BRIEF.md +0 -1
- package/IMPLEMENTATION/RFC-0062/FILES.md +0 -2
- package/IMPLEMENTATION/RFC-0062/TASKS.md +0 -4
- package/IMPLEMENTATION/RFC-0062/TESTS.md +0 -2
- package/IMPLEMENTATION/RFC-0063/ACCEPTANCE_CRITERIA.md +0 -1
- package/IMPLEMENTATION/RFC-0063/AI_BRIEF.md +0 -1
- package/IMPLEMENTATION/RFC-0063/FILES.md +0 -2
- package/IMPLEMENTATION/RFC-0063/TASKS.md +0 -4
- package/IMPLEMENTATION/RFC-0063/TESTS.md +0 -2
- package/IMPLEMENTATION/RFC-0064/ACCEPTANCE_CRITERIA.md +0 -1
- package/IMPLEMENTATION/RFC-0064/AI_BRIEF.md +0 -1
- package/IMPLEMENTATION/RFC-0064/FILES.md +0 -2
- package/IMPLEMENTATION/RFC-0064/TASKS.md +0 -4
- package/IMPLEMENTATION/RFC-0064/TESTS.md +0 -2
- package/IMPLEMENTATION/RFC-0065/ACCEPTANCE_CRITERIA.md +0 -1
- package/IMPLEMENTATION/RFC-0065/AI_BRIEF.md +0 -1
- package/IMPLEMENTATION/RFC-0065/FILES.md +0 -2
- package/IMPLEMENTATION/RFC-0065/TASKS.md +0 -4
- package/IMPLEMENTATION/RFC-0065/TESTS.md +0 -2
- package/IMPLEMENTATION/RFC-0066/ACCEPTANCE_CRITERIA.md +0 -2
- package/IMPLEMENTATION/RFC-0066/AI_BRIEF.md +0 -2
- package/IMPLEMENTATION/RFC-0066/FILES.md +0 -2
- package/IMPLEMENTATION/RFC-0066/TASKS.md +0 -4
- package/IMPLEMENTATION/RFC-0066/TESTS.md +0 -3
- package/IMPLEMENTATION/RFC-0067/ACCEPTANCE_CRITERIA.md +0 -2
- package/IMPLEMENTATION/RFC-0067/AI_BRIEF.md +0 -2
- package/IMPLEMENTATION/RFC-0067/FILES.md +0 -2
- package/IMPLEMENTATION/RFC-0067/TASKS.md +0 -4
- package/IMPLEMENTATION/RFC-0067/TESTS.md +0 -3
- package/IMPLEMENTATION/RFC-0068/ACCEPTANCE_CRITERIA.md +0 -2
- package/IMPLEMENTATION/RFC-0068/AI_BRIEF.md +0 -2
- package/IMPLEMENTATION/RFC-0068/FILES.md +0 -2
- package/IMPLEMENTATION/RFC-0068/TASKS.md +0 -4
- package/IMPLEMENTATION/RFC-0068/TESTS.md +0 -3
- package/IMPLEMENTATION/RFC-0069/ACCEPTANCE_CRITERIA.md +0 -2
- package/IMPLEMENTATION/RFC-0069/AI_BRIEF.md +0 -2
- package/IMPLEMENTATION/RFC-0069/FILES.md +0 -2
- package/IMPLEMENTATION/RFC-0069/TASKS.md +0 -4
- package/IMPLEMENTATION/RFC-0069/TESTS.md +0 -3
- package/IMPLEMENTATION/RFC-0070/ACCEPTANCE_CRITERIA.md +0 -2
- package/IMPLEMENTATION/RFC-0070/AI_BRIEF.md +0 -2
- package/IMPLEMENTATION/RFC-0070/FILES.md +0 -2
- package/IMPLEMENTATION/RFC-0070/TASKS.md +0 -4
- package/IMPLEMENTATION/RFC-0070/TESTS.md +0 -3
- package/IMPLEMENTATION/RFC-0071/ACCEPTANCE_CRITERIA.md +0 -2
- package/IMPLEMENTATION/RFC-0071/AI_BRIEF.md +0 -2
- package/IMPLEMENTATION/RFC-0071/FILES.md +0 -2
- package/IMPLEMENTATION/RFC-0071/TASKS.md +0 -4
- package/IMPLEMENTATION/RFC-0071/TESTS.md +0 -3
- package/IMPLEMENTATION/RFC-0072/ACCEPTANCE_CRITERIA.md +0 -2
- package/IMPLEMENTATION/RFC-0072/AI_BRIEF.md +0 -2
- package/IMPLEMENTATION/RFC-0072/FILES.md +0 -2
- package/IMPLEMENTATION/RFC-0072/TASKS.md +0 -4
- package/IMPLEMENTATION/RFC-0072/TESTS.md +0 -3
- package/IMPLEMENTATION/RFC-0073/ACCEPTANCE_CRITERIA.md +0 -2
- package/IMPLEMENTATION/RFC-0073/AI_BRIEF.md +0 -2
- package/IMPLEMENTATION/RFC-0073/FILES.md +0 -2
- package/IMPLEMENTATION/RFC-0073/TASKS.md +0 -4
- package/IMPLEMENTATION/RFC-0073/TESTS.md +0 -3
- package/IMPLEMENTATION/RFC-0074/ACCEPTANCE_CRITERIA.md +0 -2
- package/IMPLEMENTATION/RFC-0074/AI_BRIEF.md +0 -17
- package/IMPLEMENTATION/RFC-0074/FILES.md +0 -2
- package/IMPLEMENTATION/RFC-0074/TASKS.md +0 -4
- package/IMPLEMENTATION/RFC-0074/TESTS.md +0 -3
- package/IMPLEMENTATION/RFC-0075/ACCEPTANCE_CRITERIA.md +0 -2
- package/IMPLEMENTATION/RFC-0075/AI_BRIEF.md +0 -2
- package/IMPLEMENTATION/RFC-0075/FILES.md +0 -2
- package/IMPLEMENTATION/RFC-0075/TASKS.md +0 -4
- package/IMPLEMENTATION/RFC-0075/TESTS.md +0 -3
- package/IMPLEMENTATION/RFC-0076/ACCEPTANCE_CRITERIA.md +0 -2
- package/IMPLEMENTATION/RFC-0076/AI_BRIEF.md +0 -2
- package/IMPLEMENTATION/RFC-0076/FILES.md +0 -2
- package/IMPLEMENTATION/RFC-0076/TASKS.md +0 -4
- package/IMPLEMENTATION/RFC-0076/TESTS.md +0 -3
- package/IMPLEMENTATION/RFC-0077/ACCEPTANCE_CRITERIA.md +0 -2
- package/IMPLEMENTATION/RFC-0077/AI_BRIEF.md +0 -2
- package/IMPLEMENTATION/RFC-0077/FILES.md +0 -2
- package/IMPLEMENTATION/RFC-0077/TASKS.md +0 -4
- package/IMPLEMENTATION/RFC-0077/TESTS.md +0 -3
- package/IMPLEMENTATION/RFC-0078/ACCEPTANCE_CRITERIA.md +0 -2
- package/IMPLEMENTATION/RFC-0078/AI_BRIEF.md +0 -17
- package/IMPLEMENTATION/RFC-0078/FILES.md +0 -2
- package/IMPLEMENTATION/RFC-0078/TASKS.md +0 -4
- package/IMPLEMENTATION/RFC-0078/TESTS.md +0 -3
- package/IMPLEMENTATION/RFC-0079/ACCEPTANCE_CRITERIA.md +0 -2
- package/IMPLEMENTATION/RFC-0079/AI_BRIEF.md +0 -7
- package/IMPLEMENTATION/RFC-0079/FILES.md +0 -2
- package/IMPLEMENTATION/RFC-0079/TASKS.md +0 -4
- package/IMPLEMENTATION/RFC-0079/TESTS.md +0 -3
- package/IMPLEMENTATION/RFC-0080/ACCEPTANCE_CRITERIA.md +0 -2
- package/IMPLEMENTATION/RFC-0080/AI_BRIEF.md +0 -2
- package/IMPLEMENTATION/RFC-0080/FILES.md +0 -2
- package/IMPLEMENTATION/RFC-0080/TASKS.md +0 -4
- package/IMPLEMENTATION/RFC-0080/TESTS.md +0 -3
- package/IMPLEMENTATION/RFC-0081/ACCEPTANCE_CRITERIA.md +0 -2
- package/IMPLEMENTATION/RFC-0081/AI_BRIEF.md +0 -2
- package/IMPLEMENTATION/RFC-0081/FILES.md +0 -2
- package/IMPLEMENTATION/RFC-0081/TASKS.md +0 -4
- package/IMPLEMENTATION/RFC-0081/TESTS.md +0 -3
- package/IMPLEMENTATION/RFC-0082/ACCEPTANCE_CRITERIA.md +0 -2
- package/IMPLEMENTATION/RFC-0082/AI_BRIEF.md +0 -2
- package/IMPLEMENTATION/RFC-0082/FILES.md +0 -2
- package/IMPLEMENTATION/RFC-0082/TASKS.md +0 -4
- package/IMPLEMENTATION/RFC-0082/TESTS.md +0 -3
- package/IMPLEMENTATION/RFC-0083/ACCEPTANCE_CRITERIA.md +0 -2
- package/IMPLEMENTATION/RFC-0083/AI_BRIEF.md +0 -2
- package/IMPLEMENTATION/RFC-0083/FILES.md +0 -2
- package/IMPLEMENTATION/RFC-0083/TASKS.md +0 -4
- package/IMPLEMENTATION/RFC-0083/TESTS.md +0 -3
- package/IMPLEMENTATION/RFC-0084/ACCEPTANCE_CRITERIA.md +0 -2
- package/IMPLEMENTATION/RFC-0084/AI_BRIEF.md +0 -2
- package/IMPLEMENTATION/RFC-0084/FILES.md +0 -2
- package/IMPLEMENTATION/RFC-0084/TASKS.md +0 -4
- package/IMPLEMENTATION/RFC-0084/TESTS.md +0 -3
- package/IMPLEMENTATION/RFC-0085/ACCEPTANCE_CRITERIA.md +0 -2
- package/IMPLEMENTATION/RFC-0085/AI_BRIEF.md +0 -2
- package/IMPLEMENTATION/RFC-0085/FILES.md +0 -2
- package/IMPLEMENTATION/RFC-0085/TASKS.md +0 -4
- package/IMPLEMENTATION/RFC-0085/TESTS.md +0 -3
- package/IMPLEMENTATION/RFC-0086/ACCEPTANCE_CRITERIA.md +0 -2
- package/IMPLEMENTATION/RFC-0086/AI_BRIEF.md +0 -2
- package/IMPLEMENTATION/RFC-0086/FILES.md +0 -2
- package/IMPLEMENTATION/RFC-0086/TASKS.md +0 -4
- package/IMPLEMENTATION/RFC-0086/TESTS.md +0 -3
- package/IMPLEMENTATION/RFC-0087/ACCEPTANCE_CRITERIA.md +0 -2
- package/IMPLEMENTATION/RFC-0087/AI_BRIEF.md +0 -2
- package/IMPLEMENTATION/RFC-0087/FILES.md +0 -2
- package/IMPLEMENTATION/RFC-0087/TASKS.md +0 -4
- package/IMPLEMENTATION/RFC-0087/TESTS.md +0 -3
- package/IMPLEMENTATION/RFC-0088/ACCEPTANCE_CRITERIA.md +0 -2
- package/IMPLEMENTATION/RFC-0088/AI_BRIEF.md +0 -2
- package/IMPLEMENTATION/RFC-0088/FILES.md +0 -2
- package/IMPLEMENTATION/RFC-0088/TASKS.md +0 -4
- package/IMPLEMENTATION/RFC-0088/TESTS.md +0 -3
- package/IMPLEMENTATION/RFC-0089/ACCEPTANCE_CRITERIA.md +0 -2
- package/IMPLEMENTATION/RFC-0089/AI_BRIEF.md +0 -2
- package/IMPLEMENTATION/RFC-0089/FILES.md +0 -2
- package/IMPLEMENTATION/RFC-0089/TASKS.md +0 -4
- package/IMPLEMENTATION/RFC-0089/TESTS.md +0 -3
- package/IMPLEMENTATION/RFC-0090/ACCEPTANCE_CRITERIA.md +0 -2
- package/IMPLEMENTATION/RFC-0090/AI_BRIEF.md +0 -2
- package/IMPLEMENTATION/RFC-0090/FILES.md +0 -2
- package/IMPLEMENTATION/RFC-0090/TASKS.md +0 -4
- package/IMPLEMENTATION/RFC-0090/TESTS.md +0 -3
- package/IMPLEMENTATION/RFC-0091/ACCEPTANCE_CRITERIA.md +0 -2
- package/IMPLEMENTATION/RFC-0091/AI_BRIEF.md +0 -2
- package/IMPLEMENTATION/RFC-0091/FILES.md +0 -2
- package/IMPLEMENTATION/RFC-0091/TASKS.md +0 -4
- package/IMPLEMENTATION/RFC-0091/TESTS.md +0 -3
- package/IMPLEMENTATION/RFC-0092/ACCEPTANCE_CRITERIA.md +0 -2
- package/IMPLEMENTATION/RFC-0092/AI_BRIEF.md +0 -20
- package/IMPLEMENTATION/RFC-0092/FILES.md +0 -2
- package/IMPLEMENTATION/RFC-0092/TASKS.md +0 -4
- package/IMPLEMENTATION/RFC-0092/TESTS.md +0 -3
- package/IMPLEMENTATION/RFC-0093/ACCEPTANCE_CRITERIA.md +0 -2
- package/IMPLEMENTATION/RFC-0093/AI_BRIEF.md +0 -22
- package/IMPLEMENTATION/RFC-0093/FILES.md +0 -2
- package/IMPLEMENTATION/RFC-0093/TASKS.md +0 -4
- package/IMPLEMENTATION/RFC-0093/TESTS.md +0 -3
- package/IMPLEMENTATION/RFC-0094/ACCEPTANCE_CRITERIA.md +0 -2
- package/IMPLEMENTATION/RFC-0094/AI_BRIEF.md +0 -2
- package/IMPLEMENTATION/RFC-0094/FILES.md +0 -2
- package/IMPLEMENTATION/RFC-0094/TASKS.md +0 -4
- package/IMPLEMENTATION/RFC-0094/TESTS.md +0 -3
- package/IMPLEMENTATION/RFC-0095/ACCEPTANCE_CRITERIA.md +0 -2
- package/IMPLEMENTATION/RFC-0095/AI_BRIEF.md +0 -2
- package/IMPLEMENTATION/RFC-0095/FILES.md +0 -2
- package/IMPLEMENTATION/RFC-0095/TASKS.md +0 -4
- package/IMPLEMENTATION/RFC-0095/TESTS.md +0 -3
- package/IMPLEMENTATION/RFC-0096/ACCEPTANCE_CRITERIA.md +0 -2
- package/IMPLEMENTATION/RFC-0096/AI_BRIEF.md +0 -2
- package/IMPLEMENTATION/RFC-0096/FILES.md +0 -2
- package/IMPLEMENTATION/RFC-0096/TASKS.md +0 -4
- package/IMPLEMENTATION/RFC-0096/TESTS.md +0 -3
- package/IMPLEMENTATION/RFC-0097/ACCEPTANCE_CRITERIA.md +0 -2
- package/IMPLEMENTATION/RFC-0097/AI_BRIEF.md +0 -2
- package/IMPLEMENTATION/RFC-0097/FILES.md +0 -2
- package/IMPLEMENTATION/RFC-0097/TASKS.md +0 -4
- package/IMPLEMENTATION/RFC-0097/TESTS.md +0 -3
- package/IMPLEMENTATION/RFC-0098/ACCEPTANCE_CRITERIA.md +0 -2
- package/IMPLEMENTATION/RFC-0098/AI_BRIEF.md +0 -2
- package/IMPLEMENTATION/RFC-0098/FILES.md +0 -2
- package/IMPLEMENTATION/RFC-0098/TASKS.md +0 -4
- package/IMPLEMENTATION/RFC-0098/TESTS.md +0 -3
- package/IMPLEMENTATION/RFC-0099/ACCEPTANCE_CRITERIA.md +0 -2
- package/IMPLEMENTATION/RFC-0099/AI_BRIEF.md +0 -2
- package/IMPLEMENTATION/RFC-0099/FILES.md +0 -2
- package/IMPLEMENTATION/RFC-0099/TASKS.md +0 -4
- package/IMPLEMENTATION/RFC-0099/TESTS.md +0 -3
- package/IMPLEMENTATION/RFC-0100/ACCEPTANCE_CRITERIA.md +0 -2
- package/IMPLEMENTATION/RFC-0100/AI_BRIEF.md +0 -2
- package/IMPLEMENTATION/RFC-0100/FILES.md +0 -2
- package/IMPLEMENTATION/RFC-0100/TASKS.md +0 -4
- package/IMPLEMENTATION/RFC-0100/TESTS.md +0 -3
- package/IMPLEMENTATION/RFC-0101/ACCEPTANCE_CRITERIA.md +0 -74
- package/IMPLEMENTATION/RFC-0101/AI_BRIEF.md +0 -80
- package/IMPLEMENTATION/RFC-0101/FILES.md +0 -82
- package/IMPLEMENTATION/RFC-0101/TASKS.md +0 -92
- package/IMPLEMENTATION/RFC-0101/TESTS.md +0 -127
- package/IMPLEMENTATION/RFC-0102/ACCEPTANCE_CRITERIA.md +0 -33
- package/IMPLEMENTATION/RFC-0102/AI_BRIEF.md +0 -34
- package/IMPLEMENTATION/RFC-0102/FILES.md +0 -73
- package/IMPLEMENTATION/RFC-0102/TASKS.md +0 -75
- package/IMPLEMENTATION/RFC-0102/TESTS.md +0 -78
- package/IMPLEMENTATION/RFC-0103/ACCEPTANCE_CRITERIA.md +0 -45
- package/IMPLEMENTATION/RFC-0103/AI_BRIEF.md +0 -46
- package/IMPLEMENTATION/RFC-0103/FILES.md +0 -121
- package/IMPLEMENTATION/RFC-0103/TASKS.md +0 -97
- package/IMPLEMENTATION/RFC-0103/TESTS.md +0 -118
- package/IMPLEMENTATION/RFC-0104/ACCEPTANCE_CRITERIA.md +0 -29
- package/IMPLEMENTATION/RFC-0104/FILES.md +0 -33
- package/IMPLEMENTATION/RFC-0105/ACCEPTANCE_CRITERIA.md +0 -29
- package/IMPLEMENTATION/RFC-0105/FILES.md +0 -41
- package/IMPLEMENTATION/RFC-0106/ACCEPTANCE_CRITERIA.md +0 -29
- package/IMPLEMENTATION/RFC-0106/FILES.md +0 -43
- package/RFC/0001_LOOP_RUNTIME.md +0 -14
- package/RFC/0002_PROVIDER_ADAPTER.md +0 -3
- package/RFC/0003_QUOTA_MANAGER.md +0 -3
- package/RFC/0004_PLAYWRIGHT_ADAPTER.md +0 -3
- package/RFC/0005_GIT_WORKTREE.md +0 -3
- package/RFC/0006_CHECKPOINT_MANAGER.md +0 -56
- package/RFC/0007_SCHEDULER.md +0 -32
- package/RFC/0008_PROVIDER_ROUTER.md +0 -44
- package/RFC/0009_SHARED_CONTEXT.md +0 -32
- package/RFC/0010_CONTEXT_WINDOW_MANAGER.md +0 -50
- package/RFC/0011_SHARED_BLACKBOARD.md +0 -42
- package/RFC/0012_AGENT_HANDOFF_PROTOCOL.md +0 -41
- package/RFC/0013_E2E_TEST_ENGINE.md +0 -42
- package/RFC/0014_PROJECT_DETECTOR_AND_TEST_DATA_ENGINE.md +0 -35
- package/RFC/0015_JOB_STATE_MACHINE.md +0 -45
- package/RFC/0016_TASK_GRAPH.md +0 -31
- package/RFC/0017_MASTER_PLANNER.md +0 -32
- package/RFC/0018_REPAIR_ENGINE.md +0 -36
- package/RFC/0019_AUTO_COMPACT_AND_CONTINUE.md +0 -51
- package/RFC/0020_OUTPUT_TOKEN_LIMIT_HANDLER.md +0 -49
- package/RFC/0021_PARTIAL_RESPONSE_RECOVERY.md +0 -49
- package/RFC/0022_NOTIFICATION_CENTER.md +0 -47
- package/RFC/0023_LOCAL_BROWSER_AGENT.md +0 -67
- package/RFC/0024_LOCAL_RUNTIME_AGENT.md +0 -3
- package/RFC/0025_COMMAND_EXECUTOR.md +0 -3
- package/RFC/0026_WORKSPACE_MANAGER.md +0 -3
- package/RFC/0027_RUNTIME_API.md +0 -3
- package/RFC/0028_POLICY_ENGINE.md +0 -3
- package/RFC/0029_DEEPAGENTS_ADAPTER.md +0 -2
- package/RFC/0030_AGENT_WORKER_INTERFACE.md +0 -2
- package/RFC/0031_PROVIDER_ADAPTER_SDK.md +0 -171
- package/RFC/0032_CHECKPOINT_ENGINE.md +0 -217
- package/RFC/0033_SESSION_MANAGER.md +0 -262
- package/RFC/0034_OBSERVABILITY.md +0 -416
- package/RFC/0035_ROADMAP_V1.md +0 -295
- package/RFC/0036_CODE_REVIEW_ENGINE.md +0 -430
- package/RFC/0037_CODE_GENERATION_PIPELINE.md +0 -504
- package/RFC/0038_FRAMEWORK_DETECTOR.md +0 -466
- package/RFC/0039_TEST_DATA_GENERATOR.md +0 -504
- package/RFC/0040_FRAMEWORK_PLUGIN_SDK.md +0 -543
- package/RFC/0041_PROMPT_COMPILER.md +0 -232
- package/RFC/0042_CONTEXT_COMPILER.md +0 -216
- package/RFC/0043_REQUIREMENT_COMPILER.md +0 -211
- package/RFC/0044_TASK_COMPILER.md +0 -207
- package/RFC/0045_PROJECT_ANALYZER.md +0 -246
- package/RFC/0046_DEPENDENCY_ANALYZER.md +0 -14
- package/RFC/0047_REPOSITORY_KNOWLEDGE_GRAPH.md +0 -14
- package/RFC/0048_CODE_MERGE_ENGINE.md +0 -14
- package/RFC/0049_CONFLICT_RESOLUTION_ENGINE.md +0 -14
- package/RFC/0050_DOCUMENTATION_GENERATOR.md +0 -14
- package/RFC/0051_CAPABILITY_REGISTRY.md +0 -144
- package/RFC/0052_SKILL_REGISTRY.md +0 -167
- package/RFC/0053_MODEL_REGISTRY.md +0 -214
- package/RFC/0054_PROVIDER_ROUTER.md +0 -239
- package/RFC/0055_COST_OPTIMIZER.md +0 -285
- package/RFC/0056_PERFORMANCE_OPTIMIZER.md +0 -118
- package/RFC/0057_EVALUATION_ENGINE.md +0 -116
- package/RFC/0058_LEARNING_ENGINE.md +0 -113
- package/RFC/0059_EXPERIENCE_REPLAY.md +0 -107
- package/RFC/0060_MEMORY_ENGINE_OKF.md +0 -152
- package/RFC/0061_FRAPPE_PLUGIN.md +0 -9
- package/RFC/0062_NEXTJS_PLUGIN.md +0 -9
- package/RFC/0063_REACT_VITE_PLUGIN.md +0 -9
- package/RFC/0064_DJANGO_PLUGIN.md +0 -9
- package/RFC/0065_LARAVEL_PLUGIN.md +0 -9
- package/RFC/0066_GENERIC_WEB_PLUGIN.md +0 -24
- package/RFC/0067_CLI_PLUGIN_SDK.md +0 -101
- package/RFC/0068_MCP_ADAPTER.md +0 -114
- package/RFC/0069_GOOGLE_A2A_ADAPTER.md +0 -139
- package/RFC/0070_OPENAI_CODEX_ADAPTER.md +0 -134
- package/RFC/0071_REQUIREMENT_INTAKE.md +0 -95
- package/RFC/0072_PROJECT_BOOTSTRAP.md +0 -82
- package/RFC/0073_ARCHITECTURE_GENERATOR.md +0 -85
- package/RFC/0074_SPRINT_PLANNER.md +0 -61
- package/RFC/0075_MILESTONE_MANAGER.md +0 -58
- package/RFC/0076_BACKLOG_MANAGER.md +0 -24
- package/RFC/0077_HUMAN_APPROVAL_GATE.md +0 -24
- package/RFC/0078_RELEASE_MANAGER.md +0 -24
- package/RFC/0079_VERSION_MANAGER.md +0 -24
- package/RFC/0080_DEPLOYMENT_PIPELINE.md +0 -24
- package/RFC/0081_MULTI_USER_RUNTIME.md +0 -24
- package/RFC/0082_RBAC.md +0 -24
- package/RFC/0083_AUDIT_TRAIL.md +0 -24
- package/RFC/0084_DASHBOARD.md +0 -24
- package/RFC/0085_ANALYTICS.md +0 -24
- package/RFC/0086_DISTRIBUTED_RUNTIME.md +0 -24
- package/RFC/0087_CLUSTER_MANAGER.md +0 -24
- package/RFC/0088_RUNTIME_FEDERATION.md +0 -24
- package/RFC/0089_HIGH_AVAILABILITY.md +0 -24
- package/RFC/0090_DISASTER_RECOVERY.md +0 -24
- package/RFC/0091_AUTONOMOUS_ARCHITECTURE_REVIEW.md +0 -24
- package/RFC/0092_AUTONOMOUS_REFACTORING.md +0 -24
- package/RFC/0093_AUTONOMOUS_BUG_FIXING.md +0 -24
- package/RFC/0094_AUTONOMOUS_PERFORMANCE_TUNING.md +0 -24
- package/RFC/0095_AUTONOMOUS_SECURITY_REVIEW.md +0 -24
- package/RFC/0096_AUTONOMOUS_COST_OPTIMIZATION.md +0 -24
- package/RFC/0097_AUTONOMOUS_DOCUMENTATION.md +0 -24
- package/RFC/0098_AUTONOMOUS_KNOWLEDGE_MANAGEMENT.md +0 -24
- package/RFC/0099_RUNTIME_EVOLUTION_ENGINE.md +0 -24
- package/RFC/0100_SELF_DEVELOPING_RUNTIME.md +0 -24
- package/RFC/0101_AUTONOMOUS_OPERATIONS_RUNTIME.md +0 -1105
- package/RFC/0102_CONTEXT_ENGINEERING_PIPELINE.md +0 -508
- package/RFC/0103_SESSION_EVENT_RUNTIME_AGENT_COMMUNICATION_LAYER.md +0 -616
- package/RFC/0104_DISTRIBUTED_AGENT_COMMUNICATION.md +0 -143
- package/RFC/0105_DISTRIBUTED_KNOWLEDGE_RETRIEVAL.md +0 -301
- package/RFC/0106_KNOWLEDGE_GRAPH_PROVENANCE.md +0 -368
- package/RFC/README.md +0 -11
- package/packages/event-bus/dist/tsconfig.tsbuildinfo +0 -1
- package/packages/provider-adapter-sdk/dist/tsconfig.tsbuildinfo +0 -1
|
@@ -0,0 +1,304 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Performance Optimizer (RFC-0056)
|
|
3
|
+
*
|
|
4
|
+
* Analyzes runtime metrics and produces advisory optimization decisions.
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Detect bottlenecks from metrics
|
|
8
|
+
*/
|
|
9
|
+
function detectBottlenecks(metrics) {
|
|
10
|
+
const bottlenecks = [];
|
|
11
|
+
const { currentContextTokens, contextWindow, retryCount, successCount, failureCount, } = metrics;
|
|
12
|
+
// Context usage bottleneck
|
|
13
|
+
const contextUsagePercent = (currentContextTokens / contextWindow) * 100;
|
|
14
|
+
if (contextUsagePercent > 80) {
|
|
15
|
+
bottlenecks.push("high_context_usage");
|
|
16
|
+
}
|
|
17
|
+
// Retry bottleneck
|
|
18
|
+
const totalCalls = successCount + failureCount;
|
|
19
|
+
if (totalCalls > 0 && retryCount / totalCalls > 0.3) {
|
|
20
|
+
bottlenecks.push("high_retry_rate");
|
|
21
|
+
}
|
|
22
|
+
// Provider performance
|
|
23
|
+
const avgLatency = metrics.avgLatencyMs;
|
|
24
|
+
if (avgLatency > 30000) {
|
|
25
|
+
bottlenecks.push("high_latency");
|
|
26
|
+
}
|
|
27
|
+
return bottlenecks;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Normalize provider metrics
|
|
31
|
+
*/
|
|
32
|
+
function normalizeProviderStats(providerMetrics) {
|
|
33
|
+
const normalized = {};
|
|
34
|
+
for (const [providerId, stats] of Object.entries(providerMetrics)) {
|
|
35
|
+
const total = stats.callCount;
|
|
36
|
+
if (total > 0) {
|
|
37
|
+
normalized[providerId] = {
|
|
38
|
+
successRate: stats.successCount / total,
|
|
39
|
+
failureRate: stats.failureCount / total,
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
return normalized;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Generate context reduction recommendation
|
|
47
|
+
*/
|
|
48
|
+
function suggestContextReduction(metrics, policy) {
|
|
49
|
+
const { currentContextTokens, contextWindow } = metrics;
|
|
50
|
+
const usagePercent = (currentContextTokens / contextWindow) * 100;
|
|
51
|
+
if (usagePercent < 50) {
|
|
52
|
+
return null; // No reduction needed
|
|
53
|
+
}
|
|
54
|
+
// Calculate target (reduce to 60% of current)
|
|
55
|
+
const targetTokens = Math.floor(currentContextTokens * 0.6);
|
|
56
|
+
const reductionPercent = ((currentContextTokens - targetTokens) / currentContextTokens) * 100;
|
|
57
|
+
if (reductionPercent < policy.minContextReductionPercent) {
|
|
58
|
+
return null;
|
|
59
|
+
}
|
|
60
|
+
return {
|
|
61
|
+
type: "reduce_context",
|
|
62
|
+
targetTokens,
|
|
63
|
+
reason: `Context usage at ${usagePercent.toFixed(1)}% (${currentContextTokens}/${contextWindow} tokens). Reduce to ~60% to improve performance.`,
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Generate provider change recommendation
|
|
68
|
+
*/
|
|
69
|
+
function suggestProviderChange(metrics, providerStates, policy) {
|
|
70
|
+
if (!policy.allowProviderSwitch) {
|
|
71
|
+
return null;
|
|
72
|
+
}
|
|
73
|
+
const providerStats = normalizeProviderStats(metrics.providerMetrics);
|
|
74
|
+
// Find worst performing provider
|
|
75
|
+
let worstProvider = null;
|
|
76
|
+
let worstFailureRate = 0;
|
|
77
|
+
for (const [providerId, stats] of Object.entries(providerStats)) {
|
|
78
|
+
if (stats.failureRate > worstFailureRate && stats.failureRate > 0.1) {
|
|
79
|
+
worstProvider = providerId;
|
|
80
|
+
worstFailureRate = stats.failureRate;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
if (!worstProvider) {
|
|
84
|
+
return null;
|
|
85
|
+
}
|
|
86
|
+
// Check if there's a better available provider
|
|
87
|
+
const availableProviders = providerStates.filter((p) => p.state === "available" && p.providerId !== worstProvider);
|
|
88
|
+
if (availableProviders.length === 0) {
|
|
89
|
+
return null; // No alternative available
|
|
90
|
+
}
|
|
91
|
+
return {
|
|
92
|
+
type: "change_provider",
|
|
93
|
+
provider: availableProviders[0].providerId,
|
|
94
|
+
reason: `Provider '${worstProvider}' has ${(worstFailureRate * 100).toFixed(1)}% failure rate. Switch to '${availableProviders[0].providerId}' for better reliability.`,
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Generate parallelism recommendations
|
|
99
|
+
*/
|
|
100
|
+
function suggestParallelismChanges(metrics, providerStates, policy, taskGraph) {
|
|
101
|
+
const recommendations = [];
|
|
102
|
+
// Check for blocked tasks that could be parallel
|
|
103
|
+
if (taskGraph) {
|
|
104
|
+
const runningTasks = taskGraph.nodes.filter((n) => n.status === "running");
|
|
105
|
+
const readyTasks = taskGraph.nodes.filter((n) => n.status === "ready");
|
|
106
|
+
// If we have many ready tasks and few running, suggest increasing parallelism
|
|
107
|
+
if (readyTasks.length > 5 && runningTasks.length < 3) {
|
|
108
|
+
const suggestedLimit = Math.min(runningTasks.length + 2, policy.maxParallelism);
|
|
109
|
+
if (suggestedLimit > runningTasks.length) {
|
|
110
|
+
recommendations.push({
|
|
111
|
+
type: "increase_parallelism",
|
|
112
|
+
limit: suggestedLimit,
|
|
113
|
+
reason: `${readyTasks.length} tasks waiting. Increase parallelism to ${suggestedLimit} for faster completion.`,
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
// If too many tasks are hitting resource limits, suggest decreasing
|
|
118
|
+
const limitedProviders = providerStates.filter((p) => p.state === "limited");
|
|
119
|
+
if (limitedProviders.length > 0 && runningTasks.length > 5) {
|
|
120
|
+
recommendations.push({
|
|
121
|
+
type: "decrease_parallelism",
|
|
122
|
+
limit: Math.max(2, runningTasks.length - 2),
|
|
123
|
+
reason: `Provider quota limited. Reduce parallelism to ${Math.max(2, runningTasks.length - 2)} to avoid quota exhaustion.`,
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
return recommendations;
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Resolve conflicting recommendations
|
|
131
|
+
*/
|
|
132
|
+
function resolveConflicts(recommendations, policy) {
|
|
133
|
+
// Sort by type priority (reductions first, then parallelism, then provider)
|
|
134
|
+
const priority = {
|
|
135
|
+
reduce_context: 1,
|
|
136
|
+
decrease_parallelism: 2,
|
|
137
|
+
increase_parallelism: 3,
|
|
138
|
+
change_provider: 4,
|
|
139
|
+
reuse_checkpoint: 5,
|
|
140
|
+
skip_redundant_step: 6,
|
|
141
|
+
};
|
|
142
|
+
// Remove duplicates and conflicting recommendations
|
|
143
|
+
const seen = new Set();
|
|
144
|
+
const resolved = [];
|
|
145
|
+
for (const rec of recommendations.sort((a, b) => priority[a.type] - priority[b.type])) {
|
|
146
|
+
const key = rec.type;
|
|
147
|
+
// Check for conflicts
|
|
148
|
+
if (key === "increase_parallelism" &&
|
|
149
|
+
resolved.some((r) => r.type === "decrease_parallelism")) {
|
|
150
|
+
continue; // Skip increase if decrease already added
|
|
151
|
+
}
|
|
152
|
+
if (key === "decrease_parallelism" &&
|
|
153
|
+
resolved.some((r) => r.type === "increase_parallelism")) {
|
|
154
|
+
// Remove increase and add decrease
|
|
155
|
+
const idx = resolved.findIndex((r) => r.type === "increase_parallelism");
|
|
156
|
+
if (idx !== -1)
|
|
157
|
+
resolved.splice(idx, 1);
|
|
158
|
+
}
|
|
159
|
+
if (!seen.has(key)) {
|
|
160
|
+
seen.add(key);
|
|
161
|
+
resolved.push(rec);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
return resolved;
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Calculate expected impact
|
|
168
|
+
*/
|
|
169
|
+
function calculateImpact(metrics, recommendations) {
|
|
170
|
+
let tokenReduction = 0;
|
|
171
|
+
let latencyReduction = 0;
|
|
172
|
+
let retryReduction = 0;
|
|
173
|
+
for (const rec of recommendations) {
|
|
174
|
+
switch (rec.type) {
|
|
175
|
+
case "reduce_context":
|
|
176
|
+
// Estimate 15-30% latency improvement from context reduction
|
|
177
|
+
latencyReduction += 20;
|
|
178
|
+
break;
|
|
179
|
+
case "change_provider":
|
|
180
|
+
// Estimate 10-25% latency improvement from better provider
|
|
181
|
+
latencyReduction += 15;
|
|
182
|
+
break;
|
|
183
|
+
case "decrease_parallelism":
|
|
184
|
+
// Reduce contention
|
|
185
|
+
latencyReduction += 10;
|
|
186
|
+
retryReduction += 15;
|
|
187
|
+
break;
|
|
188
|
+
case "skip_redundant_step":
|
|
189
|
+
tokenReduction += 10;
|
|
190
|
+
break;
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
return {
|
|
194
|
+
tokenReductionPercent: tokenReduction > 0 ? Math.min(tokenReduction, 50) : undefined,
|
|
195
|
+
latencyReductionPercent: latencyReduction > 0 ? Math.min(latencyReduction, 40) : undefined,
|
|
196
|
+
retryReductionPercent: retryReduction > 0 ? Math.min(retryReduction, 30) : undefined,
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
export class PerformanceOptimizer {
|
|
200
|
+
policy;
|
|
201
|
+
constructor(policy = {}) {
|
|
202
|
+
this.policy = {
|
|
203
|
+
minContextReductionPercent: 10,
|
|
204
|
+
maxParallelism: 10,
|
|
205
|
+
minImprovementPercent: 5,
|
|
206
|
+
allowProviderSwitch: true,
|
|
207
|
+
mandatoryStages: [],
|
|
208
|
+
...policy,
|
|
209
|
+
};
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* Analyze metrics and produce optimization recommendations
|
|
213
|
+
*/
|
|
214
|
+
analyze(request) {
|
|
215
|
+
const { jobId, metrics, providerStates } = request;
|
|
216
|
+
// Emit start event
|
|
217
|
+
this.emit({ type: "performance.analysis.started", jobId });
|
|
218
|
+
try {
|
|
219
|
+
// 1. Detect bottlenecks
|
|
220
|
+
const bottlenecks = detectBottlenecks(metrics);
|
|
221
|
+
// 2. Generate recommendations
|
|
222
|
+
const recommendations = [];
|
|
223
|
+
// Context reduction
|
|
224
|
+
const contextRec = suggestContextReduction(metrics, this.policy);
|
|
225
|
+
if (contextRec) {
|
|
226
|
+
recommendations.push(contextRec);
|
|
227
|
+
this.emit({
|
|
228
|
+
type: "performance.recommendation.created",
|
|
229
|
+
jobId,
|
|
230
|
+
recommendation: contextRec,
|
|
231
|
+
});
|
|
232
|
+
}
|
|
233
|
+
// Provider change
|
|
234
|
+
const providerRec = suggestProviderChange(metrics, providerStates, this.policy);
|
|
235
|
+
if (providerRec) {
|
|
236
|
+
recommendations.push(providerRec);
|
|
237
|
+
this.emit({
|
|
238
|
+
type: "performance.recommendation.created",
|
|
239
|
+
jobId,
|
|
240
|
+
recommendation: providerRec,
|
|
241
|
+
});
|
|
242
|
+
}
|
|
243
|
+
// Parallelism changes
|
|
244
|
+
const parallelismRecs = suggestParallelismChanges(metrics, providerStates, this.policy, request.taskGraph);
|
|
245
|
+
for (const rec of parallelismRecs) {
|
|
246
|
+
recommendations.push(rec);
|
|
247
|
+
this.emit({
|
|
248
|
+
type: "performance.recommendation.created",
|
|
249
|
+
jobId,
|
|
250
|
+
recommendation: rec,
|
|
251
|
+
});
|
|
252
|
+
}
|
|
253
|
+
// 3. Resolve conflicts
|
|
254
|
+
const resolved = resolveConflicts(recommendations, this.policy);
|
|
255
|
+
// 4. Calculate impact
|
|
256
|
+
const expectedImpact = calculateImpact(metrics, resolved);
|
|
257
|
+
this.emit({ type: "performance.analysis.completed", jobId });
|
|
258
|
+
return {
|
|
259
|
+
jobId,
|
|
260
|
+
recommendations: resolved,
|
|
261
|
+
expectedImpact,
|
|
262
|
+
generatedAt: new Date().toISOString(),
|
|
263
|
+
};
|
|
264
|
+
}
|
|
265
|
+
catch (error) {
|
|
266
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
267
|
+
this.emit({
|
|
268
|
+
type: "performance.analysis.failed",
|
|
269
|
+
jobId,
|
|
270
|
+
error: errorMessage,
|
|
271
|
+
});
|
|
272
|
+
return {
|
|
273
|
+
jobId,
|
|
274
|
+
recommendations: [],
|
|
275
|
+
expectedImpact: {},
|
|
276
|
+
generatedAt: new Date().toISOString(),
|
|
277
|
+
};
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
eventListeners = [];
|
|
281
|
+
/**
|
|
282
|
+
* Subscribe to optimizer events
|
|
283
|
+
*/
|
|
284
|
+
onEvent(listener) {
|
|
285
|
+
this.eventListeners.push(listener);
|
|
286
|
+
return () => {
|
|
287
|
+
this.eventListeners = this.eventListeners.filter((l) => l !== listener);
|
|
288
|
+
};
|
|
289
|
+
}
|
|
290
|
+
emit(event) {
|
|
291
|
+
for (const listener of this.eventListeners) {
|
|
292
|
+
try {
|
|
293
|
+
listener(event);
|
|
294
|
+
}
|
|
295
|
+
catch {
|
|
296
|
+
// Best effort
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
// --- Factory ---------------------------------------------------------------
|
|
302
|
+
export function createPerformanceOptimizer(policy) {
|
|
303
|
+
return new PerformanceOptimizer(policy);
|
|
304
|
+
}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Provider ID — single source of truth for "which provider does this model id belong to".
|
|
3
|
+
*
|
|
4
|
+
* Used by:
|
|
5
|
+
* - `index.ts` to gate fetcher calls (replaces the old `isMiniMaxModel` check)
|
|
6
|
+
* - `mirror.ts` to key per-provider records
|
|
7
|
+
* - the footer renderer to label lines correctly
|
|
8
|
+
* - the cookie sanitizer and quota manager
|
|
9
|
+
*
|
|
10
|
+
* Provider boundaries (model-id prefix → provider id):
|
|
11
|
+
*
|
|
12
|
+
* | Model id prefix | Provider | Notes |
|
|
13
|
+
* |-----------------|----------------|--------------------------------------|
|
|
14
|
+
* | `minimax/` | minimax | Playwright scrape path |
|
|
15
|
+
* | `openai/` | openai | TUI signal path |
|
|
16
|
+
* | `openai-codex/` | openai-codex | OAuth (different auth shape) |
|
|
17
|
+
* | `zai/` | glm | Z.ai / Zhipu |
|
|
18
|
+
* | `zhipu/` | glm | alt alias |
|
|
19
|
+
* | `anthropic/` | anthropic | TUI signal path |
|
|
20
|
+
* | `openrouter/` | openrouter | TUI signal path |
|
|
21
|
+
* | other | null | unknown — caller decides default |
|
|
22
|
+
*
|
|
23
|
+
* Match is case-insensitive on the prefix portion.
|
|
24
|
+
*
|
|
25
|
+
* The set is intentionally small and explicit. To add a provider: add
|
|
26
|
+
* a row to MODEL_PREFIXES and to the sanitization doc in
|
|
27
|
+
* wiki/bugs/multi-provider-usage-status.md.
|
|
28
|
+
*/
|
|
29
|
+
/** True if the given string is a known, canonical provider id. */
|
|
30
|
+
export function isKnownAiProvider(value) {
|
|
31
|
+
return (value === "minimax" ||
|
|
32
|
+
value === "openai" ||
|
|
33
|
+
value === "openai-codex" ||
|
|
34
|
+
value === "glm" ||
|
|
35
|
+
value === "anthropic" ||
|
|
36
|
+
value === "openrouter");
|
|
37
|
+
}
|
|
38
|
+
const MODEL_PREFIXES = [
|
|
39
|
+
{ prefix: "minimax/", provider: "minimax" },
|
|
40
|
+
{ prefix: "openai-codex/", provider: "openai-codex" },
|
|
41
|
+
{ prefix: "openai/", provider: "openai" },
|
|
42
|
+
{ prefix: "anthropic/", provider: "anthropic" },
|
|
43
|
+
{ prefix: "openrouter/", provider: "openrouter" },
|
|
44
|
+
{ prefix: "zai/", provider: "glm" },
|
|
45
|
+
{ prefix: "zhipu/", provider: "glm" },
|
|
46
|
+
];
|
|
47
|
+
/** Return the provider id for a model id, or null if unknown. */
|
|
48
|
+
export function providerFromModelId(modelId) {
|
|
49
|
+
if (!modelId || typeof modelId !== "string")
|
|
50
|
+
return null;
|
|
51
|
+
const lower = modelId.toLowerCase();
|
|
52
|
+
for (const { prefix, provider } of MODEL_PREFIXES) {
|
|
53
|
+
if (lower.startsWith(prefix))
|
|
54
|
+
return provider;
|
|
55
|
+
}
|
|
56
|
+
// Some model ids may be just the provider name (no `/` separator) —
|
|
57
|
+
// common when the user picks via a friendly picker.
|
|
58
|
+
if (lower.startsWith("minimax"))
|
|
59
|
+
return "minimax";
|
|
60
|
+
if (lower.startsWith("openai-codex"))
|
|
61
|
+
return "openai-codex";
|
|
62
|
+
if (lower.startsWith("openai"))
|
|
63
|
+
return "openai";
|
|
64
|
+
if (lower.startsWith("anthropic") || lower.startsWith("claude"))
|
|
65
|
+
return "anthropic";
|
|
66
|
+
if (lower.startsWith("openrouter"))
|
|
67
|
+
return "openrouter";
|
|
68
|
+
if (lower.startsWith("zai") ||
|
|
69
|
+
lower.startsWith("zhipu") ||
|
|
70
|
+
lower.startsWith("glm"))
|
|
71
|
+
return "glm";
|
|
72
|
+
// Fallback for bare model names (no provider prefix)
|
|
73
|
+
if (lower.startsWith("gpt"))
|
|
74
|
+
return "openai"; // e.g., "gpt-5.4" → openai
|
|
75
|
+
return null;
|
|
76
|
+
}
|
|
77
|
+
/** Display name for the provider (used in the footer label). */
|
|
78
|
+
export function providerDisplayName(provider) {
|
|
79
|
+
switch (provider) {
|
|
80
|
+
case "minimax":
|
|
81
|
+
return "MiniMax";
|
|
82
|
+
case "openai":
|
|
83
|
+
return "OpenAI";
|
|
84
|
+
case "openai-codex":
|
|
85
|
+
return "OpenAI Codex";
|
|
86
|
+
case "glm":
|
|
87
|
+
return "GLM";
|
|
88
|
+
case "anthropic":
|
|
89
|
+
return "Anthropic";
|
|
90
|
+
case "openrouter":
|
|
91
|
+
return "OpenRouter";
|
|
92
|
+
default:
|
|
93
|
+
return provider;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
/** True if this provider has a continuous scrape path today (only MiniMax). */
|
|
97
|
+
/**
|
|
98
|
+
* Providers with continuous quota scraping via browser/API.
|
|
99
|
+
* - minimax: has both 5h and weekly windows
|
|
100
|
+
* - openai: has weekly-only window (no 5h limit since 2026)
|
|
101
|
+
*/
|
|
102
|
+
export function providerHasContinuousScrape(provider) {
|
|
103
|
+
return provider === "minimax" || provider === "openai";
|
|
104
|
+
}
|
|
105
|
+
/** True if this provider has a TUI-driven signal path today. */
|
|
106
|
+
export function providerHasTUISignal(provider) {
|
|
107
|
+
return (provider === "openai" ||
|
|
108
|
+
provider === "openai-codex" ||
|
|
109
|
+
provider === "glm" ||
|
|
110
|
+
provider === "anthropic" ||
|
|
111
|
+
provider === "openrouter");
|
|
112
|
+
}
|
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Quota Manager — RFC-0003
|
|
3
|
+
*
|
|
4
|
+
* Collects quota signals from API responses, provider status,
|
|
5
|
+
* Playwright, and local estimates. Produces provider availability state.
|
|
6
|
+
*/
|
|
7
|
+
export class QuotaManager {
|
|
8
|
+
signals = new Map();
|
|
9
|
+
staleThresholdMs;
|
|
10
|
+
constructor(staleThresholdMs = 30 * 60 * 1000) {
|
|
11
|
+
this.staleThresholdMs = staleThresholdMs;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Record a quota signal
|
|
15
|
+
*/
|
|
16
|
+
recordSignal(input) {
|
|
17
|
+
const signal = {
|
|
18
|
+
provider: input.provider,
|
|
19
|
+
windowType: input.windowType,
|
|
20
|
+
usedPct: input.usedPct ?? 0,
|
|
21
|
+
remainingPct: 100 - (input.usedPct ?? 0),
|
|
22
|
+
exhausted: input.exhausted ?? false,
|
|
23
|
+
source: input.source,
|
|
24
|
+
capturedAt: new Date().toISOString(),
|
|
25
|
+
resetsAt: input.resetsAt,
|
|
26
|
+
};
|
|
27
|
+
const key = `${input.provider}:${input.windowType}`;
|
|
28
|
+
const existing = this.signals.get(key) ?? [];
|
|
29
|
+
this.signals.set(key, [...existing, signal]);
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Get the latest signal for a provider
|
|
33
|
+
*/
|
|
34
|
+
getLatestSignal(provider, windowType) {
|
|
35
|
+
const key = windowType ? `${provider}:${windowType}` : provider;
|
|
36
|
+
if (windowType) {
|
|
37
|
+
const signals = this.signals.get(key) ?? [];
|
|
38
|
+
return (signals.sort((a, b) => Date.parse(b.capturedAt) - Date.parse(a.capturedAt))[0] ?? null);
|
|
39
|
+
}
|
|
40
|
+
// Return most recent across all window types
|
|
41
|
+
let latest = null;
|
|
42
|
+
let latestTs = 0;
|
|
43
|
+
for (const entry of Array.from(this.signals.entries())) {
|
|
44
|
+
const [k, sigs] = entry;
|
|
45
|
+
if (k.startsWith(`${provider}:`)) {
|
|
46
|
+
const mostRecent = sigs.sort((a, b) => Date.parse(b.capturedAt) - Date.parse(a.capturedAt))[0];
|
|
47
|
+
if (mostRecent) {
|
|
48
|
+
const ts = Date.parse(mostRecent.capturedAt);
|
|
49
|
+
if (ts > latestTs) {
|
|
50
|
+
latestTs = ts;
|
|
51
|
+
latest = mostRecent;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
return latest;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Get quota state for a provider
|
|
60
|
+
*/
|
|
61
|
+
getProviderState(provider) {
|
|
62
|
+
const signals = this.getSignals(provider);
|
|
63
|
+
const exhausted = signals.some((s) => s.exhausted || (s.usedPct !== undefined && s.usedPct >= 100));
|
|
64
|
+
const limited = signals.some((s) => s.usedPct !== undefined && s.usedPct >= 90);
|
|
65
|
+
// Find next reset time
|
|
66
|
+
let nextAvailableAt;
|
|
67
|
+
for (const signal of signals) {
|
|
68
|
+
if (signal.resetsAt) {
|
|
69
|
+
if (!nextAvailableAt ||
|
|
70
|
+
Date.parse(signal.resetsAt) < Date.parse(nextAvailableAt)) {
|
|
71
|
+
nextAvailableAt = signal.resetsAt;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
return {
|
|
76
|
+
provider,
|
|
77
|
+
available: !exhausted && !limited,
|
|
78
|
+
limited,
|
|
79
|
+
exhausted,
|
|
80
|
+
signals,
|
|
81
|
+
nextAvailableAt,
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Get signals for a provider
|
|
86
|
+
*/
|
|
87
|
+
getSignals(provider) {
|
|
88
|
+
const result = [];
|
|
89
|
+
const cutoff = Date.now() - this.staleThresholdMs;
|
|
90
|
+
for (const entry of Array.from(this.signals.entries())) {
|
|
91
|
+
const [key, sigs] = entry;
|
|
92
|
+
if (key.startsWith(`${provider}:`)) {
|
|
93
|
+
for (const signal of sigs) {
|
|
94
|
+
if (Date.parse(signal.capturedAt) >= cutoff) {
|
|
95
|
+
result.push(signal);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
return result;
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Check if provider is available
|
|
104
|
+
*/
|
|
105
|
+
isAvailable(provider) {
|
|
106
|
+
return this.getProviderState(provider).available;
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Check if provider is exhausted
|
|
110
|
+
*/
|
|
111
|
+
isExhausted(provider) {
|
|
112
|
+
return this.getProviderState(provider).exhausted;
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Get time until provider is available again
|
|
116
|
+
*/
|
|
117
|
+
getWaitTime(provider) {
|
|
118
|
+
const state = this.getProviderState(provider);
|
|
119
|
+
if (!state.nextAvailableAt)
|
|
120
|
+
return null;
|
|
121
|
+
const waitMs = Date.parse(state.nextAvailableAt) - Date.now();
|
|
122
|
+
return waitMs > 0 ? waitMs : null;
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Get best available provider from a list
|
|
126
|
+
*/
|
|
127
|
+
selectBestProvider(providers) {
|
|
128
|
+
const available = providers.filter((p) => this.isAvailable(p));
|
|
129
|
+
if (available.length === 0)
|
|
130
|
+
return null;
|
|
131
|
+
// Sort by remaining quota (prefer those with more remaining)
|
|
132
|
+
available.sort((a, b) => {
|
|
133
|
+
const signalA = this.getLatestSignal(a);
|
|
134
|
+
const signalB = this.getLatestSignal(b);
|
|
135
|
+
const remA = signalA?.remainingPct ?? 100;
|
|
136
|
+
const remB = signalB?.remainingPct ?? 100;
|
|
137
|
+
return remB - remA;
|
|
138
|
+
});
|
|
139
|
+
return available[0];
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Clear stale signals
|
|
143
|
+
*/
|
|
144
|
+
clearStale() {
|
|
145
|
+
const cutoff = Date.now() - this.staleThresholdMs;
|
|
146
|
+
for (const entry of Array.from(this.signals.entries())) {
|
|
147
|
+
const [key, sigs] = entry;
|
|
148
|
+
const fresh = sigs.filter((s) => Date.parse(s.capturedAt) >= cutoff);
|
|
149
|
+
if (fresh.length === 0) {
|
|
150
|
+
this.signals.delete(key);
|
|
151
|
+
}
|
|
152
|
+
else {
|
|
153
|
+
this.signals.set(key, fresh);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Generate quota report
|
|
159
|
+
*/
|
|
160
|
+
generateReport(providers) {
|
|
161
|
+
const lines = ["Quota Status Report", "=".repeat(40), ""];
|
|
162
|
+
for (const provider of providers) {
|
|
163
|
+
const state = this.getProviderState(provider);
|
|
164
|
+
const latest = this.getLatestSignal(provider);
|
|
165
|
+
const status = state.exhausted
|
|
166
|
+
? "EXHAUSTED"
|
|
167
|
+
: state.limited
|
|
168
|
+
? "LIMITED"
|
|
169
|
+
: "AVAILABLE";
|
|
170
|
+
lines.push(`${provider}: ${status}`);
|
|
171
|
+
if (latest) {
|
|
172
|
+
lines.push(` Latest: ${latest.usedPct ?? 0}% used`);
|
|
173
|
+
if (latest.resetsAt) {
|
|
174
|
+
const wait = Date.parse(latest.resetsAt) - Date.now();
|
|
175
|
+
if (wait > 0) {
|
|
176
|
+
lines.push(` Resets: in ${Math.ceil(wait / 60000)} minutes`);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
lines.push(` Source: ${latest.source}`);
|
|
180
|
+
}
|
|
181
|
+
lines.push("");
|
|
182
|
+
}
|
|
183
|
+
return lines.join("\n");
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Parse quota signal from MiniMax error
|
|
188
|
+
*/
|
|
189
|
+
export function parseMiniMaxError(error) {
|
|
190
|
+
const e = error;
|
|
191
|
+
const msg = String(e.message ?? e.error ?? "");
|
|
192
|
+
// MiniMax quota error: "Error code: 2056 - Rate limit exceeded. Retry after..."
|
|
193
|
+
if (msg.includes("2056") ||
|
|
194
|
+
msg.includes("quota") ||
|
|
195
|
+
msg.includes("rate limit")) {
|
|
196
|
+
// Try to extract retry time
|
|
197
|
+
const retryMatch = msg.match(/retry after (\d+) (seconds?|minutes?)/i);
|
|
198
|
+
let retryAfterMs;
|
|
199
|
+
if (retryMatch) {
|
|
200
|
+
const value = parseInt(retryMatch[1], 10);
|
|
201
|
+
const unit = retryMatch[2].toLowerCase();
|
|
202
|
+
retryAfterMs = unit.startsWith("minute")
|
|
203
|
+
? value * 60 * 1000
|
|
204
|
+
: value * 1000;
|
|
205
|
+
}
|
|
206
|
+
return {
|
|
207
|
+
provider: "minimax",
|
|
208
|
+
windowType: "5h",
|
|
209
|
+
usedPct: 100,
|
|
210
|
+
remainingPct: 0,
|
|
211
|
+
exhausted: true,
|
|
212
|
+
source: "api_response",
|
|
213
|
+
capturedAt: new Date().toISOString(),
|
|
214
|
+
retryAfterMs,
|
|
215
|
+
};
|
|
216
|
+
}
|
|
217
|
+
return null;
|
|
218
|
+
}
|
|
219
|
+
/**
|
|
220
|
+
* Parse quota signal from OpenAI error
|
|
221
|
+
*/
|
|
222
|
+
export function parseOpenAIError(error) {
|
|
223
|
+
const e = error;
|
|
224
|
+
const code = String(e.code ?? "");
|
|
225
|
+
const msg = String(e.message ?? e.error ?? "");
|
|
226
|
+
if (code === "insufficient_quota" || code === "context_length_exceeded") {
|
|
227
|
+
return {
|
|
228
|
+
provider: "openai",
|
|
229
|
+
windowType: "daily",
|
|
230
|
+
usedPct: 100,
|
|
231
|
+
remainingPct: 0,
|
|
232
|
+
exhausted: true,
|
|
233
|
+
source: "api_response",
|
|
234
|
+
capturedAt: new Date().toISOString(),
|
|
235
|
+
};
|
|
236
|
+
}
|
|
237
|
+
if (msg.includes("429")) {
|
|
238
|
+
const retryMatch = msg.match(/retry after (\d+) (seconds?|minutes?)/i);
|
|
239
|
+
let retryAfterMs;
|
|
240
|
+
if (retryMatch) {
|
|
241
|
+
const value = parseInt(retryMatch[1], 10);
|
|
242
|
+
const unit = retryMatch[2].toLowerCase();
|
|
243
|
+
retryAfterMs = unit.startsWith("minute")
|
|
244
|
+
? value * 60 * 1000
|
|
245
|
+
: value * 1000;
|
|
246
|
+
}
|
|
247
|
+
return {
|
|
248
|
+
provider: "openai",
|
|
249
|
+
windowType: "5h",
|
|
250
|
+
usedPct: 100,
|
|
251
|
+
remainingPct: 0,
|
|
252
|
+
exhausted: true,
|
|
253
|
+
source: "api_response",
|
|
254
|
+
capturedAt: new Date().toISOString(),
|
|
255
|
+
retryAfterMs,
|
|
256
|
+
};
|
|
257
|
+
}
|
|
258
|
+
return null;
|
|
259
|
+
}
|