autodev-cli 1.4.0

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/README.md ADDED
@@ -0,0 +1,174 @@
1
+ # autodev-cli
2
+
3
+ AutoAIDev's CLI — autonomous AI task loop with an optional one-shot launcher for **VS Code** and **Cursor**, plus a wire-protocol for connecting a workspace to a pixel-office server.
4
+
5
+ ```bash
6
+ # Install globally
7
+ npm install -g autodev-cli
8
+
9
+ # Init the current folder + open it in VS Code (or Cursor)
10
+ autodev --ide=vscode .
11
+ autodev --ide=cursor .
12
+
13
+ # Connect to a pixel-office agent in one shot (signed URL from the UI)
14
+ autodev --setup-url='https://pixel-office.tools.ooyes.net/api/cli/setup/<id>?expires=…&signature=…' .
15
+
16
+ # Or paste the WS URL directly
17
+ autodev --connect='wss://pixel-office.tools.ooyes.net/ws?token=<api_key>&endpoint=<slug>' .
18
+
19
+ # Combine the two: init + open IDE + bind credentials
20
+ autodev --setup-url='…' --ide=vscode .
21
+ ```
22
+
23
+ That single command:
24
+
25
+ 1. Creates `TODO.md` and `.autodev/settings.json`
26
+ 2. Adds `.autodev/` to `.gitignore`
27
+ 3. Installs the **AutoAIDev** extension into the chosen IDE (skipped if already installed)
28
+ 4. Opens the folder in the IDE
29
+ 5. (with `--setup-url` / `--connect`) writes the pixel-office credentials into `.autodev/settings.json`
30
+
31
+ ---
32
+
33
+ ## Install (from this repo)
34
+
35
+ ```bash
36
+ cd autodev-cli
37
+ npm install
38
+ npm run build
39
+ npm link # optional — adds `autodev` to your PATH
40
+ ```
41
+
42
+ > Requires the sibling `autodev-vscode-extension` to be compiled first:
43
+ > ```bash
44
+ > cd ../autodev-vscode-extension
45
+ > npm install
46
+ > npm run compile
47
+ > ```
48
+
49
+ ---
50
+
51
+ ## Commands
52
+
53
+ ### `autodev --ide=<ide> [path]` — top-level shortcut
54
+ Same as `autodev up --ide=<ide>`. Inits the workspace and launches the IDE.
55
+
56
+ ### `autodev up --ide=<ide> [path]`
57
+ Init + launch in one step. Auto-installs the extension if missing.
58
+
59
+ ```bash
60
+ autodev up --ide=vscode .
61
+ autodev up --ide=cursor ~/myproject -p copilot-cli
62
+ autodev up --ide=vscode . --no-extension # skip extension install
63
+ ```
64
+
65
+ ### `autodev launch --ide=<ide> [path]`
66
+ Open an existing workspace in an IDE. No init.
67
+
68
+ ### `autodev connect --setup-url=<url> [path]` / `autodev connect --url=<wsurl> [path]`
69
+ Bind the workspace to a pixel-office agent.
70
+
71
+ ```bash
72
+ # Signed URL from the pixel-office UI (preferred)
73
+ autodev connect --setup-url='https://pixel-office.tools.ooyes.net/api/cli/setup/<id>?expires=…&signature=…' .
74
+
75
+ # Or paste a full WS URL
76
+ autodev connect --url='wss://host/ws?token=<api_key>&endpoint=<slug>' .
77
+ ```
78
+
79
+ Either form writes `wsUrl`, `serverApiKey`, `webhookSlug`, and `serverBaseUrl` into `.autodev/settings.json`. The signed URL is HMAC-protected and expires in 30 minutes.
80
+
81
+ ### `autodev init [path]`
82
+ Scaffold a workspace — `TODO.md` and `.vscode/autodev.json`.
83
+ Pass `--ide=vscode|cursor` to also open it after init.
84
+
85
+ ```bash
86
+ autodev init # current directory
87
+ autodev init ~/myproject # specific path
88
+ autodev init . --ide=vscode # also open in VS Code
89
+ autodev init . --ide=cursor --no-extension # don't auto-install extension
90
+ autodev init . --provider claude-cli # pick the default provider
91
+ ```
92
+
93
+ ### `autodev start [path]`
94
+ Start the autonomous loop — reads `TODO.md` and drives the AI until all tasks are done.
95
+
96
+ ```bash
97
+ autodev start # current directory, claude-cli
98
+ autodev start ~/myproject -p copilot-cli
99
+ autodev start . --provider opencode-cli
100
+ ```
101
+
102
+ Press **Ctrl+C** to stop gracefully.
103
+
104
+ ### `autodev status [path]`
105
+ Summary of tasks in `TODO.md`.
106
+
107
+ ```bash
108
+ autodev status
109
+ autodev status ~/myproject --all # also list completed tasks
110
+ ```
111
+
112
+ ### `autodev config [path]`
113
+ Read or update `.vscode/autodev.json`.
114
+
115
+ ```bash
116
+ autodev config # print all settings
117
+ autodev config get provider # get one value
118
+ autodev config set provider copilot-cli # set provider
119
+ autodev config set taskTimeoutMinutes 60
120
+ autodev config set discordToken TOKEN
121
+ ```
122
+
123
+ ---
124
+
125
+ ## IDE launcher details
126
+
127
+ | `--ide` value | Resolves to | Extension installed |
128
+ |---------------|-------------|---------------------|
129
+ | `vscode` | `code` (or `code-insiders`) on PATH | `AutoAIDev.autoaidev` |
130
+ | `cursor` | `cursor` on PATH | `AutoAIDev.autoaidev` |
131
+
132
+ The launcher first looks for a sibling `autoaidev.vsix` next to the CLI install (handy for offline / dev installs). If it can't find one it falls back to the marketplace id `AutoAIDev.autoaidev`.
133
+
134
+ Pass `--no-extension` to skip the extension install. Pass `--no-launch` (only on `init`) to install the extension without opening the IDE.
135
+
136
+ ---
137
+
138
+ ## Configuration
139
+
140
+ Settings live in `.autodev/settings.json` inside the workspace. The legacy path `.vscode/autodev.json` is still read for back-compat — the next write migrates it to the new location automatically. Highlights:
141
+
142
+ | Key | Default | Description |
143
+ |-----|---------|-------------|
144
+ | `provider` | `claude-cli` | AI provider to use |
145
+ | `loopInterval` | `30` | Seconds between polling cycles |
146
+ | `taskTimeoutMinutes` | `30` | Minutes of TODO.md inactivity before timeout |
147
+ | `taskCheckInMinutes` | `20` | Minutes of JSONL inactivity before reminder |
148
+ | `discordToken` | `""` | Discord bot token for notifications |
149
+ | `discordChannelId` | `""` | Discord channel for notifications |
150
+ | `serverBaseUrl` | `""` | A2A webhook server URL |
151
+ | `serverApiKey` | `""` | A2A webhook API key |
152
+ | `gitEnabled` | `false` | Enable git commit after each task |
153
+
154
+ ---
155
+
156
+ ## How the loop works
157
+
158
+ 1. Reads `TODO.md` from the workspace root
159
+ 2. Picks the first `[ ]` task, sends a prompt to the chosen AI CLI provider
160
+ 3. Watches `TODO.md` for the AI to mark the task `[x]` done
161
+ 4. Loops until all tasks are complete
162
+ 5. Sends Discord / webhook notifications at each step
163
+
164
+ The loop never stops while `[ ]` or `[~]` tasks remain.
165
+
166
+ ---
167
+
168
+ ## Providers
169
+
170
+ | Provider | CLI command |
171
+ |----------|-------------|
172
+ | `claude-cli` | `claude` (Anthropic Claude CLI) |
173
+ | `copilot-cli` | `gh copilot` (GitHub Copilot CLI) |
174
+ | `opencode-cli` | `opencode` (OpenCode CLI) |
@@ -0,0 +1,83 @@
1
+ #!/usr/bin/env node
2
+ // Quick WS-handshake verifier. Reads wsUrl from <cwd>/.autodev/settings.json
3
+ // (or .vscode/autodev.json), opens a WebSocket connection, waits for the
4
+ // server's first frame (or a 2s grace period), then exits 0 on success.
5
+
6
+ const fs = require('fs');
7
+ const path = require('path');
8
+ const http = require('http');
9
+ const https = require('https');
10
+ const crypto = require('crypto');
11
+
12
+ const cwd = process.argv[2] ? path.resolve(process.argv[2]) : process.cwd();
13
+ const candidates = [
14
+ path.join(cwd, '.autodev', 'settings.json'),
15
+ path.join(cwd, '.vscode', 'autodev.json'),
16
+ ];
17
+ const file = candidates.find(p => fs.existsSync(p));
18
+ if (!file) { console.error('No settings file found in', cwd); process.exit(1); }
19
+ const settings = JSON.parse(fs.readFileSync(file, 'utf8'));
20
+ const wsUrl = settings.wsUrl;
21
+ if (!wsUrl) { console.error('settings.wsUrl is empty'); process.exit(1); }
22
+
23
+ const u = new URL(wsUrl);
24
+ const isTls = u.protocol === 'wss:';
25
+ const lib = isTls ? https : http;
26
+ const port = u.port ? Number(u.port) : (isTls ? 443 : 80);
27
+ const key = crypto.randomBytes(16).toString('base64');
28
+
29
+ console.log(`Connecting to ${wsUrl}…`);
30
+ const req = lib.request({
31
+ host: u.hostname,
32
+ port,
33
+ path: u.pathname + u.search,
34
+ method: 'GET',
35
+ headers: {
36
+ 'Connection': 'Upgrade',
37
+ 'Upgrade': 'websocket',
38
+ 'Sec-WebSocket-Version': '13',
39
+ 'Sec-WebSocket-Key': key,
40
+ 'Origin': `${u.protocol}//${u.hostname}`,
41
+ 'User-Agent': 'autodev-ping',
42
+ },
43
+ });
44
+
45
+ req.on('upgrade', (res, socket) => {
46
+ console.log('Handshake OK — status', res.statusCode);
47
+ let closed = false;
48
+ socket.on('data', (buf) => {
49
+ if (closed) return;
50
+ closed = true;
51
+ console.log('First frame:', buf.length, 'bytes — server is talking.');
52
+ try { socket.destroy(); } catch {}
53
+ setTimeout(() => process.exit(0), 50);
54
+ });
55
+ setTimeout(() => {
56
+ if (closed) return;
57
+ console.log('No frame in 2.5s, but handshake succeeded — connection is alive.');
58
+ try { socket.destroy(); } catch {}
59
+ process.exit(0);
60
+ }, 2500);
61
+ });
62
+
63
+ req.on('response', (res) => {
64
+ let body = '';
65
+ res.on('data', c => body += c);
66
+ res.on('end', () => {
67
+ console.error(`Server returned HTTP ${res.statusCode} (no upgrade): ${body.slice(0, 300)}`);
68
+ process.exit(2);
69
+ });
70
+ });
71
+
72
+ req.on('error', (err) => {
73
+ console.error('Connection error:', err.message);
74
+ process.exit(2);
75
+ });
76
+
77
+ req.setTimeout(10_000, () => {
78
+ console.error('Timed out waiting for handshake');
79
+ req.destroy();
80
+ process.exit(2);
81
+ });
82
+
83
+ req.end();
@@ -0,0 +1,138 @@
1
+ #!/usr/bin/env node
2
+ // Long-lived WS watcher — opens the agent's WebSocket and prints all text
3
+ // frames received. Use this to verify task delivery end-to-end.
4
+ //
5
+ // Usage: node autodev-watch.js [workspaceDir] [seconds]
6
+ // default workspaceDir = cwd
7
+ // default seconds = 30
8
+ //
9
+ // Reads wsUrl from <workspaceDir>/.autodev/settings.json (or .vscode/autodev.json).
10
+
11
+ const fs = require('fs');
12
+ const path = require('path');
13
+ const http = require('http');
14
+ const https = require('https');
15
+ const crypto = require('crypto');
16
+
17
+ const cwd = process.argv[2] ? path.resolve(process.argv[2]) : process.cwd();
18
+ const watchSeconds = process.argv[3] ? Number(process.argv[3]) : 30;
19
+
20
+ const candidates = [
21
+ path.join(cwd, '.autodev', 'settings.json'),
22
+ path.join(cwd, '.vscode', 'autodev.json'),
23
+ ];
24
+ const file = candidates.find(p => fs.existsSync(p));
25
+ if (!file) { console.error('No settings file found in', cwd); process.exit(1); }
26
+ const settings = JSON.parse(fs.readFileSync(file, 'utf8'));
27
+ const wsUrl = settings.wsUrl;
28
+ if (!wsUrl) { console.error('settings.wsUrl is empty'); process.exit(1); }
29
+
30
+ const u = new URL(wsUrl);
31
+ const isTls = u.protocol === 'wss:';
32
+ const lib = isTls ? https : http;
33
+ const port = u.port ? Number(u.port) : (isTls ? 443 : 80);
34
+ const key = crypto.randomBytes(16).toString('base64');
35
+
36
+ console.log(`[watch] Connecting to ${wsUrl}`);
37
+ console.log(`[watch] Watching for ${watchSeconds}s, then exiting.`);
38
+
39
+ const req = lib.request({
40
+ host: u.hostname,
41
+ port,
42
+ path: u.pathname + u.search,
43
+ method: 'GET',
44
+ headers: {
45
+ 'Connection': 'Upgrade',
46
+ 'Upgrade': 'websocket',
47
+ 'Sec-WebSocket-Version': '13',
48
+ 'Sec-WebSocket-Key': key,
49
+ 'Origin': `${u.protocol}//${u.hostname}`,
50
+ 'User-Agent': 'autodev-watch',
51
+ },
52
+ });
53
+
54
+ req.on('upgrade', (res, socket) => {
55
+ console.log(`[watch] Handshake OK — status ${res.statusCode}`);
56
+
57
+ // Minimal RFC 6455 frame parser. Server-to-client frames are unmasked.
58
+ let buf = Buffer.alloc(0);
59
+
60
+ socket.on('data', (chunk) => {
61
+ buf = Buffer.concat([buf, chunk]);
62
+ while (buf.length >= 2) {
63
+ const fin = (buf[0] & 0x80) !== 0;
64
+ const opcode = buf[0] & 0x0f;
65
+ const masked = (buf[1] & 0x80) !== 0;
66
+ let len = buf[1] & 0x7f;
67
+ let off = 2;
68
+
69
+ if (len === 126) {
70
+ if (buf.length < 4) break;
71
+ len = buf.readUInt16BE(2); off = 4;
72
+ } else if (len === 127) {
73
+ if (buf.length < 10) break;
74
+ len = Number(buf.readBigUInt64BE(2)); off = 10;
75
+ }
76
+
77
+ let mask = null;
78
+ if (masked) { if (buf.length < off + 4) break; mask = buf.slice(off, off + 4); off += 4; }
79
+ if (buf.length < off + len) break;
80
+
81
+ let payload = buf.slice(off, off + len);
82
+ if (mask) {
83
+ const out = Buffer.alloc(payload.length);
84
+ for (let i = 0; i < payload.length; i++) out[i] = payload[i] ^ mask[i % 4];
85
+ payload = out;
86
+ }
87
+ buf = buf.slice(off + len);
88
+
89
+ if (opcode === 0x1) { // text frame
90
+ const text = payload.toString('utf8');
91
+ const ts = new Date().toISOString().slice(11, 19);
92
+ console.log(`[${ts}] ← ${truncate(text, 800)}`);
93
+ } else if (opcode === 0x9) { // ping → pong
94
+ const pong = makeMaskedFrame(0xa, payload);
95
+ socket.write(pong);
96
+ } else if (opcode === 0x8) { // close
97
+ console.log(`[watch] Server closed the connection.`);
98
+ socket.end();
99
+ process.exit(0);
100
+ }
101
+ if (!fin) break; // continuation handling intentionally minimal
102
+ }
103
+ });
104
+
105
+ socket.on('error', (e) => { console.error('[watch] socket error:', e.message); process.exit(1); });
106
+ socket.on('close', () => { console.log('[watch] socket closed'); process.exit(0); });
107
+
108
+ setTimeout(() => {
109
+ console.log(`[watch] ${watchSeconds}s elapsed — exiting.`);
110
+ try { socket.end(); } catch {}
111
+ setTimeout(() => process.exit(0), 100);
112
+ }, watchSeconds * 1000);
113
+ });
114
+
115
+ req.on('response', (res) => {
116
+ let body = '';
117
+ res.on('data', c => body += c);
118
+ res.on('end', () => {
119
+ console.error(`[watch] Server returned HTTP ${res.statusCode}: ${body.slice(0, 300)}`);
120
+ process.exit(2);
121
+ });
122
+ });
123
+ req.on('error', (err) => { console.error('[watch] Connection error:', err.message); process.exit(2); });
124
+ req.end();
125
+
126
+ function makeMaskedFrame(opcode, payload) {
127
+ const mask = crypto.randomBytes(4);
128
+ const len = payload.length;
129
+ let header;
130
+ if (len < 126) header = Buffer.from([0x80 | opcode, 0x80 | len]);
131
+ else if (len < 65536) { header = Buffer.alloc(4); header[0] = 0x80 | opcode; header[1] = 0x80 | 126; header.writeUInt16BE(len, 2); }
132
+ else { header = Buffer.alloc(10); header[0] = 0x80 | opcode; header[1] = 0x80 | 127; header.writeBigUInt64BE(BigInt(len), 2); }
133
+ const masked = Buffer.alloc(payload.length);
134
+ for (let i = 0; i < payload.length; i++) masked[i] = payload[i] ^ mask[i % 4];
135
+ return Buffer.concat([header, mask, masked]);
136
+ }
137
+
138
+ function truncate(s, n) { return s.length > n ? s.slice(0, n) + ` … (+${s.length - n} bytes)` : s; }
package/bin/autodev.js ADDED
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env node
2
+ const fs = require('fs');
3
+ const path = require('path');
4
+
5
+ const compiled = path.join(__dirname, '..', 'out', 'cli.js');
6
+ if (!fs.existsSync(compiled)) {
7
+ console.error('autodev-cli: missing compiled output.');
8
+ console.error('Run `npm run build` inside the autodev-cli directory and try again.');
9
+ process.exit(1);
10
+ }
11
+ require(compiled);
package/out/cli.js ADDED
@@ -0,0 +1,119 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ const path = __importStar(require("path"));
37
+ const commander_1 = require("commander");
38
+ const start_1 = require("./commands/start");
39
+ const init_1 = require("./commands/init");
40
+ const config_1 = require("./commands/config");
41
+ const status_1 = require("./commands/status");
42
+ const up_1 = require("./commands/up");
43
+ const connect_1 = require("./commands/connect");
44
+ const tailOutput_1 = require("./commands/tailOutput");
45
+ const connect_2 = require("./connect");
46
+ const logger_1 = require("./logger");
47
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
48
+ const { version } = require('../package.json');
49
+ const program = new commander_1.Command()
50
+ .name('autodev')
51
+ .description('AutoAIDev — autonomous AI task loop with optional IDE launcher and pixel-office connect')
52
+ .version(version)
53
+ // Without this, the program-level --ide / --setup-url / --connect options
54
+ // greedily eat the same option names from subcommands. With it, anything
55
+ // after a subcommand name is parsed against that subcommand only.
56
+ .enablePositionalOptions()
57
+ // Top-level shortcuts. Any combination is valid:
58
+ // autodev --ide=vscode .
59
+ // autodev --setup-url=https://… .
60
+ // autodev --setup-url=https://… --ide=cursor .
61
+ // autodev --connect=wss://host?token=…&endpoint=… .
62
+ .option('--ide <ide>', 'Init and launch the workspace in an IDE (vscode | cursor)')
63
+ .option('-p, --provider <provider>', 'Default AI provider', 'claude-cli')
64
+ .option('--force', 'Overwrite existing files (with --ide)')
65
+ .option('--no-extension', 'Skip auto-installing the autoaidev extension (with --ide)')
66
+ .option('--connect <wsurl>', 'Bind the workspace to a ws:// / wss:// URL with ?token=&endpoint=')
67
+ .option('--setup-url <url>', 'Bind the workspace using a signed pixel-office setup URL')
68
+ .option('--git', 'Enable git auto-commit')
69
+ .option('--file-browser', 'Enable file browser tab')
70
+ .option('--profile <path>', 'Use this AUTODEV.md profile')
71
+ .argument('[path]', 'Workspace path (default: cwd)')
72
+ .action(async (maybePath, opts) => {
73
+ const cwd = maybePath ? path.resolve(maybePath) : process.cwd();
74
+ const didSomething = !!(opts.ide || opts.connect || opts.setupUrl);
75
+ if (!didSomething) {
76
+ program.help();
77
+ return;
78
+ }
79
+ // Order matters: bind credentials FIRST so when the extension activates
80
+ // on IDE launch, it reads the up-to-date wsUrl + autoStartLoop flag and
81
+ // can auto-connect immediately. Otherwise the extension activates with
82
+ // stale settings and the user has to reload the window.
83
+ try {
84
+ if (opts.setupUrl) {
85
+ await (0, connect_2.applySetupUrl)(cwd, opts.setupUrl);
86
+ }
87
+ else if (opts.connect) {
88
+ (0, connect_2.applyWsUrl)(cwd, opts.connect);
89
+ }
90
+ }
91
+ catch (err) {
92
+ logger_1.log.error(err.message);
93
+ process.exit(1);
94
+ }
95
+ if (opts.ide || opts.git || opts.fileBrowser || opts.profile) {
96
+ (0, init_1.runInit)(maybePath, {
97
+ ide: opts.ide,
98
+ provider: opts.provider,
99
+ force: opts.force,
100
+ extension: opts.extension,
101
+ git: opts.git,
102
+ fileBrowser: opts.fileBrowser,
103
+ profile: opts.profile,
104
+ });
105
+ }
106
+ });
107
+ (0, start_1.startCommand)(program);
108
+ (0, init_1.initCommand)(program);
109
+ (0, up_1.upCommand)(program);
110
+ (0, up_1.launchCommand)(program);
111
+ (0, connect_1.connectCommand)(program);
112
+ (0, tailOutput_1.tailOutputCommand)(program);
113
+ (0, config_1.configCommand)(program);
114
+ (0, status_1.statusCommand)(program);
115
+ program.parseAsync(process.argv).catch((err) => {
116
+ console.error(err.message);
117
+ process.exit(1);
118
+ });
119
+ //# sourceMappingURL=cli.js.map
package/out/cli.js.map ADDED
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,124 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.configCommand = configCommand;
37
+ const fs = __importStar(require("fs"));
38
+ const path = __importStar(require("path"));
39
+ const logger_1 = require("../logger");
40
+ const settings_1 = require("autoaidev/settings");
41
+ function configPath(cwd) {
42
+ // Read path: prefer the canonical .autodev/settings.json, fall back to the
43
+ // legacy .vscode/autodev.json if the new file is absent.
44
+ const canonical = path.join(cwd, '.autodev', 'settings.json');
45
+ if (fs.existsSync(canonical)) {
46
+ return canonical;
47
+ }
48
+ const legacy = path.join(cwd, '.vscode', 'autodev.json');
49
+ if (fs.existsSync(legacy)) {
50
+ return legacy;
51
+ }
52
+ return canonical;
53
+ }
54
+ function configWritePath(cwd) {
55
+ return path.join(cwd, '.autodev', 'settings.json');
56
+ }
57
+ function saveSettings(cwd, settings) {
58
+ const file = configWritePath(cwd);
59
+ const dir = path.dirname(file);
60
+ if (!fs.existsSync(dir)) {
61
+ fs.mkdirSync(dir, { recursive: true });
62
+ }
63
+ fs.writeFileSync(file, JSON.stringify(settings, null, 2) + '\n', 'utf8');
64
+ }
65
+ function configCommand(program) {
66
+ const cmd = program
67
+ .command('config')
68
+ .description('Read or write workspace configuration (.autodev/settings.json)')
69
+ .argument('[path]', 'Workspace directory (default: cwd)');
70
+ // autodev config [path] — print all settings
71
+ cmd.action((workspacePath) => {
72
+ const cwd = workspacePath ? path.resolve(workspacePath) : process.cwd();
73
+ const settings = (0, settings_1.loadSettingsForRoot)(cwd);
74
+ logger_1.log.section('⚙ AutoDev Config');
75
+ logger_1.log.info(`File: ${configPath(cwd)}`);
76
+ logger_1.log.plain('');
77
+ for (const [k, v] of Object.entries(settings)) {
78
+ const masked = typeof v === 'string' && (k.toLowerCase().includes('token') || k.toLowerCase().includes('password') || k.toLowerCase().includes('apikey'))
79
+ ? (v ? '***' : '')
80
+ : String(v);
81
+ logger_1.log.plain(` ${k.padEnd(28)} ${masked}`);
82
+ }
83
+ });
84
+ // autodev config set <key> <value> [path]
85
+ cmd
86
+ .command('set <key> <value> [path]')
87
+ .description('Set a config value')
88
+ .action((key, value, workspacePath) => {
89
+ const cwd = workspacePath ? path.resolve(workspacePath) : process.cwd();
90
+ const settings = (0, settings_1.loadSettingsForRoot)(cwd);
91
+ if (!(key in settings_1.SETTINGS_DEFAULTS)) {
92
+ logger_1.log.error(`Unknown key "${key}". Valid keys: ${Object.keys(settings_1.SETTINGS_DEFAULTS).join(', ')}`);
93
+ process.exit(1);
94
+ }
95
+ const defaultVal = settings_1.SETTINGS_DEFAULTS[key];
96
+ let parsed;
97
+ if (typeof defaultVal === 'number') {
98
+ parsed = Number(value);
99
+ }
100
+ else if (typeof defaultVal === 'boolean') {
101
+ parsed = value === 'true' || value === '1';
102
+ }
103
+ else {
104
+ parsed = value;
105
+ }
106
+ settings[key] = parsed;
107
+ saveSettings(cwd, settings);
108
+ logger_1.log.success(`Set ${key} = ${value}`);
109
+ });
110
+ // autodev config get <key> [path]
111
+ cmd
112
+ .command('get <key> [path]')
113
+ .description('Get a config value')
114
+ .action((key, workspacePath) => {
115
+ const cwd = workspacePath ? path.resolve(workspacePath) : process.cwd();
116
+ const settings = (0, settings_1.loadSettingsForRoot)(cwd);
117
+ if (!(key in settings)) {
118
+ logger_1.log.error(`Unknown key "${key}"`);
119
+ process.exit(1);
120
+ }
121
+ console.log(String(settings[key]));
122
+ });
123
+ }
124
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/commands/config.ts"],"names":[],"mappings":"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"}