codeep 1.0.102 → 1.0.103

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/app.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { useState, useEffect, useCallback } from 'react';
2
+ import React, { useState, useEffect, useCallback } from 'react';
3
3
  import { Box, Text, useApp, useInput, useStdout } from 'ink';
4
4
  import clipboardy from 'clipboardy';
5
5
  import { logger } from './utils/logger.js';
@@ -94,15 +94,23 @@ export const App = () => {
94
94
  const [agentDryRun, setAgentDryRun] = useState(false);
95
95
  // Track LiveCodeStream height to render placeholder after agent finishes (prevents ghost content)
96
96
  const [lastStreamHeight, setLastStreamHeight] = useState(0);
97
- // Clear placeholder height after agent finishes (let it overwrite ghost, then disappear)
97
+ // Clear ghost content when agent finishes by erasing lines above cursor
98
+ const prevAgentRunning = React.useRef(isAgentRunning);
98
99
  useEffect(() => {
99
- if (agentResult && lastStreamHeight > 0) {
100
- const timer = setTimeout(() => {
101
- setLastStreamHeight(0);
102
- }, 100); // Short delay to allow one render cycle to overwrite ghost
103
- return () => clearTimeout(timer);
100
+ if (prevAgentRunning.current === true && isAgentRunning === false && lastStreamHeight > 0) {
101
+ // Erase N lines above without scrolling: move up, clear each line, move back down
102
+ const linesToClear = lastStreamHeight;
103
+ let escapeSeq = '';
104
+ escapeSeq += `\x1b[${linesToClear}A`; // Move cursor up N lines
105
+ for (let i = 0; i < linesToClear; i++) {
106
+ escapeSeq += '\x1b[2K\x1b[B'; // Clear line, move down
107
+ }
108
+ escapeSeq += `\x1b[${linesToClear}A`; // Move back up to original position
109
+ stdout?.write(escapeSeq);
110
+ setLastStreamHeight(0);
104
111
  }
105
- }, [agentResult, lastStreamHeight]);
112
+ prevAgentRunning.current = isAgentRunning;
113
+ }, [isAgentRunning, lastStreamHeight, stdout]);
106
114
  // Load API keys for ALL providers on startup and check if current provider is configured
