deepcode-ai 1.1.27 → 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 CHANGED
@@ -3489,7 +3489,7 @@ Caminho: ${selectedPath}`;
3489
3489
  const effectiveModel = resolvedModel;
3490
3490
  if (!effectiveModel) {
3491
3491
  throw new Error(
3492
- "No model configured. Set 'defaultModel'/'defaultModels' in .deepcode/config.json or DEEPCODE_MODEL environment variable."
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
- "No model configured. Set 'defaultModel'/'defaultModels' in .deepcode/config.json or DEEPCODE_MODEL environment variable."
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: this.permissions,
3932
- pathSecurity: this.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 rootPath = await this.pathSecurity.normalize(scanInput, { enforceAccess: false });
4238
- await this.permissions.ensure({ operation: "list_projects", kind: "read", path: rootPath });
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) {
@@ -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 = /* @__PURE__ */ new Set();
6593
+ sessionAllowSet;
6574
6594
  /** Set of operation+path keys that were approved permanently (always) */
6575
- alwaysAllowSet = /* @__PURE__ */ new Set();
6595
+ alwaysAllowSet;
6576
6596
  /** Map of pending approval requests by request ID */
6577
- pendingApprovals = /* @__PURE__ */ new Map();
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();
@@ -28118,7 +28152,7 @@ function parseVersion2(version) {
28118
28152
  if (!match) return null;
28119
28153
  return [Number(match[1]), Number(match[2]), Number(match[3])];
28120
28154
  }
28121
- var VERSION = "1.1.27".length > 0 ? "1.1.27" : "0.0.0-dev";
28155
+ var VERSION = "1.1.28".length > 0 ? "1.1.28" : "0.0.0-dev";
28122
28156
  var updateCommand = {
28123
28157
  name: "update",
28124
28158
  description: "Check published DeepCode versions",
@@ -29697,6 +29731,7 @@ Follow-up suggestion:`;
29697
29731
  return null;
29698
29732
  }
29699
29733
  }
29734
+ var APPROVAL_ENTER_ARM_DELAY_MS = 350;
29700
29735
  var AppContainer = ({ cwd, config, provider, model, resumeSessionId }) => {
29701
29736
  const historyManager = useHistory();
29702
29737
  const addHistoryItem = historyManager.addItem;
@@ -29758,6 +29793,7 @@ var AppContainer = ({ cwd, config, provider, model, resumeSessionId }) => {
29758
29793
  const messageQueueRef = useRef17([]);
29759
29794
  const sessionShellAllowlistRef = useRef17(/* @__PURE__ */ new Set());
29760
29795
  const mainControlsRef = useRef17(null);
29796
+ const approvalPromptVisibleAtRef = useRef17(null);
29761
29797
  const { stdin, setRawMode } = useStdin3();
29762
29798
  const { columns: terminalWidth, rows: terminalHeight } = useTerminalSize();
29763
29799
  const mainAreaWidth = Math.min(Math.max(terminalWidth - 4, 20), 120);
@@ -29985,12 +30021,14 @@ var AppContainer = ({ cwd, config, provider, model, resumeSessionId }) => {
29985
30021
  }, [messageQueue]);
29986
30022
  useEffect27(() => {
29987
30023
  if (approvalQueue.length > 0) {
30024
+ approvalPromptVisibleAtRef.current ??= Date.now();
29988
30025
  setStreamingState(
29989
30026
  "waiting_for_confirmation"
29990
30027
  /* WaitingForConfirmation */
29991
30028
  );
29992
30029
  return;
29993
30030
  }
30031
+ approvalPromptVisibleAtRef.current = null;
29994
30032
  if (isRunning) {
29995
30033
  setStreamingState(
29996
30034
  "responding"
@@ -30416,6 +30454,8 @@ var AppContainer = ({ cwd, config, provider, model, resumeSessionId }) => {
30416
30454
  let status = "Success";
30417
30455
  let resultDisplay = "(no output)";
30418
30456
  try {
30457
+ const pathSecurity = runtime.pathSecurity.forWorktree(session.worktree);
30458
+ const permissions = runtime.permissions.forPathSecurity(pathSecurity);
30419
30459
  const result = await runToolEffect(
30420
30460
  tool.execute(parsed.data, {
30421
30461
  sessionId: session.id,
@@ -30426,8 +30466,8 @@ var AppContainer = ({ cwd, config, provider, model, resumeSessionId }) => {
30426
30466
  config: runtime.config,
30427
30467
  agentMode,
30428
30468
  cache: runtime.cache,
30429
- permissions: runtime.permissions,
30430
- pathSecurity: runtime.pathSecurity,
30469
+ permissions,
30470
+ pathSecurity,
30431
30471
  logActivity: (activity) => {
30432
30472
  runtime.events.emit("activity", {
30433
30473
  id: createId("activity"),
@@ -30973,10 +31013,12 @@ var AppContainer = ({ cwd, config, provider, model, resumeSessionId }) => {
30973
31013
  }
30974
31014
  if (approvalQueue.length > 0) {
30975
31015
  const pressed = input.toLowerCase();
30976
- if (pressed === "y" || key.return) {
31016
+ const enterArmed = approvalPromptVisibleAtRef.current !== null && Date.now() - approvalPromptVisibleAtRef.current >= APPROVAL_ENTER_ARM_DELAY_MS;
31017
+ if (pressed === "y" || key.return && enterArmed) {
30977
31018
  resolveApproval({ allowed: true, scope: "once", reason: "Approved in TUI" });
30978
31019
  return;
30979
31020
  }
31021
+ if (key.return) return;
30980
31022
  if (pressed === "s") {
30981
31023
  resolveApproval({ allowed: true, scope: "session", reason: "Approved for session in TUI" });
30982
31024
  return;