upfynai-code 2.9.0 → 2.9.2

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.
Files changed (229) hide show
  1. package/README.md +91 -66
  2. package/client/dist/api-docs.html +838 -0
  3. package/client/dist/assets/AppContent-BXZDeSIC.js +545 -0
  4. package/client/dist/assets/CanvasFullScreen-mnpCnLZ9.js +1 -0
  5. package/client/dist/assets/CanvasWorkspace-4CqmjAVQ.js +163 -0
  6. package/client/dist/assets/DashboardPanel-zFIFlw56.js +1 -0
  7. package/client/dist/assets/FileTree-B0c_GaB3.js +1 -0
  8. package/client/dist/assets/GitPanel-DUP4zVU4.js +2 -0
  9. package/client/dist/assets/KaTeX_AMS-Regular-BQhdFMY1.woff2 +0 -0
  10. package/client/dist/assets/KaTeX_AMS-Regular-DMm9YOAa.woff +0 -0
  11. package/client/dist/assets/KaTeX_AMS-Regular-DRggAlZN.ttf +0 -0
  12. package/client/dist/assets/KaTeX_Caligraphic-Bold-ATXxdsX0.ttf +0 -0
  13. package/client/dist/assets/KaTeX_Caligraphic-Bold-BEiXGLvX.woff +0 -0
  14. package/client/dist/assets/KaTeX_Caligraphic-Bold-Dq_IR9rO.woff2 +0 -0
  15. package/client/dist/assets/KaTeX_Caligraphic-Regular-CTRA-rTL.woff +0 -0
  16. package/client/dist/assets/KaTeX_Caligraphic-Regular-Di6jR-x-.woff2 +0 -0
  17. package/client/dist/assets/KaTeX_Caligraphic-Regular-wX97UBjC.ttf +0 -0
  18. package/client/dist/assets/KaTeX_Fraktur-Bold-BdnERNNW.ttf +0 -0
  19. package/client/dist/assets/KaTeX_Fraktur-Bold-BsDP51OF.woff +0 -0
  20. package/client/dist/assets/KaTeX_Fraktur-Bold-CL6g_b3V.woff2 +0 -0
  21. package/client/dist/assets/KaTeX_Fraktur-Regular-CB_wures.ttf +0 -0
  22. package/client/dist/assets/KaTeX_Fraktur-Regular-CTYiF6lA.woff2 +0 -0
  23. package/client/dist/assets/KaTeX_Fraktur-Regular-Dxdc4cR9.woff +0 -0
  24. package/client/dist/assets/KaTeX_Main-Bold-Cx986IdX.woff2 +0 -0
  25. package/client/dist/assets/KaTeX_Main-Bold-Jm3AIy58.woff +0 -0
  26. package/client/dist/assets/KaTeX_Main-Bold-waoOVXN0.ttf +0 -0
  27. package/client/dist/assets/KaTeX_Main-BoldItalic-DxDJ3AOS.woff2 +0 -0
  28. package/client/dist/assets/KaTeX_Main-BoldItalic-DzxPMmG6.ttf +0 -0
  29. package/client/dist/assets/KaTeX_Main-BoldItalic-SpSLRI95.woff +0 -0
  30. package/client/dist/assets/KaTeX_Main-Italic-3WenGoN9.ttf +0 -0
  31. package/client/dist/assets/KaTeX_Main-Italic-BMLOBm91.woff +0 -0
  32. package/client/dist/assets/KaTeX_Main-Italic-NWA7e6Wa.woff2 +0 -0
  33. package/client/dist/assets/KaTeX_Main-Regular-B22Nviop.woff2 +0 -0
  34. package/client/dist/assets/KaTeX_Main-Regular-Dr94JaBh.woff +0 -0
  35. package/client/dist/assets/KaTeX_Main-Regular-ypZvNtVU.ttf +0 -0
  36. package/client/dist/assets/KaTeX_Math-BoldItalic-B3XSjfu4.ttf +0 -0
  37. package/client/dist/assets/KaTeX_Math-BoldItalic-CZnvNsCZ.woff2 +0 -0
  38. package/client/dist/assets/KaTeX_Math-BoldItalic-iY-2wyZ7.woff +0 -0
  39. package/client/dist/assets/KaTeX_Math-Italic-DA0__PXp.woff +0 -0
  40. package/client/dist/assets/KaTeX_Math-Italic-flOr_0UB.ttf +0 -0
  41. package/client/dist/assets/KaTeX_Math-Italic-t53AETM-.woff2 +0 -0
  42. package/client/dist/assets/KaTeX_SansSerif-Bold-CFMepnvq.ttf +0 -0
  43. package/client/dist/assets/KaTeX_SansSerif-Bold-D1sUS0GD.woff2 +0 -0
  44. package/client/dist/assets/KaTeX_SansSerif-Bold-DbIhKOiC.woff +0 -0
  45. package/client/dist/assets/KaTeX_SansSerif-Italic-C3H0VqGB.woff2 +0 -0
  46. package/client/dist/assets/KaTeX_SansSerif-Italic-DN2j7dab.woff +0 -0
  47. package/client/dist/assets/KaTeX_SansSerif-Italic-YYjJ1zSn.ttf +0 -0
  48. package/client/dist/assets/KaTeX_SansSerif-Regular-BNo7hRIc.ttf +0 -0
  49. package/client/dist/assets/KaTeX_SansSerif-Regular-CS6fqUqJ.woff +0 -0
  50. package/client/dist/assets/KaTeX_SansSerif-Regular-DDBCnlJ7.woff2 +0 -0
  51. package/client/dist/assets/KaTeX_Script-Regular-C5JkGWo-.ttf +0 -0
  52. package/client/dist/assets/KaTeX_Script-Regular-D3wIWfF6.woff2 +0 -0
  53. package/client/dist/assets/KaTeX_Script-Regular-D5yQViql.woff +0 -0
  54. package/client/dist/assets/KaTeX_Size1-Regular-C195tn64.woff +0 -0
  55. package/client/dist/assets/KaTeX_Size1-Regular-Dbsnue_I.ttf +0 -0
  56. package/client/dist/assets/KaTeX_Size1-Regular-mCD8mA8B.woff2 +0 -0
  57. package/client/dist/assets/KaTeX_Size2-Regular-B7gKUWhC.ttf +0 -0
  58. package/client/dist/assets/KaTeX_Size2-Regular-Dy4dx90m.woff2 +0 -0
  59. package/client/dist/assets/KaTeX_Size2-Regular-oD1tc_U0.woff +0 -0
  60. package/client/dist/assets/KaTeX_Size3-Regular-CTq5MqoE.woff +0 -0
  61. package/client/dist/assets/KaTeX_Size3-Regular-DgpXs0kz.ttf +0 -0
  62. package/client/dist/assets/KaTeX_Size4-Regular-BF-4gkZK.woff +0 -0
  63. package/client/dist/assets/KaTeX_Size4-Regular-DWFBv043.ttf +0 -0
  64. package/client/dist/assets/KaTeX_Size4-Regular-Dl5lxZxV.woff2 +0 -0
  65. package/client/dist/assets/KaTeX_Typewriter-Regular-C0xS9mPB.woff +0 -0
  66. package/client/dist/assets/KaTeX_Typewriter-Regular-CO6r4hn1.woff2 +0 -0
  67. package/client/dist/assets/KaTeX_Typewriter-Regular-D3Ib7_Hf.ttf +0 -0
  68. package/client/dist/assets/LoginModal-BRycfsyD.js +13 -0
  69. package/client/dist/assets/MarkdownPreview-DHmk3qzu.js +1 -0
  70. package/client/dist/assets/MermaidBlock-BuBc_G-F.js +2 -0
  71. package/client/dist/assets/Onboarding-BcnaZZ0o.js +1 -0
  72. package/client/dist/assets/PreviewPanel-CqCa92Tf.js +32 -0
  73. package/client/dist/assets/SetupForm-S0g6u5yT.js +1 -0
  74. package/client/dist/assets/WorkflowsPanel-CouH9JDO.js +1 -0
  75. package/client/dist/assets/index-BFuqS0tY.css +1 -0
  76. package/client/dist/assets/index-CNDcVl2g.js +68 -0
  77. package/client/dist/assets/pdf-CE_K4jFx.js +12 -0
  78. package/client/dist/assets/vendor-canvas-BZV40eAE.css +1 -0
  79. package/client/dist/assets/vendor-canvas-D39yWul6.js +49 -0
  80. package/client/dist/assets/vendor-codemirror-CbtmxxaB.js +35 -0
  81. package/client/dist/assets/vendor-diff-DNQpbhrT.js +69 -0
  82. package/client/dist/assets/vendor-i18n-DCFGyhQR.js +1 -0
  83. package/client/dist/assets/vendor-icons-BaD0x9SL.js +711 -0
  84. package/client/dist/assets/vendor-markdown-CimbIo6Y.js +296 -0
  85. package/client/dist/assets/vendor-mermaid-CH7SGc99.js +2556 -0
  86. package/client/dist/assets/vendor-react-96lCPsRK.js +67 -0
  87. package/client/dist/assets/vendor-syntax-DuHI9Ok6.js +16 -0
  88. package/client/dist/assets/vendor-xterm-CZq1hqo1.js +66 -0
  89. package/client/dist/assets/vendor-xterm-qxJ8_QYu.css +32 -0
  90. package/client/dist/clear-cache.html +85 -0
  91. package/client/dist/convert-icons.md +53 -0
  92. package/client/dist/favicon.png +0 -0
  93. package/client/dist/favicon.svg +5 -0
  94. package/client/dist/generate-icons.js +49 -0
  95. package/client/dist/icons/claude-ai-icon.svg +1 -0
  96. package/client/dist/icons/codex-white.svg +3 -0
  97. package/client/dist/icons/codex.svg +3 -0
  98. package/client/dist/icons/cursor-white.svg +12 -0
  99. package/client/dist/icons/cursor.svg +1 -0
  100. package/client/dist/icons/icon-128x128.png +0 -0
  101. package/client/dist/icons/icon-128x128.svg +5 -0
  102. package/client/dist/icons/icon-144x144.png +0 -0
  103. package/client/dist/icons/icon-144x144.svg +5 -0
  104. package/client/dist/icons/icon-152x152.png +0 -0
  105. package/client/dist/icons/icon-152x152.svg +5 -0
  106. package/client/dist/icons/icon-192x192.png +0 -0
  107. package/client/dist/icons/icon-192x192.svg +5 -0
  108. package/client/dist/icons/icon-384x384.png +0 -0
  109. package/client/dist/icons/icon-384x384.svg +5 -0
  110. package/client/dist/icons/icon-512x512.png +0 -0
  111. package/client/dist/icons/icon-512x512.svg +5 -0
  112. package/client/dist/icons/icon-72x72.png +0 -0
  113. package/client/dist/icons/icon-72x72.svg +5 -0
  114. package/client/dist/icons/icon-96x96.png +0 -0
  115. package/client/dist/icons/icon-96x96.svg +5 -0
  116. package/client/dist/icons/icon-template.svg +5 -0
  117. package/client/dist/index.html +119 -0
  118. package/client/dist/logo-128.png +0 -0
  119. package/client/dist/logo-256.png +0 -0
  120. package/client/dist/logo-32.png +0 -0
  121. package/client/dist/logo-512.png +0 -0
  122. package/client/dist/logo-64.png +0 -0
  123. package/client/dist/logo.svg +14 -0
  124. package/client/dist/manifest.json +61 -0
  125. package/client/dist/mcp-docs.html +108 -0
  126. package/client/dist/offline.html +84 -0
  127. package/client/dist/screenshots/cli-selection.png +0 -0
  128. package/client/dist/screenshots/desktop-main.png +0 -0
  129. package/client/dist/screenshots/mobile-chat.png +0 -0
  130. package/client/dist/screenshots/tools-modal.png +0 -0
  131. package/client/dist/sw.js +82 -0
  132. package/commands/upfynai-connect.md +59 -0
  133. package/commands/upfynai-disconnect.md +31 -0
  134. package/commands/upfynai-doctor.md +99 -0
  135. package/commands/upfynai-export.md +49 -0
  136. package/commands/upfynai-local.md +82 -0
  137. package/commands/upfynai-status.md +75 -0
  138. package/commands/upfynai-stop.md +49 -0
  139. package/commands/upfynai-uninstall.md +58 -0
  140. package/commands/upfynai.md +69 -0
  141. package/package.json +143 -82
  142. package/scripts/build-client.js +17 -0
  143. package/scripts/fix-node-pty.js +67 -0
  144. package/scripts/install-commands.js +78 -0
  145. package/server/agent-loop.js +242 -0
  146. package/server/auto-compact.js +99 -0
  147. package/server/claude-sdk.js +797 -0
  148. package/server/cli-ui.js +785 -0
  149. package/server/cli.js +596 -0
  150. package/server/constants/config.js +31 -0
  151. package/server/cursor-cli.js +270 -0
  152. package/server/database/auth.db +0 -0
  153. package/server/database/db.js +1391 -0
  154. package/server/database/init.sql +70 -0
  155. package/server/index.js +3799 -0
  156. package/server/load-env.js +26 -0
  157. package/server/mcp-server.js +621 -0
  158. package/server/middleware/auth.js +176 -0
  159. package/server/middleware/relayHelpers.js +44 -0
  160. package/server/middleware/sandboxRouter.js +174 -0
  161. package/server/openai-codex.js +403 -0
  162. package/server/openrouter.js +137 -0
  163. package/server/projects.js +1807 -0
  164. package/server/provider-factory.js +174 -0
  165. package/server/relay-client.js +379 -0
  166. package/server/routes/agent.js +1226 -0
  167. package/server/routes/auth.js +554 -0
  168. package/server/routes/canvas.js +53 -0
  169. package/server/routes/cli-auth.js +263 -0
  170. package/server/routes/codex.js +396 -0
  171. package/server/routes/commands.js +707 -0
  172. package/server/routes/composio.js +176 -0
  173. package/server/routes/cursor.js +770 -0
  174. package/server/routes/dashboard.js +295 -0
  175. package/server/routes/git.js +1208 -0
  176. package/server/routes/keys.js +34 -0
  177. package/server/routes/mcp-utils.js +48 -0
  178. package/server/routes/mcp.js +661 -0
  179. package/server/routes/payments.js +227 -0
  180. package/server/routes/projects.js +655 -0
  181. package/server/routes/sessions.js +146 -0
  182. package/server/routes/settings.js +261 -0
  183. package/server/routes/taskmaster.js +1928 -0
  184. package/server/routes/user.js +106 -0
  185. package/server/routes/vapi-chat.js +624 -0
  186. package/server/routes/voice.js +235 -0
  187. package/server/routes/webhooks.js +166 -0
  188. package/server/routes/workflows.js +312 -0
  189. package/server/sandbox.js +120 -0
  190. package/server/services/composio.js +204 -0
  191. package/server/services/sessionRegistry.js +139 -0
  192. package/server/services/whisperService.js +84 -0
  193. package/server/services/workflowScheduler.js +206 -0
  194. package/server/tests/relay-flow.test.js +570 -0
  195. package/server/tests/sessions.test.js +259 -0
  196. package/server/utils/commandParser.js +303 -0
  197. package/server/utils/email.js +61 -0
  198. package/server/utils/gitConfig.js +24 -0
  199. package/server/utils/mcp-detector.js +198 -0
  200. package/server/utils/taskmaster-websocket.js +129 -0
  201. package/shared/integrationCatalog.d.ts +12 -0
  202. package/shared/integrationCatalog.js +172 -0
  203. package/shared/modelConstants.js +96 -0
  204. package/bin/cli.js +0 -97
  205. package/dist/agents/claude.js +0 -229
  206. package/dist/agents/codex.js +0 -48
  207. package/dist/agents/cursor.js +0 -48
  208. package/dist/agents/detect.js +0 -51
  209. package/dist/agents/exec.js +0 -31
  210. package/dist/agents/files.js +0 -105
  211. package/dist/agents/git.js +0 -18
  212. package/dist/agents/gitagent.js +0 -67
  213. package/dist/agents/index.js +0 -88
  214. package/dist/agents/shell.js +0 -38
  215. package/dist/agents/utils.js +0 -136
  216. package/scripts/postinstall.js +0 -9
  217. package/scripts/prepublish.js +0 -58
  218. package/src/animation.js +0 -228
  219. package/src/auth.js +0 -122
  220. package/src/config.js +0 -40
  221. package/src/connect.js +0 -416
  222. package/src/launch.js +0 -78
  223. package/src/mcp.js +0 -57
  224. package/src/permissions.js +0 -140
  225. package/src/persistent-shell.js +0 -261
  226. package/src/server.js +0 -54
  227. /package/{dist → shared}/gitagent/index.js +0 -0
  228. /package/{dist → shared}/gitagent/parser.js +0 -0
  229. /package/{dist → shared}/gitagent/prompt-builder.js +0 -0
