@dewtech/dare-cli 3.11.0 → 3.12.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 +2 -0
- package/dist/__tests__/ensure-skills.test.js +5 -0
- package/dist/__tests__/ensure-skills.test.js.map +1 -1
- package/dist/__tests__/ide-command-parity.test.js +1 -0
- package/dist/__tests__/ide-command-parity.test.js.map +1 -1
- package/dist/__tests__/project-generator.test.js +17 -0
- package/dist/__tests__/project-generator.test.js.map +1 -1
- package/dist/__tests__/reverse-facts.test.js +1 -0
- package/dist/__tests__/reverse-facts.test.js.map +1 -1
- package/dist/__tests__/terminal-parity-regression.test.d.ts +2 -0
- package/dist/__tests__/terminal-parity-regression.test.d.ts.map +1 -0
- package/dist/__tests__/terminal-parity-regression.test.js +116 -0
- package/dist/__tests__/terminal-parity-regression.test.js.map +1 -0
- package/dist/__tests__/terminal-parity.test.d.ts +2 -0
- package/dist/__tests__/terminal-parity.test.d.ts.map +1 -0
- package/dist/__tests__/terminal-parity.test.js +81 -0
- package/dist/__tests__/terminal-parity.test.js.map +1 -0
- package/dist/agent/__tests__/antigravity-driver.test.d.ts +2 -0
- package/dist/agent/__tests__/antigravity-driver.test.d.ts.map +1 -0
- package/dist/agent/__tests__/antigravity-driver.test.js +52 -0
- package/dist/agent/__tests__/antigravity-driver.test.js.map +1 -0
- package/dist/agent/__tests__/codex-driver.test.d.ts +2 -0
- package/dist/agent/__tests__/codex-driver.test.d.ts.map +1 -0
- package/dist/agent/__tests__/codex-driver.test.js +68 -0
- package/dist/agent/__tests__/codex-driver.test.js.map +1 -0
- package/dist/agent/__tests__/cursor-driver.test.d.ts +2 -0
- package/dist/agent/__tests__/cursor-driver.test.d.ts.map +1 -0
- package/dist/agent/__tests__/cursor-driver.test.js +52 -0
- package/dist/agent/__tests__/cursor-driver.test.js.map +1 -0
- package/dist/agent/driver.d.ts +1 -1
- package/dist/agent/driver.d.ts.map +1 -1
- package/dist/agent/drivers/antigravity.d.ts +8 -0
- package/dist/agent/drivers/antigravity.d.ts.map +1 -0
- package/dist/agent/drivers/antigravity.js +99 -0
- package/dist/agent/drivers/antigravity.js.map +1 -0
- package/dist/agent/drivers/codex.d.ts +12 -0
- package/dist/agent/drivers/codex.d.ts.map +1 -0
- package/dist/agent/drivers/codex.js +137 -0
- package/dist/agent/drivers/codex.js.map +1 -0
- package/dist/agent/drivers/cursor.d.ts +8 -0
- package/dist/agent/drivers/cursor.d.ts.map +1 -0
- package/dist/agent/drivers/cursor.js +99 -0
- package/dist/agent/drivers/cursor.js.map +1 -0
- package/dist/ai/__tests__/ai-core.test.d.ts +2 -0
- package/dist/ai/__tests__/ai-core.test.d.ts.map +1 -0
- package/dist/ai/__tests__/ai-core.test.js +41 -0
- package/dist/ai/__tests__/ai-core.test.js.map +1 -0
- package/dist/ai/__tests__/parity.test.d.ts +2 -0
- package/dist/ai/__tests__/parity.test.d.ts.map +1 -0
- package/dist/ai/__tests__/parity.test.js +36 -0
- package/dist/ai/__tests__/parity.test.js.map +1 -0
- package/dist/ai/__tests__/pipeline.test.d.ts +2 -0
- package/dist/ai/__tests__/pipeline.test.d.ts.map +1 -0
- package/dist/ai/__tests__/pipeline.test.js +147 -0
- package/dist/ai/__tests__/pipeline.test.js.map +1 -0
- package/dist/ai/__tests__/refine-bridge.test.d.ts +2 -0
- package/dist/ai/__tests__/refine-bridge.test.d.ts.map +1 -0
- package/dist/ai/__tests__/refine-bridge.test.js +17 -0
- package/dist/ai/__tests__/refine-bridge.test.js.map +1 -0
- package/dist/ai/__tests__/resolve.test.d.ts +2 -0
- package/dist/ai/__tests__/resolve.test.d.ts.map +1 -0
- package/dist/ai/__tests__/resolve.test.js +42 -0
- package/dist/ai/__tests__/resolve.test.js.map +1 -0
- package/dist/ai/capabilities.d.ts +3 -0
- package/dist/ai/capabilities.d.ts.map +1 -0
- package/dist/ai/capabilities.js +11 -0
- package/dist/ai/capabilities.js.map +1 -0
- package/dist/ai/command-options.d.ts +10 -0
- package/dist/ai/command-options.d.ts.map +1 -0
- package/dist/ai/command-options.js +15 -0
- package/dist/ai/command-options.js.map +1 -0
- package/dist/ai/config.d.ts +27 -0
- package/dist/ai/config.d.ts.map +1 -0
- package/dist/ai/config.js +89 -0
- package/dist/ai/config.js.map +1 -0
- package/dist/ai/parity.d.ts +13 -0
- package/dist/ai/parity.d.ts.map +1 -0
- package/dist/ai/parity.js +87 -0
- package/dist/ai/parity.js.map +1 -0
- package/dist/ai/parse-json-output.d.ts +5 -0
- package/dist/ai/parse-json-output.d.ts.map +1 -0
- package/dist/ai/parse-json-output.js +25 -0
- package/dist/ai/parse-json-output.js.map +1 -0
- package/dist/ai/pipeline.d.ts +20 -0
- package/dist/ai/pipeline.d.ts.map +1 -0
- package/dist/ai/pipeline.js +303 -0
- package/dist/ai/pipeline.js.map +1 -0
- package/dist/ai/prompts.d.ts +6 -0
- package/dist/ai/prompts.d.ts.map +1 -0
- package/dist/ai/prompts.js +49 -0
- package/dist/ai/prompts.js.map +1 -0
- package/dist/ai/providers.d.ts +63 -0
- package/dist/ai/providers.d.ts.map +1 -0
- package/dist/ai/providers.js +297 -0
- package/dist/ai/providers.js.map +1 -0
- package/dist/ai/refine-bridge.d.ts +5 -0
- package/dist/ai/refine-bridge.d.ts.map +1 -0
- package/dist/ai/refine-bridge.js +14 -0
- package/dist/ai/refine-bridge.js.map +1 -0
- package/dist/ai/registry.d.ts +12 -0
- package/dist/ai/registry.d.ts.map +1 -0
- package/dist/ai/registry.js +43 -0
- package/dist/ai/registry.js.map +1 -0
- package/dist/ai/resolve.d.ts +28 -0
- package/dist/ai/resolve.d.ts.map +1 -0
- package/dist/ai/resolve.js +83 -0
- package/dist/ai/resolve.js.map +1 -0
- package/dist/ai/schemas.d.ts +175 -0
- package/dist/ai/schemas.d.ts.map +1 -0
- package/dist/ai/schemas.js +199 -0
- package/dist/ai/schemas.js.map +1 -0
- package/dist/ai/types.d.ts +52 -0
- package/dist/ai/types.d.ts.map +1 -0
- package/dist/ai/types.js +8 -0
- package/dist/ai/types.js.map +1 -0
- package/dist/bin/dare.js +2 -0
- package/dist/bin/dare.js.map +1 -1
- package/dist/commands/__tests__/ai-command.test.d.ts +2 -0
- package/dist/commands/__tests__/ai-command.test.d.ts.map +1 -0
- package/dist/commands/__tests__/ai-command.test.js +68 -0
- package/dist/commands/__tests__/ai-command.test.js.map +1 -0
- package/dist/commands/__tests__/execute-agent.test.js +82 -0
- package/dist/commands/__tests__/execute-agent.test.js.map +1 -1
- package/dist/commands/ai.d.ts +3 -0
- package/dist/commands/ai.d.ts.map +1 -0
- package/dist/commands/ai.js +141 -0
- package/dist/commands/ai.js.map +1 -0
- package/dist/commands/blueprint.d.ts.map +1 -1
- package/dist/commands/blueprint.js +17 -3
- package/dist/commands/blueprint.js.map +1 -1
- package/dist/commands/design.d.ts.map +1 -1
- package/dist/commands/design.js +21 -2
- package/dist/commands/design.js.map +1 -1
- package/dist/commands/discover.d.ts.map +1 -1
- package/dist/commands/discover.js +9 -1
- package/dist/commands/discover.js.map +1 -1
- package/dist/commands/dna.d.ts.map +1 -1
- package/dist/commands/dna.js +23 -3
- package/dist/commands/dna.js.map +1 -1
- package/dist/commands/execute.d.ts +11 -0
- package/dist/commands/execute.d.ts.map +1 -1
- package/dist/commands/execute.js +111 -4
- package/dist/commands/execute.js.map +1 -1
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +1 -0
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/migrate.d.ts.map +1 -1
- package/dist/commands/migrate.js +14 -2
- package/dist/commands/migrate.js.map +1 -1
- package/dist/commands/patterns.d.ts.map +1 -1
- package/dist/commands/patterns.js +14 -2
- package/dist/commands/patterns.js.map +1 -1
- package/dist/commands/refine.d.ts.map +1 -1
- package/dist/commands/refine.js +23 -2
- package/dist/commands/refine.js.map +1 -1
- package/dist/commands/reverse.d.ts.map +1 -1
- package/dist/commands/reverse.js +28 -3
- package/dist/commands/reverse.js.map +1 -1
- package/dist/commands/review.d.ts.map +1 -1
- package/dist/commands/review.js +25 -3
- package/dist/commands/review.js.map +1 -1
- package/dist/core/types/project.d.ts +1 -1
- package/dist/core/types/project.d.ts.map +1 -1
- package/dist/dag-runner/run_dag.d.ts +1 -1
- package/dist/dag-runner/run_dag.d.ts.map +1 -1
- package/dist/exec/safe-spawn.d.ts.map +1 -1
- package/dist/exec/safe-spawn.js +6 -1
- package/dist/exec/safe-spawn.js.map +1 -1
- package/dist/skills/bundled.d.ts +5 -0
- package/dist/skills/bundled.d.ts.map +1 -0
- package/dist/skills/bundled.js +34 -0
- package/dist/skills/bundled.js.map +1 -0
- package/dist/skills/commands/add.d.ts +1 -3
- package/dist/skills/commands/add.d.ts.map +1 -1
- package/dist/skills/commands/add.js +20 -3
- package/dist/skills/commands/add.js.map +1 -1
- package/dist/skills/tests/bundled.spec.d.ts +2 -0
- package/dist/skills/tests/bundled.spec.d.ts.map +1 -0
- package/dist/skills/tests/bundled.spec.js +24 -0
- package/dist/skills/tests/bundled.spec.js.map +1 -0
- package/dist/types/UpdateManifest.types.d.ts +1 -1
- package/dist/types/UpdateManifest.types.d.ts.map +1 -1
- package/dist/utils/dag-converter.js +1 -1
- package/dist/utils/dag-converter.js.map +1 -1
- package/dist/utils/project-detector.d.ts +1 -0
- package/dist/utils/project-detector.d.ts.map +1 -1
- package/dist/utils/project-detector.js +8 -0
- package/dist/utils/project-detector.js.map +1 -1
- package/dist/utils/project-generator.d.ts +1 -1
- package/dist/utils/project-generator.d.ts.map +1 -1
- package/dist/utils/project-generator.js +23 -2
- package/dist/utils/project-generator.js.map +1 -1
- package/dist/utils/templates.d.ts +2 -0
- package/dist/utils/templates.d.ts.map +1 -1
- package/dist/utils/templates.js +74 -0
- package/dist/utils/templates.js.map +1 -1
- package/dist/verification/__tests__/safe-spawn.test.js +12 -0
- package/dist/verification/__tests__/safe-spawn.test.js.map +1 -1
- package/package.json +2 -1
- package/skills/dare-ax/generator.ts +325 -0
- package/skills/dare-ax/index.ts +19 -0
- package/skills/dare-ax/metrics.ts +352 -0
- package/skills/dare-ax/package-lock.json +1855 -0
- package/skills/dare-ax/package.json +50 -0
- package/skills/dare-ax/secret-detector.ts +123 -0
- package/skills/dare-ax/skill.yml +19 -0
- package/skills/dare-ax/templates/llms.txt.jinja2 +80 -0
- package/skills/dare-ax/tests/generator.spec.ts +193 -0
- package/skills/dare-ax/tests/metrics.spec.ts +394 -0
- package/skills/dare-ax/tests/validator.spec.ts +298 -0
- package/skills/dare-ax/tsconfig.json +18 -0
- package/skills/dare-ax/types.ts +79 -0
- package/skills/dare-ax/validator.ts +238 -0
- package/skills/dare-frontend-design/generator.ts +616 -0
- package/skills/dare-frontend-design/index.ts +25 -0
- package/skills/dare-frontend-design/linter.ts +227 -0
- package/skills/dare-frontend-design/metrics.ts +82 -0
- package/skills/dare-frontend-design/package-lock.json +1855 -0
- package/skills/dare-frontend-design/package.json +43 -0
- package/skills/dare-frontend-design/skill.yml +20 -0
- package/skills/dare-frontend-design/tests/frontend_design.spec.ts +435 -0
- package/skills/dare-frontend-design/tsconfig.json +18 -0
- package/skills/dare-frontend-design/types.ts +62 -0
- package/skills/dare-layered-design/generator.ts +740 -0
- package/skills/dare-layered-design/index.ts +17 -0
- package/skills/dare-layered-design/linter.ts +462 -0
- package/skills/dare-layered-design/metrics.ts +409 -0
- package/skills/dare-layered-design/package-lock.json +1855 -0
- package/skills/dare-layered-design/package.json +50 -0
- package/skills/dare-layered-design/skill.yml +35 -0
- package/skills/dare-layered-design/tests/generator.spec.ts +156 -0
- package/skills/dare-layered-design/tests/linter.spec.ts +255 -0
- package/skills/dare-layered-design/tests/metrics.spec.ts +286 -0
- package/skills/dare-layered-design/tsconfig.json +18 -0
- package/skills/dare-layered-design/types.ts +48 -0
- package/skills/dare-llm-integration/cache/llm_cache.ts +122 -0
- package/skills/dare-llm-integration/index.ts +49 -0
- package/skills/dare-llm-integration/metrics.ts +107 -0
- package/skills/dare-llm-integration/package-lock.json +1855 -0
- package/skills/dare-llm-integration/package.json +49 -0
- package/skills/dare-llm-integration/prompts/prompt_loader.ts +258 -0
- package/skills/dare-llm-integration/providers/anthropic_provider.ts +159 -0
- package/skills/dare-llm-integration/providers/dummy_provider.ts +113 -0
- package/skills/dare-llm-integration/providers/llm_provider.ts +6 -0
- package/skills/dare-llm-integration/providers/openai_provider.ts +215 -0
- package/skills/dare-llm-integration/rate_limit/token_bucket.ts +86 -0
- package/skills/dare-llm-integration/skill.yml +23 -0
- package/skills/dare-llm-integration/tests/fixtures/greet_v1.jinja2 +1 -0
- package/skills/dare-llm-integration/tests/fixtures/summarize_v1.jinja2 +1 -0
- package/skills/dare-llm-integration/tests/fixtures/summarize_v2.jinja2 +3 -0
- package/skills/dare-llm-integration/tests/llm_integration.spec.ts +657 -0
- package/skills/dare-llm-integration/tsconfig.json +23 -0
- package/skills/dare-llm-integration/types.ts +91 -0
- package/skills/dare-llm-integration/validators/output_validator.ts +200 -0
- package/skills/dare-quality-telemetry/collect.ts +134 -0
- package/skills/dare-quality-telemetry/collectors/dare_ax_collector.ts +301 -0
- package/skills/dare-quality-telemetry/collectors/dare_layered_design_collector.ts +406 -0
- package/skills/dare-quality-telemetry/collectors/index.ts +24 -0
- package/skills/dare-quality-telemetry/github_actions_template.ts +25 -0
- package/skills/dare-quality-telemetry/index.ts +18 -0
- package/skills/dare-quality-telemetry/metrics.ts +137 -0
- package/skills/dare-quality-telemetry/package-lock.json +1855 -0
- package/skills/dare-quality-telemetry/package.json +48 -0
- package/skills/dare-quality-telemetry/regression.ts +60 -0
- package/skills/dare-quality-telemetry/reporter.ts +132 -0
- package/skills/dare-quality-telemetry/skill.yml +18 -0
- package/skills/dare-quality-telemetry/tests/quality_telemetry.spec.ts +885 -0
- package/skills/dare-quality-telemetry/tsconfig.json +19 -0
- package/skills/dare-quality-telemetry/types.ts +41 -0
- package/skills/dare-realtime/event_registry.ts +101 -0
- package/skills/dare-realtime/index.ts +30 -0
- package/skills/dare-realtime/metrics.ts +84 -0
- package/skills/dare-realtime/package-lock.json +1855 -0
- package/skills/dare-realtime/package.json +43 -0
- package/skills/dare-realtime/reconnect_strategy.ts +85 -0
- package/skills/dare-realtime/schema_validator.ts +80 -0
- package/skills/dare-realtime/skill.yml +21 -0
- package/skills/dare-realtime/subscription_manager.ts +106 -0
- package/skills/dare-realtime/tests/realtime.spec.ts +482 -0
- package/skills/dare-realtime/tsconfig.json +18 -0
- package/skills/dare-realtime/types.ts +51 -0
- package/templates/ide/antigravity/.agents/skills/dare-ai/SKILL.md +17 -0
- package/templates/ide/antigravity/.agents/skills/dare-blueprint/SKILL.md +2 -0
- package/templates/ide/antigravity/.agents/skills/dare-design/SKILL.md +2 -0
- package/templates/ide/antigravity/.agents/skills/dare-dna/SKILL.md +3 -0
- package/templates/ide/antigravity/.agents/skills/dare-migrate/SKILL.md +3 -0
- package/templates/ide/antigravity/.agents/skills/dare-patterns/SKILL.md +3 -0
- package/templates/ide/antigravity/.agents/skills/dare-refine/SKILL.md +3 -0
- package/templates/ide/antigravity/.agents/skills/dare-reverse/SKILL.md +3 -0
- package/templates/ide/antigravity/.agents/skills/dare-review/SKILL.md +3 -0
- package/templates/ide/claude/.claude/commands/dare-ai.md +17 -0
- package/templates/ide/claude/.claude/commands/dare-blueprint.md +2 -0
- package/templates/ide/claude/.claude/commands/dare-design.md +2 -0
- package/templates/ide/claude/.claude/commands/dare-dna.md +2 -0
- package/templates/ide/claude/.claude/commands/dare-migrate.md +2 -0
- package/templates/ide/claude/.claude/commands/dare-patterns.md +3 -0
- package/templates/ide/claude/.claude/commands/dare-refine.md +3 -0
- package/templates/ide/claude/.claude/commands/dare-reverse.md +2 -0
- package/templates/ide/claude/.claude/commands/dare-review.md +3 -0
- package/templates/ide/cursor/.cursor/commands/dare-ai.md +17 -0
- package/templates/ide/cursor/.cursor/commands/dare-blueprint.md +3 -0
- package/templates/ide/cursor/.cursor/commands/dare-design.md +3 -0
- package/templates/ide/cursor/.cursor/commands/dare-dna.md +2 -0
- package/templates/ide/cursor/.cursor/commands/dare-migrate.md +2 -0
- package/templates/ide/cursor/.cursor/commands/dare-patterns.md +3 -0
- package/templates/ide/cursor/.cursor/commands/dare-refine.md +3 -0
- package/templates/ide/cursor/.cursor/commands/dare-reverse.md +2 -0
- package/templates/ide/cursor/.cursor/commands/dare-review.md +3 -0
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* dare-llm-integration — OpenAIProvider
|
|
3
|
+
* Real implementation using fetch (no external SDK).
|
|
4
|
+
* License: MIT
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import type {
|
|
8
|
+
LLMProvider,
|
|
9
|
+
CompletionRequest,
|
|
10
|
+
CompletionResponse,
|
|
11
|
+
EmbedRequest,
|
|
12
|
+
EmbeddingResponse,
|
|
13
|
+
} from '../types.js';
|
|
14
|
+
import { LLMCache } from '../cache/llm_cache.js';
|
|
15
|
+
import { TokenBucket } from '../rate_limit/token_bucket.js';
|
|
16
|
+
|
|
17
|
+
export interface OpenAIProviderConfig {
|
|
18
|
+
apiKey: string;
|
|
19
|
+
cache?: LLMCache;
|
|
20
|
+
rateLimiter?: TokenBucket;
|
|
21
|
+
defaultCacheTtlMs?: number;
|
|
22
|
+
defaultTimeoutMs?: number;
|
|
23
|
+
onTokenUsage?: (model: string, input: number, output: number) => void;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export class OpenAIProvider implements LLMProvider {
|
|
27
|
+
private readonly apiKey: string;
|
|
28
|
+
private readonly cache: LLMCache | null;
|
|
29
|
+
private readonly rateLimiter: TokenBucket | null;
|
|
30
|
+
private readonly defaultCacheTtlMs: number;
|
|
31
|
+
private readonly defaultTimeoutMs: number;
|
|
32
|
+
private readonly onTokenUsage: ((model: string, input: number, output: number) => void) | null;
|
|
33
|
+
|
|
34
|
+
constructor(config: OpenAIProviderConfig) {
|
|
35
|
+
this.apiKey = config.apiKey;
|
|
36
|
+
this.cache = config.cache ?? null;
|
|
37
|
+
this.rateLimiter = config.rateLimiter ?? null;
|
|
38
|
+
this.defaultCacheTtlMs = config.defaultCacheTtlMs ?? 24 * 60 * 60 * 1000; // 24h
|
|
39
|
+
this.defaultTimeoutMs = config.defaultTimeoutMs ?? 30_000;
|
|
40
|
+
this.onTokenUsage = config.onTokenUsage ?? null;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
async complete(request: CompletionRequest): Promise<CompletionResponse> {
|
|
44
|
+
const cacheKey = this.buildCacheKey('complete', request.model, request.prompt);
|
|
45
|
+
|
|
46
|
+
// Check cache
|
|
47
|
+
if (this.cache) {
|
|
48
|
+
const cached = this.cache.get(cacheKey);
|
|
49
|
+
if (cached) {
|
|
50
|
+
return cached.value as CompletionResponse;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// Rate limit
|
|
55
|
+
if (this.rateLimiter) {
|
|
56
|
+
await this.rateLimiter.acquire();
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const start = Date.now();
|
|
60
|
+
const response = await this.callCompletionAPI(request);
|
|
61
|
+
const latencyMs = Date.now() - start;
|
|
62
|
+
|
|
63
|
+
const result: CompletionResponse = {
|
|
64
|
+
...response,
|
|
65
|
+
cached: false,
|
|
66
|
+
latencyMs,
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
// Log token usage
|
|
70
|
+
if (this.onTokenUsage) {
|
|
71
|
+
this.onTokenUsage(request.model, result.tokensUsed.input, result.tokensUsed.output);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// Store in cache
|
|
75
|
+
if (this.cache) {
|
|
76
|
+
this.cache.set(cacheKey, result, this.defaultCacheTtlMs);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
return result;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
async embed(request: EmbedRequest): Promise<EmbeddingResponse> {
|
|
83
|
+
const inputStr = Array.isArray(request.input) ? request.input.join('|') : request.input;
|
|
84
|
+
const cacheKey = this.buildCacheKey('embed', request.model, inputStr);
|
|
85
|
+
|
|
86
|
+
if (this.cache) {
|
|
87
|
+
const cached = this.cache.get(cacheKey);
|
|
88
|
+
if (cached) {
|
|
89
|
+
return cached.value as EmbeddingResponse;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
if (this.rateLimiter) {
|
|
94
|
+
await this.rateLimiter.acquire();
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
const result = await this.callEmbedAPI(request);
|
|
98
|
+
|
|
99
|
+
if (this.cache) {
|
|
100
|
+
this.cache.set(cacheKey, result, this.defaultCacheTtlMs);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
return result;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
private buildCacheKey(op: string, model: string, content: string): string {
|
|
107
|
+
// Deterministic hash-like key using a simple digest
|
|
108
|
+
const combined = `${op}:${model}:${content}`;
|
|
109
|
+
let hash = 0;
|
|
110
|
+
for (let i = 0; i < combined.length; i++) {
|
|
111
|
+
const char = combined.charCodeAt(i);
|
|
112
|
+
hash = ((hash << 5) - hash) + char;
|
|
113
|
+
hash |= 0;
|
|
114
|
+
}
|
|
115
|
+
return `llm:${op}:${model}:${Math.abs(hash).toString(16)}`;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
private async callCompletionAPI(request: CompletionRequest): Promise<CompletionResponse> {
|
|
119
|
+
const timeoutMs = request.timeoutMs ?? this.defaultTimeoutMs;
|
|
120
|
+
const controller = new AbortController();
|
|
121
|
+
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
122
|
+
|
|
123
|
+
const messages: Array<{ role: string; content: string }> = [];
|
|
124
|
+
if (request.systemPrompt) {
|
|
125
|
+
messages.push({ role: 'system', content: request.systemPrompt });
|
|
126
|
+
}
|
|
127
|
+
messages.push({ role: 'user', content: request.prompt });
|
|
128
|
+
|
|
129
|
+
let data: unknown;
|
|
130
|
+
try {
|
|
131
|
+
const response = await fetch('https://api.openai.com/v1/chat/completions', {
|
|
132
|
+
method: 'POST',
|
|
133
|
+
headers: {
|
|
134
|
+
'Content-Type': 'application/json',
|
|
135
|
+
Authorization: `Bearer ${this.apiKey}`,
|
|
136
|
+
},
|
|
137
|
+
body: JSON.stringify({
|
|
138
|
+
model: request.model,
|
|
139
|
+
messages,
|
|
140
|
+
temperature: request.temperature ?? 0.7,
|
|
141
|
+
max_tokens: request.maxTokens,
|
|
142
|
+
}),
|
|
143
|
+
signal: controller.signal,
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
if (!response.ok) {
|
|
147
|
+
throw new Error(`OpenAI API error: ${response.status} ${response.statusText}`);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
data = await response.json();
|
|
151
|
+
} finally {
|
|
152
|
+
clearTimeout(timer);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
const d = data as {
|
|
156
|
+
choices: Array<{ message: { content: string } }>;
|
|
157
|
+
usage: { prompt_tokens: number; completion_tokens: number; total_tokens: number };
|
|
158
|
+
model: string;
|
|
159
|
+
};
|
|
160
|
+
|
|
161
|
+
return {
|
|
162
|
+
text: d.choices[0].message.content,
|
|
163
|
+
tokensUsed: {
|
|
164
|
+
input: d.usage.prompt_tokens,
|
|
165
|
+
output: d.usage.completion_tokens,
|
|
166
|
+
total: d.usage.total_tokens,
|
|
167
|
+
},
|
|
168
|
+
cached: false,
|
|
169
|
+
model: d.model,
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
private async callEmbedAPI(request: EmbedRequest): Promise<EmbeddingResponse> {
|
|
174
|
+
const timeoutMs = request.timeoutMs ?? this.defaultTimeoutMs;
|
|
175
|
+
const controller = new AbortController();
|
|
176
|
+
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
177
|
+
|
|
178
|
+
let data: unknown;
|
|
179
|
+
try {
|
|
180
|
+
const response = await fetch('https://api.openai.com/v1/embeddings', {
|
|
181
|
+
method: 'POST',
|
|
182
|
+
headers: {
|
|
183
|
+
'Content-Type': 'application/json',
|
|
184
|
+
Authorization: `Bearer ${this.apiKey}`,
|
|
185
|
+
},
|
|
186
|
+
body: JSON.stringify({
|
|
187
|
+
model: request.model,
|
|
188
|
+
input: request.input,
|
|
189
|
+
}),
|
|
190
|
+
signal: controller.signal,
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
if (!response.ok) {
|
|
194
|
+
throw new Error(`OpenAI API error: ${response.status} ${response.statusText}`);
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
data = await response.json();
|
|
198
|
+
} finally {
|
|
199
|
+
clearTimeout(timer);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
const d = data as {
|
|
203
|
+
data: Array<{ embedding: number[] }>;
|
|
204
|
+
usage: { total_tokens: number };
|
|
205
|
+
model: string;
|
|
206
|
+
};
|
|
207
|
+
|
|
208
|
+
return {
|
|
209
|
+
embeddings: d.data.map((item) => item.embedding),
|
|
210
|
+
tokensUsed: d.usage.total_tokens,
|
|
211
|
+
model: d.model,
|
|
212
|
+
cached: false,
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* dare-llm-integration — TokenBucket rate limiter
|
|
3
|
+
* Implements a sliding token bucket for controlling request rate.
|
|
4
|
+
* License: MIT
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
export interface TokenBucketConfig {
|
|
8
|
+
/** Requests per second */
|
|
9
|
+
rps: number;
|
|
10
|
+
/** Maximum burst capacity. Defaults to rps. */
|
|
11
|
+
maxBurst?: number;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export class TokenBucket {
|
|
15
|
+
private readonly rps: number;
|
|
16
|
+
private readonly maxBurst: number;
|
|
17
|
+
/** Interval in milliseconds between tokens refilling */
|
|
18
|
+
private readonly refillIntervalMs: number;
|
|
19
|
+
private tokens: number;
|
|
20
|
+
private lastRefillTime: number;
|
|
21
|
+
|
|
22
|
+
constructor(config: TokenBucketConfig) {
|
|
23
|
+
if (config.rps <= 0) {
|
|
24
|
+
throw new Error('TokenBucket: rps must be > 0');
|
|
25
|
+
}
|
|
26
|
+
this.rps = config.rps;
|
|
27
|
+
this.maxBurst = config.maxBurst ?? config.rps;
|
|
28
|
+
this.refillIntervalMs = 1000 / config.rps;
|
|
29
|
+
this.tokens = this.maxBurst;
|
|
30
|
+
this.lastRefillTime = Date.now();
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Blocking acquire: waits until a token is available, then consumes it.
|
|
35
|
+
*/
|
|
36
|
+
async acquire(): Promise<void> {
|
|
37
|
+
while (!this.tryAcquire()) {
|
|
38
|
+
// Calculate wait time until next token
|
|
39
|
+
const now = Date.now();
|
|
40
|
+
const elapsed = now - this.lastRefillTime;
|
|
41
|
+
const waitMs = Math.max(1, this.refillIntervalMs - elapsed);
|
|
42
|
+
await delay(waitMs);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Non-blocking attempt: returns true if a token was consumed, false otherwise.
|
|
48
|
+
*/
|
|
49
|
+
tryAcquire(): boolean {
|
|
50
|
+
this.refill();
|
|
51
|
+
if (this.tokens >= 1) {
|
|
52
|
+
this.tokens -= 1;
|
|
53
|
+
return true;
|
|
54
|
+
}
|
|
55
|
+
return false;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Current available tokens (may be fractional after partial refill).
|
|
60
|
+
*/
|
|
61
|
+
get availableTokens(): number {
|
|
62
|
+
this.refill();
|
|
63
|
+
return this.tokens;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Configured requests per second.
|
|
68
|
+
*/
|
|
69
|
+
get requestsPerSecond(): number {
|
|
70
|
+
return this.rps;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
private refill(): void {
|
|
74
|
+
const now = Date.now();
|
|
75
|
+
const elapsed = now - this.lastRefillTime;
|
|
76
|
+
if (elapsed > 0) {
|
|
77
|
+
const newTokens = (elapsed / 1000) * this.rps;
|
|
78
|
+
this.tokens = Math.min(this.tokens + newTokens, this.maxBurst);
|
|
79
|
+
this.lastRefillTime = now;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function delay(ms: number): Promise<void> {
|
|
85
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
86
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
name: dare-llm-integration
|
|
2
|
+
version: 1.0.0
|
|
3
|
+
license: MIT
|
|
4
|
+
description: >
|
|
5
|
+
Skill transversal DARE para integração com LLMs (Large Language Models).
|
|
6
|
+
Fornece LLMProvider abstraction, caching em memória com TTL, rate limiting
|
|
7
|
+
via token bucket, prompt templates versionados e validação de output via JSON Schema.
|
|
8
|
+
author: Dewtech Technologies
|
|
9
|
+
metrics:
|
|
10
|
+
- id: M-01
|
|
11
|
+
description: 100% de chamadas LLM via LLMProvider injetado
|
|
12
|
+
- id: M-02
|
|
13
|
+
description: 100% de responses LLM cacheadas (cache configurado)
|
|
14
|
+
- id: M-03
|
|
15
|
+
description: 100% de requests LLM com rate limit configurado
|
|
16
|
+
- id: M-04
|
|
17
|
+
description: 100% de respostas LLM validadas contra schema antes usar
|
|
18
|
+
antipatterns:
|
|
19
|
+
- AP-01: LLM SDK direto em Handler
|
|
20
|
+
- AP-02: Sem cache
|
|
21
|
+
- AP-03: Prompt em código
|
|
22
|
+
- AP-04: User input direto em prompt
|
|
23
|
+
- AP-05: Trusting LLM output sem validação
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Hello {{ name }}, welcome to {{ service }}!
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Summarize the following text in 2-3 sentences: {{ text }}
|