@cnrai/pave 0.3.32 → 0.3.34

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 (83) hide show
  1. package/MARKETPLACE.md +406 -0
  2. package/README.md +218 -21
  3. package/build-binary.js +591 -0
  4. package/build-npm.js +537 -0
  5. package/build.js +230 -0
  6. package/check-binary.js +26 -0
  7. package/deploy.sh +95 -0
  8. package/index.js +5775 -0
  9. package/lib/agent-registry.js +1037 -0
  10. package/lib/args-parser.js +837 -0
  11. package/lib/blessed-widget-patched.js +93 -0
  12. package/lib/cli-markdown.js +590 -0
  13. package/lib/compaction.js +153 -0
  14. package/lib/duration.js +94 -0
  15. package/lib/hash.js +22 -0
  16. package/lib/marketplace.js +866 -0
  17. package/lib/memory-config.js +166 -0
  18. package/lib/skill-manager.js +891 -0
  19. package/lib/soul.js +31 -0
  20. package/lib/tool-output-formatter.js +180 -0
  21. package/package.json +35 -33
  22. package/start-pave.sh +149 -0
  23. package/status.js +271 -0
  24. package/test/abort-stream.test.js +445 -0
  25. package/test/agent-auto-compaction.test.js +552 -0
  26. package/test/agent-comm-abort.test.js +95 -0
  27. package/test/agent-comm.test.js +598 -0
  28. package/test/agent-inbox.test.js +576 -0
  29. package/test/agent-init.test.js +264 -0
  30. package/test/agent-interrupt.test.js +314 -0
  31. package/test/agent-lifecycle.test.js +520 -0
  32. package/test/agent-log-files.test.js +349 -0
  33. package/test/agent-mode.manual-test.js +392 -0
  34. package/test/agent-parsing.test.js +228 -0
  35. package/test/agent-post-stream-idle.test.js +762 -0
  36. package/test/agent-registry.test.js +359 -0
  37. package/test/agent-rm.test.js +442 -0
  38. package/test/agent-spawn.test.js +933 -0
  39. package/test/agent-status-api.test.js +624 -0
  40. package/test/agent-update.test.js +435 -0
  41. package/test/args-parser.test.js +391 -0
  42. package/test/auto-compaction-chat.manual-test.js +227 -0
  43. package/test/auto-compaction.test.js +941 -0
  44. package/test/build-config.test.js +120 -0
  45. package/test/build-npm.test.js +388 -0
  46. package/test/chat-command.test.js +137 -0
  47. package/test/chat-leading-lines.test.js +159 -0
  48. package/test/config-flag.test.js +272 -0
  49. package/test/cursor-drift.test.js +135 -0
  50. package/test/debug-require.js +23 -0
  51. package/test/dir-migration.test.js +323 -0
  52. package/test/duration.test.js +229 -0
  53. package/test/ghostty-term.test.js +202 -0
  54. package/test/http500-backoff.test.js +854 -0
  55. package/test/integration.test.js +86 -0
  56. package/test/memory-guard-env.test.js +220 -0
  57. package/test/pr233-fixes.test.js +259 -0
  58. package/test/run-agent-init.js +297 -0
  59. package/test/run-all.js +64 -0
  60. package/test/run-config-flag.js +159 -0
  61. package/test/run-cursor-drift.js +82 -0
  62. package/test/run-session-path.js +154 -0
  63. package/test/run-tests.js +643 -0
  64. package/test/sandbox-redirect.test.js +202 -0
  65. package/test/session-path.test.js +132 -0
  66. package/test/shebang-strip.test.js +241 -0
  67. package/test/soul-reinject.test.js +1027 -0
  68. package/test/soul-reread.test.js +281 -0
  69. package/test/tool-output-formatter.test.js +486 -0
  70. package/test/tool-output-gating.test.js +143 -0
  71. package/test/tool-states.test.js +167 -0
  72. package/test/tools-flag.test.js +65 -0
  73. package/test/tui-attach.test.js +1255 -0
  74. package/test/tui-compaction.test.js +354 -0
  75. package/test/tui-wrap.test.js +568 -0
  76. package/test-binary.js +52 -0
  77. package/test-binary2.js +36 -0
  78. package/LICENSE +0 -21
  79. package/pave.js +0 -2
  80. package/sandbox/SandboxRunner.js +0 -1
  81. package/sandbox/pave-run.js +0 -2
  82. package/sandbox/permission.js +0 -1
  83. package/sandbox/utils/yaml.js +0 -1
