commandmate 0.1.12 → 0.2.1
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/.env.example +4 -9
- package/.next/BUILD_ID +1 -1
- package/.next/app-build-manifest.json +24 -24
- package/.next/app-path-routes-manifest.json +1 -1
- package/.next/build-manifest.json +7 -7
- package/.next/cache/.tsbuildinfo +1 -1
- package/.next/cache/config.json +3 -3
- package/.next/cache/webpack/client-production/0.pack +0 -0
- package/.next/cache/webpack/client-production/1.pack +0 -0
- package/.next/cache/webpack/client-production/2.pack +0 -0
- package/.next/cache/webpack/client-production/index.pack +0 -0
- package/.next/cache/webpack/client-production/index.pack.old +0 -0
- package/.next/cache/webpack/edge-server-production/0.pack +0 -0
- package/.next/cache/webpack/edge-server-production/index.pack +0 -0
- package/.next/cache/webpack/server-production/0.pack +0 -0
- package/.next/cache/webpack/server-production/index.pack +0 -0
- package/.next/next-server.js.nft.json +1 -1
- package/.next/prerender-manifest.json +1 -1
- package/.next/react-loadable-manifest.json +7 -7
- package/.next/required-server-files.json +1 -1
- package/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/.next/server/app/_not-found.html +1 -1
- package/.next/server/app/_not-found.rsc +2 -2
- package/.next/server/app/api/hooks/claude-done/route.js +1 -19
- package/.next/server/app/api/hooks/claude-done/route.js.nft.json +1 -1
- package/.next/server/app/api/repositories/clone/[jobId]/route.js +1 -1
- package/.next/server/app/api/repositories/clone/[jobId]/route.js.nft.json +1 -1
- package/.next/server/app/api/repositories/clone/route.js +1 -1
- package/.next/server/app/api/repositories/clone/route.js.nft.json +1 -1
- package/.next/server/app/api/repositories/excluded/route.js +36 -0
- package/.next/server/app/api/repositories/excluded/route.js.nft.json +1 -0
- package/.next/server/app/api/repositories/excluded.body +1 -0
- package/.next/server/app/api/repositories/excluded.meta +1 -0
- package/.next/server/app/api/repositories/restore/route.js +36 -0
- package/.next/server/app/api/repositories/restore/route.js.nft.json +1 -0
- package/.next/server/app/api/repositories/route.js +36 -1
- package/.next/server/app/api/repositories/route.js.nft.json +1 -1
- package/.next/server/app/api/repositories/scan/route.js +1 -1
- package/.next/server/app/api/repositories/sync/route.js +36 -1
- package/.next/server/app/api/slash-commands/route.js +1 -1
- package/.next/server/app/api/slash-commands.body +1 -1
- package/.next/server/app/api/worktrees/[id]/auto-yes/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/auto-yes/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/capture/route.js +2 -2
- package/.next/server/app/api/worktrees/[id]/current-output/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/current-output/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/interrupt/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/interrupt/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/kill-session/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/kill-session/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/logs/[filename]/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/logs/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/prompt-response/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/prompt-response/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/respond/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/respond/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/search/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/send/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/send/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/slash-commands/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/start-polling/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/start-polling/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/terminal/route.js +1 -1
- package/.next/server/app/api/worktrees/route.js +1 -1
- package/.next/server/app/api/worktrees/route.js.nft.json +1 -1
- package/.next/server/app/index.html +2 -2
- package/.next/server/app/index.rsc +3 -3
- package/.next/server/app/page.js +7 -7
- package/.next/server/app/page.js.nft.json +1 -1
- package/.next/server/app/page_client-reference-manifest.js +1 -1
- package/.next/server/app/proxy/[...path]/route.js +2 -2
- package/.next/server/app/worktrees/[id]/files/[...path]/page_client-reference-manifest.js +1 -1
- package/.next/server/app/worktrees/[id]/page.js +4 -4
- package/.next/server/app/worktrees/[id]/page.js.nft.json +1 -1
- package/.next/server/app/worktrees/[id]/page_client-reference-manifest.js +1 -1
- package/.next/server/app/worktrees/[id]/simple-terminal/page_client-reference-manifest.js +1 -1
- package/.next/server/app/worktrees/[id]/terminal/page_client-reference-manifest.js +1 -1
- package/.next/server/app-paths-manifest.json +10 -8
- package/.next/server/chunks/5488.js +36 -0
- package/.next/server/chunks/6550.js +1 -1
- package/.next/server/chunks/7425.js +53 -50
- package/.next/server/chunks/7536.js +1 -0
- package/.next/server/chunks/8174.js +23 -0
- package/.next/server/chunks/9367.js +19 -0
- package/.next/server/middleware-build-manifest.js +1 -1
- package/.next/server/middleware-manifest.json +2 -28
- package/.next/server/middleware-react-loadable-manifest.js +1 -1
- package/.next/server/pages/404.html +1 -1
- package/.next/server/pages/500.html +1 -1
- package/.next/server/server-reference-manifest.json +1 -1
- package/.next/static/chunks/4327.740cc7fe2d0b5049.js +60 -0
- package/.next/static/chunks/4343-ebe884a2a80eb033.js +1 -0
- package/.next/static/chunks/6568-38a33aa67d82e12b.js +1 -0
- package/.next/static/chunks/816-c254f4e2406e696a.js +1 -0
- package/.next/static/chunks/app/layout-4804cfba519283cf.js +1 -0
- package/.next/static/chunks/app/page-3926224c4cdf315b.js +1 -0
- package/.next/static/chunks/app/worktrees/[id]/page-8bd88bdc29607413.js +1 -0
- package/.next/static/chunks/main-b6d727aa9248d4f2.js +1 -0
- package/.next/static/chunks/{webpack-3fc79fab9bb738d7.js → webpack-4f85dcef6279c6ee.js} +1 -1
- package/.next/static/css/28be35e4727ae7ef.css +3 -0
- package/.next/trace +5 -5
- package/.next/types/app/api/repositories/excluded/route.ts +343 -0
- package/.next/types/app/api/repositories/restore/route.ts +343 -0
- package/README.md +2 -2
- package/dist/cli/commands/init.d.ts.map +1 -1
- package/dist/cli/commands/init.js +2 -13
- package/dist/cli/commands/start.d.ts.map +1 -1
- package/dist/cli/commands/start.js +3 -7
- package/dist/cli/config/security-messages.d.ts +11 -0
- package/dist/cli/config/security-messages.d.ts.map +1 -0
- package/dist/cli/config/security-messages.js +29 -0
- package/dist/cli/types/index.d.ts +0 -1
- package/dist/cli/types/index.d.ts.map +1 -1
- package/dist/cli/utils/daemon.d.ts.map +1 -1
- package/dist/cli/utils/daemon.js +3 -7
- package/dist/cli/utils/env-setup.d.ts +0 -4
- package/dist/cli/utils/env-setup.d.ts.map +1 -1
- package/dist/cli/utils/env-setup.js +0 -14
- package/dist/cli/utils/security-logger.d.ts.map +1 -1
- package/dist/cli/utils/security-logger.js +1 -2
- package/dist/server/server.js +25 -2
- package/dist/server/src/lib/auto-yes-manager.js +100 -11
- package/dist/server/src/lib/claude-poller.js +341 -0
- package/dist/server/src/lib/claude-session.js +48 -19
- package/dist/server/src/lib/cli-patterns.js +69 -6
- package/dist/server/src/lib/cli-tools/base.js +7 -1
- package/dist/server/src/lib/cli-tools/codex.js +14 -2
- package/dist/server/src/lib/cli-tools/manager.js +27 -0
- package/dist/server/src/lib/cli-tools/types.js +7 -0
- package/dist/server/src/lib/cli-tools/validation.js +41 -0
- package/dist/server/src/lib/db-repository.js +482 -0
- package/dist/server/src/lib/db.js +23 -0
- package/dist/server/src/lib/env.js +0 -17
- package/dist/server/src/lib/logger.js +0 -4
- package/dist/server/src/lib/prompt-detector.js +297 -109
- package/dist/server/src/lib/response-poller.js +73 -27
- package/dist/server/src/lib/tmux.js +48 -0
- package/dist/server/src/lib/ws-server.js +12 -1
- package/dist/server/src/types/sidebar.js +16 -31
- package/dist/server/src/types/slash-commands.js +2 -0
- package/package.json +1 -1
- package/.next/server/chunks/1318.js +0 -29
- package/.next/server/chunks/2597.js +0 -1
- package/.next/server/chunks/2648.js +0 -1
- package/.next/server/chunks/9703.js +0 -31
- package/.next/server/chunks/9723.js +0 -19
- package/.next/server/edge-runtime-webpack.js +0 -2
- package/.next/server/edge-runtime-webpack.js.map +0 -1
- package/.next/server/src/middleware.js +0 -14
- package/.next/server/src/middleware.js.map +0 -1
- package/.next/static/chunks/2853-d11a80b03c9a1640.js +0 -1
- package/.next/static/chunks/4327.3b84aa049900fdeb.js +0 -60
- package/.next/static/chunks/816-7e340dad784be28c.js +0 -1
- package/.next/static/chunks/9365-733d8c05712d2888.js +0 -1
- package/.next/static/chunks/app/layout-37e55f11dcc8b1bf.js +0 -1
- package/.next/static/chunks/app/page-fe35d61f14b90a51.js +0 -1
- package/.next/static/chunks/app/worktrees/[id]/page-58fcf2e63c056743.js +0 -1
- package/.next/static/chunks/main-a960f4a5e1a2f598.js +0 -1
- package/.next/static/css/376b339640084689.css +0 -3
- /package/.next/static/{564GHwluX5xIv9qpqLJV2 → oUD-A998xeBoez6zsrTH3}/_buildManifest.js +0 -0
- /package/.next/static/{564GHwluX5xIv9qpqLJV2 → oUD-A998xeBoez6zsrTH3}/_ssgManifest.js +0 -0
|
@@ -15,6 +15,7 @@ const preflight_1 = require("../utils/preflight");
|
|
|
15
15
|
const env_setup_1 = require("../utils/env-setup");
|
|
16
16
|
const prompt_1 = require("../utils/prompt");
|
|
17
17
|
const security_logger_1 = require("../utils/security-logger");
|
|
18
|
+
const security_messages_1 = require("../config/security-messages");
|
|
18
19
|
const logger = new logger_1.CLILogger();
|
|
19
20
|
/**
|
|
20
21
|
* Create default configuration (non-interactive mode)
|
|
@@ -66,15 +67,12 @@ async function promptForConfig() {
|
|
|
66
67
|
default: false,
|
|
67
68
|
});
|
|
68
69
|
let bind = env_setup_1.ENV_DEFAULTS.CM_BIND;
|
|
69
|
-
let authToken;
|
|
70
70
|
if (enableExternal) {
|
|
71
71
|
bind = '0.0.0.0';
|
|
72
|
-
const envSetup = new env_setup_1.EnvSetup();
|
|
73
|
-
authToken = envSetup.generateAuthToken();
|
|
74
72
|
logger.blank();
|
|
75
73
|
logger.success('External access enabled');
|
|
76
74
|
logger.info(` Bind address: 0.0.0.0`);
|
|
77
|
-
|
|
75
|
+
console.log(security_messages_1.REVERSE_PROXY_WARNING);
|
|
78
76
|
}
|
|
79
77
|
// CM_DB_PATH - Issue #135: Use getDefaultDbPath() for absolute path
|
|
80
78
|
const defaultDbPath = (0, env_setup_1.getDefaultDbPath)();
|
|
@@ -86,7 +84,6 @@ async function promptForConfig() {
|
|
|
86
84
|
CM_ROOT_DIR: rootDir,
|
|
87
85
|
CM_PORT: port,
|
|
88
86
|
CM_BIND: bind,
|
|
89
|
-
CM_AUTH_TOKEN: authToken,
|
|
90
87
|
CM_DB_PATH: dbPath,
|
|
91
88
|
CM_LOG_LEVEL: env_setup_1.ENV_DEFAULTS.CM_LOG_LEVEL,
|
|
92
89
|
CM_LOG_FORMAT: env_setup_1.ENV_DEFAULTS.CM_LOG_FORMAT,
|
|
@@ -105,18 +102,10 @@ function displayConfigSummary(config, envPath) {
|
|
|
105
102
|
logger.info(` CM_ROOT_DIR: ${config.CM_ROOT_DIR}`);
|
|
106
103
|
logger.info(` CM_PORT: ${config.CM_PORT}`);
|
|
107
104
|
logger.info(` CM_BIND: ${config.CM_BIND}`);
|
|
108
|
-
if (config.CM_AUTH_TOKEN) {
|
|
109
|
-
logger.info(` CM_AUTH_TOKEN: ${config.CM_AUTH_TOKEN.substring(0, 8)}... (generated)`);
|
|
110
|
-
}
|
|
111
105
|
logger.info(` CM_DB_PATH: ${config.CM_DB_PATH}`);
|
|
112
106
|
logger.blank();
|
|
113
107
|
logger.info(` Config file: ${envPath}`);
|
|
114
108
|
logger.blank();
|
|
115
|
-
if (config.CM_AUTH_TOKEN) {
|
|
116
|
-
logger.warn('IMPORTANT: Save your auth token securely!');
|
|
117
|
-
logger.info(` Token: ${config.CM_AUTH_TOKEN}`);
|
|
118
|
-
logger.blank();
|
|
119
|
-
}
|
|
120
109
|
}
|
|
121
110
|
/**
|
|
122
111
|
* Execute init command
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"start.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/start.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAKH,OAAO,EAAE,YAAY,EAA6B,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"start.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/start.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAKH,OAAO,EAAE,YAAY,EAA6B,MAAM,UAAU,CAAC;AAanE;;;;GAIG;AACH,wBAAsB,YAAY,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CA8LvE"}
|
|
@@ -17,6 +17,7 @@ const daemon_1 = require("../utils/daemon");
|
|
|
17
17
|
const security_logger_1 = require("../utils/security-logger");
|
|
18
18
|
const paths_1 = require("../utils/paths");
|
|
19
19
|
const env_setup_1 = require("../utils/env-setup");
|
|
20
|
+
const security_messages_1 = require("../config/security-messages");
|
|
20
21
|
const input_validators_1 = require("../utils/input-validators");
|
|
21
22
|
const port_allocator_1 = require("../utils/port-allocator");
|
|
22
23
|
const resource_resolvers_1 = require("../utils/resource-resolvers");
|
|
@@ -139,15 +140,10 @@ async function startCommand(options) {
|
|
|
139
140
|
if (dbPath) {
|
|
140
141
|
env.CM_DB_PATH = dbPath;
|
|
141
142
|
}
|
|
142
|
-
// Issue #
|
|
143
|
+
// Issue #179: Security warning for external access - recommend reverse proxy
|
|
143
144
|
const bindAddress = env.CM_BIND || '127.0.0.1';
|
|
144
|
-
const authToken = env.CM_AUTH_TOKEN;
|
|
145
145
|
if (bindAddress === '0.0.0.0') {
|
|
146
|
-
|
|
147
|
-
if (!authToken) {
|
|
148
|
-
logger.warn('SECURITY WARNING: No authentication token configured. External access is not recommended without CM_AUTH_TOKEN.');
|
|
149
|
-
logger.info('Run "commandmate init" to configure a secure authentication token.');
|
|
150
|
-
}
|
|
146
|
+
console.log(security_messages_1.REVERSE_PROXY_WARNING);
|
|
151
147
|
}
|
|
152
148
|
// Use package installation directory, not current working directory
|
|
153
149
|
const packageRoot = (0, paths_1.getPackageRoot)();
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Security Messages
|
|
3
|
+
* Issue #179: Reverse proxy authentication recommendation
|
|
4
|
+
* Shared warning constants for CLI commands (DRY principle)
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Warning message displayed when CM_BIND=0.0.0.0
|
|
8
|
+
* Used by: init.ts, start.ts, daemon.ts
|
|
9
|
+
*/
|
|
10
|
+
export declare const REVERSE_PROXY_WARNING = "\n\u001B[1m\u001B[31mWARNING: Server is exposed to external networks without authentication\u001B[0m\n\nExposing the server without reverse proxy authentication\nis a serious security risk.\n\n\u001B[1mRisks:\u001B[0m\n File read/write/delete and command execution\n become accessible to third parties.\n\n\u001B[1mRecommended authentication methods:\u001B[0m\n - Nginx + Basic Auth\n - Cloudflare Access\n - Tailscale\n\nDetails: https://github.com/Kewton/CommandMate/blob/main/docs/security-guide.md\n";
|
|
11
|
+
//# sourceMappingURL=security-messages.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"security-messages.d.ts","sourceRoot":"","sources":["../../../src/cli/config/security-messages.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;;GAGG;AACH,eAAO,MAAM,qBAAqB,igBAgBjC,CAAC"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Security Messages
|
|
4
|
+
* Issue #179: Reverse proxy authentication recommendation
|
|
5
|
+
* Shared warning constants for CLI commands (DRY principle)
|
|
6
|
+
*/
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
exports.REVERSE_PROXY_WARNING = void 0;
|
|
9
|
+
/**
|
|
10
|
+
* Warning message displayed when CM_BIND=0.0.0.0
|
|
11
|
+
* Used by: init.ts, start.ts, daemon.ts
|
|
12
|
+
*/
|
|
13
|
+
exports.REVERSE_PROXY_WARNING = `
|
|
14
|
+
\x1b[1m\x1b[31mWARNING: Server is exposed to external networks without authentication\x1b[0m
|
|
15
|
+
|
|
16
|
+
Exposing the server without reverse proxy authentication
|
|
17
|
+
is a serious security risk.
|
|
18
|
+
|
|
19
|
+
\x1b[1mRisks:\x1b[0m
|
|
20
|
+
File read/write/delete and command execution
|
|
21
|
+
become accessible to third parties.
|
|
22
|
+
|
|
23
|
+
\x1b[1mRecommended authentication methods:\x1b[0m
|
|
24
|
+
- Nginx + Basic Auth
|
|
25
|
+
- Cloudflare Access
|
|
26
|
+
- Tailscale
|
|
27
|
+
|
|
28
|
+
Details: https://github.com/Kewton/CommandMate/blob/main/docs/security-guide.md
|
|
29
|
+
`;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/cli/types/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;GAGG;AACH,oBAAY,QAAQ;IAClB,OAAO,IAAI;IACX,gBAAgB,IAAI;IACpB,YAAY,IAAI;IAChB,YAAY,IAAI;IAChB,WAAW,IAAI;IACf,gBAAgB,KAAK;CACtB;AAED;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,2CAA2C;IAC3C,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,uCAAuC;IACvC,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED;;;GAGG;AACH,MAAM,WAAW,YAAY;IAC3B,gCAAgC;IAChC,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,wBAAwB;IACxB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,2BAA2B;IAC3B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,6DAA6D;IAC7D,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,4DAA4D;IAC5D,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,8DAA8D;IAC9D,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;GAGG;AACH,MAAM,WAAW,WAAW;IAC1B,2BAA2B;IAC3B,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,6DAA6D;IAC7D,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;GAGG;AACH,MAAM,WAAW,aAAa;IAC5B,6DAA6D;IAC7D,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,uDAAuD;IACvD,GAAG,CAAC,EAAE,OAAO,CAAC;CACf;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,oCAAoC;IACpC,OAAO,EAAE,OAAO,CAAC;IACjB,8BAA8B;IAC9B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,+BAA+B;IAC/B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,qCAAqC;IACrC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,4CAA4C;IAC5C,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED;;;GAGG;AACH,MAAM,WAAW,eAAe;IAC9B,mBAAmB;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,uBAAuB;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,8BAA8B;IAC9B,UAAU,EAAE,MAAM,CAAC;IACnB,0CAA0C;IAC1C,QAAQ,EAAE,OAAO,CAAC;IAClB,iCAAiC;IACjC,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,sBAAsB;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,mBAAmB;IACnB,MAAM,EAAE,IAAI,GAAG,SAAS,GAAG,kBAAkB,CAAC;IAC9C,sCAAsC;IACtC,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,sDAAsD;IACtD,OAAO,EAAE,OAAO,CAAC;IACjB,oCAAoC;IACpC,OAAO,EAAE,gBAAgB,EAAE,CAAC;CAC7B;AAED;;;GAGG;AACH,MAAM,WAAW,SAAS;IACxB,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/cli/types/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"daemon.d.ts","sourceRoot":"","sources":["../../../src/cli/utils/daemon.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"daemon.d.ts","sourceRoot":"","sources":["../../../src/cli/utils/daemon.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAOtD;;GAEG;AACH,qBAAa,aAAa;IACxB,OAAO,CAAC,UAAU,CAAa;IAC/B,OAAO,CAAC,MAAM,CAAY;gBAEd,WAAW,EAAE,MAAM;IAK/B;;;;;OAKG;IACG,KAAK,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC;IA6EnD;;;;OAIG;IACG,IAAI,CAAC,KAAK,GAAE,OAAe,GAAG,OAAO,CAAC,OAAO,CAAC;IA8BpD;;;OAGG;IACG,SAAS,IAAI,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC;IA6B/C;;OAEG;IACG,SAAS,IAAI,OAAO,CAAC,OAAO,CAAC;IAInC;;OAEG;YACW,WAAW;CAiB1B"}
|
package/dist/cli/utils/daemon.js
CHANGED
|
@@ -12,6 +12,7 @@ const dotenv_1 = require("dotenv");
|
|
|
12
12
|
const pid_manager_1 = require("./pid-manager");
|
|
13
13
|
const paths_1 = require("./paths");
|
|
14
14
|
const env_setup_1 = require("./env-setup");
|
|
15
|
+
const security_messages_1 = require("../config/security-messages");
|
|
15
16
|
const logger_1 = require("./logger");
|
|
16
17
|
/**
|
|
17
18
|
* Daemon manager for background server process
|
|
@@ -60,16 +61,11 @@ class DaemonManager {
|
|
|
60
61
|
if (options.dbPath) {
|
|
61
62
|
env.CM_DB_PATH = options.dbPath;
|
|
62
63
|
}
|
|
63
|
-
// Issue #
|
|
64
|
+
// Issue #179: Security warning for external access - recommend reverse proxy
|
|
64
65
|
const bindAddress = env.CM_BIND || '127.0.0.1';
|
|
65
|
-
const authToken = env.CM_AUTH_TOKEN;
|
|
66
66
|
const port = env.CM_PORT || '3000';
|
|
67
67
|
if (bindAddress === '0.0.0.0') {
|
|
68
|
-
|
|
69
|
-
if (!authToken) {
|
|
70
|
-
this.logger.warn('SECURITY WARNING: No authentication token configured. External access is not recommended without CM_AUTH_TOKEN.');
|
|
71
|
-
this.logger.info('Run "commandmate init" to configure a secure authentication token.');
|
|
72
|
-
}
|
|
68
|
+
console.log(security_messages_1.REVERSE_PROXY_WARNING);
|
|
73
69
|
}
|
|
74
70
|
// Log startup with accurate settings (Stage 4 review: MF-2)
|
|
75
71
|
this.logger.info(`Starting server at http://${bindAddress}:${port}`);
|
|
@@ -105,10 +105,6 @@ export declare class EnvSetup {
|
|
|
105
105
|
* Backup existing .env file
|
|
106
106
|
*/
|
|
107
107
|
backupExisting(): Promise<string | null>;
|
|
108
|
-
/**
|
|
109
|
-
* Generate secure authentication token
|
|
110
|
-
*/
|
|
111
|
-
generateAuthToken(): string;
|
|
112
108
|
/**
|
|
113
109
|
* Validate configuration
|
|
114
110
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"env-setup.d.ts","sourceRoot":"","sources":["../../../src/cli/utils/env-setup.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;
|
|
1
|
+
{"version":3,"file":"env-setup.d.ts","sourceRoot":"","sources":["../../../src/cli/utils/env-setup.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAYH,OAAO,EACL,SAAS,EACT,eAAe,EACf,gBAAgB,EACjB,MAAM,UAAU,CAAC;AASlB,OAAO,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAElE;;;;;;GAMG;AACH,eAAO,MAAM,YAAY;;;;;CAMf,CAAC;AAEX;;GAEG;AACH,eAAO,MAAM,gBAAgB,QAA2B,CAAC;AAEzD;;;;;;;;;GASG;AACH,wBAAgB,gBAAgB,IAAI,MAAM,CAOzC;AAED;;;;;;;;GAQG;AACH,wBAAgB,UAAU,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAwBnD;AAED;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,GAAG,MAAM,CASpF;AAKD;;;;;GAKG;AACH,wBAAgB,UAAU,IAAI,MAAM,CAGnC;AAED;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAYvD;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAGnD;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAGlD;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAMlD;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAUpD;AAED;;GAEG;AACH,qBAAa,QAAQ;IACnB,OAAO,CAAC,OAAO,CAAS;gBAEZ,OAAO,CAAC,EAAE,MAAM;IAI5B;;;OAGG;IACG,aAAa,CACjB,MAAM,EAAE,SAAS,EACjB,OAAO,GAAE,eAAoB,GAC5B,OAAO,CAAC,IAAI,CAAC;IA6BhB;;OAEG;IACG,cAAc,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAY9C;;OAEG;IACH,cAAc,CAAC,MAAM,EAAE,SAAS,GAAG,gBAAgB;CA+BpD"}
|
|
@@ -18,7 +18,6 @@ exports.validatePort = validatePort;
|
|
|
18
18
|
exports.escapeEnvValue = escapeEnvValue;
|
|
19
19
|
const fs_1 = require("fs");
|
|
20
20
|
const path_1 = require("path");
|
|
21
|
-
const crypto_1 = require("crypto");
|
|
22
21
|
const os_1 = require("os");
|
|
23
22
|
// Issue #136: Import from install-context.ts to avoid circular imports
|
|
24
23
|
// Re-export for backward compatibility
|
|
@@ -210,9 +209,6 @@ class EnvSetup {
|
|
|
210
209
|
`CM_LOG_LEVEL=${config.CM_LOG_LEVEL}`,
|
|
211
210
|
`CM_LOG_FORMAT=${config.CM_LOG_FORMAT}`,
|
|
212
211
|
];
|
|
213
|
-
if (config.CM_AUTH_TOKEN) {
|
|
214
|
-
lines.push(`CM_AUTH_TOKEN=${config.CM_AUTH_TOKEN}`);
|
|
215
|
-
}
|
|
216
212
|
lines.push('');
|
|
217
213
|
const content = lines.join('\n');
|
|
218
214
|
// Write with secure permissions
|
|
@@ -232,12 +228,6 @@ class EnvSetup {
|
|
|
232
228
|
(0, fs_1.copyFileSync)(this.envPath, backupPath);
|
|
233
229
|
return backupPath;
|
|
234
230
|
}
|
|
235
|
-
/**
|
|
236
|
-
* Generate secure authentication token
|
|
237
|
-
*/
|
|
238
|
-
generateAuthToken() {
|
|
239
|
-
return (0, crypto_1.randomBytes)(32).toString('hex');
|
|
240
|
-
}
|
|
241
231
|
/**
|
|
242
232
|
* Validate configuration
|
|
243
233
|
*/
|
|
@@ -252,10 +242,6 @@ class EnvSetup {
|
|
|
252
242
|
if (!validBinds.includes(config.CM_BIND)) {
|
|
253
243
|
errors.push(`Invalid bind address: must be one of ${validBinds.join(', ')}`);
|
|
254
244
|
}
|
|
255
|
-
// Require auth token for external access
|
|
256
|
-
if (config.CM_BIND === '0.0.0.0' && !config.CM_AUTH_TOKEN) {
|
|
257
|
-
errors.push('auth token is required when binding to 0.0.0.0');
|
|
258
|
-
}
|
|
259
245
|
// Validate log level
|
|
260
246
|
const validLogLevels = ['debug', 'info', 'warn', 'error'];
|
|
261
247
|
if (!validLogLevels.includes(config.CM_LOG_LEVEL)) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"security-logger.d.ts","sourceRoot":"","sources":["../../../src/cli/utils/security-logger.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAMH;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,oBAAoB;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,uCAAuC;IACvC,OAAO,EAAE,MAAM,CAAC;IAChB,oBAAoB;IACpB,MAAM,EAAE,SAAS,GAAG,SAAS,GAAG,SAAS,CAAC;IAC1C,yBAAyB;IACzB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAaD;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,aAAa,GAAG,IAAI,CAU3D;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,
|
|
1
|
+
{"version":3,"file":"security-logger.d.ts","sourceRoot":"","sources":["../../../src/cli/utils/security-logger.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAMH;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,oBAAoB;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,uCAAuC;IACvC,OAAO,EAAE,MAAM,CAAC;IAChB,oBAAoB;IACpB,MAAM,EAAE,SAAS,GAAG,SAAS,GAAG,SAAS,CAAC;IAC1C,yBAAyB;IACzB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAaD;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,aAAa,GAAG,IAAI,CAU3D;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAY/E"}
|
|
@@ -43,9 +43,8 @@ function maskSensitiveData(input) {
|
|
|
43
43
|
if (!input) {
|
|
44
44
|
return input;
|
|
45
45
|
}
|
|
46
|
-
// Mask CM_AUTH_TOKEN values
|
|
47
|
-
let result = input.replace(/CM_AUTH_TOKEN=\S+/g, 'CM_AUTH_TOKEN=***masked***');
|
|
48
46
|
// Mask any token-like strings (12+ hex/alphanumeric characters after "token:")
|
|
47
|
+
let result = input;
|
|
49
48
|
result = result.replace(/(?:token|Token)[:\s]+([a-zA-Z0-9]{12,})/gi, (_match, token) => {
|
|
50
49
|
return _match.replace(token, '***');
|
|
51
50
|
});
|
package/dist/server/server.js
CHANGED
|
@@ -37,6 +37,8 @@ const response_poller_1 = require("./src/lib/response-poller");
|
|
|
37
37
|
const auto_yes_manager_1 = require("./src/lib/auto-yes-manager");
|
|
38
38
|
const db_migrations_1 = require("./src/lib/db-migrations");
|
|
39
39
|
const env_1 = require("./src/lib/env");
|
|
40
|
+
const db_repository_1 = require("./src/lib/db-repository");
|
|
41
|
+
const db_1 = require("./src/lib/db");
|
|
40
42
|
const dev = process.env.NODE_ENV !== 'production';
|
|
41
43
|
const hostname = (0, env_1.getEnvByKey)('CM_BIND') || '127.0.0.1';
|
|
42
44
|
const port = parseInt((0, env_1.getEnvByKey)('CM_PORT') || '3000', 10);
|
|
@@ -76,8 +78,29 @@ app.prepare().then(() => {
|
|
|
76
78
|
repositoryPaths.forEach((path, i) => {
|
|
77
79
|
console.log(` ${i + 1}. ${path}`);
|
|
78
80
|
});
|
|
79
|
-
//
|
|
80
|
-
|
|
81
|
+
// Issue #202: Register environment variable repositories and filter out excluded ones
|
|
82
|
+
// registerAndFilterRepositories() encapsulates the ordering constraint:
|
|
83
|
+
// registration MUST happen before filtering (see design policy Section 4)
|
|
84
|
+
const { filteredPaths, excludedPaths, excludedCount } = (0, db_repository_1.registerAndFilterRepositories)(db, repositoryPaths);
|
|
85
|
+
if (excludedCount > 0) {
|
|
86
|
+
console.log(`Excluded repositories: ${excludedCount}, Active repositories: ${filteredPaths.length}`);
|
|
87
|
+
// SF-SEC-003: Log excluded repository paths for audit/troubleshooting
|
|
88
|
+
excludedPaths.forEach(p => {
|
|
89
|
+
console.log(` [excluded] ${p}`);
|
|
90
|
+
});
|
|
91
|
+
// Issue #202: Remove worktrees of excluded repositories from DB
|
|
92
|
+
// Without this, worktree records remain in DB and appear in the UI
|
|
93
|
+
for (const excludedPath of excludedPaths) {
|
|
94
|
+
const resolvedPath = (0, db_repository_1.resolveRepositoryPath)(excludedPath);
|
|
95
|
+
const worktreeIds = (0, db_1.getWorktreeIdsByRepository)(db, resolvedPath);
|
|
96
|
+
if (worktreeIds.length > 0) {
|
|
97
|
+
const result = (0, db_1.deleteWorktreesByIds)(db, worktreeIds);
|
|
98
|
+
console.log(` Removed ${result.deletedCount} worktree(s) from excluded repository: ${resolvedPath}`);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
// Scan filtered repositories (excluded repos are skipped)
|
|
103
|
+
const worktrees = await (0, worktrees_1.scanMultipleRepositories)(filteredPaths);
|
|
81
104
|
// Sync to database
|
|
82
105
|
(0, worktrees_1.syncWorktreesToDB)(db, worktrees);
|
|
83
106
|
console.log(`✓ Total: ${worktrees.length} worktree(s) synced to database`);
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
* auto-yes responses when browser tabs are in background.
|
|
10
10
|
*/
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
-
exports.MAX_CONCURRENT_POLLERS = exports.MAX_CONSECUTIVE_ERRORS = exports.MAX_BACKOFF_MS = exports.POLLING_INTERVAL_MS = void 0;
|
|
12
|
+
exports.THINKING_CHECK_LINE_COUNT = exports.MAX_CONCURRENT_POLLERS = exports.MAX_CONSECUTIVE_ERRORS = exports.MAX_BACKOFF_MS = exports.POLLING_INTERVAL_MS = void 0;
|
|
13
13
|
exports.isValidWorktreeId = isValidWorktreeId;
|
|
14
14
|
exports.calculateBackoffInterval = calculateBackoffInterval;
|
|
15
15
|
exports.isAutoYesExpired = isAutoYesExpired;
|
|
@@ -41,6 +41,16 @@ exports.MAX_CONSECUTIVE_ERRORS = 5;
|
|
|
41
41
|
exports.MAX_CONCURRENT_POLLERS = 50;
|
|
42
42
|
/** Timeout duration: 1 hour in milliseconds */
|
|
43
43
|
const AUTO_YES_TIMEOUT_MS = 3600000;
|
|
44
|
+
/**
|
|
45
|
+
* Number of lines from the end to check for thinking indicators (Issue #191)
|
|
46
|
+
* Matches detectPrompt()'s multiple_choice scan range (50 lines in prompt-detector.ts)
|
|
47
|
+
* to ensure Issue #161 Layer 1 defense covers the same scope as prompt detection.
|
|
48
|
+
*
|
|
49
|
+
* IMPORTANT: This value is semantically coupled to the hardcoded 50 in
|
|
50
|
+
* prompt-detector.ts detectMultipleChoicePrompt() (L268: Math.max(0, lines.length - 50)).
|
|
51
|
+
* See SF-001 in Stage 1 review. A cross-reference test validates this coupling.
|
|
52
|
+
*/
|
|
53
|
+
exports.THINKING_CHECK_LINE_COUNT = 50;
|
|
44
54
|
/** Worktree ID validation pattern (security: prevent command injection) */
|
|
45
55
|
const WORKTREE_ID_PATTERN = /^[a-zA-Z0-9_-]+$/;
|
|
46
56
|
/** In-memory storage for auto-yes states (globalThis for hot reload persistence) */
|
|
@@ -205,32 +215,111 @@ async function pollAutoYes(worktreeId, cliToolId) {
|
|
|
205
215
|
try {
|
|
206
216
|
// 1. Capture tmux output
|
|
207
217
|
const output = await (0, cli_session_1.captureSessionOutput)(worktreeId, cliToolId, 5000);
|
|
208
|
-
// 2. Strip ANSI codes
|
|
218
|
+
// 2. Strip ANSI codes
|
|
209
219
|
const cleanOutput = (0, cli_patterns_1.stripAnsi)(output);
|
|
210
|
-
|
|
220
|
+
// 2.5. Skip prompt detection during thinking state (Issue #161, Layer 1)
|
|
221
|
+
// This prevents false positive detection of numbered lists in CLI output
|
|
222
|
+
// while Claude is actively processing (thinking/planning).
|
|
223
|
+
//
|
|
224
|
+
// Issue #191: Apply windowing to detectThinking() to prevent stale thinking
|
|
225
|
+
// summary lines (e.g., "· Simmering…") from blocking prompt detection.
|
|
226
|
+
// Window size matches detectPrompt()'s multiple_choice scan range (50 lines).
|
|
227
|
+
//
|
|
228
|
+
// Safety: Claude CLI does not emit prompts during thinking, so narrowing
|
|
229
|
+
// the window cannot cause false auto-responses (see IA-003 in design doc).
|
|
230
|
+
//
|
|
231
|
+
// Processing order: stripAnsi -> split -> slice -> join
|
|
232
|
+
// stripAnsi is applied BEFORE split to ensure ANSI escape sequences spanning
|
|
233
|
+
// line boundaries do not affect line counting (IA-002).
|
|
234
|
+
//
|
|
235
|
+
// Boundary case: if buffer has fewer than 50 lines, slice(-50) returns the
|
|
236
|
+
// entire array (Array.prototype.slice specification), which is safe degradation
|
|
237
|
+
// equivalent to pre-fix behavior (IA-001).
|
|
238
|
+
const recentLines = cleanOutput.split('\n').slice(-exports.THINKING_CHECK_LINE_COUNT).join('\n');
|
|
239
|
+
if ((0, cli_patterns_1.detectThinking)(cliToolId, recentLines)) {
|
|
240
|
+
scheduleNextPoll(worktreeId, cliToolId);
|
|
241
|
+
return;
|
|
242
|
+
}
|
|
243
|
+
// 3. Detect prompt
|
|
244
|
+
const promptOptions = (0, cli_patterns_1.buildDetectPromptOptions)(cliToolId);
|
|
245
|
+
const promptDetection = (0, prompt_detector_1.detectPrompt)(cleanOutput, promptOptions);
|
|
211
246
|
if (!promptDetection.isPrompt || !promptDetection.promptData) {
|
|
212
247
|
// No prompt detected, schedule next poll
|
|
213
248
|
scheduleNextPoll(worktreeId, cliToolId);
|
|
214
249
|
return;
|
|
215
250
|
}
|
|
216
|
-
//
|
|
251
|
+
// 4. Resolve auto answer
|
|
217
252
|
const answer = (0, auto_yes_resolver_1.resolveAutoAnswer)(promptDetection.promptData);
|
|
218
253
|
if (answer === null) {
|
|
219
254
|
// Cannot auto-answer this prompt
|
|
220
255
|
scheduleNextPoll(worktreeId, cliToolId);
|
|
221
256
|
return;
|
|
222
257
|
}
|
|
223
|
-
//
|
|
258
|
+
// 5. Send answer to tmux
|
|
224
259
|
const manager = manager_1.CLIToolManager.getInstance();
|
|
225
260
|
const cliTool = manager.getTool(cliToolId);
|
|
226
261
|
const sessionName = cliTool.getSessionName(worktreeId);
|
|
227
|
-
//
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
262
|
+
// Issue #193: Claude Code AskUserQuestion uses cursor-based navigation
|
|
263
|
+
// (Arrow/Space/Enter), not number input. Detect multi-choice and send
|
|
264
|
+
// appropriate key sequence instead of typing the number.
|
|
265
|
+
const isClaudeMultiChoice = cliToolId === 'claude'
|
|
266
|
+
&& promptDetection.promptData?.type === 'multiple_choice'
|
|
267
|
+
&& /^\d+$/.test(answer);
|
|
268
|
+
if (isClaudeMultiChoice && promptDetection.promptData?.type === 'multiple_choice') {
|
|
269
|
+
const targetNum = parseInt(answer, 10);
|
|
270
|
+
const mcOptions = promptDetection.promptData.options;
|
|
271
|
+
const defaultOption = mcOptions.find(o => o.isDefault);
|
|
272
|
+
const defaultNum = defaultOption?.number ?? 1;
|
|
273
|
+
const offset = targetNum - defaultNum;
|
|
274
|
+
// Detect multi-select (checkbox) prompts by checking for [ ] in option labels.
|
|
275
|
+
const isMultiSelect = mcOptions.some(o => /^\[[ x]\] /.test(o.label));
|
|
276
|
+
if (isMultiSelect) {
|
|
277
|
+
// Multi-select: toggle checkbox, then navigate to "Next" and submit
|
|
278
|
+
const checkboxCount = mcOptions.filter(o => /^\[[ x]\] /.test(o.label)).length;
|
|
279
|
+
const keys = [];
|
|
280
|
+
// 1. Navigate to target option
|
|
281
|
+
if (offset > 0) {
|
|
282
|
+
for (let i = 0; i < offset; i++)
|
|
283
|
+
keys.push('Down');
|
|
284
|
+
}
|
|
285
|
+
else if (offset < 0) {
|
|
286
|
+
for (let i = 0; i < Math.abs(offset); i++)
|
|
287
|
+
keys.push('Up');
|
|
288
|
+
}
|
|
289
|
+
// 2. Space to toggle checkbox
|
|
290
|
+
keys.push('Space');
|
|
291
|
+
// 3. Navigate to "Next" button (positioned right after all checkbox options)
|
|
292
|
+
const downToNext = checkboxCount - targetNum + 1;
|
|
293
|
+
for (let i = 0; i < downToNext; i++)
|
|
294
|
+
keys.push('Down');
|
|
295
|
+
// 4. Enter to submit
|
|
296
|
+
keys.push('Enter');
|
|
297
|
+
await (0, tmux_1.sendSpecialKeys)(sessionName, keys);
|
|
298
|
+
}
|
|
299
|
+
else {
|
|
300
|
+
// Single-select: navigate and Enter to select
|
|
301
|
+
const keys = [];
|
|
302
|
+
if (offset > 0) {
|
|
303
|
+
for (let i = 0; i < offset; i++)
|
|
304
|
+
keys.push('Down');
|
|
305
|
+
}
|
|
306
|
+
else if (offset < 0) {
|
|
307
|
+
for (let i = 0; i < Math.abs(offset); i++)
|
|
308
|
+
keys.push('Up');
|
|
309
|
+
}
|
|
310
|
+
keys.push('Enter');
|
|
311
|
+
await (0, tmux_1.sendSpecialKeys)(sessionName, keys);
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
else {
|
|
315
|
+
// Standard CLI prompt: send text + Enter (y/n, Approve?, etc.)
|
|
316
|
+
await (0, tmux_1.sendKeys)(sessionName, answer, false);
|
|
317
|
+
await new Promise(resolve => setTimeout(resolve, 100));
|
|
318
|
+
await (0, tmux_1.sendKeys)(sessionName, '', true);
|
|
319
|
+
}
|
|
320
|
+
// 6. Update timestamp
|
|
232
321
|
updateLastServerResponseTimestamp(worktreeId, Date.now());
|
|
233
|
-
//
|
|
322
|
+
// 7. Reset error count on success
|
|
234
323
|
resetErrorCount(worktreeId);
|
|
235
324
|
// Log success (without sensitive content)
|
|
236
325
|
console.info(`[Auto-Yes Poller] Sent response for worktree: ${worktreeId}`);
|