@hasna/coders 0.0.3 → 0.0.5
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/cli.mjs +461 -44
- package/dist/cli.mjs.map +4 -4
- package/package.json +3 -1
package/dist/cli.mjs
CHANGED
|
@@ -58429,7 +58429,7 @@ var init_client = __esm({
|
|
|
58429
58429
|
"Content-Type": "application/json",
|
|
58430
58430
|
"anthropic-version": "2023-06-01",
|
|
58431
58431
|
"anthropic-beta": BETA_HEADERS.join(","),
|
|
58432
|
-
"User-Agent": `coders/${"0.0.
|
|
58432
|
+
"User-Agent": `coders/${"0.0.5"}`
|
|
58433
58433
|
};
|
|
58434
58434
|
if (key.isOAuth) {
|
|
58435
58435
|
headers["Authorization"] = `Bearer ${key.apiKey}`;
|
|
@@ -59167,6 +59167,270 @@ var init_permissions = __esm({
|
|
|
59167
59167
|
}
|
|
59168
59168
|
});
|
|
59169
59169
|
|
|
59170
|
+
// src/db/index.ts
|
|
59171
|
+
import { join as join2 } from "path";
|
|
59172
|
+
import { existsSync as existsSync4, mkdirSync as mkdirSync3 } from "fs";
|
|
59173
|
+
function getDbPath() {
|
|
59174
|
+
const dir = getConfigDir();
|
|
59175
|
+
if (!existsSync4(dir)) mkdirSync3(dir, { recursive: true });
|
|
59176
|
+
return join2(dir, "coders.db");
|
|
59177
|
+
}
|
|
59178
|
+
function getDb() {
|
|
59179
|
+
if (_db) return _db;
|
|
59180
|
+
const dbPath = getDbPath();
|
|
59181
|
+
try {
|
|
59182
|
+
const { Database } = __require("bun:sqlite");
|
|
59183
|
+
_db = new Database(dbPath);
|
|
59184
|
+
} catch {
|
|
59185
|
+
try {
|
|
59186
|
+
const BetterSqlite3 = __require("better-sqlite3");
|
|
59187
|
+
_db = new BetterSqlite3(dbPath);
|
|
59188
|
+
} catch {
|
|
59189
|
+
console.warn("[db] No SQLite available \u2014 using in-memory fallback");
|
|
59190
|
+
_db = createInMemoryDb();
|
|
59191
|
+
initSchema(_db);
|
|
59192
|
+
return _db;
|
|
59193
|
+
}
|
|
59194
|
+
}
|
|
59195
|
+
try {
|
|
59196
|
+
_db.exec("PRAGMA journal_mode=WAL");
|
|
59197
|
+
} catch {
|
|
59198
|
+
}
|
|
59199
|
+
try {
|
|
59200
|
+
_db.exec("PRAGMA foreign_keys=ON");
|
|
59201
|
+
} catch {
|
|
59202
|
+
}
|
|
59203
|
+
initSchema(_db);
|
|
59204
|
+
return _db;
|
|
59205
|
+
}
|
|
59206
|
+
function initSchema(db) {
|
|
59207
|
+
db.exec(`
|
|
59208
|
+
-- Sessions
|
|
59209
|
+
CREATE TABLE IF NOT EXISTS sessions (
|
|
59210
|
+
id TEXT PRIMARY KEY,
|
|
59211
|
+
device_id TEXT NOT NULL,
|
|
59212
|
+
project_dir TEXT,
|
|
59213
|
+
original_cwd TEXT,
|
|
59214
|
+
model TEXT,
|
|
59215
|
+
app_version TEXT,
|
|
59216
|
+
build_time TEXT,
|
|
59217
|
+
fingerprint TEXT, -- JSON
|
|
59218
|
+
metadata TEXT, -- JSON
|
|
59219
|
+
created_at TEXT DEFAULT (datetime('now')),
|
|
59220
|
+
updated_at TEXT DEFAULT (datetime('now'))
|
|
59221
|
+
);
|
|
59222
|
+
|
|
59223
|
+
-- Messages (conversation history)
|
|
59224
|
+
CREATE TABLE IF NOT EXISTS messages (
|
|
59225
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
59226
|
+
session_id TEXT NOT NULL REFERENCES sessions(id),
|
|
59227
|
+
role TEXT NOT NULL CHECK(role IN ('user','assistant','system')),
|
|
59228
|
+
content TEXT NOT NULL,
|
|
59229
|
+
tool_uses TEXT, -- JSON array of tool use displays
|
|
59230
|
+
thinking TEXT,
|
|
59231
|
+
duration_ms REAL,
|
|
59232
|
+
tokens_in INTEGER DEFAULT 0,
|
|
59233
|
+
tokens_out INTEGER DEFAULT 0,
|
|
59234
|
+
cost_usd REAL DEFAULT 0,
|
|
59235
|
+
created_at TEXT DEFAULT (datetime('now'))
|
|
59236
|
+
);
|
|
59237
|
+
CREATE INDEX IF NOT EXISTS idx_messages_session ON messages(session_id);
|
|
59238
|
+
|
|
59239
|
+
-- File history (tracks reads per session)
|
|
59240
|
+
CREATE TABLE IF NOT EXISTS file_history (
|
|
59241
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
59242
|
+
session_id TEXT NOT NULL,
|
|
59243
|
+
file_path TEXT NOT NULL,
|
|
59244
|
+
content_hash TEXT,
|
|
59245
|
+
byte_size INTEGER,
|
|
59246
|
+
line_count INTEGER,
|
|
59247
|
+
read_at TEXT DEFAULT (datetime('now')),
|
|
59248
|
+
UNIQUE(session_id, file_path)
|
|
59249
|
+
);
|
|
59250
|
+
|
|
59251
|
+
-- File checkpoints (for /rewind)
|
|
59252
|
+
CREATE TABLE IF NOT EXISTS checkpoints (
|
|
59253
|
+
id TEXT PRIMARY KEY,
|
|
59254
|
+
session_id TEXT NOT NULL,
|
|
59255
|
+
file_path TEXT NOT NULL,
|
|
59256
|
+
original_content TEXT NOT NULL,
|
|
59257
|
+
edit_operation TEXT, -- JSON {old_string, new_string}
|
|
59258
|
+
created_at TEXT DEFAULT (datetime('now'))
|
|
59259
|
+
);
|
|
59260
|
+
CREATE INDEX IF NOT EXISTS idx_checkpoints_session_file ON checkpoints(session_id, file_path);
|
|
59261
|
+
|
|
59262
|
+
-- Tasks (replaces in-memory fallback for @hasna/todos)
|
|
59263
|
+
CREATE TABLE IF NOT EXISTS tasks (
|
|
59264
|
+
id TEXT PRIMARY KEY,
|
|
59265
|
+
subject TEXT NOT NULL,
|
|
59266
|
+
description TEXT DEFAULT '',
|
|
59267
|
+
status TEXT DEFAULT 'pending' CHECK(status IN ('pending','in_progress','completed','failed','cancelled')),
|
|
59268
|
+
active_form TEXT,
|
|
59269
|
+
owner TEXT,
|
|
59270
|
+
blocks TEXT DEFAULT '[]', -- JSON array of task IDs
|
|
59271
|
+
blocked_by TEXT DEFAULT '[]', -- JSON array of task IDs
|
|
59272
|
+
metadata TEXT DEFAULT '{}', -- JSON
|
|
59273
|
+
created_at TEXT DEFAULT (datetime('now')),
|
|
59274
|
+
updated_at TEXT DEFAULT (datetime('now'))
|
|
59275
|
+
);
|
|
59276
|
+
|
|
59277
|
+
-- Config (replaces JSON files)
|
|
59278
|
+
CREATE TABLE IF NOT EXISTS config (
|
|
59279
|
+
key TEXT PRIMARY KEY,
|
|
59280
|
+
value TEXT, -- JSON
|
|
59281
|
+
scope TEXT DEFAULT 'user' CHECK(scope IN ('user','project','local','global')),
|
|
59282
|
+
updated_at TEXT DEFAULT (datetime('now'))
|
|
59283
|
+
);
|
|
59284
|
+
|
|
59285
|
+
-- Memories (replaces in-memory fallback for @hasna/mementos)
|
|
59286
|
+
CREATE TABLE IF NOT EXISTS memories (
|
|
59287
|
+
id TEXT PRIMARY KEY,
|
|
59288
|
+
key TEXT UNIQUE NOT NULL,
|
|
59289
|
+
value TEXT NOT NULL,
|
|
59290
|
+
scope TEXT DEFAULT 'shared' CHECK(scope IN ('global','shared','private')),
|
|
59291
|
+
category TEXT DEFAULT 'knowledge',
|
|
59292
|
+
importance INTEGER DEFAULT 5 CHECK(importance BETWEEN 1 AND 10),
|
|
59293
|
+
tags TEXT DEFAULT '[]', -- JSON array
|
|
59294
|
+
version INTEGER DEFAULT 1,
|
|
59295
|
+
created_at TEXT DEFAULT (datetime('now')),
|
|
59296
|
+
updated_at TEXT DEFAULT (datetime('now'))
|
|
59297
|
+
);
|
|
59298
|
+
|
|
59299
|
+
-- Teams
|
|
59300
|
+
CREATE TABLE IF NOT EXISTS teams (
|
|
59301
|
+
name TEXT PRIMARY KEY,
|
|
59302
|
+
description TEXT,
|
|
59303
|
+
task_list_id TEXT,
|
|
59304
|
+
created_at TEXT DEFAULT (datetime('now'))
|
|
59305
|
+
);
|
|
59306
|
+
|
|
59307
|
+
-- Team members
|
|
59308
|
+
CREATE TABLE IF NOT EXISTS team_members (
|
|
59309
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
59310
|
+
team_name TEXT NOT NULL REFERENCES teams(name),
|
|
59311
|
+
agent_name TEXT NOT NULL,
|
|
59312
|
+
role TEXT,
|
|
59313
|
+
status TEXT DEFAULT 'idle',
|
|
59314
|
+
current_task TEXT,
|
|
59315
|
+
UNIQUE(team_name, agent_name)
|
|
59316
|
+
);
|
|
59317
|
+
|
|
59318
|
+
-- Team messages
|
|
59319
|
+
CREATE TABLE IF NOT EXISTS team_messages (
|
|
59320
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
59321
|
+
from_agent TEXT NOT NULL,
|
|
59322
|
+
to_agent TEXT NOT NULL,
|
|
59323
|
+
team_name TEXT,
|
|
59324
|
+
content TEXT NOT NULL,
|
|
59325
|
+
is_read INTEGER DEFAULT 0,
|
|
59326
|
+
is_blocking INTEGER DEFAULT 0,
|
|
59327
|
+
created_at TEXT DEFAULT (datetime('now'))
|
|
59328
|
+
);
|
|
59329
|
+
CREATE INDEX IF NOT EXISTS idx_team_msgs_to ON team_messages(to_agent, is_read);
|
|
59330
|
+
|
|
59331
|
+
-- Permissions (persisted allow/deny rules)
|
|
59332
|
+
CREATE TABLE IF NOT EXISTS permissions (
|
|
59333
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
59334
|
+
tool_name TEXT,
|
|
59335
|
+
command_pattern TEXT,
|
|
59336
|
+
path_pattern TEXT,
|
|
59337
|
+
behavior TEXT NOT NULL CHECK(behavior IN ('allow','deny')),
|
|
59338
|
+
scope TEXT DEFAULT 'session',
|
|
59339
|
+
created_at TEXT DEFAULT (datetime('now'))
|
|
59340
|
+
);
|
|
59341
|
+
|
|
59342
|
+
-- MCP servers
|
|
59343
|
+
CREATE TABLE IF NOT EXISTS mcp_servers (
|
|
59344
|
+
name TEXT PRIMARY KEY,
|
|
59345
|
+
command TEXT,
|
|
59346
|
+
args TEXT, -- JSON array
|
|
59347
|
+
env TEXT, -- JSON object
|
|
59348
|
+
url TEXT,
|
|
59349
|
+
transport TEXT DEFAULT 'stdio',
|
|
59350
|
+
scope TEXT DEFAULT 'user',
|
|
59351
|
+
enabled INTEGER DEFAULT 1,
|
|
59352
|
+
created_at TEXT DEFAULT (datetime('now'))
|
|
59353
|
+
);
|
|
59354
|
+
|
|
59355
|
+
-- Metrics (per-turn tracking)
|
|
59356
|
+
CREATE TABLE IF NOT EXISTS metrics (
|
|
59357
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
59358
|
+
session_id TEXT NOT NULL,
|
|
59359
|
+
turn_index INTEGER,
|
|
59360
|
+
tokens_in INTEGER DEFAULT 0,
|
|
59361
|
+
tokens_out INTEGER DEFAULT 0,
|
|
59362
|
+
cost_usd REAL DEFAULT 0,
|
|
59363
|
+
api_duration_ms REAL DEFAULT 0,
|
|
59364
|
+
tool_duration_ms REAL DEFAULT 0,
|
|
59365
|
+
hook_duration_ms REAL DEFAULT 0,
|
|
59366
|
+
tool_count INTEGER DEFAULT 0,
|
|
59367
|
+
model TEXT,
|
|
59368
|
+
created_at TEXT DEFAULT (datetime('now'))
|
|
59369
|
+
);
|
|
59370
|
+
|
|
59371
|
+
-- Audit log (for security \u2014 tracks all tool executions)
|
|
59372
|
+
CREATE TABLE IF NOT EXISTS audit_log (
|
|
59373
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
59374
|
+
session_id TEXT,
|
|
59375
|
+
tool_name TEXT NOT NULL,
|
|
59376
|
+
input_summary TEXT,
|
|
59377
|
+
result_summary TEXT,
|
|
59378
|
+
exit_code INTEGER,
|
|
59379
|
+
duration_ms REAL,
|
|
59380
|
+
was_allowed INTEGER DEFAULT 1,
|
|
59381
|
+
created_at TEXT DEFAULT (datetime('now'))
|
|
59382
|
+
);
|
|
59383
|
+
`);
|
|
59384
|
+
}
|
|
59385
|
+
function dbRun(sql, params = []) {
|
|
59386
|
+
const db = getDb();
|
|
59387
|
+
try {
|
|
59388
|
+
const stmt = db.prepare(sql);
|
|
59389
|
+
return stmt.run(...params);
|
|
59390
|
+
} catch (e) {
|
|
59391
|
+
try {
|
|
59392
|
+
return db.run(sql, params);
|
|
59393
|
+
} catch {
|
|
59394
|
+
throw e;
|
|
59395
|
+
}
|
|
59396
|
+
}
|
|
59397
|
+
}
|
|
59398
|
+
function createInMemoryDb() {
|
|
59399
|
+
const tables = /* @__PURE__ */ new Map();
|
|
59400
|
+
return {
|
|
59401
|
+
exec(sql) {
|
|
59402
|
+
const matches = sql.matchAll(/CREATE TABLE IF NOT EXISTS (\w+)/g);
|
|
59403
|
+
for (const m of matches) {
|
|
59404
|
+
if (!tables.has(m[1])) tables.set(m[1], /* @__PURE__ */ new Map());
|
|
59405
|
+
}
|
|
59406
|
+
},
|
|
59407
|
+
prepare(sql) {
|
|
59408
|
+
return {
|
|
59409
|
+
run(...params) {
|
|
59410
|
+
return { changes: 0 };
|
|
59411
|
+
},
|
|
59412
|
+
get(...params) {
|
|
59413
|
+
return void 0;
|
|
59414
|
+
},
|
|
59415
|
+
all(...params) {
|
|
59416
|
+
return [];
|
|
59417
|
+
}
|
|
59418
|
+
};
|
|
59419
|
+
},
|
|
59420
|
+
close() {
|
|
59421
|
+
tables.clear();
|
|
59422
|
+
}
|
|
59423
|
+
};
|
|
59424
|
+
}
|
|
59425
|
+
var _db;
|
|
59426
|
+
var init_db = __esm({
|
|
59427
|
+
"src/db/index.ts"() {
|
|
59428
|
+
"use strict";
|
|
59429
|
+
init_paths();
|
|
59430
|
+
_db = null;
|
|
59431
|
+
}
|
|
59432
|
+
});
|
|
59433
|
+
|
|
59170
59434
|
// src/core/constants.ts
|
|
59171
59435
|
var BASH_TOOL, READ_TOOL, EDIT_TOOL, WRITE_TOOL, GLOB_TOOL, GREP_TOOL, DEFAULT_BASH_TIMEOUT_MS, MAX_BASH_TIMEOUT_MS, DEFAULT_READ_LINE_LIMIT, DEFAULT_MAX_RESULT_SIZE_CHARS;
|
|
59172
59436
|
var init_constants = __esm({
|
|
@@ -59187,6 +59451,23 @@ var init_constants = __esm({
|
|
|
59187
59451
|
|
|
59188
59452
|
// src/tools/builtin/bash.ts
|
|
59189
59453
|
import { spawn } from "child_process";
|
|
59454
|
+
function isDangerousCommand(command) {
|
|
59455
|
+
for (const { pattern, reason } of DANGEROUS_PATTERNS) {
|
|
59456
|
+
if (pattern.test(command)) {
|
|
59457
|
+
return { dangerous: true, reason };
|
|
59458
|
+
}
|
|
59459
|
+
}
|
|
59460
|
+
return { dangerous: false };
|
|
59461
|
+
}
|
|
59462
|
+
function auditLog(command, exitCode, durationMs, sessionId) {
|
|
59463
|
+
try {
|
|
59464
|
+
dbRun(
|
|
59465
|
+
"INSERT INTO audit_log (session_id, tool_name, input_summary, result_summary, exit_code, duration_ms, was_allowed) VALUES (?, 'Bash', ?, ?, ?, ?, 1)",
|
|
59466
|
+
[sessionId ?? null, command.slice(0, 500), exitCode === 0 ? "success" : `exit ${exitCode}`, exitCode, durationMs]
|
|
59467
|
+
);
|
|
59468
|
+
} catch {
|
|
59469
|
+
}
|
|
59470
|
+
}
|
|
59190
59471
|
function isReadOnlyCommand(command) {
|
|
59191
59472
|
const trimmed = command.trim();
|
|
59192
59473
|
if (!trimmed) return false;
|
|
@@ -59282,12 +59563,28 @@ function truncateOutput(output, maxChars = DEFAULT_MAX_RESULT_SIZE_CHARS) {
|
|
|
59282
59563
|
|
|
59283
59564
|
` + output.slice(-half);
|
|
59284
59565
|
}
|
|
59285
|
-
var BashInputSchema, BashOutputSchema, READ_ONLY_COMMANDS, READ_ONLY_KEYWORDS, GIT_READ_ONLY_SUBCOMMANDS, NPM_READ_ONLY_SUBCOMMANDS, DOCKER_READ_ONLY_SUBCOMMANDS, backgroundTasks, nextBgId, bashTool, BASH_PROMPT;
|
|
59566
|
+
var DANGEROUS_PATTERNS, BashInputSchema, BashOutputSchema, READ_ONLY_COMMANDS, READ_ONLY_KEYWORDS, GIT_READ_ONLY_SUBCOMMANDS, NPM_READ_ONLY_SUBCOMMANDS, DOCKER_READ_ONLY_SUBCOMMANDS, backgroundTasks, nextBgId, bashTool, BASH_PROMPT;
|
|
59286
59567
|
var init_bash = __esm({
|
|
59287
59568
|
"src/tools/builtin/bash.ts"() {
|
|
59288
59569
|
"use strict";
|
|
59289
59570
|
init_zod();
|
|
59290
59571
|
init_constants();
|
|
59572
|
+
init_db();
|
|
59573
|
+
DANGEROUS_PATTERNS = [
|
|
59574
|
+
{ pattern: /\brm\s+-rf\s+\/\s*$/, reason: "Recursive delete of root filesystem" },
|
|
59575
|
+
{ pattern: /\brm\s+-rf\s+~\//, reason: "Recursive delete of home directory" },
|
|
59576
|
+
{ pattern: /\brm\s+-rf\s+\*/, reason: "Recursive delete with wildcard" },
|
|
59577
|
+
{ pattern: /\bmkfs\b/, reason: "Format filesystem" },
|
|
59578
|
+
{ pattern: /\bdd\s+.*of=\/dev\//, reason: "Direct write to device" },
|
|
59579
|
+
{ pattern: />\s*\/dev\/sd[a-z]/, reason: "Redirect to disk device" },
|
|
59580
|
+
{ pattern: /\b:(){ :\|:& };:/, reason: "Fork bomb" },
|
|
59581
|
+
{ pattern: /\bchmod\s+-R\s+777\s+\//, reason: "Recursive chmod 777 on root" },
|
|
59582
|
+
{ pattern: /\bchown\s+-R\s+.*\s+\//, reason: "Recursive chown on root" },
|
|
59583
|
+
{ pattern: /\bcurl\s.*\|\s*sh\b/, reason: "Pipe remote script to shell" },
|
|
59584
|
+
{ pattern: /\bwget\s.*\|\s*sh\b/, reason: "Pipe remote script to shell" },
|
|
59585
|
+
{ pattern: /\b\/etc\/passwd\b/, reason: "Access to passwd file" },
|
|
59586
|
+
{ pattern: /\b\/etc\/shadow\b/, reason: "Access to shadow file" }
|
|
59587
|
+
];
|
|
59291
59588
|
BashInputSchema = external_exports.strictObject({
|
|
59292
59589
|
command: external_exports.string().describe("The command to execute"),
|
|
59293
59590
|
description: external_exports.string().optional().describe("Description of what the command does"),
|
|
@@ -59507,6 +59804,14 @@ var init_bash = __esm({
|
|
|
59507
59804
|
if (input.timeout !== void 0 && input.timeout > MAX_BASH_TIMEOUT_MS) {
|
|
59508
59805
|
return { result: false, message: `Timeout exceeds maximum of ${MAX_BASH_TIMEOUT_MS}ms`, errorCode: 2 };
|
|
59509
59806
|
}
|
|
59807
|
+
const danger = isDangerousCommand(input.command);
|
|
59808
|
+
if (danger.dangerous) {
|
|
59809
|
+
try {
|
|
59810
|
+
dbRun("INSERT INTO audit_log (tool_name, input_summary, was_allowed) VALUES ('Bash', ?, 0)", [input.command.slice(0, 200)]);
|
|
59811
|
+
} catch {
|
|
59812
|
+
}
|
|
59813
|
+
return { result: false, message: `Blocked dangerous command: ${danger.reason}`, errorCode: 3 };
|
|
59814
|
+
}
|
|
59510
59815
|
return { result: true };
|
|
59511
59816
|
},
|
|
59512
59817
|
async checkPermissions(input, context) {
|
|
@@ -59587,6 +59892,7 @@ var init_bash = __esm({
|
|
|
59587
59892
|
}
|
|
59588
59893
|
stdout = truncateOutput(stdout);
|
|
59589
59894
|
stderr = truncateOutput(stderr);
|
|
59895
|
+
auditLog(command, code, durationMs);
|
|
59590
59896
|
resolve7({
|
|
59591
59897
|
data: {
|
|
59592
59898
|
stdout,
|
|
@@ -59654,7 +59960,7 @@ Instructions:
|
|
|
59654
59960
|
});
|
|
59655
59961
|
|
|
59656
59962
|
// src/tools/builtin/read.ts
|
|
59657
|
-
import { readFileSync as readFileSync3, statSync, existsSync as
|
|
59963
|
+
import { readFileSync as readFileSync3, statSync, existsSync as existsSync5 } from "fs";
|
|
59658
59964
|
import { extname, isAbsolute, resolve as resolve2 } from "path";
|
|
59659
59965
|
function hasFileBeenRead(filePath) {
|
|
59660
59966
|
return readFiles.has(resolve2(filePath));
|
|
@@ -59835,7 +60141,7 @@ var init_read = __esm({
|
|
|
59835
60141
|
return { result: false, message: "file_path is required", errorCode: 1 };
|
|
59836
60142
|
}
|
|
59837
60143
|
const resolved = resolvePath(input.file_path);
|
|
59838
|
-
if (!
|
|
60144
|
+
if (!existsSync5(resolved)) {
|
|
59839
60145
|
return { result: false, message: `File does not exist: ${input.file_path}`, errorCode: 2 };
|
|
59840
60146
|
}
|
|
59841
60147
|
try {
|
|
@@ -59889,8 +60195,9 @@ Usage:
|
|
|
59889
60195
|
});
|
|
59890
60196
|
|
|
59891
60197
|
// src/tools/builtin/edit.ts
|
|
59892
|
-
import { readFileSync as readFileSync4, writeFileSync as writeFileSync2, existsSync as
|
|
60198
|
+
import { readFileSync as readFileSync4, writeFileSync as writeFileSync2, existsSync as existsSync6 } from "fs";
|
|
59893
60199
|
import { resolve as resolve3, isAbsolute as isAbsolute2 } from "path";
|
|
60200
|
+
import { randomUUID } from "crypto";
|
|
59894
60201
|
function resolvePath2(filePath) {
|
|
59895
60202
|
if (isAbsolute2(filePath)) return filePath;
|
|
59896
60203
|
return resolve3(process.cwd(), filePath);
|
|
@@ -59904,36 +60211,64 @@ function countOccurrences(text, search) {
|
|
|
59904
60211
|
}
|
|
59905
60212
|
return count;
|
|
59906
60213
|
}
|
|
59907
|
-
function
|
|
60214
|
+
function generateUnifiedDiff(oldContent, newContent, filePath) {
|
|
59908
60215
|
const oldLines = oldContent.split("\n");
|
|
59909
60216
|
const newLines = newContent.split("\n");
|
|
59910
|
-
const
|
|
59911
|
-
|
|
59912
|
-
|
|
59913
|
-
|
|
59914
|
-
|
|
59915
|
-
|
|
59916
|
-
|
|
59917
|
-
|
|
59918
|
-
|
|
59919
|
-
|
|
59920
|
-
|
|
59921
|
-
|
|
59922
|
-
|
|
59923
|
-
|
|
59924
|
-
|
|
59925
|
-
|
|
59926
|
-
|
|
59927
|
-
|
|
59928
|
-
|
|
59929
|
-
|
|
59930
|
-
|
|
59931
|
-
|
|
59932
|
-
|
|
60217
|
+
const CONTEXT = 3;
|
|
60218
|
+
const result = [`--- a/${filePath}`, `+++ b/${filePath}`];
|
|
60219
|
+
const hunks = findDiffHunks(oldLines, newLines, CONTEXT);
|
|
60220
|
+
for (const hunk of hunks) {
|
|
60221
|
+
const { oldStart, oldCount, newStart, newCount, lines } = hunk;
|
|
60222
|
+
result.push(`@@ -${oldStart + 1},${oldCount} +${newStart + 1},${newCount} @@`);
|
|
60223
|
+
result.push(...lines);
|
|
60224
|
+
}
|
|
60225
|
+
return result.length > 2 ? result.join("\n") : "";
|
|
60226
|
+
}
|
|
60227
|
+
function findDiffHunks(oldLines, newLines, context) {
|
|
60228
|
+
const hunks = [];
|
|
60229
|
+
let oi = 0, ni = 0;
|
|
60230
|
+
while (oi < oldLines.length || ni < newLines.length) {
|
|
60231
|
+
if (oi < oldLines.length && ni < newLines.length && oldLines[oi] === newLines[ni]) {
|
|
60232
|
+
oi++;
|
|
60233
|
+
ni++;
|
|
60234
|
+
continue;
|
|
60235
|
+
}
|
|
60236
|
+
const changeOldStart = Math.max(0, oi - context);
|
|
60237
|
+
const changeNewStart = Math.max(0, ni - context);
|
|
60238
|
+
const hunkLines = [];
|
|
60239
|
+
for (let c = Math.max(0, oi - context); c < oi; c++) {
|
|
60240
|
+
hunkLines.push(` ${oldLines[c]}`);
|
|
60241
|
+
}
|
|
60242
|
+
const removedStart = oi;
|
|
60243
|
+
while (oi < oldLines.length && (ni >= newLines.length || oldLines[oi] !== newLines[ni])) {
|
|
60244
|
+
hunkLines.push(`-${oldLines[oi]}`);
|
|
60245
|
+
oi++;
|
|
60246
|
+
if (hunkLines.length > 100) break;
|
|
60247
|
+
}
|
|
60248
|
+
const addedStart = ni;
|
|
60249
|
+
while (ni < newLines.length && (oi >= oldLines.length || oldLines[oi] !== newLines[ni])) {
|
|
60250
|
+
hunkLines.push(`+${newLines[ni]}`);
|
|
60251
|
+
ni++;
|
|
60252
|
+
if (hunkLines.length > 200) break;
|
|
60253
|
+
}
|
|
60254
|
+
const afterEnd = Math.min(oi + context, oldLines.length);
|
|
60255
|
+
for (let c = oi; c < afterEnd && c < oldLines.length && ni + (c - oi) < newLines.length; c++) {
|
|
60256
|
+
if (oldLines[c] === newLines[ni + (c - oi)]) {
|
|
60257
|
+
hunkLines.push(` ${oldLines[c]}`);
|
|
59933
60258
|
}
|
|
59934
60259
|
}
|
|
60260
|
+
const oldCount = oi - changeOldStart + Math.min(context, oldLines.length - oi);
|
|
60261
|
+
const newCount = ni - changeNewStart + Math.min(context, newLines.length - ni);
|
|
60262
|
+
hunks.push({
|
|
60263
|
+
oldStart: changeOldStart,
|
|
60264
|
+
oldCount: Math.max(oldCount, 1),
|
|
60265
|
+
newStart: changeNewStart,
|
|
60266
|
+
newCount: Math.max(newCount, 1),
|
|
60267
|
+
lines: hunkLines
|
|
60268
|
+
});
|
|
60269
|
+
if (hunks.length > 20) break;
|
|
59935
60270
|
}
|
|
59936
|
-
return
|
|
60271
|
+
return hunks;
|
|
59937
60272
|
}
|
|
59938
60273
|
var EditInputSchema, EditOutputSchema, editTool, EDIT_PROMPT;
|
|
59939
60274
|
var init_edit = __esm({
|
|
@@ -59942,6 +60277,7 @@ var init_edit = __esm({
|
|
|
59942
60277
|
init_zod();
|
|
59943
60278
|
init_constants();
|
|
59944
60279
|
init_read();
|
|
60280
|
+
init_db();
|
|
59945
60281
|
EditInputSchema = external_exports.strictObject({
|
|
59946
60282
|
file_path: external_exports.string().describe("The absolute path to the file to modify"),
|
|
59947
60283
|
old_string: external_exports.string().describe("The text to replace"),
|
|
@@ -59999,7 +60335,7 @@ var init_edit = __esm({
|
|
|
59999
60335
|
return { result: false, message: "old_string and new_string must be different", errorCode: 2 };
|
|
60000
60336
|
}
|
|
60001
60337
|
const resolved = resolvePath2(input.file_path);
|
|
60002
|
-
if (!
|
|
60338
|
+
if (!existsSync6(resolved)) {
|
|
60003
60339
|
return { result: false, message: `File does not exist: ${input.file_path}`, errorCode: 3 };
|
|
60004
60340
|
}
|
|
60005
60341
|
if (!hasFileBeenRead(resolved)) {
|
|
@@ -60055,9 +60391,17 @@ var init_edit = __esm({
|
|
|
60055
60391
|
newContent = originalContent.slice(0, idx) + input.new_string + originalContent.slice(idx + input.old_string.length);
|
|
60056
60392
|
replacements = 1;
|
|
60057
60393
|
}
|
|
60394
|
+
try {
|
|
60395
|
+
const cpId = randomUUID().slice(0, 8);
|
|
60396
|
+
dbRun(
|
|
60397
|
+
"INSERT INTO checkpoints (id, session_id, file_path, original_content, edit_operation) VALUES (?, ?, ?, ?, ?)",
|
|
60398
|
+
[cpId, "current", resolved, originalContent, JSON.stringify({ old_string: input.old_string, new_string: input.new_string })]
|
|
60399
|
+
);
|
|
60400
|
+
} catch {
|
|
60401
|
+
}
|
|
60058
60402
|
writeFileSync2(resolved, newContent, "utf-8");
|
|
60059
60403
|
markFileAsRead(resolved);
|
|
60060
|
-
const gitDiff =
|
|
60404
|
+
const gitDiff = generateUnifiedDiff(originalContent, newContent, input.file_path);
|
|
60061
60405
|
return {
|
|
60062
60406
|
data: {
|
|
60063
60407
|
filePath: resolved,
|
|
@@ -60093,7 +60437,7 @@ Usage:
|
|
|
60093
60437
|
});
|
|
60094
60438
|
|
|
60095
60439
|
// src/tools/builtin/write.ts
|
|
60096
|
-
import { writeFileSync as writeFileSync3, existsSync as
|
|
60440
|
+
import { writeFileSync as writeFileSync3, existsSync as existsSync7, mkdirSync as mkdirSync4 } from "fs";
|
|
60097
60441
|
import { dirname as dirname2, resolve as resolve4, isAbsolute as isAbsolute3 } from "path";
|
|
60098
60442
|
function resolvePath3(filePath) {
|
|
60099
60443
|
if (isAbsolute3(filePath)) return filePath;
|
|
@@ -60155,7 +60499,7 @@ var init_write = __esm({
|
|
|
60155
60499
|
return { result: false, message: "file_path is required", errorCode: 1 };
|
|
60156
60500
|
}
|
|
60157
60501
|
const resolved = resolvePath3(input.file_path);
|
|
60158
|
-
if (
|
|
60502
|
+
if (existsSync7(resolved) && !hasFileBeenRead(resolved)) {
|
|
60159
60503
|
return {
|
|
60160
60504
|
result: false,
|
|
60161
60505
|
message: "This file already exists. You must Read it first before overwriting. Use the Read tool, then retry.",
|
|
@@ -60169,10 +60513,10 @@ var init_write = __esm({
|
|
|
60169
60513
|
},
|
|
60170
60514
|
async call(input, context) {
|
|
60171
60515
|
const resolved = resolvePath3(input.file_path);
|
|
60172
|
-
const created = !
|
|
60516
|
+
const created = !existsSync7(resolved);
|
|
60173
60517
|
const dir = dirname2(resolved);
|
|
60174
|
-
if (!
|
|
60175
|
-
|
|
60518
|
+
if (!existsSync7(dir)) {
|
|
60519
|
+
mkdirSync4(dir, { recursive: true });
|
|
60176
60520
|
}
|
|
60177
60521
|
writeFileSync3(resolved, input.content, "utf-8");
|
|
60178
60522
|
markFileAsRead(resolved);
|
|
@@ -67042,10 +67386,11 @@ function useSpinner(active) {
|
|
|
67042
67386
|
}, [active]);
|
|
67043
67387
|
return active ? FRAMES[i] : " ";
|
|
67044
67388
|
}
|
|
67045
|
-
function createToolHandlers(onToolStart, onToolEnd) {
|
|
67389
|
+
function createToolHandlers(onToolStart, onToolEnd, requestPermission) {
|
|
67046
67390
|
const tools = [bashTool, readTool, editTool, writeTool, globTool, grepTool];
|
|
67047
67391
|
const permCtx = createDefaultPermissionContext();
|
|
67048
67392
|
const appState = { toolPermissionContext: permCtx, verbose: false };
|
|
67393
|
+
const alwaysAllowed = /* @__PURE__ */ new Set();
|
|
67049
67394
|
return tools.map((tool) => ({
|
|
67050
67395
|
name: tool.name,
|
|
67051
67396
|
description: typeof tool.description === "function" ? `Tool: ${tool.name}` : String(tool.description),
|
|
@@ -67055,6 +67400,25 @@ function createToolHandlers(onToolStart, onToolEnd) {
|
|
|
67055
67400
|
call: async (input, ctx) => {
|
|
67056
67401
|
const summary = toolSummary(tool.name, input);
|
|
67057
67402
|
const toolId = `tool-${Date.now()}-${Math.random().toString(36).slice(2, 6)}`;
|
|
67403
|
+
if (!tool.isReadOnly() && !alwaysAllowed.has(tool.name)) {
|
|
67404
|
+
const decision = await requestPermission(tool.name, summary);
|
|
67405
|
+
if (decision === "deny") {
|
|
67406
|
+
onToolStart(toolId, tool.name, summary);
|
|
67407
|
+
onToolEnd(toolId, "Permission denied by user", "Permission denied", 0);
|
|
67408
|
+
try {
|
|
67409
|
+
dbRun("INSERT INTO audit_log (tool_name, input_summary, was_allowed) VALUES (?, ?, 0)", [tool.name, summary]);
|
|
67410
|
+
} catch {
|
|
67411
|
+
}
|
|
67412
|
+
return { error: "Permission denied by user", isError: true };
|
|
67413
|
+
}
|
|
67414
|
+
if (decision === "always") {
|
|
67415
|
+
alwaysAllowed.add(tool.name);
|
|
67416
|
+
try {
|
|
67417
|
+
dbRun("INSERT OR REPLACE INTO permissions (tool_name, behavior) VALUES (?, 'allow')", [tool.name]);
|
|
67418
|
+
} catch {
|
|
67419
|
+
}
|
|
67420
|
+
}
|
|
67421
|
+
}
|
|
67058
67422
|
onToolStart(toolId, tool.name, summary);
|
|
67059
67423
|
const t0 = performance.now();
|
|
67060
67424
|
try {
|
|
@@ -67068,11 +67432,19 @@ function createToolHandlers(onToolStart, onToolEnd) {
|
|
|
67068
67432
|
const block = tool.mapToolResultToToolResultBlockParam(result.data, toolId);
|
|
67069
67433
|
const dur = performance.now() - t0;
|
|
67070
67434
|
onToolEnd(toolId, block.content.slice(0, 500), block.is_error ? block.content : void 0, dur);
|
|
67435
|
+
try {
|
|
67436
|
+
dbRun("INSERT INTO audit_log (tool_name, input_summary, result_summary, duration_ms, was_allowed) VALUES (?, ?, ?, ?, 1)", [tool.name, summary, block.content.slice(0, 200), dur]);
|
|
67437
|
+
} catch {
|
|
67438
|
+
}
|
|
67071
67439
|
return { data: block.content };
|
|
67072
67440
|
} catch (err) {
|
|
67073
67441
|
const dur = performance.now() - t0;
|
|
67074
67442
|
const errMsg = err instanceof Error ? err.message : String(err);
|
|
67075
67443
|
onToolEnd(toolId, "", errMsg, dur);
|
|
67444
|
+
try {
|
|
67445
|
+
dbRun("INSERT INTO audit_log (tool_name, input_summary, result_summary, duration_ms, was_allowed) VALUES (?, ?, ?, ?, 1)", [tool.name, summary, errMsg.slice(0, 200), dur]);
|
|
67446
|
+
} catch {
|
|
67447
|
+
}
|
|
67076
67448
|
return { error: errMsg, isError: true };
|
|
67077
67449
|
}
|
|
67078
67450
|
}
|
|
@@ -67192,6 +67564,25 @@ function App2({ model, mode, initialPrompt }) {
|
|
|
67192
67564
|
const [history, setHistory] = (0, import_react22.useState)([]);
|
|
67193
67565
|
const [activeTools, setActiveTools] = (0, import_react22.useState)([]);
|
|
67194
67566
|
const rows = stdout?.rows ?? 24;
|
|
67567
|
+
const [permissionPending, setPermissionPending] = (0, import_react22.useState)(null);
|
|
67568
|
+
const requestPermission = (0, import_react22.useCallback)((toolName, summary) => {
|
|
67569
|
+
return new Promise((resolve7) => {
|
|
67570
|
+
setPermissionPending({ toolName, summary, resolve: resolve7 });
|
|
67571
|
+
});
|
|
67572
|
+
}, []);
|
|
67573
|
+
use_input_default((ch) => {
|
|
67574
|
+
if (!permissionPending) return;
|
|
67575
|
+
if (ch === "y" || ch === "Y") {
|
|
67576
|
+
permissionPending.resolve("allow");
|
|
67577
|
+
setPermissionPending(null);
|
|
67578
|
+
} else if (ch === "n" || ch === "N") {
|
|
67579
|
+
permissionPending.resolve("deny");
|
|
67580
|
+
setPermissionPending(null);
|
|
67581
|
+
} else if (ch === "a" || ch === "A") {
|
|
67582
|
+
permissionPending.resolve("always");
|
|
67583
|
+
setPermissionPending(null);
|
|
67584
|
+
}
|
|
67585
|
+
}, { isActive: !!permissionPending });
|
|
67195
67586
|
const onToolStart = (0, import_react22.useCallback)((id, name, summary) => {
|
|
67196
67587
|
setActiveTools((prev) => [...prev, { id, name, summary, status: "running" }]);
|
|
67197
67588
|
}, []);
|
|
@@ -67222,7 +67613,7 @@ function App2({ model, mode, initialPrompt }) {
|
|
|
67222
67613
|
setActiveTools([]);
|
|
67223
67614
|
const t0 = performance.now();
|
|
67224
67615
|
try {
|
|
67225
|
-
const toolHandlers = createToolHandlers(onToolStart, onToolEnd);
|
|
67616
|
+
const toolHandlers = createToolHandlers(onToolStart, onToolEnd, requestPermission);
|
|
67226
67617
|
const permCtx = createDefaultPermissionContext();
|
|
67227
67618
|
const result = await runAgentLoop(
|
|
67228
67619
|
newHistory,
|
|
@@ -67284,11 +67675,12 @@ function App2({ model, mode, initialPrompt }) {
|
|
|
67284
67675
|
} finally {
|
|
67285
67676
|
setBusy(false);
|
|
67286
67677
|
}
|
|
67287
|
-
}, [busy, history, model, exit, onToolStart, onToolEnd, streaming, activeTools]);
|
|
67678
|
+
}, [busy, history, model, exit, onToolStart, onToolEnd, requestPermission, streaming, activeTools]);
|
|
67288
67679
|
(0, import_react22.useEffect)(() => {
|
|
67289
67680
|
if (initialPrompt) submit(initialPrompt);
|
|
67290
67681
|
}, []);
|
|
67291
67682
|
use_input_default((ch, key) => {
|
|
67683
|
+
if (permissionPending) return;
|
|
67292
67684
|
if (busy) {
|
|
67293
67685
|
if (key.ctrl && ch === "c") {
|
|
67294
67686
|
setBusy(false);
|
|
@@ -67316,22 +67708,46 @@ function App2({ model, mode, initialPrompt }) {
|
|
|
67316
67708
|
visible.map((m) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(MessageView, { msg: m }, m.id)),
|
|
67317
67709
|
busy && activeTools.filter((t) => t.status === "running").map((t) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ToolItem, { tool: t }, t.id)),
|
|
67318
67710
|
busy && streaming && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Box_default, { marginTop: 1, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, { children: streaming }) }),
|
|
67319
|
-
busy && !streaming && activeTools.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Box_default, { marginTop: 1, children: [
|
|
67711
|
+
busy && !streaming && activeTools.length === 0 && !permissionPending && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Box_default, { marginTop: 1, children: [
|
|
67320
67712
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Text, { color: "cyan", children: [
|
|
67321
67713
|
FRAMES[0],
|
|
67322
67714
|
" "
|
|
67323
67715
|
] }),
|
|
67324
67716
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, { dimColor: true, children: "Thinking..." })
|
|
67717
|
+
] }),
|
|
67718
|
+
permissionPending && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Box_default, { flexDirection: "column", marginTop: 1, children: [
|
|
67719
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Box_default, { children: [
|
|
67720
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, { color: "yellow", bold: true, children: "? " }),
|
|
67721
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, { children: "Allow " }),
|
|
67722
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, { bold: true, children: permissionPending.toolName }),
|
|
67723
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Text, { dimColor: true, children: [
|
|
67724
|
+
": ",
|
|
67725
|
+
permissionPending.summary.slice(0, 80)
|
|
67726
|
+
] })
|
|
67727
|
+
] }),
|
|
67728
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Box_default, { children: [
|
|
67729
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, { dimColor: true, children: " " }),
|
|
67730
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, { color: "green", bold: true, children: "(y)" }),
|
|
67731
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, { color: "green", children: "es" }),
|
|
67732
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, { children: " " }),
|
|
67733
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, { color: "red", bold: true, children: "(n)" }),
|
|
67734
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, { color: "red", children: "o" }),
|
|
67735
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, { children: " " }),
|
|
67736
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, { color: "blue", bold: true, children: "(a)" }),
|
|
67737
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, { color: "blue", children: "lways allow" })
|
|
67738
|
+
] })
|
|
67325
67739
|
] })
|
|
67326
67740
|
] }),
|
|
67741
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Box_default, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, { dimColor: true, children: "\u2500".repeat(Math.min(stdout?.columns ?? 80, 120)) }) }),
|
|
67327
67742
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Box_default, { children: [
|
|
67328
67743
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Text, { color: "cyan", bold: true, children: [
|
|
67329
67744
|
PROMPT,
|
|
67330
67745
|
" "
|
|
67331
67746
|
] }),
|
|
67332
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, { children: input }),
|
|
67747
|
+
input.startsWith("/") ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, { color: "magenta", children: input }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, { children: input }),
|
|
67333
67748
|
!busy && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, { color: "gray", children: "\u258E" })
|
|
67334
67749
|
] }),
|
|
67750
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Box_default, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, { dimColor: true, children: "\u2500".repeat(Math.min(stdout?.columns ?? 80, 120)) }) }),
|
|
67335
67751
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(StatusBar, { model, mode, cost, tokens })
|
|
67336
67752
|
] });
|
|
67337
67753
|
}
|
|
@@ -67392,6 +67808,7 @@ var init_app = __esm({
|
|
|
67392
67808
|
init_streaming();
|
|
67393
67809
|
init_agent_loop();
|
|
67394
67810
|
init_permissions();
|
|
67811
|
+
init_db();
|
|
67395
67812
|
init_bash();
|
|
67396
67813
|
init_read();
|
|
67397
67814
|
init_edit();
|
|
@@ -67619,8 +68036,8 @@ async function bootstrap() {
|
|
|
67619
68036
|
var VERSION, BUILD_TIME, PACKAGE_NAME2, ISSUES_URL2, startupTimestamps, originalCwd, RESET_TERMINAL, cleanupHandlers, earlyInput, earlyInputCapturing;
|
|
67620
68037
|
var init_index = __esm({
|
|
67621
68038
|
"src/cli/index.ts"() {
|
|
67622
|
-
VERSION = "0.0.
|
|
67623
|
-
BUILD_TIME = "2026-03-
|
|
68039
|
+
VERSION = "0.0.5";
|
|
68040
|
+
BUILD_TIME = "2026-03-20T07:42:41.423Z";
|
|
67624
68041
|
PACKAGE_NAME2 = "@hasna/coders";
|
|
67625
68042
|
ISSUES_URL2 = "https://github.com/hasnaxyz/open-coders/issues";
|
|
67626
68043
|
startupTimestamps = {};
|