superoc 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (85) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +37 -0
  3. package/bin/nimsuper.js +21 -0
  4. package/bin/nimsuper.ts +10 -0
  5. package/bin/superoc.js +21 -0
  6. package/bin/superoc.ts +10 -0
  7. package/dist/antigravity.d.ts +59 -0
  8. package/dist/antigravity.d.ts.map +1 -0
  9. package/dist/antigravity.js +423 -0
  10. package/dist/antigravity.js.map +1 -0
  11. package/dist/errors.d.ts +22 -0
  12. package/dist/errors.d.ts.map +1 -0
  13. package/dist/errors.js +122 -0
  14. package/dist/errors.js.map +1 -0
  15. package/dist/errors.test.d.ts +2 -0
  16. package/dist/errors.test.d.ts.map +1 -0
  17. package/dist/errors.test.js +137 -0
  18. package/dist/errors.test.js.map +1 -0
  19. package/dist/index.d.ts +5 -0
  20. package/dist/index.d.ts.map +1 -0
  21. package/dist/index.js +809 -0
  22. package/dist/index.js.map +1 -0
  23. package/dist/opencode-sync.d.ts +9 -0
  24. package/dist/opencode-sync.d.ts.map +1 -0
  25. package/dist/opencode-sync.js +157 -0
  26. package/dist/opencode-sync.js.map +1 -0
  27. package/dist/provider.d.ts +5 -0
  28. package/dist/provider.d.ts.map +1 -0
  29. package/dist/provider.js +100 -0
  30. package/dist/provider.js.map +1 -0
  31. package/dist/provider.test.d.ts +2 -0
  32. package/dist/provider.test.d.ts.map +1 -0
  33. package/dist/provider.test.js +94 -0
  34. package/dist/provider.test.js.map +1 -0
  35. package/dist/quota.d.ts +12 -0
  36. package/dist/quota.d.ts.map +1 -0
  37. package/dist/quota.js +105 -0
  38. package/dist/quota.js.map +1 -0
  39. package/dist/quota.test.d.ts +2 -0
  40. package/dist/quota.test.d.ts.map +1 -0
  41. package/dist/quota.test.js +20 -0
  42. package/dist/quota.test.js.map +1 -0
  43. package/dist/storage.d.ts +43 -0
  44. package/dist/storage.d.ts.map +1 -0
  45. package/dist/storage.js +447 -0
  46. package/dist/storage.js.map +1 -0
  47. package/dist/themes.d.ts +64 -0
  48. package/dist/themes.d.ts.map +1 -0
  49. package/dist/themes.js +424 -0
  50. package/dist/themes.js.map +1 -0
  51. package/dist/tui/actions.d.ts +14 -0
  52. package/dist/tui/actions.d.ts.map +1 -0
  53. package/dist/tui/actions.js +464 -0
  54. package/dist/tui/actions.js.map +1 -0
  55. package/dist/tui/app.d.ts +2 -0
  56. package/dist/tui/app.d.ts.map +1 -0
  57. package/dist/tui/app.js +323 -0
  58. package/dist/tui/app.js.map +1 -0
  59. package/dist/tui/benchmark.d.ts +42 -0
  60. package/dist/tui/benchmark.d.ts.map +1 -0
  61. package/dist/tui/benchmark.js +379 -0
  62. package/dist/tui/benchmark.js.map +1 -0
  63. package/dist/tui/screens.d.ts +23 -0
  64. package/dist/tui/screens.d.ts.map +1 -0
  65. package/dist/tui/screens.js +791 -0
  66. package/dist/tui/screens.js.map +1 -0
  67. package/dist/tui/state.d.ts +54 -0
  68. package/dist/tui/state.d.ts.map +1 -0
  69. package/dist/tui/state.js +85 -0
  70. package/dist/tui/state.js.map +1 -0
  71. package/dist/tui/types.d.ts +16 -0
  72. package/dist/tui/types.d.ts.map +1 -0
  73. package/dist/tui/types.js +2 -0
  74. package/dist/tui/types.js.map +1 -0
  75. package/dist/tui/ui.d.ts +17 -0
  76. package/dist/tui/ui.d.ts.map +1 -0
  77. package/dist/tui/ui.js +77 -0
  78. package/dist/tui/ui.js.map +1 -0
  79. package/dist/types.d.ts +52 -0
  80. package/dist/types.d.ts.map +1 -0
  81. package/dist/types.js +2 -0
  82. package/dist/types.js.map +1 -0
  83. package/package.json +68 -0
  84. package/scripts/postinstall.js +77 -0
  85. package/scripts/uninstall.js +119 -0