@@ -1,88 +0,0 @@
1
- /**
2
- * Agent Registry
3
- * Central dispatch for all command actions.
4
- *
5
- * Usage:
6
- * import { executeAction, isStreamingAction } from 'upfynai-shared/agents';
7
- *
8
- * // Sync action (file-read, git-operation, etc.)
9
- * const result = await executeAction('file-read', { filePath: '/foo' }, ctx);
10
- * // result = { content: '...' }
11
- *
12
- * // Streaming action (claude-query, codex-query, etc.)
13
- * const result = await executeAction('claude-query', params, {
14
- * ...ctx,
15
- * stream: (data) => ws.send(JSON.stringify({ type: 'relay-stream', requestId, data })),
16
- * });
17
- * // result = { exitCode: 0, sessionId: '...' }
18
- */
19
- import claudeAgent from './claude.js';
20
- import codexAgent from './codex.js';
21
- import cursorAgent from './cursor.js';
22
- import shellAgent from './shell.js';
23
- import filesAgent from './files.js';
24
- import gitAgent from './git.js';
25
- import execAgent from './exec.js';
26
- import detectAgent from './detect.js';
27
- import gitagentAgent from './gitagent.js';
28
-
29
- const agents = [claudeAgent, codexAgent, cursorAgent, shellAgent, filesAgent, gitAgent, execAgent, detectAgent, gitagentAgent];
30
-
31
- /** Map of action name → handler function */
32
- const actionMap = new Map();
33
-
34
- /** Set of actions that use streaming (ctx.stream) instead of returning data */
35
- const streamingActions = new Set(['claude-query', 'claude-task-query', 'codex-query', 'cursor-query']);
36
-
37
- for (const agent of agents) {
38
- for (const [action, handler] of Object.entries(agent.actions)) {
39
- actionMap.set(action, handler);
40
- }
41
- }
42
-
43
- /**
44
- * Execute an agent action.
45
- * @param {string} action - Action name (e.g., 'file-read', 'claude-query')
46
- * @param {object} params - Action parameters from the command payload
47
- * @param {object} ctx - Execution context:
48
- * - stream(data): Send streaming chunk (required for streaming actions)
49
- * - requestId: Current request ID
50
- * - trackProcess(id, entry): Register process for abort support
51
- * - untrackProcess(id): Remove process from tracking
52
- * - getPersistentShell(cwd): Get persistent shell instance (CLI only)
53
- * - resolveBinary(name): Resolve binary path (CLI only)
54
- * - localBinDir: Path to local node_modules/.bin (CLI only)
55
- * - streamMode: 'structured' | 'simple' (claude agent only)
56
- * - log(msg): Logging function
57
- * @returns {Promise<object>} Action result
58
- */
59
- export async function executeAction(action, params, ctx = {}) {
60
- const handler = actionMap.get(action);
61
- if (!handler) throw new Error(`Unknown action: ${action}`);
62
- return handler(params, ctx);
63
- }
64
-
65
- /**
66
- * Check if an action uses streaming.
67
- * Streaming actions require ctx.stream() and return { exitCode, ... } via Promise.
68
- * Non-streaming actions return { data } directly.
69
- */
70
- export function isStreamingAction(action) {
71
- return streamingActions.has(action);
72
- }
73
-
74
- /**
75
- * Check if an action is registered.
76
- */
77
- export function hasAction(action) {
78
- return actionMap.has(action);
79
- }
80
-
81
- /**
82
- * Get all registered action names.
83
- */
84
- export function getActionNames() {
85
- return Array.from(actionMap.keys());
86
- }
87
-
88
- export { agents };
@@ -1,38 +0,0 @@
1
- /**
2
- * Shell Agent
3
- * Handles: shell-command
4
- *
5
- * Two execution modes:
6
- * - Persistent shell (connect.js) — commands share one shell process
7
- * - Simple exec (relay-client.js) — each command spawns a new process
8
- *
9
- * The caller provides the execution strategy via ctx.execShell or falls back to execCommand.
10
- */
11
- import { execCommand, DANGEROUS_SHELL_PATTERNS } from './utils.js';
12
-
13
- export default {
14
- name: 'shell',
15
- actions: {
16
- 'shell-command': async (params, ctx) => {
17
- const { command, cwd } = params;
18
- if (!command || typeof command !== 'string') throw new Error('Invalid command');
19
-
20
- // Block dangerous shell patterns
21
- const cmdLower = command.toLowerCase();
22
- if (DANGEROUS_SHELL_PATTERNS.some(d => cmdLower.includes(d.toLowerCase()))) {
23
- throw new Error('Command blocked for safety');
24
- }
25
-
26
- // Use persistent shell if provided (connect.js), otherwise simple exec
27
- if (ctx.getPersistentShell) {
28
- const shell = ctx.getPersistentShell(cwd || process.cwd());
29
- const result = await shell.exec(command, { timeoutMs: 60000 });
30
- return { stdout: result.stdout, stderr: result.stderr, exitCode: result.exitCode, cwd: result.cwd };
31
- }
32
-
33
- // Simple exec fallback
34
- const result = await execCommand(command, [], { cwd: cwd || process.cwd(), timeout: 60000 });
35
- return { stdout: result };
36
- },
37
- },
38
- };
@@ -1,136 +0,0 @@
1
- /**
2
- * Shared utilities for agent command handlers.
3
- * Used by both CLI relay clients and backend server.
4
- */
5
- import { spawn } from 'child_process';
6
- import { promises as fsPromises } from 'fs';
7
- import os from 'os';
8
- import path from 'path';
9
-
10
- /**
11
- * Execute a shell command and return stdout.
12
- * @param {string} cmd - Command to run
13
- * @param {string[]} args - Command arguments
14
- * @param {object} options - { cwd, env, timeout }
15
- * @returns {Promise<string>} stdout
16
- */
17
- export function execCommand(cmd, args, options = {}) {
18
- return new Promise((resolve, reject) => {
19
- const proc = spawn(cmd, args, {
20
- shell: true,
21
- cwd: options.cwd || os.homedir(),
22
- env: { ...process.env, ...options.env },
23
- stdio: ['pipe', 'pipe', 'pipe'],
24
- });
25
-
26
- let stdout = '';
27
- let stderr = '';
28
- proc.stdout.on('data', (d) => { stdout += d; });
29
- proc.stderr.on('data', (d) => { stderr += d; });
30
-
31
- const timeout = setTimeout(() => {
32
- proc.kill();
33
- reject(new Error('Command timed out'));
34
- }, options.timeout || 30000);
35
-
36
- proc.on('close', (code) => {
37
- clearTimeout(timeout);
38
- if (code === 0) resolve(stdout);
39
- else reject(new Error(stderr || `Exit code ${code}`));
40
- });
41
-
42
- proc.on('error', (err) => {
43
- clearTimeout(timeout);
44
- reject(err);
45
- });
46
- });
47
- }
48
-
49
- /**
50
- * Build a file tree for a directory (recursive).
51
- * @param {string} dirPath - Directory to scan
52
- * @param {number} maxDepth - Maximum recursion depth
53
- * @param {number} currentDepth - Current depth (internal)
54
- * @param {object} options - { maxEntries, includeStats, skipDotfilesAtRoot }
55
- * @returns {Promise<Array>} File tree items
56
- */
57
- export async function buildFileTree(dirPath, maxDepth, currentDepth = 0, options = {}) {
58
- const { maxEntries = 200, includeStats = false, skipDotfilesAtRoot = false } = options;
59
- if (currentDepth >= maxDepth) return [];
60
-
61
- const SKIP_DIRS = new Set(['node_modules', '.git', 'dist', 'build', '.svn', '.hg']);
62
-
63
- try {
64
- const entries = await fsPromises.readdir(dirPath, { withFileTypes: true });
65
- const items = [];
66
- for (const entry of entries.slice(0, maxEntries)) {
67
- if (SKIP_DIRS.has(entry.name)) continue;
68
- if (entry.name.startsWith('.') && skipDotfilesAtRoot && currentDepth === 0) continue;
69
-
70
- const itemPath = path.join(dirPath, entry.name);
71
- const item = {
72
- name: entry.name,
73
- path: itemPath,
74
- type: entry.isDirectory() ? 'directory' : 'file',
75
- };
76
-
77
- if (includeStats) {
78
- try {
79
- const stats = await fsPromises.stat(itemPath);
80
- item.size = stats.size;
81
- item.modified = stats.mtime.toISOString();
82
- } catch { /* ignore stat errors */ }
83
- }
84
-
85
- if (entry.isDirectory() && currentDepth < maxDepth - 1) {
86
- item.children = await buildFileTree(itemPath, maxDepth, currentDepth + 1, options);
87
- }
88
- items.push(item);
89
- }
90
- return items;
91
- } catch {
92
- return [];
93
- }
94
- }
95
-
96
- /**
97
- * Resolve a path that may start with ~ to an absolute path.
98
- * @param {string} inputPath - Path to resolve
99
- * @returns {string} Resolved absolute path
100
- */
101
- export function resolveTildePath(inputPath) {
102
- if (!inputPath) return os.homedir();
103
- if (inputPath === '~') return os.homedir();
104
- if (inputPath.startsWith('~/') || inputPath.startsWith('~\\')) {
105
- return path.join(os.homedir(), inputPath.slice(2));
106
- }
107
- return path.resolve(inputPath);
108
- }
109
-
110
- /** Blocked paths for file reads (security) */
111
- export const BLOCKED_READ_PATTERNS = ['/etc/shadow', '/etc/passwd', '.ssh/id_rsa', '.ssh/id_ed25519', '/.env'];
112
-
113
- /** Blocked paths for file writes (security) */
114
- export const BLOCKED_WRITE_PATTERNS = [
115
- '/etc/', '/usr/bin/', '/usr/sbin/',
116
- '/windows/system32', '/windows/syswow64', '/program files',
117
- '.ssh/', '/.env',
118
- ];
119
-
120
- /** Dangerous shell patterns to block */
121
- export const DANGEROUS_SHELL_PATTERNS = [
122
- 'rm -rf /', 'mkfs', 'dd if=', ':(){', 'fork bomb', '> /dev/sd',
123
- 'format c:', 'format d:', 'format e:', 'del /s /q c:\\',
124
- 'rd /s /q c:\\', 'reg delete', 'bcdedit',
125
- ];
126
-
127
- /**
128
- * Check if a normalized path matches any blocked patterns.
129
- * @param {string} normalizedPath - Absolute path (resolved)
130
- * @param {string[]} patterns - Blocked patterns to check
131
- * @returns {boolean}
132
- */
133
- export function isBlockedPath(normalizedPath, patterns) {
134
- const lower = normalizedPath.toLowerCase().replace(/\\/g, '/');
135
- return patterns.some(b => lower.includes(b));
136
- }
@@ -1,9 +0,0 @@
1
- #!/usr/bin/env node
2
- import { playInstallAnimation } from '../src/animation.js';
3
-
4
- try {
5
- await playInstallAnimation();
6
- } catch {
7
- // Silently fail — animation is cosmetic, don't break installs
8
- console.log('\n ✓ upfynai-code installed. Run `uc --help` to get started.\n');
9
- }
@@ -1,58 +0,0 @@
1
- #!/usr/bin/env node
2
- /**
3
- * Prepublish script — copies shared agents into dist/ for npm distribution.
4
- *
5
- * In the monorepo, connect.js imports from ../../shared/agents/.
6
- * For npm, we copy those files into dist/agents/ and connect.js
7
- * resolves them at runtime.
8
- */
9
- import { cpSync, mkdirSync, rmSync, existsSync } from 'fs';
10
- import { join, dirname } from 'path';
11
- import { fileURLToPath } from 'url';
12
-
13
- const __dirname = dirname(fileURLToPath(import.meta.url));
14
- const cliRoot = join(__dirname, '..');
15
- const distAgents = join(cliRoot, 'dist', 'agents');
16
- const sharedAgents = join(cliRoot, '..', 'shared', 'agents');
17
-
18
- // Clean
19
- if (existsSync(distAgents)) rmSync(distAgents, { recursive: true });
20
- mkdirSync(distAgents, { recursive: true });
21
-
22
- // Copy all agent files
23
- const files = [
24
- 'index.js', 'utils.js',
25
- 'claude.js', 'codex.js', 'cursor.js',
26
- 'shell.js', 'files.js', 'git.js', 'exec.js', 'detect.js',
27
- 'gitagent.js',
28
- ];
29
-
30
- let copied = 0;
31
- for (const file of files) {
32
- const src = join(sharedAgents, file);
33
- const dest = join(distAgents, file);
34
- if (existsSync(src)) {
35
- cpSync(src, dest);
36
- copied++;
37
- } else {
38
- console.warn(` [WARN] Missing: ${file}`);
39
- }
40
- }
41
-
42
- // Copy gitagent module (parser + prompt-builder) — needed by gitagent agent
43
- const sharedGitagent = join(cliRoot, '..', 'shared', 'gitagent');
44
- const distGitagent = join(cliRoot, 'dist', 'gitagent');
45
- if (existsSync(distGitagent)) rmSync(distGitagent, { recursive: true });
46
- mkdirSync(distGitagent, { recursive: true });
47
-
48
- const gitagentFiles = ['index.js', 'parser.js', 'prompt-builder.js'];
49
- for (const file of gitagentFiles) {
50
- const src = join(sharedGitagent, file);
51
- const dest = join(distGitagent, file);
52
- if (existsSync(src)) {
53
- cpSync(src, dest);
54
- copied++;
55
- }
56
- }
57
-
58
- console.log(` [prepublish] Copied ${copied} files to dist/`);
package/src/animation.js DELETED
@@ -1,228 +0,0 @@
1
- /**
2
- * CLI spaceship-to-star animation for Upfyn-Code.
3
- * Plays after install (postinstall) and before `uc connect` starts.
4
- */
5
-
6
- const STAR_FRAMES = ['✦', '✧', '✦', '★'];
7
-
8
- // Spaceship frames (4 animation states)
9
- const SHIP = [
10
- ' ╱▏▔▔╲ ',
11
- ' ╱ ▏══ ╲ ',
12
- '╱ ▏▁▁ ╲ ',
13
- ' ╱▏▔▔╲ ',
14
- ];
15
-
16
- // Simpler inline ship for the travel animation
17
- const SHIP_R = [
18
- ' ▄▄ ',
19
- ' ◁━━██━━▷ ',
20
- ' ▀▀ ',
21
- ];
22
-
23
- const SHIP_SMALL = '◁━━▶';
24
- const SHIP_TRAVEL = '⟫⟫';
25
- const EXHAUST_CHARS = ['░', '▒', '▓', '═', '~', '·'];
26
-
27
- function sleep(ms) {
28
- return new Promise(r => setTimeout(r, ms));
29
- }
30
-
31
- function clearLines(n) {
32
- for (let i = 0; i < n; i++) {
33
- process.stdout.write('\x1b[1A\x1b[2K');
34
- }
35
- }
36
-
37
- function dim(s) { return `\x1b[2m${s}\x1b[0m`; }
38
- function cyan(s) { return `\x1b[36m${s}\x1b[0m`; }
39
- function yellow(s) { return `\x1b[33m${s}\x1b[0m`; }
40
- function bold(s) { return `\x1b[1m${s}\x1b[0m`; }
41
- function magenta(s) { return `\x1b[35m${s}\x1b[0m`; }
42
- function white(s) { return `\x1b[97m${s}\x1b[0m`; }
43
- function green(s) { return `\x1b[32m${s}\x1b[0m`; }
44
- function blue(s) { return `\x1b[34m${s}\x1b[0m`; }
45
-
46
- /**
47
- * Generate a star field background line
48
- */
49
- function starFieldLine(width, density = 0.08, frame = 0) {
50
- let line = '';
51
- for (let i = 0; i < width; i++) {
52
- if (Math.random() < density) {
53
- const stars = ['.', '·', '∘', '°', '✧'];
54
- const s = stars[Math.floor(Math.random() * stars.length)];
55
- line += dim(s);
56
- } else {
57
- line += ' ';
58
- }
59
- }
60
- return line;
61
- }
62
-
63
- /**
64
- * Main spaceship-to-star animation
65
- * @param {'install'|'connect'} mode
66
- */
67
- export async function playSpaceshipAnimation(mode = 'connect') {
68
- const cols = Math.min(process.stdout.columns || 70, 80);
69
- const totalFrames = 28;
70
- const LINES = 11; // total lines we'll use
71
-
72
- const starX = cols - 6;
73
-
74
- // Phase 1: Launch sequence text
75
- const tagline = mode === 'install'
76
- ? 'Installation complete!'
77
- : 'Launching relay bridge...';
78
-
79
- console.log('');
80
- console.log(dim(' ─'.repeat(Math.floor(cols / 3))));
81
- console.log('');
82
-
83
- // Phase 2: Spaceship travels across the screen toward a star
84
- for (let frame = 0; frame < totalFrames; frame++) {
85
- const progress = frame / (totalFrames - 1); // 0 → 1
86
- const shipX = Math.floor(progress * (cols - 16)) + 2;
87
-
88
- // Build exhaust trail
89
- const exhaustLen = Math.min(shipX, Math.floor(progress * 20));
90
- let exhaust = '';
91
- for (let e = 0; e < exhaustLen; e++) {
92
- const intensity = 1 - (e / exhaustLen);
93
- if (intensity > 0.7) exhaust = '▓' + exhaust;
94
- else if (intensity > 0.4) exhaust = '▒' + exhaust;
95
- else if (intensity > 0.2) exhaust = '░' + exhaust;
96
- else exhaust = '·' + exhaust;
97
- }
98
-
99
- // Star pulse
100
- const starChar = STAR_FRAMES[frame % STAR_FRAMES.length];
101
- const starGlow = progress > 0.7 ? yellow('✦ ') : '';
102
-
103
- // Build the 5 display lines
104
- const lines = [];
105
-
106
- // Line 1: starfield
107
- lines.push(' ' + starFieldLine(cols - 4, 0.05, frame));
108
-
109
- // Line 2: top space
110
- lines.push(' ' + starFieldLine(cols - 4, 0.03, frame));
111
-
112
- // Line 3: ship row (main action)
113
- let shipRow = '';
114
- const beforeShip = Math.max(0, shipX - exhaustLen);
115
- shipRow += ' '.repeat(beforeShip);
116
- shipRow += dim(exhaust);
117
- shipRow += cyan(' ◁━━▶');
118
- // Fill to star position
119
- const afterShip = Math.max(0, starX - shipX - 7);
120
- // Dots between ship and star
121
- let midSpace = '';
122
- for (let d = 0; d < afterShip; d++) {
123
- midSpace += Math.random() < 0.06 ? dim('·') : ' ';
124
- }
125
- shipRow += midSpace;
126
- if (progress < 0.92) {
127
- shipRow += starGlow + yellow(starChar);
128
- } else {
129
- shipRow += yellow('✦★✦');
130
- }
131
- lines.push(shipRow);
132
-
133
- // Line 4: thrust glow
134
- let thrustRow = ' '.repeat(Math.max(0, shipX + 1));
135
- if (frame % 2 === 0) {
136
- thrustRow += dim(magenta('~≈~'));
137
- } else {
138
- thrustRow += dim(magenta('≈~≈'));
139
- }
140
- lines.push(thrustRow);
141
-
142
- // Line 5: starfield
143
- lines.push(' ' + starFieldLine(cols - 4, 0.04, frame));
144
-
145
- // Line 6: message (centered)
146
- const msg = progress < 0.3
147
- ? dim(` ${tagline}`)
148
- : progress < 0.6
149
- ? cyan(` ⟫ Navigating to the stars...`)
150
- : progress < 0.9
151
- ? magenta(` ⟫⟫ Almost there...`)
152
- : green(` ★ ${mode === 'install' ? 'Ready for launch!' : 'Connection established!'}`);
153
- lines.push(msg);
154
-
155
- // Line 7: progress bar
156
- const barWidth = cols - 10;
157
- const filled = Math.floor(progress * barWidth);
158
- const bar = ' ' + dim('[')
159
- + cyan('█'.repeat(filled))
160
- + dim('░'.repeat(barWidth - filled))
161
- + dim(']')
162
- + dim(` ${Math.floor(progress * 100)}%`);
163
- lines.push(bar);
164
-
165
- // Print
166
- if (frame > 0) clearLines(lines.length);
167
- for (const l of lines) console.log(l);
168
-
169
- // Speed: start slow, middle fast, end slow
170
- const delay = progress < 0.2 ? 120
171
- : progress > 0.85 ? 150
172
- : 60;
173
- await sleep(delay);
174
- }
175
-
176
- // Phase 3: Final flash
177
- await sleep(200);
178
- clearLines(7);
179
-
180
- // Arrival burst
181
- const burstLines = [];
182
- burstLines.push(' ' + starFieldLine(cols - 4, 0.06));
183
- burstLines.push('');
184
- burstLines.push(
185
- ' '.repeat(Math.floor(cols / 2 - 12))
186
- + yellow('· ✧ · ★ ')
187
- + bold(white('UPFYN'))
188
- + yellow(' ★ · ✧ ·')
189
- );
190
- burstLines.push('');
191
-
192
- if (mode === 'install') {
193
- burstLines.push(
194
- ' '.repeat(Math.floor(cols / 2 - 20))
195
- + green('✓ ') + bold('upfynai-code') + dim(' installed successfully')
196
- );
197
- burstLines.push('');
198
- burstLines.push(dim(' Quick start:'));
199
- burstLines.push(cyan(' uc login ') + dim('— authenticate'));
200
- burstLines.push(cyan(' uc connect ') + dim('— bridge to cloud'));
201
- burstLines.push(cyan(' uc --local ') + dim('— start local server'));
202
- } else {
203
- burstLines.push(
204
- ' '.repeat(Math.floor(cols / 2 - 16))
205
- + green('✓ ') + bold('Relay bridge activated')
206
- );
207
- }
208
-
209
- burstLines.push('');
210
- burstLines.push(dim(' ─'.repeat(Math.floor(cols / 3))));
211
- burstLines.push('');
212
-
213
- for (const l of burstLines) console.log(l);
214
- }
215
-
216
- /**
217
- * Postinstall animation (shorter variant)
218
- */
219
- export async function playInstallAnimation() {
220
- return playSpaceshipAnimation('install');
221
- }
222
-
223
- /**
224
- * Connect animation
225
- */
226
- export async function playConnectAnimation() {
227
- return playSpaceshipAnimation('connect');
228
- }
package/src/auth.js DELETED
@@ -1,122 +0,0 @@
1
- import prompts from 'prompts';
2
- import chalk from 'chalk';
3
- import { readConfig, writeConfig, clearConfig, displayUrl } from './config.js';
4
-
5
- async function apiCall(path, options = {}) {
6
- const config = readConfig();
7
- const url = `${config.serverUrl}${path}`;
8
- const res = await fetch(url, {
9
- ...options,
10
- headers: {
11
- 'Content-Type': 'application/json',
12
- ...(options.headers || {}),
13
- },
14
- });
15
- return res;
16
- }
17
-
18
- export function getToken() {
19
- const config = readConfig();
20
- return config.token || null;
21
- }
22
-
23
- export async function validateToken() {
24
- const token = getToken();
25
- if (!token) return null;
26
-
27
- try {
28
- const res = await apiCall('/api/auth/user', {
29
- headers: { Authorization: `Bearer ${token}` },
30
- });
31
- if (!res.ok) return null;
32
- const data = await res.json();
33
- return data.user || null;
34
- } catch {
35
- return null;
36
- }
37
- }
38
-
39
- export async function login(options = {}) {
40
- // Allow --server flag to override the server URL
41
- if (options.server) {
42
- writeConfig({ serverUrl: options.server.replace(/\/+$/, '') });
43
- }
44
-
45
- console.log(chalk.bold('\n Upfyn Code — Login\n'));
46
-
47
- const response = await prompts([
48
- {
49
- type: 'text',
50
- name: 'username',
51
- message: 'Username',
52
- validate: v => (v.trim() ? true : 'Username is required'),
53
- },
54
- {
55
- type: 'password',
56
- name: 'password',
57
- message: 'Password',
58
- validate: v => (v ? true : 'Password is required'),
59
- },
60
- ], {
61
- onCancel: () => {
62
- console.log(chalk.dim('\n Login cancelled.\n'));
63
- process.exit(0);
64
- },
65
- });
66
-
67
- const { username, password } = response;
68
-
69
- try {
70
- const res = await apiCall('/api/auth/login', {
71
- method: 'POST',
72
- body: JSON.stringify({ username: username.trim(), password }),
73
- });
74
-
75
- const data = await res.json();
76
-
77
- if (!res.ok) {
78
- console.log(chalk.red(`\n Login failed: ${data.error || 'Unknown error'}\n`));
79
- process.exit(1);
80
- }
81
-
82
- writeConfig({
83
- token: data.token,
84
- user: data.user,
85
- });
86
-
87
- const name = data.user.first_name || data.user.username;
88
- console.log(chalk.green(`\n Logged in as ${chalk.bold(name)}!\n`));
89
- } catch (err) {
90
- const config = readConfig();
91
- console.log(chalk.red(`\n Connection error. Could not reach ${displayUrl(config.serverUrl)}.`));
92
- console.log(chalk.dim(' Check your network and try again.\n'));
93
- process.exit(1);
94
- }
95
- }
96
-
97
- export async function logout() {
98
- clearConfig();
99
- console.log(chalk.green('\n Logged out. Credentials cleared.\n'));
100
- }
101
-
102
- export async function status() {
103
- const config = readConfig();
104
-
105
- if (!config.token) {
106
- console.log(chalk.yellow('\n Not logged in. Run `uc login` to authenticate.\n'));
107
- return;
108
- }
109
-
110
- console.log(chalk.dim('\n Checking session...'));
111
- const user = await validateToken();
112
-
113
- if (!user) {
114
- console.log(chalk.yellow(' Session expired. Run `uc login` to re-authenticate.\n'));
115
- return;
116
- }
117
-
118
- const name = user.first_name || user.username;
119
- console.log(chalk.bold(` Logged in as: ${chalk.cyan(name)} (${chalk.dim(user.username)})`));
120
- console.log(chalk.dim(` Server: ${displayUrl(config.serverUrl)}`));
121
- console.log(chalk.dim(` Local port: ${config.localPort}\n`));
122
- }