package/build.js ADDED
@@ -0,0 +1,230 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Build script for PAVE distribution
4
+ *
5
+ * Creates a distributable package that can be run directly with Node.js
6
+ *
7
+ * Output:
8
+ * dist/
9
+ * pave.js - Main executable (bundled)
10
+ * package.json - Minimal dependencies (blessed only)
11
+ * node_modules/ - blessed (auto-installed with --install)
12
+ */
13
+
14
+ const esbuild = require('esbuild');
15
+ const fs = require('fs');
16
+ const path = require('path');
17
+ const { execSync } = require('child_process');
18
+
19
+ // Get version from package.json
20
+ const packageJson = JSON.parse(fs.readFileSync(path.join(__dirname, 'package.json'), 'utf8'));
21
+ const VERSION = packageJson.version || '0.0.0';
22
+ console.log(`Building PAVE version: ${VERSION}`);
23
+
24
+ const DIST_DIR = path.join(__dirname, 'dist');
25
+ const BUNDLE_PATH = path.join(DIST_DIR, 'pave.js');
26
+ const PACKAGE_PATH = path.join(DIST_DIR, 'package.json');
27
+
28
+ // Check for flags
29
+ const shouldInstall = process.argv.includes('--install');
30
+
31
+ async function build() {
32
+ console.log('='.repeat(50));
33
+ console.log('Building PAVE Distribution');
34
+ console.log('='.repeat(50));
35
+
36
+ // Clean and recreate dist directory
37
+ if (fs.existsSync(DIST_DIR)) {
38
+ fs.rmSync(DIST_DIR, { recursive: true, force: true });
39
+ }
40
+ fs.mkdirSync(DIST_DIR, { recursive: true });
41
+
42
+ // Step 1: Bundle with esbuild
43
+ console.log('\n[1/3] Bundling with esbuild...');
44
+
45
+ try {
46
+ await esbuild.build({
47
+ entryPoints: [path.join(__dirname, 'index.js')],
48
+ bundle: true,
49
+ platform: 'node',
50
+ target: 'node16',
51
+ outfile: BUNDLE_PATH,
52
+ // Inject version at build time
53
+ define: {
54
+ PAVE_VERSION: JSON.stringify(VERSION),
55
+ },
56
+ // Help esbuild find modules when bundling files from ../opencode-lite/
57
+ nodePaths: [path.join(__dirname, 'node_modules')],
58
+ // Keep external modules that can't be bundled due to dynamic requires
59
+ external: [
60
+ 'blessed', // Terminal UI - uses dynamic requires
61
+ 'abort-controller', // Optional polyfill (native in Node 16+)
62
+ 'term.js', // Optional blessed terminal widget
63
+ 'pty.js', // Optional blessed pty support
64
+ ],
65
+ // Minify for smaller size
66
+ minify: true,
67
+ // Keep names for better error messages
68
+ keepNames: true,
69
+ // Source maps for debugging (optional)
70
+ sourcemap: false,
71
+ // CommonJS format
72
+ format: 'cjs',
73
+ });
74
+
75
+ // Add shebang as first line and make executable
76
+ let bundleContent = fs.readFileSync(BUNDLE_PATH, 'utf-8');
77
+ bundleContent = bundleContent.replace(/^(#!.*\n)+/, '');
78
+ bundleContent = '#!/usr/bin/env node\n' + bundleContent;
79
+ fs.writeFileSync(BUNDLE_PATH, bundleContent);
80
+ fs.chmodSync(BUNDLE_PATH, '755');
81
+
82
+ const bundleStats = fs.statSync(BUNDLE_PATH);
83
+ console.log(' Bundle created: ' + BUNDLE_PATH);
84
+ console.log(' Bundle size: ' + (bundleStats.size / 1024).toFixed(1) + ' KB');
85
+ } catch (err) {
86
+ console.error('Bundle failed:', err);
87
+ process.exit(1);
88
+ }
89
+
90
+ // Step 2: Create package.json with minimal dependencies
91
+ console.log('\n[2/3] Creating package.json...');
92
+
93
+ const distPackage = {
94
+ name: 'pave',
95
+ version: '1.0.0',
96
+ description: 'PAVE - Personal AI Virtual Environment',
97
+ main: 'pave.js',
98
+ bin: {
99
+ pave: './pave.js',
100
+ },
101
+ scripts: {
102
+ start: 'node pave.js',
103
+ 'start:ish': 'node --expose-gc --jitless --max-old-space-size=128 pave.js',
104
+ },
105
+ engines: {
106
+ node: '>=16.0.0',
107
+ },
108
+ dependencies: {
109
+ blessed: '^0.1.81',
110
+ 'js-yaml': '^4.1.0', // Required for sandbox permissions YAML parsing
111
+ },
112
+ };
113
+
114
+ fs.writeFileSync(PACKAGE_PATH, JSON.stringify(distPackage, null, 2));
115
+ console.log(' Package.json created: ' + PACKAGE_PATH);
116
+
117
+ // Step 2.5: Copy sandbox runner files (pave-run.js and dependencies)
118
+ console.log('\n[2.5/3] Copying sandbox runner files...');
119
+
120
+ const OPENCODE_LITE_DIR = path.join(__dirname, '..', 'opencode-lite');
121
+ const SANDBOX_DEST_DIR = path.join(DIST_DIR, 'sandbox');
122
+
123
+ // Create sandbox directory
124
+ fs.mkdirSync(SANDBOX_DEST_DIR, { recursive: true });
125
+
126
+ // Files to copy for sandbox execution
127
+ const sandboxFiles = [
128
+ { src: 'bin/pave-run.js', dest: 'pave-run.js' },
129
+ { src: 'src/sandbox/SandboxRunner.js', dest: 'SandboxRunner.js' },
130
+ { src: 'src/tools/permission.js', dest: 'permission.js' },
131
+ { src: 'src/utils/yaml.js', dest: 'utils/yaml.js' },
132
+ ];
133
+
134
+ // Create utils subdirectory for yaml.js
135
+ fs.mkdirSync(path.join(SANDBOX_DEST_DIR, 'utils'), { recursive: true });
136
+
137
+ for (const file of sandboxFiles) {
138
+ const srcPath = path.join(OPENCODE_LITE_DIR, file.src);
139
+ const destPath = path.join(SANDBOX_DEST_DIR, file.dest);
140
+
141
+ if (fs.existsSync(srcPath)) {
142
+ let content = fs.readFileSync(srcPath, 'utf-8');
143
+
144
+ // Fix require paths for the bundled structure
145
+ if (file.dest === 'pave-run.js') {
146
+ // Update paths in pave-run.js to point to local files
147
+ content = content.replace(
148
+ /var sandboxPath = path\.join\(__dirname.*SandboxRunner\.js'\);/,
149
+ "var sandboxPath = path.join(__dirname, 'SandboxRunner.js');",
150
+ );
151
+ content = content.replace(
152
+ /var permissionPath = path\.join\(__dirname.*permission\.js'\);/,
153
+ "var permissionPath = path.join(__dirname, 'permission.js');",
154
+ );
155
+ }
156
+
157
+ if (file.dest === 'SandboxRunner.js') {
158
+ // Update paths in SandboxRunner.js to point to local permission.js
159
+ content = content.replace(
160
+ /} = require\(['"]\.\.\/tools\/permission['"]\);/,
161
+ "} = require('./permission');",
162
+ );
163
+ content = content.replace(
164
+ /require\(['"]\.\.\/tools\/permission['"]\)/g,
165
+ "require('./permission')",
166
+ );
167
+ }
168
+
169
+ if (file.dest === 'permission.js') {
170
+ // Update paths in permission.js to point to local utils/yaml.js
171
+ content = content.replace(
172
+ /require\(['"]\.\.\/utils\/yaml['"]\)/g,
173
+ "require('./utils/yaml')",
174
+ );
175
+ }
176
+
177
+ fs.writeFileSync(destPath, content);
178
+ console.log(' Copied: ' + file.dest);
179
+ } else {
180
+ console.warn(' Warning: Missing file: ' + srcPath);
181
+ }
182
+ }
183
+
184
+ console.log(' Sandbox runner files copied to: ' + SANDBOX_DEST_DIR);
185
+
186
+ // Step 3: Optionally install dependencies
187
+ if (shouldInstall) {
188
+ console.log('\n[3/3] Installing dependencies...');
189
+ try {
190
+ execSync('npm install --production', {
191
+ cwd: DIST_DIR,
192
+ stdio: 'inherit',
193
+ });
194
+ console.log(' Dependencies installed');
195
+ } catch (err) {
196
+ console.error(' Failed to install dependencies:', err.message);
197
+ console.error(' Run manually: cd dist && npm install');
198
+ }
199
+ } else {
200
+ console.log('\n[3/3] Skipping dependency installation');
201
+ console.log(' Run: cd dist && npm install');
202
+ console.log(' Or use: node build.js --install');
203
+ }
204
+
205
+ // Calculate total size
206
+ let totalSize = fs.statSync(BUNDLE_PATH).size;
207
+ if (fs.existsSync(PACKAGE_PATH)) {
208
+ totalSize += fs.statSync(PACKAGE_PATH).size;
209
+ }
210
+
211
+ console.log('\n' + '='.repeat(50));
212
+ console.log('Build complete!');
213
+ console.log('='.repeat(50));
214
+ console.log('\nDistribution: ' + DIST_DIR);
215
+ console.log('Bundle size: ' + (totalSize / 1024).toFixed(1) + ' KB');
216
+ console.log('\nTo use:');
217
+ console.log(' 1. cd dist && npm install # Install blessed');
218
+ console.log(' 2. node pave.js # Run PAVE');
219
+ console.log('\nOr copy the entire dist/ folder to deploy:');
220
+ console.log(' cp -r dist /path/to/deploy/pave');
221
+ console.log(' cd /path/to/deploy/pave && npm install && node pave.js');
222
+ console.log('\nFor iSH iOS:');
223
+ console.log(' node --expose-gc --jitless pave.js');
224
+ console.log('\nBuilt with Node ' + process.version);
225
+ }
226
+
227
+ build().catch((err) => {
228
+ console.error('Build failed:', err);
229
+ process.exit(1);
230
+ });
@@ -0,0 +1,26 @@
1
+ const fs = require('fs');
2
+
3
+ const binaryPath = '/Users/raymond/pave-apps/openpave/src/packages/pave/dist/bin/pave-darwin-arm64';
4
+
5
+ try {
6
+ const binary = fs.readFileSync(binaryPath);
7
+ const str = binary.toString('utf8');
8
+
9
+ console.log('='.repeat(60));
10
+ console.log('PAVE Binary Analysis');
11
+ console.log('='.repeat(60));
12
+ console.log('Binary size:', (binary.length / 1024 / 1024).toFixed(1), 'MB');
13
+ console.log('');
14
+ console.log('Checking if sensitive strings are visible:');
15
+ console.log('');
16
+ console.log(' newGlobal:', str.includes('newGlobal') ? '⚠️ FOUND' : '✅ NOT FOUND');
17
+ console.log(' os.system:', str.includes('os.system') ? '⚠️ FOUND' : '✅ NOT FOUND');
18
+ console.log(' SandboxRunner:', str.includes('SandboxRunner') ? '⚠️ FOUND' : '✅ NOT FOUND');
19
+ console.log(' __ipc__:', str.includes('__ipc__') ? '⚠️ FOUND' : '✅ NOT FOUND');
20
+ console.log(' drainJobQueue:', str.includes('drainJobQueue') ? '⚠️ FOUND' : '✅ NOT FOUND');
21
+ console.log(' OPENCODE_TOKENS:', str.includes('OPENCODE_TOKENS') ? '⚠️ FOUND' : '✅ NOT FOUND');
22
+ console.log('');
23
+ console.log('='.repeat(60));
24
+ } catch (err) {
25
+ console.error('Error:', err.message);
26
+ }
package/deploy.sh ADDED
@@ -0,0 +1,95 @@
1
+ #!/bin/bash
2
+ #
3
+ # PAVE Deployment Script
4
+ # Deploys PAVE to a remote server
5
+ #
6
+ # Usage: ./deploy.sh [user@host:port] [install_path]
7
+ # Default: root@default-2.local:2222 /root/pave
8
+ #
9
+
10
+ set -e
11
+
12
+ # Configuration
13
+ REMOTE="${1:-root@default-2.local}"
14
+ PORT="${2:-2222}"
15
+ INSTALL_PATH="${3:-/root/pave}"
16
+ SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
17
+
18
+ # Parse host and port from first argument if port included
19
+ if [[ "$REMOTE" == *":"* ]]; then
20
+ PORT="${REMOTE##*:}"
21
+ REMOTE="${REMOTE%:*}"
22
+ fi
23
+
24
+ echo "=================================================="
25
+ echo "PAVE Deployment Script"
26
+ echo "=================================================="
27
+ echo "Target: $REMOTE (port $PORT)"
28
+ echo "Install path: $INSTALL_PATH"
29
+ echo "Source: $SCRIPT_DIR"
30
+ echo ""
31
+
32
+ # Step 1: Build the distribution
33
+ echo "[1/4] Building distribution..."
34
+ cd "$SCRIPT_DIR"
35
+ node build.js
36
+
37
+ if [ ! -f "$SCRIPT_DIR/dist/pave.js" ]; then
38
+ echo "ERROR: Build failed - dist/pave.js not found"
39
+ exit 1
40
+ fi
41
+
42
+ echo " Build complete"
43
+
44
+ # Step 2: Install dependencies in dist
45
+ echo ""
46
+ echo "[2/4] Installing dependencies in dist..."
47
+ cd "$SCRIPT_DIR/dist"
48
+ npm i --production
49
+ cd "$SCRIPT_DIR"
50
+
51
+ echo " Dependencies installed"
52
+
53
+ # Step 3: Create remote directory and copy all files in dist using tar over ssh (iSH doesn't support scp)
54
+ echo ""
55
+ echo "[3/4] Copying dist/* to remote server..."
56
+
57
+ ssh -p "$PORT" "$REMOTE" "mkdir -p $INSTALL_PATH"
58
+ tar -cf - -C "$SCRIPT_DIR/dist" . | ssh -p "$PORT" "$REMOTE" "tar -xf - -C $INSTALL_PATH"
59
+
60
+ echo " Files copied"
61
+
62
+ # Step 4: Create symlink in /usr/local/bin
63
+ echo ""
64
+ echo "[4/4] Creating /usr/local/bin/pave and /bin/pave launchers..."
65
+
66
+ # Node options for iSH (memory-constrained environment)
67
+ NODE_OPTS="--jitless --max-old-space-size=128 --optimize-for-size --no-lazy --expose-gc --gc-interval=25 --max-semi-space-size=8 --memory-reducer --no-compilation-cache --no-turbo-inlining --no-use-osr --no-opt --stack-size=512"
68
+
69
+ ssh -p "$PORT" "$REMOTE" "
70
+ cat > /usr/local/bin/pave << WRAPPER
71
+ #!/bin/sh
72
+ # PAVE launcher (iSH optimized)
73
+ exec node $NODE_OPTS $INSTALL_PATH/pave.js \"\\\$@\"
74
+ WRAPPER
75
+ chmod +x /usr/local/bin/pave
76
+ cp /usr/local/bin/pave /bin/pave 2>/dev/null || true
77
+ "
78
+
79
+ echo ""
80
+ echo "=================================================="
81
+ echo "Deployment complete!"
82
+ echo "=================================================="
83
+ echo ""
84
+ echo "To run PAVE on the remote server:"
85
+ echo " ssh -p $PORT $REMOTE"
86
+ echo " pave"
87
+ echo ""
88
+ echo "Or with custom port:"
89
+ echo " PORT=4097 pave"
90
+ echo ""
91
+ echo "The launcher includes iSH-optimized Node options:"
92
+ echo " --jitless --max-old-space-size=128 --expose-gc ..."
93
+ echo ""
94
+ echo "Server logs are written to: ~/.pave/pave.log"
95
+ echo ""