@cnrai/pave 0.3.33 → 0.3.35
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/MARKETPLACE.md +406 -0
- package/README.md +218 -21
- package/build-binary.js +591 -0
- package/build-npm.js +537 -0
- package/build.js +230 -0
- package/check-binary.js +26 -0
- package/deploy.sh +95 -0
- package/index.js +5776 -0
- package/lib/agent-registry.js +1037 -0
- package/lib/args-parser.js +837 -0
- package/lib/blessed-widget-patched.js +93 -0
- package/lib/cli-markdown.js +590 -0
- package/lib/compaction.js +153 -0
- package/lib/duration.js +94 -0
- package/lib/hash.js +22 -0
- package/lib/marketplace.js +866 -0
- package/lib/memory-config.js +166 -0
- package/lib/skill-manager.js +891 -0
- package/lib/soul.js +31 -0
- package/lib/tool-output-formatter.js +180 -0
- package/package.json +35 -32
- package/start-pave.sh +149 -0
- package/status.js +271 -0
- package/test/abort-stream.test.js +445 -0
- package/test/agent-auto-compaction.test.js +552 -0
- package/test/agent-comm-abort.test.js +95 -0
- package/test/agent-comm.test.js +598 -0
- package/test/agent-inbox.test.js +576 -0
- package/test/agent-init.test.js +264 -0
- package/test/agent-interrupt.test.js +314 -0
- package/test/agent-lifecycle.test.js +520 -0
- package/test/agent-log-files.test.js +349 -0
- package/test/agent-mode.manual-test.js +392 -0
- package/test/agent-parsing.test.js +228 -0
- package/test/agent-post-stream-idle.test.js +762 -0
- package/test/agent-registry.test.js +359 -0
- package/test/agent-rm.test.js +442 -0
- package/test/agent-spawn.test.js +933 -0
- package/test/agent-status-api.test.js +624 -0
- package/test/agent-update.test.js +435 -0
- package/test/args-parser.test.js +391 -0
- package/test/auto-compaction-chat.manual-test.js +227 -0
- package/test/auto-compaction.test.js +941 -0
- package/test/build-config.test.js +120 -0
- package/test/build-npm.test.js +388 -0
- package/test/chat-command.test.js +137 -0
- package/test/chat-leading-lines.test.js +159 -0
- package/test/config-flag.test.js +272 -0
- package/test/cursor-drift.test.js +135 -0
- package/test/debug-require.js +23 -0
- package/test/dir-migration.test.js +323 -0
- package/test/duration.test.js +229 -0
- package/test/ghostty-term.test.js +202 -0
- package/test/http500-backoff.test.js +854 -0
- package/test/integration.test.js +86 -0
- package/test/memory-guard-env.test.js +220 -0
- package/test/pr233-fixes.test.js +259 -0
- package/test/run-agent-init.js +297 -0
- package/test/run-all.js +64 -0
- package/test/run-config-flag.js +159 -0
- package/test/run-cursor-drift.js +82 -0
- package/test/run-session-path.js +154 -0
- package/test/run-tests.js +643 -0
- package/test/sandbox-redirect.test.js +202 -0
- package/test/session-path.test.js +132 -0
- package/test/shebang-strip.test.js +241 -0
- package/test/soul-reinject.test.js +1027 -0
- package/test/soul-reread.test.js +281 -0
- package/test/tool-output-formatter.test.js +486 -0
- package/test/tool-output-gating.test.js +143 -0
- package/test/tool-states.test.js +167 -0
- package/test/tools-flag.test.js +65 -0
- package/test/tui-attach.test.js +1255 -0
- package/test/tui-compaction.test.js +354 -0
- package/test/tui-wrap.test.js +568 -0
- package/test-binary.js +52 -0
- package/test-binary2.js +36 -0
- package/LICENSE +0 -21
- package/pave.js +0 -3
- package/sandbox/SandboxRunner.js +0 -1
- package/sandbox/pave-run.js +0 -2
- package/sandbox/permission.js +0 -1
- package/sandbox/utils/yaml.js +0 -1
package/lib/soul.js
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SOUL file validation helper.
|
|
3
|
+
* This module has NO side effects when required - safe to import in tests.
|
|
4
|
+
*
|
|
5
|
+
* @module lib/soul
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const fs = require('fs');
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Validate that a SOUL file path points to an existing, readable, regular file.
|
|
12
|
+
* Returns { valid: true } on success, or { valid: false, error: string } on failure.
|
|
13
|
+
* @param {string} resolvedPath - Absolute path to the SOUL file
|
|
14
|
+
* @returns {{ valid: boolean, error?: string }}
|
|
15
|
+
*/
|
|
16
|
+
function validateSoulFile(resolvedPath) {
|
|
17
|
+
try {
|
|
18
|
+
const stat = fs.statSync(resolvedPath);
|
|
19
|
+
if (!stat.isFile()) {
|
|
20
|
+
return { valid: false, error: `SOUL path is not a regular file: ${resolvedPath}` };
|
|
21
|
+
}
|
|
22
|
+
fs.accessSync(resolvedPath, fs.constants.R_OK);
|
|
23
|
+
return { valid: true };
|
|
24
|
+
} catch (err) {
|
|
25
|
+
const code = err && err.code ? ` (${err.code})` : '';
|
|
26
|
+
const message = err && err.message ? err.message : 'Unknown error';
|
|
27
|
+
return { valid: false, error: `Error validating SOUL file${code}: ${message} (path: ${resolvedPath})` };
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
module.exports = { validateSoulFile };
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool Output Formatting Utilities for PAVE CLI
|
|
3
|
+
* Provides shell-box style formatting matching the TUI output format
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
// ANSI color codes for tool output
|
|
7
|
+
const TOOL_COLORS = {
|
|
8
|
+
reset: '\x1b[0m',
|
|
9
|
+
bold: '\x1b[1m',
|
|
10
|
+
dim: '\x1b[2m',
|
|
11
|
+
red: '\x1b[31m',
|
|
12
|
+
green: '\x1b[32m',
|
|
13
|
+
yellow: '\x1b[33m',
|
|
14
|
+
cyan: '\x1b[36m',
|
|
15
|
+
gray: '\x1b[90m',
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
// Box drawing characters (matching TUI)
|
|
19
|
+
const BOX = {
|
|
20
|
+
topLeft: '╭',
|
|
21
|
+
topRight: '╮',
|
|
22
|
+
bottomLeft: '╰',
|
|
23
|
+
bottomRight: '╯',
|
|
24
|
+
horizontal: '─',
|
|
25
|
+
vertical: '│',
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Extract command string from tool input for display
|
|
30
|
+
* Creates pseudo-commands for non-bash tools (matching TUI behavior)
|
|
31
|
+
* @param {string} tool - Tool name
|
|
32
|
+
* @param {object|string} input - Tool input data
|
|
33
|
+
* @returns {string} Command string for display
|
|
34
|
+
*/
|
|
35
|
+
function extractToolCommand(tool, input) {
|
|
36
|
+
if (!input) return tool;
|
|
37
|
+
|
|
38
|
+
try {
|
|
39
|
+
const inputData = typeof input === 'string' ? JSON.parse(input) : input;
|
|
40
|
+
|
|
41
|
+
// bash tool - use actual command
|
|
42
|
+
if (inputData.command) {
|
|
43
|
+
return inputData.command;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// read tool - show as "read <filepath>"
|
|
47
|
+
if (inputData.filePath && tool === 'read') {
|
|
48
|
+
return `read ${inputData.filePath}`;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// grep tool - show as 'grep "pattern" path'
|
|
52
|
+
if (inputData.pattern && tool === 'grep') {
|
|
53
|
+
const path = inputData.path || inputData.include || '.';
|
|
54
|
+
return `grep "${inputData.pattern}" ${path}`;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// glob tool - show as 'glob "pattern"'
|
|
58
|
+
if (inputData.pattern && tool === 'glob') {
|
|
59
|
+
return `glob "${inputData.pattern}"`;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// edit tool - show as 'edit <filepath>'
|
|
63
|
+
if (inputData.filePath && tool === 'edit') {
|
|
64
|
+
return `edit ${inputData.filePath}`;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// write tool - show as 'write <filepath>'
|
|
68
|
+
if (inputData.filePath && tool === 'write') {
|
|
69
|
+
return `write ${inputData.filePath}`;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// task tool - show as 'task "<description>"'
|
|
73
|
+
if (inputData.description && tool === 'task') {
|
|
74
|
+
return `task "${inputData.description}"`;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// webfetch tool - show as 'fetch <url>'
|
|
78
|
+
if (inputData.url && tool === 'webfetch') {
|
|
79
|
+
return `fetch ${inputData.url}`;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// Default: just return tool name
|
|
83
|
+
return tool;
|
|
84
|
+
} catch (e) {
|
|
85
|
+
return tool;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Format tool output as a shell-style box (matching TUI format)
|
|
91
|
+
* @param {string} toolName - Name of the tool (e.g., 'bash', 'read')
|
|
92
|
+
* @param {string} status - Tool status ('running', 'completed', 'error')
|
|
93
|
+
* @param {object|string} input - Tool input parameters
|
|
94
|
+
* @param {string} output - Tool output/result
|
|
95
|
+
* @param {number} duration - Execution duration in milliseconds
|
|
96
|
+
* @param {object} options - Formatting options
|
|
97
|
+
* @param {boolean} options.verbose - Show input details (not used in box format)
|
|
98
|
+
* @param {boolean} options.noColor - Disable colors
|
|
99
|
+
* @param {number} options.width - Box width (default 60, matching TUI)
|
|
100
|
+
* @returns {string} Formatted shell box string
|
|
101
|
+
*/
|
|
102
|
+
function formatToolOutput(toolName, status, input, output, duration, options = {}) {
|
|
103
|
+
const { noColor = false, width = 60 } = options;
|
|
104
|
+
|
|
105
|
+
// Use colors or empty strings based on noColor option
|
|
106
|
+
const C = noColor ? {
|
|
107
|
+
reset: '', bold: '', dim: '', red: '', green: '', yellow: '', cyan: '', gray: '',
|
|
108
|
+
} : TOOL_COLORS;
|
|
109
|
+
|
|
110
|
+
const b = BOX;
|
|
111
|
+
const boxWidth = width;
|
|
112
|
+
|
|
113
|
+
// Extract command for display
|
|
114
|
+
const command = extractToolCommand(toolName, input);
|
|
115
|
+
|
|
116
|
+
// Status indicator and header color
|
|
117
|
+
let statusIcon = '';
|
|
118
|
+
let headerColor = C.cyan;
|
|
119
|
+
if (status === 'completed') {
|
|
120
|
+
statusIcon = ` ${C.green}✓${C.reset}`;
|
|
121
|
+
headerColor = C.cyan;
|
|
122
|
+
} else if (status === 'error') {
|
|
123
|
+
statusIcon = ` ${C.red}✗${C.reset}`;
|
|
124
|
+
headerColor = C.red;
|
|
125
|
+
} else if (status === 'running') {
|
|
126
|
+
statusIcon = ` ${C.yellow}⟳${C.reset}`;
|
|
127
|
+
headerColor = C.yellow;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// Duration string
|
|
131
|
+
const durationStr = duration !== undefined ? ` ${C.gray}(${duration}ms)${C.reset}` : '';
|
|
132
|
+
|
|
133
|
+
// Build header: ╭─ bash ✓ (17ms) ────────╮
|
|
134
|
+
const headerLabel = ` ${toolName}${statusIcon}${durationStr} `;
|
|
135
|
+
// Calculate actual display length (strip ANSI codes)
|
|
136
|
+
const labelDisplayLen = headerLabel.replace(/\x1b\[[0-9;]*m/g, '').length;
|
|
137
|
+
// Account for: topLeft(1) + leading horizontal(1) + label + trailing fill + topRight(1) = boxWidth
|
|
138
|
+
const headerFill = Math.max(0, boxWidth - labelDisplayLen - 3);
|
|
139
|
+
const topBorder = `${C.gray}${b.topLeft}${b.horizontal}${C.reset}${headerColor}${headerLabel}${C.reset}${C.gray}${b.horizontal.repeat(headerFill)}${b.topRight}${C.reset}`;
|
|
140
|
+
|
|
141
|
+
// Build content lines
|
|
142
|
+
const lines = [];
|
|
143
|
+
|
|
144
|
+
// Command line with $ prompt and optional cursor for running state
|
|
145
|
+
const cursor = status === 'running' ? '█' : '';
|
|
146
|
+
const cmdLine = `${C.green}$${C.reset} ${command}${cursor}`;
|
|
147
|
+
lines.push(cmdLine);
|
|
148
|
+
|
|
149
|
+
// Output lines (show everything)
|
|
150
|
+
if (output) {
|
|
151
|
+
// Stringify object output if needed
|
|
152
|
+
const outputStr = typeof output === 'object' ? JSON.stringify(output, null, 2) : output;
|
|
153
|
+
const outputLines = outputStr.split('\n');
|
|
154
|
+
for (const line of outputLines) {
|
|
155
|
+
// Apply error coloring for error status
|
|
156
|
+
const lineContent = status === 'error' ? `${C.red}${line}${C.reset}` : line;
|
|
157
|
+
lines.push(lineContent);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// Remove trailing empty/whitespace-only lines to avoid extra blank lines at the bottom of the box
|
|
162
|
+
// Strip ANSI escape codes before checking emptiness so colored empty lines (e.g., error output) are caught
|
|
163
|
+
while (lines.length > 0 && lines[lines.length - 1].replace(/\x1b\[[0-9;]*m/g, '').trim() === '') {
|
|
164
|
+
lines.pop();
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// Bottom border - account for: bottomLeft(1) + fill + bottomRight(1) = boxWidth
|
|
168
|
+
const bottomBorder = `${C.gray}${b.bottomLeft}${b.horizontal.repeat(Math.max(0, boxWidth - 2))}${b.bottomRight}${C.reset}`;
|
|
169
|
+
|
|
170
|
+
// Combine all parts, adding a leading and trailing newline around the box
|
|
171
|
+
const result = '\n' + [topBorder, ...lines, bottomBorder].join('\n') + '\n';
|
|
172
|
+
return result;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
module.exports = {
|
|
176
|
+
formatToolOutput,
|
|
177
|
+
extractToolCommand,
|
|
178
|
+
TOOL_COLORS,
|
|
179
|
+
BOX,
|
|
180
|
+
};
|
package/package.json
CHANGED
|
@@ -1,14 +1,36 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cnrai/pave",
|
|
3
|
-
"version": "0.3.
|
|
4
|
-
"description": "
|
|
5
|
-
"main": "
|
|
3
|
+
"version": "0.3.35",
|
|
4
|
+
"description": "Personal AI Virtual Environment - Terminal UI + OpenCode-Lite Server",
|
|
5
|
+
"main": "index.js",
|
|
6
6
|
"bin": {
|
|
7
|
-
"pave": "./
|
|
7
|
+
"pave": "./index.js"
|
|
8
8
|
},
|
|
9
9
|
"scripts": {
|
|
10
|
-
"start": "node
|
|
10
|
+
"start": "node index.js",
|
|
11
|
+
"start:ish": "node --expose-gc index.js",
|
|
12
|
+
"start:debug": "node --expose-gc index.js --debug --verbose",
|
|
13
|
+
"help": "node index.js --help",
|
|
14
|
+
"build": "node build.js",
|
|
15
|
+
"build:install": "node build.js --install",
|
|
16
|
+
"build:npm": "node build-npm.js",
|
|
17
|
+
"build:npm:publish": "node build-npm.js --publish",
|
|
18
|
+
"clean": "rm -rf dist",
|
|
19
|
+
"test": "node test/run-tests.js",
|
|
20
|
+
"test:verbose": "node test/run-tests.js --verbose",
|
|
21
|
+
"test:ish": "node test/ish-fetch.test.js",
|
|
22
|
+
"status": "node status.js"
|
|
11
23
|
},
|
|
24
|
+
"keywords": [
|
|
25
|
+
"ai",
|
|
26
|
+
"terminal",
|
|
27
|
+
"tui",
|
|
28
|
+
"opencode",
|
|
29
|
+
"ish",
|
|
30
|
+
"ios",
|
|
31
|
+
"memory-efficient",
|
|
32
|
+
"resource-constrained"
|
|
33
|
+
],
|
|
12
34
|
"engines": {
|
|
13
35
|
"node": ">=16.0.0"
|
|
14
36
|
},
|
|
@@ -18,34 +40,15 @@
|
|
|
18
40
|
"win32"
|
|
19
41
|
],
|
|
20
42
|
"dependencies": {
|
|
21
|
-
"
|
|
22
|
-
"
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
"pave.js",
|
|
26
|
-
"sandbox/",
|
|
27
|
-
"README.md",
|
|
28
|
-
"LICENSE"
|
|
29
|
-
],
|
|
30
|
-
"keywords": [
|
|
31
|
-
"ai",
|
|
32
|
-
"terminal",
|
|
33
|
-
"tui",
|
|
34
|
-
"agent",
|
|
35
|
-
"cli",
|
|
36
|
-
"ish",
|
|
37
|
-
"ios",
|
|
38
|
-
"node16",
|
|
39
|
-
"memory-efficient"
|
|
40
|
-
],
|
|
41
|
-
"repository": {
|
|
42
|
-
"type": "git",
|
|
43
|
-
"url": "git+https://github.com/cnrai/openpave.git"
|
|
43
|
+
"abort-controller": "^3.0.0",
|
|
44
|
+
"figlet": "^1.10.0",
|
|
45
|
+
"js-yaml": "^4.1.0",
|
|
46
|
+
"ulid": "^2.3.0"
|
|
44
47
|
},
|
|
45
|
-
"
|
|
46
|
-
|
|
47
|
-
"
|
|
48
|
+
"devDependencies": {
|
|
49
|
+
"esbuild": "^0.27.3",
|
|
50
|
+
"javascript-obfuscator": "^5.3.0"
|
|
48
51
|
},
|
|
49
|
-
"author": "
|
|
52
|
+
"author": "PAVE Team",
|
|
50
53
|
"license": "MIT"
|
|
51
54
|
}
|
package/start-pave.sh
ADDED
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# PAVE Startup Script
|
|
3
|
+
# Automatically detects environment and applies optimal settings
|
|
4
|
+
|
|
5
|
+
set -e
|
|
6
|
+
|
|
7
|
+
# Get script directory
|
|
8
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
9
|
+
PAVE_DIR="$SCRIPT_DIR"
|
|
10
|
+
|
|
11
|
+
# Default options
|
|
12
|
+
NODE_ARGS="--expose-gc"
|
|
13
|
+
PAVE_ARGS=""
|
|
14
|
+
|
|
15
|
+
# Parse arguments
|
|
16
|
+
HELP_REQUESTED=false
|
|
17
|
+
ISH_MODE=""
|
|
18
|
+
MEMORY_LIMIT=""
|
|
19
|
+
DEBUG_MODE=false
|
|
20
|
+
|
|
21
|
+
while [[ $# -gt 0 ]]; do
|
|
22
|
+
case $1 in
|
|
23
|
+
--help|-h)
|
|
24
|
+
HELP_REQUESTED=true
|
|
25
|
+
shift
|
|
26
|
+
;;
|
|
27
|
+
--ish-mode)
|
|
28
|
+
ISH_MODE="--ish-mode"
|
|
29
|
+
if [[ $2 =~ ^(true|false|on|off|1|0)$ ]]; then
|
|
30
|
+
ISH_MODE="--ish-mode $2"
|
|
31
|
+
shift
|
|
32
|
+
fi
|
|
33
|
+
shift
|
|
34
|
+
;;
|
|
35
|
+
--memory-limit)
|
|
36
|
+
if [[ $2 =~ ^[0-9]+$ ]]; then
|
|
37
|
+
MEMORY_LIMIT="--memory-limit $2"
|
|
38
|
+
shift
|
|
39
|
+
fi
|
|
40
|
+
shift
|
|
41
|
+
;;
|
|
42
|
+
--debug)
|
|
43
|
+
DEBUG_MODE=true
|
|
44
|
+
PAVE_ARGS="$PAVE_ARGS --debug"
|
|
45
|
+
shift
|
|
46
|
+
;;
|
|
47
|
+
--verbose)
|
|
48
|
+
PAVE_ARGS="$PAVE_ARGS --verbose"
|
|
49
|
+
shift
|
|
50
|
+
;;
|
|
51
|
+
--no-gc)
|
|
52
|
+
NODE_ARGS=""
|
|
53
|
+
shift
|
|
54
|
+
;;
|
|
55
|
+
*)
|
|
56
|
+
# Pass through other arguments to PAVE
|
|
57
|
+
PAVE_ARGS="$PAVE_ARGS $1"
|
|
58
|
+
shift
|
|
59
|
+
;;
|
|
60
|
+
esac
|
|
61
|
+
done
|
|
62
|
+
|
|
63
|
+
# Show help if requested
|
|
64
|
+
if [ "$HELP_REQUESTED" = true ]; then
|
|
65
|
+
cat << EOF
|
|
66
|
+
PAVE Startup Script
|
|
67
|
+
|
|
68
|
+
USAGE:
|
|
69
|
+
$0 [options] [pave-options]
|
|
70
|
+
|
|
71
|
+
STARTUP OPTIONS:
|
|
72
|
+
--help, -h Show this help
|
|
73
|
+
--ish-mode [on|off] Force ISH mode on/off (auto-detected by default)
|
|
74
|
+
--memory-limit <MB> Set memory limit in MB
|
|
75
|
+
--debug Enable debug mode
|
|
76
|
+
--verbose Enable verbose output
|
|
77
|
+
--no-gc Disable --expose-gc Node.js flag
|
|
78
|
+
|
|
79
|
+
EXAMPLES:
|
|
80
|
+
$0 # Standard startup with auto-detection
|
|
81
|
+
$0 --ish-mode # Force ISH mode
|
|
82
|
+
$0 --memory-limit 32 # Custom memory limit
|
|
83
|
+
$0 --debug --verbose # Debug mode with verbose output
|
|
84
|
+
|
|
85
|
+
All other arguments are passed to PAVE directly.
|
|
86
|
+
For full PAVE options, run: $0 -- --help
|
|
87
|
+
|
|
88
|
+
ENVIRONMENT DETECTION:
|
|
89
|
+
- ISH mode is auto-detected based on platform and environment
|
|
90
|
+
- Garbage collection is enabled by default for memory protection
|
|
91
|
+
- Memory limits are automatically set based on detected environment
|
|
92
|
+
|
|
93
|
+
EOF
|
|
94
|
+
exit 0
|
|
95
|
+
fi
|
|
96
|
+
|
|
97
|
+
# Build final command arguments
|
|
98
|
+
FINAL_PAVE_ARGS="$ISH_MODE $MEMORY_LIMIT $PAVE_ARGS"
|
|
99
|
+
|
|
100
|
+
# Environment detection
|
|
101
|
+
detect_environment() {
|
|
102
|
+
local is_ish=false
|
|
103
|
+
|
|
104
|
+
# Check for iSH indicators
|
|
105
|
+
if [[ "$OSTYPE" == "linux"* ]]; then
|
|
106
|
+
if [[ "$TERM_PROGRAM" == "iSH" ]] || [[ -f "/etc/alpine-release" ]] || [[ "$(uname -a)" == *"alpine"* ]]; then
|
|
107
|
+
is_ish=true
|
|
108
|
+
fi
|
|
109
|
+
fi
|
|
110
|
+
|
|
111
|
+
echo $is_ish
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
IS_ISH=$(detect_environment)
|
|
115
|
+
|
|
116
|
+
# Print startup banner
|
|
117
|
+
echo "=============================================="
|
|
118
|
+
echo "PAVE Startup Script"
|
|
119
|
+
echo "=============================================="
|
|
120
|
+
echo "Environment: $(if [ "$IS_ISH" = true ]; then echo "iSH (iOS)"; else echo "Standard"; fi)"
|
|
121
|
+
echo "Node args: $NODE_ARGS"
|
|
122
|
+
echo "PAVE args: $FINAL_PAVE_ARGS"
|
|
123
|
+
echo "Working directory: $PAVE_DIR"
|
|
124
|
+
|
|
125
|
+
# ISH-specific recommendations
|
|
126
|
+
if [ "$IS_ISH" = true ]; then
|
|
127
|
+
echo ""
|
|
128
|
+
echo "ISH DETECTED:"
|
|
129
|
+
echo " - Memory protection enabled"
|
|
130
|
+
echo " - Garbage collection enabled"
|
|
131
|
+
echo " - Conservative memory limits applied"
|
|
132
|
+
|
|
133
|
+
if [ "$DEBUG_MODE" = true ]; then
|
|
134
|
+
echo " - Debug logging enabled (logs to ~/.pave/pave.log)"
|
|
135
|
+
fi
|
|
136
|
+
fi
|
|
137
|
+
|
|
138
|
+
echo "=============================================="
|
|
139
|
+
echo ""
|
|
140
|
+
|
|
141
|
+
# Change to PAVE directory
|
|
142
|
+
cd "$PAVE_DIR"
|
|
143
|
+
|
|
144
|
+
# Execute PAVE with appropriate arguments
|
|
145
|
+
if [ -n "$NODE_ARGS" ]; then
|
|
146
|
+
exec node $NODE_ARGS index.js $FINAL_PAVE_ARGS
|
|
147
|
+
else
|
|
148
|
+
exec node index.js $FINAL_PAVE_ARGS
|
|
149
|
+
fi
|