jawere 1.4.0 → 1.5.1
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/dist/index.js +158 -59
- package/package.json +1 -1
- package/dist/agent.d.ts +0 -15
- package/dist/agent.js +0 -321
- package/dist/config.d.ts +0 -19
- package/dist/config.js +0 -53
- package/dist/convex-client.d.ts +0 -41
- package/dist/convex-client.js +0 -99
- package/dist/crypto.d.ts +0 -12
- package/dist/crypto.js +0 -79
- package/dist/index.d.ts +0 -1
- package/dist/prompt.d.ts +0 -9
- package/dist/prompt.js +0 -325
- package/dist/scanner.d.ts +0 -29
- package/dist/scanner.js +0 -520
- package/dist/spinner.d.ts +0 -23
- package/dist/spinner.js +0 -83
- package/dist/system-prompt.d.ts +0 -1
- package/dist/system-prompt.js +0 -115
- package/dist/tools.d.ts +0 -22
- package/dist/tools.js +0 -551
package/dist/index.js
CHANGED
|
@@ -13339,6 +13339,30 @@ var TOOL_DEFS = [
|
|
|
13339
13339
|
}
|
|
13340
13340
|
}
|
|
13341
13341
|
},
|
|
13342
|
+
{
|
|
13343
|
+
type: "function",
|
|
13344
|
+
function: {
|
|
13345
|
+
name: "diff",
|
|
13346
|
+
description: "Show a git diff of changes. Useful for reviewing what changed before committing. Supports --staged for staged changes, and optional path/file and base ref.",
|
|
13347
|
+
parameters: {
|
|
13348
|
+
type: "object",
|
|
13349
|
+
properties: {
|
|
13350
|
+
path: {
|
|
13351
|
+
type: "string",
|
|
13352
|
+
description: "Specific file or directory to diff (optional \u2014 diffs everything if omitted)"
|
|
13353
|
+
},
|
|
13354
|
+
staged: {
|
|
13355
|
+
type: "boolean",
|
|
13356
|
+
description: "Show staged changes (git diff --staged). Default: false (working tree)"
|
|
13357
|
+
},
|
|
13358
|
+
base: {
|
|
13359
|
+
type: "string",
|
|
13360
|
+
description: "Base ref to diff against (e.g. HEAD~1, main). Default: HEAD for staged, working tree otherwise"
|
|
13361
|
+
}
|
|
13362
|
+
}
|
|
13363
|
+
}
|
|
13364
|
+
}
|
|
13365
|
+
},
|
|
13342
13366
|
{
|
|
13343
13367
|
type: "function",
|
|
13344
13368
|
function: {
|
|
@@ -13757,6 +13781,14 @@ async function statTool(path, workDir) {
|
|
|
13757
13781
|
return `Error: [stat-failed] ${fullPath}: ${err.message}`;
|
|
13758
13782
|
}
|
|
13759
13783
|
}
|
|
13784
|
+
async function diffTool(path, staged, base, workDir) {
|
|
13785
|
+
const args = ["diff"];
|
|
13786
|
+
if (staged) args.push("--staged");
|
|
13787
|
+
if (base) args.push(base);
|
|
13788
|
+
if (path) args.push("--", path);
|
|
13789
|
+
else args.push("--", ".");
|
|
13790
|
+
return execBash(`git ${args.join(" ")}`, workDir, 30);
|
|
13791
|
+
}
|
|
13760
13792
|
async function executeTool(call, workDir) {
|
|
13761
13793
|
const { id, function: fn } = call;
|
|
13762
13794
|
let args;
|
|
@@ -13799,6 +13831,14 @@ async function executeTool(call, workDir) {
|
|
|
13799
13831
|
case "find":
|
|
13800
13832
|
result = await findTool(args.pattern, args.path, workDir);
|
|
13801
13833
|
break;
|
|
13834
|
+
case "diff":
|
|
13835
|
+
result = await diffTool(
|
|
13836
|
+
args.path,
|
|
13837
|
+
args.staged,
|
|
13838
|
+
args.base,
|
|
13839
|
+
workDir
|
|
13840
|
+
);
|
|
13841
|
+
break;
|
|
13802
13842
|
case "grep":
|
|
13803
13843
|
result = await grepTool(
|
|
13804
13844
|
args.pattern,
|
|
@@ -13891,8 +13931,10 @@ function isDevMode() {
|
|
|
13891
13931
|
if (process.env.NODE_ENV === "production") return false;
|
|
13892
13932
|
if (process.env.NODE_ENV === "development") return true;
|
|
13893
13933
|
const main2 = process.argv[1] || "";
|
|
13934
|
+
if (main2.includes("node_modules")) return false;
|
|
13935
|
+
if (main2.endsWith("bin/jawere.js")) return false;
|
|
13936
|
+
if (main2.includes("/dist/")) return false;
|
|
13894
13937
|
if (main2.endsWith(".ts") || main2.includes("/src/")) return true;
|
|
13895
|
-
if (main2.includes("/node_modules/") || main2.includes("/.local/lib/node_modules/")) return false;
|
|
13896
13938
|
return true;
|
|
13897
13939
|
}
|
|
13898
13940
|
var cachedConfig = null;
|
|
@@ -14265,13 +14307,14 @@ async function listSessions(convexUrl) {
|
|
|
14265
14307
|
|
|
14266
14308
|
// src/agent.ts
|
|
14267
14309
|
var MAX_TURNS = 500;
|
|
14268
|
-
var MAX_OUTPUT_TOKENS =
|
|
14310
|
+
var MAX_OUTPUT_TOKENS = 393216;
|
|
14269
14311
|
var COL = () => process.stdout.columns || 80;
|
|
14270
14312
|
var GRUVBOX_GREEN = "\x1B[38;2;184;187;3m";
|
|
14271
14313
|
var GRUVBOX_GRAY = "\x1B[38;2;146;131;116m";
|
|
14272
14314
|
var GRUVBOX_RED = "\x1B[38;2;251;73;52m";
|
|
14273
14315
|
var RESET2 = "\x1B[0m";
|
|
14274
14316
|
var FILE_TOOLS = /* @__PURE__ */ new Set(["read", "write", "edit", "stat"]);
|
|
14317
|
+
var SILENT_TOOLS = /* @__PURE__ */ new Set(["diff"]);
|
|
14275
14318
|
function toolDetail(name, args) {
|
|
14276
14319
|
switch (name) {
|
|
14277
14320
|
case "read": {
|
|
@@ -14296,6 +14339,7 @@ function toolDetail(name, args) {
|
|
|
14296
14339
|
}
|
|
14297
14340
|
}
|
|
14298
14341
|
function displayToolLine(name, args, ok, spin) {
|
|
14342
|
+
if (SILENT_TOOLS.has(name)) return;
|
|
14299
14343
|
if (spin?.running) {
|
|
14300
14344
|
spin.stop();
|
|
14301
14345
|
}
|
|
@@ -14463,86 +14507,120 @@ async function runAgent(userMessage, options = {}) {
|
|
|
14463
14507
|
return { text: msg2, sessionId, history: messages };
|
|
14464
14508
|
}
|
|
14465
14509
|
spin.update("Thinking\u2026");
|
|
14466
|
-
|
|
14467
|
-
|
|
14468
|
-
|
|
14469
|
-
|
|
14470
|
-
|
|
14471
|
-
|
|
14472
|
-
|
|
14473
|
-
|
|
14474
|
-
|
|
14475
|
-
|
|
14476
|
-
|
|
14477
|
-
|
|
14478
|
-
|
|
14510
|
+
let streamedContent = "";
|
|
14511
|
+
const streamedToolCalls = /* @__PURE__ */ new Map();
|
|
14512
|
+
let streamUsage;
|
|
14513
|
+
try {
|
|
14514
|
+
const stream = await withRetry(async () => {
|
|
14515
|
+
return client.chat.completions.create({
|
|
14516
|
+
model: config.model,
|
|
14517
|
+
messages,
|
|
14518
|
+
tools: TOOL_DEFS,
|
|
14519
|
+
tool_choice: "auto",
|
|
14520
|
+
temperature: 0.2,
|
|
14521
|
+
max_tokens: MAX_OUTPUT_TOKENS,
|
|
14522
|
+
stream: true,
|
|
14523
|
+
stream_options: { include_usage: true },
|
|
14524
|
+
// Enable thinking/reasoning — DeepSeek specific params
|
|
14525
|
+
...{
|
|
14526
|
+
thinking: { type: "enabled" },
|
|
14527
|
+
reasoning_effort: "max"
|
|
14528
|
+
}
|
|
14529
|
+
});
|
|
14479
14530
|
});
|
|
14480
|
-
|
|
14531
|
+
for await (const chunk of stream) {
|
|
14532
|
+
if (options.signal?.aborted) break;
|
|
14533
|
+
const delta = chunk.choices?.[0]?.delta;
|
|
14534
|
+
if (!delta) {
|
|
14535
|
+
if (chunk.usage) {
|
|
14536
|
+
streamUsage = {
|
|
14537
|
+
input: chunk.usage.prompt_tokens || 0,
|
|
14538
|
+
output: chunk.usage.completion_tokens || 0,
|
|
14539
|
+
total: chunk.usage.total_tokens || 0
|
|
14540
|
+
};
|
|
14541
|
+
}
|
|
14542
|
+
continue;
|
|
14543
|
+
}
|
|
14544
|
+
if (delta.content) {
|
|
14545
|
+
streamedContent += delta.content;
|
|
14546
|
+
}
|
|
14547
|
+
if (delta.tool_calls) {
|
|
14548
|
+
for (const tc of delta.tool_calls) {
|
|
14549
|
+
const idx = tc.index ?? 0;
|
|
14550
|
+
if (!streamedToolCalls.has(idx)) {
|
|
14551
|
+
streamedToolCalls.set(idx, { id: "", name: "", arguments: "" });
|
|
14552
|
+
}
|
|
14553
|
+
const entry = streamedToolCalls.get(idx);
|
|
14554
|
+
if (tc.id) entry.id = tc.id;
|
|
14555
|
+
if (tc.function?.name) entry.name += tc.function.name;
|
|
14556
|
+
if (tc.function?.arguments) entry.arguments += tc.function.arguments;
|
|
14557
|
+
}
|
|
14558
|
+
}
|
|
14559
|
+
spin.update("Thinking\u2026");
|
|
14560
|
+
}
|
|
14561
|
+
} catch (err) {
|
|
14481
14562
|
if (err.name === "AbortError" || err.name === "Canceled") {
|
|
14482
|
-
|
|
14563
|
+
spin.stop();
|
|
14564
|
+
const msg2 = "\n[Cancelled by user]";
|
|
14565
|
+
return { text: msg2, sessionId, history: messages };
|
|
14483
14566
|
}
|
|
14484
14567
|
throw err;
|
|
14485
|
-
}
|
|
14486
|
-
if (
|
|
14568
|
+
}
|
|
14569
|
+
if (options.signal?.aborted) {
|
|
14487
14570
|
spin.stop();
|
|
14488
14571
|
const msg2 = "\n[Cancelled by user]";
|
|
14489
14572
|
return { text: msg2, sessionId, history: messages };
|
|
14490
14573
|
}
|
|
14491
|
-
const
|
|
14492
|
-
if (
|
|
14493
|
-
|
|
14494
|
-
|
|
14495
|
-
() => appendAssistantMessage(config.convexUrl, sessionId, "(error: no response)", null),
|
|
14496
|
-
"appendAssistantMessage"
|
|
14497
|
-
);
|
|
14498
|
-
return { text: "Error: No response from model.", sessionId, history: messages };
|
|
14499
|
-
}
|
|
14500
|
-
const { message } = choice;
|
|
14501
|
-
const usage = response.usage ? {
|
|
14502
|
-
input: response.usage.prompt_tokens || 0,
|
|
14503
|
-
output: response.usage.completion_tokens || 0,
|
|
14504
|
-
total: response.usage.total_tokens || 0
|
|
14505
|
-
} : void 0;
|
|
14506
|
-
if (message.tool_calls && message.tool_calls.length > 0) {
|
|
14507
|
-
const toolCallsMeta = message.tool_calls.map((tc) => ({
|
|
14574
|
+
const hasToolCalls = streamedToolCalls.size > 0;
|
|
14575
|
+
if (hasToolCalls) {
|
|
14576
|
+
const toolCallArray = Array.from(streamedToolCalls.entries()).sort(([a2], [b2]) => a2 - b2).map(([_2, tc]) => tc);
|
|
14577
|
+
const toolCallsMeta = toolCallArray.map((tc) => ({
|
|
14508
14578
|
id: tc.id,
|
|
14509
|
-
name: tc.
|
|
14510
|
-
arguments: tc.
|
|
14579
|
+
name: tc.name,
|
|
14580
|
+
arguments: tc.arguments
|
|
14511
14581
|
}));
|
|
14512
14582
|
safeCall(
|
|
14513
14583
|
() => appendAssistantMessage(
|
|
14514
14584
|
config.convexUrl,
|
|
14515
14585
|
sessionId,
|
|
14516
|
-
|
|
14586
|
+
streamedContent || null,
|
|
14517
14587
|
toolCallsMeta.length > 0 ? toolCallsMeta : null,
|
|
14518
|
-
|
|
14588
|
+
streamUsage
|
|
14519
14589
|
),
|
|
14520
14590
|
"appendAssistantMessage"
|
|
14521
14591
|
);
|
|
14592
|
+
const openaiToolCalls = toolCallArray.map((tc) => ({
|
|
14593
|
+
id: tc.id,
|
|
14594
|
+
type: "function",
|
|
14595
|
+
function: {
|
|
14596
|
+
name: tc.name,
|
|
14597
|
+
arguments: tc.arguments
|
|
14598
|
+
}
|
|
14599
|
+
}));
|
|
14522
14600
|
messages.push({
|
|
14523
14601
|
role: "assistant",
|
|
14524
|
-
content:
|
|
14525
|
-
tool_calls:
|
|
14602
|
+
content: streamedContent || null,
|
|
14603
|
+
tool_calls: openaiToolCalls
|
|
14526
14604
|
});
|
|
14527
|
-
for (const tc of
|
|
14605
|
+
for (const tc of toolCallArray) {
|
|
14528
14606
|
let args = {};
|
|
14529
14607
|
try {
|
|
14530
|
-
args = JSON.parse(tc.
|
|
14608
|
+
args = JSON.parse(tc.arguments);
|
|
14531
14609
|
} catch {
|
|
14532
14610
|
}
|
|
14533
|
-
spin.update(`Running ${tc.
|
|
14611
|
+
spin.update(`Running ${tc.name}\u2026`);
|
|
14534
14612
|
const result = await executeTool(
|
|
14535
14613
|
{
|
|
14536
14614
|
id: tc.id,
|
|
14537
14615
|
function: {
|
|
14538
|
-
name: tc.
|
|
14539
|
-
arguments: tc.
|
|
14616
|
+
name: tc.name,
|
|
14617
|
+
arguments: tc.arguments
|
|
14540
14618
|
}
|
|
14541
14619
|
},
|
|
14542
14620
|
config.workDir
|
|
14543
14621
|
);
|
|
14544
14622
|
const ok = !result.content.startsWith("Error");
|
|
14545
|
-
displayToolLine(tc.
|
|
14623
|
+
displayToolLine(tc.name, args, ok, spin);
|
|
14546
14624
|
messages.push({
|
|
14547
14625
|
role: "tool",
|
|
14548
14626
|
tool_call_id: result.tool_call_id,
|
|
@@ -14554,7 +14632,7 @@ async function runAgent(userMessage, options = {}) {
|
|
|
14554
14632
|
config.convexUrl,
|
|
14555
14633
|
sessionId,
|
|
14556
14634
|
result.tool_call_id,
|
|
14557
|
-
tc.
|
|
14635
|
+
tc.name,
|
|
14558
14636
|
result.content,
|
|
14559
14637
|
isError
|
|
14560
14638
|
),
|
|
@@ -14564,10 +14642,9 @@ async function runAgent(userMessage, options = {}) {
|
|
|
14564
14642
|
continue;
|
|
14565
14643
|
}
|
|
14566
14644
|
spin.stop();
|
|
14567
|
-
const
|
|
14568
|
-
const text = stripThinking(rawText) || "(empty response)";
|
|
14645
|
+
const text = stripThinking(streamedContent) || "(empty response)";
|
|
14569
14646
|
safeCall(
|
|
14570
|
-
() => appendAssistantMessage(config.convexUrl, sessionId, text, null,
|
|
14647
|
+
() => appendAssistantMessage(config.convexUrl, sessionId, text, null, streamUsage),
|
|
14571
14648
|
"appendAssistantMessage"
|
|
14572
14649
|
);
|
|
14573
14650
|
console.log("");
|
|
@@ -14871,20 +14948,32 @@ function getProjectInfo(workDir) {
|
|
|
14871
14948
|
}
|
|
14872
14949
|
return { name, version };
|
|
14873
14950
|
}
|
|
14874
|
-
async function scanCodebase(workDir) {
|
|
14951
|
+
async function scanCodebase(workDir, onProgress) {
|
|
14875
14952
|
const codebaseDir = resolve2(workDir, CODEBASE_DIR);
|
|
14876
14953
|
await mkdir3(codebaseDir, { recursive: true });
|
|
14954
|
+
onProgress?.("listing files");
|
|
14877
14955
|
const allFiles = await getAllFiles(workDir, workDir);
|
|
14878
14956
|
const files = allFiles.sort();
|
|
14957
|
+
onProgress?.(`found ${files.length} files`);
|
|
14958
|
+
onProgress?.("building tree");
|
|
14879
14959
|
const tree = buildTree(files);
|
|
14960
|
+
onProgress?.(`summarizing ${files.length} files`);
|
|
14880
14961
|
const summaries = {};
|
|
14881
|
-
|
|
14882
|
-
|
|
14962
|
+
let lastReport = 0;
|
|
14963
|
+
for (let i2 = 0; i2 < files.length; i2++) {
|
|
14964
|
+
const summary = await summarizeFile(resolve2(workDir, files[i2]));
|
|
14883
14965
|
if (summary) {
|
|
14884
|
-
summaries[
|
|
14966
|
+
summaries[files[i2]] = summary;
|
|
14967
|
+
}
|
|
14968
|
+
const now = Date.now();
|
|
14969
|
+
if (i2 - lastReport >= 10 || now - lastReport > 200) {
|
|
14970
|
+
onProgress?.(`summarizing ${i2 + 1}/${files.length}`);
|
|
14971
|
+
lastReport = i2;
|
|
14885
14972
|
}
|
|
14886
14973
|
}
|
|
14974
|
+
onProgress?.("reading project info");
|
|
14887
14975
|
const { name, version } = getProjectInfo(workDir);
|
|
14976
|
+
onProgress?.("hashing files");
|
|
14888
14977
|
const gitHash = await getGitHash(workDir);
|
|
14889
14978
|
const checksums = {
|
|
14890
14979
|
scannedAt: Date.now(),
|
|
@@ -14902,9 +14991,12 @@ async function scanCodebase(workDir) {
|
|
|
14902
14991
|
}
|
|
14903
14992
|
}
|
|
14904
14993
|
}
|
|
14994
|
+
onProgress?.("writing checksums");
|
|
14905
14995
|
await writeFile3(resolve2(workDir, CHECKSUMS_FILE), JSON.stringify(checksums, null, 2) + "\n", "utf-8");
|
|
14996
|
+
onProgress?.("writing tree.yaml");
|
|
14906
14997
|
const treeYaml = generateTreeYaml(name, version, tree, summaries);
|
|
14907
14998
|
await writeFile3(resolve2(workDir, TREE_FILE), treeYaml, "utf-8");
|
|
14999
|
+
onProgress?.("writing meta.json");
|
|
14908
15000
|
const meta = {
|
|
14909
15001
|
scannedAt: Date.now(),
|
|
14910
15002
|
fileCount: files.length,
|
|
@@ -14992,11 +15084,18 @@ async function runScanner(workDir, force = false) {
|
|
|
14992
15084
|
const meta = JSON.parse(
|
|
14993
15085
|
await readFile3(resolve2(workDir, META_FILE), "utf-8")
|
|
14994
15086
|
);
|
|
15087
|
+
process.stderr.write(` (cached)`);
|
|
14995
15088
|
return { fileCount: meta.fileCount, cached: true };
|
|
14996
15089
|
} catch {
|
|
14997
15090
|
}
|
|
14998
15091
|
}
|
|
14999
|
-
const
|
|
15092
|
+
const GRAY2 = "\x1B[38;2;146;131;116m";
|
|
15093
|
+
const RESET3 = "\x1B[0m";
|
|
15094
|
+
const { fileCount } = await scanCodebase(workDir, (phase, detail) => {
|
|
15095
|
+
const msg = detail || phase;
|
|
15096
|
+
process.stderr.write(`\r\x1B[K${GRAY2} scanning: ${msg}${RESET3}`);
|
|
15097
|
+
});
|
|
15098
|
+
process.stderr.write(`\r\x1B[K`);
|
|
15000
15099
|
return { fileCount, cached: false };
|
|
15001
15100
|
}
|
|
15002
15101
|
|
|
@@ -15351,10 +15450,10 @@ async function main() {
|
|
|
15351
15450
|
try {
|
|
15352
15451
|
const scanResult = await runScanner(config.workDir);
|
|
15353
15452
|
if (scanResult.cached) {
|
|
15354
|
-
process.stderr.write(` ${G_GRAY2}(
|
|
15453
|
+
process.stderr.write(` ${G_GRAY2}(${scanResult.fileCount} files)${R3}
|
|
15355
15454
|
`);
|
|
15356
15455
|
} else {
|
|
15357
|
-
process.stderr.write(
|
|
15456
|
+
process.stderr.write(`${G_GRAY2}Done \u2014 ${scanResult.fileCount} files indexed${R3}
|
|
15358
15457
|
`);
|
|
15359
15458
|
}
|
|
15360
15459
|
} catch (err) {
|
package/package.json
CHANGED
package/dist/agent.d.ts
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import type { ChatCompletionMessageParam } from 'openai/resources/chat/completions';
|
|
2
|
-
export interface AgentOptions {
|
|
3
|
-
sessionId?: string;
|
|
4
|
-
title?: string;
|
|
5
|
-
history?: ChatCompletionMessageParam[];
|
|
6
|
-
signal?: AbortSignal;
|
|
7
|
-
}
|
|
8
|
-
export interface AgentResult {
|
|
9
|
-
text: string;
|
|
10
|
-
sessionId: string;
|
|
11
|
-
history: ChatCompletionMessageParam[];
|
|
12
|
-
}
|
|
13
|
-
/** Print the assistant's FINAL response — the summary shown when all work is done. */
|
|
14
|
-
export declare function printAssistantResponse(text: string): void;
|
|
15
|
-
export declare function runAgent(userMessage: string, options?: AgentOptions): Promise<AgentResult>;
|