deepcode-ai 1.1.26 → 1.1.28
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 +212 -44
- package/dist/index.js.map +1 -1
- package/package.json +3 -2
package/dist/index.js
CHANGED
|
@@ -2281,8 +2281,8 @@ var PermissionDeniedError = class extends DeepCodeError {
|
|
|
2281
2281
|
}
|
|
2282
2282
|
};
|
|
2283
2283
|
var PathNotAllowedError = class extends DeepCodeError {
|
|
2284
|
-
constructor(
|
|
2285
|
-
super(`Path is not allowed: ${
|
|
2284
|
+
constructor(path152, reason) {
|
|
2285
|
+
super(`Path is not allowed: ${path152}. ${reason}`, "PATH_NOT_ALLOWED");
|
|
2286
2286
|
this.name = "PathNotAllowedError";
|
|
2287
2287
|
}
|
|
2288
2288
|
};
|
|
@@ -3489,7 +3489,7 @@ Caminho: ${selectedPath}`;
|
|
|
3489
3489
|
const effectiveModel = resolvedModel;
|
|
3490
3490
|
if (!effectiveModel) {
|
|
3491
3491
|
throw new Error(
|
|
3492
|
-
|
|
3492
|
+
`No model configured for ${resolvedTarget.provider}. Run /model or set defaultModels.${resolvedTarget.provider} in .deepcode/config.json, or set DEEPCODE_MODEL.`
|
|
3493
3493
|
);
|
|
3494
3494
|
}
|
|
3495
3495
|
session.status = "planning";
|
|
@@ -3552,7 +3552,7 @@ Caminho: ${selectedPath}`;
|
|
|
3552
3552
|
const model = options.model ?? session.model ?? resolveConfiguredModelForProvider(this.config, providerId);
|
|
3553
3553
|
if (!model) {
|
|
3554
3554
|
throw new Error(
|
|
3555
|
-
|
|
3555
|
+
`No model configured for ${providerId}. Run /model or set defaultModels.${providerId} in .deepcode/config.json, or set DEEPCODE_MODEL.`
|
|
3556
3556
|
);
|
|
3557
3557
|
}
|
|
3558
3558
|
const alreadyTrackingBudget = this.activeBudgets.has(session.id);
|
|
@@ -3919,6 +3919,7 @@ ${assistantText}` : assistantText;
|
|
|
3919
3919
|
errorMessage: `Invalid arguments for ${call.name}: ${parsed.error.message}`
|
|
3920
3920
|
};
|
|
3921
3921
|
}
|
|
3922
|
+
const scopedSecurity = this.securityForSession(session);
|
|
3922
3923
|
const context = {
|
|
3923
3924
|
sessionId: session.id,
|
|
3924
3925
|
messageId: createId("msg"),
|
|
@@ -3928,8 +3929,8 @@ ${assistantText}` : assistantText;
|
|
|
3928
3929
|
config: this.config,
|
|
3929
3930
|
agentMode: mode,
|
|
3930
3931
|
cache: this.cache,
|
|
3931
|
-
permissions:
|
|
3932
|
-
pathSecurity:
|
|
3932
|
+
permissions: scopedSecurity.permissions,
|
|
3933
|
+
pathSecurity: scopedSecurity.pathSecurity,
|
|
3933
3934
|
logActivity: (activity) => {
|
|
3934
3935
|
const full = { ...activity, id: createId("activity"), createdAt: nowIso() };
|
|
3935
3936
|
session.activities.push(full);
|
|
@@ -3979,6 +3980,13 @@ ${assistantText}` : assistantText;
|
|
|
3979
3980
|
};
|
|
3980
3981
|
}
|
|
3981
3982
|
}
|
|
3983
|
+
securityForSession(session) {
|
|
3984
|
+
const pathSecurity = this.pathSecurity.forWorktree(session.worktree);
|
|
3985
|
+
return {
|
|
3986
|
+
pathSecurity,
|
|
3987
|
+
permissions: this.permissions.forPathSecurity(pathSecurity)
|
|
3988
|
+
};
|
|
3989
|
+
}
|
|
3982
3990
|
logToolActivity(session, activity) {
|
|
3983
3991
|
const full = { ...activity, id: createId("activity"), createdAt: nowIso() };
|
|
3984
3992
|
session.activities.push(full);
|
|
@@ -4234,8 +4242,9 @@ ${assistantText}` : assistantText;
|
|
|
4234
4242
|
return "Git nao esta instalado. Quer que eu instale?";
|
|
4235
4243
|
}
|
|
4236
4244
|
const scanInput = inputPath === "." ? process.env.HOME ?? inputPath : inputPath;
|
|
4237
|
-
const
|
|
4238
|
-
await
|
|
4245
|
+
const security = this.securityForSession(session);
|
|
4246
|
+
const rootPath = await security.pathSecurity.normalize(scanInput, { enforceAccess: false });
|
|
4247
|
+
await security.permissions.ensure({ operation: "list_projects", kind: "read", path: rootPath });
|
|
4239
4248
|
const results = [];
|
|
4240
4249
|
await this.walkForProjects(rootPath, 3, results, /* @__PURE__ */ new Set());
|
|
4241
4250
|
if (results.length === 0) {
|
|
@@ -5043,13 +5052,13 @@ var GitHubClient = class {
|
|
|
5043
5052
|
}
|
|
5044
5053
|
return parseGitHubRemote(result.stdout.trim());
|
|
5045
5054
|
}
|
|
5046
|
-
async request(
|
|
5055
|
+
async request(path152, init = {}) {
|
|
5047
5056
|
if (!this.options.token) {
|
|
5048
5057
|
throw new Error(
|
|
5049
5058
|
"GitHub token is required. Set GITHUB_TOKEN or .deepcode/config.json github.token."
|
|
5050
5059
|
);
|
|
5051
5060
|
}
|
|
5052
|
-
const response = await fetch(`${this.apiBase}${
|
|
5061
|
+
const response = await fetch(`${this.apiBase}${path152}`, {
|
|
5053
5062
|
...init,
|
|
5054
5063
|
headers: {
|
|
5055
5064
|
accept: "application/vnd.github+json",
|
|
@@ -5065,13 +5074,13 @@ var GitHubClient = class {
|
|
|
5065
5074
|
if (response.status === 204) return void 0;
|
|
5066
5075
|
return await response.json();
|
|
5067
5076
|
}
|
|
5068
|
-
async requestText(
|
|
5077
|
+
async requestText(path152, init = {}) {
|
|
5069
5078
|
if (!this.options.token) {
|
|
5070
5079
|
throw new Error(
|
|
5071
5080
|
"GitHub token is required. Set GITHUB_TOKEN or .deepcode/config.json github.token."
|
|
5072
5081
|
);
|
|
5073
5082
|
}
|
|
5074
|
-
const response = await fetch(`${this.apiBase}${
|
|
5083
|
+
const response = await fetch(`${this.apiBase}${path152}`, {
|
|
5075
5084
|
...init,
|
|
5076
5085
|
headers: {
|
|
5077
5086
|
accept: "application/vnd.github+json",
|
|
@@ -5539,12 +5548,12 @@ function fromFileUri(uri) {
|
|
|
5539
5548
|
var SECRET_KEY_PATTERN = /(api[_-]?key|token|authorization|secret|password|passwd|credential|private[_-]?key)/i;
|
|
5540
5549
|
var MIN_SECRET_VALUE_LENGTH = 4;
|
|
5541
5550
|
function redactSecrets(value, options = {}) {
|
|
5542
|
-
const
|
|
5551
|
+
const path152 = options.path ?? [];
|
|
5543
5552
|
const secretPlaceholder = options.secretPlaceholder ?? "[redacted]";
|
|
5544
5553
|
const emptySecretPlaceholder = options.emptySecretPlaceholder ?? "[empty]";
|
|
5545
5554
|
const secretValues = options.secretValues ?? collectSecretValues();
|
|
5546
5555
|
if (typeof value === "string") {
|
|
5547
|
-
if (isSecretPath(
|
|
5556
|
+
if (isSecretPath(path152)) {
|
|
5548
5557
|
return value.length > 0 ? secretPlaceholder : emptySecretPlaceholder;
|
|
5549
5558
|
}
|
|
5550
5559
|
return redactText(value, secretValues, secretPlaceholder);
|
|
@@ -5553,7 +5562,7 @@ function redactSecrets(value, options = {}) {
|
|
|
5553
5562
|
return value.map(
|
|
5554
5563
|
(item, index) => redactSecrets(item, {
|
|
5555
5564
|
...options,
|
|
5556
|
-
path: [...
|
|
5565
|
+
path: [...path152, String(index)],
|
|
5557
5566
|
secretValues
|
|
5558
5567
|
})
|
|
5559
5568
|
);
|
|
@@ -5564,7 +5573,7 @@ function redactSecrets(value, options = {}) {
|
|
|
5564
5573
|
key,
|
|
5565
5574
|
redactSecrets(item, {
|
|
5566
5575
|
...options,
|
|
5567
|
-
path: [...
|
|
5576
|
+
path: [...path152, key],
|
|
5568
5577
|
secretValues
|
|
5569
5578
|
})
|
|
5570
5579
|
])
|
|
@@ -5602,8 +5611,8 @@ function collectSecretValues(config) {
|
|
|
5602
5611
|
}
|
|
5603
5612
|
return [...values].sort((left, right) => right.length - left.length);
|
|
5604
5613
|
}
|
|
5605
|
-
function isSecretPath(
|
|
5606
|
-
const key =
|
|
5614
|
+
function isSecretPath(path152) {
|
|
5615
|
+
const key = path152[path152.length - 1] ?? "";
|
|
5607
5616
|
if (/(api[_-]?key|token|secret|credential).*file/i.test(key)) return false;
|
|
5608
5617
|
return SECRET_KEY_PATTERN.test(key);
|
|
5609
5618
|
}
|
|
@@ -6485,10 +6494,14 @@ function globToRegex(glob) {
|
|
|
6485
6494
|
}
|
|
6486
6495
|
return new RegExp(`^${globPatternToRegexSource(glob)}$`);
|
|
6487
6496
|
}
|
|
6488
|
-
var PathSecurity = class {
|
|
6497
|
+
var PathSecurity = class _PathSecurity {
|
|
6489
6498
|
constructor(worktree, rules) {
|
|
6490
6499
|
this.worktree = worktree;
|
|
6491
6500
|
this.home = process.env.HOME ?? os2.homedir();
|
|
6501
|
+
this.sourceRules = {
|
|
6502
|
+
whitelist: [...rules.whitelist],
|
|
6503
|
+
blacklist: [...rules.blacklist]
|
|
6504
|
+
};
|
|
6492
6505
|
this.rules = {
|
|
6493
6506
|
whitelist: rules.whitelist.map((rule) => this.expand(rule, this.home)),
|
|
6494
6507
|
blacklist: rules.blacklist.map((rule) => this.expand(rule, this.home))
|
|
@@ -6496,7 +6509,11 @@ var PathSecurity = class {
|
|
|
6496
6509
|
}
|
|
6497
6510
|
worktree;
|
|
6498
6511
|
rules;
|
|
6512
|
+
sourceRules;
|
|
6499
6513
|
home;
|
|
6514
|
+
forWorktree(worktree) {
|
|
6515
|
+
return new _PathSecurity(path7.resolve(worktree), this.sourceRules);
|
|
6516
|
+
}
|
|
6500
6517
|
async normalize(inputPath, options = {}) {
|
|
6501
6518
|
const enforceAccess = options.enforceAccess ?? true;
|
|
6502
6519
|
const resolved = await this.resolvePath(inputPath);
|
|
@@ -6556,13 +6573,16 @@ var PathSecurity = class {
|
|
|
6556
6573
|
return targetPath;
|
|
6557
6574
|
}
|
|
6558
6575
|
};
|
|
6559
|
-
var PermissionGateway = class {
|
|
6560
|
-
constructor(config, pathSecurity, audit, eventBus, interactive = false) {
|
|
6576
|
+
var PermissionGateway = class _PermissionGateway {
|
|
6577
|
+
constructor(config, pathSecurity, audit, eventBus, interactive = false, state) {
|
|
6561
6578
|
this.config = config;
|
|
6562
6579
|
this.pathSecurity = pathSecurity;
|
|
6563
6580
|
this.audit = audit;
|
|
6564
6581
|
this.eventBus = eventBus;
|
|
6565
6582
|
this.interactive = interactive;
|
|
6583
|
+
this.sessionAllowSet = state?.sessionAllowSet ?? /* @__PURE__ */ new Set();
|
|
6584
|
+
this.alwaysAllowSet = state?.alwaysAllowSet ?? /* @__PURE__ */ new Set();
|
|
6585
|
+
this.pendingApprovals = state?.pendingApprovals ?? /* @__PURE__ */ new Map();
|
|
6566
6586
|
}
|
|
6567
6587
|
config;
|
|
6568
6588
|
pathSecurity;
|
|
@@ -6570,11 +6590,25 @@ var PermissionGateway = class {
|
|
|
6570
6590
|
eventBus;
|
|
6571
6591
|
interactive;
|
|
6572
6592
|
/** Set of operation+path keys that were approved for the current session */
|
|
6573
|
-
sessionAllowSet
|
|
6593
|
+
sessionAllowSet;
|
|
6574
6594
|
/** Set of operation+path keys that were approved permanently (always) */
|
|
6575
|
-
alwaysAllowSet
|
|
6595
|
+
alwaysAllowSet;
|
|
6576
6596
|
/** Map of pending approval requests by request ID */
|
|
6577
|
-
pendingApprovals
|
|
6597
|
+
pendingApprovals;
|
|
6598
|
+
forPathSecurity(pathSecurity) {
|
|
6599
|
+
return new _PermissionGateway(
|
|
6600
|
+
this.config,
|
|
6601
|
+
pathSecurity,
|
|
6602
|
+
this.audit,
|
|
6603
|
+
this.eventBus,
|
|
6604
|
+
this.interactive,
|
|
6605
|
+
{
|
|
6606
|
+
sessionAllowSet: this.sessionAllowSet,
|
|
6607
|
+
alwaysAllowSet: this.alwaysAllowSet,
|
|
6608
|
+
pendingApprovals: this.pendingApprovals
|
|
6609
|
+
}
|
|
6610
|
+
);
|
|
6611
|
+
}
|
|
6578
6612
|
/** Clear all session-scoped permissions (e.g., when session ends) */
|
|
6579
6613
|
clearSessionAllowSet() {
|
|
6580
6614
|
this.sessionAllowSet.clear();
|
|
@@ -7824,8 +7858,8 @@ import { useState as useState22, useEffect as useEffect22, useCallback as useCal
|
|
|
7824
7858
|
import { Box as Box2, Text as Text22, useInput as useInput2, useApp as useApp2 } from "ink";
|
|
7825
7859
|
import path42 from "path";
|
|
7826
7860
|
import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
7827
|
-
import
|
|
7828
|
-
import
|
|
7861
|
+
import fs8 from "fs";
|
|
7862
|
+
import path15 from "path";
|
|
7829
7863
|
import { isValidElement, useCallback as useCallback26, useEffect as useEffect27, useMemo as useMemo18, useRef as useRef17, useState as useState29 } from "react";
|
|
7830
7864
|
import { Box as Box42, Text as Text50, useInput as useInput6, useStdin as useStdin3 } from "ink";
|
|
7831
7865
|
import os4 from "os";
|
|
@@ -9810,6 +9844,9 @@ import { jsx as jsx39, jsxs as jsxs35 } from "react/jsx-runtime";
|
|
|
9810
9844
|
import { Box as Box31, Text as Text39 } from "ink";
|
|
9811
9845
|
import { jsx as jsx40, jsxs as jsxs36 } from "react/jsx-runtime";
|
|
9812
9846
|
import { jsx as jsx41, jsxs as jsxs37 } from "react/jsx-runtime";
|
|
9847
|
+
import fs6 from "fs";
|
|
9848
|
+
import os5 from "os";
|
|
9849
|
+
import path132 from "path";
|
|
9813
9850
|
import { Box as Box33, Text as Text41 } from "ink";
|
|
9814
9851
|
import { jsx as jsx42, jsxs as jsxs38 } from "react/jsx-runtime";
|
|
9815
9852
|
import { useCallback as useCallback19, useMemo as useMemo11, useRef as useRef14 } from "react";
|
|
@@ -9827,8 +9864,8 @@ import { jsx as jsx46, jsxs as jsxs42 } from "react/jsx-runtime";
|
|
|
9827
9864
|
import { useCallback as useCallback23, useEffect as useEffect25, useMemo as useMemo15, useRef as useRef16, useState as useState27 } from "react";
|
|
9828
9865
|
import { Box as Box38, Text as Text46, useInput as useInput4 } from "ink";
|
|
9829
9866
|
import { jsx as jsx47, jsxs as jsxs43 } from "react/jsx-runtime";
|
|
9830
|
-
import
|
|
9831
|
-
import
|
|
9867
|
+
import fs7 from "fs";
|
|
9868
|
+
import path142 from "path";
|
|
9832
9869
|
import { useCallback as useCallback24, useMemo as useMemo16 } from "react";
|
|
9833
9870
|
import { Box as Box39, Text as Text47 } from "ink";
|
|
9834
9871
|
import { jsx as jsx48, jsxs as jsxs44 } from "react/jsx-runtime";
|
|
@@ -28039,6 +28076,109 @@ var compactCommand = {
|
|
|
28039
28076
|
await context.ui.compact();
|
|
28040
28077
|
}
|
|
28041
28078
|
};
|
|
28079
|
+
var CACHE_TTL_MS = 24 * 60 * 60 * 1e3;
|
|
28080
|
+
var PACKAGE_NAME = "deepcode-ai";
|
|
28081
|
+
function cachePath() {
|
|
28082
|
+
const cacheHome = process.env["XDG_CACHE_HOME"] ?? path132.join(os5.homedir(), ".cache");
|
|
28083
|
+
return path132.join(cacheHome, "deepcode-ai", "update.json");
|
|
28084
|
+
}
|
|
28085
|
+
function readCache() {
|
|
28086
|
+
try {
|
|
28087
|
+
const raw = fs6.readFileSync(cachePath(), "utf8");
|
|
28088
|
+
const parsed = JSON.parse(raw);
|
|
28089
|
+
if (typeof parsed.checkedAt !== "number" || typeof parsed.latest !== "string" || Date.now() - parsed.checkedAt >= CACHE_TTL_MS) {
|
|
28090
|
+
return null;
|
|
28091
|
+
}
|
|
28092
|
+
return {
|
|
28093
|
+
checkedAt: parsed.checkedAt,
|
|
28094
|
+
latest: parsed.latest,
|
|
28095
|
+
stable: typeof parsed.stable === "string" ? parsed.stable : null
|
|
28096
|
+
};
|
|
28097
|
+
} catch {
|
|
28098
|
+
return null;
|
|
28099
|
+
}
|
|
28100
|
+
}
|
|
28101
|
+
function writeCache(cache) {
|
|
28102
|
+
try {
|
|
28103
|
+
const filePath = cachePath();
|
|
28104
|
+
fs6.mkdirSync(path132.dirname(filePath), { recursive: true });
|
|
28105
|
+
fs6.writeFileSync(filePath, `${JSON.stringify(cache)}
|
|
28106
|
+
`, "utf8");
|
|
28107
|
+
} catch {
|
|
28108
|
+
}
|
|
28109
|
+
}
|
|
28110
|
+
async function checkForUpdate(_currentVersion, options = {}) {
|
|
28111
|
+
if (process.env["CI"] || process.env["NODE_ENV"] === "test" || process.env["DEEPCODE_DISABLE_UPDATE_CHECK"] === "1") {
|
|
28112
|
+
return null;
|
|
28113
|
+
}
|
|
28114
|
+
if (!options.force) {
|
|
28115
|
+
const cached = readCache();
|
|
28116
|
+
if (cached) {
|
|
28117
|
+
return { latest: cached.latest, stable: cached.stable };
|
|
28118
|
+
}
|
|
28119
|
+
}
|
|
28120
|
+
try {
|
|
28121
|
+
const response = await fetch(
|
|
28122
|
+
`https://registry.npmjs.org/-/package/${PACKAGE_NAME}/dist-tags`,
|
|
28123
|
+
{ signal: AbortSignal.timeout(3e3) }
|
|
28124
|
+
);
|
|
28125
|
+
if (!response.ok) return null;
|
|
28126
|
+
const tags = await response.json();
|
|
28127
|
+
const latest = tags["latest"];
|
|
28128
|
+
if (typeof latest !== "string" || latest.length === 0) return null;
|
|
28129
|
+
const stable = typeof tags["stable"] === "string" && tags["stable"].length > 0 ? tags["stable"] : null;
|
|
28130
|
+
const update = { latest, stable };
|
|
28131
|
+
writeCache({ ...update, checkedAt: Date.now() });
|
|
28132
|
+
return update;
|
|
28133
|
+
} catch {
|
|
28134
|
+
return null;
|
|
28135
|
+
}
|
|
28136
|
+
}
|
|
28137
|
+
function isNewer(current, candidate) {
|
|
28138
|
+
const currentParts = parseVersion2(current);
|
|
28139
|
+
const candidateParts = parseVersion2(candidate);
|
|
28140
|
+
if (!currentParts || !candidateParts) return false;
|
|
28141
|
+
for (let index = 0; index < 3; index += 1) {
|
|
28142
|
+
const currentPart = currentParts[index] ?? 0;
|
|
28143
|
+
const candidatePart = candidateParts[index] ?? 0;
|
|
28144
|
+
if (candidatePart !== currentPart) {
|
|
28145
|
+
return candidatePart > currentPart;
|
|
28146
|
+
}
|
|
28147
|
+
}
|
|
28148
|
+
return false;
|
|
28149
|
+
}
|
|
28150
|
+
function parseVersion2(version) {
|
|
28151
|
+
const match = version.trim().match(/^v?(\d+)\.(\d+)\.(\d+)(?:[-+].*)?$/);
|
|
28152
|
+
if (!match) return null;
|
|
28153
|
+
return [Number(match[1]), Number(match[2]), Number(match[3])];
|
|
28154
|
+
}
|
|
28155
|
+
var VERSION = "1.1.28".length > 0 ? "1.1.28" : "0.0.0-dev";
|
|
28156
|
+
var updateCommand = {
|
|
28157
|
+
name: "update",
|
|
28158
|
+
description: "Check published DeepCode versions",
|
|
28159
|
+
kind: "built-in",
|
|
28160
|
+
supportedModes: ["interactive"],
|
|
28161
|
+
action: async () => {
|
|
28162
|
+
const update = await checkForUpdate(VERSION, { force: true });
|
|
28163
|
+
const lines = [`Current version: ${VERSION}`];
|
|
28164
|
+
if (!update) {
|
|
28165
|
+
lines.push("Could not reach the npm registry right now.");
|
|
28166
|
+
} else {
|
|
28167
|
+
const latestStatus = isNewer(VERSION, update.latest) ? "available" : "current or older";
|
|
28168
|
+
lines.push(`Latest version: ${update.latest} (${latestStatus})`);
|
|
28169
|
+
if (update.stable) {
|
|
28170
|
+
const stableStatus = isNewer(VERSION, update.stable) ? "available" : "current or older";
|
|
28171
|
+
lines.push(`Stable version: ${update.stable} (${stableStatus})`);
|
|
28172
|
+
} else {
|
|
28173
|
+
lines.push("Stable version: not published yet");
|
|
28174
|
+
}
|
|
28175
|
+
}
|
|
28176
|
+
lines.push("");
|
|
28177
|
+
lines.push("Install latest: npm install -g deepcode-ai@latest");
|
|
28178
|
+
lines.push("Install stable: npm install -g deepcode-ai@stable");
|
|
28179
|
+
return { type: "message", messageType: "info", content: lines.join("\n") };
|
|
28180
|
+
}
|
|
28181
|
+
};
|
|
28042
28182
|
function sessionNotReady() {
|
|
28043
28183
|
return {
|
|
28044
28184
|
type: "message",
|
|
@@ -29093,11 +29233,11 @@ var RATINGS = [
|
|
|
29093
29233
|
];
|
|
29094
29234
|
var CANCEL_VALUE2 = "__cancel__";
|
|
29095
29235
|
function appendFeedbackEntry(cwd, rating, label) {
|
|
29096
|
-
const file =
|
|
29236
|
+
const file = path142.join(cwd, ".deepcode", "feedback.log");
|
|
29097
29237
|
const entry = JSON.stringify({ ts: (/* @__PURE__ */ new Date()).toISOString(), rating, label });
|
|
29098
29238
|
try {
|
|
29099
|
-
|
|
29100
|
-
|
|
29239
|
+
fs7.mkdirSync(path142.dirname(file), { recursive: true });
|
|
29240
|
+
fs7.appendFileSync(file, `${entry}
|
|
29101
29241
|
`, "utf8");
|
|
29102
29242
|
} catch {
|
|
29103
29243
|
}
|
|
@@ -29591,6 +29731,7 @@ Follow-up suggestion:`;
|
|
|
29591
29731
|
return null;
|
|
29592
29732
|
}
|
|
29593
29733
|
}
|
|
29734
|
+
var APPROVAL_ENTER_ARM_DELAY_MS = 350;
|
|
29594
29735
|
var AppContainer = ({ cwd, config, provider, model, resumeSessionId }) => {
|
|
29595
29736
|
const historyManager = useHistory();
|
|
29596
29737
|
const addHistoryItem = historyManager.addItem;
|
|
@@ -29652,6 +29793,7 @@ var AppContainer = ({ cwd, config, provider, model, resumeSessionId }) => {
|
|
|
29652
29793
|
const messageQueueRef = useRef17([]);
|
|
29653
29794
|
const sessionShellAllowlistRef = useRef17(/* @__PURE__ */ new Set());
|
|
29654
29795
|
const mainControlsRef = useRef17(null);
|
|
29796
|
+
const approvalPromptVisibleAtRef = useRef17(null);
|
|
29655
29797
|
const { stdin, setRawMode } = useStdin3();
|
|
29656
29798
|
const { columns: terminalWidth, rows: terminalHeight } = useTerminalSize();
|
|
29657
29799
|
const mainAreaWidth = Math.min(Math.max(terminalWidth - 4, 20), 120);
|
|
@@ -29674,12 +29816,12 @@ var AppContainer = ({ cwd, config, provider, model, resumeSessionId }) => {
|
|
|
29674
29816
|
const configAdapter = configAdapterRef.current ?? new DeepCodeConfigAdapter(cwd);
|
|
29675
29817
|
const isValidPath = useCallback26(
|
|
29676
29818
|
(candidate) => {
|
|
29677
|
-
const resolved =
|
|
29678
|
-
const relative2 =
|
|
29679
|
-
if (relative2.startsWith("..") ||
|
|
29819
|
+
const resolved = path15.resolve(cwd, candidate);
|
|
29820
|
+
const relative2 = path15.relative(cwd, resolved);
|
|
29821
|
+
if (relative2.startsWith("..") || path15.isAbsolute(relative2)) {
|
|
29680
29822
|
return false;
|
|
29681
29823
|
}
|
|
29682
|
-
return
|
|
29824
|
+
return fs8.existsSync(resolved);
|
|
29683
29825
|
},
|
|
29684
29826
|
[cwd]
|
|
29685
29827
|
);
|
|
@@ -29709,6 +29851,7 @@ var AppContainer = ({ cwd, config, provider, model, resumeSessionId }) => {
|
|
|
29709
29851
|
modelCommand,
|
|
29710
29852
|
modeCommand,
|
|
29711
29853
|
renameCommand,
|
|
29854
|
+
updateCommand,
|
|
29712
29855
|
settingsDialogCommand,
|
|
29713
29856
|
themeDialogCommand,
|
|
29714
29857
|
permissionsDialogCommand,
|
|
@@ -29878,12 +30021,14 @@ var AppContainer = ({ cwd, config, provider, model, resumeSessionId }) => {
|
|
|
29878
30021
|
}, [messageQueue]);
|
|
29879
30022
|
useEffect27(() => {
|
|
29880
30023
|
if (approvalQueue.length > 0) {
|
|
30024
|
+
approvalPromptVisibleAtRef.current ??= Date.now();
|
|
29881
30025
|
setStreamingState(
|
|
29882
30026
|
"waiting_for_confirmation"
|
|
29883
30027
|
/* WaitingForConfirmation */
|
|
29884
30028
|
);
|
|
29885
30029
|
return;
|
|
29886
30030
|
}
|
|
30031
|
+
approvalPromptVisibleAtRef.current = null;
|
|
29887
30032
|
if (isRunning) {
|
|
29888
30033
|
setStreamingState(
|
|
29889
30034
|
"responding"
|
|
@@ -30091,6 +30236,25 @@ var AppContainer = ({ cwd, config, provider, model, resumeSessionId }) => {
|
|
|
30091
30236
|
);
|
|
30092
30237
|
}
|
|
30093
30238
|
setIsInitializing(false);
|
|
30239
|
+
checkForUpdate(VERSION).then((update) => {
|
|
30240
|
+
if (!mounted || !update) return;
|
|
30241
|
+
const available = [];
|
|
30242
|
+
if (isNewer(VERSION, update.latest)) {
|
|
30243
|
+
available.push(`latest v${update.latest}`);
|
|
30244
|
+
}
|
|
30245
|
+
if (update.stable && isNewer(VERSION, update.stable)) {
|
|
30246
|
+
available.push(`stable v${update.stable}`);
|
|
30247
|
+
}
|
|
30248
|
+
if (available.length === 0) return;
|
|
30249
|
+
addHistoryItem(
|
|
30250
|
+
{
|
|
30251
|
+
type: "info",
|
|
30252
|
+
text: `Update available: ${available.join(", ")}. Run /update for install commands.`
|
|
30253
|
+
},
|
|
30254
|
+
Date.now()
|
|
30255
|
+
);
|
|
30256
|
+
}).catch(() => {
|
|
30257
|
+
});
|
|
30094
30258
|
} catch (error) {
|
|
30095
30259
|
if (!mounted) return;
|
|
30096
30260
|
const message = error instanceof Error ? error.message : String(error);
|
|
@@ -30290,6 +30454,8 @@ var AppContainer = ({ cwd, config, provider, model, resumeSessionId }) => {
|
|
|
30290
30454
|
let status = "Success";
|
|
30291
30455
|
let resultDisplay = "(no output)";
|
|
30292
30456
|
try {
|
|
30457
|
+
const pathSecurity = runtime.pathSecurity.forWorktree(session.worktree);
|
|
30458
|
+
const permissions = runtime.permissions.forPathSecurity(pathSecurity);
|
|
30293
30459
|
const result = await runToolEffect(
|
|
30294
30460
|
tool.execute(parsed.data, {
|
|
30295
30461
|
sessionId: session.id,
|
|
@@ -30300,8 +30466,8 @@ var AppContainer = ({ cwd, config, provider, model, resumeSessionId }) => {
|
|
|
30300
30466
|
config: runtime.config,
|
|
30301
30467
|
agentMode,
|
|
30302
30468
|
cache: runtime.cache,
|
|
30303
|
-
permissions
|
|
30304
|
-
pathSecurity
|
|
30469
|
+
permissions,
|
|
30470
|
+
pathSecurity,
|
|
30305
30471
|
logActivity: (activity) => {
|
|
30306
30472
|
runtime.events.emit("activity", {
|
|
30307
30473
|
id: createId("activity"),
|
|
@@ -30847,10 +31013,12 @@ var AppContainer = ({ cwd, config, provider, model, resumeSessionId }) => {
|
|
|
30847
31013
|
}
|
|
30848
31014
|
if (approvalQueue.length > 0) {
|
|
30849
31015
|
const pressed = input.toLowerCase();
|
|
30850
|
-
|
|
31016
|
+
const enterArmed = approvalPromptVisibleAtRef.current !== null && Date.now() - approvalPromptVisibleAtRef.current >= APPROVAL_ENTER_ARM_DELAY_MS;
|
|
31017
|
+
if (pressed === "y" || key.return && enterArmed) {
|
|
30851
31018
|
resolveApproval({ allowed: true, scope: "once", reason: "Approved in TUI" });
|
|
30852
31019
|
return;
|
|
30853
31020
|
}
|
|
31021
|
+
if (key.return) return;
|
|
30854
31022
|
if (pressed === "s") {
|
|
30855
31023
|
resolveApproval({ allowed: true, scope: "session", reason: "Approved for session in TUI" });
|
|
30856
31024
|
return;
|
|
@@ -30963,7 +31131,7 @@ var AppContainer = ({ cwd, config, provider, model, resumeSessionId }) => {
|
|
|
30963
31131
|
mainControlsRef,
|
|
30964
31132
|
constrainHeight: false,
|
|
30965
31133
|
currentModel,
|
|
30966
|
-
sessionName:
|
|
31134
|
+
sessionName: path15.basename(cwd),
|
|
30967
31135
|
isConfigInitialized: !isInitializing && !initError,
|
|
30968
31136
|
sessionStats: {
|
|
30969
31137
|
lastPromptTokenCount,
|
|
@@ -31202,11 +31370,11 @@ function isInteractiveDialog(dialog) {
|
|
|
31202
31370
|
return dialog === "theme" || dialog === "permissions" || dialog === "auth" || dialog === "provider" || dialog === "model" || dialog === "feedback" || dialog === "sessions";
|
|
31203
31371
|
}
|
|
31204
31372
|
function tuiThemeFilePath(cwd) {
|
|
31205
|
-
return
|
|
31373
|
+
return path15.join(cwd, ".deepcode", "tui-theme.json");
|
|
31206
31374
|
}
|
|
31207
31375
|
function readSavedTheme(cwd) {
|
|
31208
31376
|
try {
|
|
31209
|
-
const parsed = JSON.parse(
|
|
31377
|
+
const parsed = JSON.parse(fs8.readFileSync(tuiThemeFilePath(cwd), "utf8"));
|
|
31210
31378
|
return typeof parsed.theme === "string" ? parsed.theme : null;
|
|
31211
31379
|
} catch {
|
|
31212
31380
|
return null;
|
|
@@ -31214,8 +31382,8 @@ function readSavedTheme(cwd) {
|
|
|
31214
31382
|
}
|
|
31215
31383
|
function writeSavedTheme(cwd, themeName) {
|
|
31216
31384
|
const file = tuiThemeFilePath(cwd);
|
|
31217
|
-
|
|
31218
|
-
|
|
31385
|
+
fs8.mkdirSync(path15.dirname(file), { recursive: true });
|
|
31386
|
+
fs8.writeFileSync(file, `${JSON.stringify({ theme: themeName }, null, 2)}
|
|
31219
31387
|
`);
|
|
31220
31388
|
}
|
|
31221
31389
|
function errorMessage(error) {
|
|
@@ -31354,7 +31522,7 @@ function createProgram() {
|
|
|
31354
31522
|
writeOut: writeStdoutSync,
|
|
31355
31523
|
writeErr: writeStderrSync
|
|
31356
31524
|
});
|
|
31357
|
-
program.name("deepcode").description("AI coding agent for the terminal").version(
|
|
31525
|
+
program.name("deepcode").description("AI coding agent for the terminal").version(VERSION).option("-C, --cwd <path>", "working directory", process.cwd()).option("--config <path>", "config file path");
|
|
31358
31526
|
program.command("init").description("create .deepcode/config.json").action(async () => {
|
|
31359
31527
|
await initCommand(program.opts().cwd);
|
|
31360
31528
|
});
|