@@ -0,0 +1,22 @@
1
+ export interface SessionState {
2
+ attemptIndex: number;
3
+ inRetry: boolean;
4
+ aborting: boolean;
5
+ pendingRetryIndex: number | undefined;
6
+ lastUserMessageID: string | undefined;
7
+ activeChainKey: string | undefined;
8
+ activeChainModelId: string | undefined;
9
+ rateLimitCount: number;
10
+ currentModelId: string | undefined;
11
+ lastFailedModelId: string | undefined;
12
+ lastErrorHandledAt: number;
13
+ createdAt: number;
14
+ sessionProviderId: string | undefined;
15
+ lastUsedKeyId?: string;
16
+ }
17
+ export declare function extractStatus(error: unknown): number | undefined;
18
+ export declare function isStatusMessageRateLimited(message: unknown): boolean;
19
+ export declare const is429Error: (error: unknown) => boolean;
20
+ export declare function describeError(error: unknown, state: SessionState, maxRateLimitFailures: number): string;
21
+ export declare function shouldRetryForError(error: unknown, state: SessionState): boolean;
22
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,YAAY;IAC3B,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,OAAO,CAAC;IAClB,iBAAiB,EAAE,MAAM,GAAG,SAAS,CAAC;IACtC,iBAAiB,EAAE,MAAM,GAAG,SAAS,CAAC;IACtC,cAAc,EAAE,MAAM,GAAG,SAAS,CAAC;IACnC,kBAAkB,EAAE,MAAM,GAAG,SAAS,CAAC;IACvC,cAAc,EAAE,MAAM,CAAC;IACvB,cAAc,EAAE,MAAM,GAAG,SAAS,CAAC;IACnC,iBAAiB,EAAE,MAAM,GAAG,SAAS,CAAC;IACtC,kBAAkB,EAAE,MAAM,CAAC;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,iBAAiB,EAAE,MAAM,GAAG,SAAS,CAAC;IACtC,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAID,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAShE;AAWD,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAGpE;AAED,eAAO,MAAM,UAAU,GAAI,OAAO,OAAO,KAAG,OAO3C,CAAC;AAEF,wBAAgB,aAAa,CAC3B,KAAK,EAAE,OAAO,EACd,KAAK,EAAE,YAAY,EACnB,oBAAoB,EAAE,MAAM,GAC3B,MAAM,CA0DR;AAED,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,OAAO,EACd,KAAK,EAAE,YAAY,GAClB,OAAO,CAmCT"}
package/dist/errors.js ADDED
@@ -0,0 +1,122 @@
1
+ const RETRYABLE_STATUS_CODES = new Set([408, 429, 500, 502, 503, 504]);
2
+ export function extractStatus(error) {
3
+ if (!error || typeof error !== "object")
4
+ return undefined;
5
+ const rec = error;
6
+ const data = rec.data;
7
+ if (typeof data?.statusCode === "number")
8
+ return data.statusCode;
9
+ if (typeof data?.status === "number")
10
+ return data.status;
11
+ if (typeof rec.status === "number")
12
+ return rec.status;
13
+ if (typeof rec.statusCode === "number")
14
+ return rec.statusCode;
15
+ return undefined;
16
+ }
17
+ const RATE_LIMIT_MESSAGE_PATTERNS = [
18
+ /\b429\b/,
19
+ /too many requests/i,
20
+ /rate[- ]limit(?:ed| reach)/i,
21
+ /exceeded.*(?:rate|quota)/i,
22
+ /quota.*exceeded/i,
23
+ /resource.*exhausted/i,
24
+ ];
25
+ export function isStatusMessageRateLimited(message) {
26
+ if (typeof message !== "string" || message.length === 0)
27
+ return false;
28
+ return RATE_LIMIT_MESSAGE_PATTERNS.some((re) => re.test(message));
29
+ }
30
+ export const is429Error = (error) => {
31
+ if (!error || typeof error !== "object")
32
+ return false;
33
+ if (extractStatus(error) === 429)
34
+ return true;
35
+ const rec = error;
36
+ const data = rec.data;
37
+ const message = data?.message ?? rec.message;
38
+ return isStatusMessageRateLimited(message);
39
+ };
40
+ export function describeError(error, state, maxRateLimitFailures) {
41
+ if (!error || typeof error !== "object")
42
+ return "Unknown error";
43
+ const rec = error;
44
+ if (rec.name === "MessageAbortedError") {
45
+ const msg = typeof rec.data?.message === "string"
46
+ ? rec.data.message
47
+ : "";
48
+ if (/time\s*out|timed\s*out|timeout/i.test(msg))
49
+ return "Request timed out after 60s";
50
+ return `Message aborted: ${msg || "no details"}`;
51
+ }
52
+ if (rec.name === "APIError") {
53
+ const data = rec.data;
54
+ const statusCode = extractStatus(error);
55
+ const body = data?.body;
56
+ const apiMsg = typeof body?.message === "string"
57
+ ? body.message
58
+ : typeof body?.error === "string"
59
+ ? body.error
60
+ : typeof body?.title === "string"
61
+ ? body.title
62
+ : undefined;
63
+ if (statusCode === 429) {
64
+ return `Rate limited (429) — ${state.rateLimitCount}/${maxRateLimitFailures} consecutive`;
65
+ }
66
+ if (typeof statusCode === "number") {
67
+ return `API error ${statusCode}${apiMsg ? `: ${apiMsg}` : ""}`;
68
+ }
69
+ return `API error${apiMsg ? `: ${apiMsg}` : ""}`;
70
+ }
71
+ if (rec.name === "ProviderAuthError")
72
+ return "Provider auth error";
73
+ const statusCode = extractStatus(error);
74
+ if (statusCode === 429) {
75
+ return `Rate limited (429) — ${state.rateLimitCount}/${maxRateLimitFailures} consecutive`;
76
+ }
77
+ if (typeof statusCode === "number") {
78
+ const title = typeof rec.title === "string"
79
+ ? rec.title
80
+ : typeof rec.message === "string"
81
+ ? rec.message
82
+ : undefined;
83
+ return `API error ${statusCode}${title ? `: ${title}` : ""}`;
84
+ }
85
+ const msg = typeof rec.message === "string"
86
+ ? rec.message
87
+ : typeof rec.code === "string"
88
+ ? rec.code
89
+ : "Unknown error";
90
+ return msg;
91
+ }
92
+ export function shouldRetryForError(error, state) {
93
+ if (!error || typeof error !== "object")
94
+ return false;
95
+ const rec = error;
96
+ if (rec.name === "MessageAbortedError") {
97
+ const msg = typeof rec.data?.message === "string"
98
+ ? rec.data.message
99
+ : "";
100
+ return /time\s*out|timed\s*out|timeout/i.test(msg);
101
+ }
102
+ if (rec.name === "APIError") {
103
+ const data = rec.data;
104
+ if (data?.isRetryable)
105
+ return true;
106
+ const statusCode = extractStatus(error);
107
+ if (typeof statusCode === "number" &&
108
+ RETRYABLE_STATUS_CODES.has(statusCode)) {
109
+ return true;
110
+ }
111
+ return is429Error(error);
112
+ }
113
+ if (rec.name === "ProviderAuthError")
114
+ return false;
115
+ const statusCode = extractStatus(error);
116
+ if (typeof statusCode === "number" &&
117
+ RETRYABLE_STATUS_CODES.has(statusCode)) {
118
+ return true;
119
+ }
120
+ return is429Error(error);
121
+ }
122
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=errors.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.test.d.ts","sourceRoot":"","sources":["../src/errors.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,137 @@
1
+ import { describe, it, expect } from "bun:test";
2
+ import { extractStatus, isStatusMessageRateLimited, is429Error, describeError, shouldRetryForError, } from "./errors.js";
3
+ function makeState(overrides = {}) {
4
+ return {
5
+ attemptIndex: 0,
6
+ inRetry: false,
7
+ aborting: false,
8
+ pendingRetryIndex: undefined,
9
+ lastUserMessageID: undefined,
10
+ activeChainKey: undefined,
11
+ activeChainModelId: undefined,
12
+ rateLimitCount: 0,
13
+ currentModelId: undefined,
14
+ lastFailedModelId: undefined,
15
+ lastErrorHandledAt: 0,
16
+ createdAt: 0,
17
+ sessionProviderId: undefined,
18
+ ...overrides,
19
+ };
20
+ }
21
+ describe("extractStatus", () => {
22
+ it("returns number statusCode from data", () => {
23
+ expect(extractStatus({ data: { statusCode: 429 } })).toBe(429);
24
+ expect(extractStatus({ data: { status: 500 } })).toBe(500);
25
+ });
26
+ it("returns number status from root", () => {
27
+ expect(extractStatus({ status: 503 })).toBe(503);
28
+ expect(extractStatus({ statusCode: 504 })).toBe(504);
29
+ });
30
+ it("returns undefined for non-objects", () => {
31
+ expect(extractStatus(null)).toBeUndefined();
32
+ expect(extractStatus("error")).toBeUndefined();
33
+ expect(extractStatus(42)).toBeUndefined();
34
+ });
35
+ it("returns undefined when status is string", () => {
36
+ expect(extractStatus({ data: { statusCode: "429" } })).toBeUndefined();
37
+ expect(extractStatus({ data: { status: "500" } })).toBeUndefined();
38
+ });
39
+ });
40
+ describe("isStatusMessageRateLimited", () => {
41
+ it("matches 429 in message", () => {
42
+ expect(isStatusMessageRateLimited("Error 429")).toBe(true);
43
+ });
44
+ it("matches rate limit phrases", () => {
45
+ expect(isStatusMessageRateLimited("Too many requests")).toBe(true);
46
+ expect(isStatusMessageRateLimited("Rate-limited")).toBe(true);
47
+ expect(isStatusMessageRateLimited("Rate limited")).toBe(true);
48
+ expect(isStatusMessageRateLimited("Rate limit reached")).toBe(true);
49
+ expect(isStatusMessageRateLimited("exceeded rate")).toBe(true);
50
+ expect(isStatusMessageRateLimited("exceeded quota")).toBe(true);
51
+ expect(isStatusMessageRateLimited("quota exceeded")).toBe(true);
52
+ expect(isStatusMessageRateLimited("resource exhausted")).toBe(true);
53
+ });
54
+ it("returns false for non-matching messages", () => {
55
+ expect(isStatusMessageRateLimited("Not found")).toBe(false);
56
+ expect(isStatusMessageRateLimited("")).toBe(false);
57
+ expect(isStatusMessageRateLimited(42)).toBe(false);
58
+ expect(isStatusMessageRateLimited(null)).toBe(false);
59
+ });
60
+ });
61
+ describe("is429Error", () => {
62
+ it("detects numeric 429 status", () => {
63
+ expect(is429Error({ data: { statusCode: 429 } })).toBe(true);
64
+ expect(is429Error({ status: 429 })).toBe(true);
65
+ });
66
+ it("detects message-based 429", () => {
67
+ expect(is429Error({ data: { message: "Error 429" } })).toBe(true);
68
+ expect(is429Error({ message: "Too many requests" })).toBe(true);
69
+ expect(is429Error({ data: { message: "Rate limited" } })).toBe(true);
70
+ });
71
+ it("returns false for non-429 errors", () => {
72
+ expect(is429Error({ data: { statusCode: 500 } })).toBe(false);
73
+ expect(is429Error({ message: "Not found" })).toBe(false);
74
+ expect(is429Error(null)).toBe(false);
75
+ });
76
+ });
77
+ describe("shouldRetryForError", () => {
78
+ it("retries on MessageAbortedError with timeout", () => {
79
+ const error = { name: "MessageAbortedError", data: { message: "timeout" } };
80
+ expect(shouldRetryForError(error, makeState())).toBe(true);
81
+ });
82
+ it("retries on APIError with isRetryable", () => {
83
+ const error = { name: "APIError", data: { isRetryable: true } };
84
+ expect(shouldRetryForError(error, makeState())).toBe(true);
85
+ });
86
+ it("retries on APIError with retryable status code", () => {
87
+ expect(shouldRetryForError({ name: "APIError", data: { statusCode: 429 } }, makeState())).toBe(true);
88
+ expect(shouldRetryForError({ name: "APIError", data: { statusCode: 500 } }, makeState())).toBe(true);
89
+ expect(shouldRetryForError({ name: "APIError", data: { statusCode: 503 } }, makeState())).toBe(true);
90
+ });
91
+ it("retries on APIError with string statusCode via message fallback (CRITICAL FIX)", () => {
92
+ // This is the exact bug: statusCode is "429" (string), so extractStatus returns undefined,
93
+ // but is429Error catches it via message pattern
94
+ const error = {
95
+ name: "APIError",
96
+ data: { statusCode: "429", message: "Error 429" },
97
+ };
98
+ expect(shouldRetryForError(error, makeState())).toBe(true);
99
+ });
100
+ it("retries on generic error with retryable status code", () => {
101
+ expect(shouldRetryForError({ statusCode: 502 }, makeState())).toBe(true);
102
+ expect(shouldRetryForError({ statusCode: 504 }, makeState())).toBe(true);
103
+ });
104
+ it("does not retry ProviderAuthError", () => {
105
+ expect(shouldRetryForError({ name: "ProviderAuthError" }, makeState())).toBe(false);
106
+ });
107
+ it("does not retry non-retryable errors", () => {
108
+ expect(shouldRetryForError({ name: "APIError", data: { statusCode: 400 } }, makeState())).toBe(false);
109
+ expect(shouldRetryForError({ statusCode: 404 }, makeState())).toBe(false);
110
+ });
111
+ });
112
+ describe("describeError", () => {
113
+ it("describes MessageAbortedError timeout", () => {
114
+ const error = { name: "MessageAbortedError", data: { message: "timeout" } };
115
+ expect(describeError(error, makeState(), 3)).toBe("Request timed out after 60s");
116
+ });
117
+ it("describes 429 rate limit", () => {
118
+ const error = { name: "APIError", data: { statusCode: 429 } };
119
+ const state = makeState({ rateLimitCount: 2 });
120
+ expect(describeError(error, state, 3)).toBe("Rate limited (429) — 2/3 consecutive");
121
+ });
122
+ it("describes generic API error with status", () => {
123
+ const error = {
124
+ name: "APIError",
125
+ data: { statusCode: 500, body: { message: "Server error" } },
126
+ };
127
+ expect(describeError(error, makeState(), 3)).toBe("API error 500: Server error");
128
+ });
129
+ it("describes ProviderAuthError", () => {
130
+ expect(describeError({ name: "ProviderAuthError" }, makeState(), 3)).toBe("Provider auth error");
131
+ });
132
+ it("describes unknown error", () => {
133
+ expect(describeError(null, makeState(), 3)).toBe("Unknown error");
134
+ expect(describeError({ message: "Something broke" }, makeState(), 3)).toBe("Something broke");
135
+ });
136
+ });
137
+ //# sourceMappingURL=errors.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.test.js","sourceRoot":"","sources":["../src/errors.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ import type { Plugin } from "@opencode-ai/plugin";
2
+ export declare const SuperocPlugin: Plugin;
3
+ export declare const NimSuperPlugin: Plugin;
4
+ export default SuperocPlugin;
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAsB,MAAM,qBAAqB,CAAC;AAuGtE,eAAO,MAAM,aAAa,EAAE,MA4wB3B,CAAC;AAEF,eAAO,MAAM,cAAc,QAAgB,CAAC;AAC5C,eAAe,aAAa,CAAC"}