ai-spec-dev 0.42.0 → 0.46.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.
- package/README.md +33 -17
- package/cli/commands/create.ts +232 -11
- package/cli/commands/init.ts +310 -107
- package/cli/commands/model.ts +7 -11
- package/cli/index.ts +1 -1
- package/cli/utils.ts +72 -4
- package/core/config-defaults.ts +44 -0
- package/core/constitution-generator.ts +2 -1
- package/core/dsl-extractor.ts +2 -1
- package/core/error-feedback.ts +3 -2
- package/core/openapi-exporter.ts +3 -2
- package/core/repo-store.ts +95 -0
- package/core/reviewer.ts +14 -13
- package/core/run-logger.ts +3 -4
- package/core/run-snapshot.ts +2 -3
- package/core/run-trend.ts +3 -4
- package/core/spec-generator.ts +27 -42
- package/core/token-budget.ts +3 -8
- package/core/vcr.ts +3 -1
- package/dist/cli/index.js +919 -519
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/index.mjs +912 -512
- package/dist/cli/index.mjs.map +1 -1
- package/dist/index.d.mts +3 -2
- package/dist/index.d.ts +3 -2
- package/dist/index.js +43 -53
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +43 -53
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/demo-backend/.ai-spec-constitution.md +0 -65
- package/demo-backend/package.json +0 -21
- package/demo-backend/prisma/schema.prisma +0 -22
- package/demo-backend/specs/feature-1-bookmark-id-uuid-title-string-required-url-str-v1.dsl.json +0 -186
- package/demo-backend/specs/feature-1-bookmark-id-uuid-title-string-required-url-str-v1.md +0 -211
- package/demo-backend/src/controllers/bookmark.controller.test.ts +0 -255
- package/demo-backend/src/controllers/bookmark.controller.ts +0 -187
- package/demo-backend/src/index.ts +0 -17
- package/demo-backend/src/routes/bookmark.routes.test.ts +0 -264
- package/demo-backend/src/routes/bookmark.routes.ts +0 -11
- package/demo-backend/src/routes/index.ts +0 -8
- package/demo-backend/src/services/bookmark.service.test.ts +0 -433
- package/demo-backend/src/services/bookmark.service.ts +0 -261
- package/demo-backend/tsconfig.json +0 -12
- package/demo-frontend/.ai-spec-constitution.md +0 -95
- package/demo-frontend/package.json +0 -23
- package/demo-frontend/src/App.tsx +0 -12
- package/demo-frontend/src/main.tsx +0 -9
- package/demo-frontend/tsconfig.json +0 -13
package/dist/index.mjs
CHANGED
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
import { GoogleGenerativeAI } from "@google/generative-ai";
|
|
3
3
|
import Anthropic from "@anthropic-ai/sdk";
|
|
4
4
|
import OpenAI from "openai";
|
|
5
|
-
import axios from "axios";
|
|
6
5
|
import { ProxyAgent } from "undici";
|
|
7
6
|
|
|
8
7
|
// prompts/spec.prompt.ts
|
|
@@ -295,7 +294,9 @@ var PROVIDER_CATALOG = {
|
|
|
295
294
|
displayName: "MiMo (Xiaomi)",
|
|
296
295
|
description: "\u5C0F\u7C73 MiMo \u2014 mimo-v2-pro (Anthropic-compatible API)",
|
|
297
296
|
models: ["mimo-v2-pro"],
|
|
298
|
-
envKey: "MIMO_API_KEY"
|
|
297
|
+
envKey: "MIMO_API_KEY",
|
|
298
|
+
// Fallback env var — MiMo's token plan uses ANTHROPIC_AUTH_TOKEN
|
|
299
|
+
fallbackEnvKeys: ["ANTHROPIC_AUTH_TOKEN"]
|
|
299
300
|
// baseURL not used — MiMo has a dedicated provider class
|
|
300
301
|
},
|
|
301
302
|
gemini: {
|
|
@@ -464,8 +465,8 @@ var ClaudeProvider = class {
|
|
|
464
465
|
...systemInstruction ? { system: systemInstruction } : {},
|
|
465
466
|
messages: [{ role: "user", content: prompt }]
|
|
466
467
|
});
|
|
467
|
-
const
|
|
468
|
-
if (
|
|
468
|
+
const textBlock = message.content.find((b) => b.type === "text");
|
|
469
|
+
if (textBlock) return textBlock.text;
|
|
469
470
|
throw new Error("Unexpected response type from Claude API");
|
|
470
471
|
},
|
|
471
472
|
{ label: `${this.providerName}/${this.modelName}` }
|
|
@@ -510,43 +511,29 @@ var OpenAICompatibleProvider = class {
|
|
|
510
511
|
}
|
|
511
512
|
};
|
|
512
513
|
var MiMoProvider = class {
|
|
514
|
+
client;
|
|
513
515
|
providerName = "mimo";
|
|
514
516
|
modelName;
|
|
515
|
-
apiKey;
|
|
516
|
-
baseUrl = "https://api.xiaomimimo.com/anthropic/v1/messages";
|
|
517
517
|
constructor(apiKey, modelName = PROVIDER_CATALOG.mimo.models[0]) {
|
|
518
|
-
|
|
518
|
+
const baseURL = process.env["MIMO_BASE_URL"] || process.env["ANTHROPIC_BASE_URL"] || "https://token-plan-cn.xiaomimimo.com/anthropic";
|
|
519
|
+
this.client = new Anthropic({ apiKey, baseURL });
|
|
519
520
|
this.modelName = modelName;
|
|
520
521
|
}
|
|
521
522
|
async generate(prompt, systemInstruction) {
|
|
522
523
|
return withReliability(
|
|
523
524
|
async () => {
|
|
524
|
-
const
|
|
525
|
+
const stream = this.client.messages.stream({
|
|
525
526
|
model: this.modelName,
|
|
526
|
-
max_tokens:
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
stream: false,
|
|
530
|
-
temperature: 1,
|
|
531
|
-
stop_sequences: null
|
|
532
|
-
};
|
|
533
|
-
if (systemInstruction) {
|
|
534
|
-
body.system = systemInstruction;
|
|
535
|
-
}
|
|
536
|
-
const response = await axios.post(this.baseUrl, body, {
|
|
537
|
-
headers: {
|
|
538
|
-
"api-key": this.apiKey,
|
|
539
|
-
"Content-Type": "application/json"
|
|
540
|
-
}
|
|
527
|
+
max_tokens: 65536,
|
|
528
|
+
...systemInstruction ? { system: systemInstruction } : {},
|
|
529
|
+
messages: [{ role: "user", content: prompt }]
|
|
541
530
|
});
|
|
542
|
-
const
|
|
543
|
-
const
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
if (
|
|
547
|
-
|
|
548
|
-
}
|
|
549
|
-
throw new Error(`Unexpected MiMo response: ${JSON.stringify(response.data).slice(0, 200)}`);
|
|
531
|
+
const message = await stream.finalMessage();
|
|
532
|
+
const textBlock = message.content.find((b) => b.type === "text");
|
|
533
|
+
if (textBlock) return textBlock.text;
|
|
534
|
+
const thinkBlock = message.content.find((b) => b.type === "thinking");
|
|
535
|
+
if (thinkBlock) return thinkBlock.thinking;
|
|
536
|
+
return message.content.map((b) => b.text ?? "").join("");
|
|
550
537
|
},
|
|
551
538
|
{ label: `${this.providerName}/${this.modelName}` }
|
|
552
539
|
);
|
|
@@ -5151,13 +5138,11 @@ function typeLabel(v2) {
|
|
|
5151
5138
|
|
|
5152
5139
|
// core/token-budget.ts
|
|
5153
5140
|
import chalk6 from "chalk";
|
|
5154
|
-
|
|
5155
|
-
|
|
5156
|
-
|
|
5157
|
-
|
|
5158
|
-
|
|
5159
|
-
return Math.ceil(cjkCount + nonCjkLength / 4);
|
|
5160
|
-
}
|
|
5141
|
+
|
|
5142
|
+
// core/config-defaults.ts
|
|
5143
|
+
var DEFAULT_REVIEW_HISTORY_FILE = ".ai-spec-reviews.json";
|
|
5144
|
+
var DEFAULT_MAX_CONSTITUTION_CHARS = 4e3;
|
|
5145
|
+
var DEFAULT_MAX_REVIEW_FILE_CHARS = 3e3;
|
|
5161
5146
|
var DEFAULT_TOKEN_BUDGETS = {
|
|
5162
5147
|
gemini: 9e5,
|
|
5163
5148
|
claude: 18e4,
|
|
@@ -5165,8 +5150,18 @@ var DEFAULT_TOKEN_BUDGETS = {
|
|
|
5165
5150
|
deepseek: 6e4,
|
|
5166
5151
|
default: 1e5
|
|
5167
5152
|
};
|
|
5153
|
+
|
|
5154
|
+
// core/token-budget.ts
|
|
5155
|
+
var CJK_RANGE = /[\u4e00-\u9fff\u3400-\u4dbf\u3000-\u303f\uff00-\uffef]/g;
|
|
5156
|
+
function estimateTokens(text) {
|
|
5157
|
+
if (!text) return 0;
|
|
5158
|
+
const cjkCount = (text.match(CJK_RANGE) ?? []).length;
|
|
5159
|
+
const nonCjkLength = text.length - cjkCount;
|
|
5160
|
+
return Math.ceil(cjkCount + nonCjkLength / 4);
|
|
5161
|
+
}
|
|
5162
|
+
var DEFAULT_TOKEN_BUDGETS2 = DEFAULT_TOKEN_BUDGETS;
|
|
5168
5163
|
function getDefaultBudget(providerName) {
|
|
5169
|
-
return
|
|
5164
|
+
return DEFAULT_TOKEN_BUDGETS2[providerName] ?? DEFAULT_TOKEN_BUDGETS2.default;
|
|
5170
5165
|
}
|
|
5171
5166
|
|
|
5172
5167
|
// core/dsl-extractor.ts
|
|
@@ -6627,7 +6622,7 @@ ${context.routeSummary}
|
|
|
6627
6622
|
}
|
|
6628
6623
|
if (context.schema) {
|
|
6629
6624
|
parts.push(`=== Prisma Schema ===
|
|
6630
|
-
${context.schema.slice(0,
|
|
6625
|
+
${context.schema.slice(0, DEFAULT_MAX_CONSTITUTION_CHARS)}
|
|
6631
6626
|
`);
|
|
6632
6627
|
}
|
|
6633
6628
|
if (context.errorPatterns) {
|
|
@@ -6691,7 +6686,7 @@ async function loadAccumulatedLessons(projectRoot) {
|
|
|
6691
6686
|
const nextSection = section.slice(marker.length).match(/\n## \d/);
|
|
6692
6687
|
return nextSection ? section.slice(0, marker.length + nextSection.index) : section;
|
|
6693
6688
|
}
|
|
6694
|
-
var REVIEW_HISTORY_FILE =
|
|
6689
|
+
var REVIEW_HISTORY_FILE = DEFAULT_REVIEW_HISTORY_FILE;
|
|
6695
6690
|
async function loadReviewHistory(projectRoot) {
|
|
6696
6691
|
const historyPath = path8.join(projectRoot, REVIEW_HISTORY_FILE);
|
|
6697
6692
|
try {
|
|
@@ -6822,15 +6817,13 @@ ${specContent || "(No spec \u2014 review for general code quality)"}
|
|
|
6822
6817
|
${codeContext}`;
|
|
6823
6818
|
const archReview = await this.provider.generate(archPrompt, reviewArchitectureSystemPrompt);
|
|
6824
6819
|
console.log(chalk12.gray(" Pass 2/3: Implementation review..."));
|
|
6820
|
+
const specDigest = specContent && specContent.length > 600 ? specContent.slice(0, 600) + "\n... [spec truncated \u2014 see Pass 0/1 for full text]" : specContent || "(No spec)";
|
|
6825
6821
|
const history = await loadReviewHistory(this.projectRoot);
|
|
6826
6822
|
const historyContext = buildHistoryContext(history);
|
|
6827
6823
|
const implPrompt = `Review the implementation details of this change.
|
|
6828
6824
|
|
|
6829
|
-
=== Feature Spec ===
|
|
6830
|
-
${
|
|
6831
|
-
|
|
6832
|
-
=== Code ===
|
|
6833
|
-
${codeContext}
|
|
6825
|
+
=== Feature Spec (digest \u2014 full spec was provided in Pass 0/1) ===
|
|
6826
|
+
${specDigest}
|
|
6834
6827
|
|
|
6835
6828
|
=== Architecture Review (Pass 1 \u2014 do NOT repeat these findings) ===
|
|
6836
6829
|
${archReview}
|
|
@@ -6839,11 +6832,8 @@ ${historyContext}`;
|
|
|
6839
6832
|
console.log(chalk12.gray(" Pass 3/3: Impact & complexity assessment..."));
|
|
6840
6833
|
const impactPrompt = `Assess the impact and complexity of this change.
|
|
6841
6834
|
|
|
6842
|
-
=== Feature Spec ===
|
|
6843
|
-
${
|
|
6844
|
-
|
|
6845
|
-
=== Code ===
|
|
6846
|
-
${codeContext}
|
|
6835
|
+
=== Feature Spec (digest) ===
|
|
6836
|
+
${specDigest}
|
|
6847
6837
|
|
|
6848
6838
|
=== Architecture Review (Pass 1 \u2014 do NOT repeat) ===
|
|
6849
6839
|
${archReview}
|
|
@@ -6917,8 +6907,8 @@ ${sep}
|
|
|
6917
6907
|
filesSection += `
|
|
6918
6908
|
|
|
6919
6909
|
=== ${filePath} ===
|
|
6920
|
-
${content.slice(0,
|
|
6921
|
-
if (content.length >
|
|
6910
|
+
${content.slice(0, DEFAULT_MAX_REVIEW_FILE_CHARS)}`;
|
|
6911
|
+
if (content.length > DEFAULT_MAX_REVIEW_FILE_CHARS) filesSection += `
|
|
6922
6912
|
... (truncated, ${content.length} chars total)`;
|
|
6923
6913
|
} catch {
|
|
6924
6914
|
filesSection += `
|