107
115
  useEffect(() => {
108
116
  loadAllApiKeys().then(() => {
@@ -1426,7 +1434,7 @@ export const App = () => {
1426
1434
  // If we got here, we're in an unknown state - default to chat
1427
1435
  return null;
1428
1436
  }
1429
- return (_jsxs(Box, { flexDirection: "column", children: [messages.length === 0 && !isLoading && _jsx(Logo, {}), messages.length === 0 && !isLoading && (_jsxs(Box, { flexDirection: "column", marginY: 1, children: [_jsx(Box, { justifyContent: "center", children: _jsxs(Text, { children: ["Connected to ", _jsx(Text, { color: "#f02a30", children: config.get('model') }), ". Type ", _jsx(Text, { color: "#f02a30", children: "/help" }), " for commands."] }) }), _jsx(Text, { children: " " }), _jsx(Box, { justifyContent: "center", children: _jsx(Text, { color: "cyan", bold: true, children: "Welcome to Codeep - Your AI Coding Assistant" }) }), _jsx(Text, { children: " " }), _jsxs(Box, { flexDirection: "column", paddingX: 2, children: [_jsxs(Text, { children: [_jsx(Text, { color: "#f02a30", children: "\u2022" }), " Ask questions about your code or request implementations"] }), _jsxs(Text, { children: [_jsx(Text, { color: "#f02a30", children: "\u2022" }), " Use ", _jsxs(Text, { color: "cyan", children: ["/agent ", '<task>'] }), " for autonomous task execution"] }), _jsxs(Text, { children: [_jsx(Text, { color: "#f02a30", children: "\u2022" }), " Type ", _jsx(Text, { color: "cyan", children: "/diff" }), " to review changes, ", _jsx(Text, { color: "cyan", children: "/commit" }), " to generate commit messages"] }), _jsxs(Text, { children: [_jsx(Text, { color: "#f02a30", children: "\u2022" }), " Configure settings with ", _jsx(Text, { color: "cyan", children: "/settings" }), " - enable Agent Mode for auto-execution"] })] }), _jsx(Text, { children: " " }), _jsx(Box, { justifyContent: "center", children: _jsx(Text, { color: "gray", children: "Start typing your message or use a command to begin..." }) }), _jsx(Text, { children: " " })] })), _jsx(MessageList, { messages: messages, streamingContent: streamingContent, scrollOffset: 0, terminalHeight: stdout.rows || 24 }, sessionId), isLoading && !isAgentRunning && _jsx(Loading, { isStreaming: !!streamingContent }), isAgentRunning ? (_jsxs(Box, { flexDirection: "column", children: [_jsx(LiveCodeStream, { actions: agentActions, isRunning: true, terminalWidth: stdout?.columns || 80 }), _jsx(AgentProgress, { isRunning: true, iteration: agentIteration, maxIterations: 50, actions: agentActions, currentThinking: agentThinking, dryRun: agentDryRun })] }, "agent-running")) : agentResult ? (_jsxs(Box, { flexDirection: "column", children: [lastStreamHeight > 0 && (_jsx(Box, { flexDirection: "column", children: Array.from({ length: lastStreamHeight }).map((_, i) => (_jsx(Text, { children: " " }, i))) })), _jsx(AgentSummary, { success: agentResult.success, iterations: agentResult.iterations, actions: agentActions, error: agentResult.error, aborted: agentResult.aborted })] }, "agent-complete")) : null, pendingFileChanges.length > 0 && !isLoading && (_jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: "#f02a30", padding: 1, marginY: 1, children: [_jsxs(Text, { color: "#f02a30", bold: true, children: ["\u2713 Detected ", pendingFileChanges.length, " file change(s):"] }), pendingFileChanges.map((change, i) => {
1437
+ return (_jsxs(Box, { flexDirection: "column", children: [messages.length === 0 && !isLoading && _jsx(Logo, {}), messages.length === 0 && !isLoading && (_jsxs(Box, { flexDirection: "column", marginY: 1, children: [_jsx(Box, { justifyContent: "center", children: _jsxs(Text, { children: ["Connected to ", _jsx(Text, { color: "#f02a30", children: config.get('model') }), ". Type ", _jsx(Text, { color: "#f02a30", children: "/help" }), " for commands."] }) }), _jsx(Text, { children: " " }), _jsx(Box, { justifyContent: "center", children: _jsx(Text, { color: "cyan", bold: true, children: "Welcome to Codeep - Your AI Coding Assistant" }) }), _jsx(Text, { children: " " }), _jsxs(Box, { flexDirection: "column", paddingX: 2, children: [_jsxs(Text, { children: [_jsx(Text, { color: "#f02a30", children: "\u2022" }), " Ask questions about your code or request implementations"] }), _jsxs(Text, { children: [_jsx(Text, { color: "#f02a30", children: "\u2022" }), " Use ", _jsxs(Text, { color: "cyan", children: ["/agent ", '<task>'] }), " for autonomous task execution"] }), _jsxs(Text, { children: [_jsx(Text, { color: "#f02a30", children: "\u2022" }), " Type ", _jsx(Text, { color: "cyan", children: "/diff" }), " to review changes, ", _jsx(Text, { color: "cyan", children: "/commit" }), " to generate commit messages"] }), _jsxs(Text, { children: [_jsx(Text, { color: "#f02a30", children: "\u2022" }), " Configure settings with ", _jsx(Text, { color: "cyan", children: "/settings" }), " - enable Agent Mode for auto-execution"] })] }), _jsx(Text, { children: " " }), _jsx(Box, { justifyContent: "center", children: _jsx(Text, { color: "gray", children: "Start typing your message or use a command to begin..." }) }), _jsx(Text, { children: " " })] })), _jsx(MessageList, { messages: messages, streamingContent: streamingContent, scrollOffset: 0, terminalHeight: stdout.rows || 24 }, sessionId), isLoading && !isAgentRunning && _jsx(Loading, { isStreaming: !!streamingContent }), isAgentRunning ? (_jsxs(Box, { flexDirection: "column", children: [_jsx(LiveCodeStream, { actions: agentActions, isRunning: true, terminalWidth: stdout?.columns || 80 }), _jsx(AgentProgress, { isRunning: true, iteration: agentIteration, maxIterations: 50, actions: agentActions, currentThinking: agentThinking, dryRun: agentDryRun })] }, "agent-running")) : agentResult ? (_jsx(Box, { flexDirection: "column", children: _jsx(AgentSummary, { success: agentResult.success, iterations: agentResult.iterations, actions: agentActions, error: agentResult.error, aborted: agentResult.aborted }) }, "agent-complete")) : null, pendingFileChanges.length > 0 && !isLoading && (_jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: "#f02a30", padding: 1, marginY: 1, children: [_jsxs(Text, { color: "#f02a30", bold: true, children: ["\u2713 Detected ", pendingFileChanges.length, " file change(s):"] }), pendingFileChanges.map((change, i) => {
1430
1438
  const actionColor = change.action === 'delete' ? 'red' : change.action === 'edit' ? 'yellow' : 'green';
1431
1439
  const actionLabel = change.action === 'delete' ? 'DELETE' : change.action === 'edit' ? 'EDIT' : 'CREATE';
1432
1440
  return (_jsxs(Text, { children: ["\u2022 ", _jsxs(Text, { color: actionColor, children: ["[", actionLabel, "]"] }), " ", change.path, change.action !== 'delete' && change.content.includes('\n') && ` (${change.content.split('\n').length} lines)`] }, i));
@@ -109,15 +109,15 @@ export interface SessionInfo {
109
109
  */
110
110
  export declare function listSessionsWithInfo(projectPath?: string): SessionInfo[];
111
111
  /**
112
- * Get project permission from local .codeep/config.json
112
+ * Get project permission from local .codeep/config.json or global config
113
113
  */
114
114
  export declare function getProjectPermission(projectPath: string): ProjectPermission | null;
115
115
  /**
116
- * Set project permission in local .codeep/config.json
116
+ * Set project permission in local .codeep/config.json or global config
117
117
  */
118
118
  export declare function setProjectPermission(projectPath: string, read: boolean, write: boolean): void;
119
119
  /**
120
- * Remove project permission from local .codeep/config.json
120
+ * Remove project permission from local .codeep/config.json or global config
121
121
  */
122
122
  export declare function removeProjectPermission(projectPath: string): boolean;
123
123
  export declare function hasReadPermission(projectPath: string): boolean;
@@ -504,64 +504,88 @@ export function listSessionsWithInfo(projectPath) {
504
504
  }
505
505
  // Project permission management
506
506
  /**
507
- * Get project permission from local .codeep/config.json
507
+ * Get project permission from local .codeep/config.json or global config
508
508
  */
509
509
  export function getProjectPermission(projectPath) {
510
+ // First try local .codeep/config.json (for recognized projects)
510
511
  const configPath = getLocalConfigPath(projectPath);
511
- if (!configPath || !existsSync(configPath)) {
512
- return null;
513
- }
514
- try {
515
- const data = JSON.parse(readFileSync(configPath, 'utf-8'));
516
- return data.permission || null;
517
- }
518
- catch {
519
- return null;
512
+ if (configPath && existsSync(configPath)) {
513
+ try {
514
+ const data = JSON.parse(readFileSync(configPath, 'utf-8'));
515
+ if (data.permission)
516
+ return data.permission;
517
+ }
518
+ catch {
519
+ // Fall through to global config
520
+ }
520
521
  }
522
+ // Fallback to global config for non-project folders
523
+ const permissions = config.get('projectPermissions') || [];
524
+ return permissions.find((p) => p.path === projectPath) || null;
521
525
  }
522
526
  /**
523
- * Set project permission in local .codeep/config.json
527
+ * Set project permission in local .codeep/config.json or global config
524
528
  */
525
529
  export function setProjectPermission(projectPath, read, write) {
526
- const configPath = getLocalConfigPath(projectPath);
527
- if (!configPath)
528
- return;
529
530
  const permission = {
530
531
  path: projectPath,
531
532
  readPermission: read,
532
533
  writePermission: write,
533
534
  grantedAt: new Date().toISOString(),
534
535
  };
535
- let data = {};
536
- if (existsSync(configPath)) {
537
- try {
538
- data = JSON.parse(readFileSync(configPath, 'utf-8'));
539
- }
540
- catch {
541
- // Invalid JSON, start fresh
536
+ // Try to save to local .codeep/config.json (for recognized projects)
537
+ const configPath = getLocalConfigPath(projectPath);
538
+ if (configPath) {
539
+ let data = {};
540
+ if (existsSync(configPath)) {
541
+ try {
542
+ data = JSON.parse(readFileSync(configPath, 'utf-8'));
543
+ }
544
+ catch {
545
+ // Invalid JSON, start fresh
546
+ }
542
547
  }
548
+ data.permission = permission;
549
+ writeFileSync(configPath, JSON.stringify(data, null, 2));
550
+ return;
551
+ }
552
+ // Fallback to global config for non-project folders
553
+ const permissions = config.get('projectPermissions') || [];
554
+ const existingIndex = permissions.findIndex((p) => p.path === projectPath);
555
+ if (existingIndex >= 0) {
556
+ permissions[existingIndex] = permission;
543
557
  }
544
- data.permission = permission;
545
- writeFileSync(configPath, JSON.stringify(data, null, 2));
558
+ else {
559
+ permissions.push(permission);
560
+ }
561
+ config.set('projectPermissions', permissions);
546
562
  }
547
563
  /**
548
- * Remove project permission from local .codeep/config.json
564
+ * Remove project permission from local .codeep/config.json or global config
549
565
  */
550
566
  export function removeProjectPermission(projectPath) {
567
+ // Try to remove from local .codeep/config.json
551
568
  const configPath = getLocalConfigPath(projectPath);
552
- if (!configPath || !existsSync(configPath)) {
553
- return false;
554
- }
555
- try {
556
- const data = JSON.parse(readFileSync(configPath, 'utf-8'));
557
- if (data.permission) {
558
- delete data.permission;
559
- writeFileSync(configPath, JSON.stringify(data, null, 2));
560
- return true;
569
+ if (configPath && existsSync(configPath)) {
570
+ try {
571
+ const data = JSON.parse(readFileSync(configPath, 'utf-8'));
572
+ if (data.permission) {
573
+ delete data.permission;
574
+ writeFileSync(configPath, JSON.stringify(data, null, 2));
575
+ return true;
576
+ }
577
+ }
578
+ catch {
579
+ // Fall through to global config
561
580
  }
562
581
  }
563
- catch {
564
- // Ignore errors
582
+ // Try to remove from global config
583
+ const permissions = config.get('projectPermissions') || [];
584
+ const existingIndex = permissions.findIndex((p) => p.path === projectPath);
585
+ if (existingIndex >= 0) {
586
+ permissions.splice(existingIndex, 1);
587
+ config.set('projectPermissions', permissions);
588
+ return true;
565
589
  }
566
590
  return false;
567
591
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "codeep",
3
- "version": "1.0.102",
3
+ "version": "1.0.103",
4
4
  "description": "AI-powered coding assistant built for the terminal. Multiple LLM providers, project-aware context, and a seamless development workflow.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",