compact-agent 1.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.
- package/README.md +394 -0
- package/bin/anycode.js +2 -0
- package/bin/crowcoder.js +19 -0
- package/bin/ecc-hooks.cjs +138 -0
- package/dist/agents.d.ts +17 -0
- package/dist/agents.js +1603 -0
- package/dist/agents.js.map +1 -0
- package/dist/api.d.ts +16 -0
- package/dist/api.js +115 -0
- package/dist/api.js.map +1 -0
- package/dist/autonomous-loops.d.ts +108 -0
- package/dist/autonomous-loops.js +526 -0
- package/dist/autonomous-loops.js.map +1 -0
- package/dist/codemaps.d.ts +53 -0
- package/dist/codemaps.js +325 -0
- package/dist/codemaps.js.map +1 -0
- package/dist/compaction.d.ts +30 -0
- package/dist/compaction.js +125 -0
- package/dist/compaction.js.map +1 -0
- package/dist/config.d.ts +5 -0
- package/dist/config.js +79 -0
- package/dist/config.js.map +1 -0
- package/dist/content-engine.d.ts +97 -0
- package/dist/content-engine.js +721 -0
- package/dist/content-engine.js.map +1 -0
- package/dist/cost-tracker.d.ts +49 -0
- package/dist/cost-tracker.js +150 -0
- package/dist/cost-tracker.js.map +1 -0
- package/dist/counter-button.d.ts +35 -0
- package/dist/counter-button.js +48 -0
- package/dist/counter-button.js.map +1 -0
- package/dist/counter.d.ts +21 -0
- package/dist/counter.js +31 -0
- package/dist/counter.js.map +1 -0
- package/dist/coverage.d.ts +23 -0
- package/dist/coverage.js +215 -0
- package/dist/coverage.js.map +1 -0
- package/dist/docs-sync.d.ts +23 -0
- package/dist/docs-sync.js +266 -0
- package/dist/docs-sync.js.map +1 -0
- package/dist/ecc.d.ts +41 -0
- package/dist/ecc.js +644 -0
- package/dist/ecc.js.map +1 -0
- package/dist/evaluation.d.ts +24 -0
- package/dist/evaluation.js +412 -0
- package/dist/evaluation.js.map +1 -0
- package/dist/export.d.ts +22 -0
- package/dist/export.js +109 -0
- package/dist/export.js.map +1 -0
- package/dist/git-workflow.d.ts +22 -0
- package/dist/git-workflow.js +197 -0
- package/dist/git-workflow.js.map +1 -0
- package/dist/hook-controls.d.ts +34 -0
- package/dist/hook-controls.js +90 -0
- package/dist/hook-controls.js.map +1 -0
- package/dist/hooks.d.ts +30 -0
- package/dist/hooks.js +130 -0
- package/dist/hooks.js.map +1 -0
- package/dist/html-parser.d.ts +18 -0
- package/dist/html-parser.js +101 -0
- package/dist/html-parser.js.map +1 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.js +1230 -0
- package/dist/index.js.map +1 -0
- package/dist/learning.d.ts +35 -0
- package/dist/learning.js +238 -0
- package/dist/learning.js.map +1 -0
- package/dist/login.d.ts +37 -0
- package/dist/login.js +191 -0
- package/dist/login.js.map +1 -0
- package/dist/memory.d.ts +39 -0
- package/dist/memory.js +183 -0
- package/dist/memory.js.map +1 -0
- package/dist/model-router.d.ts +23 -0
- package/dist/model-router.js +145 -0
- package/dist/model-router.js.map +1 -0
- package/dist/modes.d.ts +17 -0
- package/dist/modes.js +217 -0
- package/dist/modes.js.map +1 -0
- package/dist/orchestration.d.ts +37 -0
- package/dist/orchestration.js +139 -0
- package/dist/orchestration.js.map +1 -0
- package/dist/package-detect.d.ts +36 -0
- package/dist/package-detect.js +529 -0
- package/dist/package-detect.js.map +1 -0
- package/dist/permissions.d.ts +25 -0
- package/dist/permissions.js +50 -0
- package/dist/permissions.js.map +1 -0
- package/dist/pm2-manager.d.ts +40 -0
- package/dist/pm2-manager.js +127 -0
- package/dist/pm2-manager.js.map +1 -0
- package/dist/query.d.ts +15 -0
- package/dist/query.js +278 -0
- package/dist/query.js.map +1 -0
- package/dist/refactor.d.ts +22 -0
- package/dist/refactor.js +226 -0
- package/dist/refactor.js.map +1 -0
- package/dist/retry.d.ts +20 -0
- package/dist/retry.js +88 -0
- package/dist/retry.js.map +1 -0
- package/dist/rules.d.ts +34 -0
- package/dist/rules.js +942 -0
- package/dist/rules.js.map +1 -0
- package/dist/schema.d.ts +23 -0
- package/dist/schema.js +12 -0
- package/dist/schema.js.map +1 -0
- package/dist/search-first.d.ts +17 -0
- package/dist/search-first.js +301 -0
- package/dist/search-first.js.map +1 -0
- package/dist/security.d.ts +10 -0
- package/dist/security.js +145 -0
- package/dist/security.js.map +1 -0
- package/dist/sessions.d.ts +21 -0
- package/dist/sessions.js +112 -0
- package/dist/sessions.js.map +1 -0
- package/dist/skill-create.d.ts +38 -0
- package/dist/skill-create.js +389 -0
- package/dist/skill-create.js.map +1 -0
- package/dist/skills.d.ts +34 -0
- package/dist/skills.js +161 -0
- package/dist/skills.js.map +1 -0
- package/dist/strategic-compaction.d.ts +24 -0
- package/dist/strategic-compaction.js +144 -0
- package/dist/strategic-compaction.js.map +1 -0
- package/dist/system-prompt.d.ts +3 -0
- package/dist/system-prompt.js +101 -0
- package/dist/system-prompt.js.map +1 -0
- package/dist/theme.d.ts +60 -0
- package/dist/theme.js +220 -0
- package/dist/theme.js.map +1 -0
- package/dist/tools/bash.d.ts +2 -0
- package/dist/tools/bash.js +49 -0
- package/dist/tools/bash.js.map +1 -0
- package/dist/tools/edit.d.ts +2 -0
- package/dist/tools/edit.js +76 -0
- package/dist/tools/edit.js.map +1 -0
- package/dist/tools/glob.d.ts +2 -0
- package/dist/tools/glob.js +54 -0
- package/dist/tools/glob.js.map +1 -0
- package/dist/tools/grep.d.ts +2 -0
- package/dist/tools/grep.js +64 -0
- package/dist/tools/grep.js.map +1 -0
- package/dist/tools/index.d.ts +5 -0
- package/dist/tools/index.js +27 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/list-dir.d.ts +2 -0
- package/dist/tools/list-dir.js +51 -0
- package/dist/tools/list-dir.js.map +1 -0
- package/dist/tools/read.d.ts +2 -0
- package/dist/tools/read.js +56 -0
- package/dist/tools/read.js.map +1 -0
- package/dist/tools/types.d.ts +45 -0
- package/dist/tools/types.js +2 -0
- package/dist/tools/types.js.map +1 -0
- package/dist/tools/web-fetch.d.ts +2 -0
- package/dist/tools/web-fetch.js +41 -0
- package/dist/tools/web-fetch.js.map +1 -0
- package/dist/tools/web-search.d.ts +27 -0
- package/dist/tools/web-search.js +139 -0
- package/dist/tools/web-search.js.map +1 -0
- package/dist/tools/write.d.ts +2 -0
- package/dist/tools/write.js +36 -0
- package/dist/tools/write.js.map +1 -0
- package/dist/types.d.ts +28 -0
- package/dist/types.js +57 -0
- package/dist/types.js.map +1 -0
- package/dist/users.d.ts +51 -0
- package/dist/users.js +193 -0
- package/dist/users.js.map +1 -0
- package/dist/verification.d.ts +73 -0
- package/dist/verification.js +269 -0
- package/dist/verification.js.map +1 -0
- package/dist/walkthrough.d.ts +10 -0
- package/dist/walkthrough.js +121 -0
- package/dist/walkthrough.js.map +1 -0
- package/package.json +58 -0
- package/resources/ecc/agents/architect.json +16 -0
- package/resources/ecc/agents/architect.md +212 -0
- package/resources/ecc/agents/build-error-resolver.json +17 -0
- package/resources/ecc/agents/build-error-resolver.md +116 -0
- package/resources/ecc/agents/chief-of-staff.json +17 -0
- package/resources/ecc/agents/chief-of-staff.md +153 -0
- package/resources/ecc/agents/code-reviewer.json +16 -0
- package/resources/ecc/agents/code-reviewer.md +238 -0
- package/resources/ecc/agents/database-reviewer.json +16 -0
- package/resources/ecc/agents/database-reviewer.md +92 -0
- package/resources/ecc/agents/doc-updater.json +16 -0
- package/resources/ecc/agents/doc-updater.md +108 -0
- package/resources/ecc/agents/e2e-runner.json +17 -0
- package/resources/ecc/agents/e2e-runner.md +109 -0
- package/resources/ecc/agents/go-build-resolver.json +17 -0
- package/resources/ecc/agents/go-build-resolver.md +96 -0
- package/resources/ecc/agents/go-reviewer.json +16 -0
- package/resources/ecc/agents/go-reviewer.md +77 -0
- package/resources/ecc/agents/harness-optimizer.json +15 -0
- package/resources/ecc/agents/harness-optimizer.md +34 -0
- package/resources/ecc/agents/loop-operator.json +16 -0
- package/resources/ecc/agents/loop-operator.md +36 -0
- package/resources/ecc/agents/planner.json +15 -0
- package/resources/ecc/agents/planner.md +212 -0
- package/resources/ecc/agents/python-reviewer.json +16 -0
- package/resources/ecc/agents/python-reviewer.md +99 -0
- package/resources/ecc/agents/refactor-cleaner.json +17 -0
- package/resources/ecc/agents/refactor-cleaner.md +87 -0
- package/resources/ecc/agents/security-reviewer.json +16 -0
- package/resources/ecc/agents/security-reviewer.md +109 -0
- package/resources/ecc/agents/tdd-guide.json +17 -0
- package/resources/ecc/agents/tdd-guide.md +93 -0
- package/resources/ecc/commands/add-language-rules.md +39 -0
- package/resources/ecc/commands/database-migration.md +36 -0
- package/resources/ecc/commands/feature-development.md +38 -0
- package/resources/ecc/prompts/build-fix.prompt.md +47 -0
- package/resources/ecc/prompts/code-review.prompt.md +56 -0
- package/resources/ecc/prompts/plan.prompt.md +52 -0
- package/resources/ecc/prompts/refactor.prompt.md +50 -0
- package/resources/ecc/prompts/security-review.prompt.md +70 -0
- package/resources/ecc/prompts/tdd.prompt.md +47 -0
- package/resources/ecc/rules/common-agents.md +53 -0
- package/resources/ecc/rules/common-coding-style.md +52 -0
- package/resources/ecc/rules/common-development-workflow.md +33 -0
- package/resources/ecc/rules/common-git-workflow.md +28 -0
- package/resources/ecc/rules/common-hooks.md +34 -0
- package/resources/ecc/rules/common-patterns.md +35 -0
- package/resources/ecc/rules/common-performance.md +59 -0
- package/resources/ecc/rules/common-security.md +33 -0
- package/resources/ecc/rules/common-testing.md +33 -0
- package/resources/ecc/rules/golang-coding-style.md +31 -0
- package/resources/ecc/rules/golang-hooks.md +16 -0
- package/resources/ecc/rules/golang-patterns.md +44 -0
- package/resources/ecc/rules/golang-security.md +33 -0
- package/resources/ecc/rules/golang-testing.md +30 -0
- package/resources/ecc/rules/kotlin-coding-style.md +39 -0
- package/resources/ecc/rules/kotlin-hooks.md +16 -0
- package/resources/ecc/rules/kotlin-patterns.md +50 -0
- package/resources/ecc/rules/kotlin-security.md +58 -0
- package/resources/ecc/rules/kotlin-testing.md +38 -0
- package/resources/ecc/rules/php-coding-style.md +25 -0
- package/resources/ecc/rules/php-hooks.md +21 -0
- package/resources/ecc/rules/php-patterns.md +23 -0
- package/resources/ecc/rules/php-security.md +24 -0
- package/resources/ecc/rules/php-testing.md +26 -0
- package/resources/ecc/rules/python-coding-style.md +42 -0
- package/resources/ecc/rules/python-hooks.md +19 -0
- package/resources/ecc/rules/python-patterns.md +39 -0
- package/resources/ecc/rules/python-security.md +30 -0
- package/resources/ecc/rules/python-testing.md +38 -0
- package/resources/ecc/rules/swift-coding-style.md +47 -0
- package/resources/ecc/rules/swift-hooks.md +20 -0
- package/resources/ecc/rules/swift-patterns.md +66 -0
- package/resources/ecc/rules/swift-security.md +33 -0
- package/resources/ecc/rules/swift-testing.md +45 -0
- package/resources/ecc/rules/typescript-coding-style.md +63 -0
- package/resources/ecc/rules/typescript-hooks.md +20 -0
- package/resources/ecc/rules/typescript-patterns.md +50 -0
- package/resources/ecc/rules/typescript-security.md +26 -0
- package/resources/ecc/rules/typescript-testing.md +16 -0
- package/resources/ecc/skills/agent-introspection-debugging/SKILL.md +152 -0
- package/resources/ecc/skills/agent-introspection-debugging/agents/openai.yaml +7 -0
- package/resources/ecc/skills/agent-sort/SKILL.md +214 -0
- package/resources/ecc/skills/agent-sort/agents/openai.yaml +7 -0
- package/resources/ecc/skills/api-design/SKILL.md +522 -0
- package/resources/ecc/skills/api-design/agents/openai.yaml +7 -0
- package/resources/ecc/skills/article-writing/SKILL.md +78 -0
- package/resources/ecc/skills/article-writing/agents/openai.yaml +7 -0
- package/resources/ecc/skills/backend-patterns/SKILL.md +597 -0
- package/resources/ecc/skills/backend-patterns/agents/openai.yaml +7 -0
- package/resources/ecc/skills/brand-voice/SKILL.md +96 -0
- package/resources/ecc/skills/brand-voice/agents/openai.yaml +7 -0
- package/resources/ecc/skills/brand-voice/references/voice-profile-schema.md +55 -0
- package/resources/ecc/skills/bun-runtime/SKILL.md +83 -0
- package/resources/ecc/skills/bun-runtime/agents/openai.yaml +7 -0
- package/resources/ecc/skills/coding-standards/SKILL.md +548 -0
- package/resources/ecc/skills/coding-standards/agents/openai.yaml +7 -0
- package/resources/ecc/skills/content-engine/SKILL.md +130 -0
- package/resources/ecc/skills/content-engine/agents/openai.yaml +7 -0
- package/resources/ecc/skills/crosspost/SKILL.md +110 -0
- package/resources/ecc/skills/crosspost/agents/openai.yaml +7 -0
- package/resources/ecc/skills/deep-research/SKILL.md +154 -0
- package/resources/ecc/skills/deep-research/agents/openai.yaml +7 -0
- package/resources/ecc/skills/dmux-workflows/SKILL.md +143 -0
- package/resources/ecc/skills/dmux-workflows/agents/openai.yaml +7 -0
- package/resources/ecc/skills/documentation-lookup/SKILL.md +89 -0
- package/resources/ecc/skills/documentation-lookup/agents/openai.yaml +7 -0
- package/resources/ecc/skills/e2e-testing/SKILL.md +325 -0
- package/resources/ecc/skills/e2e-testing/agents/openai.yaml +7 -0
- package/resources/ecc/skills/eval-harness/SKILL.md +235 -0
- package/resources/ecc/skills/eval-harness/agents/openai.yaml +7 -0
- package/resources/ecc/skills/everything-claude-code/SKILL.md +442 -0
- package/resources/ecc/skills/everything-claude-code/agents/openai.yaml +7 -0
- package/resources/ecc/skills/exa-search/SKILL.md +169 -0
- package/resources/ecc/skills/exa-search/agents/openai.yaml +7 -0
- package/resources/ecc/skills/fal-ai-media/SKILL.md +276 -0
- package/resources/ecc/skills/fal-ai-media/agents/openai.yaml +7 -0
- package/resources/ecc/skills/frontend-patterns/SKILL.md +647 -0
- package/resources/ecc/skills/frontend-patterns/agents/openai.yaml +7 -0
- package/resources/ecc/skills/frontend-slides/SKILL.md +183 -0
- package/resources/ecc/skills/frontend-slides/STYLE_PRESETS.md +330 -0
- package/resources/ecc/skills/frontend-slides/agents/openai.yaml +7 -0
- package/resources/ecc/skills/investor-materials/SKILL.md +95 -0
- package/resources/ecc/skills/investor-materials/agents/openai.yaml +7 -0
- package/resources/ecc/skills/investor-outreach/SKILL.md +90 -0
- package/resources/ecc/skills/investor-outreach/agents/openai.yaml +7 -0
- package/resources/ecc/skills/market-research/SKILL.md +74 -0
- package/resources/ecc/skills/market-research/agents/openai.yaml +7 -0
- package/resources/ecc/skills/mcp-server-patterns/SKILL.md +66 -0
- package/resources/ecc/skills/mcp-server-patterns/agents/openai.yaml +7 -0
- package/resources/ecc/skills/mle-workflow/SKILL.md +346 -0
- package/resources/ecc/skills/mle-workflow/agents/openai.yaml +7 -0
- package/resources/ecc/skills/nextjs-turbopack/SKILL.md +43 -0
- package/resources/ecc/skills/nextjs-turbopack/agents/openai.yaml +7 -0
- package/resources/ecc/skills/product-capability/SKILL.md +140 -0
- package/resources/ecc/skills/product-capability/agents/openai.yaml +7 -0
- package/resources/ecc/skills/security-review/SKILL.md +494 -0
- package/resources/ecc/skills/security-review/agents/openai.yaml +7 -0
- package/resources/ecc/skills/strategic-compact/SKILL.md +102 -0
- package/resources/ecc/skills/strategic-compact/agents/openai.yaml +7 -0
- package/resources/ecc/skills/tdd-workflow/SKILL.md +409 -0
- package/resources/ecc/skills/tdd-workflow/agents/openai.yaml +7 -0
- package/resources/ecc/skills/verification-loop/SKILL.md +125 -0
- package/resources/ecc/skills/verification-loop/agents/openai.yaml +7 -0
- package/resources/ecc/skills/video-editing/SKILL.md +307 -0
- package/resources/ecc/skills/video-editing/agents/openai.yaml +7 -0
- package/resources/ecc/skills/x-api/SKILL.md +229 -0
- package/resources/ecc/skills/x-api/agents/openai.yaml +7 -0
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { readFileSync, statSync } from 'node:fs';
|
|
2
|
+
import { resolve } from 'node:path';
|
|
3
|
+
export const ReadTool = {
|
|
4
|
+
name: 'read_file',
|
|
5
|
+
description: 'Read the contents of a file. Returns numbered lines. For large files, use offset and limit to read a portion.',
|
|
6
|
+
parameters: {
|
|
7
|
+
type: 'object',
|
|
8
|
+
properties: {
|
|
9
|
+
file_path: {
|
|
10
|
+
type: 'string',
|
|
11
|
+
description: 'Absolute or relative path to the file',
|
|
12
|
+
},
|
|
13
|
+
offset: {
|
|
14
|
+
type: 'number',
|
|
15
|
+
description: 'Line number to start from (0-based, default 0)',
|
|
16
|
+
},
|
|
17
|
+
limit: {
|
|
18
|
+
type: 'number',
|
|
19
|
+
description: 'Max lines to read (default 2000)',
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
required: ['file_path'],
|
|
23
|
+
},
|
|
24
|
+
isReadOnly: true,
|
|
25
|
+
isDestructive: false,
|
|
26
|
+
async call(input, cwd) {
|
|
27
|
+
try {
|
|
28
|
+
const filePath = resolve(cwd, input.file_path);
|
|
29
|
+
const stat = statSync(filePath);
|
|
30
|
+
if (stat.isDirectory()) {
|
|
31
|
+
return { output: `Error: "${filePath}" is a directory, not a file.`, isError: true };
|
|
32
|
+
}
|
|
33
|
+
if (stat.size > 5 * 1024 * 1024) {
|
|
34
|
+
return { output: `Error: File is ${(stat.size / 1024 / 1024).toFixed(1)}MB — too large. Use offset/limit.`, isError: true };
|
|
35
|
+
}
|
|
36
|
+
const content = readFileSync(filePath, 'utf-8');
|
|
37
|
+
const lines = content.split('\n');
|
|
38
|
+
const offset = input.offset || 0;
|
|
39
|
+
const limit = input.limit || 2000;
|
|
40
|
+
const slice = lines.slice(offset, offset + limit);
|
|
41
|
+
const numbered = slice
|
|
42
|
+
.map((line, i) => `${(offset + i + 1).toString().padStart(5)}\t${line}`)
|
|
43
|
+
.join('\n');
|
|
44
|
+
let result = numbered;
|
|
45
|
+
if (lines.length > offset + limit) {
|
|
46
|
+
result += `\n\n... (${lines.length - offset - limit} more lines)`;
|
|
47
|
+
}
|
|
48
|
+
return { output: result || '(empty file)', isError: false };
|
|
49
|
+
}
|
|
50
|
+
catch (e) {
|
|
51
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
52
|
+
return { output: `Error reading file: ${msg}`, isError: true };
|
|
53
|
+
}
|
|
54
|
+
},
|
|
55
|
+
};
|
|
56
|
+
//# sourceMappingURL=read.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"read.js","sourceRoot":"","sources":["../../src/tools/read.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACjD,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAGpC,MAAM,CAAC,MAAM,QAAQ,GAAS;IAC5B,IAAI,EAAE,WAAW;IACjB,WAAW,EACT,+GAA+G;IACjH,UAAU,EAAE;QACV,IAAI,EAAE,QAAQ;QACd,UAAU,EAAE;YACV,SAAS,EAAE;gBACT,IAAI,EAAE,QAAQ;gBACd,WAAW,EAAE,uCAAuC;aACrD;YACD,MAAM,EAAE;gBACN,IAAI,EAAE,QAAQ;gBACd,WAAW,EAAE,gDAAgD;aAC9D;YACD,KAAK,EAAE;gBACL,IAAI,EAAE,QAAQ;gBACd,WAAW,EAAE,kCAAkC;aAChD;SACF;QACD,QAAQ,EAAE,CAAC,WAAW,CAAC;KACxB;IACD,UAAU,EAAE,IAAI;IAChB,aAAa,EAAE,KAAK;IAEpB,KAAK,CAAC,IAAI,CAAC,KAAK,EAAE,GAAG;QACnB,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,EAAE,KAAK,CAAC,SAAmB,CAAC,CAAC;YACzD,MAAM,IAAI,GAAG,QAAQ,CAAC,QAAQ,CAAC,CAAC;YAEhC,IAAI,IAAI,CAAC,WAAW,EAAE,EAAE,CAAC;gBACvB,OAAO,EAAE,MAAM,EAAE,WAAW,QAAQ,+BAA+B,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;YACvF,CAAC;YAED,IAAI,IAAI,CAAC,IAAI,GAAG,CAAC,GAAG,IAAI,GAAG,IAAI,EAAE,CAAC;gBAChC,OAAO,EAAE,MAAM,EAAE,kBAAkB,CAAC,IAAI,CAAC,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,mCAAmC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;YAC9H,CAAC;YAED,MAAM,OAAO,GAAG,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;YAChD,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YAClC,MAAM,MAAM,GAAI,KAAK,CAAC,MAAiB,IAAI,CAAC,CAAC;YAC7C,MAAM,KAAK,GAAI,KAAK,CAAC,KAAgB,IAAI,IAAI,CAAC;YAC9C,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,EAAE,MAAM,GAAG,KAAK,CAAC,CAAC;YAElD,MAAM,QAAQ,GAAG,KAAK;iBACnB,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;iBACvE,IAAI,CAAC,IAAI,CAAC,CAAC;YAEd,IAAI,MAAM,GAAG,QAAQ,CAAC;YACtB,IAAI,KAAK,CAAC,MAAM,GAAG,MAAM,GAAG,KAAK,EAAE,CAAC;gBAClC,MAAM,IAAI,YAAY,KAAK,CAAC,MAAM,GAAG,MAAM,GAAG,KAAK,cAAc,CAAC;YACpE,CAAC;YACD,OAAO,EAAE,MAAM,EAAE,MAAM,IAAI,cAAc,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;QAC9D,CAAC;QAAC,OAAO,CAAU,EAAE,CAAC;YACpB,MAAM,GAAG,GAAG,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;YACvD,OAAO,EAAE,MAAM,EAAE,uBAAuB,GAAG,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;QACjE,CAAC;IACH,CAAC;CACF,CAAC"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool definition interface.
|
|
3
|
+
* All tools must implement this contract to be used by the AI agent.
|
|
4
|
+
*/
|
|
5
|
+
export interface Tool {
|
|
6
|
+
/** Unique tool name (used by the AI to call the tool) */
|
|
7
|
+
name: string;
|
|
8
|
+
/** Human-readable description of what the tool does */
|
|
9
|
+
description: string;
|
|
10
|
+
/** JSON schema for the tool's input parameters */
|
|
11
|
+
parameters: JsonSchema;
|
|
12
|
+
/** If true, the tool only reads data and never modifies state */
|
|
13
|
+
isReadOnly: boolean;
|
|
14
|
+
/** If true, the tool can make destructive changes (writes, deletes) */
|
|
15
|
+
isDestructive: boolean;
|
|
16
|
+
/**
|
|
17
|
+
* Execute the tool with the given input.
|
|
18
|
+
* @param input - Parsed JSON arguments matching the tool's schema
|
|
19
|
+
* @param cwd - Current working directory
|
|
20
|
+
* @returns Tool result with output and error status
|
|
21
|
+
*/
|
|
22
|
+
call(input: Record<string, unknown>, cwd: string): Promise<ToolResult>;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Result returned by a tool after execution.
|
|
26
|
+
*/
|
|
27
|
+
export interface ToolResult {
|
|
28
|
+
/** Text output from the tool (stdout or error message) */
|
|
29
|
+
output: string;
|
|
30
|
+
/** True if the tool encountered an error */
|
|
31
|
+
isError: boolean;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Simplified JSON Schema definition for tool parameters.
|
|
35
|
+
*/
|
|
36
|
+
export interface JsonSchema {
|
|
37
|
+
/** JSON Schema type (usually "object") */
|
|
38
|
+
type: string;
|
|
39
|
+
/** Property definitions keyed by parameter name */
|
|
40
|
+
properties: Record<string, unknown>;
|
|
41
|
+
/** List of required parameter names */
|
|
42
|
+
required?: string[];
|
|
43
|
+
/** Whether additional properties are allowed */
|
|
44
|
+
additionalProperties?: boolean;
|
|
45
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/tools/types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { htmlToText } from '../html-parser.js';
|
|
2
|
+
export const WebFetchTool = {
|
|
3
|
+
name: 'web_fetch',
|
|
4
|
+
description: 'Fetch a URL and return its text content (HTML converted to plain text). Useful for reading docs, APIs, or web pages.',
|
|
5
|
+
parameters: {
|
|
6
|
+
type: 'object',
|
|
7
|
+
properties: {
|
|
8
|
+
url: {
|
|
9
|
+
type: 'string',
|
|
10
|
+
description: 'The URL to fetch',
|
|
11
|
+
},
|
|
12
|
+
},
|
|
13
|
+
required: ['url'],
|
|
14
|
+
},
|
|
15
|
+
isReadOnly: true,
|
|
16
|
+
isDestructive: false,
|
|
17
|
+
async call(input) {
|
|
18
|
+
try {
|
|
19
|
+
const url = input.url;
|
|
20
|
+
const resp = await fetch(url, {
|
|
21
|
+
headers: { 'User-Agent': 'Crowcoder-CLI/1.0' },
|
|
22
|
+
signal: AbortSignal.timeout(30_000),
|
|
23
|
+
});
|
|
24
|
+
if (!resp.ok) {
|
|
25
|
+
return { output: `HTTP ${resp.status}: ${resp.statusText}`, isError: true };
|
|
26
|
+
}
|
|
27
|
+
const contentType = resp.headers.get('content-type') || '';
|
|
28
|
+
let text = await resp.text();
|
|
29
|
+
// Convert HTML to readable plain text
|
|
30
|
+
if (contentType.includes('html')) {
|
|
31
|
+
text = htmlToText(text);
|
|
32
|
+
}
|
|
33
|
+
return { output: text.slice(0, 80_000), isError: false };
|
|
34
|
+
}
|
|
35
|
+
catch (e) {
|
|
36
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
37
|
+
return { output: `Fetch error: ${msg}`, isError: true };
|
|
38
|
+
}
|
|
39
|
+
},
|
|
40
|
+
};
|
|
41
|
+
//# sourceMappingURL=web-fetch.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"web-fetch.js","sourceRoot":"","sources":["../../src/tools/web-fetch.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAE/C,MAAM,CAAC,MAAM,YAAY,GAAS;IAChC,IAAI,EAAE,WAAW;IACjB,WAAW,EACT,sHAAsH;IACxH,UAAU,EAAE;QACV,IAAI,EAAE,QAAQ;QACd,UAAU,EAAE;YACV,GAAG,EAAE;gBACH,IAAI,EAAE,QAAQ;gBACd,WAAW,EAAE,kBAAkB;aAChC;SACF;QACD,QAAQ,EAAE,CAAC,KAAK,CAAC;KAClB;IACD,UAAU,EAAE,IAAI;IAChB,aAAa,EAAE,KAAK;IAEpB,KAAK,CAAC,IAAI,CAAC,KAAK;QACd,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,KAAK,CAAC,GAAa,CAAC;YAChC,MAAM,IAAI,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;gBAC5B,OAAO,EAAE,EAAE,YAAY,EAAE,mBAAmB,EAAE;gBAC9C,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,MAAM,CAAC;aACpC,CAAC,CAAC;YAEH,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC;gBACb,OAAO,EAAE,MAAM,EAAE,QAAQ,IAAI,CAAC,MAAM,KAAK,IAAI,CAAC,UAAU,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;YAC9E,CAAC;YAED,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,IAAI,EAAE,CAAC;YAC3D,IAAI,IAAI,GAAG,MAAM,IAAI,CAAC,IAAI,EAAE,CAAC;YAE7B,sCAAsC;YACtC,IAAI,WAAW,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;gBACjC,IAAI,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC;YAC1B,CAAC;YAED,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,MAAM,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;QAC3D,CAAC;QAAC,OAAO,CAAU,EAAE,CAAC;YACpB,MAAM,GAAG,GAAG,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;YACvD,OAAO,EAAE,MAAM,EAAE,gBAAgB,GAAG,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;QAC1D,CAAC;IACH,CAAC;CACF,CAAC"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* web_search — keyword web search backed by DuckDuckGo's HTML endpoint.
|
|
3
|
+
*
|
|
4
|
+
* Free, no API key, no rate-limit signup. Returns up to N results as a
|
|
5
|
+
* structured plain-text list (title, URL, snippet) the model can read and
|
|
6
|
+
* then follow up with `web_fetch` for the full page.
|
|
7
|
+
*
|
|
8
|
+
* Why this exists: free models routinely hallucinate `web_search_exa` /
|
|
9
|
+
* `google_search` tool calls. This gives them a real tool of the right shape
|
|
10
|
+
* so the call succeeds.
|
|
11
|
+
*/
|
|
12
|
+
import type { Tool } from './types.js';
|
|
13
|
+
import { htmlToText } from '../html-parser.js';
|
|
14
|
+
interface SearchResult {
|
|
15
|
+
title: string;
|
|
16
|
+
url: string;
|
|
17
|
+
snippet: string;
|
|
18
|
+
}
|
|
19
|
+
declare function decodeDdgRedirect(href: string): string;
|
|
20
|
+
declare function parseDdgLite(html: string, limit: number): SearchResult[];
|
|
21
|
+
export declare const WebSearchTool: Tool;
|
|
22
|
+
export declare const _internal: {
|
|
23
|
+
parseDdgLite: typeof parseDdgLite;
|
|
24
|
+
decodeDdgRedirect: typeof decodeDdgRedirect;
|
|
25
|
+
htmlToText: typeof htmlToText;
|
|
26
|
+
};
|
|
27
|
+
export {};
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import { htmlToText } from '../html-parser.js';
|
|
2
|
+
// DDG Lite (GET) is the most reliable free backend — the POST endpoints
|
|
3
|
+
// (html.duckduckgo.com, lite POST) are aggressively bot-blocked.
|
|
4
|
+
const DDG_LITE = 'https://lite.duckduckgo.com/lite/';
|
|
5
|
+
const USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0 Safari/537.36';
|
|
6
|
+
function decodeDdgRedirect(href) {
|
|
7
|
+
// DDG wraps result links as: //duckduckgo.com/l/?uddg=<encoded>&rut=...
|
|
8
|
+
// Sometimes they're absolute, sometimes scheme-relative.
|
|
9
|
+
try {
|
|
10
|
+
const normalized = href.startsWith('//') ? `https:${href}` : href;
|
|
11
|
+
const u = new URL(normalized);
|
|
12
|
+
const uddg = u.searchParams.get('uddg');
|
|
13
|
+
if (uddg)
|
|
14
|
+
return decodeURIComponent(uddg);
|
|
15
|
+
return normalized;
|
|
16
|
+
}
|
|
17
|
+
catch {
|
|
18
|
+
return href;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
function decodeEntities(s) {
|
|
22
|
+
return s
|
|
23
|
+
.replace(/&/g, '&')
|
|
24
|
+
.replace(/</g, '<')
|
|
25
|
+
.replace(/>/g, '>')
|
|
26
|
+
.replace(/"/g, '"')
|
|
27
|
+
.replace(/'/g, "'")
|
|
28
|
+
.replace(/ /g, ' ')
|
|
29
|
+
.replace(/'/g, "'")
|
|
30
|
+
.replace(/…/g, '…');
|
|
31
|
+
}
|
|
32
|
+
function stripTags(s) {
|
|
33
|
+
return decodeEntities(s.replace(/<[^>]+>/g, '')).replace(/\s+/g, ' ').trim();
|
|
34
|
+
}
|
|
35
|
+
function parseDdgLite(html, limit) {
|
|
36
|
+
// DDG Lite layout (simplified):
|
|
37
|
+
// <a href="REDIRECT_URL" class='result-link'>TITLE</a>
|
|
38
|
+
// ...
|
|
39
|
+
// <td class='result-snippet'>SNIPPET</td>
|
|
40
|
+
// Quoting is single quotes for class, double quotes for href.
|
|
41
|
+
const results = [];
|
|
42
|
+
// Capture title + redirect URL. Then find the nearest following snippet td.
|
|
43
|
+
const linkRe = /<a[^>]*href="([^"]+)"[^>]*class=['"]result-link['"][^>]*>([\s\S]*?)<\/a>/g;
|
|
44
|
+
const snippetRe = /<td[^>]*class=['"]result-snippet['"][^>]*>([\s\S]*?)<\/td>/g;
|
|
45
|
+
// Collect all snippets with their offsets so we can pair them with links.
|
|
46
|
+
const snippets = [];
|
|
47
|
+
for (const m of html.matchAll(snippetRe)) {
|
|
48
|
+
snippets.push({ offset: m.index ?? 0, text: stripTags(m[1]) });
|
|
49
|
+
}
|
|
50
|
+
for (const m of html.matchAll(linkRe)) {
|
|
51
|
+
if (results.length >= limit)
|
|
52
|
+
break;
|
|
53
|
+
const url = decodeDdgRedirect(m[1]);
|
|
54
|
+
const title = stripTags(m[2]);
|
|
55
|
+
if (!title || !url)
|
|
56
|
+
continue;
|
|
57
|
+
if (url.includes('duckduckgo.com/y.js'))
|
|
58
|
+
continue; // skip ads/internal
|
|
59
|
+
const linkOffset = m.index ?? 0;
|
|
60
|
+
// Find the first snippet that appears after this link
|
|
61
|
+
const matchedSnippet = snippets.find((s) => s.offset > linkOffset);
|
|
62
|
+
const snippet = matchedSnippet?.text ?? '';
|
|
63
|
+
results.push({ title, url, snippet });
|
|
64
|
+
}
|
|
65
|
+
return results;
|
|
66
|
+
}
|
|
67
|
+
function formatResults(query, results) {
|
|
68
|
+
if (results.length === 0) {
|
|
69
|
+
return `No results for "${query}". Try a different query, or use web_fetch directly if you know the URL.`;
|
|
70
|
+
}
|
|
71
|
+
const lines = [`Search results for "${query}" (${results.length}):`, ''];
|
|
72
|
+
results.forEach((r, i) => {
|
|
73
|
+
lines.push(`${i + 1}. ${r.title}`);
|
|
74
|
+
lines.push(` ${r.url}`);
|
|
75
|
+
if (r.snippet)
|
|
76
|
+
lines.push(` ${r.snippet}`);
|
|
77
|
+
lines.push('');
|
|
78
|
+
});
|
|
79
|
+
lines.push('To read a result fully, call web_fetch with its URL.');
|
|
80
|
+
return lines.join('\n');
|
|
81
|
+
}
|
|
82
|
+
export const WebSearchTool = {
|
|
83
|
+
name: 'web_search',
|
|
84
|
+
description: 'Search the web by keyword. Returns a ranked list of title/URL/snippet results from DuckDuckGo. Use this for discovery; use web_fetch to read a specific URL in full. No API key required.',
|
|
85
|
+
parameters: {
|
|
86
|
+
type: 'object',
|
|
87
|
+
properties: {
|
|
88
|
+
query: {
|
|
89
|
+
type: 'string',
|
|
90
|
+
description: 'The search query — natural language or keywords.',
|
|
91
|
+
},
|
|
92
|
+
limit: {
|
|
93
|
+
type: 'number',
|
|
94
|
+
description: 'Maximum results to return (default 5, max 15).',
|
|
95
|
+
},
|
|
96
|
+
},
|
|
97
|
+
required: ['query'],
|
|
98
|
+
},
|
|
99
|
+
isReadOnly: true,
|
|
100
|
+
isDestructive: false,
|
|
101
|
+
async call(input) {
|
|
102
|
+
const query = String(input.query || '').trim();
|
|
103
|
+
if (!query) {
|
|
104
|
+
return { output: 'web_search: missing required parameter "query"', isError: true };
|
|
105
|
+
}
|
|
106
|
+
const limit = Math.max(1, Math.min(15, Number(input.limit) || 5));
|
|
107
|
+
try {
|
|
108
|
+
const url = `${DDG_LITE}?q=${encodeURIComponent(query)}&kl=us-en`;
|
|
109
|
+
const resp = await fetch(url, {
|
|
110
|
+
method: 'GET',
|
|
111
|
+
headers: {
|
|
112
|
+
'User-Agent': USER_AGENT,
|
|
113
|
+
'Accept': 'text/html,application/xhtml+xml',
|
|
114
|
+
'Accept-Language': 'en-US,en;q=0.9',
|
|
115
|
+
},
|
|
116
|
+
signal: AbortSignal.timeout(20_000),
|
|
117
|
+
});
|
|
118
|
+
if (!resp.ok) {
|
|
119
|
+
return { output: `web_search HTTP ${resp.status}: ${resp.statusText}`, isError: true };
|
|
120
|
+
}
|
|
121
|
+
const html = await resp.text();
|
|
122
|
+
const results = parseDdgLite(html, limit);
|
|
123
|
+
if (results.length === 0 && /captcha|automated|blocked/i.test(html)) {
|
|
124
|
+
return {
|
|
125
|
+
output: `web_search: DuckDuckGo returned an anti-bot page. Try again in a few minutes, or use web_fetch on a specific URL.`,
|
|
126
|
+
isError: true,
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
return { output: formatResults(query, results), isError: false };
|
|
130
|
+
}
|
|
131
|
+
catch (e) {
|
|
132
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
133
|
+
return { output: `web_search error: ${msg}`, isError: true };
|
|
134
|
+
}
|
|
135
|
+
},
|
|
136
|
+
};
|
|
137
|
+
// Internal export for tests
|
|
138
|
+
export const _internal = { parseDdgLite, decodeDdgRedirect, htmlToText };
|
|
139
|
+
//# sourceMappingURL=web-search.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"web-search.js","sourceRoot":"","sources":["../../src/tools/web-search.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { writeFileSync, mkdirSync } from 'node:fs';
|
|
2
|
+
import { resolve, dirname } from 'node:path';
|
|
3
|
+
export const WriteTool = {
|
|
4
|
+
name: 'write_file',
|
|
5
|
+
description: 'Create or overwrite a file with the given content. Parent directories are created automatically.',
|
|
6
|
+
parameters: {
|
|
7
|
+
type: 'object',
|
|
8
|
+
properties: {
|
|
9
|
+
file_path: {
|
|
10
|
+
type: 'string',
|
|
11
|
+
description: 'Absolute or relative path to the file',
|
|
12
|
+
},
|
|
13
|
+
content: {
|
|
14
|
+
type: 'string',
|
|
15
|
+
description: 'The full content to write',
|
|
16
|
+
},
|
|
17
|
+
},
|
|
18
|
+
required: ['file_path', 'content'],
|
|
19
|
+
},
|
|
20
|
+
isReadOnly: false,
|
|
21
|
+
isDestructive: true,
|
|
22
|
+
async call(input, cwd) {
|
|
23
|
+
try {
|
|
24
|
+
const filePath = resolve(cwd, input.file_path);
|
|
25
|
+
mkdirSync(dirname(filePath), { recursive: true });
|
|
26
|
+
writeFileSync(filePath, input.content, 'utf-8');
|
|
27
|
+
const lines = input.content.split('\n').length;
|
|
28
|
+
return { output: `Wrote ${lines} lines to ${filePath}`, isError: false };
|
|
29
|
+
}
|
|
30
|
+
catch (e) {
|
|
31
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
32
|
+
return { output: `Error writing file: ${msg}`, isError: true };
|
|
33
|
+
}
|
|
34
|
+
},
|
|
35
|
+
};
|
|
36
|
+
//# sourceMappingURL=write.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"write.js","sourceRoot":"","sources":["../../src/tools/write.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAG7C,MAAM,CAAC,MAAM,SAAS,GAAS;IAC7B,IAAI,EAAE,YAAY;IAClB,WAAW,EACT,kGAAkG;IACpG,UAAU,EAAE;QACV,IAAI,EAAE,QAAQ;QACd,UAAU,EAAE;YACV,SAAS,EAAE;gBACT,IAAI,EAAE,QAAQ;gBACd,WAAW,EAAE,uCAAuC;aACrD;YACD,OAAO,EAAE;gBACP,IAAI,EAAE,QAAQ;gBACd,WAAW,EAAE,2BAA2B;aACzC;SACF;QACD,QAAQ,EAAE,CAAC,WAAW,EAAE,SAAS,CAAC;KACnC;IACD,UAAU,EAAE,KAAK;IACjB,aAAa,EAAE,IAAI;IAEnB,KAAK,CAAC,IAAI,CAAC,KAAK,EAAE,GAAG;QACnB,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,EAAE,KAAK,CAAC,SAAmB,CAAC,CAAC;YACzD,SAAS,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;YAClD,aAAa,CAAC,QAAQ,EAAE,KAAK,CAAC,OAAiB,EAAE,OAAO,CAAC,CAAC;YAC1D,MAAM,KAAK,GAAI,KAAK,CAAC,OAAkB,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC;YAC3D,OAAO,EAAE,MAAM,EAAE,SAAS,KAAK,aAAa,QAAQ,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;QAC3E,CAAC;QAAC,OAAO,CAAU,EAAE,CAAC;YACpB,MAAM,GAAG,GAAG,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;YACvD,OAAO,EAAE,MAAM,EAAE,uBAAuB,GAAG,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;QACjE,CAAC;IACH,CAAC;CACF,CAAC"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type OpenAI from 'openai';
|
|
2
|
+
export type Role = 'system' | 'user' | 'assistant' | 'tool';
|
|
3
|
+
export interface Message {
|
|
4
|
+
role: Role;
|
|
5
|
+
content: string | null;
|
|
6
|
+
tool_calls?: OpenAI.Chat.ChatCompletionMessageToolCall[];
|
|
7
|
+
tool_call_id?: string;
|
|
8
|
+
name?: string;
|
|
9
|
+
}
|
|
10
|
+
export interface CrowcoderConfig {
|
|
11
|
+
apiKey: string;
|
|
12
|
+
baseURL: string;
|
|
13
|
+
model: string;
|
|
14
|
+
provider: string;
|
|
15
|
+
maxTokens: number;
|
|
16
|
+
temperature: number;
|
|
17
|
+
permissionMode: 'ask' | 'auto' | 'yolo';
|
|
18
|
+
dryRun?: boolean;
|
|
19
|
+
theme?: 'full' | 'compact' | 'minimal';
|
|
20
|
+
showThinking?: boolean;
|
|
21
|
+
}
|
|
22
|
+
export interface ProviderPreset {
|
|
23
|
+
name: string;
|
|
24
|
+
baseURL: string;
|
|
25
|
+
defaultModel: string;
|
|
26
|
+
requiresKey: boolean;
|
|
27
|
+
}
|
|
28
|
+
export declare const PROVIDERS: Record<string, ProviderPreset>;
|
package/dist/types.js
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
export const PROVIDERS = {
|
|
2
|
+
anthropic: {
|
|
3
|
+
name: 'Anthropic (Claude)',
|
|
4
|
+
baseURL: 'https://api.anthropic.com/v1/',
|
|
5
|
+
defaultModel: 'claude-sonnet-4-20250514',
|
|
6
|
+
requiresKey: true,
|
|
7
|
+
},
|
|
8
|
+
openai: {
|
|
9
|
+
name: 'OpenAI (GPT)',
|
|
10
|
+
baseURL: 'https://api.openai.com/v1',
|
|
11
|
+
defaultModel: 'gpt-4o',
|
|
12
|
+
requiresKey: true,
|
|
13
|
+
},
|
|
14
|
+
openrouter: {
|
|
15
|
+
name: 'OpenRouter (Any Model)',
|
|
16
|
+
baseURL: 'https://openrouter.ai/api/v1',
|
|
17
|
+
defaultModel: 'anthropic/claude-sonnet-4',
|
|
18
|
+
requiresKey: true,
|
|
19
|
+
},
|
|
20
|
+
google: {
|
|
21
|
+
name: 'Google (Gemini)',
|
|
22
|
+
baseURL: 'https://generativelanguage.googleapis.com/v1beta/openai/',
|
|
23
|
+
defaultModel: 'gemini-2.5-flash',
|
|
24
|
+
requiresKey: true,
|
|
25
|
+
},
|
|
26
|
+
deepseek: {
|
|
27
|
+
name: 'DeepSeek',
|
|
28
|
+
baseURL: 'https://api.deepseek.com/v1',
|
|
29
|
+
defaultModel: 'deepseek-chat',
|
|
30
|
+
requiresKey: true,
|
|
31
|
+
},
|
|
32
|
+
ollama: {
|
|
33
|
+
name: 'Ollama (Local)',
|
|
34
|
+
baseURL: 'http://localhost:11434/v1',
|
|
35
|
+
defaultModel: 'qwen2.5-coder:latest',
|
|
36
|
+
requiresKey: false,
|
|
37
|
+
},
|
|
38
|
+
lmstudio: {
|
|
39
|
+
name: 'LM Studio',
|
|
40
|
+
baseURL: 'http://localhost:1234/v1',
|
|
41
|
+
defaultModel: 'loaded-model',
|
|
42
|
+
requiresKey: false,
|
|
43
|
+
},
|
|
44
|
+
glm: {
|
|
45
|
+
name: 'GLM (ZhipuAI)',
|
|
46
|
+
baseURL: 'https://open.bigmodel.cn/api/paas/v4',
|
|
47
|
+
defaultModel: 'glm-4-plus',
|
|
48
|
+
requiresKey: true,
|
|
49
|
+
},
|
|
50
|
+
custom: {
|
|
51
|
+
name: 'Custom',
|
|
52
|
+
baseURL: '',
|
|
53
|
+
defaultModel: '',
|
|
54
|
+
requiresKey: true,
|
|
55
|
+
},
|
|
56
|
+
};
|
|
57
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAmCA,MAAM,CAAC,MAAM,SAAS,GAAmC;IACvD,SAAS,EAAE;QACT,IAAI,EAAE,oBAAoB;QAC1B,OAAO,EAAE,+BAA+B;QACxC,YAAY,EAAE,0BAA0B;QACxC,WAAW,EAAE,IAAI;KAClB;IACD,MAAM,EAAE;QACN,IAAI,EAAE,cAAc;QACpB,OAAO,EAAE,2BAA2B;QACpC,YAAY,EAAE,QAAQ;QACtB,WAAW,EAAE,IAAI;KAClB;IACD,UAAU,EAAE;QACV,IAAI,EAAE,wBAAwB;QAC9B,OAAO,EAAE,8BAA8B;QACvC,YAAY,EAAE,2BAA2B;QACzC,WAAW,EAAE,IAAI;KAClB;IACD,MAAM,EAAE;QACN,IAAI,EAAE,iBAAiB;QACvB,OAAO,EAAE,0DAA0D;QACnE,YAAY,EAAE,kBAAkB;QAChC,WAAW,EAAE,IAAI;KAClB;IACD,QAAQ,EAAE;QACR,IAAI,EAAE,UAAU;QAChB,OAAO,EAAE,6BAA6B;QACtC,YAAY,EAAE,eAAe;QAC7B,WAAW,EAAE,IAAI;KAClB;IACD,MAAM,EAAE;QACN,IAAI,EAAE,gBAAgB;QACtB,OAAO,EAAE,2BAA2B;QACpC,YAAY,EAAE,sBAAsB;QACpC,WAAW,EAAE,KAAK;KACnB;IACD,QAAQ,EAAE;QACR,IAAI,EAAE,WAAW;QACjB,OAAO,EAAE,0BAA0B;QACnC,YAAY,EAAE,cAAc;QAC5B,WAAW,EAAE,KAAK;KACnB;IACD,GAAG,EAAE;QACH,IAAI,EAAE,eAAe;QACrB,OAAO,EAAE,sCAAsC;QAC/C,YAAY,EAAE,YAAY;QAC1B,WAAW,EAAE,IAAI;KAClB;IACD,MAAM,EAAE;QACN,IAAI,EAAE,QAAQ;QACd,OAAO,EAAE,EAAE;QACX,YAAY,EAAE,EAAE;QAChB,WAAW,EAAE,IAAI;KAClB;CACF,CAAC"}
|
package/dist/users.d.ts
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { type UserRow, type UsersTable } from './schema.js';
|
|
2
|
+
export type User = UserRow;
|
|
3
|
+
export type UsersData = UsersTable;
|
|
4
|
+
/**
|
|
5
|
+
* Create a new user. Returns the created User.
|
|
6
|
+
*/
|
|
7
|
+
export declare function createUser(name: string, email?: string, role?: string): User;
|
|
8
|
+
/**
|
|
9
|
+
* List all users.
|
|
10
|
+
*/
|
|
11
|
+
export declare function listUsers(): User[];
|
|
12
|
+
/**
|
|
13
|
+
* Get a user by ID.
|
|
14
|
+
*/
|
|
15
|
+
export declare function getUser(id: string): User | null;
|
|
16
|
+
/**
|
|
17
|
+
* Get a user by email address.
|
|
18
|
+
*/
|
|
19
|
+
export declare function getUserByEmail(email: string): User | null;
|
|
20
|
+
/**
|
|
21
|
+
* Get the currently active user.
|
|
22
|
+
*/
|
|
23
|
+
export declare function getActiveUser(): User | null;
|
|
24
|
+
/**
|
|
25
|
+
* Update a user's fields. Returns the updated User or null if not found.
|
|
26
|
+
*/
|
|
27
|
+
export declare function updateUser(id: string, updates: Partial<Pick<User, 'name' | 'email' | 'role' | 'active' | 'metadata'>>): User | null;
|
|
28
|
+
/**
|
|
29
|
+
* Delete a user by ID. Returns true if deleted, false if not found.
|
|
30
|
+
*/
|
|
31
|
+
export declare function deleteUser(id: string): boolean;
|
|
32
|
+
/**
|
|
33
|
+
* Set the active user by ID. Returns the activated User or null if not found.
|
|
34
|
+
*/
|
|
35
|
+
export declare function setActiveUser(id: string): User | null;
|
|
36
|
+
/**
|
|
37
|
+
* Set user metadata key/value pair.
|
|
38
|
+
*/
|
|
39
|
+
export declare function setUserMetadata(id: string, key: string, value: string): User | null;
|
|
40
|
+
/**
|
|
41
|
+
* Get a metadata value for a user.
|
|
42
|
+
*/
|
|
43
|
+
export declare function getUserMetadata(id: string, key: string): string | undefined;
|
|
44
|
+
/**
|
|
45
|
+
* Print a formatted user list to stdout.
|
|
46
|
+
*/
|
|
47
|
+
export declare function printUserList(): void;
|
|
48
|
+
/**
|
|
49
|
+
* Build a context string about the active user for the system prompt.
|
|
50
|
+
*/
|
|
51
|
+
export declare function buildUserContext(): string;
|