@redstone-md/mapr 0.0.4-alpha → 0.0.6-alpha
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/README.md +20 -0
- package/index.ts +57 -4
- package/lib/ai-analyzer.ts +177 -330
- package/lib/ai-json.ts +40 -1
- package/lib/analysis-fallback.ts +39 -0
- package/lib/analysis-helpers.ts +108 -0
- package/lib/cli-args.ts +20 -2
- package/lib/codex-auth.ts +275 -0
- package/lib/config-prompts.ts +74 -0
- package/lib/config.ts +164 -55
- package/lib/progress.ts +144 -0
- package/lib/promise-pool.ts +25 -0
- package/lib/provider.ts +216 -14
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -10,6 +10,7 @@ This repository is public for source visibility and collaboration. The license r
|
|
|
10
10
|
|
|
11
11
|
- Bun-only CLI/TUI with interactive setup through `@clack/prompts`
|
|
12
12
|
- OpenAI and OpenAI-compatible provider support
|
|
13
|
+
- OpenAI Codex family support with fast/reasoning selection
|
|
13
14
|
- Built-in provider presets for BlackBox AI, Nvidia NIM, and OnlySQ
|
|
14
15
|
- Model discovery with searchable selection
|
|
15
16
|
- Automatic context-window detection from provider model metadata when available
|
|
@@ -77,6 +78,14 @@ npx @redstone-md/mapr --help
|
|
|
77
78
|
- `onlysq` -> `https://api.onlysq.ru/ai/openai`
|
|
78
79
|
- `custom` -> any other OpenAI-compatible endpoint
|
|
79
80
|
|
|
81
|
+
## OpenAI Auth Modes
|
|
82
|
+
|
|
83
|
+
- `API key` uses the standard OpenAI API at `https://api.openai.com/v1`
|
|
84
|
+
- `Use existing Codex CLI auth` reuses the local `codex login` browser session from `~/.codex/auth.json`
|
|
85
|
+
- Codex CLI auth automatically switches OpenAI requests to `https://chatgpt.com/backend-api/codex`
|
|
86
|
+
- When the local Codex access token expires, Mapr refreshes it through the official OpenAI refresh-token flow before retrying the request
|
|
87
|
+
- If Codex CLI auth is missing, run `codex login` first and then re-run Mapr
|
|
88
|
+
|
|
80
89
|
## Usage
|
|
81
90
|
|
|
82
91
|
Interactive:
|
|
@@ -105,6 +114,17 @@ List models with detected context sizes when available:
|
|
|
105
114
|
npx @redstone-md/mapr --list-models --headless --provider-preset nvidia-nim --api-key secret
|
|
106
115
|
```
|
|
107
116
|
|
|
117
|
+
List models through an existing Codex CLI login:
|
|
118
|
+
|
|
119
|
+
```bash
|
|
120
|
+
npx @redstone-md/mapr \
|
|
121
|
+
--headless \
|
|
122
|
+
--list-models \
|
|
123
|
+
--provider-type openai \
|
|
124
|
+
--auth-method codex-cli \
|
|
125
|
+
--codex-home ~/.codex
|
|
126
|
+
```
|
|
127
|
+
|
|
108
128
|
Useful flags:
|
|
109
129
|
|
|
110
130
|
- `--max-pages <n>` limits same-origin HTML pages
|
package/index.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env bun
|
|
2
2
|
|
|
3
|
-
import { cancel, confirm, intro, isCancel, log, outro, spinner, text } from "@clack/prompts";
|
|
3
|
+
import { cancel, confirm, intro, isCancel, log, outro, select, spinner, text } from "@clack/prompts";
|
|
4
4
|
import pc from "picocolors";
|
|
5
5
|
import packageJson from "./package.json";
|
|
6
6
|
|
|
@@ -9,11 +9,15 @@ import { AiBundleAnalyzer, chunkTextByBytes, deriveChunkSizeBytes } from "./lib/
|
|
|
9
9
|
import { getConfigOverrides, parseCliArgs, renderHelpText } from "./lib/cli-args";
|
|
10
10
|
import { ConfigManager } from "./lib/config";
|
|
11
11
|
import { BundleFormatter } from "./lib/formatter";
|
|
12
|
-
import { renderProgressBar } from "./lib/progress";
|
|
12
|
+
import { renderAdaptiveAnalysisProgressLine, renderProgressBar } from "./lib/progress";
|
|
13
|
+
import { findKnownModelInfo, isCodexModel } from "./lib/provider";
|
|
13
14
|
import { ReportWriter } from "./lib/reporter";
|
|
14
15
|
import { BundleScraper } from "./lib/scraper";
|
|
15
16
|
import { SWARM_AGENT_ORDER } from "./lib/swarm-prompts";
|
|
16
17
|
|
|
18
|
+
process.env.AI_SDK_LOG_WARNINGS = "false";
|
|
19
|
+
(globalThis as typeof globalThis & { AI_SDK_LOG_WARNINGS?: boolean }).AI_SDK_LOG_WARNINGS = false;
|
|
20
|
+
|
|
17
21
|
function exitIfCancelled<T>(value: T): T {
|
|
18
22
|
if (isCancel(value)) {
|
|
19
23
|
cancel("Operation cancelled.");
|
|
@@ -62,6 +66,30 @@ async function resolveTargetUrl(headless: boolean, prefilledUrl?: string): Promi
|
|
|
62
66
|
);
|
|
63
67
|
}
|
|
64
68
|
|
|
69
|
+
async function resolveAnalysisConcurrency(headless: boolean, prefilledValue: number | undefined, totalChunks: number): Promise<number> {
|
|
70
|
+
if (prefilledValue !== undefined) {
|
|
71
|
+
return prefilledValue;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
if (headless || totalChunks <= 1) {
|
|
75
|
+
return 1;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
return Number(
|
|
79
|
+
exitIfCancelled(
|
|
80
|
+
await select({
|
|
81
|
+
message: "Analysis concurrency",
|
|
82
|
+
initialValue: 2,
|
|
83
|
+
options: [
|
|
84
|
+
{ value: 1, label: "1 lane", hint: "Most stable" },
|
|
85
|
+
{ value: 2, label: "2 lanes", hint: "Recommended" },
|
|
86
|
+
{ value: 4, label: "4 lanes", hint: "Aggressive" },
|
|
87
|
+
],
|
|
88
|
+
}),
|
|
89
|
+
),
|
|
90
|
+
);
|
|
91
|
+
}
|
|
92
|
+
|
|
65
93
|
async function run(): Promise<void> {
|
|
66
94
|
const args = parseCliArgs(process.argv.slice(2));
|
|
67
95
|
|
|
@@ -147,21 +175,41 @@ async function run(): Promise<void> {
|
|
|
147
175
|
sum + chunkTextByBytes(artifact.formattedContent || artifact.content, deriveChunkSizeBytes(config.modelContextSize)).length,
|
|
148
176
|
0,
|
|
149
177
|
);
|
|
178
|
+
const analysisConcurrency = await resolveAnalysisConcurrency(headless, args.analysisConcurrency, totalChunks);
|
|
150
179
|
const totalAgentTasks = Math.max(1, totalChunks * SWARM_AGENT_ORDER.length);
|
|
151
180
|
let completedAgentTasks = 0;
|
|
181
|
+
const analysisStartedAt = Date.now();
|
|
152
182
|
|
|
153
183
|
const analysisStep = spinner({ indicator: "timer" });
|
|
154
|
-
analysisStep.start(formatAnalysisProgress(0, totalAgentTasks,
|
|
184
|
+
analysisStep.start(formatAnalysisProgress(0, totalAgentTasks, `Starting swarm analysis (${analysisConcurrency} lane${analysisConcurrency === 1 ? "" : "s"})`));
|
|
155
185
|
|
|
156
186
|
const analyzer = new AiBundleAnalyzer({
|
|
157
187
|
providerConfig: config,
|
|
158
188
|
localRag: args.localRag,
|
|
189
|
+
analysisConcurrency,
|
|
159
190
|
onProgress(event) {
|
|
160
191
|
if (event.stage === "agent" && event.state === "completed") {
|
|
161
192
|
completedAgentTasks += 1;
|
|
162
193
|
}
|
|
163
194
|
|
|
164
|
-
const progressLine =
|
|
195
|
+
const progressLine =
|
|
196
|
+
event.stage === "agent" && event.agent
|
|
197
|
+
? renderAdaptiveAnalysisProgressLine({
|
|
198
|
+
completed: completedAgentTasks,
|
|
199
|
+
total: totalAgentTasks,
|
|
200
|
+
elapsedMs: Date.now() - analysisStartedAt,
|
|
201
|
+
agent: event.agent,
|
|
202
|
+
state: event.state,
|
|
203
|
+
artifactUrl: event.artifactUrl,
|
|
204
|
+
...(event.chunkIndex !== undefined ? { chunkIndex: event.chunkIndex } : {}),
|
|
205
|
+
...(event.chunkCount !== undefined ? { chunkCount: event.chunkCount } : {}),
|
|
206
|
+
...(event.estimatedOutputTokens !== undefined
|
|
207
|
+
? { estimatedOutputTokens: event.estimatedOutputTokens }
|
|
208
|
+
: {}),
|
|
209
|
+
...(event.outputTokens !== undefined ? { outputTokens: event.outputTokens } : {}),
|
|
210
|
+
...(event.tokensPerSecond !== undefined ? { tokensPerSecond: event.tokensPerSecond } : {}),
|
|
211
|
+
})
|
|
212
|
+
: formatAnalysisProgress(completedAgentTasks, totalAgentTasks, event.message);
|
|
165
213
|
analysisStep.message(progressLine);
|
|
166
214
|
|
|
167
215
|
if (args.verboseAgents && event.stage === "agent" && event.state === "completed") {
|
|
@@ -218,12 +266,17 @@ async function run(): Promise<void> {
|
|
|
218
266
|
});
|
|
219
267
|
reportStep.stop(reportStatus === "partial" ? "Partial report written to disk" : "Report written to disk");
|
|
220
268
|
|
|
269
|
+
const selectedModelInfo = findKnownModelInfo(config.model);
|
|
221
270
|
const summaryLines = [
|
|
222
271
|
reportStatus === "partial" ? `${pc.yellow("Analysis incomplete.")}` : `${pc.green("Analysis complete.")}`,
|
|
223
272
|
`${pc.bold("Status:")} ${reportStatus === "partial" ? "partial report saved after error" : "complete"}`,
|
|
224
273
|
`${pc.bold("Target:")} ${scrapeResult.pageUrl}`,
|
|
225
274
|
`${pc.bold("Provider:")} ${config.providerName} (${config.model})`,
|
|
275
|
+
...(config.authMethod !== undefined ? [`${pc.bold("Auth:")} ${config.authMethod}`] : []),
|
|
226
276
|
`${pc.bold("Context size:")} ${config.modelContextSize.toLocaleString()} tokens`,
|
|
277
|
+
...(config.openAiMode !== undefined ? [`${pc.bold("OpenAI mode:")} ${config.openAiMode}`] : []),
|
|
278
|
+
...(isCodexModel(config.model) && selectedModelInfo?.usageLimitsNote ? [`${pc.bold("Codex limits:")} ${selectedModelInfo.usageLimitsNote}`] : []),
|
|
279
|
+
`${pc.bold("Concurrency:")} ${analysisConcurrency}`,
|
|
227
280
|
`${pc.bold("Local RAG:")} ${args.localRag ? "enabled" : "disabled"}`,
|
|
228
281
|
`${pc.bold("Pages:")} ${scrapeResult.htmlPages.length}`,
|
|
229
282
|
`${pc.bold("Artifacts:")} ${formattedArtifacts.length}`,
|